commit fc5cb0c32c0c428f044213d5311ba99b3e349f96 Author: WatermelonModders <94921328+WatermelonModders@users.noreply.github.com> Date: Tue May 31 12:35:46 2022 -0400 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0d6ab98 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +# os +FROM ubuntu:16.04 +RUN apt-get -y update && apt-get install -y git vim libev-dev tar wget libevent-dev build-essential libnet-ifconfig-wrapper-perl cmake python-pip libjson-c-dev curl valgrind zlib1g-dev python-webpy +# couchbase +RUN cd ~ && wget http://packages.couchbase.com/releases/4.5.0/couchbase-server-enterprise_4.5.0-ubuntu14.04_amd64.deb +RUN cd ~ && dpkg -i couchbase-server-enterprise_4.5.0-ubuntu14.04_amd64.deb +RUN cd ~ && git clone https://github.com/couchbase/libcouchbase.git +RUN cd ~ && cd libcouchbase && cmake . && make && make install +RUN cd ~ && wget http://packages.couchbase.com/clients/c/libcouchbase-2.5.8_ubuntu1404_amd64.tar && tar xvf *.tar && cd libcouchbase-2.5.8_ubuntu1404_amd64/ && dpkg -i *.deb +RUN pip install couchbase +# hearthmod +RUN cd ~ && git clone https://github.com/farb3yonddriv3n/hm_database.git +RUN cd ~ && git clone https://github.com/farb3yonddriv3n/hm_base.git +RUN cd ~ && git clone https://github.com/farb3yonddriv3n/hm_gameserver.git +RUN cd ~ && git clone https://github.com/farb3yonddriv3n/hm_lobbyserver.git +RUN cd ~ && git clone https://github.com/farb3yonddriv3n/hm_ctl.git +RUN cd ~ && git clone https://github.com/farb3yonddriv3n/hm_stud.git +# cleanup +RUN rm -rf ~/couchbase-server-enterprise_4.5.0-ubuntu14.04_amd64.deb ~/libcouchb* diff --git a/README.md b/README.md new file mode 100644 index 0000000..58b9e3c --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# hearthmodanvilnew + diff --git a/docker_ctl.sh b/docker_ctl.sh new file mode 100644 index 0000000..3c25d74 --- /dev/null +++ b/docker_ctl.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +case $1 in + bucket_create) + /opt/couchbase/bin/couchbase-cli bucket-create -c localhost:8091 -u Administrator -p password --bucket=hbs --bucket-password=aci --bucket-type=couchbase --bucket-ramsize=200 --bucket-replica=1 --wait + ;; + bucket_restore) + /opt/couchbase/bin/cbrestore ~/hm_database/ http://localhost:8091/ --bucket-source=hbs + ;; + compile) + make -C ~/hm_gameserver + make -C ~/hm_lobbyserver + ;; + start) + mkdir -p ~/hm_log + valgrind --log-file=/root/hm_log/hm_gameserver_valgrind_$(date +%s) --trace-children=yes ~/hm_gameserver/hm_gameserver --log=/root/hm_log/hm_gameserver_$(date +%s) + valgrind --log-file=/root/hm_log/hm_lobbyserver_valgrind_$(date +%s) --trace-children=yes ~/hm_lobbyserver/hm_lobbyserver --log=/root/hm_log/hm_lobbyserver_$(date +%s) + ;; + stop) + ps -ef | grep hm_ | grep -v grep | awk '{print $2}' | xargs kill -9 + ;; + *) + echo "Usage: ctl.sh {bucket_create|bucket_restore|compile|start|stop}" >&2 + exit 3 +esac diff --git a/hm_base/.gitignore b/hm_base/.gitignore new file mode 100644 index 0000000..03cdf5c --- /dev/null +++ b/hm_base/.gitignore @@ -0,0 +1,3 @@ +tags +*.swp +*.o diff --git a/hm_base/CREDITS b/hm_base/CREDITS new file mode 100644 index 0000000..fd2aaeb --- /dev/null +++ b/hm_base/CREDITS @@ -0,0 +1 @@ +Filip Pancik diff --git a/hm_base/LICENSE b/hm_base/LICENSE new file mode 100644 index 0000000..e0345c0 --- /dev/null +++ b/hm_base/LICENSE @@ -0,0 +1,622 @@ + GNU GENERAL PUBLIC LICENSE + + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/hm_base/Makefile b/hm_base/Makefile new file mode 100644 index 0000000..b5c4464 --- /dev/null +++ b/hm_base/Makefile @@ -0,0 +1,28 @@ +ifeq ($(target),game) +CFLAGS+=-g -Wall -DHM_GAMESERVER +else +CFLAGS+=-g -Wall -DHM_LOBBYSERVER +endif +INCS= -Isrc/include +LIBS= -lcouchbase + +compile = $(CC) -c $(CFLAGS) $(INCS) $(LIBS) src/$(1).c -o src/$(1).o + +game: hmbase + +hmbase: src/*.c src/include/*.h + rm -rf lib/ + $(call compile,log) + $(call compile,hashtable) + $(call compile,rb) + $(call compile,pool) + $(call compile,connector) + $(call compile,couchbase) + $(call compile,async_client) + mkdir -p lib/ + ar cq lib/libhmbase.a src/*.o + +clean: + rm -rf src/*.o ./lib/ + +.PHONY: static hmbase diff --git a/hm_base/README.md b/hm_base/README.md new file mode 100644 index 0000000..12aa1ea --- /dev/null +++ b/hm_base/README.md @@ -0,0 +1,7 @@ +# hm_base + +base library + +# This is not a standalone project! + +[hm_base](https://github.com/farb3yonddriv3n/hm_base) is part of [hearthmod software stack](https://github.com/hearthmod/hearthmod) diff --git a/hm_base/src/async_client.c b/hm_base/src/async_client.c new file mode 100644 index 0000000..9586c6a --- /dev/null +++ b/hm_base/src/async_client.c @@ -0,0 +1,654 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include // fcntl +#include +#include // close +#include +#include +#include +#include + +#include + +#include + +#define ASYNC_HANG_TIMEOUT 14 + +struct ht_s **async_clients; + +static unsigned long long client_index = 0; + +static int async_client_accept(struct conn_client_s *client); +static void *connector_addclient(struct conn_server_s *cs, struct conn_client_s *cc); + +void shutdown_server(struct conn_server_s *cs) +{ + struct conn_client_holder_s *c, *dc; + struct hm_pool_s *p; + + hm_log(LOG_INFO, cs->log, "{Connector}: shutting down server, clients: %d", cs->clients); + + for(c = cs->clients_head; c != NULL; ) { + if(c->signal_shutdown == 0 && c->client) { + c->client->error_callback(c->client, CL_SERVERSHUTDOWN_ERR); + } + + dc = c; + c = c->next; + hm_pfree(cs->pool, dc); + } + + p = cs->pool; + ev_io_stop(cs->loop, &cs->listener); + connector_fd_close(cs->fd); + hm_pfree(p, cs); +} + +static void client_error(struct conn_client_s *c, enum clerr_e err) +{ + async_shutdown_client(c); +} + +int setnonblock(int fd) +{ + int nb; + + nb = 1; + return ioctl(fd, FIONBIO, &nb); +} + +#ifdef HM_LOBBYSERVER +static char read_byte(char **dst, const char *end) +{ + char out; + + if(*dst + sizeof(char) > end) { + return -1; + } + + out = *((char *)(*dst)); + + (*dst)++; + return out; +} + +static int read_uint(char **dst, const char *end) +{ + int num = 0, num2; + int i; + + for(i = 0; (i < 5 && *dst < end); i++) { + num2 = read_byte(dst, end); + + if(i == 4 && (num2 & 240) != 0) { + abort(); + } + + if((num2 & 128) == 0) { + return num | (unsigned int)((unsigned int)num2 << 7 * i); + } + + num |= (unsigned int)((unsigned int)(num2 & 127) << 7 * i); + } + + return num; +} + +static void recv_append_lobby(struct conn_client_s *c, char *src, int nsrc) +{ + unsigned short h; + int i, total; + struct conn_server_s *cs = c->parent; + + if(nsrc < 2) { + return; + } + + hm_log(LOG_DEBUG, c->log, "{Connector}: Received %d bytes", nsrc); + + /** hbs lobby client */ + if(nsrc > 12 && *(int *)src == -1) { + hm_log(LOG_DEBUG, c->log, "{Connector}: HBS lobby client packet"); + cs->recv(c, src, nsrc); + return; + } + + /** hbs game client */ + hm_log(LOG_DEBUG, c->log, "{Connector}: HBS game client packet"); + h = (unsigned char )src[0]; + h <<= 8; + h |= (unsigned char )src[1]; + + if(h == 0) { + return; + } + + h += 2; + + for(total = 0, i = 2; i < h; i++) { + if(src[i] == 0x28 && (i + 1) < h) { + char *ptr = &src[i + 1]; + total = read_uint(&ptr, ptr + nsrc - h); + break; + } + } + + total += h; + + cs->recv(c, src, total); + + if(total < nsrc) { + hm_log(LOG_DEBUG, c->log, "{Connector}: Next packet of %d bytes prepared", nsrc - total); + recv_append_lobby(c, src + total, nsrc - total); + } +} +#endif // HM_LOBBYSERVER + +static void recv_append(struct conn_client_s *c) +{ +#ifdef HM_GAMESERVER + int sz; + char *next; + struct conn_server_s *cs = c->parent; + + next = rb_recv_read(&c->rb, &sz); + rb_recv_pop(&c->rb); + cs->recv(c, next, sz); +#elif defined HM_LOBBYSERVER + int sz; + char *next; + + next = rb_recv_read(&c->rb, &sz); + c->net_nbuf = sz; + memcpy(c->net_buf, next, sz); + rb_recv_pop(&c->rb); + recv_append_lobby(c, c->net_buf, c->net_nbuf); +#endif +} + +static void connector_client(struct ev_loop *loop, ev_io *w, int revents) +{ + (void) revents; + struct sockaddr_storage addr; + socklen_t sl = sizeof(addr); + int client; + struct conn_client_s *cc; + struct conn_server_s *cs = w->data; + + assert(cs); + + client = accept(w->fd, (struct sockaddr *) &addr, &sl); + if(client == -1) { + switch (errno) { + case EMFILE: + hm_log(LOG_ERR, cs->log, "{Connector}: accept() failed; too many open files for this process"); + break; + + case ENFILE: + hm_log(LOG_ERR, cs->log, "{client} accept() failed; too many open files for this system"); + break; + + default: + assert(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN); + break; + } + return; + } + + int flag = 1; + int ret = setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); + if(ret == -1) { + hm_log(LOG_ERR, cs->log, "{Connector}: Couldn't setsockopt on client (TCP_NODELAY)"); + } +#ifdef TCP_CWND + int cwnd = 10; + ret = setsockopt(client, IPPROTO_TCP, TCP_CWND, &cwnd, sizeof(cwnd)); + if(ret == -1) { + hm_log(LOG_ERR, cs->log, "Couldn't setsockopt on client (TCP_CWND)"); + } +#endif + + setnonblock(client); + setkeepalive(client); + +#define PEER_NAME +#ifdef PEER_NAME + socklen_t len; + struct sockaddr_storage paddr; + char ipstr[INET6_ADDRSTRLEN]; + int pport, peer; + + len = sizeof(paddr); + peer = getpeername(client, (struct sockaddr*)&paddr, &len); + + // deal with both IPv4 and IPv6: + if(paddr.ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&paddr; + pport = ntohs(s->sin_port); + inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof(ipstr)); + } else { // AF_INET6 + struct sockaddr_in6 *s = (struct sockaddr_in6 *)&paddr; + pport = ntohs(s->sin6_port); + inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof(ipstr)); + } + + if(peer == -1) { + hm_log(LOG_WARNING, cs->log, "{Connector}: Couldn't retrieve peer name"); + } +#endif + + cc = hm_palloc(cs->pool, sizeof(struct conn_client_s)); + if(cc == NULL) { + hm_log(LOG_WARNING, cs->log, "{Connector}: Memory allocation failed"); + return; + } + + memset(cc, 0, sizeof(struct conn_client_s)); + + cc->loop = loop; + cc->fd = client; + cc->pool = cs->pool; + cc->log = cs->log; + cc->read.data = cc; + cc->write.data = cc; + cc->parent = cs; + cc->error_callback = client_error; + cc->client_dc = cs->client_dc; +#ifdef PEER_NAME + cc->nip = strlen(ipstr); + memcpy(cc->ip, ipstr, cc->nip); + cc->port = pport; +#endif + + if(connector_addclient(cs, cc) == NULL) { + hm_pfree(cs->pool, cc); + return; + } + + cc->recv = recv_append; + async_client_accept(cc); +} + +int connector_server(struct conn_server_s *cs) +{ + int t = 1; + int timeout = 1; + struct addrinfo *ai, hints; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + const int gai_err = getaddrinfo(cs->host, cs->port, &hints, &ai); + + if(gai_err != 0) { + hm_log(LOG_CRIT, cs->log, "{Connector}: [%s]", gai_strerror(gai_err)); + return -1; + } + + cs->fd = socket(ai->ai_family, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP); + if(cs->fd == -1) { + hm_log(LOG_CRIT, cs->log, "{Connector}: socket() failed"); + return -2; + } + + hm_log(LOG_INFO, cs->log, "{Connector}: opening server on %s:%s fd: %d", cs->host, cs->port, cs->fd); +#ifdef SO_REUSEADDR + setsockopt(cs->fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)); +#endif +#ifdef SO_REUSEPORT + setsockopt(cs->fd, SOL_SOCKET, SO_REUSEPORT, &t, sizeof(int)); +#endif + + if(bind(cs->fd, ai->ai_addr, ai->ai_addrlen)) { + hm_log(LOG_CRIT, cs->log, "{Connector}: bind() failed"); + return -3; + } + +#if TCP_DEFER_ACCEPT + setsockopt(cs->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int)); +#endif + + freeaddrinfo(ai); + listen(cs->fd, 128); + + ev_io_init(&cs->listener, connector_client, cs->fd, EV_READ); + cs->listener.data = cs; + ev_io_start(cs->loop, &cs->listener); + + return 0; +} + + +static void *connector_addclient(struct conn_server_s *cs, struct conn_client_s *cc) +{ + struct conn_client_holder_s *cch; + + cch = hm_palloc(cs->pool, sizeof(*cch)); + + if(cch == NULL) { + hm_log(LOG_WARNING, cs->log, "{Connector}: Memory allocation failed"); + return NULL; + } + + memset(cch, 0, sizeof(*cch)); + + cch->client = cc; + cch->next = cs->clients_head; + + cc->shutdown_signal_holder = &cch->signal_shutdown; + + cs->clients_head = cch; + cs->clients++; + + cc->holder = cch; + + hm_log(LOG_NOTICE, cs->log, "{Connector}: adding client %.*s:%d, total: %d", cc->nip, cc->ip, cc->port, cs->clients); + + return cch; +} + +int async_shutdown_client(struct conn_client_s *c) +{ + if(c == NULL) { + return -1; + } + + ev_io_stop(c->loop, &c->read); + ev_io_stop(c->loop, &c->write); + ev_timer_stop(c->loop, &c->hang_timer); + + /** pop in case it wasn't sent */ + rb_send_pop(&c->rb, c->pool); + + /** let holder know we're about to shutdown */ + if(c->shutdown_signal_holder) { + *c->shutdown_signal_holder = 1; + } + + if(c->monitor == 1 && c->parent != NULL) { + c->parent->clients--; + } + + hm_log(LOG_DEBUG, c->log, "{Connector}: async removing client %.*s:%d fd: %d type: %d alive since: %s", c->nip, c->ip, c->port, c->fd, c->type, c->date); + + connector_fd_close(c->fd); + + if(c->client_dc) { + c->client_dc(c->data, c->foreign_client_index, c->hbs_id); + } + +#ifdef HM_GAMESERVER + HT_REM(async_clients, c->client_index, strlen(c->client_index), c->pool); +#endif + + hm_pfree(c->pool, c); + + return 0; +} + +void async_handle_socket_errno(struct conn_client_s *c) +{ + if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + return; + } + + if(c == NULL) { + return; + } + + if(errno == ECONNRESET) { + hm_log(LOG_ERR, c->log, "{Connector} Connection reset by peer"); + } else if(errno == ETIMEDOUT) { + hm_log(LOG_ERR, c->log, "{Connector} Connection to backend timed out"); + } else if(errno == EPIPE) { + hm_log(LOG_ERR, c->log, "{Connector} Broken pipe to backend (EPIPE)"); + } else { + hm_log(LOG_ERR, c->log, "{Connector} errno: %d", errno); + } +} + +static void async_hang_timeout(struct ev_loop *loop, struct ev_timer *timer, int revents) +{ + struct conn_client_s *c = (struct conn_client_s *)timer->data; + + assert(c); + + hm_log(LOG_DEBUG, c->log, "{Connector}: read timeout"); + + if(c->error_callback) { + c->error_callback(c, CL_HANGTIMEOUT_ERR); + } +} + +#define NETDUMP(type, _buf, qq)\ + int i;\ +if(1 == 1) {\ + if(type == 0) {\ + hm_log(LOG_DEBUG, c->log, "sent: [%d] bytes %d", qq, fd);\ + } else {\ + hm_log(LOG_DEBUG, c->log, "received: [%d] bytes to fd %d", qq, fd);\ + }\ + printf("Ascii:\n--------\n");\ + for(i = 0; i < qq; i++) {\ + printf("%c", _buf[i] );\ + }\ + printf("Binary: ");\ + for( i = 0; i < qq; i++ ) {\ + printf("%.2x", (unsigned char)_buf[i] );\ + }\ + printf("\n");\ +} + +static void async_read(struct ev_loop *loop, ev_io *w, int revents) +{ + (void) revents; + int t = 0; + struct conn_client_s *c = (struct conn_client_s *)w->data; + int fd = w->fd, used; + + char *buf = rb_recv_ptr(&c->rb, &used); + + if(c->want_shutdown) { + if(c->error_callback) { + c->error_callback(c, CL_WANTSHUTDOWN_ERR); + } + + return; + } + + hm_log(LOG_DEBUG, c->log, "Received from fd %d", fd); + + t = recv(fd, buf, RB_SLOT_SIZE - used, 0); + + if(t > 0) { + //NETDUMP(1, buf, t) + rb_recv_append(&c->rb, t); + + if(rb_recv_is_full(&c->rb)) { + ev_io_stop(c->loop, &c->read); + if(c->error_callback) { + c->error_callback(c, CL_READRBFULL_ERR); + } + return; + } + + if(c->hang_timer_enabled == 1) { + ev_timer_stop(c->loop, &c->hang_timer); + ev_timer_again(c->loop, &c->hang_timer); + } + + c->recv(c); + + } else if(t == 0) { + async_handle_socket_errno(c); + if(c->error_callback) { + c->error_callback(c, CL_READZERO_ERR); + } + } else { + async_handle_socket_errno(c); + if(c->error_callback) { + c->error_callback(c, CL_READ_ERR); + } + } +} + +static void async_write(struct ev_loop *loop, ev_io *w, int revents) +{ + (void)revents; + int t; + struct conn_client_s *c = (struct conn_client_s *)w->data; + int fd = w->fd; + int sz; + + assert(c); + + char *next = rb_send_next(&c->rb, &sz); + + if(sz == 0) { + ev_io_stop(loop, &c->write); + return; + } + + t = send(fd, next, sz, MSG_NOSIGNAL); + if(t > 0) { + //NETDUMP(0, next, t) + rb_send_skip(&c->rb, t); + if(rb_send_is_empty(&c->rb)) { + ev_io_stop(loop, &c->write); + } + } else { + //assert(t == -1); + async_handle_socket_errno(c); + if(c->error_callback) { + c->error_callback(c, CL_WRITE_ERR); + } + } +} + +static void timestring(char *b, const int nb) +{ + char buf[128]; + time_t s; + struct timespec spec; + long long ms; + struct tm ts; + + clock_gettime(CLOCK_REALTIME, &spec); + s = spec.tv_sec; + ms = round(spec.tv_nsec / 1.0e6); + + ts = *localtime(&s); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts); + + snprintf(b, nb, "[%s.%03lld] ", buf, ms); +} + +int async_client(struct conn_client_s *client, const int monitor, const int hang) +{ + struct sockaddr_in servaddr; + char ip[32]; + + assert(client); + + /** TCP & non-blocking */ + client->fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + if(-1 == client->fd) { + hm_log(LOG_ERR, client->log, "{Connector}: node init socket error: %d", client->fd); + client->error_callback(client, CL_SOCKET_ERR); + return -1; + } + + snprintf(ip, sizeof(ip), "%.*s", client->nip, client->ip); + + setkeepalive(client->fd); + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = inet_addr(ip); + servaddr.sin_port = htons(client->port); + + ev_io_init(&client->write, async_write, client->fd, EV_WRITE); + ev_io_init(&client->read, async_read, client->fd, EV_READ); + ev_init(&client->hang_timer, async_hang_timeout); + + if(hang == 1) { + client->hang_timer.repeat = ASYNC_HANG_TIMEOUT; + client->hang_timer.data = client; + client->hang_timer_enabled = 1; + } else { + client->hang_timer_enabled = 0; + } + client->read.data = client; + client->write.data = client; + timestring(client->date, sizeof(client->date)); + + if(monitor == 1) { + connector_addclient(client->parent, client); + client->monitor = 1; + } + + ev_io_start(client->loop, &client->read); + ev_timer_again(client->loop, &client->hang_timer); + if(connect(client->fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != -1 && errno != EINPROGRESS) { + async_shutdown_client(client); + hm_log(LOG_ERR, client->log, "{Connector}: connect() errno: %d", errno); + return -1; + } + + return 0; +} + +static int async_client_accept(struct conn_client_s *client) +{ + ev_io_init(&client->write, async_write, client->fd, EV_WRITE); + ev_io_init(&client->read, async_read, client->fd, EV_READ); + //ev_init(&client->hang_timer, async_hang_timeout); + + client->hang_timer.repeat = ASYNC_HANG_TIMEOUT; + //client->hang_timer.data = client; + client->read.data = client; + client->write.data = client; + + ev_io_start(client->loop, &client->read); + + timestring(client->date, sizeof(client->date)); + //ev_timer_again(client->loop, &client->hang_timer); + + snprintf(client->client_index, sizeof(client->client_index), "%lld", client_index++); + +#ifdef HM_GAMESERVER + HT_ADD_WA(async_clients, client->client_index, strlen(client->client_index), client, sizeof(client), client->pool); +#endif + + return 0; +} diff --git a/hm_base/src/connector.c b/hm_base/src/connector.c new file mode 100644 index 0000000..e899370 --- /dev/null +++ b/hm_base/src/connector.c @@ -0,0 +1,277 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include // fcntl +#include +#include // close +#include +#include + +#include + +#include +#include + +#define CL(a, b) case a: hm_log(LOG_ERR, log, "{Connector}: fd:%d, "b, fd); break; + +void connector_fd_close(int fd) +{ + if(fd > STDERR_FILENO) { + close(fd); + } +} + +static int getsockerr(int fd, int name, void *optval, const int l, struct hm_log_s *log) +{ + int r; + socklen_t len = l; + + r = getsockopt(fd, SOL_SOCKET, name, optval, &len); + if(r < 0) { + switch(errno) { + CL(EBADF, "The argument sockfd is not a valid descriptor."); + CL(EFAULT, "The address pointed to by optval is not in a valid part of the process address space."); + CL(EINVAL, "optlen invalid in setsockopt()"); + CL(ENOPROTOOPT, "The option is unknown at the level indicated."); + CL(ENOTSOCK, "The argument sockfd is a file, not a socket."); + } + return -1; + } + return 0; +} + +static int getsoerror(int fd, struct hm_log_s *log) +{ + int error = 0; + + if(getsockerr(fd, SO_ERROR, &error, sizeof(int), log) < 0) { + return -1; + } + + switch(error) { + case 0: return 0; break; + CL(EACCES, "For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file, or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)"); CL(EPERM, "The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the connection request failed because of a local firewall rule."); + CL(EADDRINUSE, "Local address is already in use."); + CL(EAFNOSUPPORT, "The passed address didn't have the correct address family in its sa_family field."); + CL(EAGAIN, "No more free local ports or insufficient entries in the routing cache. For AF_INET see the description of /proc/sys/net/ipv4/ip_local_port_range ip(7) for information on how to increase the number of local ports."); + CL(EALREADY, "The socket is nonblocking and a previous connection attempt has not yet been completed."); + CL(EBADF, "The file descriptor is not a valid index in the descriptor table."); + CL(ECONNREFUSED, "No-one listening on the remote address."); + CL(EFAULT, "The socket structure address is outside the user's address space."); + CL(EINPROGRESS, "The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by selecting the socket forwriting. After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure)."); + CL(EINTR, "The system call was interrupted by a signal that was caught; see signal(7)."); + CL(EISCONN, "The socket is already connected."); + CL(ENETUNREACH, "Network is unreachable."); + CL(ENOTSOCK, "The file descriptor is not associated with a socket."); + CL(ETIMEDOUT, "Timeout while attempting connection. The server may be too busy to accept new connections. Note that for IP sockets the timeout may be very long when syncookies are enabled on the server."); + } + return -2; +} + +static int islinger(struct conn_node_s *c) +{ + struct linger l; + + if(getsockerr(c->fd, SO_LINGER, &l, sizeof(l), c->log) < 0) { + return -1; + } + + return l.l_onoff; +} + +static void failed_cb(struct ev_loop *loop, ev_timer *w, int revents) +{ + int r; + struct conn_node_s *c = (struct conn_node_s *)w->data; +#ifdef D_ASSERT + assert(c != NULL); +#endif + + ev_io_stop(loop, &c->io); + + r = islinger(c); + if(r < 0) { + hm_log(LOG_ERR, c->log, "{Connector}: error on socket %d", c->fd); + } else if(r > 0) { + hm_log(LOG_ERR, c->log, "{Connector}: SO_LINGER set on fd %d", c->fd); + } + connector_fd_close(c->fd); +} + +static void established_cb(struct ev_loop *loop, ev_io *w, int revents) +{ + int r; + struct conn_node_s *c = (struct conn_node_s *)w->data; + +#ifdef D_ASSERT + assert(c != NULL); +#endif + + ev_timer_stop(loop, &c->timer); + ev_io_stop(loop, w); + + r = getsoerror(c->fd, c->log); + + if(r == 0) { + c->status |= CONN_F_CONNECTED; + + if(!(c->status & CONN_F_FDOPEN)) { + r = islinger(c); + if(r < 0) { + hm_log(LOG_ERR, c->log, "{Connector}: error on socket %d", c->fd); + } else if(r > 0) { + hm_log(LOG_ERR, c->log, "{Connector}: SO_LINGER set on fd %d", c->fd); + } + connector_fd_close(c->fd); + } + + /**< return immediately when single check is performed or all nodes are connected */ + if(c->status & CONN_F_SINGLECHECK || ++(c->parent->established) == c->parent->size) { + ev_timer_stop(loop, &c->parent->timer); + c->parent->callback(c->parent); + } + } +} + +static int check_connection(struct conn_data_s *cd, struct conn_node_s *c) +{ + struct sockaddr_in servaddr; + +#ifdef D_ASSERT + assert(c != NULL && cd->loop != NULL); +#endif + if(strlen(c->host) < 1 || c->port < 1 || c->port > ((1<<16) - 1)) { + hm_log(LOG_ERR, c->log, "{Connector}: incorrect hostname or port: [%s]:%d", c->host, c->port); + return -1; + } + + c->fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + if(-1 == c->fd) { + hm_log(LOG_ERR, c->log, "{Connector}: FD = -1"); + return -1; + } + + // TODO: setsockopt depending on c->status + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=inet_addr(c->host); + servaddr.sin_port=htons(c->port); + + c->io.data = c; + ev_io_init(&c->io, established_cb, c->fd, EV_WRITE); + ev_io_start(cd->loop, &c->io); + + c->timer.data = c; + ev_timer_init(&c->timer, failed_cb, cd->timeout, 0); + ev_timer_start(cd->loop, &c->timer); + + hm_log(LOG_INFO, c->log, "{Connector}: connecting to %s:%d", c->host, c->port); + connect(c->fd, (struct sockaddr *)&servaddr, sizeof(servaddr)); + + return 0; +} + +static void terminator(struct ev_loop *loop, ev_timer *w, int revents) +{ + int i; + struct conn_data_s *c = (struct conn_data_s *)w->data; + +#ifdef D_ASSERT + assert(c != NULL); +#endif + /**< Terminate all connector events */ + for(i = 0; i < c->size; i++) { + if(c && c->loop && c->src[i]) { + ev_io_stop(c->loop, &c->src[i]->io); + ev_timer_stop(c->loop, &c->src[i]->timer); + } + } + + c->callback(c); +} + +int setkeepalive(int fd) +{ + int optval; + socklen_t optlen = sizeof(optval); + + optval = 1; + if(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { + return -1; + } + + return 0; +} + +int connector(struct conn_data_s *c) +{ + int i; + +#ifdef D_ASSERT + assert(c != NULL); +#endif + + c->established = 0; + for(i = 0; i < c->size; i++) { + c->src[i]->parent = c; + c->src[i]->log = c->log; + check_connection(c, c->src[i]); + } + + c->timer.data = c; + + ev_timer_init(&c->timer, terminator, c->exptime, 0); + ev_timer_start(c->loop, &c->timer); + + return 0; +} + +void connector_free(struct conn_data_s *c) +{ + if(!c) { + return; + } + + int i; + for(i = 0; i < c->size; i++) { + ev_io_stop(c->loop, &c->src[i]->io); + ev_timer_stop(c->loop, &c->src[i]->timer); + connector_fd_close(c->src[i]->fd); + hm_pfree(c->pool, c->src[i]); + } + + ev_timer_stop(c->loop, &c->timer); + hm_pfree(c->pool, c->src); + hm_pfree(c->pool, c); +} diff --git a/hm_base/src/couchbase.c b/hm_base/src/couchbase.c new file mode 100644 index 0000000..44430aa --- /dev/null +++ b/hm_base/src/couchbase.c @@ -0,0 +1,567 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// TODO: even though these globals can stay here, move them elsewhere in the future +static lcb_t *active_instance; +static struct conn_node_s **c; +static struct conn_data_s *cd; +static int BUCKETS_PER_CLUSTER; +static int HOSTS; +static int grcount = 0; /**< groups counter */ +static void (*callback)(struct instance_s *) = NULL; +static struct instance_s *instances = NULL; +static struct connstr_s **groups = NULL; +static struct hm_log_s *cb_log = NULL; + +static void error_callback(lcb_t instance, struct cbop_s *cbop, lcb_error_t error); +static int is_active_instance(lcb_t instance); +static void switch_instances(lcb_t instance); +static void bootstrap_callback(lcb_t instance, lcb_error_t err); +static void store_callback(lcb_t instance, const void *cookie, + lcb_storage_t operation, lcb_error_t error, const lcb_store_resp_t *resp); +static void remove_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_remove_resp_t *resp); +static void arithmetic_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_arithmetic_resp_t *resp); +static void get_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_get_resp_t *resp); +static int cb_get(struct cbop_s *cbop); +static int cb_arithmetic(struct cbop_s *cbop); +static int cb_remove(struct cbop_s *cbop); +static int cb_store(struct cbop_s *cbop); +static int cb_view(struct cbop_s *cbop); +static int storage_init(struct conn_data_s *cd, struct conn_node_s *cn, struct connstr_s *cs, const int idx ); +static void connector_cb(struct conn_data_s *c); + +static void error_callback(lcb_t instance, struct cbop_s *cbop, lcb_error_t error) +{ + hm_log(LOG_ERR, cb_log, "{Couchbase}: error 0x%x", error); + + // network related errors + if(error == LCB_NETWORK_ERROR || error == LCB_ETIMEDOUT || error == LCB_ENETUNREACH) { + if(is_active_instance(instance) == CB_ERR_OK) { + // switch instances and try again + // TODO: keep track of switching to avoid dead lock if all groups are offline + switch_instances(instance); + couchbase_operation(cbop); + } + } +} + +#define TYPE(T)\ + if(resp->version == CB_QUERY_VER) {\ + cbop->lcb_error = error;\ + cbop->u.T.r = resp;\ + if(cbop->post) {\ + cbop->post(cbop);\ + }\ + } + +static void store_callback(lcb_t instance, const void *cookie, + lcb_storage_t operation, lcb_error_t error, const lcb_store_resp_t *resp) +{ + struct cbop_s *cbop = (struct cbop_s *)cookie; + + if(error == LCB_SUCCESS || error == LCB_KEY_ENOENT || error == LCB_KEY_EEXISTS || (error == LCB_ETMPFAIL && CBSQ(cas) != 0)) { + TYPE(s) + } else { + error_callback(instance, cbop, error); + } +} + +static void remove_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_remove_resp_t *resp) +{ + struct cbop_s *cbop = (struct cbop_s *)cookie; + + if(error == LCB_SUCCESS || error == LCB_KEY_ENOENT || (error == LCB_ETMPFAIL && CBRQ(cas) != 0)) { + TYPE(r) + } else { + error_callback(instance, cbop, error); + } +} + +static void arithmetic_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_arithmetic_resp_t *resp) +{ + struct cbop_s *cbop = (struct cbop_s *)cookie; + + if(error == LCB_SUCCESS || error == LCB_KEY_ENOENT) { + TYPE(a) + } else { + error_callback(instance, cbop, error); + } +} + +static void get_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_get_resp_t *resp) +{ + struct cbop_s *cbop = (struct cbop_s *)cookie; + + if(error == LCB_SUCCESS || error == LCB_KEY_ENOENT) { + TYPE(g) + } else { + error_callback(instance, cbop, error); + } +} + +static int cb_get(struct cbop_s *cbop) +{ + lcb_error_t error; + const lcb_get_cmd_t *commands[] = { &(cbop->u.g.q) }; + + if(0) hm_log(LOG_DEBUG, cb_log, "{Couchbase}: get [%.*s]", (int)commands[0]->v.v0.nkey, (char*)commands[0]->v.v0.key); + error = lcb_get(active_instance[cbop->bucket], cbop, 1, commands); + if(error != LCB_SUCCESS) { + hm_log(LOG_ERR, cb_log, "{Couchbase}: couchbase operation failed with error: %d", error); + return error; + } + + return CB_ERR_OK; +} + +static int cb_arithmetic(struct cbop_s *cbop) +{ + lcb_error_t error; + const lcb_arithmetic_cmd_t *cmds[] = { &(cbop->u.a.q) }; + + error = lcb_arithmetic(active_instance[cbop->bucket], cbop, 1, cmds); + if(error != LCB_SUCCESS) { + hm_log(LOG_ERR, cb_log, "{Couchbase}: couchbase operation failed with error: %d", error); + return error; + } + + return CB_ERR_OK; +} + +static int cb_remove(struct cbop_s *cbop) +{ + lcb_error_t error; + const lcb_remove_cmd_t *cmds[] = { &(cbop->u.r.q) }; + + error = lcb_remove(active_instance[cbop->bucket], cbop, 1, cmds); + if(error != LCB_SUCCESS) { + hm_log(LOG_ERR, cb_log, "{Couchbase}: couchbase operation failed with error: %d", error); + return error; + } + + return CB_ERR_OK; +} + +static int cb_store(struct cbop_s *cbop) +{ + lcb_error_t error; + const lcb_store_cmd_t *cmds[] = { &(cbop->u.s.q) }; + + if(1 == 1) hm_log(LOG_DEBUG, cb_log, "{Couchbase}: set [%.*s], cas=0x%lx [%.*s]", (int)cmds[0]->v.v0.nkey, (char*)cmds[0]->v.v0.key, cmds[0]->v.v0.cas, (int)cmds[0]->v.v0.nbytes, (char*)cmds[0]->v.v0.bytes); + printf("bucket %p\n", active_instance[cbop->bucket]); + error = lcb_store(active_instance[cbop->bucket], cbop, 1, cmds); + + printf("bucket %p\n", active_instance[cbop->bucket]); + if (error != LCB_SUCCESS) { + hm_log(LOG_ERR, cb_log, "{Couchbase}: couchbase operation failed with error: %d", error); + return error; + } + + printf("error %d\n", error); + + return CB_ERR_OK; +} + +static int cb_view(struct cbop_s *cbop) +{ + lcb_error_t error; + + error = lcb_view_query(active_instance[cbop->bucket], cbop, &(cbop->u.v.q)); + if (error != LCB_SUCCESS) { + hm_log(LOG_ERR, cb_log, "{Couchbase}: couchbase operation failed with error: %d", error); + return error; + } + + return CB_ERR_OK; +} + +/**< @brief + * + * Natural selection based on network latency, whichever instance comes first, takes 0 index + */ +static void set_instance(lcb_t instance) +{ + const void *cookie; + struct instance_s *ins; + + cookie = lcb_get_cookie(instance); + ins = (struct instance_s *)cookie; + + if(active_instance[ins->index] == NULL) { + active_instance[ins->index] = instance; + hm_log(LOG_DEBUG, ins->log, "{Couchbase}: New instance on index %d from group: %d : %p", ins->index, ins->group, instance); + } +} + +// broken instance is set as active? +static int is_active_instance(lcb_t instance) +{ + int i; + + for(i = 0; i < BUCKETS_PER_CLUSTER; i++) { + if(active_instance[i] == instance) { + return CB_ERR_OK; + } + } + + return CB_ERR_NOACTIVE; +} + +static void switch_instances(lcb_t instance) +{ + int i, j, k; + const void *cookie; + struct instance_s *ins; + + cookie = lcb_get_cookie(instance); + ins = (struct instance_s *)cookie; + + for(i = 0; i < HOSTS; i++) { + for(j = 0; j < BUCKETS_PER_CLUSTER; j++) { + if(((struct cluster_s *)(cd->src[i]->data))->instance[j] != instance && + cd->src[i]->group != ins->group ) { + for(k = 0; k < BUCKETS_PER_CLUSTER; k++) { + hm_log(LOG_DEBUG, ins->log, "{Couchbase}: old instance: %p, new instance: %p, index: %d new host: %s", active_instance[k], ((struct cluster_s *)(cd->src[i]->data))->instance[k], k, cd->src[i]->host); + active_instance[k] = ((struct cluster_s *)(cd->src[i]->data))->instance[k]; + } + return; + } + } + } +} + +static void bootstrap_callback(lcb_t instance, lcb_error_t err) +{ + static int counter = 0; + const void *cookie; + struct instance_s *ins; + + cookie = lcb_get_cookie(instance); + ins = (struct instance_s *)cookie; + + if(err == LCB_SUCCESS) { + ins->status = 1; + set_instance(instance); + } else { + ins->status = 0; + hm_log(LOG_ERR, ins->log, "{Couchbase}: Bootstrap error 0x%x", err); + } + + ins->next = instances; + instances = ins; + + if(++counter >= (BUCKETS_PER_CLUSTER * grcount) && callback) { + callback(instances); + } +} + +static void destroy_callback(const void *cookie) +{ + struct instance_s *ins; + + ins = (struct instance_s *)cookie; + + ///< this causes SIGSEGV + //lcb_destroy_io_ops(ins->ioops); + + hm_pfree(ins->pool, ins); +} + +static int storage_init(struct conn_data_s *cd, struct conn_node_s *cn, struct connstr_s *cs, const int idx) +{ + lcb_error_t error; + struct lcb_create_io_ops_st ciops; + struct lcb_create_st copts; + char connstr[CONNSTR_SIZE]; + struct instance_s *ins; + struct cluster_s *cl = cn->data; + int nconnstr; + + memset(&ciops, 0, sizeof(ciops)); + memset(&copts, 0, sizeof(copts)); + ins = hm_palloc(cd->pool, sizeof(*ins)); + + ciops.v.v0.type = LCB_IO_OPS_LIBEV; + ciops.v.v0.cookie = cd->loop; + + assert(cl != NULL); + + error = lcb_create_io_ops(&ins->ioops, &ciops); + if(error != LCB_SUCCESS) { + hm_pfree(cd->pool, ins); + return CB_ERR_LCBCREATEIO; + } + + snprintf(connstr, sizeof(connstr), "couchbase://%.*s/%s", cs->len - 1, cs->host, cl->bucket[idx]); + hm_log(LOG_DEBUG, cd->log, "{Connector}: connstr: [%s]", connstr); + copts.version = 3; + copts.v.v3.connstr = connstr; + copts.v.v3.username = cl->bucket[idx]; + copts.v.v3.passwd = cl->passwd[idx]; + copts.v.v3.io = ins->ioops; + + error = lcb_create(&cl->instance[idx], &copts); + if(error != LCB_SUCCESS) { + hm_pfree(cd->pool, ins); + return CB_ERR_LCBCREATE; + } + + nconnstr = strlen(connstr); + ins->group = cs->id; + ins->index = idx; + memcpy(ins->connstr, connstr, nconnstr); + ins->connstr[nconnstr] = 0; + ins->loop = cd->loop; + ins->log = cd->log; + ins->pool = cd->pool; + lcb_set_cookie(cl->instance[idx], ins); + + lcb_set_bootstrap_callback(cl->instance[idx], bootstrap_callback); + lcb_set_get_callback(cl->instance[idx], get_callback); + lcb_set_store_callback(cl->instance[idx], store_callback); + lcb_set_remove_callback(cl->instance[idx], remove_callback); + lcb_set_arithmetic_callback(cl->instance[idx], arithmetic_callback); + lcb_set_destroy_callback(cl->instance[idx], destroy_callback); + + if((error = lcb_connect(cl->instance[idx])) != LCB_SUCCESS) { + lcb_destroy(cl->instance[idx]); + hm_pfree(cd->pool, ins); + return CB_ERR_LCBCONNECT; + } + + return CB_ERR_OK; +} + +static void buildconnstr(struct conn_data_s *c, struct connstr_s **groups, const char *host, const int group) +{ + int len; + + if(group >= MAX_GROUPS || group < 0) { + hm_log(LOG_ERR, c->log, "{Couchbase}: groups count error: %d", group); + return; + } + + if(groups[group] == NULL) { + groups[group] = hm_palloc(c->pool, sizeof(struct connstr_s)); + groups[group]->host = hm_palloc(c->pool, CONNSTR_SIZE); /**< max size */ + groups[group]->len = strlen(host); + groups[group]->id = group; + + memcpy(groups[group]->host, host, groups[group]->len); + groups[group]->host[groups[group]->len++] = ','; /**< connstr delimiter */ + + grcount++; + } else { + len = strlen(host); + memcpy(&(groups[group]->host[groups[group]->len]), host, len); + groups[group]->len += len; + groups[group]->host[groups[group]->len++] = ','; /**< connstr delimiter */ + } +} + +static void connector_cb(struct conn_data_s *c) +{ + int i, j, error, connected = 0; + + for(i = 0; i < c->size; i++) { + if(c->src[i] && (c->src[i]->status & CONN_F_CONNECTED)) { + hm_log(LOG_DEBUG, c->log, "{Connector}: Connected to %s:%d", c->src[i]->host, c->src[i]->port); + buildconnstr(c, groups, c->src[i]->host, c->src[i]->group); + connected = 1; + } else { + hm_log(LOG_NOTICE, c->log, "{Connector}: Failed to connect to %s:%d", c->src[i]->host, c->src[i]->port); + } + } + + /**< No available hosts found */ + if(connected != 1) { + callback(NULL); + return; + } + + for(i = 0; i < MAX_GROUPS; i++) { + if(groups[i] != NULL) { + for(j = 0; j < BUCKETS_PER_CLUSTER; j++) { + error = storage_init(c, c->src[i], groups[i], j); + if(error != CB_ERR_OK) { + hm_log(LOG_ERR, c->log, "{Couchbase}: storage_init failed for %s:%d with code 0x%x", c->src[i]->host, c->src[i]->port, error); + } + } + } + } +} + +int couchbase_init(struct couchbase_data_s *cbd) +{ + int i, j; + struct cluster_s *cl; + + groups = hm_palloc(cbd->pool, sizeof(void *) * MAX_GROUPS); + memset(groups, 0, sizeof(void *) * MAX_GROUPS); + + BUCKETS_PER_CLUSTER = cbd->nbuckets; + HOSTS = cbd->nhosts; + + assert(cbd->pool != NULL && cbd->log != NULL); + + cd = hm_palloc(cbd->pool, sizeof(*cd)); + cd->size = HOSTS; + cd->loop = cbd->loop; + cd->callback = connector_cb; + cd->log = cbd->log; + cd->pool = cbd->pool; + cd->timeout = 1.0; + cd->exptime = 2.0; + callback = cbd->callback; + cb_log = cbd->log; + + active_instance = hm_palloc(cd->pool, BUCKETS_PER_CLUSTER * sizeof(lcb_t)); + for(i = 0; i < BUCKETS_PER_CLUSTER; i++) { + active_instance[i] = NULL; + } + + c = hm_palloc(cd->pool, HOSTS * sizeof(void *)); + for( i = 0; i < HOSTS; i++ ) { + c[i] = hm_palloc(cd->pool, sizeof(*(c[i]))); + bzero(c[i], sizeof(*c[i])); + c[i]->port = 8091; + c[i]->status = CONN_F_COUCHBASE; /**< Couchbase opens its own FD */ + c[i]->group = cbd->hgroups[i]; + + memcpy( c[i]->host, cbd->hosts[i], strlen(cbd->hosts[i])+1 ); + + cl = hm_palloc(cd->pool, sizeof(*cl)); + cl->bucket = hm_palloc(cd->pool, sizeof(void *) * BUCKETS_PER_CLUSTER); + cl->passwd = hm_palloc(cd->pool, sizeof(void *) * BUCKETS_PER_CLUSTER); + cl->instance = hm_palloc(cd->pool, sizeof(lcb_t) * BUCKETS_PER_CLUSTER); + memset(cl->instance, 0, sizeof(lcb_t) * BUCKETS_PER_CLUSTER); + + for( j = 0; j < BUCKETS_PER_CLUSTER; j++ ) { + cl->bucket[j] = hm_palloc(cd->pool, strlen(cbd->buckets[j])+1); + cl->passwd[j] = hm_palloc(cd->pool, strlen(cbd->bpasswd[j])+1); + memcpy(cl->bucket[j], cbd->buckets[j], strlen(cbd->buckets[j])+1); + memcpy(cl->passwd[j], cbd->bpasswd[j], strlen(cbd->bpasswd[j])+1); + } + + c[i]->data = cl; + } + + cd->src = c; + connector( cd ); + + return CB_ERR_OK; +} + +int couchbase_bucket_index(const char *bucketName) { + if(HOSTS == 0) { + return -1; + } + + struct cluster_s *cl = (struct cluster_s*)c[0]->data; + int i; + for(i=0; ibucket[i], bucketName) == 0) { + return i; + } + } + return -1; +} + +int couchbase_operation(struct cbop_s *cbop) +{ + // TODO: check if bucket index in range + if(active_instance[cbop->bucket] == NULL) { + hm_log(LOG_ERR, cb_log, "{Couchbase}: No active instance for bucket: %d", cbop->bucket); + return CB_ERR_NOINSTANCE; + } + + switch(cbop->operation) { + case CB_GET: + return cb_get(cbop); + break; + case CB_STORE: + return cb_store(cbop); + break; + case CB_REMOVE: + return cb_remove(cbop); + break; + case CB_ARITH: + return cb_arithmetic(cbop); + break; + case CB_VIEW: + return cb_view(cbop); + break; + default: + hm_log(LOG_ERR, cb_log, "{Couchbase}: Operation not supported: %d", cbop->operation); + return CB_ERR_OPNOT; + break; + } +} + +void couchbase_deinit() +{ + int i, j; + //lcb_t instance; + struct cluster_s *cl; + const void *cookie; + + for(i = 0; i < MAX_GROUPS; i++) { + if(groups[i]) { + hm_pfree(cd->pool, groups[i]->host); + hm_pfree(cd->pool, groups[i]); + } + } + hm_pfree(cd->pool, groups); /**< groups */ + hm_pfree(cd->pool, active_instance); /**< active instances */ + + for(i = 0; i < HOSTS; i++) { + cl = cd->src[i]->data; + + for(j = 0; j < BUCKETS_PER_CLUSTER; j++) { + hm_pfree(cd->pool, cl->bucket[j]); + hm_pfree(cd->pool, cl->passwd[j]); + if(cl->instance[j]) { + cookie = lcb_get_cookie(cl->instance[j]); + lcb_destroy_async(cl->instance[j], cookie); + //lcb_destroy_io_ops(((struct instance_s *)cookie)->ioops); + } + } + hm_pfree(cd->pool, cl->bucket); + hm_pfree(cd->pool, cl->passwd); + hm_pfree(cd->pool, cl->instance); + hm_pfree(cd->pool, cl); + } + + connector_free(cd); +} diff --git a/hm_base/src/hashtable.c b/hm_base/src/hashtable.c new file mode 100644 index 0000000..a1b515e --- /dev/null +++ b/hm_base/src/hashtable.c @@ -0,0 +1,204 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include + +#include + +struct ht_s **ht_init(struct hm_pool_s *pool) +{ + struct ht_s **ht; + + ht = hm_palloc(pool, sizeof(void *) * HT_MAX); + if(ht == NULL) { + return NULL; + } + + memset(ht, 0, sizeof(void *) * HT_MAX); + + return ht; +} + +void ht_free(struct ht_s **ht, struct hm_pool_s *pool) +{ + hm_pfree(pool, ht); +} + +inline static void ht_key(int *dst, const char *key, const int nkey) +{ + int i; + + for(i = 0; i < nkey; i++) { + *dst += key[i]; + } + + *dst %= HT_MAX; +} + +int ht_add(struct ht_s **ht, const char *key, const int nkey, const void *value, const int nvalue, const int alloc, struct hm_pool_s *pool) +{ + struct ht_s *h; + int index = 0; + + assert(ht); + + ht_key(&index, key, nkey); + + for(h = ht[index]; h != NULL; h = h->next) { + if(nkey == h->nk && memcmp(key, h->k, nkey) == 0) { + /** first, free existing value */ + if(h->flag == HT_ALLOC) { + hm_pfree(pool, h->s); + } + + /** then copy new value */ + if(alloc == HT_ALLOC) { + h->s = hm_palloc(pool, nvalue); + if(h->s == NULL) { + return -1; + } +#ifdef POOL_STDLIB + memcpy(h->s, value, nvalue); +#else + hm_memcpy(h->s, value, nvalue, h->s); +#endif + } else { + h->s = (void *)value; + } + + h->flag = alloc; + h->n = nvalue; + + return 0; + } + } + + h = hm_palloc(pool, sizeof(*h)); + if(h == NULL) { + return -1; + } + + h->nk = nkey; + h->k = hm_palloc(pool, nkey); + if(h->k == NULL) { + return -1; + } + + h->n = nvalue; + + /* always allocate a key */ +#ifdef POOL_STDLIB + memcpy(h->k, key, nkey); +#else + hm_memcpy(h->k, key, nkey, h->k); +#endif + + if(alloc == HT_ALLOC) { + h->flag = HT_ALLOC; + h->s = hm_palloc(pool, nvalue); + if(h->s == NULL) { + return -1; + } + +#ifdef POOL_STDLIB + memcpy(h->s, value, nvalue); +#else + hm_memcpy(h->s, value, nvalue, h->s); +#endif + } else { + h->flag = 0; + h->s = (void *)value; + } + + h->next = ht[index]; + ht[index] = h; + + return 0; +} + +int ht_rem(struct ht_s **ht, const char *key, const int nkey, struct hm_pool_s *pool) +{ + struct ht_s *h, *prev = NULL; + int index = 0; + + assert(ht); + + ht_key(&index, key, nkey); + + for(h = ht[index], prev = NULL; h != NULL; prev = h, h = h->next) { + if(nkey == h->nk && memcmp(h->k, key, nkey) == 0) { + if(prev == NULL) { + ht[index] = h->next; + } else { + prev->next = h->next; + } + + if(h->flag == HT_ALLOC) { + hm_pfree(pool, h->s); + } + hm_pfree(pool, h->k); + + hm_pfree(pool, h); + return 0; + } + } + + return -1; +} + +struct ht_s *ht_get(struct ht_s **ht, const char *key, const int nkey) +{ + struct ht_s *h; + int index = 0; + + assert(ht); + + ht_key(&index, key, nkey); + + if(ht[index]) { + /** fast access - only one key exists under ht index */ + if(ht[index] && ht[index]->next == NULL) { + return ht[index]; + } + + /** otherwise traverse compare against all existing keys */ + for(h = ht[index]; h != NULL; h = h->next) { + if(h->nk == nkey && memcmp(h->k, key, nkey) == 0) { + return h; + } + } + return NULL; + } else { + return NULL; + } +} + +void ht_dump_index(struct ht_s **ht, const char *key, const int nkey) +{ + struct ht_s *h; + int index = 0; + + assert(ht); + + ht_key(&index, key, nkey); + + for(h = ht[index]; h != NULL; h = h->next) { + printf("index [%d] with key [%.*s], value [%.*s]\n", index, h->nk, h->k, h->n, h->s); + } +} diff --git a/hm_base/src/include/async_client.h b/hm_base/src/include/async_client.h new file mode 100644 index 0000000..6a796e9 --- /dev/null +++ b/hm_base/src/include/async_client.h @@ -0,0 +1,154 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HMCLIENT_H_ +#define HMCLIENT_H_ + +#define hm_send(c, conn_buf, conn_len)\ + /** Only respond if client is still active */\ +if(c) {\ + rb_send_init(&c->rb, (char *)conn_buf, conn_len, c->pool);\ + assert(c->loop);\ + ev_io_start(c->loop, &c->write);\ +} + +struct conn_client_s; + +enum clerr_e { + CL_NOERROR = 1, + CL_HANGTIMEOUT_ERR, + CL_WANTSHUTDOWN_ERR, + CL_READRBFULL_ERR, + CL_READZERO_ERR, + CL_READ_ERR, + CL_WRITE_ERR, + CL_BUFFERFULL_ERR, + CL_PACKETLEN_ERR, + CL_PACKETEXPECT_ERR, + CL_SERVERSHUTDOWN_ERR, + CL_SOCKET_ERR +}; + +struct conn_client_holder_s { + int signal_shutdown; ///< signal from client struct if it's already gone + struct conn_client_s *client; ///< actual client + struct conn_client_holder_s *next; ///< next client +}; + +struct conn_server_s { + struct ev_loop *loop; /**< An external event loop. */ + struct hm_pool_s *pool; + struct hm_log_s *log; + + struct conn_client_holder_s *clients_head; + int clients; + + struct ev_io listener; + int fd; + + const char *host; + const char *port; + + void (*recv)(struct conn_client_s *data, const char *buf, const int len); + void (*client_dc)(void *data, const char *foreign_client_index, const char *hbs_id); + void (*shutdown)(); +}; + +struct watcher_s { + struct conn_client_s *p1; + struct conn_client_s *p2; + int counter; + int target; +}; + +struct player_deck_s { + char code[16]; + int count; + struct player_deck_s *next; +}; + +struct conn_client_s { + struct ev_loop *loop; + struct hm_pool_s *pool; + struct hm_log_s *log; + + struct ev_io read; + struct ev_io write; + struct ev_timer hang_timer; + + int hang_timer_enabled; ///< TODO: move this to flag + int monitor; ///< TODO: move this to flag + + unsigned long long logs; /**< log sequence number */ + + int fd; + int *shutdown_signal_holder; + + int want_shutdown; + int type; + + struct rb_s rb; + + char net_buf[RB_SLOT_SIZE]; + int net_nbuf; + int net_expect; + + char client_index[32]; + char foreign_client_index[32]; + + char ip[64]; + int nip; + int port; + + char date[32]; + + void (*recv)(struct conn_client_s *client); + void (*error_callback)(struct conn_client_s *client, enum clerr_e error); + void (*client_dc)(void *data, const char *foregin_client_index, const char *hbs_id); + + void *data; + + struct conn_server_s *parent; + struct conn_client_holder_s *holder; + + char hbs_id[16]; +#ifdef HM_GAMESERVER + struct player_deck_s *cards; + int ncards; + char hero[16]; + char hp[16]; +#elif defined HM_LOBBYSERVER + char token[32]; + int ntoken; + + struct { + char user[32]; + char pass[32]; + char secret[32]; + } login; + + int skip; +#endif +}; + +struct ht_s **async_clients; // ht of async clients + +int async_shutdown_client(struct conn_client_s *c); +void shutdown_server(struct conn_server_s *cs); +int connector_server(struct conn_server_s *cs); + +#endif diff --git a/hm_base/src/include/connector.h b/hm_base/src/include/connector.h new file mode 100644 index 0000000..e351fad --- /dev/null +++ b/hm_base/src/include/connector.h @@ -0,0 +1,70 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CONNECTOR_H_ +#define CONNECTOR_H_ + +#define CONN_F_CONNECTED 0x1 /**< connected */ +#define CONN_F_FDOPEN 0x2 /**< keep FD open */ +#define CONN_F_SINGLECHECK 0x4 /**< interrupt watcher when single client connection est */ +#define CONN_F_COUCHBASE 0x8 /**< couchbase connection */ + +struct conn_data_s; +typedef void (*conn_cb_t)(struct conn_data_s *c); + +struct conn_node_s { + struct conn_data_s *parent; + int group; /**< Group ID */ + char host[128]; /**< Hostname that must be recognized by inet_addr */ + int port; /**< Port number */ + + int fd; /**< File descriptor */ + + unsigned int status; /**< Hostname:port's flag status */ + + struct ev_io io; /**< Event that is pushed to an external event loop. */ + struct ev_timer timer; /**< Timer which stops 'io'. */ + + unsigned long long logs; + + void *data; /**< Passed data */ + + struct hm_log_s *log; +}; + +struct conn_data_s { + struct ev_loop *loop; /**< An external event loop. */ + struct hm_pool_s *pool; + struct hm_log_s *log; + + unsigned long long logs; + + struct conn_node_s **src; /**< An array of conn_node_s to be watched. */ + int size; /**< Number of connectors to watch. */ + int established; + conn_cb_t callback; /**< Callback function to call when watcher finishes all jobs. */ + struct ev_timer timer; /**< Timer which finishes all jobs and invokes callback. */ + float exptime; /**< Expiration time which terminates all jobs */ + float timeout; /**< Timeout for specific host */ +}; + +int connector(struct conn_data_s *c); +void connector_fd_close(int fd); +void connector_free(struct conn_data_s *c); +int setkeepalive(int fd) ; + +#endif diff --git a/hm_base/src/include/hashtable.h b/hm_base/src/include/hashtable.h new file mode 100644 index 0000000..f5ffa0f --- /dev/null +++ b/hm_base/src/include/hashtable.h @@ -0,0 +1,51 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HASHTABLE_H_ +#define HASHTABLE_H_ + +#define HT_MAX (1<<12) +#define HT_ALLOC 0x1 + +#define HT_ADD(ht, key, nkey, value, nvalue, pool) ht_add(ht, key, nkey, value, nvalue, HT_ALLOC, pool) +#define HT_ADD_WA(ht, key, nkey, value, nvalue, pool) ht_add(ht, key, nkey, value, nvalue, 0, pool) +#define HT_REM(ht, key, nkey, pool) ht_rem(ht, key, nkey, pool) + +#define ht_item_clear(pool, dst)\ + if(dst && dst->n > 0) {\ + hm_pfree(pool, dst->s);\ + dst->s = NULL;\ + dst->n = 0;\ + } + +struct ht_s { + char *k; + int nk; + char *s; ///< value + int n; ///< nvalue + unsigned int flag; + struct ht_s *next; +}; + +struct ht_s **ht_init(struct hm_pool_s *pool); +void ht_free(struct ht_s **ht, struct hm_pool_s *pool); +int ht_add(struct ht_s **ht, const char *key, const int nkey, const void *value, const int nvalue, const int alloc, struct hm_pool_s *pool); +int ht_rem(struct ht_s **ht, const char *key, const int nkey, struct hm_pool_s *pool); +struct ht_s *ht_get(struct ht_s **ht, const char *key, const int nkey); +void ht_dump_index(struct ht_s **ht, const char *key, const int nkey); + +#endif diff --git a/hm_base/src/include/hmbase.h b/hm_base/src/include/hmbase.h new file mode 100644 index 0000000..f3f7542 --- /dev/null +++ b/hm_base/src/include/hmbase.h @@ -0,0 +1,32 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HMBASE_H_ +#define HMBASE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/hm_base/src/include/hmcouchbase.h b/hm_base/src/include/hmcouchbase.h new file mode 100644 index 0000000..7f468c8 --- /dev/null +++ b/hm_base/src/include/hmcouchbase.h @@ -0,0 +1,271 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HMCOUCHBASE_H_ +#define HMCOUCHBASE_H_ + +#include + +#define CB_ERR_OK 0x0 /**< No error */ +#define CB_ERR_LCBCREATEIO 0x1 /**< Failed to lcb_create_io_ops() */ +#define CB_ERR_LCBCREATE 0x2 /**< Failed to lcb_create() */ +#define CB_ERR_LCBCONNECT 0x3 /**< Failed to lcb_connect() */ +#define CB_ERR_NOINSTANCE 0x4 /**< No active instance found */ +#define CB_ERR_NOACTIVE 0x5 /**< Instance is not active */ +#define CB_ERR_OPNOT 0x6 /**< Operation not supporeted */ +#define CB_ERR_OPERR 0x7 /**< Operation error */ + +#define CB_QUERY_VER 0 + +#define CBVQ(m) cbop->u.v.q.m // couchbase view query +#define CBSQ(m) cbop->u.s.q.v.v0.m // couchbase store query +#define CBRQ(m) cbop->u.r.q.v.v0.m // couchbase remove query +#define CBGQ(m) cbop->u.g.q.v.v0.m // couchbase get query +#define CBGR(m) cbop->u.g.r->v.v0.m // CouchBase Get Reply +#define CBRR(m) cbop->u.r.r->v.v0.m // couchbase remove reply +#define CBSR(m) cbop->u.s.r->v.v0.m // couchbase store reply +#define CBAQ(m) cbop->u.a.q.v.v0.m // couchbase arithmetic query +#define CBAR(m) cbop->u.a.r->v.v0.m // couchbase arithmetic reply + +/**< CBSQ_V0 - CouchBase Store Query V0 + * bucket, operation, key, nkey, bytes, nbytes, callback, cas, exptime, datatype, flags + * 'struct cbop_s *cbop' must exist within context + */ +#define CBSQ_V0(b, o, k, nk, bt, nb, f, c, e, d, flag)\ + cbop->bucket = b;\ +cbop->operation = CB_STORE;\ +cbop->u.s.q.version = CB_QUERY_VER;\ +CBSQ(operation) = o;\ +CBSQ(key) = k;\ +CBSQ(nkey) = nk;\ +CBSQ(bytes) = bt;\ +CBSQ(nbytes) = nb;\ +CBSQ(cas) = c;\ +CBSQ(exptime) = e;\ +CBSQ(datatype) = d;\ +CBSQ(flags) = flag;\ +cbop->post = f;\ +(void)couchbase_operation(cbop); +/*if(couchbase_operation(cbop) != CB_ERR_OK) { */ + + +/**< CBGQ_V0 - CouchBase Get Query V0 + * bucket, key, nkey, callback, exptime, lock + * 'struct cbop_s *cbop' must exist within context + */ +#define CBGQ_V0(b, k, nk, f, e, l)\ + cbop->bucket = b;\ +cbop->operation = CB_GET;\ +cbop->u.g.q.version = CB_QUERY_VER;\ +CBGQ(key) = k;\ +CBGQ(nkey) = nk;\ +CBGQ(exptime) = e;\ +CBGQ(lock) = l;\ +cbop->post = f;\ +(void)couchbase_operation(cbop); +/*if(couchbase_operation(cbop) != CB_ERR_OK) { */ + +/**< CBRQ_V0 - CouchBase Remove Query V0 + * bucket, key, nkey, callback, cas + * 'struct cbop_s *cbop' must exist within context + */ +#define CBRQ_V0(b, k, nk, f, c)\ + cbop->bucket = b;\ +cbop->operation = CB_REMOVE;\ +cbop->u.r.q.version = CB_QUERY_VER;\ +CBRQ(key) = k;\ +CBRQ(nkey) = nk;\ +CBRQ(cas) = c;\ +cbop->post = f;\ +(void)couchbase_operation(cbop); +/*if(couchbase_operation(cbop) != CB_ERR_OK) { */ + +/**< CBAQ_V0 - CouchBase Arithmetic Query V0 + * bucket, key, nkey, callback, create, delta, initial + * 'struct cbop_s *cbop' must exist within context + */ +#define CBAQ_V0(b, k, nk, f, c, d, i)\ + cbop->bucket = b;\ +cbop->operation = CB_ARITH;\ +cbop->u.a.q.version = CB_QUERY_VER;\ +CBAQ(key) = k;\ +CBAQ(nkey) = nk;\ +CBAQ(create) = c;\ +CBAQ(delta) = d;\ +CBAQ(initial) = i;\ +cbop->post = f;\ +(void)couchbase_operation(cbop); +/*if(couchbase_operation(cbop) != CB_ERR_OK) { */ + +/**< CBVQ_V0 - CouchBase View Query V0 + * bucket, cmd, doc, ndoc, view, nview, options, noptions, post, npost, dcm, callback, handle + * 'struct cbop_s *cbop' must exist within context + */ +#define CBVQ_V0(b, c, d, nd, v, nv, o, no, p, np, dcm, f, h)\ + cbop->bucket = b;\ +cbop->operation = CB_VIEW;\ +CBVQ(cmdflags) = c;\ +CBVQ(ddoc) = d;\ +CBVQ(nddoc) = nd;\ +CBVQ(view) = v;\ +CBVQ(nview) = nv;\ +CBVQ(optstr) = o;\ +CBVQ(noptstr) = no;\ +CBVQ(postdata) = p;\ +CBVQ(npostdata) = np;\ +CBVQ(docs_concurrent_max) = dcm;\ +CBVQ(callback) = f;\ +CBVQ(handle) = h;\ +(void)couchbase_operation(cbop); +/*if(couchbase_operation(cbop) != CB_ERR_OK) { */ + +#define CONNSTR_SIZE 2048 +#define MAX_GROUPS 16 /**< max couchbase datacenters */ + +typedef enum { + CB_GET = 0x1, + CB_STORE = 0x2, + CB_REMOVE = 0x3, + CB_ARITH = 0x4, + CB_VIEW = 0x5 +} cboperation_t; + +/* + typedef enum { + LCB_ADD = 0x01, + LCB_REPLACE = 0x02, + LCB_SET = 0x03, + LCB_APPEND = 0x04, + LCB_PREPEND = 0x05 + } lcb_storage_t; + */ + +/* + syslog priorities: + LOG_EMERG system is unusable + LOG_ALERT action must be taken immediately + LOG_CRIT critical conditions + LOG_ERR error conditions + LOG_WARNING warning conditions + LOG_NOTICE normal, but significant, condition + LOG_INFO informational message + LOG_DEBUG debug-level message + */ + +/** + * @brief cbop_s structure is passed to every couchbase request + * + * User must allocate and deallocate space for this structure. + */ +struct cbop_s { + int bucket; /**< Index of bucket */ + cboperation_t operation; /**< Couchbase operation, @see cboperation_t */ + void (*post)(struct cbop_s *cbop); + lcb_error_t lcb_error; /**< Libcouchbase error code in case callback function needs it */ + + union { + struct { + lcb_get_cmd_t q; /**< Query */ + const lcb_get_resp_t *r; /**< Response */ + } g; /**< This is a Get procedure definition. */ + + struct { + lcb_store_cmd_t q; /**< Query */ + const lcb_store_resp_t *r; /**< Response */ + } s; /**< This is a Store procedure definition. */ + + struct { + lcb_remove_cmd_t q; /**< Query */ + const lcb_remove_resp_t *r; /**< Response */ + } r; /**< This is a Remove procedure definition. */ + + struct { + lcb_arithmetic_cmd_t q; /**< Query */ + const lcb_arithmetic_resp_t *r; /**< Response */ + } a; /**< This is an Arithmetic procedure definition. */ + + struct { + lcb_CMDVIEWQUERY q; /**< Query */ + struct lcb_RESPVIEW_st r; /**< Response */ + } v; /**< This is a View procedure definition. */ + } u; + + void *g_child; /** grunt's child */ + void *data; /**< Some other client's data. */ +}; + +/** + * @brief struct cluster_s + * + * Every bucket has its own instance. + */ +struct cluster_s { + char **bucket; + char **passwd; + lcb_t *instance; + +}; + +struct couchbase_data_s; +/** + * @brief struct instance_s + * + * Every cluster has its own group. + */ +struct instance_s { + struct ev_loop *loop; + struct hm_log_s *log; + struct hm_pool_s *pool; + char connstr[CONNSTR_SIZE]; + int status; + int group; + int index; + lcb_io_opt_t ioops; + struct instance_s *next; +}; + +/** + * @brief struct couchbase_data_s + * + */ +struct couchbase_data_s { + struct ev_loop *loop; + struct hm_log_s *log; + struct hm_pool_s *pool; + void (*callback)(struct instance_s *data); + + const char **hosts; + const int *hgroups; + int nhosts; + const char **buckets; + const char **bpasswd; + int nbuckets; +}; + +struct connstr_s { + int id; + char *host; + int len; +}; + +int couchbase_init(struct couchbase_data_s *cbd); +int couchbase_bucket_index(const char *bucketName); ///< Returns the bucket index, or -1 if there is no such bucket +int couchbase_operation(struct cbop_s *cbop); +void couchbase_deinit(); +extern int couchbase_deinit_async; + +#endif diff --git a/hm_base/src/include/log.h b/hm_base/src/include/log.h new file mode 100644 index 0000000..2fa9690 --- /dev/null +++ b/hm_base/src/include/log.h @@ -0,0 +1,50 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HMLOG_H_ +#define HMLOG_H_ + +#include + +enum errors_e { + LOG_EMERG = 0, ///< system is unusable + LOG_ALERT, ///< action must be taken immediately + LOG_CRIT, ///< critical conditions + LOG_ERR, ///< error conditions + LOG_WARNING, ///< warning conditions + LOG_NOTICE, //< normal, but significant, condition + LOG_INFO, //< informational message + LOG_DEBUG, ///< debug-level message + LOG_MEMORY, ///< memory-level message +}; + +struct hm_log_s { + const char *name; + int fd; + FILE *file; + void *data; + int priority; +}; + +#define hm_log(t, l, fmt...)\ + hm_log_impl(0, t, l, __FILE__, __LINE__, __FUNCTION__, fmt) + +int hm_log_impl(unsigned long long seq_nb, int priority, struct hm_log_s *log, const char *file, int line, const char *func, const char *fmt, ...) __attribute__ ((format (printf, 7, 8))); +int hm_log_open(struct hm_log_s *l, const char *filename, const int priority); +int hm_log_close(struct hm_log_s *l); + +#endif diff --git a/hm_base/src/include/pool.h b/hm_base/src/include/pool.h new file mode 100644 index 0000000..5d6b3ef --- /dev/null +++ b/hm_base/src/include/pool.h @@ -0,0 +1,55 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HMPOOL_H_ +#define HMPOOL_H_ + +#define POOL_DEBUG +#define POOL_STDLIB + +struct pool_bucket_s { + void *memory_region; + void *nodes; + struct pool_bucket_s *next; +}; + +struct hm_pool_s { + int size; + int used; + struct hm_log_s *log; + struct pool_node_s *freenode; + struct pool_bucket_s *buckets; + struct hm_pool_s *next; +}; + +struct pool_node_s { + void *ptr; + int size; + int realsize; + int used; + struct hm_pool_s *pool; + struct pool_node_s *next; +}; + +struct hm_pool_s *hm_create_pool(); +void *hm_palloc(struct hm_pool_s *pool, int size); +void *hm_prealloc(struct hm_pool_s *pool, void *ptr, const int size); +void *hm_memcpy(void *dst, const void *src, const int n, void *start); +int hm_pfree(struct hm_pool_s *pool, void *ptr); +int hm_destroy_pool(struct hm_pool_s *pool); + +#endif diff --git a/hm_base/src/include/rb.h b/hm_base/src/include/rb.h new file mode 100644 index 0000000..177dbe2 --- /dev/null +++ b/hm_base/src/include/rb.h @@ -0,0 +1,51 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef RB_H +#define RB_H + +#define RB_SLOT_SIZE (16 * 1024) + + +struct rb_slot_s { + void *buf; + int len; + int sent; + struct rb_slot_s *next; +}; + +struct rb_s { + struct { + char slot[RB_SLOT_SIZE]; + int len; + } recv; + + struct rb_slot_s *send, *tail; +}; + +char *rb_send_next(struct rb_s *rb, int *size); +void rb_send_skip(struct rb_s *rb, int offset); +int rb_send_is_empty(struct rb_s *rb); +void rb_send_pop(struct rb_s *rb, struct hm_pool_s *pool); +int rb_send_init(struct rb_s *rb, char *buf, const int len, struct hm_pool_s *pool); +char *rb_recv_ptr(struct rb_s *rb, int *used); +void rb_recv_append(struct rb_s *rb, const int len); +char *rb_recv_read(struct rb_s *rb, int *size); +void rb_recv_pop(struct rb_s *rb); +int rb_recv_is_full(struct rb_s *rb); + +#endif diff --git a/hm_base/src/include/utils.h b/hm_base/src/include/utils.h new file mode 100644 index 0000000..565c2be --- /dev/null +++ b/hm_base/src/include/utils.h @@ -0,0 +1,139 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef UTILS_H_ +#define UTILS_H_ + +#include +#include +#include +#include + +#define EQFLAG(d, f)\ + ((d & f) == f) + +/** N memory compare */ +#define nmc(dst, ndst, src, nsrc) (ndst == nsrc && memcmp(dst, src, ndst) == 0) + +inline static void to_lower(char *bytes, const int nbytes) +{ + int i; + + for(i = 0; i < nbytes; i++) { + if(bytes[i] >= 65 && bytes[i] <= 90) { + bytes[i] += 32; + } + } +} + +inline static void mac_tonum(char *dst, const int ndst, char *src, const int nsrc) +{ + char *s, *e; + int i; + + if(nsrc != 17 || ndst < 17) { + return; + } + + for(i = 0, s = src, e = src + nsrc; s < e; s++) { + if(*s == ':' && s - 2 >= src) { + memcpy(&dst[i], s - 2, 2); + i += 2; + } + else if(i == 10 && s + 2 <= e) { + memcpy(&dst[i], s, 2); + i += 2; + } + } + + dst[i] = '\0'; +} + +inline static void replace_space(char *dst, const int ndst, const char src) +{ + char *s, *e; + + for(s = dst, e = dst + ndst; s < e; s++) { + if(*s == ' ') { + *s = src; + } + } +} + +inline static void num_tomac(char *dst, const int ndst, char *src, const int nsrc) +{ + int i = 0; + char *ds, *de; + char *ss, *se; + + // 17 + 1 term + if(ndst < 18) { + return; + } + + for(i = 0, + ss = src, se = src + nsrc, + ds = dst, de = dst + ndst; + (ss < se && (ds + i)< de); + /* void */) { + memcpy(&dst[i], ss, 2); + i += 2; + dst[i++] = ':'; + ss += 2; + if(i >= 16) { + dst[--i] = '\0'; + return; + } + } +} + +inline static int is_valid_mac(char *buf, const int len) +{ + char *s, *e; + + if(len < 17) { + return -1; + } + + /** buf must point to first char of mac */ + for(s = buf, e = buf + len; s < e; s++) { + /** we're looking for a mac address xx:xx:xx:xx:xx:xx + * ( 1 - : ) || ( A - Z ) || ( a - z ) + */ + if(!((*s >= 48 && *s <= 58) || (*s >= 65 && *s <= 90) || (*s >= 97 && *s <= 122))) { + return -1; + } + + if(s - buf == 16) { + return (s - buf) + 1; + } + } + + return -1; +} + +inline static int random_number(int max) +{ + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + srand(ts.tv_nsec); + + return (rand() % max); +} + +#endif diff --git a/hm_base/src/log.c b/hm_base/src/log.c new file mode 100644 index 0000000..5b56e6f --- /dev/null +++ b/hm_base/src/log.c @@ -0,0 +1,133 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int hm_log_impl(unsigned long long seq_nb, int priority, struct hm_log_s *log, const char *file, const int line, const char *func, const char *msg, ...) +{ + size_t len = 0; + char out[8192], buf[128]; + time_t s; + struct timespec spec; + long long ms; + struct tm ts; + + assert(log); + + /** only display messages user asked for */ + if(priority > log->priority) { + return -1; + } + + //if(log->fd == STDERR_FILENO) + { + const char *colour; + switch(priority) { + case LOG_EMERG: //< system is unusable + colour = "(%llu) \33[1;31;41mLOG_EMERG\33[m"; + break; + case LOG_ALERT: //< action must be taken immediately + colour = "(%llu) \33[1;33;41mLOG_ALERT\33[m"; + break; + case LOG_CRIT: //< critical conditions + colour = "(%llu) \33[1;31;40mLOG_CRIT\33[m"; + break; + case LOG_ERR: //< error conditions + colour = "(%llu) \33[1;34;41mLOG_ERR\33[m"; + break; + case LOG_WARNING: //< warning conditions + colour = "(%llu) \33[1;37;43mLOG_WARNING\33[m"; + break; + case LOG_NOTICE: //< normal, but significant, condition + colour = "(%llu) \33[1;34;47mLOG_NOTICE\33[m"; + break; + case LOG_INFO: //< informational message + colour = "(%llu) \33[1;37;42mLOG_INFO\33[m"; + break; + case LOG_DEBUG: //< debug-level message + colour = "(%llu) \33[1;32;40mLOG_DEBUG\33[m"; + break; + case LOG_MEMORY: //< memory message + colour = "(%llu) \33[1;35;34mLOG_MEMORY\33[m"; + break; + default: + colour = NULL; + } + if(colour) { + len += snprintf(out, sizeof(out), colour, seq_nb); + } + } + + clock_gettime(CLOCK_REALTIME, &spec); + s = spec.tv_sec; + ms = round(spec.tv_nsec / 1.0e6); + + ts = *localtime(&s); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts); + + len += snprintf(out + len, sizeof(out) - len, "[%s.%03lld] ", buf, ms); + + va_list args; + va_start(args, msg); + len += vsnprintf(out+len, 3*sizeof(out)/4-len, msg, args); + va_end(args); + if(len >= 3*sizeof(out)/4) { + len += snprintf(out + len, sizeof(out) - len, "..."); + } + + len += snprintf(out+len, sizeof(out)-len, ", %s:%d(%s)\n", file, line, func); + + ssize_t nwritten = write(log->fd, out, len); + return (nwritten == len) ? 0 : -1; +} + +int hm_log_open(struct hm_log_s *l, const char *filename, const int priority) +{ + if(filename != NULL) { + l->file = fopen(filename, "a"); + if(l->file == NULL) { + return -1; + } + l->fd = fileno(l->file); + } else { + l->file = stderr; + l->fd = STDERR_FILENO; + } + + l->priority = priority; + + return 0; +} + +int hm_log_close(struct hm_log_s *l) +{ + if(l->file && l->file != stderr) { + fclose(l->file); + return 0; + } else { + return -1; + } +} diff --git a/hm_base/src/pool.c b/hm_base/src/pool.c new file mode 100644 index 0000000..6db27ad --- /dev/null +++ b/hm_base/src/pool.c @@ -0,0 +1,368 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +#include + +#define BUCKET_MAX 2 +#define ROUND16(dst) (((dst) + 15) & ~15) + +#define get_meta(m_ptr) (*(struct pool_node_s **)((struct pool_node_s ***)(m_ptr - sizeof(void *)))) + +static int pool_create_bucket(struct hm_pool_s *pool); + +int hm_pfree(struct hm_pool_s *pool, void *ptr) +{ +#ifdef POOL_STDLIB + free(ptr); + return 0; +#endif + + struct hm_pool_s *p; + struct pool_node_s *node; + + if(ptr == NULL) { + return -1; + } + + /** get to metadata */ + node = get_meta(ptr); + + for(p = pool; p != NULL; p = p->next) { + if(node && node->used && node->size == p->size) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: old freenode: %p/%d, new freenode: %p/%d from pool:%p/%d", p->freenode, p->freenode->realsize, node, node->realsize, p, p->size); +#endif + node->used = 0; + node->next = p->freenode; + p->freenode = node; + + --p->used; + + return 0; + } + } + + return -1; +} + +static void *pool_get_node(struct hm_pool_s *pool, const int realsize) +{ + struct pool_node_s *node = NULL; + + node = pool->freenode; + assert(node); + pool->freenode = node->next; + + if(node->next == NULL) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "no more freenodes remaining in pool: %p/%d, creating new bucket", pool, pool->size); +#endif + if(pool_create_bucket(pool) != 0) { + return NULL; + } + } + +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: returning node: %p/%d, new freenode: %p from pool: %p/%d", node, realsize, pool->freenode, pool, pool->size); +#endif + + /** increment used nodes */ + ++pool->used; + + /** real size of block */ + node->realsize = realsize; + + node->used = 1; + + /** metadata offset */ + return (node->ptr + sizeof(void *)); +} + +/** don't do anything but creating a zero valued holder */ +struct hm_pool_s *hm_create_pool(struct hm_log_s *log) +{ + struct hm_pool_s *pool; + + pool = malloc(sizeof(*pool)); + + if(pool == NULL) { + return NULL; + } + + memset(pool, 0, sizeof(*pool)); + pool->log = log; + +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: pool created %p", pool); +#endif + return pool; +} + +static int pool_create_bucket(struct hm_pool_s *pool) +{ + int i; + void *nodes, *region; + struct pool_bucket_s *b; + struct pool_node_s *node; + + /** holder of buckets */ + b = malloc(sizeof(*b)); + + if(b == NULL) { + return -1; + } + + region = malloc((pool->size + sizeof(void *)) * BUCKET_MAX); + + /** nodes holders */ + nodes = malloc(BUCKET_MAX * sizeof(struct pool_node_s)); + + if(nodes == NULL) { + return -1; + } + + b->memory_region = region; + b->nodes = nodes; + + for(i = 0; BUCKET_MAX > i; i++) { + node = (struct pool_node_s *)(nodes + (i * sizeof(struct pool_node_s))); + /** node's offset set by i * (metadata + size)*/ + node->ptr = (void *)(region + i * (sizeof(void *) + pool->size)); + /** copy metadata to offset + 0 */ + memcpy(node->ptr, &node, sizeof(node)); + +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "new node: %p in pool: %p old freenode: %p pool size: %d node ptr: %p reg: %p", node, pool, pool->freenode, pool->size, node->ptr, *(void **)node->ptr); + + /* + for(j = 0; j < 32; j++) { + printf("%d|", ((char *)(node->ptr))[j]); + } + */ +#endif + + node->size = pool->size; + node->next = pool->freenode; + node->pool = pool; + node->realsize = 0; + pool->freenode = node; + } + + b->next = pool->buckets; + pool->buckets = b; + + return 0; +} + +void *hm_memcpy(void *dst, const void *src, const int n, void *start) +{ + int diff; + struct pool_node_s *node; + + node = get_meta(start); + + diff = dst - (node->ptr + sizeof(void *)); + + //printf("memcpy diff %d\n", node->size); + + if(n + diff > node->size) { + hm_log(LOG_ERR, node->pool->log, "{Pool}: illegal memcpy(), overlapping dst of %d with %d bytes", node->size, diff + n); + return NULL; + } else { + return memcpy(dst, src, n); + } +} + +static struct hm_pool_s *pool_create_append(struct hm_pool_s *pool, const int size) +{ + struct hm_pool_s *p, *tp; + + p = malloc(sizeof(*p)); + + if(p == NULL) { + return NULL; + } + + /** set pool size */ + p->size = size; + p->next = NULL; + p->freenode = NULL; + p->buckets = NULL; + p->used = 0; + p->log = pool->log; + + if(pool_create_bucket(p) != 0) { + return NULL; + } + + for(tp = pool; tp != NULL; tp = tp->next) { + if(tp->next == NULL) { + tp->next = p; + break; + } + } + + return p; +} + +/** + The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents + will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If + the new size is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the + call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, + then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call + to malloc(), calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done. + */ +void *hm_prealloc(struct hm_pool_s *pool, void *ptr, const int size) +{ +#ifdef POOL_STDLIB + return realloc(ptr, size); +#endif + + struct pool_node_s *node = NULL; + void *dst; + + if(ptr != NULL) { + node = get_meta(ptr); + } + + if(ptr == NULL && size == 0) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: doing nothing"); +#endif + /** do nothing */ + return NULL; + } else if(ptr == NULL && size != 0) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: malloc() size: %d", size); +#endif + /** malloc() */ + return hm_palloc(pool, size); + } else if(ptr != NULL && size == 0) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: free() size: %d", size); +#endif + /** free() */ + if(hm_pfree(pool, ptr) != 0) { + return NULL; + } + + return NULL; + } else if(ptr != NULL && node != NULL && node->size == size) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: status quo for size: %d", size); +#endif + /** nothing needs to be changed - return exactly the same pointer */ + return ptr; + } else if(ptr != NULL && size > 0 && node != NULL && node->size != size) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: realloc for old size: %d new size: %d", node->size, size); +#endif + /** realloc() */ + + /** first allocate new dst */ + dst = hm_palloc(pool, size); + + if(dst == NULL) { + return NULL; + } + + /** copy src to dst */ + if(node->realsize <= size) { + memcpy(dst, ptr, node->realsize); + } else { + memcpy(dst, ptr, size); + } + + /** free src */ + hm_pfree(pool, ptr); + + return dst; + } + + return NULL; +} + +void *hm_palloc(struct hm_pool_s *pool, int size) +{ +#ifdef POOL_STDLIB + return malloc(size); +#endif + + struct hm_pool_s *p; + + assert(pool); + + for(p = pool; p != NULL; p = p->next) { + /** do we match an existing pool */ + if(ROUND16(size) == p->size) { +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: found existing pool: %p/%d", p, p->size); +#endif + return pool_get_node(p, size); + } + } + + p = pool_create_append(pool, ROUND16(size)); + + if(p == NULL) { + return NULL; + } + +#ifdef POOL_DEBUG + hm_log(LOG_MEMORY, pool->log, "{Pool}: creating new pool with parent pool: %p/%d", p, p->size); +#endif + + return pool_get_node(p, size); +} + +int hm_destroy_pool(struct hm_pool_s *pool) +{ + struct hm_pool_s *p, *pd; + struct pool_bucket_s *b, *bd; + + for(p = pool; p != NULL; ) { + for(b = p->buckets; b != NULL; ) { + free(b->memory_region); + free(b->nodes); + + bd = b; + b = b->next; + free(bd); + } + pd = p; + p = p->next; + free(pd); + } + + return 0; +} + +void pool_info(struct hm_pool_s *pool) +{ + struct hm_pool_s *p; + + for(p = pool; p != NULL; p = p->next) { + printf("pool size: %d used: %d\n", p->size, p->used); + } +} diff --git a/hm_base/src/rb.c b/hm_base/src/rb.c new file mode 100644 index 0000000..ae101f4 --- /dev/null +++ b/hm_base/src/rb.c @@ -0,0 +1,147 @@ +/* + hm_base - hearthmod base library + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include + +#include + +/** Send functions */ +char *rb_send_next(struct rb_s *rb, int *size) +{ + assert(rb); + + if(rb->send == NULL) { + *size = 0; + return NULL; + } + + *size = rb->send->len - rb->send->sent; + // test + /* + if(*size >= 10) { + *size = 10; + } + */ + + return (char *)(rb->send->buf + rb->send->sent); +} + +static void rb_next(struct rb_s *rb) +{ + struct rb_slot_s *next; + + if(rb && rb->send && rb->send->sent == rb->send->len) { + next = rb->send->next; + free(rb->send->buf); + free(rb->send); + rb->send = next; + if(rb->send == NULL) { + rb->tail = NULL; + } + } + +} + +void rb_send_skip(struct rb_s *rb, int offset) +{ + assert(rb); + assert(rb->send); + rb->send->sent += offset; + + rb_next(rb); +} + +int rb_send_is_empty(struct rb_s *rb) +{ + assert(rb); + return (rb->send == NULL); +} + +void rb_send_pop(struct rb_s *rb, struct hm_pool_s *pool) +{ + rb_next(rb); +} + +int rb_send_init(struct rb_s *rb, char *buf, const int len, struct hm_pool_s *pool) +{ + assert(rb); + struct rb_slot_s *slot; + + slot = malloc(sizeof(*slot)); + if(slot == NULL) { + return -1; + } + slot->buf = malloc(len); + if(slot->buf == NULL) { + free(slot); + return -1; + } + + memcpy(slot->buf, buf, len); + slot->len = len; + slot->sent = 0; + slot->next = NULL; + + if(rb->send == NULL && rb->tail == NULL) { + //printf("added to head send init\n"); + rb->send = rb->tail = slot; + } else { + + //printf("added to tail send init\n"); + assert(rb->tail); + rb->tail->next = slot; + rb->tail = slot; + } + + return 0; +} + +/** Receive functions */ +char *rb_recv_ptr(struct rb_s *rb, int *used) +{ + assert(rb && used); + *used = rb->recv.len; + return (rb->recv.slot + rb->recv.len); +} + +void rb_recv_append(struct rb_s *rb, const int len) +{ + assert(rb); + rb->recv.len += len; +} + +char *rb_recv_read(struct rb_s *rb, int *size) +{ + assert(rb && size); + *size = rb->recv.len; + return rb->recv.slot; +} + +void rb_recv_pop(struct rb_s *rb) +{ + assert(rb); + rb->recv.len = 0; +} + +int rb_recv_is_full(struct rb_s *rb) +{ + assert(rb); + return (rb->recv.len >= RB_SLOT_SIZE); +} diff --git a/hm_database/README.md b/hm_database/README.md new file mode 100644 index 0000000..b5557d6 --- /dev/null +++ b/hm_database/README.md @@ -0,0 +1,6 @@ +# hm_database +hearthmod database dump + +# This is not a standalone project! + +[hm_database](https://github.com/farb3yonddriv3n/hm_database) is part of [hearthmod software stack](https://github.com/hearthmod/hearthmod) diff --git a/hm_database/backup.sh b/hm_database/backup.sh new file mode 100644 index 0000000..bf596b7 --- /dev/null +++ b/hm_database/backup.sh @@ -0,0 +1,2 @@ +/opt/couchbase/bin/cbbackup http://localhost:8091 `pwd`/hbs/ \ + -u $1 -p $2 -b hbs diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/design.json b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/design.json new file mode 100644 index 0000000..1c3245b --- /dev/null +++ b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/design.json @@ -0,0 +1 @@ +[{"controllers": {"compact": "/pools/default/buckets/hbs/ddocs/_design%2Fdev_result/controller/compactView", "setUpdateMinChanges": "/pools/default/buckets/hbs/ddocs/_design%2Fdev_result/controller/setUpdateMinChanges"}, "doc": {"json": {"views": {"result": {"map": "function (doc, meta) {\n if(doc.w && doc.l) {\n \temit(meta.id, doc);\n }\n}"}}}, "meta": {"rev": "4-1816919e", "id": "_design/dev_result"}}}] \ No newline at end of file diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/index.json b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/index.json new file mode 100644 index 0000000..5f089cf --- /dev/null +++ b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/index.json @@ -0,0 +1 @@ +{"metadata": [{"indexerId": "7a:b4:24:44:47:40:57:8e"}]} \ No newline at end of file diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/data-0000.cbb b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/data-0000.cbb new file mode 100644 index 0000000..79f7449 Binary files /dev/null and b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/data-0000.cbb differ diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/failover.json b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/failover.json new file mode 100644 index 0000000..816c9ad --- /dev/null +++ b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/failover.json @@ -0,0 +1 @@ +{"344": [[109511276406493, 0], [8197387970012, 0], [124900151077590, 0], [251989250869696, 0], [132149525650875, 0], [114321195273677, 0], [220786799163528, 0], [145772213395739, 0], [138341386813203, 0]], "0": [[211873880862224, 0], [38217831624821, 0], [260739638952872, 0], [11309532803740, 0], [263688395877725, 0], [140626966386946, 0], [155514617464798, 0], [86201614130009, 0], [22144714569130, 0]], "346": [[59813372362336, 0], [205545927297157, 0], [99171498691780, 0], [129610042928685, 0], [154451580484378, 0], [156468338165112, 0], [141429184655374, 0], [205021733194380, 0], [43068707193820, 0]], "347": [[13552419956369, 0], [131492504105843, 0], [20632857731080, 0], [274716182515791, 0], [220831831621356, 0], [28649070393510, 0], [249864616718711, 0], [63512855621536, 0], [143542829686395, 0]], "340": [[160483784755964, 0], [142241822461333, 0], [210386310943947, 0], [14631199190832, 0], [35324966406517, 0], [149087001027627, 0], [131819827476540, 0], [103520876803049, 0], [132740904928340, 0]], "341": [[224584014985074, 0], [107080893752204, 0], [85763059202669, 0], [170206230636485, 0], [264580711492969, 0], [145854273900940, 0], [95079591674540, 0], [82041730696678, 0], [142625463737757, 0]], "342": [[54640742380481, 0], [119224449005949, 0], [122940888123966, 0], [275772353046410, 0], [172347715791067, 0], [115635772995008, 0], [8898540154971, 0], [44615626944799, 0], [186487305468764, 0]], "343": [[42031608620168, 0], [213666733765623, 0], [217653515359615, 0], [165628972212582, 0], [156998193060934, 0], [151472750020608, 0], [259615069761785, 0], [51938053441333, 0], [214170561350720, 0]], "810": [[27953013828354, 0], [138778486570826, 0], [48816109474868, 0], [86710849177419, 0], [28119533112347, 0], [204750037219816, 0], [276090378436098, 0], [172301613948160, 0], [272766455298064, 0]], "811": [[169043273031924, 0], [200019688656368, 0], [240524727162374, 0], [221472243915795, 0], [212999219154954, 0], [214809862599790, 0], [168675885181900, 0], [247406612232453, 0], [277989961324584, 0]], "812": [[252491739679122, 0], [158446718034446, 0], [241785892532964, 0], [62054066395985, 0], [176926764457359, 0], [135114858092618, 0], [240434444621242, 0], [206151332800088, 0], [261006606659459, 0]], "813": [[24096903799977, 0], [82662981941463, 0], [154636190842931, 0], [30164002740405, 0], [40477136727199, 0], [44620926640308, 0], [142324016948501, 0], [115504322883, 0], [10036393427240, 0]], "348": [[178815953954050, 0], [112191438750470, 0], [12036964745429, 0], [69424333642469, 0], [44743479560352, 0], [95741919915515, 0], [231059397297153, 0], [278119283607015, 0], [45394980792911, 0]], "349": [[63586708953153, 0], [43000074354588, 0], [137165707968536, 0], [71987230328308, 0], [232262580282559, 0], [155922091509247, 0], [23658979989547, 0], [30814411121208, 0], [253105284513690, 0]], "816": [[97579767889608, 0], [142112955931575, 0], [34434338792248, 0], [237039019800382, 0], [128356025408207, 0], [88562195926937, 0], [119345280532010, 0], [43462609099587, 0], [68514953271293, 0]], "817": [[267322951392207, 0], [167762569022878, 0], [91381778085750, 0], [26209856528639, 0], [26899269754817, 0], [250917700822623, 0], [142612054610644, 0], [122180450725542, 0], [207516437537360, 0]], "595": [[194551117411596, 0], [165297045011697, 0], [48261051641027, 0], [189879263531985, 0], [130704497250135, 0], [129131534743113, 0], [127479852515866, 0], [74346886503789, 0], [228949840762296, 0]], "719": [[53818810953105, 0], [180989621641936, 0], [174860666121962, 0], [155395733426334, 0], [86154251870149, 0], [77639873267307, 0], [119571096739036, 0], [258743816998748, 0], [107842198364523, 0]], "718": [[37679611059782, 0], [148198076420563, 0], [170975970787922, 0], [166577280261543, 0], [126105641122244, 0], [9956158903092, 0], [104062525252544, 0], [97889716527373, 0], [71876965249590, 0]], "717": [[215490201083594, 0], [151134370505222, 0], [14024781853351, 0], [127273010945485, 0], [224514627544655, 0], [230412635170480, 0], [124274845231824, 0], [64873880147137, 0], [215420210830565, 0]], "716": [[43841591727314, 0], [145125178473020, 0], [84487444269885, 0], [248913951575669, 0], [240273100857735, 0], [258756231052924, 0], [23493082623903, 0], [122429561483782, 0], [155797319545890, 0]], "715": [[130682194252576, 0], [14739755291715, 0], [273842023107715, 0], [105405495774251, 0], [204972532970890, 0], [36076061462697, 0], [250341259145539, 0], [119073202910480, 0], [231143990077000, 0]], "714": [[47262298101349, 0], [108602085290393, 0], [46680884999684, 0], [174606566835705, 0], [278578515634419, 0], [23153249383651, 0], [279607105068149, 0], [239128323474087, 0], [171557178424996, 0]], "713": [[184731129459399, 0], [242836276400057, 0], [5236885722369, 0], [103893165109205, 0], [96383695453235, 0], [247335976796391, 0], [202877071592927, 0], [96789096455193, 0], [188218366583050, 0]], "712": [[143156668510866, 0], [36863619247201, 0], [216562340000829, 0], [200979308912903, 0], [91685440997284, 0], [226601890606001, 0], [211575773814257, 0], [59596297279409, 0], [185384117959825, 0]], "711": [[254919800632368, 0], [149560288276954, 0], [77320521667728, 0], [54782814155765, 0], [68238094761305, 0], [45379071361445, 0], [203169353486948, 0], [158243205576004, 0], [168122138398130, 0]], "710": [[4028647821072, 0], [193122800358172, 0], [2936739257533, 0], [243557715795557, 0], [52540353153125, 0], [257726758473518, 0], [209931298256433, 0], [207745880669401, 0], [172362312040109, 0]], "915": [[238663227667957, 0], [7533199378557, 0], [265415180175448, 0], [99020390306834, 0], [58171850204369, 0], [64599487377882, 0], [220147329281332, 0], [204696856723757, 0], [202942931457080, 0]], "914": [[277811512424985, 0], [230221673678085, 0], [160544688758899, 0], [177877761859190, 0], [57422057110760, 0], [270318603199374, 0], [145864769395909, 0], [27078298226624, 0], [206641155456849, 0]], "606": [[93116974424051, 0], [10587509507544, 0], [124606427229273, 0], [81570654394866, 0], [232202238973726, 0], [234289734634214, 0], [151210943967260, 0], [251935798704624, 0], [277051431954816, 0]], "917": [[277691023435407, 0], [106101444414148, 0], [44921689937044, 0], [51043549604772, 0], [165078146792241, 0], [88704803082685, 0], [54735837188253, 0], [52361319959656, 0], [177420139922965, 0]], "594": [[125320191564331, 0], [251212417157209, 0], [168167931362583, 0], [175870549271665, 0], [96236307040859, 0], [216342020204530, 0], [136089864479078, 0], [152247012298204, 0], [226390176301907, 0]], "736": [[105087070041161, 0], [232657090782919, 0], [10394254396100, 0], [65537461871989, 0], [144594857491101, 0], [120651074664678, 0], [63428088349294, 0], [112374605852855, 0], [268376817246224, 0]], "916": [[70398074800803, 0], [242856616886256, 0], [145320678466968, 0], [17099822902722, 0], [268096059502112, 0], [171281608004487, 0], [65082939296938, 0], [35389518513000, 0], [171063200478410, 0]], "911": [[80801306810934, 0], [109410383269450, 0], [19391747478136, 0], [255760264925052, 0], [133031626402533, 0], [74196149053889, 0], [259676523965500, 0], [187270762325352, 0], [78222381661522, 0]], "619": [[195815343701357, 0], [32727199230880, 0], [26602684127728, 0], [6041058277203, 0], [199932356539189, 0], [88606495291753, 0], [241724270460026, 0], [221721745281634, 0], [23702151866691, 0]], "910": [[157580702294275, 0], [75645693426238, 0], [41168821137236, 0], [112233661327123, 0], [53387589448949, 0], [164197006360710, 0], [276125772461489, 0], [59984935230947, 0], [59644591801182, 0]], "913": [[265262404930339, 0], [34713744712093, 0], [244909751933318, 0], [45846767212221, 0], [280080873761110, 0], [256018064112627, 0], [36498053305217, 0], [148803661621507, 0], [242377291491114, 0]], "298": [[130026259028023, 0], [247848192196023, 0], [21826185835801, 0], [15492733044429, 0], [279849421966681, 0], [104163942221861, 0], [143718571214550, 0], [148541272736045, 0], [76627800299951, 0]], "299": [[159567275457812, 0], [242363812869610, 0], [1829524724331, 0], [149532769740076, 0], [155639356740329, 0], [33624093061233, 0], [226121216046166, 0], [24573369986335, 0], [246890957986543, 0]], "296": [[190107625852074, 0], [261471653831487, 0], [229545983151568, 0], [281442613928434, 0], [77989045218151, 0], [210215556727141, 0], [9165702507643, 0], [23217949179700, 0], [99647837218156, 0]], "297": [[200993203199939, 2], [64350137207860, 2], [38288955561108, 2], [280520086900355, 2], [115845211035772, 2], [130748871044568, 2], [47588429237247, 1], [66689737072972, 1], [212499871218288, 0]], "294": [[212758615577086, 0], [39175665331991, 0], [193674959632860, 0], [251277810533533, 0], [197857191502086, 0], [17794011136272, 0], [52875383268007, 0], [114143521900952, 0], [215227135240908, 0]], "295": [[87866593065399, 0], [208007045873474, 0], [218379960227246, 0], [217537142441565, 0], [102624600088184, 0], [134787299257496, 0], [71531530833847, 0], [230582440993753, 0], [245398815328210, 0]], "292": [[50488344866815, 0], [129280786069154, 0], [169880065478547, 0], [200575917588914, 0], [234090324629514, 0], [43071498173893, 0], [12168699070715, 0], [84119134335469, 0], [13167667337665, 0]], "293": [[94153308027302, 0], [266896042155054, 0], [165168254248337, 0], [24254771734055, 0], [195353800562992, 0], [166646125903363, 0], [225034788324630, 0], [249906113675926, 0], [17338569567688, 0]], "290": [[79130488231743, 0], [107881526012040, 0], [205820533956578, 0], [262951173307485, 0], [139134787638012, 0], [260101801701533, 0], [228127590024426, 0], [223341483791001, 0], [179789809911695, 0]], "291": [[259837072582083, 0], [171791594676320, 0], [13780489446825, 0], [123832593350170, 0], [167951254264263, 0], [153362094678390, 0], [276808924771508, 0], [211225313230621, 0], [269439855145905, 0]], "591": [[146246928410909, 0], [11840596778620, 0], [48167670708826, 0], [39648524273005, 0], [243042622779994, 0], [141961805005503, 0], [271578835382118, 0], [275559180950451, 0], [244016551319181, 0]], "590": [[273454163406057, 0], [204396865441190, 0], [240239390966930, 0], [197971441550967, 0], [17522941832658, 0], [271363286953795, 0], [111061596648162, 0], [51785663410755, 0], [243369707195022, 0]], "593": [[212263378239708, 0], [226419010783085, 0], [159492476244963, 0], [197877701453323, 0], [75773129527907, 0], [118236741221043, 0], [8426674030257, 0], [38020759818123, 0], [116973233220394, 0]], "592": [[47571508930554, 0], [49529491032725, 0], [154423293924874, 0], [224142325951055, 0], [220743854561557, 0], [39360045690225, 0], [85570962525518, 0], [108241727193974, 0], [235228408002478, 0]], "199": [[140934691389069, 0], [252075471198242, 0], [181310222623733, 0], [146716583305646, 0], [97255504771471, 0], [98934843448475, 0], [54211256283064, 0], [64538770889697, 0], [39181377886893, 0]], "198": [[154735978588906, 0], [119784528512146, 0], [250202386606010, 0], [59317234054634, 0], [20456618445880, 0], [11600204495321, 0], [123241070690316, 0], [230731386991475, 0], [64854529604085, 0]], "597": [[34346715425197, 0], [140767569553085, 0], [147167864000905, 0], [184889051506066, 0], [129484858256610, 0], [277980458887989, 0], [112624091185131, 0], [236243004393053, 0], [256580814406368, 0]], "596": [[86578819798144, 0], [206872857647239, 0], [84017228591468, 0], [259563627993285, 0], [255009754770043, 0], [251013011326428, 0], [253470008711439, 0], [35878301435149, 0], [3781046284850, 0]], "195": [[17000255704531, 0], [268827762875863, 0], [232672359550416, 0], [148133104296014, 0], [94925341047062, 0], [136732023761241, 0], [177935929732647, 0], [56238839886777, 0], [85269731891885, 0]], "194": [[118173213571019, 0], [245371276753902, 0], [168527574139883, 0], [154379893778862, 0], [168847726662274, 0], [54017297391643, 0], [101741316339288, 0], [49567295949691, 0], [83150854389690, 0]], "197": [[234452791114962, 0], [93426973473906, 0], [107907430466610, 0], [77419047776156, 0], [106851918107385, 0], [35380460748674, 0], [44579504464654, 0], [39612079596042, 0], [164833490014127, 0]], "196": [[97816218030448, 0], [66325872514010, 0], [211753860833632, 0], [118514861463937, 0], [2605651068511, 0], [18871776219640, 0], [270388281805687, 0], [110266982718928, 0], [271138693428529, 0]], "191": [[249719862512866, 0], [115430875844889, 0], [99129179135222, 0], [90392214161395, 0], [159111807957331, 0], [193422671486916, 0], [6384738183635, 0], [59431227731093, 0], [202709559037407, 0]], "190": [[272911773882333, 0], [262288074180655, 0], [154106104958383, 0], [242801328601776, 0], [235733109046497, 0], [97763219724404, 0], [262516572468151, 0], [40244108123944, 0], [215115806539753, 0]], "193": [[45678208790073, 0], [258871388315518, 0], [262820427453614, 0], [35704215980025, 0], [220040831873238, 0], [210658569901413, 0], [186107796293281, 0], [62403881086568, 0], [113254214858396, 0]], "192": [[11267519443992, 0], [86588176159786, 0], [200482895138750, 0], [235408991489402, 0], [137652524334997, 0], [56903618919736, 0], [244210292286065, 0], [138997453343145, 0], [180658456665896, 0]], "270": [[1228427206359, 0], [218267170548365, 0], [218245787986465, 0], [236835878366909, 0], [126975258232729, 0], [244696399997688, 0], [241293302735484, 0], [126885114943115, 0], [215242267609860, 0]], "271": [[72419727513651, 0], [33936117716636, 0], [54250434273252, 0], [69522215315979, 0], [156012379527241, 0], [62925019869467, 0], [160861672649307, 0], [248730314528128, 0], [227723843584112, 0]], "272": [[67153478268553, 0], [92787067398641, 0], [152226671258395, 0], [248827226719569, 0], [73736590725236, 0], [184267943786298, 0], [170266950683605, 0], [139757771105006, 0], [273768026243355, 0]], "273": [[47940160366598, 0], [176497191349371, 0], [211073882504152, 0], [233447294320226, 0], [105994709655096, 0], [2719614314573, 0], [147049235485220, 0], [46158144702544, 0], [83403592606046, 0]], "274": [[160168363810082, 0], [209295109730412, 0], [277980454593055, 0], [255073348379099, 0], [250767471579110, 0], [175301264166817, 0], [189870010821534, 0], [56543530586710, 0], [281006809462177, 0]], "275": [[90162723442999, 0], [122089480341966, 0], [207435814131761, 0], [120122257216468, 0], [206369532715354, 0], [123549008601144, 0], [29151310313948, 0], [220673617823727, 0], [222824077945781, 0]], "276": [[68832454359885, 0], [2280834742513, 0], [192981709989669, 0], [221737761466131, 0], [236189214450108, 0], [69884163901720, 0], [278320674734503, 0], [210712759890293, 0], [51513727918463, 0]], "277": [[168845567680609, 626], [203030672539436, 626], [57234509456675, 626], [185243534693558, 284], [278731326066704, 271], [235259542722731, 208], [233910653403475, 113], [187694798908501, 52], [61162876100704, 0]], "278": [[277014120869658, 0], [77408236503230, 0], [194589643032917, 0], [116847774215867, 0], [159791661700398, 0], [24425046366288, 0], [176254404196936, 0], [251507112886400, 0], [261095098876103, 0]], "279": [[174883660919935, 0], [221761667656597, 0], [217622238308971, 0], [129190077176117, 0], [218438727859589, 0], [73570759866711, 0], [157385783332174, 0], [219195033378983, 0], [212208771378668, 0]], "738": [[174417990224516, 0], [145136230133908, 0], [136606220303926, 0], [174558077183899, 0], [247361468586081, 0], [216411682225399, 0], [106585608265363, 0], [229197223284552, 0], [47965094200727, 0]], "524": [[176492674935292, 0], [235032655776404, 0], [119870909278176, 0], [123988230806535, 0], [223418001083037, 0], [18269737088795, 0], [39453056840105, 0], [97056559253199, 0], [109532795792059, 0]], "525": [[269991727842171, 0], [217493550191852, 0], [40330749093660, 0], [239218425482657, 0], [55434991177924, 0], [115145191199995, 0], [25896317380077, 0], [192735174531053, 0], [115083762864211, 0]], "526": [[235376725107083, 0], [5281053702715, 0], [185110624830974, 0], [257959538063731, 0], [79365865330510, 0], [200178577090947, 0], [170213882169764, 0], [46419437529379, 0], [120222425440591, 0]], "527": [[234631497667665, 0], [58852936522987, 0], [208982914771994, 0], [177676682680472, 0], [50883734370839, 0], [225715106672520, 0], [40884651799091, 0], [256665251588644, 0], [98689681003023, 0]], "520": [[272287949377455, 0], [47520366142927, 0], [2697276594944, 0], [79538357052172, 0], [280156852462126, 0], [75864574868203, 0], [180270655688492, 0], [43768403630, 0], [108296337482996, 0]], "521": [[150648246320833, 0], [144428631782093, 0], [163278780881487, 0], [148961112800492, 0], [180600232930610, 0], [131107921377039, 0], [258774002987389, 0], [21917192740538, 0], [17078402469222, 0]], "522": [[40466720776060, 736], [203196271435920, 736], [261978342342064, 736], [158883644409685, 288], [163913498643556, 275], [161367317212093, 214], [267069650725002, 118], [277579222799485, 54], [265590101817199, 0]], "523": [[56799811968618, 0], [27444083078775, 0], [248302904209322, 0], [138766711188074, 0], [134987027564613, 0], [43317370277648, 0], [15272011336144, 0], [206980406640348, 0], [153650915526583, 0]], "1014": [[38239209206885, 0], [154594250445067, 0], [4218505634389, 0], [195547505868419, 0], [164098236239393, 0], [47740084932765, 0], [192863640207532, 0], [113292574154028, 0], [21798724467909, 0]], "1015": [[88054656888648, 0], [114870931740988, 0], [63559780450418, 0], [242529026579118, 0], [170893139992027, 0], [191364867188325, 0], [99148284254974, 0], [224648786494448, 0], [205530514110346, 0]], "599": [[165132312053531, 0], [21633442559585, 0], [172657157254972, 0], [225034170112, 0], [13420174807699, 0], [22951580322336, 0], [172422096613449, 0], [82686383419061, 0], [72066776160259, 0]], "1017": [[12477250537213, 0], [235484532152640, 0], [33277981071604, 0], [113246764529861, 0], [241935294494191, 0], [157967329615450, 0], [88256958401313, 0], [46881762927150, 0], [219080668596100, 0]], "528": [[248207079083844, 0], [199485144453569, 0], [89388318067608, 0], [59885118534115, 0], [60500213672631, 0], [64570311753914, 0], [190672167701080, 0], [88914822553357, 0], [72253112214455, 0]], "529": [[104611309032514, 0], [257195620174269, 0], [263498511404802, 0], [29836664809986, 0], [75342740410769, 0], [261122566323282, 0], [96103394675400, 0], [98106113207948, 0], [201429946695460, 0]], "994": [[124251919161873, 0], [31310090583269, 0], [293842494209, 0], [114773611539817, 0], [77682768287483, 0], [12631736792296, 0], [252327028695232, 0], [53680599889566, 0], [122510035945486, 0]], "1013": [[263735181151195, 0], [272591285083165, 0], [164435363820870, 0], [23136564991975, 0], [58524131167119, 0], [117996858948868, 0], [145857677039528, 0], [130915458645236, 0], [10231828585742, 0]], "449": [[230667111859818, 0], [116394417321196, 0], [255712974154852, 0], [11647585970045, 0], [248784531226623, 0], [12014810369086, 0], [119493812668104, 0], [68588974818784, 0], [142928974418160, 0]], "448": [[217542219699115, 0], [150604165567066, 0], [250561517534557, 0], [77743691869171, 0], [147977502921669, 0], [33954339100403, 0], [276518809172955, 0], [226210022708769, 0], [104983873768811, 0]], "443": [[237549409512625, 0], [243084818536944, 0], [95212592234621, 0], [328654391362, 0], [38017333943926, 0], [255226165858212, 0], [38436304014001, 0], [225424624240717, 0], [182453204040158, 0]], "442": [[31680249892358, 0], [229975189174341, 0], [175118991517476, 0], [189068260384105, 0], [152990297926495, 0], [266033663563131, 0], [172858543006574, 0], [127571778297677, 0], [222702053881330, 0]], "441": [[27257303010237, 0], [102188606182571, 0], [276644659359135, 0], [64800322648669, 0], [247965771155067, 0], [161693994104298, 0], [19326702203292, 0], [108948613607526, 0], [28898390082970, 0]], "440": [[43291642631492, 0], [158725413332639, 0], [96614261760627, 0], [217878663068226, 0], [137735545962348, 0], [129650503015109, 0], [75256524214485, 0], [168067393242267, 0], [235865973482478, 0]], "447": [[64509696313713, 0], [205523855831330, 0], [234024772686119, 0], [107197570902463, 0], [58931389017559, 0], [28828115163013, 0], [137614830650902, 0], [96038186747694, 0], [113885233105507, 0]], "446": [[156143293118017, 0], [196045791948284, 0], [159251549094738, 0], [53907439970123, 0], [177414316304858, 0], [54997602560736, 0], [163907806544265, 0], [203260909103998, 0], [230572632286730, 0]], "445": [[238045770812631, 0], [15734086995831, 0], [52387773110154, 0], [11244324695551, 0], [159832989583352, 0], [5647553886268, 0], [102069589134671, 0], [64018629578959, 0], [53981156746588, 0]], "444": [[225616551632827, 0], [99527736011773, 0], [103807533282401, 0], [245666528126814, 0], [117505814774200, 0], [278347298212640, 0], [88371244672839, 0], [28226849958532, 0], [146141659333265, 0]], "108": [[158277519390030, 0], [9343099382436, 0], [241298996994996, 0], [145225964759420, 0], [239402134251808, 0], [11052177689757, 0], [72206950983761, 0], [101945948572101, 0], [98075370618917, 0]], "109": [[142538074602908, 0], [277168477321335, 0], [150466663290069, 0], [203942622628334, 0], [183633881657404, 0], [228375710558757, 0], [66410426102728, 0], [86187117460495, 0], [158237414053607, 0]], "102": [[27582311728842, 0], [269685050864768, 0], [159097843426795, 0], [183878962458493, 0], [18354861322571, 0], [47951415789896, 0], [279431219796535, 0], [101730468737414, 0], [213964127663761, 0]], "103": [[61151792179157, 0], [144461701452172, 0], [233403218552159, 0], [166231815863471, 0], [83300286550436, 0], [42605946422328, 0], [195302007700274, 0], [11455980448676, 0], [279149404495673, 0]], "100": [[45659979320065, 0], [18327037747750, 0], [38088340843556, 0], [266551199796604, 0], [40058086759168, 0], [236650944545058, 0], [207893454117380, 0], [25992741496646, 0], [43842017413327, 0]], "101": [[124419168690861, 0], [152252235312736, 0], [183087811163850, 0], [259015482415175, 0], [194711393162364, 0], [88634958147418, 0], [255587796908201, 0], [15372081847217, 0], [97343310431523, 0]], "106": [[178981485569168, 0], [221376714665435, 0], [108211349307399, 0], [114833221124557, 0], [15659615091389, 0], [210893004635036, 0], [7739069380731, 0], [95619403803032, 0], [142864710464350, 0]], "107": [[181063015763128, 0], [264672733223713, 0], [61759355266867, 0], [98410802967882, 0], [55219405162358, 0], [91761570219427, 0], [217827197761885, 0], [111927633135164, 0], [111906810764678, 0]], "104": [[278613386636922, 0], [137062563668298, 0], [79377567811853, 0], [45834960890480, 0], [90571309213423, 0], [247371556025488, 0], [105454145654801, 0], [276034759488384, 0], [87260487242562, 0]], "105": [[261439960208928, 0], [162794967785690, 0], [232256905147209, 0], [85763301523406, 0], [221063643481306, 0], [46135783248772, 0], [225045414361888, 0], [153716113025036, 0], [281074232624157, 0]], "902": [[137930298872663, 2], [226380155982162, 2], [178324462776547, 2], [35307792928143, 0], [59036457354325, 0], [261522140052867, 0], [158944527280803, 0], [178992774977234, 0], [221738106927587, 0]], "903": [[73297403862067, 0], [125932555043970, 0], [198848701677972, 0], [68416368185944, 0], [72105182218725, 0], [16216867048831, 0], [253491714315404, 0], [201315186424265, 0], [199666944364225, 0]], "39": [[223784390723762, 3], [218890986207235, 3], [120090953376077, 3], [221761945337970, 3], [136806179765427, 3], [31571076020885, 3], [84026119819896, 3], [175687831037587, 3], [251908435766484, 0]], "38": [[51094974942361, 0], [114380017261557, 0], [280138881059601, 0], [34525241306394, 0], [257415517463032, 0], [60107403741069, 0], [44058360094763, 0], [94351915766433, 0], [50815986495998, 0]], "906": [[65929445493197, 0], [140210302051650, 0], [274494943368347, 0], [227054113828458, 0], [24983433103347, 0], [15859404032259, 0], [225370064536720, 0], [125559845572113, 0], [187479977730938, 0]], "907": [[75169674117779, 0], [175066740264066, 0], [171664563009536, 0], [178570375366351, 0], [21489326275045, 0], [109514467057665, 0], [188848445324559, 0], [208321911711054, 0], [236487815606421, 0]], "904": [[99393832694626, 0], [164388485935320, 0], [153511333733147, 0], [118713776404669, 0], [190931163726244, 0], [139425093259872, 0], [220463621890301, 0], [56707034972670, 0], [128258202733107, 0]], "905": [[120528510182008, 0], [235258276224162, 0], [147624978394138, 0], [125241900046417, 0], [101900796425953, 0], [217755532907127, 0], [202830596959656, 0], [226738190870001, 0], [211688330147491, 0]], "33": [[211954468826947, 0], [182911403773907, 0], [79232938933519, 0], [201333303361944, 0], [224762265352048, 0], [118767755410824, 0], [98233353567251, 0], [260610066626239, 0], [45749833488990, 0]], "32": [[155511395690390, 0], [129612507478645, 0], [120497549390412, 0], [89948100716068, 0], [120233560568598, 0], [118979253871048, 0], [105688359959944, 0], [136504094246946, 0], [7445065778376, 0]], "31": [[254313407866402, 0], [142398592799278, 0], [167382405426829, 0], [95638039196721, 0], [46426410610718, 0], [222272185368232, 0], [104539278012718, 0], [233856594618248, 0], [37515542350995, 0]], "30": [[214498796165125, 0], [135014260030875, 0], [267927480578528, 0], [249888790185196, 0], [252127835426606, 0], [145600507226292, 0], [121255410833751, 0], [166064415878317, 0], [74547245961060, 0]], "37": [[217516840386553, 0], [11353021136711, 0], [127681711036372, 0], [249680638479383, 0], [123310334174173, 0], [128356332396844, 0], [176936729124722, 0], [79859783409178, 0], [70315024353749, 0]], "36": [[98089523102518, 0], [113727215387181, 0], [27539859248337, 0], [2046992376176, 0], [66497167879300, 0], [80528953347164, 0], [142717605732994, 0], [256957860324465, 0], [250659066119564, 0]], "35": [[265764295113486, 0], [44030110034358, 0], [138025576008548, 0], [154369643791994, 0], [280328054051924, 0], [56005737979608, 0], [187980742800691, 0], [96508887166220, 0], [159214657608400, 0]], "34": [[21903353802490, 0], [60307299857563, 0], [28032473882976, 0], [161594867557191, 0], [138572389464048, 0], [131839963396389, 0], [128140590069756, 0], [185546859308974, 0], [171387199394193, 0]], "641": [[244522099794306, 0], [46187289198654, 0], [216999273750554, 0], [199565057900294, 0], [133519247758865, 0], [147975237679356, 0], [4795563953854, 0], [150525681996747, 0], [252569943476961, 0]], "640": [[89304594057412, 0], [148479336314266, 0], [1239278882791, 0], [182548387413999, 0], [185716982535704, 0], [79609333737240, 0], [211762444305398, 0], [68101609124653, 0], [225073875433344, 0]], "643": [[26890190945772, 0], [88395427217287, 0], [165940032057406, 0], [257797797087907, 0], [223193291137818, 0], [245354627982954, 0], [259193111981805, 0], [122161722545662, 0], [93482360209079, 0]], "642": [[67330607618808, 0], [113905918948501, 0], [45553506244991, 0], [144949673799615, 0], [210874008281757, 0], [222584925950035, 0], [223483214443785, 0], [197091955293985, 0], [17436540833919, 0]], "645": [[79792072864749, 0], [146019694907641, 0], [157535983460600, 0], [218254989103661, 0], [40319767477139, 0], [211299932347356, 0], [121180896069650, 0], [205825223831783, 0], [229491172908119, 0]], "644": [[106815779307830, 0], [280432718062043, 0], [46403766980255, 0], [32122754682137, 0], [252988228413571, 0], [159548828425839, 0], [102798227835929, 0], [54170661079155, 0], [127917174872483, 0]], "438": [[111746103867536, 0], [19517268818673, 0], [274488047244130, 0], [246920937354155, 0], [205701311912815, 0], [108143335089053, 0], [102348693564130, 0], [245188898556896, 0], [101909124161815, 0]], "439": [[23061204740747, 0], [39132064615830, 0], [22020882982031, 0], [27787139648846, 0], [123035972660874, 0], [182016257199017, 0], [53254127190950, 0], [184647199981755, 0], [243668041538724, 0]], "436": [[24472608439764, 0], [63969095306922, 0], [251197188660181, 0], [154007517048611, 0], [180434541319595, 0], [10594549646941, 0], [12625611287585, 0], [79653552075124, 0], [267901705924348, 0]], "437": [[113323603713325, 0], [165244639187597, 0], [242840351187741, 0], [52384348018354, 0], [53999815099320, 0], [1678251302238, 0], [258812416246039, 0], [229349275677496, 0], [275684208895045, 0]], "434": [[99768050892397, 0], [8720848414669, 0], [58590268054206, 0], [270341528660946, 0], [156787712189199, 0], [67186614550788, 0], [111304473072369, 0], [175634790088787, 0], [57973415482291, 0]], "435": [[122112443474233, 0], [123495384869355, 0], [173889497730608, 0], [23687456402764, 0], [171149318611712, 0], [13713450108935, 0], [110984178573975, 0], [195403470917454, 0], [7877209912870, 0]], "432": [[64476064765086, 0], [158532938390779, 0], [94609258093045, 0], [276268751831797, 0], [78031613415722, 0], [103448296894664, 0], [276651611436415, 0], [144814419279921, 0], [70063578461577, 0]], "433": [[44357528314520, 0], [65858898035696, 0], [42335932632068, 0], [207409968770680, 0], [204249555747486, 0], [131198722479896, 0], [43064609992351, 0], [192916995422267, 0], [111551183664245, 0]], "430": [[220436168151967, 0], [203505593045188, 0], [212350232701288, 0], [45588596535589, 0], [36050213958276, 0], [147677991884238, 0], [213548154586258, 0], [109462542780311, 0], [45623627319114, 0]], "431": [[3463235905734, 0], [98158828597955, 0], [205810418874908, 0], [117470666338584, 0], [252084296591077, 0], [22973288317821, 0], [47669883915695, 0], [185818667841857, 0], [98339171599305, 0]], "1002": [[76792775490057, 0], [60779978930824, 0], [172231756067330, 0], [196742160129963, 0], [63136332000854, 0], [113663929962862, 0], [2049815503842, 0], [242587716648985, 0], [245913566450469, 0]], "339": [[183215799760853, 0], [94329841042981, 0], [259778220212299, 0], [248885472612472, 0], [234244646329881, 0], [24436919314541, 0], [96306051095416, 0], [74283082400303, 0], [189086960508463, 0]], "338": [[148260906797927, 0], [271168148039188, 0], [262221880275263, 0], [189101089502328, 0], [133360230044208, 0], [185836301585962, 0], [98019888324995, 0], [240166501998336, 0], [29272814067249, 0]], "335": [[228512612310442, 0], [36238803339318, 0], [61464822288827, 0], [41870955450280, 0], [252619435852414, 0], [256369409366044, 0], [100646870591473, 0], [110482181263001, 0], [277313980336962, 0]], "334": [[145493710060268, 0], [109180297507446, 0], [61384935331146, 0], [220434727698247, 0], [101114555260449, 0], [214162228937522, 0], [272272802170220, 0], [181544659889489, 0], [207067800390213, 0]], "337": [[255393169494993, 0], [272634020716280, 0], [88052025360896, 0], [19395002659726, 0], [133854917481449, 0], [125066324945604, 0], [25566520056657, 0], [46184609068609, 0], [233609337852440, 0]], "336": [[89693155075044, 0], [208620163961630, 0], [132435538394219, 0], [262390547180142, 0], [79979804012211, 0], [220267462246744, 0], [99127611734780, 0], [236626797210830, 0], [278011837589399, 0]], "331": [[185062023172930, 0], [237209482120580, 0], [161218498579695, 0], [157606278911419, 0], [7784749554441, 0], [108897782731181, 0], [258142483866145, 0], [32162298190564, 0], [240118982634981, 0]], "330": [[251570238689080, 0], [16507716064781, 0], [84564973382411, 0], [254163534664427, 0], [146048313971974, 0], [241379415130760, 0], [42198011168631, 0], [41351542287123, 0], [203393905953005, 0]], "333": [[20672077978685, 0], [209286782602048, 0], [159518224480156, 0], [25985222936060, 0], [186411286042611, 0], [120277382803365, 0], [30815292830840, 0], [187544633264241, 0], [254308783897578, 0]], "332": [[83644858421781, 0], [257037241262300, 0], [83229559558801, 0], [43460425612909, 0], [232907013046071, 0], [212015885614868, 0], [8871002284930, 0], [163100551551112, 0], [245648370573437, 0]], "744": [[105751497288407, 0], [152558236680110, 0], [120089980735983, 0], [139882058991979, 0], [174828341773104, 0], [159744223345181, 0], [30609809696243, 0], [82499971358659, 0], [32076739157679, 0]], "1000": [[184101526682750, 0], [37102797721850, 0], [188267801781476, 0], [180122243255026, 0], [227477964325229, 0], [187669900504711, 0], [273831163943633, 0], [49072085113529, 0], [190951829762232, 0]], "745": [[92272831587728, 0], [2205611511405, 0], [82129814721391, 0], [242409736954943, 0], [42210224933412, 0], [279410009259527, 0], [134659035452308, 0], [240897454537436, 0], [89188034828768, 0]], "854": [[16287513583212, 0], [68950887245089, 0], [8693937487099, 0], [165518335938451, 0], [28383375365168, 0], [198357692843796, 0], [41471176799503, 0], [224553600897016, 0], [278649469854826, 0]], "818": [[57528630005184, 0], [69194507364878, 0], [86377579994289, 0], [280536623962812, 0], [172089732658578, 0], [65756076904173, 0], [21273782806301, 0], [280071196613725, 0], [153636881036821, 0]], "856": [[124913017122859, 0], [136829284398297, 0], [241819191694587, 0], [264489219500914, 0], [239116663438574, 0], [99478647554405, 0], [248999523568996, 0], [86094378190070, 0], [268471311659605, 0]], "857": [[239612341601902, 0], [220717804072791, 0], [175944871016882, 0], [100866537049887, 0], [73838289930069, 0], [140860033055478, 0], [212675014442101, 0], [158264413781311, 0], [228011486487269, 0]], "850": [[69122199863980, 0], [266893285512939, 0], [167912987123094, 0], [63617345964572, 0], [56367397095871, 0], [99822104888009, 0], [136241007962640, 0], [31581704236819, 0], [112001641762689, 0]], "851": [[237793031650863, 0], [75141551115213, 0], [205460078160035, 0], [272566780420499, 0], [86334942835154, 0], [93855391127164, 0], [155645746384882, 0], [182208780114182, 0], [58647050246410, 0]], "852": [[138543042280893, 0], [225618876368253, 0], [103160956157352, 0], [101384845154499, 0], [137268494565435, 0], [110011346988301, 0], [109500925315150, 0], [237823154589861, 0], [16899661144777, 0]], "345": [[109279632002741, 0], [84730919137554, 0], [77538723074674, 0], [187072037255785, 0], [250178394367826, 0], [75255668590867, 0], [97671215689091, 0], [109775807344808, 0], [190887624976714, 0]], "858": [[22962346302718, 0], [225568477724224, 0], [46594294891745, 0], [145169559031979, 0], [92322619035432, 0], [96863960626926, 0], [167445191290334, 0], [199583635316626, 0], [144104633587725, 0]], "859": [[45729249763659, 0], [154079797811336, 0], [87545200335536, 0], [196984627958567, 0], [253213102389724, 0], [58078183865348, 0], [184295727913967, 0], [233943833006826, 0], [248254906587329, 0]], "748": [[192559630258460, 0], [130680560917612, 0], [39660055339284, 0], [189855495746765, 0], [66839059261532, 0], [197933190062071, 0], [213616479030634, 0], [98162249776881, 0], [171848180278015, 0]], "6": [[217181460017872, 0], [155537495304912, 0], [215561181391501, 0], [67087673445961, 0], [23057692187969, 0], [214157318439044, 0], [279821268700182, 0], [50235689963536, 0], [237356871086897, 0]], "900": [[33874524784785, 0], [81020072520672, 0], [222581878745381, 0], [104295880139234, 0], [73514951222954, 0], [278296747468700, 0], [24049368647880, 0], [272788536655661, 0], [33535342359046, 0]], "848": [[216538049864873, 0], [252987489432616, 0], [166826927639241, 0], [277646089556744, 0], [143622313968416, 0], [224896606707427, 0], [82454665447653, 0], [169365805941302, 0], [27984066151731, 0]], "99": [[158892258198639, 0], [127765665991998, 0], [21024079276777, 0], [205411130920543, 0], [268756135911488, 0], [116517849946266, 0], [106439566396639, 0], [98523259144103, 0], [160246572095396, 0]], "98": [[168069415513113, 0], [210877984945525, 0], [12803655026258, 0], [170089064926540, 0], [23841510112346, 0], [45750745052453, 0], [53922318404072, 0], [202126981014415, 0], [66966440122066, 0]], "844": [[21315102254321, 0], [68528594638464, 0], [131087041133274, 0], [114535088887949, 0], [281408038352333, 0], [144021307831751, 0], [221330478744611, 0], [69988592453632, 0], [127315418852433, 0]], "91": [[189854389502977, 0], [250956790062524, 0], [73547609915497, 0], [124218849277105, 0], [79963132727081, 0], [71172196478670, 0], [226819580271565, 0], [260697103301861, 0], [40116100202024, 0]], "90": [[117419370399453, 0], [113912460905461, 0], [216473032836387, 0], [40414454312023, 0], [13841691061657, 0], [235912440860709, 0], [6874871928328, 0], [71818261822970, 0], [223171338613599, 0]], "93": [[263310140882394, 0], [263919244768507, 0], [65891160714080, 0], [175763111766715, 0], [247415947242958, 0], [125065865214517, 0], [185328867678174, 0], [255121181257604, 0], [185775406740488, 0]], "92": [[273172371818332, 0], [171202523086553, 0], [63531001603227, 0], [79195892434116, 0], [17811468771656, 0], [233198359752509, 0], [182796956757008, 0], [198324448907152, 0], [258702488272917, 0]], "95": [[107278442150713, 0], [190880496665118, 0], [178648390995615, 0], [205114344303193, 0], [233030549082887, 0], [58765509158692, 0], [118575361459889, 0], [39450838915696, 0], [243910249084522, 0]], "94": [[206183928795171, 0], [11925207502382, 0], [98423077098163, 0], [13592119584796, 0], [189583016901655, 0], [36951984307608, 0], [145578756626902, 0], [154578614190894, 0], [200104105981493, 0]], "97": [[158538137148327, 0], [219891550920568, 0], [177089803825904, 0], [48101486186012, 0], [141269266959552, 0], [268371197802644, 0], [179197243226699, 0], [204821795062053, 0], [199130726383791, 0]], "96": [[37143748478244, 0], [204302226981904, 0], [139953943817446, 0], [232388063522930, 0], [232235007076353, 0], [154006424696595, 0], [229410135894991, 0], [245826459721758, 0], [162224772431780, 0]], "814": [[176972182533977, 0], [125187267306122, 0], [186188155403288, 0], [232439929250403, 0], [124438128009473, 0], [141572427361380, 0], [254124135546649, 0], [118465312950516, 0], [64856145340067, 0]], "815": [[117409878905456, 0], [63866362877752, 0], [129842276900424, 0], [51088745851338, 0], [122258575133070, 0], [28210486442379, 0], [95592163483734, 0], [158759815454734, 0], [275041808851669, 0]], "740": [[24463112081604, 0], [79886414344307, 0], [234541124653874, 0], [112395630004813, 0], [24920423686253, 0], [16630266187209, 0], [39938788880405, 0], [55814093024853, 0], [151435027301829, 0]], "741": [[196118820177659, 0], [271452524037597, 0], [94564849878920, 0], [45172617640030, 0], [237849994694650, 0], [278654584792808, 0], [129723065220227, 0], [65176677127796, 0], [51072496211679, 0]], "742": [[81616721837100, 0], [275611715397371, 0], [57295328128825, 0], [210561577102156, 0], [78470987524556, 0], [238763781212003, 0], [24420124379647, 0], [166876838293003, 0], [100594693806564, 0]], "743": [[127684193864731, 0], [97810926646390, 0], [168515435600642, 0], [153710069440718, 0], [279646578980242, 0], [152278710000310, 0], [191410382575987, 0], [25923240321368, 0], [267287126535751, 0]], "559": [[248197082982842, 0], [45534488392205, 0], [168752574538587, 0], [216045294194700, 0], [15677803400201, 0], [227443995715211, 0], [92437519447439, 0], [227670462206595, 0], [178177137314798, 0]], "558": [[33551604631243, 0], [24087031533575, 0], [62057168093785, 0], [118717926357483, 0], [83836550126213, 0], [82988697586741, 0], [225094618351691, 0], [185882193873448, 0], [165829446323824, 0]], "746": [[95191216701693, 0], [49264851862999, 0], [164119530189943, 0], [249819917891267, 0], [122992827765001, 0], [272479797007796, 0], [276977045278618, 0], [173582097076075, 0], [190051806180432, 0]], "747": [[274676127996991, 0], [229054535233985, 0], [29424685815175, 0], [52467380930487, 0], [262446571146295, 0], [23612272783151, 0], [267074421381789, 0], [219927353294870, 0], [23653790849313, 0]], "555": [[44505260560989, 0], [181883609749920, 0], [255160077844576, 0], [200757107409122, 0], [60699599603829, 0], [74612458635743, 0], [121168173857500, 0], [92589702354033, 0], [190174221437371, 0]], "554": [[132452852141907, 0], [60870915623635, 0], [226734512268852, 0], [183479764146174, 0], [261599931081280, 0], [124378866004096, 0], [87640729904627, 0], [226153538565379, 0], [3442312199914, 0]], "557": [[36534569524107, 0], [161636249922494, 0], [29852371054209, 0], [248958950822923, 0], [117961471692219, 0], [149063583373888, 0], [7269650898794, 0], [254288117566046, 0], [232285970516571, 0]], "556": [[249260249561518, 0], [171476614188186, 0], [233762747518634, 0], [99081133629516, 0], [33616250353473, 0], [99240722674709, 0], [31387983454957, 0], [102456787906587, 0], [211096615513407, 0]], "551": [[122393474760862, 0], [74132661053458, 0], [149749826002902, 0], [188886323302660, 0], [9628348547694, 0], [15564028937160, 0], [33050018487530, 0], [165533650675849, 0], [76793964055610, 0]], "550": [[27214794669609, 0], [56031133554685, 0], [260497580730254, 0], [208695819292795, 0], [166455394488565, 0], [263043483293570, 0], [182584659957143, 0], [16669261421114, 0], [178981118146993, 0]], "553": [[71828892392789, 0], [211084669455419, 0], [126282831235728, 0], [107352371726847, 0], [258858423462083, 0], [189391035986984, 0], [268664634817604, 0], [198267772026723, 0], [55733276070199, 0]], "552": [[219196432817501, 0], [228726821483325, 0], [266137816980173, 0], [245154442293488, 0], [272722081223071, 0], [157780383295607, 0], [242065078134734, 0], [272970231959445, 0], [141146694130388, 0]], "238": [[132542908199210, 0], [70552161550240, 0], [7801757383150, 0], [156438684918987, 0], [10488492363403, 0], [140525075582366, 0], [225295624117086, 0], [93537626086623, 0], [66994396128848, 0]], "239": [[108056152613983, 0], [257891137155547, 0], [114172431337716, 0], [220982945106866, 0], [249845733912528, 0], [255091167415605, 0], [71528044201910, 0], [132783089877104, 0], [245715113591025, 0]], "234": [[258770349571706, 0], [265066900416129, 0], [241430015565509, 0], [239247046310413, 0], [167475279990284, 0], [134581206050486, 0], [130543809526836, 0], [181577816299723, 0], [123046639444725, 0]], "235": [[142726857952765, 0], [20693879462924, 0], [118860348350128, 0], [80237790427120, 0], [38017861533717, 0], [75913208096767, 0], [112739824002750, 0], [141262184182187, 0], [11272318298815, 0]], "236": [[33769676746090, 0], [54177828132507, 0], [96463810782465, 0], [267204975620856, 0], [171833635017148, 0], [46645912738865, 0], [123318373747290, 0], [43502286118011, 0], [233944881766164, 0]], "237": [[268462981268233, 0], [205126842687380, 0], [148748095862185, 0], [139698525980449, 0], [170577121031858, 0], [81108563170184, 0], [215082532785292, 0], [267230958631363, 0], [158109233655398, 0]], "230": [[249744022632009, 0], [250545043356846, 0], [213154790736287, 0], [108302715682551, 0], [43146730623105, 0], [82322198777381, 0], [54853282993203, 0], [87104784532493, 0], [240983971223404, 0]], "231": [[131325531159908, 0], [166416865088593, 0], [50296237541438, 0], [17674550014825, 0], [60892688670652, 0], [149767492345687, 0], [140621839670190, 0], [149294638563999, 0], [75834842301300, 0]], "232": [[187485580187504, 0], [170825912418847, 0], [66803652646086, 0], [220475800360236, 0], [197309263537719, 0], [101597675896761, 0], [51701388882179, 0], [273370732966350, 0], [57360483216568, 0]], "233": [[183095217814006, 0], [125061489434969, 0], [77306454616462, 0], [248733690387069, 0], [42420234343662, 0], [64443656767949, 0], [233178505666682, 0], [137303747618520, 0], [53241698002483, 0]], "992": [[139167526781827, 0], [93434362424940, 0], [58235724898852, 0], [161473110703953, 0], [64331393319723, 0], [152149364369774, 0], [158769206386002, 0], [110592813303217, 0], [37686996943425, 0]], "1": [[30945523163402, 0], [225951675349017, 0], [84841452541259, 0], [61301521610922, 0], [176705936882887, 0], [204010279831261, 0], [125248231958331, 0], [237152014636609, 0], [171775842047004, 0]], "614": [[88300578536380, 0], [128141047375196, 0], [112801443440390, 0], [140760544340364, 0], [18035499055980, 0], [87811935835496, 0], [201333464657223, 0], [34057655213076, 0], [13050393421321, 0]], "146": [[116325206239563, 0], [218835998011646, 0], [145812998322845, 0], [227278176599527, 0], [25533781081659, 0], [38486211804484, 0], [80261379484938, 0], [47486636782101, 0], [59315663051345, 0]], "147": [[35048849704849, 2], [82788966414002, 2], [129669193375452, 2], [117424535569224, 2], [10571209483123, 2], [250899401585343, 2], [23133461887481, 2], [268325484984424, 2], [40662615209551, 0]], "144": [[21382068170675, 0], [106184101432660, 0], [176318067943858, 0], [139847691322631, 0], [223279243372702, 0], [81079464509791, 0], [226246782042538, 0], [254892890891406, 0], [11873882348442, 0]], "145": [[93147954637281, 0], [54805067788552, 0], [168444587295965, 0], [229133388869552, 0], [135232966780844, 0], [281229439634526, 0], [45031119903705, 0], [230245566355345, 0], [246274090800135, 0]], "142": [[28645006429765, 0], [271225474546802, 0], [114207779597213, 0], [183799711326505, 0], [73525931645609, 0], [62067123546952, 0], [202054076906438, 0], [223465545874289, 0], [9383851197261, 0]], "143": [[46384277986603, 0], [85190151087781, 0], [175195795465537, 0], [260849627164040, 0], [126107497998615, 0], [93569099895609, 0], [68285416361610, 0], [3145001933768, 0], [147424744669537, 0]], "140": [[253271093809959, 0], [35622664200024, 0], [31613952057646, 0], [131596379848386, 0], [102125545509354, 0], [14773310924617, 0], [97045766405017, 0], [121904168574081, 0], [203568863528646, 0]], "141": [[96384623421625, 0], [142756889849741, 0], [14356817636430, 0], [99658695860403, 0], [128477400455515, 0], [261326969958350, 0], [267270067483214, 0], [13018405621471, 0], [159468882573458, 0]], "612": [[159035904555819, 0], [230156541484721, 0], [280151572420240, 0], [124184009953938, 0], [58093098655735, 0], [8865402857884, 0], [277003328951503, 0], [115460011011917, 0], [543668358174, 0]], "613": [[157479714729953, 0], [221194722179677, 0], [250794322596826, 0], [63415933573088, 0], [195280544517498, 0], [125925370536425, 0], [226263365249960, 0], [212824771144325, 0], [37198355513949, 0]], "610": [[6237775299921, 0], [117737102801579, 0], [204658342257530, 0], [219423206440613, 0], [145775668332844, 0], [158547905039476, 0], [13504157000367, 0], [252401624130763, 0], [95580518309873, 0]], "611": [[155233522570180, 0], [278889700937964, 0], [92743736409937, 0], [253132544123845, 0], [265631868240252, 0], [141487122989345, 0], [223763489015199, 0], [62458118887637, 0], [3373355254664, 0]], "616": [[138471489876683, 0], [216082680190342, 0], [196221050751973, 0], [2245063347864, 0], [113541264232619, 0], [236753120672812, 0], [277742258686519, 0], [175307110850677, 0], [202922248378979, 0]], "617": [[184031378947112, 0], [266733566526004, 0], [1308798861843, 0], [176058547830794, 0], [187655805547835, 0], [3359953833822, 0], [279405406001544, 0], [186908043800090, 0], [180851217940770, 0]], "148": [[218783456793920, 0], [115973039290361, 0], [55436209189430, 0], [195650255006568, 0], [145721204586484, 0], [83042361751049, 0], [150670737886916, 0], [75226205812855, 0], [122396943827715, 0]], "149": [[157602833436571, 0], [140657714501348, 0], [227026038502363, 0], [62196690551807, 0], [89512670975058, 0], [177390624130558, 0], [184033127083370, 0], [12500789773454, 0], [270431551935507, 0]], "1007": [[129412114554961, 0], [97139974997781, 0], [63500778680287, 0], [180186599099292, 0], [622326859753, 0], [166305930249969, 0], [270318072423267, 0], [187942927796984, 0], [270504754665013, 0]], "912": [[55431517486909, 0], [12166657444384, 0], [171524988163548, 0], [106655247411281, 0], [524988924617, 0], [272559605779763, 0], [273022368171934, 0], [164916851782450, 0], [250082312285252, 0]], "1006": [[53063312894763, 0], [206401343407630, 0], [236615647037906, 0], [241702033678995, 0], [151926779282744, 0], [161448033149295, 0], [95102084097506, 0], [186297729463108, 0], [169506039239632, 0]], "951": [[152811805993316, 0], [93239403185449, 0], [116070352522765, 0], [139759908171830, 0], [155751254173348, 0], [45444048580088, 0], [254744874872432, 0], [29656181817666, 0], [21497356834738, 0]], "1005": [[116624006514426, 0], [266295063721769, 0], [13058510171656, 0], [77569235229291, 0], [257248869912041, 0], [145733877261839, 0], [230384866364338, 0], [213001913719937, 0], [43258045906145, 0]], "1004": [[154764141195941, 0], [276465255687294, 0], [243467585876935, 0], [52302143156103, 0], [263610032110312, 0], [147619621991573, 0], [239987242744190, 0], [20143978995653, 0], [75976370752461, 0]], "948": [[114549256313040, 0], [228212644686419, 0], [250604454208382, 0], [95634192284288, 0], [160642075438941, 0], [88065399176919, 0], [154638882665653, 0], [74703436498063, 0], [130459584779073, 0]], "949": [[40952825305150, 0], [185564280168513, 0], [8344492110789, 0], [140117482871151, 0], [194448980744925, 0], [183721632848221, 0], [65921588052864, 0], [213394331754534, 0], [217624221160162, 0]], "946": [[230485159460624, 0], [133645222527140, 0], [245595069463746, 0], [131999116387509, 0], [35904901727791, 0], [192134609870933, 0], [32220800270560, 0], [152820435463136, 0], [168239561940284, 0]], "947": [[95724452144295, 0], [111825526301160, 0], [248779232253083, 0], [127539928202151, 0], [191063914415222, 0], [6839745462366, 0], [33511774187858, 0], [85122611654833, 0], [8998352734134, 0]], "944": [[203782298023124, 0], [1722899517673, 0], [221149441616519, 0], [199605024189784, 0], [165094346534610, 0], [253400175052522, 0], [145360143803650, 0], [226372926204999, 0], [212007818618037, 0]], "945": [[45119891206201, 0], [207385430923797, 0], [264258109814616, 0], [221985603301774, 0], [230027227020542, 0], [101604890697364, 0], [93245849308434, 0], [177594820216395, 0], [89749095873081, 0]], "942": [[208643130213114, 0], [116968473458646, 0], [95050675421253, 0], [211752478419423, 0], [88124602378093, 0], [196468091675487, 0], [221254762451992, 0], [196122325468290, 0], [217075522209600, 0]], "943": [[44622556443107, 0], [2758363340988, 0], [93005540013175, 0], [23220117476400, 0], [37682605144421, 0], [114138260029494, 0], [260863751152511, 0], [131853327294491, 0], [220124411720164, 0]], "940": [[23077131313926, 0], [207847960829722, 0], [33580777502223, 0], [133875078473656, 0], [180724920413506, 0], [193882507692690, 0], [115319955817197, 0], [279873627419293, 0], [49091862867804, 0]], "941": [[211986603004751, 0], [218068274904104, 0], [171827382521836, 0], [156707379105033, 0], [230913447304538, 0], [147239524840170, 0], [232504658469163, 0], [154283109712890, 0], [136069685085225, 0]], "768": [[91745932181705, 0], [13430904370973, 0], [273783574929909, 0], [115847825342272, 0], [84216727584025, 0], [215575473021076, 0], [103288699260549, 0], [175537342797989, 0], [5171483842676, 0]], "689": [[96762179432779, 0], [39480476376669, 0], [265294838301434, 0], [183340794047516, 0], [147548174663918, 0], [59233419623961, 0], [109121846309502, 0], [311947365481, 0], [208484726823407, 0]], "688": [[137654454403466, 0], [117653718399480, 0], [153466656316817, 0], [5445433790749, 0], [225556280020491, 0], [73090816748958, 0], [127224371888148, 0], [141211126194161, 0], [247179467153729, 0]], "685": [[272327460337949, 0], [92923249604465, 0], [44893529356917, 0], [173675566187800, 0], [272670420750754, 0], [77386565621438, 0], [140938470736486, 0], [180910692638062, 0], [123284062296065, 0]], "684": [[135728982679242, 0], [37326155998807, 0], [245303827481623, 0], [101423589656324, 0], [251768103535487, 0], [260284700927923, 0], [49894444886921, 0], [54654723542962, 0], [148889277554274, 0]], "687": [[246724161557601, 0], [250862587833872, 0], [214981473122245, 0], [144246055136961, 0], [119230953627712, 0], [224166876618784, 0], [11990370515796, 0], [8347294406309, 0], [199288990790023, 0]], "686": [[11964049761489, 0], [50586153213829, 0], [134151627174442, 0], [14996459832190, 0], [7505931271103, 0], [238232324207798, 0], [279608078626907, 0], [148492485324680, 0], [273188023840480, 0]], "681": [[87058100865099, 0], [124874958365021, 0], [165690706784693, 0], [232297226370386, 0], [43768028321112, 0], [45258405946477, 0], [53004327943236, 0], [130528256562957, 0], [213538985713000, 0]], "680": [[219308146631953, 0], [280713762034363, 0], [9521377237351, 0], [275165135835615, 0], [271982213750794, 0], [196741097843670, 0], [7441290263854, 0], [203701844397420, 0], [140542933940850, 0]], "683": [[98748852953644, 0], [249701143805519, 0], [183114057049927, 0], [40023770307097, 0], [11230680572446, 0], [72647982691253, 0], [215684006515076, 0], [206900200883744, 0], [169280921304538, 0]], "682": [[44473090284264, 0], [265926820496744, 0], [41376970444456, 0], [244575837994891, 0], [66383974196667, 0], [203661203769053, 0], [98521692713704, 0], [174834810780202, 0], [251098606343193, 0]], "623": [[139196227718774, 0], [34736500912823, 0], [207626070545758, 0], [126810956327459, 0], [189269755636292, 0], [262552259398704, 0], [272412506495032, 0], [21074552278882, 0], [108949688194175, 0]], "819": [[158784449644245, 0], [218845119048347, 0], [242824426041288, 0], [230134181043095, 0], [96684454492977, 0], [19227661968407, 0], [190196489321719, 0], [166762562382935, 0], [196101634253668, 0]], "622": [[64802821678484, 0], [166659518245420, 0], [95685413347985, 0], [83108938718848, 0], [199529202391180, 0], [56311320943736, 0], [209342399077082, 0], [90554043181444, 0], [90603182229913, 0]], "133": [[216454323045028, 0], [268841287868122, 0], [155129151925833, 0], [184399367128299, 0], [176677103691842, 0], [164289331789703, 0], [176886600553991, 0], [31590709529408, 0], [30595366957517, 0]], "132": [[60951182654, 0], [94347081443111, 0], [73702989139953, 0], [205722743033580, 0], [33816520307724, 0], [213862331982899, 0], [82834567162129, 0], [185449371819776, 0], [272421018511859, 0]], "131": [[174847261135164, 0], [185644084194825, 0], [64331385668877, 0], [12193151109532, 0], [281401084449734, 0], [29796651290205, 0], [47653333869051, 0], [115260509706685, 0], [2807357155298, 0]], "130": [[109534323280295, 0], [103549414560533, 0], [127881928282369, 0], [2869599263179, 0], [211052813096457, 0], [19957538243861, 0], [67767654855202, 0], [118378729499445, 0], [116791362094186, 0]], "137": [[195967320142920, 0], [9725337055333, 0], [122079697128811, 0], [162384790207019, 0], [102801157826053, 0], [58416197099626, 0], [164212946639448, 0], [278961579636612, 0], [129405143967447, 0]], "136": [[135160516919926, 0], [216275482053504, 0], [6787710574360, 0], [111534029407488, 0], [22562513982847, 0], [225255459652254, 0], [116356107740111, 0], [203162163663896, 0], [217084701035993, 0]], "135": [[56282743942322, 428], [233310313257230, 428], [111166687862459, 428], [95602944204220, 428], [217815550983848, 428], [31212796671185, 428], [253731731102452, 267], [163382236205917, 171], [226001838801617, 0]], "134": [[5801120890726, 0], [196785555632810, 0], [32840282310990, 0], [222899586774579, 0], [170688371925413, 0], [151099907437319, 0], [65671796270973, 0], [253889200324722, 0], [18829474546103, 0]], "494": [[261395513873158, 0], [54850154909331, 0], [60013778728194, 0], [274715610975769, 0], [100604476520585, 0], [196331740999599, 0], [272390278147534, 0], [221401434186442, 0], [1645957778796, 0]], "495": [[126920147954837, 0], [235609780697359, 0], [15081646896848, 0], [245437962278282, 0], [83827981688547, 0], [86303821397729, 0], [166998053483183, 0], [157580207342364, 0], [182598529552215, 0]], "139": [[145972888532372, 0], [159331745422232, 0], [124207537450409, 0], [16757080988095, 0], [53627102005403, 0], [225110797190459, 0], [216475206717751, 0], [211888020469259, 0], [266274621842448, 0]], "138": [[265283650594724, 0], [83932342928140, 0], [261768399676118, 0], [145148693105003, 0], [191172175390232, 0], [2403040497719, 0], [107989407715867, 0], [196562046563004, 0], [203266941010358, 0]], "490": [[270579883126100, 0], [144265118055569, 0], [234868073418241, 0], [102688506056097, 0], [209265954546699, 0], [266312721785980, 0], [211008514645531, 0], [56131451048057, 0], [253998553427694, 0]], "491": [[215157242701324, 0], [76192722314737, 0], [40331635076661, 0], [31158511887489, 0], [195314060697187, 0], [244778030046298, 0], [14362572269482, 0], [122714208691868, 0], [165378045733680, 0]], "492": [[186647446271937, 0], [231625432010383, 0], [109783811342310, 0], [81780989706886, 0], [272986071907854, 0], [265561904495062, 0], [168926253609579, 0], [51116086303178, 0], [95311934538628, 0]], "493": [[30440317657306, 0], [135963286361300, 0], [21125754414370, 0], [49645077982557, 0], [84312730771270, 0], [248491936733862, 0], [119206042672846, 0], [193049251813389, 0], [117579502594928, 0]], "24": [[275411265699266, 0], [175129134170347, 0], [170680517976346, 0], [250782574267214, 0], [42402423032230, 0], [182390943772223, 0], [197662315287735, 0], [14427753801954, 0], [120806817538177, 0]], "25": [[208455667530705, 0], [273733728979025, 0], [113025424012439, 0], [101337955667127, 0], [113917338797889, 0], [37618408225729, 0], [93825046977826, 0], [222315816833538, 0], [66931116932208, 0]], "26": [[47472429127103, 0], [225928546070799, 0], [254602612536205, 0], [24922252334102, 0], [203172001053699, 0], [197883281222883, 0], [248134836470837, 0], [252864493095316, 0], [144657146428573, 0]], "27": [[119390827439084, 0], [155260604360359, 0], [227633409439969, 0], [222960328483456, 0], [57553226273921, 0], [263580195247623, 0], [143137952031312, 0], [189792073277210, 0], [253710473600392, 0]], "20": [[61374282933807, 68], [148192287627732, 68], [199268824836859, 68], [276418949421203, 53], [164420927147822, 53], [68797317845689, 38], [38067601713274, 37], [224626736149242, 37], [243056997668066, 0]], "21": [[115219709159485, 0], [13078116330619, 0], [34218514705028, 0], [121690418079684, 0], [228290889750617, 0], [236391792475363, 0], [49668654652694, 0], [267058827417335, 0], [72253770498957, 0]], "22": [[325800626638, 0], [82336856829122, 0], [151639143438177, 0], [11735012337958, 0], [219888874828218, 0], [237739029384624, 0], [128632324619974, 0], [252750356734881, 0], [195342180076714, 0]], "23": [[22175146703415, 0], [27239081435647, 0], [234708497525848, 0], [62505408776339, 0], [240280927858564, 0], [272389104145490, 0], [147366662756300, 0], [145970184100712, 0], [66747994973631, 0]], "927": [[18958705465025, 0], [201706542119608, 0], [42801229653689, 0], [202549174066113, 0], [98709771790002, 0], [15959522280142, 0], [193417167446630, 0], [174520843545899, 0], [15535686761768, 0]], "28": [[273972413269537, 0], [215493185503419, 0], [81837770994611, 0], [63055633756260, 0], [212047073302253, 0], [245800334175439, 0], [213365863586457, 0], [243919659187330, 0], [157309656003726, 0]], "29": [[181009889413700, 0], [68925688468610, 0], [61246260220806, 0], [130926011119724, 0], [192536632040077, 0], [228756930069999, 0], [81078229810845, 0], [100624519689897, 0], [82441499830684, 0]], "407": [[264066957037399, 0], [260370705922655, 0], [67371905574358, 0], [37808893459326, 0], [243136518188821, 0], [25621491330836, 0], [1053706450694, 0], [105053026075700, 0], [3290584956070, 0]], "406": [[185559789283274, 0], [129673504825753, 0], [3857845509116, 0], [114160075166696, 0], [242696561166017, 0], [243728973522476, 0], [116839012204075, 0], [168867145728023, 0], [273884462034199, 0]], "405": [[120087080944533, 0], [62050654734200, 0], [250561497771395, 0], [276556256473591, 0], [150586163033926, 0], [9885335220059, 0], [16617718279788, 0], [175234638314919, 0], [183667519470264, 0]], "404": [[229019430992072, 0], [53887170534995, 0], [26974845447823, 0], [250101590108724, 0], [249813129937773, 0], [191222353355273, 0], [255988843764123, 0], [82701984559106, 0], [163184443585615, 0]], "403": [[214442456138232, 0], [205361471970061, 0], [41519528546221, 0], [48797440455712, 0], [83944100506570, 0], [207768743753176, 0], [149405058445739, 0], [218408943840953, 0], [212497681961254, 0]], "402": [[8248783709869, 0], [96073805966432, 0], [203396225370975, 0], [4698361524771, 0], [252010682351855, 0], [104849594199908, 0], [242372130787031, 0], [155173888800510, 0], [267478928793108, 0]], "401": [[205244139908024, 0], [214110644214616, 0], [145532358763871, 0], [246524542030800, 0], [242577262385396, 0], [39478263141581, 0], [15572329501232, 0], [24594125825065, 0], [78554067274506, 0]], "400": [[256031929005136, 0], [51220180775419, 0], [260238076811457, 0], [188613321270193, 0], [66762190062644, 0], [133794116600940, 0], [121459480910616, 0], [71275764705813, 0], [249753218728051, 0]], "933": [[168602545246111, 0], [250868644264876, 0], [19439246934309, 0], [276487059914491, 0], [67748001394046, 0], [273478948686483, 0], [183892243436619, 0], [66796618025484, 0], [230591218071625, 0]], "932": [[246410338314239, 0], [8728294912980, 0], [194603286428807, 0], [82018906790440, 0], [134449628411255, 0], [50165654877163, 0], [119924554483913, 0], [82566602836188, 0], [205302138302673, 0]], "931": [[621244109183, 0], [272344796965649, 0], [278980272667712, 0], [172716916404594, 0], [20307462031611, 0], [117344724084681, 0], [119878291603998, 0], [4658659688897, 0], [274328969079614, 0]], "930": [[50744858175878, 0], [96704333639647, 0], [36164321904488, 0], [13877672988740, 0], [82860798768294, 0], [48763591295130, 0], [58805311647416, 0], [177986667759913, 0], [102200825438970, 0]], "937": [[69990902927508, 0], [186287350962212, 0], [181515816335361, 0], [141768012575972, 0], [74029373975282, 0], [226923898602464, 0], [86960397636033, 0], [258301922855181, 0], [66804618416739, 0]], "629": [[265250939611247, 0], [28636677817175, 0], [274159639158026, 0], [128064079615891, 0], [29125809063202, 0], [142127492212421, 0], [71850839969958, 0], [147633827223204, 0], [234643972437385, 0]], "409": [[183502456040128, 0], [112520540802892, 0], [169675443650452, 0], [91748815579052, 0], [188794605123524, 0], [255579123746775, 0], [211760060947943, 0], [105103888288557, 0], [62753896473297, 0]], "408": [[155370519714902, 0], [106691649553064, 0], [84200447806007, 0], [99672118482089, 0], [64244405862846, 0], [234461989822707, 0], [124994981991799, 0], [255315548023895, 0], [124476783090745, 0]], "628": [[271157128519765, 0], [38527707997367, 0], [33832076730084, 0], [16901976517288, 0], [110051091540345, 0], [25792503589635, 0], [262552558011486, 0], [145174457359458, 0], [107423857905202, 0]], "758": [[112014631470217, 0], [168460392049782, 0], [212323928607421, 0], [125334046817243, 0], [167573867799372, 0], [154550899830511, 0], [133504481786485, 0], [274718070323481, 0], [184342343595898, 0]], "1018": [[258062533541841, 0], [264614214138390, 0], [253437429903887, 0], [248694737513415, 0], [589889171221, 0], [126300323273909, 0], [143700490361558, 0], [227838906919029, 0], [13438421811791, 0]], "379": [[55261607398047, 0], [126376180136742, 0], [241826199669419, 0], [274350433031958, 0], [273915338612960, 0], [157573927652272, 0], [51361443906029, 0], [72689847666297, 0], [151595942273981, 0]], "378": [[68640948259757, 0], [243732812828229, 0], [107322683958612, 0], [12144040758171, 0], [166217172918578, 0], [19640696415365, 0], [95283288006267, 0], [51621845960332, 0], [143202290568197, 0]], "829": [[34421349118334, 0], [166274599383573, 0], [127936475115153, 0], [14644823014416, 0], [25886244185873, 0], [2766961969626, 0], [95259733473123, 0], [46523328879, 0], [161248389074420, 0]], "828": [[133449456355700, 0], [135135955828481, 0], [190235879689784, 0], [229095470360063, 0], [82010799264313, 0], [102034613102509, 0], [213656032014969, 0], [82272754538900, 0], [77839647461206, 0]], "371": [[243221009101221, 0], [151700220055727, 0], [52283166624921, 0], [63456348001028, 0], [117870323222117, 0], [237798434664396, 0], [208725475311103, 0], [22848080491640, 0], [102921900225266, 0]], "370": [[125739232106231, 0], [158008902335726, 0], [177016221821275, 0], [47208229735168, 0], [191262099720992, 0], [152564528122102, 0], [279064047246682, 0], [111787190714867, 0], [88684986489266, 0]], "373": [[181902149691058, 0], [270636544639002, 0], [110791639576414, 0], [263000118263089, 0], [80497732712760, 0], [130627914734129, 0], [279606364387689, 0], [148925838096085, 0], [258314207590804, 0]], "372": [[237666739976680, 0], [89151145648530, 0], [60892181460411, 0], [174856575514518, 0], [165191601482757, 0], [143468034777362, 0], [260057270959939, 0], [94869361601590, 0], [246365089712585, 0]], "375": [[136856002469041, 0], [12922546138333, 0], [66057521629233, 0], [50285367296982, 0], [263813045241884, 0], [18483984033807, 0], [206550292303831, 0], [175487417308229, 0], [179077277755296, 0]], "374": [[143134522369720, 0], [142622456720317, 0], [99172655877027, 0], [149562398791225, 0], [252764851012563, 0], [214533343182441, 0], [120716443411413, 0], [185920561165704, 0], [73979772023818, 0]], "377": [[199609465206264, 0], [239089299377431, 0], [261918086812054, 0], [166502881431551, 0], [277602038378075, 0], [231977803534710, 0], [209671010194077, 0], [43935897688478, 0], [78494993035198, 0]], "376": [[180817274679894, 0], [80690889065899, 0], [1641569419278, 0], [154599374226028, 0], [185840527535049, 0], [226036915027920, 0], [245847546357375, 0], [266855759352654, 0], [272836275702515, 0]], "1019": [[124927567000147, 0], [127580495161493, 0], [30956062903335, 0], [75491535047809, 0], [222083154669173, 0], [31395210156227, 0], [104199177296844, 0], [28418319614862, 0], [187072135943019, 0]], "708": [[279321584713498, 0], [140374126296552, 0], [118232202356865, 0], [49135082066142, 0], [277157004157984, 0], [111933411287196, 0], [22819917593791, 0], [204981625781319, 0], [81350394760516, 0]], "709": [[89148113253175, 0], [113970376721887, 0], [197540339907060, 0], [85770373318692, 0], [38507941557259, 0], [18150187380927, 0], [187897443024035, 0], [227700652458385, 0], [178823733027735, 0]], "704": [[174898096902719, 0], [159321779276251, 0], [191732198991001, 0], [110338466643111, 0], [194660157673312, 0], [106070904931631, 0], [41296972188445, 0], [149030617118258, 0], [233459490734329, 0]], "705": [[220774276627731, 0], [128543663231361, 0], [108993517947218, 0], [145047702738367, 0], [9852059286263, 0], [64924867961299, 0], [220574789496895, 0], [92861310670582, 0], [198833297311345, 0]], "706": [[54592971378786, 0], [164623272203367, 0], [171789499363377, 0], [169101723524933, 0], [124659500075186, 0], [254629512125545, 0], [230405875776767, 0], [275876220591192, 0], [29910902259220, 0]], "707": [[38282701909329, 0], [110078842199375, 0], [47820430447402, 0], [246183237236798, 0], [142418825270302, 0], [134371426138103, 0], [141608983678155, 0], [256046092865648, 0], [28694818374203, 0]], "700": [[276581177971901, 0], [7754098128320, 0], [171412406275585, 0], [108952068286806, 0], [111220109716148, 0], [116236921745735, 0], [4033442000976, 0], [263507448396541, 0], [162963199921770, 0]], "618": [[26674059991209, 0], [159466302271554, 0], [226819835176799, 0], [155867645794655, 0], [247581720407466, 0], [11227052079759, 0], [217519997939886, 0], [182080192375009, 0], [150887436457059, 0]], "702": [[120864307471824, 0], [142130462884267, 0], [25936975622514, 0], [22504681649096, 0], [174048162013134, 0], [267419302789015, 0], [56476443223079, 0], [157742542842218, 0], [57268737609595, 0]], "703": [[172669065979446, 0], [66828622936494, 0], [204711701671113, 0], [195391208101389, 0], [126258958187508, 0], [163266702247281, 0], [129933362909152, 0], [175755461272549, 0], [141347408090966, 0]], "393": [[276871479152793, 0], [147626322588738, 0], [84123495620851, 0], [249129720720519, 0], [54554198568890, 0], [207291010296550, 0], [14809258659227, 0], [144455231438962, 0], [5781926560692, 0]], "392": [[201108243045046, 0], [266640222408475, 0], [54115445700122, 0], [92077028071605, 0], [87355553104503, 0], [91914130759090, 0], [2861558117229, 0], [86425050042496, 0], [95553763782850, 0]], "88": [[175949537459087, 0], [104224693440171, 0], [249580697073810, 0], [142280501365606, 0], [257236554724572, 0], [198776926261561, 0], [14942523967005, 0], [197322860245617, 0], [248502833661282, 0]], "89": [[211516431399353, 0], [74050594067655, 0], [264155959292419, 0], [33183993585272, 0], [26332335021455, 0], [28063590966922, 0], [16070083154776, 0], [103577623796394, 0], [235259891658696, 0]], "397": [[114051361945959, 0], [98036984635353, 0], [275709513518723, 0], [256487685442241, 0], [6570707508442, 0], [138516263183932, 0], [140300408039641, 0], [185882512848613, 0], [162935112488118, 0]], "396": [[68667772927050, 0], [139301719383369, 0], [100073099852439, 0], [234244370434216, 0], [108829443321436, 0], [79754274903244, 0], [73436574206837, 0], [116499553879985, 0], [15763418061272, 0]], "395": [[246977038585268, 0], [17505045731275, 0], [35127450345507, 0], [237093451201067, 0], [270776018347177, 0], [47145233342778, 0], [80918350359229, 0], [179293735474938, 0], [158598397254786, 0]], "394": [[45330963784578, 0], [119191236375289, 0], [234844352436065, 0], [162816964766796, 0], [231486620174366, 0], [187160806552464, 0], [133330056912713, 0], [34109848049377, 0], [183653893159407, 0]], "82": [[230486251079148, 0], [113065963826704, 0], [183656185272650, 0], [25981449027725, 0], [266887487257339, 0], [174612925086293, 0], [71143676683809, 0], [224180878466437, 0], [15550321466613, 0]], "83": [[198043496186692, 0], [237485642455646, 0], [36510095573583, 0], [21245846641097, 0], [80064192547212, 0], [24014785161818, 0], [267415713731750, 0], [19654009958805, 0], [162973458575559, 0]], "80": [[134437502765649, 0], [157971197939734, 0], [92247580949742, 0], [111032208009676, 0], [215343421283650, 0], [214318107915385, 0], [132085576330755, 0], [119059628309182, 0], [119006046073666, 0]], "81": [[114117032261637, 0], [38223653637531, 0], [110095450002343, 0], [149041999639227, 0], [268297353168323, 0], [268210272890254, 0], [183688013727829, 0], [183909138911025, 0], [26520289801547, 0]], "86": [[250344062347444, 0], [18860734561415, 0], [251049917074263, 0], [227054295303511, 0], [240148067911570, 0], [21606875095394, 0], [203033330202838, 0], [43037042744375, 0], [206179687792641, 0]], "87": [[151455959349089, 0], [44743674178362, 0], [156839410106908, 0], [107837454680972, 0], [78956093815750, 0], [21835314053835, 0], [184057188476657, 0], [261826805186860, 0], [241547552903154, 0]], "84": [[2440729351392, 0], [80759778973140, 0], [35309085674547, 0], [233008565359918, 0], [237912229681714, 0], [202287671965549, 0], [189500798036482, 0], [271704202521870, 0], [172981310357056, 0]], "85": [[186176881652664, 0], [12890180555807, 0], [94763384544602, 0], [211399839943735, 0], [36897915341635, 0], [7670720725455, 0], [85527423456521, 0], [219232341396124, 0], [190193271214807, 0]], "797": [[31003182406435, 0], [38401844806261, 0], [247629339974554, 0], [29785181567482, 0], [17879270716800, 0], [71138327382238, 0], [239604711279275, 0], [76759734146602, 0], [85954352765533, 0]], "796": [[240413360260379, 0], [130143226209005, 0], [128983961851082, 0], [187587916908120, 0], [25101484464747, 0], [205139865898085, 0], [42833723415794, 0], [243907048251398, 0], [194334845688894, 0]], "795": [[196807764175563, 0], [191090586403171, 0], [193302003295789, 0], [83467274726188, 0], [161091658244561, 0], [50415715615621, 0], [134034658984243, 0], [169775826084175, 0], [230441697015683, 0]], "794": [[103084507683823, 0], [157989714712221, 0], [90478920258427, 0], [66707944091078, 0], [186847030302056, 0], [55890798975230, 0], [240869919101418, 0], [171081846963527, 0], [70724882423497, 0]], "793": [[22151804026287, 0], [71859218716964, 0], [170169788708976, 0], [152288406124825, 0], [96698536974709, 0], [185216286833743, 0], [256710364410885, 0], [102199075292887, 0], [231343864779774, 0]], "792": [[167034592660887, 0], [80387591335071, 0], [134796983466120, 0], [166607353665912, 0], [236635253040942, 0], [201146712342097, 0], [254758631438439, 0], [70677054452646, 0], [249327274971655, 0]], "791": [[195795900548445, 0], [260393974568834, 0], [21643428333365, 0], [82247521633934, 0], [259340966726777, 0], [178415368168703, 0], [10290852645753, 0], [8801967441356, 0], [174985687886845, 0]], "790": [[232884081271610, 0], [259915511363695, 0], [166349453336449, 0], [41807409207747, 0], [138619348258288, 0], [259852921387118, 0], [93052517985321, 0], [73303064036232, 0], [122847078772852, 0]], "799": [[33969104230306, 0], [199874140758596, 0], [48956100949619, 0], [157024627470877, 0], [7098278114450, 0], [241036492359185, 0], [149430612386336, 0], [220361789460071, 0], [202746540299245, 0]], "798": [[39960812854130, 0], [85372785813489, 0], [272028261471452, 0], [220885336613272, 0], [90908075937139, 0], [268338495638186, 0], [257180656146112, 0], [211408404504264, 0], [57243150066670, 0]], "7": [[256872369435759, 0], [234335075829932, 0], [143491205083114, 0], [240136135763748, 0], [187253693751205, 0], [35258976903701, 0], [46509262520261, 0], [215079013238811, 0], [123699989695541, 0]], "601": [[252365867876321, 0], [37495434373387, 0], [267200052121493, 0], [233774961745233, 0], [151283490533442, 0], [186108054181168, 0], [5346624908953, 0], [109147499897254, 0], [191374829571649, 0]], "607": [[100958887385564, 0], [109867856498987, 0], [81296986634356, 0], [134151703073924, 0], [78363318383736, 0], [169390023303212, 0], [243859264492026, 0], [120829714210727, 0], [96498286792106, 0]], "586": [[26322972083257, 0], [44514184573034, 0], [164013929933032, 0], [78849924819425, 0], [249575119257519, 0], [175665789740252, 0], [165503893014399, 0], [110045517067325, 0], [141763791388415, 0]], "587": [[251541913315792, 0], [179499597070404, 0], [267916079709107, 0], [148113320457796, 0], [266532737283948, 0], [55178286202123, 0], [194554988225031, 0], [4651846170543, 0], [199102251897775, 0]], "584": [[221014875991995, 0], [139963449000976, 0], [135086090995436, 0], [53754664051835, 0], [201928710427600, 0], [228293229326592, 0], [248195257551963, 0], [56252610838355, 0], [210689729591717, 0]], "585": [[94371514139273, 0], [66036999284009, 0], [267520002317595, 0], [192248634652104, 0], [217544870828693, 0], [264301223195337, 0], [24924867802710, 0], [260775524045393, 0], [14171901576023, 0]], "582": [[40331725518214, 0], [220916502636618, 0], [198187160745649, 0], [121864319482169, 0], [124808636456139, 0], [143750347710900, 0], [997158440698, 0], [204525752235128, 0], [112953576549132, 0]], "583": [[137026126143227, 0], [116589670860032, 0], [152325307201960, 0], [252111257022493, 0], [111692078645304, 0], [234111438990418, 0], [178214910330331, 0], [226702822087228, 0], [81771766571812, 0]], "580": [[39586301506443, 0], [3550912410847, 0], [270619984140249, 0], [151926804415918, 0], [9776152404210, 0], [5957762951412, 0], [265833913824729, 0], [19366104508413, 0], [105058532629225, 0]], "581": [[221033358453804, 0], [253341377338798, 0], [50730817882126, 0], [86611851233539, 0], [25052486212905, 0], [173548484800861, 0], [83132481943798, 0], [73076303824430, 0], [219643126188995, 0]], "588": [[268255286050045, 0], [46342674257662, 0], [130706211922503, 0], [278808797235529, 0], [264344117366831, 0], [155540566684274, 0], [232140218167988, 0], [207534810176534, 0], [243817175958224, 0]], "589": [[122132056911078, 0], [240745664493727, 0], [109798574775179, 0], [278057685758848, 0], [257365489325703, 0], [201501008147026, 0], [251900248377971, 0], [271952806153012, 0], [95190612021171, 0]], "245": [[30602490189000, 0], [17620303359504, 0], [60401567884426, 0], [6231052305811, 0], [250908496191780, 0], [11425595507931, 0], [105237288333953, 0], [120936386262637, 0], [108032704215154, 0]], "244": [[112524342504401, 0], [22623325591711, 0], [111339938076153, 0], [57502968818275, 0], [88911215204914, 0], [46536768464826, 0], [138744817055429, 0], [52999807953372, 0], [131133319805272, 0]], "247": [[278122510043546, 0], [263854232978937, 0], [206428792078264, 0], [112713896992889, 0], [175420553478682, 0], [163835513777577, 0], [80097867727848, 0], [79316355948067, 0], [272129368272813, 0]], "246": [[235345019461278, 0], [19537680634590, 0], [234557717605257, 0], [118835510186754, 0], [126522995250015, 0], [100246807036584, 0], [169152656861470, 0], [116807878006405, 0], [279914585922837, 0]], "241": [[22365922320006, 0], [112805753944187, 0], [158023975996876, 0], [106258287719484, 0], [33134418465034, 0], [93113607949037, 0], [244833162889653, 0], [54463648982787, 0], [195629734715558, 0]], "240": [[39621530529675, 0], [171649551438481, 0], [63598101549738, 0], [118407824928525, 0], [108304521275801, 0], [98802601972037, 0], [73479084283708, 0], [194506175675150, 0], [267945255081877, 0]], "243": [[173939228338679, 0], [243989452664324, 0], [41640419116714, 0], [211303233996009, 0], [143699615372803, 0], [208421022029060, 0], [36277473857931, 0], [274707927644003, 0], [246294993122628, 0]], "242": [[52573813769470, 0], [46476610374044, 0], [133933260678561, 0], [28252367539436, 0], [92626200228557, 0], [6813392835783, 0], [161976859401775, 0], [56033212578027, 0], [83552184879869, 0]], "615": [[110478632704801, 0], [154147789816666, 0], [129797115461873, 0], [223706186494726, 0], [100742656314424, 0], [89588989204836, 0], [109167390188291, 0], [46052139189691, 0], [127849574097961, 0]], "249": [[216254960566258, 0], [188010436491244, 0], [130097273957307, 0], [248354420222194, 0], [95510405635044, 0], [129120922631351, 0], [95675179747086, 0], [215452448810332, 0], [192610187867579, 0]], "248": [[221657814678469, 0], [125218228685016, 0], [181960341414285, 0], [203396317922915, 0], [253086588612797, 0], [188348255335045, 0], [60267219553137, 0], [133440384036056, 0], [148782057541138, 0]], "924": [[188831844178248, 0], [181362908867713, 0], [76101554485978, 0], [116287332936205, 0], [8800392650182, 0], [278541679471786, 0], [277517746010526, 0], [7390718552580, 0], [20419122759807, 0]], "970": [[151104128836432, 0], [218872522233531, 0], [142476255959155, 0], [163985356447404, 0], [84655526425596, 0], [99653507068836, 0], [148560168219535, 0], [217270834041148, 0], [60382427789611, 0]], "925": [[222921890067045, 0], [128842301675369, 0], [224819734180537, 0], [106911882574737, 0], [27178665456710, 0], [100182331153018, 0], [256622469974537, 0], [143521339677138, 0], [221453328805531, 0]], "519": [[4836420361471, 0], [75458830475081, 0], [2858849330729, 0], [21010099297587, 0], [42985305179144, 0], [21578230355922, 0], [137123307998589, 0], [67609091269391, 0], [240911480718147, 0]], "518": [[142606378531894, 0], [167194569221941, 0], [248139050622848, 0], [37260627820203, 0], [192055555494110, 0], [131499219366651, 0], [1900689228127, 0], [19401917211794, 0], [25262904194785, 0]], "926": [[257856544442789, 0], [88734705233101, 0], [207140578013357, 0], [184949538908380, 0], [258039525246888, 0], [208756926578260, 0], [74165383267850, 0], [205108557266169, 0], [29717786640783, 0]], "1009": [[195417364244696, 0], [189466334182935, 0], [26662560663628, 0], [13709973558905, 0], [278050904266906, 0], [177965715837065, 0], [258458517606962, 0], [189727365500449, 0], [125266691060142, 0]], "1008": [[204061375810101, 0], [254846079053967, 0], [39002833046772, 0], [24142820261942, 0], [113861179826228, 0], [153546807711262, 0], [21610021991094, 0], [209331886171812, 0], [178765487565988, 0]], "511": [[43586728271262, 0], [58927533078978, 0], [25498963788744, 0], [67094877240453, 0], [30362779822064, 0], [91467478334560, 0], [56921992382359, 0], [226806108927160, 0], [229225308652370, 0]], "510": [[125614889613469, 0], [216001040231298, 0], [280326244223948, 0], [273212140608544, 0], [154533718224256, 0], [230842382541313, 0], [270049323944491, 0], [61307261864877, 0], [181227319089209, 0]], "513": [[43035941947599, 0], [119327579344237, 0], [68734709256403, 0], [18951440874361, 0], [81476045672006, 0], [221539239174723, 0], [263999987627505, 0], [153399280071976, 0], [136315636150836, 0]], "512": [[23550606136942, 0], [54882483935495, 0], [211933974874764, 0], [161429642058592, 0], [111205688480417, 0], [238734329041307, 0], [154507629578465, 0], [66463037038494, 0], [45456520409850, 0]], "515": [[92859028226837, 0], [15436392466011, 0], [272646226658760, 0], [22047751925814, 0], [6155068435281, 0], [167009086112751, 0], [194158869014226, 0], [3424068340725, 0], [111933088632383, 0]], "514": [[21123669084792, 0], [21579701142976, 0], [118666183201409, 0], [256018631459455, 0], [233750603816683, 0], [34573793999274, 0], [115377658614597, 0], [59174248863656, 0], [211268625744429, 0]], "517": [[184649438639735, 0], [15729059623605, 0], [60304677247617, 0], [137993932814093, 0], [149601076295265, 0], [42633120708291, 0], [226604360266170, 0], [201191584155937, 0], [32962067018380, 0]], "516": [[276583253361155, 0], [172139242694642, 0], [165171724724140, 0], [99605462358902, 0], [124329473286793, 0], [177903591881840, 0], [257291242180200, 0], [99435910385621, 0], [259699165748416, 0]], "458": [[15241249815468, 0], [37268859277402, 0], [39793641590560, 0], [223014149149409, 0], [110213706448033, 0], [267760622604568, 0], [233849809850042, 0], [243437446111721, 0], [205975212901493, 0]], "459": [[84503634787731, 0], [163311473838333, 0], [219584048207793, 0], [47462419060890, 0], [125855627476266, 0], [131990876725075, 0], [238362865773449, 0], [85264665686697, 0], [8605464122443, 0]], "621": [[271725136012625, 0], [227092534271787, 0], [131341949373590, 0], [266395826007637, 0], [25144435596135, 0], [174453677768136, 0], [24561088839317, 0], [252695559907835, 0], [117295546007838, 0]], "620": [[135846212392094, 2], [139367035185941, 2], [208097329736197, 2], [35858513490184, 2], [157638975947915, 2], [230122540091109, 2], [111738619203409, 2], [191146888774110, 2], [217916923107446, 0]], "627": [[16461922564443, 0], [71915745319012, 0], [163692152557633, 0], [93431383781260, 0], [213349924448319, 0], [99569114830027, 0], [59685415901248, 0], [89199804702847, 0], [232869825353711, 0]], "626": [[7394724661592, 0], [60529199780316, 0], [84613908019685, 0], [230099362396908, 0], [33774993187968, 0], [81330274080793, 0], [42332285620037, 0], [147685610912138, 0], [159369052486966, 0]], "625": [[56788721956686, 0], [3120618425253, 0], [14846836530062, 0], [111972263105446, 0], [18104649586295, 0], [115605589235218, 0], [26894542102984, 0], [215658823810986, 0], [17201875419843, 0]], "624": [[37620558209404, 0], [138083167317566, 0], [36343376636551, 0], [16892453323175, 0], [89498084204701, 0], [66057203035165, 0], [136799977026615, 0], [86415769120107, 0], [210406071939040, 0]], "450": [[16136693058573, 0], [240187339204313, 0], [79756519686980, 0], [156955821159901, 0], [52332340710716, 0], [176085152528352, 0], [236080638611644, 0], [8971540004148, 0], [200808605566389, 0]], "451": [[163456336865281, 0], [18550436449121, 0], [242156156033562, 0], [260948328327658, 0], [21661444030146, 0], [262552323960278, 0], [184805973499855, 0], [161209949840571, 0], [57588164437207, 0]], "452": [[105062350609525, 0], [130437134791531, 0], [121408808873160, 0], [332519069289, 0], [101154510531621, 0], [207188931222633, 0], [213592128072790, 0], [199263455148365, 0], [141316576431314, 0]], "453": [[134613154249186, 0], [208962348743158, 0], [140217552577537, 0], [24731846296261, 0], [76754387154999, 0], [131034576406860, 0], [274690765882587, 0], [77702534074454, 0], [123323785593749, 0]], "454": [[190512206844753, 0], [135189148188229, 0], [215588663750999, 0], [208631806273554, 0], [24709813568904, 0], [58718579792142, 0], [45842270322180, 0], [154078875154689, 0], [213004453438611, 0]], "455": [[105006342194328, 0], [218513652332496, 0], [125785888343506, 0], [144408967412802, 0], [65791084673230, 0], [40971633121470, 0], [81100877705624, 0], [198108382303637, 0], [15486358459649, 0]], "456": [[160159151994773, 0], [234634603051742, 0], [64132049278424, 0], [222353892873750, 0], [128665157990738, 0], [126940606114882, 0], [66493192647650, 0], [280246415592318, 0], [60459659181697, 0]], "457": [[246755413901083, 0], [265490341944406, 0], [44647430772514, 0], [70876837217207, 0], [280887986561948, 0], [175659778796330, 0], [145280201214527, 0], [280113591125300, 0], [100623187893253, 0]], "979": [[165616085398527, 0], [167195784875855, 0], [192521471836795, 0], [138763771235040, 0], [129650223236036, 0], [10360383400139, 0], [242223334721346, 0], [15044891847608, 0], [166118120668223, 0]], "179": [[111590098302383, 0], [6484237203340, 0], [185204316208444, 0], [183154942335462, 0], [74153228144699, 0], [218766250272502, 0], [96259688241468, 0], [221424683090422, 0], [168579264490553, 0]], "178": [[37156014088342, 0], [186121942652733, 0], [164551625467028, 0], [260675543323060, 0], [207265738130311, 0], [68622983953504, 0], [79225243923548, 0], [218754783076454, 0], [245064801147284, 0]], "177": [[28246983087794, 0], [212960741181580, 0], [18477944156720, 0], [56697070316251, 0], [169823657392846, 0], [943009272792, 0], [10329287235191, 0], [166032116380414, 0], [226678283677487, 0]], "176": [[235044069576691, 0], [29707851395247, 0], [178386550537206, 0], [171332708233503, 0], [230166087495243, 0], [275773527640993, 0], [123793965026756, 0], [262633562631463, 0], [235711659697610, 0]], "175": [[226858481964033, 0], [203880143111440, 0], [222689728401051, 0], [224078135091928, 0], [54883454397055, 0], [256603396963752, 0], [178707787914645, 0], [129738090837442, 0], [2848952999090, 0]], "174": [[46078618833998, 0], [279164510723098, 0], [176762969835533, 0], [32980432079186, 0], [125494656188059, 0], [140573647903535, 0], [254482513013034, 0], [116599600789708, 0], [184569642339231, 0]], "173": [[272691388804791, 0], [190742378381718, 0], [26589870564237, 0], [91424754831432, 0], [17367418438496, 0], [168087217868011, 0], [77815280247742, 0], [55949189188353, 0], [163893932891228, 0]], "172": [[26034784121315, 0], [228547057330385, 0], [177261319473378, 0], [67162331133299, 0], [271000037887434, 0], [42621781478060, 0], [166386440372316, 0], [34287763133001, 0], [2733374586919, 0]], "171": [[247086322625588, 0], [21585650674605, 0], [1505265560908, 0], [81166765746275, 0], [104871093978797, 0], [35706841861751, 0], [190518899315680, 0], [193008085357643, 0], [91195593431582, 0]], "170": [[182514996552573, 0], [247172538414341, 0], [173809496004845, 0], [87635275563694, 0], [57497167289100, 0], [175612055962101, 0], [119852648630531, 0], [15805200542586, 0], [258998720597015, 0]], "977": [[227408772115026, 0], [14250489707008, 0], [90142250019236, 0], [72286762411745, 0], [24438395434168, 0], [159335157460135, 0], [32572435868940, 0], [260429494286636, 0], [120916987908628, 0]], "656": [[86078536962419, 0], [46876265953508, 0], [153365692031132, 0], [135645518075538, 0], [272039624845503, 0], [253580279371546, 0], [169239508430789, 0], [278469676814184, 0], [190911774380708, 0]], "975": [[218768043738079, 0], [128640508932076, 0], [201233817103392, 0], [245364503347890, 0], [171281673149320, 0], [96060615743375, 0], [4491650046471, 0], [100918746683523, 0], [217546522423141, 0]], "974": [[207471241440274, 0], [69692369244539, 0], [79786509069232, 0], [143432609495693, 0], [47273605279048, 0], [57276833544545, 0], [113164231089763, 0], [196542642540299, 0], [216858992006999, 0]], "973": [[86977943366106, 0], [255685668614663, 0], [239560871434614, 0], [67152579369210, 0], [139243673618385, 0], [230261471101903, 0], [258626114273599, 0], [165686424147565, 0], [208245669289724, 0]], "972": [[60748469259540, 0], [99195056433302, 0], [246816981470291, 0], [268947753453963, 0], [42383191181089, 0], [104807471128254, 0], [113259376163331, 0], [191982766945857, 0], [143462342375992, 0]], "971": [[91727457811994, 0], [264841217707201, 0], [208095855772792, 0], [92081014411571, 0], [186273208488039, 0], [239411135330964, 0], [103697384646879, 0], [241068969424439, 0], [187405846739507, 0]], "657": [[228658842451927, 0], [61041586104267, 0], [233108394783164, 0], [266459563665414, 0], [138671212282128, 0], [23882691252121, 0], [46028287875400, 0], [136352215581803, 0], [77987213381674, 0]], "654": [[4417396590291, 0], [64193842994708, 0], [107917676917102, 0], [106978222673099, 0], [156227335341483, 0], [31139758847054, 0], [9155056110038, 0], [266997887332753, 0], [72369423645011, 0]], "253": [[39751587303673, 0], [60964851873059, 0], [228881020242174, 0], [15899737183416, 0], [244075499387186, 0], [77698944904706, 0], [25070169774543, 0], [193626276276553, 0], [2671176539563, 0]], "978": [[166514962391726, 0], [97030427894639, 0], [157750529235672, 0], [120364775863540, 0], [162857032082442, 0], [272117485947980, 0], [57376162025062, 0], [3688472287786, 0], [172678992992623, 0]], "182": [[182422513189422, 6], [170019203614684, 6], [225632003097015, 6], [21962488455408, 2], [162507229573881, 2], [25078140811632, 2], [238942320424846, 0], [14425080477545, 0], [84626687818887, 0]], "183": [[178541616412234, 0], [132284377274421, 0], [259710759085639, 0], [278368811629317, 0], [178852674755634, 0], [143365650809304, 0], [59692414197060, 0], [126771788248288, 0], [36740347972381, 0]], "180": [[53205399648502, 0], [30578313763630, 0], [250228129844210, 0], [204976460305748, 0], [165650283906386, 0], [243025291530694, 0], [153250098026538, 0], [78003613329413, 0], [188000454014394, 0]], "181": [[170978870800693, 0], [86036233954598, 0], [45753058518545, 0], [10353110835913, 0], [92564071742046, 0], [93993540514098, 0], [40132211539862, 0], [255069831564111, 0], [250771418756439, 0]], "186": [[277126647794715, 0], [162331467626141, 0], [134164214285534, 0], [249543863719551, 0], [30913435183350, 0], [9815679002302, 0], [98396654406022, 0], [261927240521437, 0], [18607503787064, 0]], "187": [[254798055500068, 0], [164112569611383, 0], [164347789569437, 0], [6695135242345, 0], [78112548147958, 0], [259944026435912, 0], [133610075578084, 0], [132534967137360, 0], [258757414354637, 0]], "184": [[244415223105929, 0], [16723348149765, 0], [274230671994269, 0], [12603572349942, 0], [31302226764107, 0], [96062997825468, 0], [20109874951950, 0], [191891301555083, 0], [167696510948504, 0]], "185": [[44989980959831, 0], [65309069276369, 0], [174612448637339, 0], [35830920397092, 0], [56194315351816, 0], [201368660091438, 0], [278429330882985, 0], [119859045238090, 0], [184261841038182, 0]], "886": [[32877788968471, 0], [184780366116882, 0], [261084223301709, 0], [183669843772521, 0], [6266670239307, 0], [195605871610577, 0], [277130821173879, 0], [106486207712829, 0], [3941966392635, 0]], "652": [[57206547282697, 0], [74070720786469, 0], [236540662461442, 0], [195219222330159, 0], [276596717239527, 0], [175344966288198, 0], [257085157459381, 0], [157306973802065, 0], [174468544555397, 0]], "188": [[109713316086516, 0], [266071943473331, 0], [161313939992436, 0], [23471771546730, 0], [267262872390572, 0], [47824899622922, 0], [49383178772739, 0], [213380195583777, 0], [116593130839881, 0]], "189": [[130295542165044, 0], [191679779600062, 0], [217463411255396, 0], [248716456535915, 0], [141168853418431, 0], [63436859092289, 0], [191337839143558, 0], [278153178129720, 0], [76437798886121, 0]], "658": [[48277418170670, 0], [232873011152801, 0], [67407770825422, 0], [52673602892105, 0], [272540631331485, 0], [32094759118818, 0], [166090845072125, 0], [112181407669775, 0], [116301176621505, 0]], "653": [[237461566694859, 0], [74369211109131, 0], [119752592027983, 0], [270011575619490, 0], [137563929623294, 0], [124293965219768, 0], [246914778865103, 0], [256835861407336, 0], [127461457727192, 0]], "650": [[101350894120266, 0], [129477521869924, 0], [95006925164055, 0], [71590085103666, 0], [278106186821591, 0], [166500461459039, 0], [99101291249868, 0], [197173809823781, 0], [113203720210270, 0]], "651": [[254037044269048, 0], [129433699747031, 0], [56245114630751, 0], [139327395438728, 0], [258068949013757, 0], [117285793497861, 0], [237169654539717, 0], [27947521344278, 0], [141316103976699, 0]], "764": [[55440337502692, 0], [37331425789481, 0], [187850918839231, 0], [104104049361869, 0], [80423875501901, 0], [93943406189366, 0], [102552295224670, 0], [193650958512213, 0], [179613503574193, 0]], "11": [[221997029905758, 0], [113333367653647, 0], [203222362043128, 0], [165270640828810, 0], [272735104302784, 0], [177177158197309, 0], [16466589541877, 0], [98001969342833, 0], [152802961340004, 0]], "10": [[123219005230218, 0], [181346861407437, 0], [243520240624504, 0], [166568909005749, 0], [262231737487004, 0], [121178778570108, 0], [110967804961868, 0], [119000779752986, 0], [172579392318744, 0]], "13": [[241536005989768, 0], [74423454481834, 0], [9898834771229, 0], [153096850605684, 0], [159452077670175, 0], [201231749945958, 0], [130831083769117, 0], [85923860044678, 0], [237606196388880, 0]], "12": [[249765117627097, 0], [242043453128146, 0], [270058604083152, 0], [112923795997699, 0], [256114255590266, 0], [67540909067115, 0], [19677551938284, 0], [50577066116788, 0], [2559403765940, 0]], "15": [[135656857755281, 0], [277459464488320, 0], [156978357971941, 0], [155968257185603, 0], [206653095519943, 0], [226047521269884, 0], [179559771383472, 0], [205016524478625, 0], [223660567600827, 0]], "14": [[188977277207611, 0], [29561687709464, 0], [186070927229065, 0], [108229644642487, 0], [173479062885893, 0], [49618636605692, 0], [153685462473711, 0], [129911770787561, 0], [147245084681099, 0]], "17": [[201826529725859, 0], [257517185559589, 0], [194821799649184, 0], [22853340069681, 0], [280956624592230, 0], [270486001191704, 0], [239798801990315, 0], [231921097444077, 0], [12924111259340, 0]], "16": [[99092297530388, 0], [107739542806991, 0], [68459684307006, 0], [248858710688984, 0], [201215326102599, 0], [258344874860118, 0], [147858947618750, 0], [148437967268719, 0], [158650538399030, 0]], "19": [[185509598552912, 0], [162122247114904, 0], [49084344409169, 0], [197523597173664, 0], [43529078076126, 0], [122278505654055, 0], [125324654970321, 0], [56690949077697, 0], [54142864594691, 0]], "18": [[127240524719073, 0], [274548614143590, 0], [181674787934406, 0], [228955931482129, 0], [145785101905400, 0], [208665569518259, 0], [89929706869818, 0], [173616998465111, 0], [270760785355076, 0]], "863": [[20553533418644, 0], [226356410352159, 0], [268101898042994, 0], [116216722488858, 0], [275530021567266, 0], [226052000333977, 0], [249120382017679, 0], [250998213130149, 0], [212355698068307, 0]], "862": [[61563685549429, 0], [15357011750821, 0], [272285666228116, 0], [231905359745481, 0], [57842629039679, 0], [210602001397243, 0], [142955411675345, 0], [193399800886225, 0], [230537317204017, 0]], "865": [[108579308877891, 0], [167842991115200, 0], [67772842904186, 0], [260111795127017, 0], [269735538608495, 0], [271667449665068, 0], [273039330234383, 0], [94940741059136, 0], [249913361542109, 0]], "864": [[10171833226277, 0], [160570887480127, 0], [261735086658726, 0], [13583793919612, 0], [57291032109653, 0], [111252787211246, 0], [129363683445953, 0], [264658772712243, 0], [148471287556162, 0]], "867": [[11910759087587, 0], [107704840150170, 0], [114561757990650, 0], [90606363676119, 0], [31059307128688, 0], [194742773802251, 0], [149162909514719, 0], [124609165436598, 0], [132184887244340, 0]], "866": [[39822630898201, 0], [144148623938139, 0], [52112689663303, 0], [39105325365928, 0], [278082156768844, 0], [254353513337654, 0], [218955725812735, 0], [116145912702960, 0], [131181429057069, 0]], "884": [[122285711212579, 0], [98872911914150, 0], [267150576667097, 0], [86132660996479, 0], [236314290385531, 0], [56792138364707, 0], [197147171795977, 0], [122029585134834, 0], [209756991588820, 0]], "938": [[62275118658966, 0], [33729658515522, 0], [50131709463575, 0], [48680285106377, 0], [278371240777151, 0], [29256718307057, 0], [28662922207619, 0], [101155850388738, 0], [160506738587411, 0]], "659": [[129745033922865, 0], [62929898044555, 0], [42288755011116, 0], [119773324637205, 0], [215948976741174, 0], [197965768558171, 0], [32382452179787, 0], [191726373334038, 0], [59556229680528, 0]], "883": [[264538447342543, 0], [200201694748881, 0], [153157504492159, 0], [143355401050800, 0], [201626796769873, 0], [201623198279521, 0], [142863222469998, 0], [126110667341527, 0], [214177663198312, 0]], "753": [[181598326415548, 0], [274411471609046, 0], [149366758303872, 0], [177614399463788, 0], [203793932486594, 0], [181377961545391, 0], [270774660752722, 0], [219887554216011, 0], [91771705970951, 0]], "881": [[30173178163601, 0], [276483574165924, 0], [19474463499185, 0], [145537951527618, 0], [181389210602567, 0], [51473663503824, 0], [252021046977034, 0], [59171729922709, 0], [175160398600220, 0]], "880": [[61593455682535, 0], [156774967943498, 0], [83795834386347, 0], [272658007047000, 0], [241642648350787, 0], [211803832152449, 0], [194032537796534, 0], [176033461772229, 0], [185067474161050, 0]], "887": [[82446787584042, 0], [51767921416744, 0], [97871753476551, 0], [104893409177834, 0], [266899872848024, 0], [262850835815063, 0], [90766501140279, 0], [113870411262532, 0], [106003396823753, 0]], "831": [[240683649100675, 0], [253065086930062, 0], [232601681121702, 0], [225152085953480, 0], [194836525739158, 0], [146583885201395, 0], [51387826629236, 0], [253983678167801, 0], [144917287880846, 0]], "885": [[9082593483803, 0], [214432274647448, 0], [26085147315314, 0], [43528601447637, 0], [139665627496484, 0], [277875927234101, 0], [149147983864231, 0], [28074383968257, 0], [179300248968750, 0]], "752": [[260484343425935, 0], [230757562175634, 0], [135962261143732, 0], [154568201824427, 0], [145712477318804, 0], [63331200653976, 0], [197693238301917, 0], [175916250201658, 0], [259303056026206, 0]], "928": [[116654133434769, 0], [46752003481714, 0], [71995340746758, 0], [270094340628082, 0], [161290905900524, 0], [65004691074751, 0], [69663979271282, 0], [229437379283788, 0], [277334156510956, 0]], "62": [[104398971680638, 2], [127208561778304, 2], [1836319442954, 2], [149363250171413, 1], [116966462772542, 1], [150306525437376, 0], [92430398965170, 0], [187910195824605, 0], [158728167816118, 0]], "888": [[88026121218521, 0], [273778418940261, 0], [221241231423170, 0], [157159502814455, 0], [54057639689464, 0], [25398771986517, 0], [105617272775874, 0], [180136745985152, 0], [196491289565211, 0]], "1012": [[33742445918923, 0], [83714036250340, 0], [228237175241512, 0], [94240357993793, 0], [160093512346923, 0], [113531313290837, 0], [111455556341703, 0], [99813272407024, 0], [2150414871257, 0]], "950": [[236147134430015, 0], [215664466602302, 0], [226861589914125, 0], [184480338619744, 0], [227392057773142, 0], [205131974945254, 0], [209860610148689, 0], [84701525291769, 0], [245874685879539, 0]], "756": [[53425515808172, 0], [113162442972531, 0], [120528758775118, 0], [278763642068356, 0], [55691689852222, 0], [110578358637719, 0], [6262285127662, 0], [88213884474489, 0], [175699508715837, 0]], "929": [[227564375245429, 0], [233295188476321, 0], [118926136471417, 0], [92808861474014, 0], [4074730412903, 0], [36368881846028, 0], [86209929887774, 0], [175367987760111, 0], [84090470714240, 0]], "809": [[202044975007785, 0], [246235698727582, 0], [6477089044495, 0], [109295973315368, 0], [267138064562917, 0], [88272778656422, 0], [93402361119548, 0], [97461373251895, 0], [240071521684067, 0]], "322": [[232583703491526, 0], [123582281373694, 0], [156332036106938, 0], [230789103970877, 0], [144999086863750, 0], [38780969530329, 0], [186574562592869, 0], [226900070793292, 0], [214668313859044, 0]], "323": [[212833012258220, 0], [199592916752653, 0], [150612737003806, 0], [16575105129787, 0], [34776491315292, 0], [117091898644078, 0], [141932318578598, 0], [191836913750191, 0], [145304257095655, 0]], "320": [[227078213485544, 0], [78599366689712, 0], [231195221297586, 0], [66289291335217, 0], [273867858940348, 0], [85741311675868, 0], [148793244872749, 0], [181301181320159, 0], [132384778598162, 0]], "321": [[4432689972509, 1809], [144167129400862, 1809], [176965350631484, 1809], [272986720154769, 216], [241686492735936, 201], [235165795142009, 33], [259931166125910, 0], [59481067490854, 0], [128608925652953, 0]], "326": [[67412863025432, 0], [254144904317149, 0], [245001233864700, 0], [144071502640202, 0], [260790600185532, 0], [189156296254285, 0], [224413516724660, 0], [117055679650530, 0], [158791861054318, 0]], "327": [[154552165891876, 0], [231029129137186, 0], [242507416667398, 0], [121147982431553, 0], [111276652801178, 0], [114866318429511, 0], [178345992283544, 0], [135434966703285, 0], [239725955655620, 0]], "324": [[67772930258190, 0], [125264074199825, 0], [53462659014830, 0], [233200216570007, 0], [85898938455206, 0], [195900682597420, 0], [128510017200658, 0], [2410201492462, 0], [141796197414313, 0]], "325": [[9418562346639, 0], [218306665565944, 0], [169212171725342, 0], [31668187395845, 0], [190355907976813, 0], [281070070783043, 0], [253014595242982, 0], [148561924478448, 0], [225339618975466, 0]], "328": [[187694300531401, 0], [166755093894653, 0], [179568345849252, 0], [20814291290808, 0], [199664214987330, 0], [226009247633653, 0], [2413536957802, 0], [144280722481033, 0], [8980198363378, 0]], "329": [[269440055511753, 0], [23235057745638, 0], [200871409203569, 0], [119049926917901, 0], [230458338996099, 0], [210656987198000, 0], [98931426747101, 0], [223277572691258, 0], [48457534650907, 0]], "759": [[26939885009828, 0], [235710385263299, 0], [5172102290071, 0], [171674358180087, 0], [213448926915548, 0], [161067785209377, 0], [120369819922777, 0], [137286156284886, 0], [125311529832767, 0]], "201": [[193555272411525, 0], [235656066058382, 0], [62365351779631, 0], [18259739269610, 0], [128967712398771, 0], [15296871500817, 0], [138379828112595, 0], [149965755434683, 0], [47005733727630, 0]], "200": [[239166748142515, 0], [61748363191543, 0], [56325623093242, 0], [50011798962981, 0], [54503889342433, 0], [133545487667277, 0], [165530390912224, 0], [258482966071237, 0], [55411886452034, 0]], "203": [[186857677678069, 0], [53493189817473, 0], [31740003052487, 0], [25465481751307, 0], [218766318911520, 0], [18668896490576, 0], [161735173576542, 0], [7361137390113, 0], [3344887259331, 0]], "202": [[221238396725615, 0], [182076203351242, 0], [82603799621501, 0], [57726258648611, 0], [272025008777848, 0], [55652172027306, 0], [233294878501853, 0], [150113730679802, 0], [63755661951406, 0]], "205": [[215797516224283, 0], [109472596603587, 0], [32630145888768, 0], [154511849645849, 0], [28021163043080, 0], [118654607142550, 0], [175343828791307, 0], [63686084419936, 0], [34275419932659, 0]], "204": [[49098176646021, 0], [155211548047224, 0], [170851557289696, 0], [181649558508989, 0], [240425092547586, 0], [247835250930117, 0], [147553009678021, 0], [148315282402362, 0], [79380544519328, 0]], "207": [[71421714445991, 0], [77547882918329, 0], [158941000842590, 0], [2606591157974, 0], [71494968209118, 0], [57529867026895, 0], [187251205162724, 0], [32817614071851, 0], [169622802589651, 0]], "206": [[269403464564712, 0], [58624338696806, 0], [157900082694136, 0], [141644094955703, 0], [233552832316191, 0], [109442715321778, 0], [50696765115660, 0], [96838779551758, 0], [233311818875730, 0]], "209": [[223488300268906, 0], [204839704024050, 0], [65741706165546, 0], [50299109560349, 0], [92940636445840, 0], [80436339023976, 0], [220170164874062, 0], [9075609821637, 0], [222771013005110, 0]], "208": [[687856253170, 0], [272513080162706, 0], [50196869208187, 0], [280044833845993, 0], [278976827341768, 0], [161014346486332, 0], [17142626027380, 0], [270037982228483, 0], [249371147655983, 0]], "779": [[75871257766954, 147], [226680632724678, 147], [197604005132087, 147], [79555537402251, 91], [215285608718021, 91], [216948031204446, 57], [266615865162246, 57], [147099014472923, 57], [72689552669588, 0]], "778": [[116901656881640, 0], [242871363773514, 0], [231619109773745, 0], [109682404185454, 0], [19835089099943, 0], [27439671645732, 0], [189753426529548, 0], [146412278372203, 0], [136378472687790, 0]], "889": [[238330178245260, 0], [46338079511328, 0], [11762536064408, 0], [150678927788514, 0], [105771591402113, 0], [93736816800124, 0], [279982847099666, 0], [45164740877630, 0], [69682489997654, 0]], "77": [[96090553108339, 0], [124347294723412, 0], [278986302758065, 0], [87022058222285, 0], [124964745198485, 0], [256708779664492, 0], [240055281358139, 0], [27402135651932, 0], [1614483288741, 0]], "76": [[133356282936686, 0], [171086737119086, 0], [160821126185933, 0], [147601819556500, 0], [132052103666561, 0], [265254186318081, 0], [207115722956523, 0], [32507275931837, 0], [53832177437926, 0]], "75": [[183046922985433, 0], [13817386992671, 0], [111385811440692, 0], [95768893238602, 0], [114998394674440, 0], [16772082383609, 0], [87752621157207, 0], [268318947908526, 0], [165573558806712, 0]], "74": [[214088068032321, 0], [199277407627779, 0], [169494916907045, 0], [275622775208875, 0], [84951504404438, 0], [34066795668238, 0], [76006832909987, 0], [150729198766391, 0], [240451747451002, 0]], "73": [[129687867933217, 0], [167458570070039, 0], [21308208966021, 0], [169815753144781, 0], [222657356506390, 0], [148746583289918, 0], [249587035929984, 0], [135928059265303, 0], [229072092580426, 0]], "72": [[229555056265265, 0], [258387137286426, 0], [51673046414502, 0], [256344241294078, 0], [249510591711962, 0], [13632731384955, 0], [183477035676062, 0], [134966048574804, 0], [214057707072854, 0]], "71": [[62070487661343, 0], [192519943483378, 0], [218317307441629, 0], [113215340451780, 0], [89582629577896, 0], [42650352069087, 0], [18849895770490, 0], [266551192651894, 0], [254876660275184, 0]], "70": [[270970483840703, 0], [201202829159786, 0], [219908733093150, 0], [211908117362485, 0], [132822216232505, 0], [41468458461818, 0], [95301012174001, 0], [9725707654738, 0], [39750197803693, 0]], "655": [[280902483556418, 0], [238659727229523, 0], [192750334882023, 0], [207570958220668, 0], [114199324851070, 0], [118251679058477, 0], [24049108730267, 0], [72085553724051, 0], [98256291996324, 0]], "79": [[228915022530569, 0], [252405798355384, 0], [277175281312149, 0], [116428307436842, 0], [235558381500632, 0], [38581597433087, 0], [86918820978954, 0], [92336877421444, 0], [165977832191759, 0]], "78": [[204222461723976, 0], [110715301848306, 0], [144779398967330, 0], [68782393614437, 0], [171843269323191, 0], [193160741762526, 0], [99838360057716, 0], [23759188848067, 0], [125426926311853, 0]], "2": [[189708831321441, 0], [153137569561689, 0], [112654136244499, 0], [245470860954008, 0], [7331277899758, 0], [272762730097790, 0], [32856333023199, 0], [49806299200355, 0], [47336454921728, 0]], "805": [[52661317961045, 0], [10422586030840, 0], [196460103301498, 0], [51856326349249, 0], [141463871646922, 0], [125294668310064, 0], [62359685100085, 0], [140534776496101, 0], [223424605657790, 0]], "804": [[170336045450428, 0], [190336752821103, 0], [70562671176003, 0], [230935376877067, 0], [210307550596372, 0], [203163614040483, 0], [164292267432665, 0], [131129690778572, 0], [125863497364511, 0]], "669": [[171478845001328, 2], [246546980467207, 2], [274196972826053, 2], [116409681192563, 0], [156519949497195, 0], [219140509149347, 0], [150009360299575, 0], [99429204301610, 0], [138150281597076, 0]], "668": [[4545013777109, 0], [127627074755781, 0], [21574556590613, 0], [139814289491719, 0], [151738936835955, 0], [9978008425460, 0], [188086600356821, 0], [83407529306854, 0], [158220041051507, 0]], "667": [[114402476521561, 0], [57406400221905, 0], [215022174009359, 0], [180227511165952, 0], [141061908009379, 0], [236210921825021, 0], [215335532862733, 0], [226323486162991, 0], [141756086121932, 0]], "666": [[113793086375622, 0], [254819737247698, 0], [21290984862254, 0], [28535058118900, 0], [45558547281833, 0], [135543610011812, 0], [47929495317531, 0], [206936498802687, 0], [89240721094490, 0]], "665": [[44124849739222, 0], [219310004957036, 0], [262198148435995, 0], [45103356742685, 0], [138198962608255, 0], [280903351385231, 0], [109087708202342, 0], [50189936976301, 0], [120685432847779, 0]], "664": [[78131932853637, 0], [135389625574483, 0], [135433521769440, 0], [42947175214570, 0], [42288837087966, 0], [259874265534863, 0], [21185441515463, 0], [33652890672147, 0], [24080662899687, 0]], "663": [[203916855668102, 0], [35531131003742, 0], [142292883938065, 0], [194221044264841, 0], [138563694886983, 0], [86944382941275, 0], [212290441156792, 0], [249510296701259, 0], [238690832845703, 0]], "662": [[117135167627531, 0], [271848076602515, 0], [10432583847851, 0], [130417096517718, 0], [141274907597400, 0], [140726180265226, 0], [106244401627590, 0], [266595349185598, 0], [41036915376660, 0]], "661": [[118370247142491, 0], [155061696192148, 0], [254863655662820, 0], [262879689489044, 0], [50532092676700, 0], [108029726130976, 0], [207260908890042, 0], [79967883201282, 0], [15645419352238, 0]], "660": [[119564974596034, 0], [172880365652070, 0], [60892349228775, 0], [83983957218149, 0], [235008893914904, 0], [82122903689589, 0], [92404272636078, 0], [207892883942208, 0], [244631495271179, 0]], "769": [[11505944097636, 0], [163646681511774, 0], [31231684243139, 0], [25316087821016, 0], [243020211401202, 0], [207633325114865, 0], [20907129421018, 0], [44990495090349, 0], [98025990126941, 0]], "692": [[229134628709119, 0], [133934768493951, 0], [250864555261241, 0], [279585317266208, 0], [161263668010059, 0], [238901678649390, 0], [230452777283981, 0], [222509693822860, 0], [211721569077298, 0]], "693": [[90573417152395, 0], [91161073447765, 0], [153452247197912, 0], [158199282798961, 0], [122115759034073, 0], [166372868378416, 0], [215857376078265, 0], [124792982399559, 0], [16109617141775, 0]], "690": [[37417294001242, 0], [139919386508977, 0], [27247014147601, 0], [223062214198488, 0], [103718033425948, 0], [184454351761801, 0], [50650693044932, 0], [205492189329502, 0], [192345547247801, 0]], "691": [[92088401810598, 0], [269517543967836, 0], [51894956918682, 0], [6523554950544, 0], [103637810740731, 0], [228344226357389, 0], [18116170075737, 0], [144105020831341, 0], [206147599623910, 0]], "696": [[43524928583345, 0], [236758144164936, 0], [93231738911651, 0], [52094192224086, 0], [57923533422569, 0], [12625802126257, 0], [230522998341841, 0], [225740196775495, 0], [245651901655961, 0]], "697": [[62567055175349, 0], [250511030877803, 0], [150002163120550, 0], [114853225592658, 0], [244016109323956, 0], [209080231264902, 0], [76870594696188, 0], [141376307147769, 0], [113356329848677, 0]], "694": [[174016582831451, 0], [7500780518682, 0], [132071772201422, 0], [16404151738912, 0], [164677356410428, 0], [177080103298255, 0], [52894784965359, 0], [107282625129796, 0], [130326622260332, 0]], "695": [[109391056101698, 0], [147336747834482, 0], [276773410522175, 0], [104103081131239, 0], [208209319401488, 0], [187825364948544, 0], [229993817347535, 0], [54194813761780, 0], [18042161941307, 0]], "698": [[196639642237274, 0], [111186926226966, 0], [257457190964337, 0], [105096843785999, 0], [101337598969917, 0], [145816375029674, 0], [91580088636807, 0], [202430490090464, 0], [233715316329504, 0]], "699": [[239121355935472, 0], [265475545518566, 0], [242239718351705, 0], [208236896690508, 0], [35373974542749, 0], [99676837253679, 0], [164489100963380, 0], [163879216513976, 0], [85121938938640, 0]], "542": [[119977809684765, 0], [117817551090466, 0], [233175761723820, 0], [117346189222471, 0], [277785578511393, 0], [68716953940170, 0], [105862805657812, 0], [33182391256945, 0], [66081845819456, 0]], "543": [[111823619051809, 0], [158038992283736, 0], [38147762012646, 0], [219898091161637, 0], [44555208055476, 0], [158255440771679, 0], [88497042755153, 0], [222885004367285, 0], [268553486847662, 0]], "540": [[257827524285837, 0], [52696577767493, 0], [132831261399750, 0], [73845683870921, 0], [104120693657198, 0], [185521501001190, 0], [17720343077035, 0], [271848857362601, 0], [87155010663906, 0]], "541": [[131291670166646, 0], [11951398235185, 0], [222979258348551, 0], [251313021673684, 0], [279434344630847, 0], [184321754183496, 0], [182412182619203, 0], [141966011290312, 0], [108929606234673, 0]], "546": [[217826555936549, 0], [183142568392231, 0], [157970149530776, 0], [12478350320719, 0], [41729037027340, 0], [277633853637698, 0], [256085827066234, 0], [184459404051250, 0], [263134493259462, 0]], "547": [[120218776341014, 0], [119678946608204, 0], [111224500459761, 0], [78417076072901, 0], [243498984166312, 0], [261829832290734, 0], [224008319030275, 0], [46683320565333, 0], [73515576154969, 0]], "544": [[76787833935824, 0], [210350048968465, 0], [158025619210450, 0], [51359541521748, 0], [214047747701325, 0], [157908067630286, 0], [118490514416461, 0], [216979221151831, 0], [265833848052185, 0]], "545": [[172812526329581, 0], [57781745730355, 0], [148424052281978, 0], [157592808184442, 0], [216368892725577, 0], [141559007955341, 0], [174413593787963, 0], [235891133761023, 0], [3732972626188, 0]], "8": [[221141860806003, 0], [36123205125711, 0], [97680988768935, 0], [178402231396292, 0], [115446378565206, 0], [196733287938126, 0], [18717536558175, 0], [195632149927636, 0], [34197829032991, 0]], "548": [[157859742386353, 0], [228618307530097, 0], [85330050953301, 0], [44305580640764, 0], [25899372098970, 0], [189420225212330, 0], [268783201016520, 0], [7937017180588, 0], [249034299800996, 0]], "549": [[159382898286074, 0], [82269580681026, 0], [31789991672154, 0], [56988653284071, 0], [209113704711986, 0], [25185700162851, 0], [109345658661121, 0], [37104371807816, 0], [193358987630109, 0]], "68": [[191883037772119, 0], [134048988423058, 0], [166096397672616, 0], [60739805448090, 0], [268780775278706, 0], [172428684338488, 0], [142997728750233, 0], [5573699077467, 0], [99717161316755, 0]], "598": [[73626526815737, 0], [156154376912942, 0], [224535443311422, 0], [115479554012501, 0], [165647483014294, 0], [154554598068071, 0], [259938903338867, 0], [244315513129867, 0], [183437191299703, 0]], "995": [[244834286599822, 0], [204723143203386, 0], [279413814527394, 0], [131509416500858, 0], [27435315347561, 0], [260089803669989, 0], [280799757573835, 0], [19284379361143, 0], [69930006118070, 0]], "869": [[217661619554123, 0], [212769708875054, 0], [269387810920710, 0], [97710429456377, 0], [163808813640929, 0], [110824576983566, 0], [267802375219696, 0], [244178549093346, 0], [102035672187244, 0]], "997": [[5938311269822, 0], [122672701799530, 0], [101885726759054, 0], [112997678087448, 0], [217852853922081, 0], [73527155697372, 0], [204781531458791, 0], [221777597986567, 0], [184392890390678, 0]], "996": [[83801144656602, 0], [245569686712364, 0], [202444708023930, 0], [49342311014680, 0], [10277662876241, 0], [9412819108114, 0], [5984884622983, 0], [72706689486936, 0], [85320613946479, 0]], "991": [[51081988890053, 0], [112660186918230, 0], [229943273563643, 0], [264502102263028, 0], [59643001474155, 0], [37076540404991, 0], [57624747088863, 0], [85965938787104, 0], [233000145522735, 0]], "990": [[12940166499802, 0], [232221793079678, 0], [239444693105246, 0], [178804064166282, 0], [67448213882852, 0], [215422387202798, 0], [55075265028784, 0], [145908890896020, 0], [181806527039250, 0]], "993": [[2839221362363, 0], [110916134640862, 0], [118638662262146, 0], [130396280939952, 0], [231398320965704, 0], [258530256337528, 0], [178723213714115, 0], [254480629341703, 0], [103871069795192, 0]], "868": [[212998366745759, 0], [239404225593087, 0], [127637570734300, 0], [49832411740051, 0], [29223081318322, 0], [233649947687018, 0], [271336871639132, 0], [271625968275486, 0], [191991616209571, 0]], "999": [[83664649271361, 0], [196891124975671, 0], [190929069767061, 0], [83642200335190, 0], [215607300554027, 0], [17070877116474, 0], [250149490935632, 0], [7929189226357, 0], [170604150069430, 0]], "998": [[158487554427411, 0], [193504818206038, 0], [20014148026659, 0], [100647691860375, 0], [114295264385994, 0], [57280414049607, 0], [112889733530722, 0], [93966060235927, 0], [23237151752606, 0]], "120": [[137387283553209, 0], [266556792456336, 0], [244251751826822, 0], [92663885881626, 0], [30413589565060, 0], [279885904832640, 0], [57406082474306, 0], [179393868166093, 0], [213819889523999, 0]], "121": [[235693830893909, 0], [77635925699955, 0], [82988765122758, 0], [230503921189246, 0], [47821647181771, 0], [30002422774018, 0], [234994170929492, 0], [252997660367089, 0], [48027960889732, 0]], "122": [[29014494616346, 0], [163196476589268, 0], [206188261063288, 0], [17846255098603, 0], [44360310692338, 0], [23323875556104, 0], [96474646794121, 0], [133671291672598, 0], [174680726923920, 0]], "123": [[221723789874952, 0], [148098382660057, 0], [43947907771084, 0], [154455562229214, 0], [127945866298545, 0], [255703952167792, 0], [96829577277660, 0], [70881067871258, 0], [114584779418548, 0]], "124": [[17338974883952, 0], [193005939241038, 0], [241300661337935, 0], [137854443303147, 0], [133785909483453, 0], [84099943510538, 0], [6250842932730, 0], [174658981276511, 0], [156405470158101, 0]], "125": [[276057291590012, 0], [232701617714941, 0], [154528703586360, 0], [260911520210070, 0], [143417171543067, 0], [75032930681593, 0], [174337514507020, 0], [219014625714985, 0], [42155039264878, 0]], "126": [[151104971187923, 2], [183844583085701, 2], [29703870881458, 2], [210594845447085, 2], [53948947832003, 2], [269523154569081, 0], [275599681799820, 0], [53144281574414, 0], [194711982767795, 0]], "127": [[105404282725226, 3], [230561673040360, 3], [91680834798236, 3], [77339400966713, 3], [56380838435139, 3], [23553067939291, 3], [48509137886744, 3], [35679657472641, 3], [188006520732254, 0]], "128": [[171098945128051, 0], [236994124667834, 0], [7054428826267, 0], [164926912776990, 0], [80834984647108, 0], [220186938439930, 0], [78382674787751, 0], [76448257796716, 0], [161085980018769, 0]], "129": [[187857449172128, 0], [45436693387266, 0], [243521731443727, 0], [272133945592105, 0], [105542174206481, 0], [121720237867624, 0], [70449591645895, 0], [164857353089822, 0], [238985092536633, 0]], "765": [[47439822833189, 0], [31369901015347, 0], [202751634120572, 0], [42605128687724, 0], [120213275541860, 0], [163633919557009, 0], [139098262270902, 0], [68458905770184, 0], [200831771422981, 0]], "1016": [[258707191432847, 0], [115211380480902, 0], [158441295474505, 0], [18125913459057, 0], [97392689262941, 0], [244713846249323, 0], [143949550782578, 0], [87930465998004, 0], [204412586482454, 0]], "1010": [[12897217067325, 0], [99172400403187, 0], [30538123560671, 0], [28201642756474, 0], [188070131479917, 0], [6345048288149, 0], [26878954307166, 0], [186663872508052, 0], [233210543258550, 0]], "1011": [[139413594571675, 0], [241981014955895, 0], [136373085963859, 0], [97327878694478, 0], [46846752214561, 0], [201632640315235, 0], [144295124513443, 0], [33076368184176, 0], [220944511563151, 0]], "414": [[153126443580335, 0], [66198824865164, 0], [97706693585179, 0], [254630426257007, 0], [214397316004105, 0], [69106861209545, 0], [184968214570908, 0], [170489109569114, 0], [243267740872715, 0]], "415": [[227076752192435, 0], [141281179613175, 0], [234318878793386, 0], [173695353292948, 0], [130448467769822, 0], [227207088127259, 0], [48552817409715, 0], [245803517664394, 0], [252145891384983, 0]], "416": [[238230592811658, 0], [180553309959282, 0], [198103526187002, 0], [184871639014882, 0], [105688684079174, 0], [190527257038611, 0], [281228065158087, 0], [253496669965359, 0], [71093198462017, 0]], "417": [[240450820473282, 0], [721884897837, 0], [217776637362145, 0], [83239466719034, 0], [16415576265976, 0], [180241262006450, 0], [57585947207338, 0], [189047547529844, 0], [190025988906261, 0]], "410": [[26041251090486, 0], [244174871536821, 0], [210588420203761, 0], [75156556650594, 0], [48529329930576, 0], [193913273877273, 0], [252785263563196, 0], [228700305070514, 0], [87510050521618, 0]], "411": [[39245062702786, 0], [104658217028762, 0], [82061358254413, 0], [170915526119325, 0], [27316519433679, 0], [70027193715239, 0], [27431885874434, 0], [125823138301811, 0], [91352696032121, 0]], "412": [[38062551343079, 0], [16096400646638, 0], [155200146186871, 0], [217721550529384, 0], [177990495848347, 0], [218366699318457, 0], [118790623829271, 0], [73144739811183, 0], [194075305114596, 0]], "413": [[83867433052807, 0], [79780012083846, 0], [231163624694072, 0], [74935787209260, 0], [72738060278115, 0], [143081186251265, 0], [941049016608, 0], [103618932691528, 0], [163940030565817, 0]], "920": [[169134074781856, 0], [55974360649000, 0], [123014033887241, 0], [135870703948063, 0], [108849161382379, 0], [279765926883430, 0], [120609077027092, 0], [67969842704657, 0], [26428493414867, 0]], "498": [[205254992177523, 0], [57899868445753, 0], [226881952461754, 0], [100091893545779, 0], [155570093593122, 0], [162853270771194, 0], [220478618290032, 0], [88999943594901, 0], [10226362167123, 0]], "922": [[25318617898575, 0], [40688799882915, 0], [10046371260590, 0], [76193160041943, 0], [224809261227603, 0], [174866796970509, 0], [112471995298302, 0], [109893799503658, 0], [27576953459242, 0]], "923": [[47263977357982, 0], [103759820132004, 0], [281172653318803, 0], [118336819058997, 0], [129061393711928, 0], [106438980694167, 0], [47543667883003, 0], [249319673679509, 0], [148165988076208, 0]], "418": [[94400238691, 0], [51530381718196, 0], [17722525578520, 0], [67639484699883, 0], [240395186948094, 0], [163288778177880, 0], [26356293574735, 0], [98439079044664, 0], [73077397803175, 0]], "419": [[56107891647246, 0], [208011171587211, 0], [126979465439142, 0], [19186725543459, 0], [15474329690374, 0], [149954586372381, 0], [214574104345002, 0], [227082428572702, 0], [230835866598482, 0]], "776": [[219661659209943, 0], [15652778580737, 0], [3952431833402, 0], [111840164479008, 0], [198864725395983, 0], [197202955259306, 0], [67820976911588, 0], [277954202864452, 0], [96094561821063, 0]], "499": [[269973481282988, 0], [87585749022966, 0], [52040480459497, 0], [230184109363893, 0], [122701330714826, 0], [198653333151822, 0], [190480562408635, 0], [43460021429462, 0], [224656040835166, 0]], "319": [[155211885754003, 0], [194237719596282, 0], [135796509114129, 0], [44056978815508, 0], [172173637511473, 0], [216711960829423, 0], [257755337872436, 0], [77288918900952, 0], [279809001546042, 0]], "318": [[220013405939212, 0], [171385470206740, 0], [22084251855823, 0], [83381013864227, 0], [176208558216674, 0], [62091330282356, 0], [40520977555942, 0], [223265289054335, 0], [170336270905007, 0]], "313": [[35078996717329, 0], [7504162272815, 0], [130650985993081, 0], [132445705270320, 0], [206527172560667, 0], [219363925073226, 0], [71154729733602, 0], [47730329788678, 0], [156032098494529, 0]], "312": [[220306611953270, 0], [71505955064303, 0], [35560899790586, 0], [185098890140182, 0], [256086824617679, 0], [88776900557902, 0], [169077838254880, 0], [94459402961327, 0], [9492672228090, 0]], "311": [[271152648693202, 0], [161069725533571, 0], [199418391271671, 0], [273439103332521, 0], [165286668966073, 0], [275414502107754, 0], [225396190969213, 0], [55905363482359, 0], [139767786277020, 0]], "310": [[167746553015911, 0], [7668846059996, 0], [201054061560459, 0], [188770800793066, 0], [154654340634905, 0], [191165501397471, 0], [68918821608079, 0], [95560167185857, 0], [50801776190922, 0]], "317": [[163851354638737, 0], [102257918632220, 0], [6737246652739, 0], [123986825906992, 0], [194505808356531, 0], [71850956803347, 0], [66938906359749, 0], [193564563317604, 0], [183202866084674, 0]], "316": [[274107863024695, 0], [142533675415922, 0], [151996323241756, 0], [9263058552683, 0], [95265724363039, 0], [201923039458132, 0], [216409208007658, 0], [207437441895387, 0], [126998012681289, 0]], "315": [[219090491172292, 0], [126330056018216, 0], [205347995897092, 0], [3507599279667, 0], [115753780881069, 0], [157076382693260, 0], [113935933828342, 0], [17597370934237, 0], [62341216794602, 0]], "314": [[222111669225360, 0], [70173905640369, 0], [100308772024066, 0], [183287988093334, 0], [163067704020474, 0], [235592184785831, 0], [238036755317991, 0], [241894348690662, 0], [196686015189741, 0]], "861": [[239919478283928, 0], [50620955558042, 0], [182976430494320, 0], [263490323478978, 0], [275975044437708, 0], [130003160121056, 0], [15538738830658, 0], [14913000102309, 0], [69441572015987, 0]], "921": [[163871462048896, 0], [237553845003222, 0], [167062785576422, 0], [2572488514896, 0], [198290512358578, 0], [160248512249830, 0], [77038199200985, 0], [158293273175202, 0], [242615525841237, 0]], "496": [[4290356380460, 0], [77999265442912, 0], [231723102525067, 0], [147865600539785, 0], [178588420661835, 0], [185245834150941, 0], [227633565459774, 0], [105426063514223, 0], [256702251404121, 0]], "832": [[57697072985172, 0], [83431062019521, 0], [123669350660827, 0], [185512070854764, 0], [261013806641767, 0], [151298925167163, 0], [269838982658625, 0], [70284659757587, 0], [160000379728421, 0]], "833": [[211850900264671, 0], [30111743706248, 0], [22683456786109, 0], [37692230264869, 0], [70679678822314, 0], [90757814703632, 0], [171210968957919, 0], [77311427663454, 0], [259596450513707, 0]], "830": [[238261016809924, 0], [151617263467596, 0], [123824994482925, 0], [137904293918488, 0], [15909144783063, 0], [59127372737378, 0], [29222447453146, 0], [238371214422254, 0], [197058461321568, 0]], "497": [[200578238783344, 0], [71490797202130, 0], [279606956908167, 0], [197607082970341, 0], [150106640812903, 0], [117450713523133, 0], [57319381623021, 0], [266897998702659, 0], [69433494031116, 0]], "836": [[276711906121935, 0], [78612873763667, 0], [85997608717630, 0], [201403587403166, 0], [34270910248946, 0], [264272937544078, 0], [54611633282426, 0], [277010113095225, 0], [149309024080430, 0]], "837": [[230122170923773, 0], [90837921567710, 0], [280765412526417, 0], [155243751075740, 0], [202888379300762, 0], [236621290867443, 0], [82168384532118, 0], [179086168553769, 0], [177298938910597, 0]], "834": [[99385228831731, 0], [249429332823397, 0], [201439997414672, 0], [221722046813798, 0], [134038556157315, 0], [275495013189316, 0], [135445050930594, 0], [82242332867363, 0], [142209872831190, 0]], "835": [[101468158767051, 0], [239058889181836, 0], [86401364355180, 0], [155736155575445, 0], [43859052102790, 0], [244660172475467, 0], [52998891960285, 0], [50402295365435, 0], [125716803338413, 0]], "838": [[145232912180213, 0], [46039998432148, 0], [255114573127729, 0], [229196195242056, 0], [193224112219267, 0], [68218129047550, 0], [252890849559036, 0], [106377323023914, 0], [181072114270846, 0]], "839": [[234784988312939, 0], [98533053775275, 0], [90178324460257, 0], [14448282645142, 0], [47378863215686, 0], [280895163980853, 0], [167056546013250, 0], [110212945260889, 0], [121235265511047, 0]], "808": [[253667718342305, 0], [18170132324855, 0], [1374005596564, 0], [132073991540942, 0], [28711481656074, 0], [183514286471840, 0], [49105557988587, 0], [153687605998875, 0], [74626897169688, 0]], "3": [[576160632516, 0], [49491869254012, 0], [209550023671729, 0], [165685717545385, 0], [264823757149228, 0], [122693089400452, 0], [111926040497747, 0], [51297479960470, 0], [46379503986110, 0]], "725": [[78214000022005, 0], [51935440227706, 0], [233090875274332, 0], [65190999471871, 0], [120266981417664, 0], [65579778943068, 0], [16076130941296, 0], [45788361265196, 0], [52417480742158, 0]], "368": [[280588097673796, 0], [204239549872550, 0], [218841814892454, 0], [68202327248933, 0], [94159818702434, 0], [240145511583341, 0], [272331336725670, 0], [197076569931702, 0], [73906526530062, 0]], "369": [[274235532371822, 0], [175364682299373, 0], [51193105699014, 0], [233191394622816, 0], [130998554873599, 0], [201476233541846, 0], [188027648974095, 0], [35102558294373, 0], [30676262897195, 0]], "366": [[118694864343480, 0], [225953942132187, 0], [224381093007945, 0], [118264806293568, 0], [207409410810863, 0], [69272693714280, 0], [98479487741726, 0], [217216907463855, 0], [274011306222343, 0]], "367": [[78214263239971, 0], [73405169944672, 0], [7343563235607, 0], [14803245351499, 0], [85068284767523, 0], [69482146857275, 0], [110851119353392, 0], [88359758699231, 0], [183678581269070, 0]], "364": [[242445490078561, 0], [64391492971697, 0], [161935035707705, 0], [55115538424228, 0], [74327211088644, 0], [158116765870490, 0], [38724510455844, 0], [194386600221989, 0], [100995287667405, 0]], "365": [[102415579564279, 0], [36124082947368, 0], [36254596575048, 0], [161721819885226, 0], [142168374878068, 0], [86160099470294, 0], [195876390265671, 0], [20860738525296, 0], [204728482601783, 0]], "362": [[58324979208571, 0], [116913478763797, 0], [108345528894603, 0], [35660032481711, 0], [156104950837948, 0], [199811020767880, 0], [123563686872370, 0], [2505410443058, 0], [79052865188674, 0]], "363": [[15497930043566, 0], [167860938909078, 0], [229460367677716, 0], [228080932906123, 0], [179440372781741, 0], [122861463464349, 0], [215847532937568, 0], [145830981915192, 0], [203382241702033, 0]], "360": [[174235134535701, 0], [196332861427919, 0], [124027611429370, 0], [118983493822866, 0], [186371379980172, 0], [57969121574953, 0], [232431557965643, 0], [79275808988005, 0], [263370770277001, 0]], "361": [[21771616984145, 0], [269451086256712, 0], [139640400001218, 0], [128046252124257, 0], [63867773219323, 0], [140342098019860, 0], [278009119808859, 0], [67411705640598, 0], [244960518686835, 0]], "959": [[131952582094144, 0], [274349626652004, 0], [250275579795329, 0], [42648252439733, 0], [26183070981538, 0], [186920315786126, 0], [32790685694319, 0], [53324353557584, 0], [264443647351422, 0]], "952": [[56014563642791, 0], [261501260677456, 0], [212766223157259, 0], [249776916635259, 0], [99631907477722, 0], [46156643673697, 0], [227853479207029, 0], [19027777632540, 0], [33462609390934, 0]], "882": [[181131605618630, 0], [83798384185288, 0], [249017277460857, 0], [262344891983578, 0], [235716903541773, 0], [129749720919703, 0], [215618294608507, 0], [26570133376121, 0], [230839140214651, 0]], "380": [[127614445732295, 0], [71119284931946, 0], [278704739969986, 0], [20832882408584, 0], [394052948885, 0], [258108759870293, 0], [250427575197679, 0], [64301904313536, 0], [221942469948005, 0]], "381": [[125494281114456, 0], [70062951378628, 0], [152503978168515, 0], [162995030055482, 0], [273498733786483, 0], [109885189873698, 0], [213606655749356, 0], [178225609624896, 0], [27866640426672, 0]], "382": [[31008125954969, 0], [150239086980167, 0], [142897366676115, 0], [99297722313535, 0], [74966944607890, 0], [34719546991470, 0], [156909991354149, 0], [159779746129154, 0], [169396975412506, 0]], "383": [[162337809602060, 0], [76786804717084, 0], [103312244659243, 0], [7175097620805, 0], [144332232990180, 0], [163135114083104, 0], [196434574526705, 0], [128277006154965, 0], [55936925172271, 0]], "384": [[91840642301697, 0], [148073410371756, 0], [11144006219138, 0], [176080007617583, 0], [114761145720401, 0], [39601045245864, 0], [22590510883177, 0], [164137909946105, 0], [62600206721197, 0]], "385": [[191293984167559, 0], [95789320762562, 0], [130267541078413, 0], [260587023028166, 0], [27730199399671, 0], [55683876199292, 0], [18679365213027, 0], [114787532166111, 0], [127416850215776, 0]], "386": [[26985798042580, 3], [228031197616412, 3], [106094731094296, 3], [61381279618647, 3], [164326590755793, 3], [154978791400628, 3], [1503479700591, 3], [224160169669456, 3], [252024707783482, 0]], "387": [[213259399745857, 0], [135369026994443, 0], [243868359494083, 0], [242628909623549, 0], [132489449889876, 0], [119136444502633, 0], [137210356087446, 0], [112984193849072, 0], [93940836420953, 0]], "388": [[36327788164084, 0], [248034855590303, 0], [33979523700262, 0], [103662548742730, 0], [55086094836233, 0], [274019585349365, 0], [98562717503945, 0], [15480049286226, 0], [63689034779600, 0]], "389": [[43072735690252, 0], [141395512253470, 0], [222701831809538, 0], [252828880167561, 0], [168330275597064, 0], [260097497504197, 0], [25740017626537, 0], [265822063665663, 0], [14584934673994, 0]], "784": [[209547390667590, 0], [124115060797080, 0], [10878213630669, 0], [81686352356987, 0], [213580802491782, 0], [157711972379714, 0], [71160289304694, 0], [107599095636159, 0], [259514598844063, 0]], "785": [[274156560873057, 0], [218837541605794, 0], [150329650798794, 0], [215994155282649, 0], [65093464658827, 0], [247766502825644, 0], [59931712947928, 0], [6990071944175, 0], [169190823899263, 0]], "786": [[196016638327646, 0], [146031206393902, 0], [196436544022847, 0], [267198876811667, 0], [112194666176459, 0], [58040717561411, 0], [175110673595569, 0], [85290773463630, 0], [46158175753511, 0]], "787": [[255607468007911, 0], [96661634883378, 0], [35827153244744, 0], [124625922835131, 0], [83349282376544, 0], [237051200086682, 0], [111718635600943, 0], [220638077165183, 0], [112156433890931, 0]], "780": [[14078925682295, 0], [116465151030686, 0], [111831673348979, 0], [236291037049033, 0], [33759912664918, 0], [228317407998377, 0], [5697162819426, 0], [37644305383688, 0], [197143339221759, 0]], "781": [[7503564770610, 0], [11981976641307, 0], [172950690013190, 0], [187557583998076, 0], [221244135661653, 0], [274197672787899, 0], [68492713305536, 0], [191783070354180, 0], [102349389616101, 0]], "782": [[78840841725920, 0], [127285640761063, 0], [77697264757588, 0], [216496030927798, 0], [22044532784600, 0], [50671410937204, 0], [68644507635150, 0], [8904044355944, 0], [151123205030748, 0]], "783": [[231376836858872, 0], [101586544137567, 0], [231826592508374, 0], [114860663893373, 0], [273641702297376, 0], [271343824435805, 0], [51615182947692, 0], [75425457323908, 0], [12068185818280, 0]], "788": [[279198323510585, 0], [204402117325581, 0], [269672480493216, 0], [71539704590243, 0], [256247070710753, 0], [82752328789617, 0], [40675854660972, 0], [40782105277055, 0], [45272396122070, 0]], "789": [[74803541608705, 0], [279863651890220, 0], [258111271440561, 0], [212186321264126, 0], [211342038991913, 0], [164147306416869, 0], [126560340739605, 0], [226653265564340, 0], [141977394156002, 0]], "860": [[260352526689174, 0], [172549295697540, 0], [257128866409377, 0], [140275155568850, 0], [150503626874504, 0], [3950718723, 0], [71078022293293, 0], [279559828297957, 0], [187730931034775, 0]], "605": [[191143076297658, 0], [26422076428783, 0], [89178148606228, 0], [151959082920043, 0], [104066965077224, 0], [162767483323836, 0], [102561340490000, 0], [242130955568110, 0], [234061350945198, 0]], "579": [[247402702477435, 0], [110170397614691, 0], [111426308657171, 0], [96607984653752, 0], [8483029948345, 0], [5014072913546, 0], [183877386379590, 0], [101982417433363, 0], [109840601913336, 0]], "578": [[215948316685301, 0], [95259201791773, 0], [37508980640304, 0], [215416420634052, 0], [227331982118692, 0], [204572939164778, 0], [200282992101923, 0], [211376688374568, 0], [276415933169116, 0]], "604": [[90048734668911, 0], [49103165260102, 0], [220253383117857, 0], [37611728788054, 0], [99864570536416, 0], [149498356036859, 0], [212405869801095, 0], [193973222995553, 0], [140665735140767, 0]], "573": [[217126469074256, 0], [222904488396744, 0], [166886776229872, 0], [136683739291279, 0], [207172495063064, 0], [212698813291836, 0], [115522388162386, 0], [120949401341399, 0], [119123044066732, 0]], "572": [[165363614330191, 0], [216959544150274, 0], [242397773555172, 0], [66437829301583, 0], [5522020718632, 0], [168836185199843, 0], [5637126408015, 0], [97102408690878, 0], [131570135139120, 0]], "571": [[202082012549289, 0], [231674638337889, 0], [95733703136273, 0], [204750290226836, 0], [75485958863083, 0], [177173895339769, 0], [154765964102985, 0], [134577935157560, 0], [261689133175848, 0]], "570": [[9678528180255, 0], [133274558400844, 0], [203182468261095, 0], [206246852310921, 0], [168219043875674, 0], [2622722709467, 0], [118256828915634, 0], [5158303064690, 0], [112282920895485, 0]], "577": [[157950289735100, 0], [117304393919650, 0], [57269743659578, 0], [43553789259108, 0], [251550493393205, 0], [147145208517741, 0], [154239535347314, 0], [94211971554700, 0], [187643194612055, 0]], "576": [[223182936325797, 0], [240326564248275, 0], [67351903586702, 0], [208548771386269, 0], [31128276589055, 0], [259931245440166, 0], [223161853468120, 0], [54483015777591, 0], [227245713175310, 0]], "575": [[33968691873891, 0], [3203005122188, 0], [147731333065949, 0], [226017669185384, 0], [69706863704134, 0], [34377911701736, 0], [163304084139476, 0], [135272355363468, 0], [204191440840156, 0]], "574": [[220758184178698, 0], [173997710406462, 0], [91559073521616, 0], [269733177304454, 0], [175548809400524, 0], [136768711364923, 0], [97743825368369, 0], [167890515821464, 0], [165314689578637, 0]], "60": [[123448500094445, 0], [230130662368495, 0], [239604897956222, 0], [236544791204767, 0], [127039396759652, 0], [155087437434575, 0], [164010795103576, 0], [146218554240750, 0], [168956269496399, 0]], "61": [[137865122392796, 0], [263809041274065, 0], [167038437249113, 0], [243706551796486, 0], [233096477856887, 0], [143493085172142, 0], [113383310715171, 0], [244013895571481, 0], [186815789861657, 0]], "258": [[173603367774088, 0], [119187658001179, 0], [238325267754105, 0], [182157732939546, 0], [18633488926445, 0], [173242216202421, 0], [105988409708018, 0], [218128941621080, 0], [11555062316214, 0]], "259": [[265768954806791, 0], [108819861853676, 0], [49838540834276, 0], [79217705851532, 0], [133257309958236, 0], [6269581723914, 0], [101355531650075, 0], [81199867775930, 0], [154384386542940, 0]], "64": [[258548495389353, 0], [175845785611402, 0], [881725491689, 0], [37962037859865, 0], [120604620005675, 0], [220004660299946, 0], [132462990872162, 0], [198671610694357, 0], [265755227129241, 0]], "65": [[209522664107585, 0], [147633735206013, 0], [61187714060267, 0], [168499035014731, 0], [120141479453702, 0], [261602307648846, 0], [114430528292232, 0], [237357994325331, 0], [164086132531066, 0]], "66": [[129956089718270, 0], [127214393263701, 0], [169790641374066, 0], [73969275435297, 0], [73487863101223, 0], [273534025491389, 0], [88362224933444, 0], [52398874391741, 0], [13075310704202, 0]], "67": [[198579585690956, 0], [262218698857387, 0], [17336400065593, 0], [278801339066669, 0], [233216430812440, 0], [18120144305603, 0], [109145862371000, 0], [143136261399053, 0], [102980934433733, 0]], "252": [[200821473863136, 0], [146475008024900, 0], [137575466981890, 0], [131153783106707, 0], [149814661189118, 0], [27866764924375, 0], [133757837877026, 0], [243807823324022, 0], [187808887260924, 0]], "69": [[208422747642840, 0], [94329218530199, 0], [113078383715499, 0], [145825363621927, 0], [279256093249152, 0], [232905325769996, 0], [207163276562555, 0], [196248077112007, 0], [104102703009070, 0]], "250": [[73793053046906, 0], [142359603471125, 0], [3603852851932, 0], [28454193364282, 0], [171470191641353, 0], [217396052970524, 0], [195921730311652, 0], [126222801836918, 0], [138079783777371, 0]], "251": [[265586648969261, 0], [230449954332838, 0], [184020971639101, 0], [24907952516518, 0], [179598721182611, 0], [106529399359589, 0], [222372975430180, 0], [210193148304113, 0], [264996878423714, 0]], "256": [[138404782816504, 0], [11420149976337, 0], [16213956134004, 0], [82954540206099, 0], [200243969975117, 0], [12428797057462, 0], [62971076721220, 0], [98586222915332, 0], [247925415295325, 0]], "257": [[185636730897917, 0], [242122289617478, 0], [261696137938446, 0], [261313157067792, 0], [152521189385581, 0], [251870286485434, 0], [178078603744819, 0], [165355413979741, 0], [177199649761525, 0]], "254": [[187247602195587, 0], [48864928419340, 0], [68621325373123, 0], [272005485542163, 0], [115743937924296, 0], [270851743958484, 0], [846948850607, 0], [178847863915465, 0], [40876723975889, 0]], "255": [[267469238448072, 0], [174344894351629, 0], [230930110014949, 0], [31191244092504, 0], [84102083707222, 0], [110385212554726, 0], [156332781666513, 0], [35317210522113, 0], [17890456821551, 0]], "603": [[65698321266438, 0], [92455024649551, 0], [58663095504020, 0], [201619067948628, 0], [183200012085057, 0], [68538343982852, 0], [69654736353022, 0], [178560075491703, 0], [37866884182538, 0]], "602": [[22187667226588, 0], [131710732463382, 0], [24533038114741, 0], [77062882683357, 0], [275418786659267, 0], [76533668876444, 0], [229106275984588, 0], [174009219978526, 0], [7398040608845, 0]], "939": [[133914402738943, 0], [170060239950418, 0], [25323795955051, 0], [57166996193796, 0], [227397903808705, 0], [85802511227625, 0], [107102391880369, 0], [280521581279021, 0], [100068385571841, 0]], "731": [[207034642349432, 0], [67436882901737, 0], [156466798788194, 0], [35691091246010, 0], [44536926954240, 0], [257894110823180, 0], [225492390091766, 0], [138985914888960, 0], [11448576189691, 0]], "730": [[201979839324675, 0], [106623993361372, 0], [243653108974017, 0], [97017899914833, 0], [131609390095980, 0], [266777167912137, 0], [51717919285750, 0], [88333363581660, 0], [278692933203472, 0]], "733": [[206678716691046, 0], [173614110509736, 0], [221073857189208, 0], [134255321237571, 0], [203563420507342, 0], [90197839597971, 0], [166790832549261, 0], [107562205651961, 0], [143232959991458, 0]], "732": [[238738931844706, 0], [90028159464180, 0], [65017794049312, 0], [173176377101566, 0], [142479321354338, 0], [260617134862430, 0], [68199169980915, 0], [254931035353091, 0], [256281210977348, 0]], "735": [[141910888740460, 0], [188730191699125, 0], [98184845138929, 0], [212541212555643, 0], [216135953294208, 0], [154315020413056, 0], [50141075581695, 0], [218955150561405, 0], [198263579053814, 0]], "734": [[117461598524287, 0], [248953294229788, 0], [195638832632449, 0], [237146222403119, 0], [97488524563382, 0], [257536306455919, 0], [33166357847224, 0], [191849789712289, 0], [91468169883501, 0]], "508": [[4966661989353, 0], [66084143086073, 0], [268416958049904, 0], [69070310446209, 0], [253331970874439, 0], [272953460476359, 0], [138064794298452, 0], [201863299207771, 0], [72666091355764, 0]], "509": [[141188150999744, 0], [49959255957397, 0], [62580765008190, 0], [100709334665937, 0], [50424679734156, 0], [280169599306300, 0], [59327918308479, 0], [136517193531686, 0], [77265271443193, 0]], "506": [[116231835232364, 0], [264319346594537, 0], [98534012153538, 0], [188378535760161, 0], [136434916133504, 0], [239090174247229, 0], [98876232243723, 0], [184645066153216, 0], [238382214344606, 0]], "507": [[148138963982468, 0], [134885902733888, 0], [18255054960181, 0], [88386421629598, 0], [124779046886121, 0], [135260003682586, 0], [233318655990724, 0], [12526316382963, 0], [160222112249335, 0]], "504": [[216262955580927, 0], [92671835494717, 0], [279007339057855, 0], [24288121836779, 0], [60734046710017, 0], [236844628431981, 0], [31361690733178, 0], [41548996183879, 0], [241007378683807, 0]], "505": [[184497093305356, 0], [25504907512301, 0], [113287732566200, 0], [198212558217158, 0], [275591869510235, 0], [100677784262503, 0], [91833880694027, 0], [62852858014837, 0], [63355264192171, 0]], "502": [[190963675409988, 0], [227703905463939, 0], [111356079067944, 0], [79345136023247, 0], [33214611178990, 0], [259326844522058, 0], [79827976642326, 0], [136653693098115, 0], [198424827909624, 0]], "503": [[222037720662951, 0], [268075306408500, 0], [201073690762700, 0], [248445633064618, 0], [105350616317479, 0], [55940537774671, 0], [189367119094280, 0], [245069152055789, 0], [247546764695285, 0]], "500": [[124647623587745, 0], [196176280091414, 0], [181998809737514, 0], [147923831115429, 0], [95624734300709, 0], [114485763332164, 0], [198005627597996, 0], [10517856164143, 0], [113299017612781, 0]], "501": [[72822391547291, 0], [69823105200816, 0], [40139424277491, 0], [238837667623966, 0], [218736267436420, 0], [159612842525279, 0], [33693485478243, 0], [255490867067866, 0], [261297772660289, 0]], "630": [[50393306055171, 0], [48663244691236, 0], [163332815867867, 0], [123093870890699, 0], [77975860396337, 0], [168110705973539, 0], [158308803419916, 0], [243387364465325, 0], [153804325957222, 0]], "631": [[31533194471713, 0], [265431759332405, 0], [162630630738801, 0], [50713100831057, 0], [136644168131789, 0], [36728525823890, 0], [84888388108641, 0], [76794135921528, 0], [73751509784087, 0]], "632": [[189769250986235, 0], [24280387149319, 0], [112558511148416, 0], [76724797476431, 0], [197217517572813, 0], [73763700194159, 0], [234108646159135, 0], [215551130167154, 0], [132431626565677, 0]], "633": [[157422047619435, 0], [194625717283599, 0], [42090781155831, 0], [262033543994056, 0], [166191523941018, 0], [161979329571196, 0], [27296481974295, 0], [199800260013532, 0], [203752208821689, 0]], "469": [[54006646283491, 0], [269673266425446, 0], [209932884998357, 0], [53744765808159, 0], [39766379619041, 0], [249742220132721, 0], [92444830413835, 0], [206315737636427, 0], [90999031732008, 0]], "468": [[143410137828444, 0], [2572663294422, 0], [134665340149796, 0], [80771553770260, 0], [96665223667362, 0], [72262300667333, 0], [143698601949983, 0], [213492060723511, 0], [146035262561640, 0]], "636": [[191597017546939, 0], [193132341164071, 0], [190795445240833, 0], [199679671582263, 0], [214252864215538, 0], [50976716233409, 0], [56653484333190, 0], [246128067855825, 0], [224192154978722, 0]], "637": [[35167097941404, 0], [272708169608325, 0], [165042879943266, 0], [57216903396120, 0], [242123897795243, 0], [47324219065314, 0], [192833508342621, 0], [66964817618159, 0], [48083631043247, 0]], "465": [[238229435277617, 1], [123074189462639, 1], [205363766069176, 1], [190672937462699, 1], [18704102791263, 1], [200437113302134, 1], [233988022946460, 0], [80798123267633, 0], [242324699578605, 0]], "464": [[255460915786645, 0], [125139810392679, 0], [64744266667524, 0], [168576615720332, 0], [163045673320931, 0], [141231663247471, 0], [25131945636134, 0], [128307994715026, 0], [148710900549681, 0]], "467": [[74275879816116, 0], [88257051089473, 0], [150468999902207, 0], [66442280700180, 0], [252178206439556, 0], [190409237892324, 0], [151513556845015, 0], [235569051001987, 0], [68026563931098, 0]], "466": [[29627548685, 0], [6694995004397, 0], [54288460788154, 0], [31120181220773, 0], [173338654891656, 0], [28187785594142, 0], [237443043253408, 0], [153506471118173, 0], [112123632529589, 0]], "461": [[188062890447722, 0], [52825476544401, 0], [174816595633127, 0], [162790613035173, 0], [175781674594125, 0], [9550790725610, 0], [95840714378635, 0], [22419929229150, 0], [11538955315581, 0]], "460": [[64957093759193, 0], [124696734603334, 0], [194217038436881, 0], [38019472555518, 0], [226190450219185, 0], [105822081363939, 0], [189109165513583, 0], [6066815692039, 0], [138078508369700, 0]], "463": [[231380176715479, 0], [47166464320069, 0], [89007192670404, 0], [143790153375525, 0], [216413380507893, 0], [269052248571582, 0], [189081591814416, 0], [225682576477250, 0], [165008902127985, 0]], "462": [[186098005259128, 0], [193314369910420, 0], [224584558397686, 0], [2604700966907, 0], [125812627918166, 0], [247043973475938, 0], [152873851469985, 0], [149884506069692, 0], [67058736963858, 0]], "901": [[128626203588743, 0], [61960292977019, 0], [160391678763030, 0], [170662883449093, 0], [225044880734300, 0], [115482765399465, 0], [103487876889757, 0], [23365268277871, 0], [260161193595849, 0]], "168": [[281001179466767, 0], [186982804132966, 0], [27825084573719, 0], [250260747223083, 0], [231897948163423, 0], [193279517971594, 0], [163190484266465, 0], [113096942222059, 0], [246708286209003, 0]], "169": [[228992497748066, 0], [171109567442992, 0], [157758565202315, 0], [260247775615179, 0], [247907888206397, 0], [44781833058145, 0], [70400005534623, 0], [96947599305597, 0], [51260022985446, 0]], "164": [[47103163937595, 0], [139954760346622, 0], [139012866360905, 0], [97062856856273, 0], [97078001380163, 0], [114499614821289, 0], [217908707893883, 0], [249310105590357, 0], [26465700789803, 0]], "165": [[109605487116647, 0], [170426404104379, 0], [198922510020414, 0], [194509377755418, 0], [61735301922840, 0], [166445980122659, 0], [194670248178719, 0], [180878011115169, 0], [186889128585068, 0]], "166": [[184904701767026, 0], [106128658614429, 0], [44381792867566, 0], [143379979316825, 0], [73644200396795, 0], [23542276772446, 0], [160657166366453, 0], [10782235791437, 0], [87212179088193, 0]], "167": [[118201826567559, 0], [27374860970654, 0], [126702002515715, 0], [55290275667263, 0], [165514480178450, 0], [142162964513608, 0], [123493787535175, 0], [11176253669609, 0], [105543522228318, 0]], "160": [[121039735686695, 0], [100691790815671, 0], [216728565440782, 0], [207313429267255, 0], [133708672461554, 0], [135955620566133, 0], [3466445951998, 0], [191655251745213, 0], [239212043626424, 0]], "161": [[130726833966621, 0], [266092382738409, 0], [112191364946110, 0], [261545496437959, 0], [71552012033018, 0], [225341726736075, 0], [176901823079844, 0], [241696526061301, 0], [200244205706517, 0]], "162": [[12633050284725, 0], [126763493861, 0], [194524542454795, 0], [53622611335209, 0], [17864655971829, 0], [55002986991618, 0], [15212430342550, 0], [281130996671402, 0], [210647630373836, 0]], "163": [[203162193142029, 0], [272079620107679, 0], [80912132342579, 0], [269470864377403, 0], [244701137798877, 0], [182386107109209, 0], [130169535254532, 0], [276922556076944, 0], [47530964211628, 0]], "964": [[251335175322282, 0], [224415180361043, 0], [192536546219611, 0], [62624851552878, 0], [74880979109614, 0], [179771722955559, 0], [24069464726671, 0], [243794957406204, 0], [173928181539473, 0]], "965": [[189657297138360, 0], [260093402738247, 0], [145892585781315, 0], [252648134967345, 0], [221066914116457, 0], [41039013727446, 0], [164985314806893, 0], [214129763208852, 0], [67474299169501, 0]], "966": [[93414760884576, 0], [224019509611155, 0], [237532075817383, 0], [232496571069049, 0], [49300138689385, 0], [135464064039750, 0], [194844024270027, 0], [205368051356767, 0], [22242756673260, 0]], "967": [[256208470874749, 0], [115361105773942, 0], [47859308197703, 0], [198602721941917, 0], [73954323441339, 0], [5030271006597, 0], [52896664288200, 0], [89281083354874, 0], [95001123020148, 0]], "960": [[79152685886540, 0], [27159061067600, 0], [62833922931579, 0], [27083621602631, 0], [66462922400638, 0], [273752957899834, 0], [70558813716108, 0], [38712935602442, 0], [193522007638305, 0]], "961": [[69936373006698, 0], [276436847287328, 0], [81483252443412, 0], [119246885291825, 0], [100620467845351, 0], [185326919854523, 0], [119115377407704, 0], [267254603538800, 0], [115514554223341, 0]], "962": [[131141361736610, 0], [160724453170044, 0], [271670062441813, 0], [277184278811272, 0], [12921660671250, 0], [123125861016447, 0], [229209545069792, 0], [32142537865322, 0], [146928853195267, 0]], "963": [[256772611781353, 0], [9257730038388, 0], [102547656400134, 0], [155370796385109, 0], [8542964947626, 0], [111539164299941, 0], [250773566915239, 0], [272676880305340, 0], [16046072162896, 0]], "968": [[185334358880257, 0], [85290196549124, 0], [25607779186400, 0], [167252582688864, 0], [280791794989926, 0], [157082606809027, 0], [269434688459275, 0], [227034308602033, 0], [234760753904812, 0]], "969": [[225480828327124, 0], [195431093887067, 0], [125425264811328, 0], [136914876736243, 0], [206241032408838, 0], [211972544574959, 0], [176762914695789, 0], [191873204900041, 0], [219559713777042, 0]], "936": [[244057020055402, 0], [13672542727189, 0], [209779190869194, 0], [168057375215489, 0], [179314878879881, 0], [66526395274260, 0], [192161775164769, 0], [44624444845537, 0], [182063431889206, 0]], "935": [[78602885496806, 0], [206475468691724, 0], [83107352589985, 0], [279854304395201, 0], [175428078850220, 0], [171003126966520, 0], [3504804980419, 0], [148058420207414, 0], [109031233342004, 0]], "934": [[232674784892286, 0], [185946683502711, 0], [173772553161670, 0], [90737589007308, 0], [87471275247012, 0], [135419094527999, 0], [244226161613892, 0], [281103622879739, 0], [264611540224300, 0]], "908": [[109472452549329, 0], [173982787945842, 0], [24600417523096, 0], [160250908589037, 0], [111095447384317, 0], [205659904146387, 0], [238289734540731, 0], [199112500146009, 0], [172036846289103, 0]], "909": [[189310713745757, 0], [212929278014463, 0], [189553525479405, 0], [148876369100780, 0], [152936802297769, 0], [129602430287378, 0], [153636102307168, 0], [188641306671442, 0], [115286666470674, 0]], "600": [[178922614756861, 0], [182119379322382, 0], [102594776214813, 0], [164101502089920, 0], [62038361510617, 0], [112799009617010, 0], [54401350751926, 0], [119403518421198, 0], [176892413728954, 0]], "878": [[252260948217600, 0], [84772228141183, 0], [54146340311732, 0], [171522748475039, 0], [111608228468754, 0], [155379574425175, 0], [55136715214697, 0], [13430273955098, 0], [104972675088474, 0]], "879": [[224631775692901, 0], [274488457550284, 0], [185814655576683, 0], [71314327025423, 0], [123618832413522, 0], [68920329983350, 0], [242884571789457, 0], [8217499650267, 0], [210316152651077, 0]], "876": [[99365708514812, 0], [130114079590640, 0], [154064390747526, 0], [199867939369851, 0], [161010767657556, 0], [87460173972864, 0], [27776553747416, 0], [155964017509660, 0], [97940146460671, 0]], "877": [[194607913035482, 0], [280403165327905, 0], [114748810700567, 0], [258925519870530, 0], [177036832743884, 0], [128796028073189, 0], [189212361244359, 0], [143526187586862, 0], [276412450346797, 0]], "874": [[115040859728306, 0], [1551226914017, 0], [51637131902726, 0], [131540229018730, 0], [177719102116846, 0], [258020309717940, 0], [195012847692354, 0], [274198102976888, 0], [230332628750083, 0]], "875": [[113739446686535, 0], [193257989506609, 0], [179869065727504, 0], [164676508321688, 0], [140552693644405, 0], [163668684818993, 0], [88902652740361, 0], [130706620663075, 0], [243913350040351, 0]], "872": [[209096849036046, 0], [220877584379048, 0], [148879890358891, 0], [180728370207099, 0], [56046073404053, 0], [91494849351689, 0], [85194056948256, 0], [276645234131510, 0], [194021666968056, 0]], "873": [[264436846361233, 0], [143244162917321, 0], [101899313500430, 0], [126915671891227, 0], [108559413716328, 0], [259944124286271, 0], [49726992089545, 0], [1456538771822, 0], [264655399307783, 0]], "870": [[8594971275165, 0], [235012370498726, 0], [274721699891796, 0], [174424961760765, 0], [15736478949100, 0], [272976150591545, 0], [205162569515263, 0], [15920651774374, 0], [155339706002802, 0]], "871": [[206069484952929, 0], [249536174725423, 0], [220887707016475, 0], [178759914627177, 0], [61376709443629, 0], [105898201142819, 0], [136870000609795, 0], [19507497613016, 0], [215727636591422, 0]], "9": [[79897532520454, 0], [59155704974113, 0], [41737026582055, 0], [229517045145992, 0], [230260353757398, 0], [70094690576098, 0], [21638990033491, 0], [173772464571409, 0], [183854162650130, 0]], "890": [[183612991508541, 0], [275844733105253, 0], [10422620161087, 0], [209097536790443, 0], [19699697446844, 0], [49393026537843, 0], [48345111285596, 0], [15535625201197, 0], [43826841585880, 0]], "891": [[111948428189106, 0], [19386943035441, 0], [252377959465357, 0], [150809172323800, 0], [182585320107097, 0], [36016000136536, 0], [18467261292259, 0], [101191993900913, 0], [270886773377357, 0]], "892": [[91327456029931, 0], [141712851479067, 0], [251318527680218, 0], [96323858742554, 0], [104915956421283, 0], [77955072984602, 0], [253541252835791, 0], [157057743817487, 0], [74245551843643, 0]], "893": [[3700548739413, 0], [9825723334648, 0], [112172371538022, 0], [88163844531750, 0], [15892105127768, 0], [100892195925732, 0], [117795045843375, 0], [84323110570286, 0], [44700459749004, 0]], "894": [[47445620335898, 0], [258495677049244, 0], [112869639633172, 0], [157066045005888, 0], [57265389525290, 0], [270817074266270, 0], [33415749688176, 0], [273737068768327, 0], [109269689272418, 0]], "647": [[40374918045110, 0], [143414828456718, 0], [146570051985959, 0], [1040225792562, 0], [167485663068754, 0], [19826641741376, 0], [260186951615312, 0], [111179627923140, 0], [264364833491924, 0]], "896": [[222860191926316, 0], [237834709318519, 0], [113197457243072, 0], [108117171234690, 0], [98653391028025, 0], [115708856630740, 0], [53417482100116, 0], [124281218064102, 0], [279496153277524, 0]], "897": [[6858306663239, 0], [135625411591756, 0], [133682944348897, 0], [32669562060217, 0], [267299144854575, 0], [227212413134640, 0], [220196226116209, 0], [87037379021498, 0], [173561854865748, 0]], "898": [[195716720946800, 0], [27058843073573, 0], [10896984881058, 0], [99107415981050, 0], [165101782514007, 0], [143404536205913, 0], [205641178191782, 0], [142162002560814, 0], [95832522755903, 0]], "899": [[280982049585137, 0], [165113940455737, 0], [212211727402834, 0], [247504915970077, 0], [198046739806788, 0], [112599925833554, 0], [107398171865085, 0], [174470240731335, 0], [64470666777132, 0]], "646": [[206361522460305, 0], [68207466771498, 0], [159159842056263, 0], [52228332271811, 0], [57779312312404, 0], [178942654055750, 0], [45166901609357, 0], [207525709261729, 0], [1300038222663, 0]], "649": [[34795450643774, 0], [237363991418872, 0], [233549864310875, 0], [181841918081039, 0], [48609112554291, 0], [271435242647022, 0], [255586748354120, 0], [172194237012812, 0], [29016779703358, 0]], "648": [[10362233968410, 0], [114434082872920, 0], [85813722891671, 0], [17758083623522, 0], [102638825877858, 0], [258565677566454, 0], [56118654821651, 0], [186461569873335, 0], [212272703921580, 0]], "357": [[271331623119747, 0], [33078917365700, 0], [156695103161322, 0], [137476296647591, 0], [92202418729987, 0], [28820218848077, 0], [178250595069157, 0], [166521897104621, 0], [196611968830673, 0]], "356": [[55367519139355, 0], [146875874083150, 0], [121267023477813, 0], [247470988596136, 0], [155146710363986, 0], [125118390943474, 0], [153217728071919, 0], [236997157714348, 0], [123984890199345, 0]], "355": [[75253913134871, 0], [185014796817099, 0], [45626512882586, 0], [275308745391714, 0], [59265352000798, 0], [85064721831583, 0], [167209035166434, 0], [97515974859880, 0], [205995685583965, 0]], "354": [[63384727142798, 0], [72007650015826, 0], [13492174683618, 0], [181465821571452, 0], [126142555776150, 0], [156080147383239, 0], [267852462148340, 0], [169257013766967, 0], [57964360326515, 0]], "353": [[84699475061971, 0], [6575942700095, 0], [196622683123046, 0], [96570232341974, 0], [207682150955052, 0], [175646759779799, 0], [191146163804791, 0], [253395754844419, 0], [63313926827969, 0]], "352": [[173802070917770, 0], [90342373164657, 0], [14565389013763, 0], [97651770793576, 0], [123003198890555, 0], [127786044229038, 0], [231082720083568, 0], [95281949705146, 0], [237026237536620, 0]], "351": [[138049654352839, 0], [32768613745241, 0], [179137744456440, 0], [3535764064223, 0], [75423920950713, 0], [134788097774616, 0], [41992729224024, 0], [243908599936189, 0], [281297375310083, 0]], "350": [[36741823907381, 0], [270287290816940, 0], [264848560500957, 0], [262154401960744, 0], [168511791287905, 0], [217365246971252, 0], [46602227440950, 0], [126614839653410, 0], [46728739102830, 0]], "803": [[256430565764301, 0], [181835428671214, 0], [108525477877409, 0], [201241826148648, 0], [96299468358892, 0], [203394498204142, 0], [16183618270669, 0], [150631309220275, 0], [216290076979896, 0]], "802": [[134329130910563, 0], [70498958576930, 0], [60236193390533, 0], [70318458984847, 0], [116861524950608, 0], [275275109941582, 0], [133217298041829, 0], [259366916892105, 0], [33420177498601, 0]], "801": [[266984314844420, 0], [230684628134571, 0], [212450338754489, 0], [192500903624611, 0], [61198844540047, 0], [59164658769042, 0], [89128640030995, 0], [221873874808426, 0], [5488707384562, 0]], "800": [[220849064531391, 0], [115592819285651, 0], [57305533973155, 0], [78798831256404, 0], [99894367070471, 0], [49466876249815, 0], [251141245779187, 0], [112891386798132, 0], [139006227060165, 0]], "807": [[146284097992411, 0], [96045405465366, 0], [201064501830738, 0], [262563436105681, 0], [94831108884741, 0], [98275353873267, 0], [139511558239956, 0], [148233806407528, 0], [100032122174635, 0]], "806": [[179781877406051, 0], [231543429995146, 0], [138535823557052, 0], [124122534184077, 0], [122965215659138, 0], [229582440682110, 0], [150281597526852, 0], [271124380617202, 0], [218303368902009, 0]], "359": [[217619791559467, 0], [168938351741334, 0], [259581500540388, 0], [46993223683501, 0], [86522552660737, 0], [71171617840516, 0], [163448969418633, 0], [96490360974474, 0], [146492565212427, 0]], "358": [[124940818799992, 0], [265146616960792, 0], [22978793667936, 0], [147314183815402, 0], [67777097155763, 0], [154751304287235, 0], [25043772689982, 0], [209918606682607, 0], [11300807909562, 0]], "216": [[201456249074358, 0], [240105341800557, 0], [101267936600793, 0], [18862175309028, 0], [142307422162842, 0], [105188678314818, 0], [197255743411860, 0], [212872741818867, 0], [131749824224482, 0]], "217": [[26683318228292, 0], [97435137470350, 0], [255862830960480, 0], [82180699926975, 0], [7300079717034, 0], [109336686683861, 0], [20452526971847, 0], [221668155145202, 0], [113104616993673, 0]], "214": [[245608022312617, 0], [182946566626750, 0], [194373244954119, 0], [278611480638627, 0], [129851407789354, 0], [47839711574178, 0], [21248024480292, 0], [35898069986415, 0], [70522882629835, 0]], "215": [[77495730448039, 0], [15484537933181, 0], [11129131873474, 0], [205762977029272, 0], [203815459986206, 0], [210158892869244, 0], [112963043505093, 0], [279163946656816, 0], [92386211413938, 0]], "212": [[73339173421575, 0], [237713154160573, 0], [100520449482797, 0], [238379514112698, 0], [148787684878383, 0], [242519841162594, 0], [192162035508171, 0], [47651891330750, 0], [20934742525, 0]], "213": [[21121178822203, 0], [130180604803683, 0], [162131059750970, 0], [126399645421263, 0], [27913053749344, 0], [142307616544044, 0], [55929081214216, 0], [156455544876545, 0], [89974954137639, 0]], "210": [[236546103973034, 0], [42953235464815, 0], [255156038860473, 0], [7804652151867, 0], [8496072992807, 0], [129657199765855, 0], [217818757417838, 0], [18109626662149, 0], [124026028203600, 0]], "211": [[115481566013540, 0], [217060606375757, 0], [164000095050142, 0], [188936942638817, 0], [212268045570147, 0], [241474033196738, 0], [235246376726105, 0], [113371152866687, 0], [73332234421029, 0]], "762": [[164590179519240, 0], [221763803153666, 0], [234922987982950, 0], [82191636236259, 0], [270485970174210, 0], [237901249856233, 0], [80127064675206, 0], [23220725532833, 0], [186576770539774, 0]], "763": [[216300013693924, 0], [23658430405219, 0], [226692481034451, 0], [163344503229499, 0], [158947056645059, 0], [53996397853590, 0], [204614446404460, 0], [133812201578552, 0], [33736046864568, 0]], "760": [[58231290278902, 0], [36489654145033, 0], [11718222945990, 0], [20846804072500, 0], [232411853515270, 0], [146492540134090, 0], [135265721920417, 0], [238022392350748, 0], [134870640831348, 0]], "761": [[52158773524975, 0], [143168119474815, 0], [76020322254657, 0], [36110857006949, 0], [237740103004296, 0], [105265522300989, 0], [260962459472460, 0], [79109636317822, 0], [83555232771442, 0]], "766": [[91483530311154, 0], [32817463454628, 0], [274963405357806, 0], [103852687177985, 0], [223824801300556, 0], [6916301816837, 0], [173169304600103, 0], [58992610007264, 0], [161825037880078, 0]], "767": [[198835734844260, 0], [278335491212717, 0], [241251470774902, 0], [258951753542802, 0], [147997936082904, 0], [67965299862320, 0], [259770517131672, 0], [123809327063110, 0], [95444849510879, 0]], "218": [[65527998977293, 0], [122343292464143, 0], [5992716277876, 0], [30319629543623, 0], [40856023274653, 0], [233317572152726, 0], [205959050841609, 0], [228115329770050, 0], [100256951971966, 0]], "219": [[8406374993946, 0], [106462243961912, 0], [196907919252926, 0], [169397929953044, 0], [109359425195138, 0], [19957870086100, 0], [150255038208469, 0], [57538565435050, 0], [56010351147467, 0]], "957": [[43302444293971, 0], [142545417398165, 0], [171703269826796, 0], [148218175009060, 0], [77804207874294, 0], [161355956461245, 0], [13957181999323, 0], [44124242252582, 0], [212459412287582, 0]], "956": [[170379878236968, 0], [152361857795837, 0], [121450475846872, 0], [165617958959358, 0], [263897546841288, 0], [170773618163268, 0], [229405008064481, 0], [125731652383515, 0], [76319416787663, 0]], "289": [[145421261214567, 0], [162879831394225, 0], [252984312233728, 0], [147869179744054, 0], [147534096259678, 0], [28977343997524, 0], [176281202523558, 0], [194135988382978, 0], [170502798525675, 0]], "288": [[125058350577886, 0], [3123628158477, 0], [155494608587047, 0], [165918767067772, 0], [181710017349159, 0], [164216385249325, 0], [256190904612581, 0], [56404554794865, 0], [110026659651579, 0]], "1003": [[1808184466553, 0], [223935128427919, 0], [243475083068685, 0], [37932763072781, 0], [253825009846956, 0], [62629145979157, 0], [130353573695304, 0], [233287609425952, 0], [121484726027258, 0]], "4": [[242950544076641, 0], [135291896987482, 0], [47093520208415, 0], [197443911987375, 0], [170898137143370, 0], [165634290140506, 0], [281201394213913, 0], [81609713434650, 0], [30076151998530, 0]], "281": [[128916147669947, 0], [156491308091992, 0], [145392703869196, 0], [168080687159656, 0], [231938140762668, 0], [192556677252539, 0], [148192002737479, 0], [212973659703931, 0], [4152747268666, 0]], "280": [[112261217840686, 0], [142747810823264, 0], [44636821343561, 0], [59607487235723, 0], [163548583020826, 0], [245831616029092, 0], [253904075147062, 0], [258371184664284, 0], [64404027531052, 0]], "283": [[11301789111568, 0], [113411024737389, 0], [62329966641896, 0], [1849053362743, 0], [253949976130817, 0], [55686001070148, 0], [37896156056369, 0], [188638978396530, 0], [273143840124972, 0]], "282": [[111984602505639, 0], [21432368627096, 0], [220274395018934, 0], [44970591962288, 0], [236071133395206, 0], [185239723765292, 0], [208577424645556, 0], [9778991810398, 0], [35742120576463, 0]], "285": [[258471952708522, 0], [239101396380040, 0], [249279428698315, 0], [20576721528650, 0], [268202338652437, 0], [206932799084904, 0], [20864655931207, 0], [191653358796165, 0], [250522537180858, 0]], "284": [[107028726167000, 0], [254869759903001, 0], [226782104099952, 0], [29379415069209, 0], [216975830656349, 0], [268178457071326, 0], [281316020098050, 0], [262924507526839, 0], [240726803216545, 0]], "287": [[45575276095519, 0], [165867429246227, 0], [239600685106050, 0], [91233391017633, 0], [130039775365394, 0], [197251617197066, 0], [102331796870751, 0], [7173278924438, 0], [233657103361330, 0]], "286": [[185225039859894, 0], [202300725109540, 0], [221664573382506, 0], [141428933581477, 0], [97463773702344, 0], [63110610591376, 0], [114040394776362, 0], [150932777653111, 0], [225705471277291, 0]], "678": [[244588205010982, 0], [94248605658347, 0], [107665999777309, 0], [146358887342367, 0], [158222291081253, 0], [79856656478135, 0], [90240694436295, 0], [274306628420078, 0], [100910968689128, 0]], "679": [[162512612097328, 0], [68814178185948, 0], [132256412067288, 0], [129126822676547, 0], [12760380068241, 0], [151929074534551, 0], [264223644218249, 0], [200729118771372, 0], [111580304927546, 0]], "674": [[140327882735258, 2], [42828321446249, 2], [30986634311210, 2], [205625156054886, 2], [253082764062198, 2], [201472315924620, 2], [36017150532552, 2], [175645868015136, 2], [196834963261322, 0]], "675": [[252812955942828, 0], [7761211057002, 0], [50724111788385, 0], [52035363705257, 0], [194601345953370, 0], [40106686136394, 0], [87794621010752, 0], [20250908807784, 0], [75742772715979, 0]], "676": [[44142666751919, 0], [122391247161313, 0], [100707438607293, 0], [94306767244088, 0], [10562327000490, 0], [249905173603014, 0], [161338964217487, 0], [169051485058846, 0], [36783228335129, 0]], "677": [[60638633035567, 0], [244860412801896, 0], [204591350643680, 0], [102697617418046, 0], [194753801475615, 0], [180410352443860, 0], [106503875719313, 0], [513503337451, 0], [187320914570751, 0]], "670": [[141628949587893, 0], [188733938078563, 0], [184527433858637, 0], [261145485818267, 0], [205881376654877, 0], [83725424519132, 0], [37458177932902, 0], [18042297954536, 0], [99412311302701, 0]], "671": [[170203494414489, 0], [192398670384194, 0], [222917880122868, 0], [57306892820261, 0], [213719522966745, 0], [255638130965859, 0], [9257803934001, 0], [99949834652150, 0], [137903137391537, 0]], "672": [[8686618815446, 0], [79450634604336, 0], [232263778786939, 0], [119647434721528, 0], [54625860657712, 0], [169643131275574, 0], [231029139268958, 0], [223303854707825, 0], [162433792913994, 0]], "673": [[133553477672242, 0], [208969955722145, 0], [266341598651150, 0], [266070106429977, 0], [224526278381293, 0], [98735127142014, 0], [4688859085449, 0], [176499622322657, 0], [69730766721005, 0]], "263": [[183639397073331, 0], [203433661425959, 0], [205956448209765, 0], [271677707290107, 0], [208168427182061, 0], [159348950052041, 0], [22284804583071, 0], [154093929300044, 0], [172226455387824, 0]], "262": [[199052825042245, 0], [91988350128878, 0], [178904926239729, 0], [141171923294183, 0], [22914065093243, 0], [108850346206108, 0], [275282772500061, 0], [226611112437314, 0], [280331644275588, 0]], "261": [[180374988794496, 0], [224034340402249, 0], [64287151302903, 0], [260152195550668, 0], [56067537728775, 0], [105396167686114, 0], [190439056165374, 0], [86563030700046, 0], [107209223438114, 0]], "260": [[118663302840074, 0], [141418986361309, 0], [160986115051350, 0], [105148832603566, 0], [237958171130382, 0], [169580771849625, 0], [236505204636939, 0], [30849858352469, 0], [274918473980341, 0]], "267": [[277328640297833, 0], [41231424236893, 0], [208976900144278, 0], [34683569237121, 0], [15036509283288, 0], [255998374455275, 0], [141609446236473, 0], [3264457560959, 0], [261635543845737, 0]], "266": [[118479809902809, 0], [199470655721062, 0], [115512314658543, 0], [161241765955731, 0], [236789409810640, 0], [9070188069016, 0], [245477267811068, 0], [244683239036525, 0], [17569118507581, 0]], "265": [[117709255556293, 0], [176556739961702, 0], [108423472452628, 0], [157571670965795, 0], [152549897505216, 0], [232754653318661, 0], [184299932501129, 0], [78679350998701, 0], [83590217143284, 0]], "264": [[86622123328952, 0], [94598571203707, 0], [221707015961830, 0], [80960631992779, 0], [132007918332283, 0], [253894592294754, 0], [8284618241212, 0], [101700897019139, 0], [214632528986627, 0]], "269": [[155671548382758, 0], [131007293885611, 0], [244876200964168, 0], [111817561613632, 0], [51604089402971, 0], [44783607263469, 0], [184690948736089, 0], [54927676442824, 0], [170093056240808, 0]], "268": [[225667807618690, 0], [244577032991122, 0], [1861839501067, 0], [208341615907976, 0], [112547719336202, 0], [273197211537286, 0], [11170916905064, 0], [39524221661440, 0], [79950501641766, 0]], "701": [[192134305883672, 0], [85753916648168, 0], [256087622547459, 0], [198441071837854, 0], [196142844302108, 0], [228088719401228, 0], [141303924355984, 0], [136633923674123, 0], [74844946138377, 0]], "59": [[189433756676099, 0], [124421935329530, 0], [114422990992977, 0], [180063936028830, 0], [166818749650932, 0], [12285057599850, 0], [241256104202176, 0], [78283913446288, 0], [170557847288978, 0]], "58": [[270033750558058, 0], [145419324468721, 0], [4242815097760, 0], [6976426486501, 0], [85730609022342, 0], [104970896086552, 0], [134569422777067, 0], [234983029795982, 0], [257401446878285, 0]], "55": [[118667931117235, 0], [187983373801778, 0], [250527150138792, 0], [153896075142890, 0], [185447958260508, 0], [206973678951569, 0], [190378820436892, 0], [200495213837465, 0], [164560685816177, 0]], "54": [[54502911540588, 0], [185439150880560, 0], [32889997826032, 0], [55101546528370, 0], [194739502591458, 0], [198251451391528, 0], [148591354384983, 0], [25923835970106, 0], [40397658745897, 0]], "57": [[161798033252769, 0], [25499759993247, 0], [77356004758057, 0], [51288706137080, 0], [246064879735150, 0], [92087999055598, 0], [249766865841967, 0], [3686263711185, 0], [189431498306374, 0]], "56": [[224971111762402, 0], [225467538795713, 0], [274435481173896, 0], [7112771919044, 0], [87044855905332, 0], [115138940897874, 0], [113913994231556, 0], [75545575655293, 0], [141479350212813, 0]], "51": [[96479161799115, 0], [218698577163253, 0], [80259841133305, 0], [223936680263401, 0], [152660552337145, 0], [222234811634120, 0], [101823009493304, 0], [174391462972117, 0], [114983949448525, 0]], "50": [[234505893146328, 0], [42382003242806, 0], [28905076826183, 0], [229458722672436, 0], [191012038611596, 0], [183619810235649, 0], [193017565335958, 0], [181636878720843, 0], [214013716970421, 0]], "53": [[184623032085900, 0], [50056807034111, 0], [171004004831576, 0], [72616361749466, 0], [101008708884124, 0], [183957921458568, 0], [281361426532416, 0], [206599166809835, 0], [99606605039379, 0]], "52": [[159087581014904, 0], [35106084567947, 0], [121741558197271, 0], [238510041317558, 0], [260222215480393, 0], [262846436561263, 0], [106128894597476, 0], [186360696141773, 0], [200518109298684, 0]], "537": [[267704292021453, 0], [196856878618336, 0], [213232001688965, 0], [258920967985641, 0], [202469526936654, 0], [67814433926712, 0], [38598116145564, 0], [155798783378469, 0], [67585920302940, 0]], "536": [[77934432077697, 0], [160494074267102, 0], [40589519353851, 0], [125362184676163, 0], [163805818371334, 0], [8201327212490, 0], [158925490482041, 0], [153479931557338, 0], [183352025106832, 0]], "535": [[6060378068820, 0], [55826062349846, 0], [44752951227760, 0], [206695906945099, 0], [44192503750573, 0], [213753410057283, 0], [126376271501464, 0], [97410824133154, 0], [5674015377705, 0]], "63": [[9968816893676, 0], [40331522907802, 0], [156590737174852, 0], [257254863672288, 0], [210001677059947, 0], [165729291761598, 0], [254594674145180, 0], [240271242186766, 0], [151116510211756, 0]], "533": [[105816467064431, 0], [77611344803965, 0], [151078991991567, 0], [210919337661149, 0], [227334528237389, 0], [5226241675973, 0], [151436569254894, 0], [163545266269658, 0], [192468824400328, 0]], "532": [[213179687015857, 0], [236976825402325, 0], [78912444799485, 0], [244108345526440, 0], [43702845527772, 0], [242231691264392, 0], [238582777641056, 0], [155449068930271, 0], [49420620794056, 0]], "531": [[13067024214184, 0], [121225161616202, 0], [37567473307140, 0], [102681867097809, 0], [125325012426352, 0], [92228971130564, 0], [24084639382834, 0], [281314460524857, 0], [58287353351157, 0]], "530": [[240158765948658, 0], [89652432107873, 0], [225000253097882, 0], [185616955120855, 0], [250818306188854, 0], [113521208357869, 0], [41190007335231, 0], [83594231585372, 0], [278816514772490, 0]], "539": [[183519087966762, 0], [500221540095, 0], [117528885421785, 0], [156234202493324, 0], [142336922062508, 0], [146521958693500, 0], [25829296926103, 0], [222071836958240, 0], [184625415852449, 0]], "538": [[266329827182229, 0], [72437146952455, 0], [111355870637050, 0], [125835551460815, 0], [98651226713648, 0], [246538199009594, 0], [63025879248738, 0], [197105871257551, 0], [15190579431836, 0]], "987": [[21422367271139, 0], [269750493760387, 0], [66260598139613, 0], [80181470386293, 0], [201318128266307, 0], [253201909554788, 0], [178178172064358, 0], [157378872800133, 0], [107249723317081, 0]], "775": [[238980359604264, 0], [220317606393219, 0], [1039337181114, 0], [141438728679880, 0], [272586181946289, 0], [28833937522227, 0], [126376465712984, 0], [258886447100989, 0], [1575388729839, 0]], "988": [[4142421201479, 0], [44480511786353, 0], [60812862327926, 0], [215981576948724, 0], [159516061594757, 0], [124995589088516, 0], [229638873596901, 0], [144286491515150, 0], [155453835414521, 0]], "989": [[156648930978665, 0], [52543079049845, 0], [122709606788472, 0], [30143361997865, 0], [87128737566684, 0], [36124499223828, 0], [191997005896731, 0], [247647209508047, 0], [60178359367059, 0]], "774": [[22259952393157, 0], [245734486410899, 0], [74114573616799, 0], [165949076469606, 0], [120915387486313, 0], [151728379568222, 0], [104574924503666, 0], [272709022151000, 0], [6302856340980, 0]], "982": [[97707745997422, 0], [121684729400425, 0], [14383339736887, 0], [151213186215436, 0], [195818447228188, 0], [263755584233741, 0], [78642677489910, 0], [200925449717886, 0], [265277712486496, 0]], "983": [[77583788654941, 0], [163863114324731, 0], [57612603047690, 0], [184704895798906, 0], [138596051566637, 0], [1138826521724, 0], [570178384059, 0], [14595439854804, 0], [69665045961152, 0]], "980": [[130627802593301, 0], [65809243953288, 0], [222036203954672, 0], [226858797389567, 0], [270383159765800, 0], [269215348907226, 0], [6010337701047, 0], [179928541321681, 0], [2235994860264, 0]], "981": [[181139736355590, 0], [44335474889208, 0], [72893970466786, 0], [247577085760879, 0], [72583719668756, 0], [41997882257472, 0], [86668868127118, 0], [190138577999194, 0], [256702474793640, 0]], "986": [[155702792836036, 0], [99215197655171, 0], [79637987987002, 0], [156528856414953, 0], [174544338611055, 0], [44333386417298, 0], [104755795511274, 0], [132452551296410, 0], [16197019866696, 0]], "777": [[15728035592882, 0], [57289720479521, 0], [260178157113714, 0], [38172833031361, 0], [151688837255109, 0], [110465032404817, 0], [92267595176010, 0], [64179494535003, 0], [65992446569213, 0]], "984": [[33375080921110, 0], [5832692318248, 0], [196368886754589, 0], [88850194757739, 0], [262853567528381, 0], [13674135881865, 0], [117661844603815, 0], [90227477327777, 0], [13617277763915, 0]], "985": [[142311520573356, 0], [170481181518258, 0], [141211631626629, 0], [95649910682275, 0], [161120358847054, 0], [93607914240590, 0], [211956005409468, 0], [40486110283907, 0], [161487626746664, 0]], "115": [[150732064062578, 0], [272752621590957, 0], [163509553739215, 0], [275607611605842, 0], [146956846654846, 0], [251933084974815, 0], [250564596649202, 0], [241188266654650, 0], [26929708694510, 0]], "114": [[54987494514824, 0], [238509806234804, 0], [155093065772808, 0], [55752052697287, 0], [78084054913092, 0], [114122598898327, 0], [59640517780733, 0], [233606378766282, 0], [183885361037227, 0]], "117": [[169532407841749, 0], [199665854389271, 0], [76401733061125, 0], [255030049257768, 0], [123779254203130, 0], [89450186505736, 0], [172299485075963, 0], [72263876585835, 0], [164140296322799, 0]], "116": [[228786836833576, 0], [66006595191236, 0], [83658484546884, 0], [213502852120829, 0], [147616677058646, 0], [34304845354328, 0], [262828745499604, 0], [137074660670257, 0], [71299870014640, 0]], "111": [[60534128651936, 0], [153430987155024, 0], [237025356348548, 0], [145021621361207, 0], [235728316389088, 0], [204638973796, 0], [278111967823120, 0], [141912372891747, 0], [38580621326630, 0]], "110": [[78582690415685, 0], [199873841053417, 0], [21326463391639, 0], [208474416941460, 0], [133322430493433, 0], [200817418345971, 0], [29219113515826, 0], [37550758052893, 0], [76906250427454, 0]], "113": [[142095991416690, 0], [150698302647228, 0], [34599832628213, 0], [278736989099298, 0], [234540412884673, 0], [139645006122738, 0], [93147687665945, 0], [277859489230930, 0], [240210584796258, 0]], "112": [[275497613043382, 0], [9261832566681, 0], [66570388279261, 0], [70645121287824, 0], [141248680045323, 0], [135432226331709, 0], [177267677677246, 0], [78798932543098, 0], [265174444204136, 0]], "771": [[257957158080049, 0], [107204563014448, 0], [33846956071658, 0], [252829879632203, 0], [111612926252533, 0], [93602210884411, 0], [239528794529751, 0], [96748516002602, 0], [190043784038532, 0]], "119": [[207906818844572, 0], [16975957792054, 0], [167542358673213, 0], [229234567352425, 0], [257087100706870, 0], [248260637836670, 0], [173126679601120, 0], [264874101274376, 0], [65888158014742, 0]], "118": [[227025927417554, 0], [109711808982922, 0], [13845140834882, 0], [232008670235312, 0], [138839616678292, 0], [106637782130749, 0], [142454265551046, 0], [266944188974521, 0], [272659759196126, 0]], "770": [[244771030059981, 0], [14918746532799, 0], [184885730503187, 0], [221898493556296, 0], [159280843628224, 0], [68539294193589, 0], [140680605376211, 0], [234876138568341, 0], [49123282852275, 0]], "773": [[173817738157369, 0], [157784460448777, 0], [94827178187479, 0], [22909179478198, 0], [180454642903787, 0], [116027590342508, 0], [185220037304157, 0], [150222030266984, 0], [118429309358446, 0]], "772": [[167182328443189, 0], [65181930206900, 0], [128580594184673, 0], [237115878525559, 0], [158918437348216, 0], [127863396404512, 0], [214037333890125, 0], [91146470988007, 0], [153745798346837, 0]], "953": [[72783094714315, 2], [222591200483861, 2], [245286916629558, 2], [114405719099173, 2], [51529837359275, 2], [2727256902213, 2], [274320591415188, 0], [210303123910459, 0], [138929906460374, 0]], "429": [[160204606905920, 0], [144053760668536, 0], [89121809934389, 0], [118089722138962, 0], [272665394626822, 0], [18330135629823, 0], [198873004118545, 0], [90499022196731, 0], [23651370372359, 0]], "428": [[201513935548994, 0], [83418941379720, 0], [71320065355609, 0], [214144933312312, 0], [19876185436757, 0], [280090792825197, 0], [112134655748600, 0], [11471332610259, 0], [100242379481959, 0]], "534": [[197424257530536, 0], [220122592273866, 0], [173768340861387, 0], [129668992239908, 0], [132437534373014, 0], [231895179273234, 0], [185561071232024, 0], [163487581000340, 0], [100951924583417, 0]], "919": [[132694815802638, 0], [258005999892500, 0], [187219925793496, 0], [187326085869103, 0], [38427106414646, 0], [50525586135980, 0], [259677479431104, 0], [245603150420655, 0], [203736436443716, 0]], "918": [[21669773887719, 0], [145843198662967, 0], [78335425971307, 0], [118391270375172, 0], [231394347047329, 0], [92951158691282, 0], [88604305178111, 0], [39209360233167, 0], [251923853850509, 0]], "421": [[219751851189582, 0], [18208109515269, 0], [56050801030330, 0], [85739455682924, 0], [98392803108046, 0], [41354975685095, 0], [193390004852684, 0], [14559476202351, 0], [49012014393590, 0]], "420": [[64705764976061, 0], [260222970684019, 0], [64274967656588, 0], [121785043978442, 0], [64294577958903, 0], [100873535565478, 0], [241521649009138, 0], [278636466957582, 0], [93147900344336, 0]], "423": [[246735523208023, 0], [182193303577623, 0], [164685611695353, 0], [4779365648842, 0], [263621458273231, 0], [229325713121106, 0], [201738843727639, 0], [19508756211986, 0], [87592376057498, 0]], "422": [[141604746396341, 0], [247628995873437, 0], [26781741832688, 0], [21456372678360, 0], [271201655128428, 0], [106359665929064, 0], [237260862298128, 0], [265806780803894, 0], [141687109602408, 0]], "425": [[62256987790168, 0], [131093523197957, 0], [52114310349716, 0], [279509441910775, 0], [170463727168443, 0], [114144488385867, 0], [103173844516156, 0], [253158126824863, 0], [97078561009765, 0]], "424": [[111051325048063, 0], [277233796029763, 0], [225243333527575, 0], [179684291606603, 0], [68749372133080, 0], [81601351495325, 0], [152512583984112, 0], [194935780861801, 0], [217736480785955, 0]], "427": [[276921073465245, 0], [11194076783866, 0], [59678527785852, 0], [246369481606486, 0], [15761648726768, 0], [143173641294442, 0], [216919580778007, 0], [144687224286824, 0], [224300590668088, 0]], "426": [[43096555643621, 0], [86768852692563, 0], [130851427140303, 0], [217083743342587, 0], [17892376565331, 0], [2660548733213, 0], [272494845779384, 0], [137321788460585, 0], [159355184827021, 0]], "308": [[76986299955317, 0], [201503007834402, 0], [47160981017429, 0], [21718471436679, 0], [172498520883254, 0], [195300216343237, 0], [52741392170021, 0], [149361690627608, 0], [220041566092816, 0]], "309": [[276041929930587, 0], [180563299653254, 0], [232802342445191, 0], [203283163184523, 0], [12075129641901, 0], [116183461811964, 0], [193443760102406, 0], [256749890973418, 0], [43480705887850, 0]], "855": [[279398709833995, 0], [194181293795189, 0], [54530762661269, 0], [127738697765214, 0], [179335554273492, 0], [116119332827262, 0], [11583035880971, 0], [268589031212532, 0], [77200470606072, 0]], "300": [[7032803417580, 0], [274752840578781, 0], [191324602917614, 0], [200294881593559, 0], [72012044025921, 0], [136669989524698, 0], [182003185967232, 0], [28491740943737, 0], [227016098782048, 0]], "301": [[277664963797871, 0], [228499408026525, 0], [165864286595702, 0], [69837942367132, 0], [25154875097659, 0], [247065512930170, 0], [67065152517889, 0], [184651424517622, 0], [228882008328614, 0]], "302": [[180487703314755, 0], [98702537211340, 0], [7388654652752, 0], [30178463223012, 0], [154815380454026, 0], [245686869173984, 0], [159932888830302, 0], [127898954321740, 0], [89743442135202, 0]], "303": [[39429131430640, 0], [20222994704480, 0], [201618159519304, 0], [183184811547528, 0], [207476768006392, 0], [191690771562713, 0], [132827405977516, 0], [131988620428893, 0], [85782808911007, 0]], "304": [[202064536099644, 0], [27919145375915, 0], [87925969829514, 0], [83420717288447, 0], [29782125058214, 0], [41456436240036, 0], [142051022017233, 0], [10229648681912, 0], [148019177064262, 0]], "305": [[25342395680404, 0], [137923088959889, 0], [242985883814720, 0], [83342849168184, 0], [23877428077753, 0], [89218306590536, 0], [44904899231090, 0], [255005415564767, 0], [198880253886350, 0]], "306": [[27422404779450, 0], [193118193097033, 0], [63958730618982, 0], [205558714514956, 0], [163688427639853, 0], [184897855237148, 0], [143649237269218, 0], [147286263316345, 0], [163877980124917, 0]], "307": [[74703923733798, 0], [148954808598414, 0], [62917884302920, 0], [174049825310420, 0], [16830835088532, 0], [120935957208245, 0], [193274545205698, 0], [226494425809721, 0], [54305150825592, 0]], "895": [[102980606445868, 0], [176837077916984, 0], [93333898035762, 0], [270306494487846, 0], [210300660500468, 0], [137125851364139, 0], [95247925116541, 0], [135461200860338, 0], [72816685674331, 0]], "825": [[134933053168376, 0], [10046224002011, 0], [206902323623953, 0], [116739649812357, 0], [229715455045283, 0], [79495200026605, 0], [221958074255420, 0], [189416942722770, 0], [216722953294661, 0]], "824": [[56115527434241, 0], [27088003455281, 0], [210973306958769, 0], [244060140036519, 0], [275642717802227, 0], [177661354514085, 0], [149120748304912, 0], [68259116843307, 0], [13747334857408, 0]], "827": [[113402414855872, 0], [14650670101412, 0], [102976485171022, 0], [151857165379104, 0], [109522041758316, 0], [274535592611548, 0], [50016601307745, 0], [121527550020527, 0], [63750293817852, 0]], "847": [[265739039080147, 0], [201317434617687, 0], [133342439514169, 0], [278725473166231, 0], [25574467290971, 0], [176054658619924, 0], [194650075011553, 0], [128637765545891, 0], [123596844663149, 0]], "846": [[246167664742976, 0], [17105501519734, 0], [18625713911614, 0], [69193733856281, 0], [70478303458052, 0], [1820857975570, 0], [138506279847576, 0], [94649068292909, 0], [276728229959932, 0]], "845": [[259581383077333, 0], [52738010524643, 0], [60611379714433, 0], [20001654225373, 0], [193893021057792, 0], [144167591293690, 0], [97983904733166, 0], [187515105523035, 0], [173790674286287, 0]], "826": [[207770814199129, 0], [191686480041169, 0], [55302224408063, 0], [116879543281497, 0], [145923805456460, 0], [246508538897437, 0], [17846533850292, 0], [256099437083616, 0], [280099391684123, 0]], "843": [[178189646117948, 0], [53243497270371, 0], [224938875741545, 0], [78986954862973, 0], [30468400422057, 0], [153141588536036, 0], [230145281787091, 0], [259152188645030, 0], [145923944197100, 0]], "842": [[15826169216700, 0], [254432427394953, 0], [190744564501774, 0], [201559112231578, 0], [10757681395101, 0], [257152401107967, 0], [30599234320836, 0], [261965368353373, 0], [239032405600534, 0]], "841": [[123762869857529, 0], [51296961343426, 0], [199879562528761, 0], [271325600176426, 0], [86115443264379, 0], [185024688247918, 0], [42837574234226, 0], [94015170152763, 0], [219984916879805, 0]], "840": [[243858928432997, 0], [142867076711163, 0], [165158386139925, 0], [79287395167197, 0], [96312760463789, 0], [280050467901540, 0], [32368805781300, 0], [225619375723097, 0], [177237815225853, 0]], "821": [[94285677880163, 0], [59382556180576, 0], [196229098494830, 0], [84813617024294, 0], [99977878952971, 0], [186710106299528, 0], [34817587142189, 0], [18011141580704, 0], [107927216885153, 0]], "853": [[176847912574180, 0], [220499888129273, 0], [144615520029469, 0], [225089468802038, 0], [102482929634745, 0], [229542735582828, 0], [236000622456591, 0], [262289132243393, 0], [48817480230898, 0]], "849": [[32017530412, 0], [221571901117076, 0], [97999247786842, 0], [96325073815363, 0], [174120188238213, 0], [84463780242498, 0], [60741519789471, 0], [74186842619846, 0], [213622961379426, 0]], "820": [[103209630414662, 0], [249821889333986, 0], [35779348467063, 0], [47586818683360, 0], [22876581707565, 0], [219875839779606, 0], [187882094209260, 0], [46548964863095, 0], [203540456030043, 0]], "823": [[123077477605831, 0], [108426003737157, 0], [33408941799132, 0], [225796047725509, 0], [54323117909732, 0], [200158623457726, 0], [229794284679947, 0], [237437341670232, 0], [17374354423847, 0]], "822": [[203043197362628, 0], [225779978430258, 0], [69740438412182, 0], [280860310823078, 0], [10191846631672, 0], [48757196734588, 0], [121747130286894, 0], [66510564415966, 0], [215289639986106, 0]], "954": [[250203606567123, 0], [35280192256859, 0], [51524159141577, 0], [262752398120141, 0], [2613276641236, 0], [14081658045967, 0], [79034907949850, 0], [133708929447950, 0], [85402474368767, 0]], "568": [[253362058502579, 0], [30756607916723, 0], [14129796747146, 0], [88571706645427, 0], [73802469209980, 0], [22882799283551, 0], [135319376225257, 0], [169143165818553, 0], [94447805259142, 0]], "569": [[123465925920958, 0], [163258589015354, 0], [29899408473692, 0], [98652229306111, 0], [76689288373562, 0], [142580113563648, 0], [79530078905114, 0], [144376601166642, 0], [118419225606085, 0]], "751": [[27745162506583, 0], [11869127097319, 0], [18599635583429, 0], [120366515381705, 0], [141826762724373, 0], [251294350305677, 0], [14064057968365, 0], [80458097709593, 0], [245112310362495, 0]], "750": [[165869692241395, 0], [150291038715978, 0], [94387349207383, 0], [30892770109409, 0], [223217582609567, 0], [43701762466788, 0], [177664758832481, 0], [25721945047859, 0], [109879294494888, 0]], "757": [[46002446270659, 0], [123331743339872, 0], [241856679753373, 0], [129565185718161, 0], [263154042952195, 0], [156646033111413, 0], [125038556232465, 0], [35984188486001, 0], [165589963285652, 0]], "737": [[216282964498811, 0], [197941972012007, 0], [200900948072170, 0], [179597951276073, 0], [176215061880144, 0], [78667401121756, 0], [228759243237306, 0], [38185270191183, 0], [137357313768572, 0]], "755": [[140518634878389, 0], [230686983883748, 0], [278585496181188, 0], [116445278426562, 0], [203054105859157, 0], [35472356521921, 0], [189583340972331, 0], [109460526983193, 0], [26573250416886, 0]], "754": [[246668828362628, 0], [26847286238179, 0], [229670788430114, 0], [24638363956520, 0], [144113410084093, 0], [87280386760391, 0], [48682239804764, 0], [26508784661448, 0], [53674974280018, 0]], "560": [[67511482446535, 0], [70231389413964, 0], [69178528187790, 0], [58912817283998, 0], [236644401195092, 0], [141568591568177, 0], [54848157806839, 0], [9546932168206, 0], [203441723394065, 0]], "561": [[202399167849096, 0], [130327742073295, 0], [167685164792825, 0], [116272374632733, 0], [52953083754835, 0], [161355130608096, 0], [96957218535957, 0], [219096053419476, 0], [18185701735755, 0]], "562": [[151050005021713, 0], [23077566173081, 0], [13675672257975, 0], [200391734074394, 0], [9801167732476, 0], [171384611430491, 0], [227122245777149, 0], [195174651038931, 0], [63313287888442, 0]], "563": [[221088708544396, 0], [101512559836904, 0], [280189391690635, 0], [52484498560266, 0], [18444471201314, 0], [102700855108461, 0], [146052053703302, 0], [151731553692871, 0], [141814151238332, 0]], "564": [[278881029906672, 0], [178964320578535, 0], [202380811500694, 0], [81022842499703, 0], [87459980406044, 0], [206188732142916, 0], [237286445702041, 0], [63673450237153, 0], [218450711927994, 0]], "565": [[20375786445503, 0], [71724020712495, 0], [156911819562720, 0], [147691087355300, 0], [58937045092237, 0], [118453167454491, 0], [95420629240294, 0], [185766568544713, 0], [148724584611405, 0]], "566": [[242298676255230, 0], [246541767457424, 0], [162741897700298, 0], [117788779085293, 0], [265184302132794, 0], [158118408224068, 0], [73939870311101, 0], [250519160976013, 0], [203896602603116, 0]], "567": [[160598961766821, 0], [35254064842854, 0], [38210235518895, 0], [261713414829455, 0], [23354541156700, 0], [249451444874052, 0], [197754464657224, 0], [100865508175927, 0], [41426717975994, 0]], "739": [[81108788556115, 0], [199441569870521, 0], [179860817733825, 0], [16629629232580, 0], [78005870590043, 0], [134984134844794, 0], [237648862973118, 0], [94352520726080, 0], [51168678646353, 0]], "229": [[232318605228173, 0], [242335893150912, 0], [11351588803369, 0], [220877371177872, 0], [90266416563093, 0], [248269598834050, 0], [90470073860042, 0], [82533639304582, 0], [214426001483864, 0]], "228": [[10070877375075, 0], [68023552725629, 0], [137683665185453, 0], [28604509115817, 0], [53113165860565, 0], [269493738898702, 0], [159638951503958, 0], [213288305375636, 0], [202630488359720, 0]], "227": [[7826044977549, 0], [61401067849668, 0], [108444020078782, 0], [91933283500524, 0], [239361643291638, 0], [124964533098449, 0], [223019042296870, 0], [208843773284614, 0], [215849839680801, 0]], "226": [[168740968370887, 0], [277710803787112, 0], [77156209029750, 0], [273705245404578, 0], [157981470285087, 0], [220595479996667, 0], [244247786232098, 0], [28746964091556, 0], [73525531369516, 0]], "225": [[121861938645030, 0], [82001948580439, 0], [137331470585418, 0], [57108373822699, 0], [202606413879861, 0], [130117246500359, 0], [153916682205193, 0], [161966794472932, 0], [235051925075527, 0]], "224": [[45100492693232, 0], [56432098802894, 0], [70338005058606, 0], [258204837941831, 0], [182691142920238, 0], [239732258540808, 0], [165007695087896, 0], [22511963878178, 0], [146468950355876, 0]], "223": [[275672969077580, 0], [72719909122483, 0], [229152329637087, 0], [17415491145807, 0], [62478304674335, 0], [114925280674453, 0], [105473778445689, 0], [263401416886031, 0], [158744109831747, 0]], "222": [[61919038022470, 0], [221441219192876, 0], [166792660538444, 0], [225644167362640, 0], [279330163495745, 0], [19992718211288, 0], [186995758077784, 0], [227351184269844, 0], [102604170107462, 0]], "221": [[128543302883135, 0], [245480779523894, 0], [201367255540858, 0], [278449749778111, 0], [241819497481825, 0], [87554743262938, 0], [44375856441552, 0], [131944436154050, 0], [251974552092185, 0]], "220": [[34152162182260, 0], [32489763548837, 0], [265922174558845, 0], [122411618456165, 0], [67438022299888, 0], [69205711819970, 0], [262167406792518, 0], [181457806370579, 0], [8165313553030, 0]], "1001": [[199098012345521, 0], [95440503375924, 0], [257155051014492, 0], [107264943679703, 0], [82592528321259, 0], [257277517061957, 0], [242303788706944, 0], [31210410262482, 0], [174218292662378, 0]], "1021": [[174632913802503, 0], [63591071108754, 0], [240184891473524, 0], [227291232131743, 0], [210812943929796, 0], [163150265936803, 0], [131298756097580, 0], [12171705634199, 0], [211435662717305, 0]], "1020": [[173576379974101, 0], [222175739875283, 0], [6300474982041, 0], [66653692751991, 0], [55634735363205, 0], [222638202404959, 0], [8741440593571, 0], [168855950390611, 0], [137208044343084, 0]], "1023": [[243444426362309, 0], [202095466121513, 0], [174421399952473, 0], [102700083481510, 0], [202455824860244, 0], [192198933190341, 0], [55377240672798, 0], [279633538103080, 0], [152364986863598, 0]], "1022": [[99847505912056, 0], [12941248447247, 0], [34190338827754, 0], [134235743124131, 0], [67266426123559, 0], [136109245374166, 0], [136654865243661, 0], [15587209096350, 0], [179040897601848, 0]], "391": [[142616776072289, 0], [49982528541925, 0], [262053199619783, 0], [226257065109786, 0], [276571983166975, 0], [184927629993013, 0], [247295612593204, 0], [80416910074897, 0], [142140469630852, 0]], "726": [[148692044316167, 0], [222073155791676, 0], [254587228420574, 0], [209547143861025, 0], [160931882800250, 0], [69305373567268, 0], [177194388061268, 0], [113419839946092, 0], [92686494301482, 0]], "727": [[104517521077718, 0], [266498802096244, 0], [279170960237788, 0], [196130631127707, 0], [167575027342343, 0], [215816846065099, 0], [27296376888573, 0], [62632977083968, 0], [190530669804788, 0]], "724": [[277046422898542, 0], [195802132377739, 0], [138211826914330, 0], [6410554632338, 0], [214983779264295, 0], [267811314568301, 0], [140667911886389, 0], [227091412811728, 0], [34991757839781, 0]], "390": [[82816479238637, 0], [58249713693132, 0], [93031135585791, 0], [55588634670459, 0], [251832570267187, 0], [237274590140402, 0], [56999052731050, 0], [99952420982436, 0], [135956750310834, 0]], "722": [[118118280186102, 0], [8661102199434, 0], [239151979665612, 0], [157491262636543, 0], [17151072383208, 0], [35223252170907, 0], [26089050922465, 0], [242038239179864, 0], [22335460523707, 0]], "723": [[134926338252609, 0], [187910414473408, 0], [43828577361598, 0], [24287606690422, 0], [219107958099241, 0], [218606986363118, 0], [206206319264916, 0], [110256132668134, 0], [128895896395117, 0]], "720": [[61085569338396, 0], [81451577274543, 0], [250019478794050, 0], [278095490917815, 0], [42566785365166, 0], [223796382560940, 0], [112398471537294, 0], [218671164844564, 0], [240039950358601, 0]], "721": [[236729437465482, 0], [121792772598774, 0], [2787776667842, 0], [19032338053628, 0], [229582069599103, 0], [208438499529036, 0], [20931098391658, 0], [157134129479208, 0], [168839421324554, 0]], "728": [[221175105124218, 0], [87860133417308, 0], [97342588136957, 0], [152930027822704, 0], [124984196967026, 0], [271686572889186, 0], [142675669549482, 0], [116803295154248, 0], [236575323579356, 0]], "729": [[79511132347425, 0], [173904530852987, 0], [254812519078523, 0], [187097859769545, 0], [113664205830976, 0], [274862539861289, 0], [217998475214530, 0], [32583719840127, 0], [207045086185776, 0]], "151": [[194381709280626, 0], [142469778258057, 0], [219530065092056, 0], [70119617718077, 0], [253687067049102, 0], [120585151710505, 0], [16900752600781, 0], [167189551949121, 0], [182710892309827, 0]], "150": [[48189077981611, 0], [58905057315905, 0], [146206227558424, 0], [17343411189885, 0], [209487664389219, 0], [167753670389083, 0], [105721014464672, 0], [137249066382335, 0], [94630521503891, 0]], "153": [[258100973939490, 0], [139225227588384, 0], [46485438755648, 0], [49179697934667, 0], [231852892800691, 0], [159769084287877, 0], [19515772929440, 0], [204919531058532, 0], [47658145060337, 0]], "152": [[215029797419180, 0], [123325601633537, 0], [137270409750856, 0], [50582721332766, 0], [145895662698593, 0], [226923707408633, 0], [204290461428180, 0], [268108399572113, 0], [18013602885823, 0]], "155": [[262063603397686, 0], [165847293291406, 0], [102811013236994, 0], [151186618079000, 0], [128343399810889, 0], [271728049320448, 0], [80349341790263, 0], [249203763358824, 0], [236966739057762, 0]], "154": [[218535875602385, 0], [105181644756807, 0], [54662290008385, 0], [153198491672777, 0], [60631704125228, 0], [76201584702898, 0], [182453384114390, 0], [211468077751428, 0], [113576381125752, 0]], "157": [[79040005483718, 0], [116710935065836, 0], [170822307959583, 0], [11342953110515, 0], [10068077924814, 0], [77920666474447, 0], [8440225821697, 0], [192707972375206, 0], [118349800306068, 0]], "156": [[159342683686847, 0], [23466868742557, 0], [240847505673303, 0], [164951203739739, 0], [60421843559153, 0], [224962724584786, 0], [248195804678201, 0], [1841891544515, 0], [157302097357865, 0]], "159": [[137882394958445, 0], [196521058940639, 0], [77254704150081, 0], [150520747738343, 0], [210165953768737, 0], [1827447446145, 0], [160333776002271, 0], [37625164848842, 0], [103778585207830, 0]], "158": [[41305135850783, 0], [72027220320023, 0], [225175969334280, 0], [8509037158652, 0], [261324310065573, 0], [164269914123207, 0], [191856037834294, 0], [122874388702824, 0], [248576896922998, 0]], "609": [[114634517885554, 0], [163593397832015, 0], [260490509637169, 0], [279554799325462, 0], [69114300643014, 0], [88296671690887, 0], [268498401558383, 0], [228268478283185, 0], [279897955232178, 0]], "608": [[227913672954795, 0], [120054489066869, 0], [57002833924499, 0], [7945387866733, 0], [127698407678047, 0], [230147963739865, 0], [163524678390073, 0], [129358527148596, 0], [34026951955240, 0]], "976": [[53535330362180, 0], [8441066095887, 0], [24655806398912, 0], [227779883707979, 0], [120946215065418, 0], [141243841757552, 0], [21067044013289, 0], [36345245741742, 0], [163859561398104, 0]], "634": [[280144289292093, 0], [218512405579539, 0], [269818679887989, 0], [148301893325676, 0], [195761530781528, 0], [270590730371839, 0], [31862026374455, 0], [169908121146782, 0], [90500536643721, 0]], "399": [[3146360472279, 0], [165696840857498, 0], [1370897430079, 0], [236641652136210, 0], [114066092278543, 0], [261176325441470, 0], [131713764452688, 0], [99177465801567, 0], [71418435104102, 0]], "635": [[249733167440037, 0], [201084210664919, 0], [132076609868901, 0], [127046757867315, 0], [81995426429629, 0], [97690235826008, 0], [144534687736773, 0], [64157228144061, 0], [261892223364337, 0]], "749": [[11745441152633, 0], [253241382688630, 0], [178723904953653, 0], [35817248845732, 0], [58856529308982, 0], [156678961224691, 0], [222856106916579, 0], [60502993149470, 0], [75713565567234, 0]], "958": [[239158876318151, 0], [132284770529317, 0], [104642527454189, 0], [161968454725243, 0], [32254746501101, 0], [72712079044726, 0], [196683876691981, 0], [116976889731287, 0], [189851624483512, 0]], "398": [[44875439129282, 0], [18185595575317, 0], [480167575768, 0], [98761452570703, 0], [160709057714833, 0], [256814749193603, 0], [191651454155757, 0], [157007424198972, 0], [70586775954210, 0]], "48": [[77409562046274, 0], [230396099088597, 0], [212439595740490, 0], [130110063247985, 0], [103624802349708, 0], [271614430930842, 0], [273396665972252, 0], [161370099648088, 0], [69257584418727, 0]], "49": [[146156221448022, 0], [240583184069899, 0], [22601330400667, 0], [13593943992643, 0], [263777433578383, 0], [197203878878900, 0], [171527097420747, 0], [175146061263570, 0], [3740743392126, 0]], "46": [[18622692449984, 0], [234347460167902, 0], [172736793270372, 0], [118976224777619, 0], [151966618907705, 0], [103153321213848, 0], [236263346467132, 0], [75697110935832, 0], [223345274558072, 0]], "47": [[197667753943225, 0], [271735920256131, 0], [1876753261001, 0], [13284796204954, 0], [86086602377079, 0], [228870020071484, 0], [113025258002794, 0], [181594956203473, 0], [128777511553400, 0]], "44": [[167068988611575, 0], [171967833077741, 0], [184913511236318, 0], [11392292473290, 0], [289624652264, 0], [273513475273023, 0], [59842137169659, 0], [133857673685294, 0], [96414530601652, 0]], "45": [[21567590597067, 0], [20690174105719, 0], [140027188601889, 0], [261938839661426, 0], [30380279446861, 0], [267570931904924, 0], [8082302665779, 0], [216083914950928, 0], [142520190524572, 0]], "42": [[262570476521377, 0], [11051589710496, 0], [57900830479766, 0], [234870328930495, 0], [166351456408655, 0], [151905340064691, 0], [190227371349472, 0], [165111128424254, 0], [29441622256696, 0]], "43": [[12835786245559, 0], [135151630525628, 0], [230848657507511, 0], [248974266034309, 0], [119955913793318, 0], [16135288623489, 0], [262556770408755, 0], [124955234054171, 0], [182445061616477, 0]], "40": [[73443256309723, 0], [18028112744598, 0], [163041272588597, 0], [237582079324676, 0], [103270200683131, 0], [68194442833814, 0], [80075879063872, 0], [42048496292548, 0], [181730124119736, 0]], "41": [[241722176236520, 0], [208686475566305, 0], [185241474467090, 0], [61353561887720, 0], [220453220705487, 0], [243495631374494, 0], [104537624542828, 0], [166216313103133, 0], [54637704313316, 0]], "638": [[12917533966915, 0], [119943569318638, 0], [62499564527168, 0], [185284228645325, 0], [136358222810367, 0], [253589735495216, 0], [248560435274379, 0], [52492353382746, 0], [263738829961240, 0]], "5": [[21495512545914, 0], [219926104322878, 0], [185308891400396, 0], [231085565711223, 0], [273117310768106, 0], [58203422243032, 0], [61599765175482, 0], [35052623257009, 0], [77920205986160, 0]], "639": [[228077656929143, 0], [64653098342598, 0], [49706016729943, 0], [229595048281704, 0], [168977912280607, 0], [104804581200124, 0], [108740771590162, 0], [102253478992104, 0], [214263661942092, 0]], "489": [[277417250913555, 0], [257006153500948, 0], [164214341074313, 0], [168457107816010, 0], [165795585369187, 0], [203212899772160, 0], [243815919674564, 0], [132709910266926, 0], [111789943954747, 0]], "488": [[258399802264394, 0], [250083380972072, 0], [227752375210795, 0], [76993616537051, 0], [277634308984919, 0], [347589577064, 0], [230073630212700, 0], [83473337342421, 0], [43725444785289, 0]], "487": [[182211799958845, 0], [217202889524615, 0], [164954818245849, 0], [98461686609488, 0], [92166722250792, 0], [128035512516767, 0], [237144641960336, 0], [49965455675743, 0], [126560699067206, 0]], "486": [[9385776079886, 0], [67960154300988, 0], [130453055483854, 0], [197106420505322, 0], [60220904457116, 0], [205954353112073, 0], [49901414864360, 0], [151245532521331, 0], [228435414056056, 0]], "485": [[129679068965610, 0], [61935540169130, 0], [267209972974141, 0], [111456999705147, 0], [125837852939866, 0], [245000267453590, 0], [3844243062394, 0], [67416504571756, 0], [163804672653808, 0]], "484": [[184714013430607, 0], [766622379545, 0], [13590598978083, 0], [225844773746228, 0], [240843796348261, 0], [111320009892926, 0], [28747439068186, 0], [25278611286998, 0], [44311473323578, 0]], "483": [[114315850952182, 0], [270038707118233, 0], [230003892235740, 0], [44011370239749, 0], [243241883041508, 0], [213953179509018, 0], [113589104495229, 0], [63439480778525, 0], [83230283702062, 0]], "482": [[269169336488852, 0], [147070378901896, 0], [119194264310057, 0], [272992696121645, 0], [66504190324816, 0], [234519413228654, 0], [107460720851268, 0], [197401567696090, 0], [130381738077872, 0]], "481": [[160749673631982, 0], [252560902708925, 0], [141468881623774, 0], [241479364172911, 0], [142783564454736, 0], [171753134891608, 0], [32433017494540, 0], [187493080146406, 0], [64074129502532, 0]], "480": [[166236941080887, 0], [40548946759860, 0], [109492964265813, 0], [188838041211300, 0], [51762217806722, 0], [110798430894190, 0], [119835656527321, 0], [187321657210018, 0], [36317052574001, 0]], "955": [[270348863383132, 0], [170814318886334, 0], [22042991877662, 0], [197285640341645, 0], [79009325816889, 0], [274727183017969, 0], [25504819299451, 0], [62249569705525, 0], [193166360841418, 0]], "472": [[190843470550711, 0], [203187307054952, 0], [223063251494686, 0], [187516270666078, 0], [57742364286000, 0], [180005928528909, 0], [85130222773146, 0], [224445391569527, 0], [196911818635833, 0]], "473": [[254019907708453, 0], [243315127562240, 0], [164409213808337, 0], [250529933414442, 0], [258076423105448, 0], [235429608337848, 0], [152527945800897, 0], [76865259044574, 0], [188507384760390, 0]], "470": [[28274466392804, 0], [193532161718376, 0], [147658893255033, 0], [173843687862681, 0], [61929672459431, 0], [33545780791747, 0], [254726113663814, 0], [254595906724108, 0], [71275029231591, 0]], "471": [[39307293264959, 0], [246085033685894, 0], [223004387660335, 0], [29913872146697, 0], [211297734834476, 0], [133562812994897, 0], [259582765443064, 0], [53606586215287, 0], [94538849277882, 0]], "476": [[233013632132743, 0], [243336561429147, 0], [218583990339779, 0], [254429899730012, 0], [187300122935755, 0], [197508356935979, 0], [48242058965359, 0], [171683964164802, 0], [160408638696569, 0]], "477": [[249672913355750, 0], [198589891401041, 0], [242854401466104, 0], [14691606571516, 0], [197597997539052, 0], [2343883044743, 0], [63973796816679, 0], [47984898122037, 0], [46648368474324, 0]], "474": [[213417899182682, 0], [160276231951914, 0], [211287253689643, 0], [21814933161156, 0], [141591081733742, 0], [149111132818223, 0], [185671263222318, 0], [273337094585855, 0], [196265754756093, 0]], "475": [[119355980803641, 0], [178229822625823, 0], [1911880865595, 0], [167040873549322, 0], [32215912165315, 0], [220013171242955, 0], [143936520349751, 0], [80959730494086, 0], [189543185972860, 0]], "478": [[55647540824814, 0], [241897106432097, 0], [70165863192672, 0], [156094545647300, 0], [85414622614139, 0], [31107207571820, 0], [141200092903812, 0], [147133684042058, 0], [65022284498835, 0]], "479": [[104020186415194, 0], [30981227519423, 0], [27464126688220, 0], [76853752704976, 0], [240787410372962, 0], [153654730556524, 0], [151445574281066, 0], [193574218015269, 0], [86029392448868, 0]]} \ No newline at end of file diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/meta.json b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/meta.json new file mode 100644 index 0000000..86b073c --- /dev/null +++ b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/meta.json @@ -0,0 +1 @@ +{"pred": []} \ No newline at end of file diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/seqno.json b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/seqno.json new file mode 100644 index 0000000..2ff8aaf --- /dev/null +++ b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/seqno.json @@ -0,0 +1 @@ +{"386": 3, "147": 2, "39": 3, "620": 2, "20": 68, "126": 2, "669": 3, "465": 2, "953": 2, "277": 626, "779": 147, "902": 2, "182": 6, "674": 2, "62": 2, "321": 1861, "135": 428, "127": 3, "297": 2, "522": 736} \ No newline at end of file diff --git a/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/snapshot_markers.json b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/snapshot_markers.json new file mode 100644 index 0000000..0a57015 --- /dev/null +++ b/hm_database/hbs/2017-01-10T210220Z/2017-01-10T210220Z-full/bucket-hbs/node-127.0.0.1%3A8091/snapshot_markers.json @@ -0,0 +1 @@ +{"386": [0, 3], "147": [0, 2], "39": [0, 3], "620": [0, 2], "20": [0, 68], "126": [0, 2], "669": [0, 3], "465": [0, 2], "953": [0, 2], "277": [0, 626], "779": [0, 147], "902": [0, 2], "182": [0, 6], "674": [0, 2], "62": [0, 2], "321": [0, 1861], "135": [0, 428], "127": [0, 3], "297": [0, 2], "522": [0, 736]} \ No newline at end of file diff --git a/hm_gameserver/.gitignore b/hm_gameserver/.gitignore new file mode 100644 index 0000000..8b29101 --- /dev/null +++ b/hm_gameserver/.gitignore @@ -0,0 +1,4 @@ +tags +*.pyc +*.swp +*.o diff --git a/hm_gameserver/CREDITS b/hm_gameserver/CREDITS new file mode 100644 index 0000000..fd2aaeb --- /dev/null +++ b/hm_gameserver/CREDITS @@ -0,0 +1 @@ +Filip Pancik diff --git a/hm_gameserver/LICENSE b/hm_gameserver/LICENSE new file mode 100644 index 0000000..e0345c0 --- /dev/null +++ b/hm_gameserver/LICENSE @@ -0,0 +1,622 @@ + GNU GENERAL PUBLIC LICENSE + + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/hm_gameserver/Makefile b/hm_gameserver/Makefile new file mode 100644 index 0000000..ff92cb1 --- /dev/null +++ b/hm_gameserver/Makefile @@ -0,0 +1,39 @@ +CFLAGS=-Wall -DMOD_$(mod) -g -Isrc/include -Isrc/include/proto -I../hm_base/src/include -I/usr/include/json-c/ -Iscript/mechanics/include #-DTURNOFF_TIMER -DMANA_ZERO -DTEST_DECK -DSPELL_ZERO_MANA +LIBS=-lev -lhmbase -lm -ljson-c -lcouchbase +LIBPATH=-L../hm_base/lib +TARGET=hm_gameserver + +SOURCES=$(shell find src -type f -iname '*.c') + +OBJECTS=$(foreach x, $(basename $(SOURCES)), $(x).o) + +all: base script hm_gameserver + +base: + $(MAKE) -C ../hm_base target=game + +hm_gameserver: + $(CC) $(SOURCES) $(CFLAGS) $(LIBPATH) -o $(TARGET) $(LIBS) + +script: + mkdir -p script/mechanics/include + cd script/ && python entities.py + cd script/mechanics/ && python main.py + cd script/ && python flags.py + cd script/ && python entities.py + cd script/mechanics/ && python main.py + +clean: + rm -f $(OBJECTS) $(TARGET) tags \ + script/flags_sections \ + script/mechanics/*.pyc \ + src/flag_def.c \ + src/proto/ent.c \ + src/proto/ent_sections.c \ + src/levelup.c \ + src/include/levelup.h \ + src/include/flag_def.h \ + src/include/proto/ent_gen.h \ + script/mechanics/include/*.h + +.PHONY: all hm_gameserver script diff --git a/hm_gameserver/README.md b/hm_gameserver/README.md new file mode 100644 index 0000000..90cd36d --- /dev/null +++ b/hm_gameserver/README.md @@ -0,0 +1,22 @@ +# hm_gameserver # + +hm_gameserver is a HearthStone hearthmod gameserver. This server daemon is part of hearthmod stack which allows user to create custom modes and cards. + +## Dependencies ## + +- libev >= 4.22 +- libjson-c >= 0.11 +- libcouchbase >= 2.5.8 +- libhmbase >= 0.1 + +## Compatiblity ## + +hm_gameserver is compatible with HearthStone client 5.2.x. + +## Compilation ## + +cd hm_gameserver && make + +# This is not a standalone project! + +[hm_gameserver](https://github.com/farb3yonddriv3n/hm_gameserver) is part of [hearthmod software stack](https://github.com/hearthmod/hearthmod) diff --git a/hm_gameserver/script/custom_mod b/hm_gameserver/script/custom_mod new file mode 100644 index 0000000..029c20c --- /dev/null +++ b/hm_gameserver/script/custom_mod @@ -0,0 +1,731 @@ +#!/bin/sh +# Game entity +name="Game Entity" card=GAME_ENTITY tags={10:85,20:1,49:1,198:4,202:1,204:2} + +# Mana Card +name="Coin" card=GAME_005 tags={49:3,202:5,313:1} + +# Player1 +name="Player1" card=PLAYER1 tags={7:75,17:1,27:64,28:10,29:4,30:1,31:1,49:1,176:10,202:2,272:1,399:4} + +# Player2 +name="Player2" card=PLAYER2 tags={7:75,17:1,23:1,24:1,27:66,28:10,29:4,30:2,31:2,49:1,176:10,202:2,272:1,399:3} + +# Power of the Horde +name="Kill Roshan" card=PRO_001c tags={183:11,202:5,48:30,330:0,331:0,} custom=1 + +# The Sentinel +name="The Sentinel" card=TB_SPT_Boss tags={183:18,202:3,47:0,45:30,380:39537,} custom=1 + +# The Scourge +name="The Scourge " card=LOEA04_01 tags={183:20,45:30,330:0,331:0,380:16231,202:3,} custom=1 + +# Enrage +name="Tether" card=NAX12_04e tags={183:12,202:6,330:0,331:0,338:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Lantern of Power +name="Grow" card=LOEA16_3e tags={183:20,202:6,330:0,331:0,} custom=1 flags=(CARD_ATTACHMENT) + +# Lothar's Left Greave +name="Arcane Boots" card=LOEA16_9 tags={183:20,202:5,48:0,330:0,331:0,} custom=1 + +# Mountain Giant +name="Tiny" card=EX1_105 tags={183:3,202:4,201:3,203:5,48:1,47:0,45:1,251:6,321:1,} custom=1 attachment=LOEA16_3e + +# Youthful Brewmaster +name="Youthful Brewmaster" card=EX1_049 tags={183:3,202:4,201:2,203:1,48:2,47:3,45:2,251:6,321:1,330:0,331:0,218:1,} custom=1 + +# Brann Bronzebeard +name="Karroch, the Beastmaster" card=LOE_077 tags={183:20,202:4,203:5,114:1,321:1,48:5,47:2,45:3,330:0,331:0,362:0,} custom=1 + +# Abomination +name="Pudge, the Butcher" card=EX1_097 tags={183:3,202:4,201:3,203:3,48:5,47:0,45:4,251:6,321:1,330:0,331:0,190:0,217:0,} custom=1 + +# Piloted Sky Golem +name="Boush, the Tinker" card=GVG_105 tags={183:13,321:1,48:3,202:4,203:4,47:1,45:2,200:17,330:0,331:0,217:1,} custom=1 + +# Icehowl +[AT_125] + +# Skeleton +name="Skeleton" card=NAX4_03H tags={183:12,202:4,48:7,47:6,45:5,} custom=1 + +# Skeleton Knight +name="The Skeleton King" card=AT_128 tags={183:15,321:1,203:5,202:4,48:7,47:6,45:5,114:1,330:0,331:0,217:1,} custom=1 + +# Deathwing +name="Deathwing" card=NEW1_030 tags={183:3,203:5,202:4,48:10,47:12,45:12,200:24,114:1,321:1,330:0,331:0,218:1,} custom=1 + +# Treant +name="Treant" card=EX1_158t tags={183:3,202:4,201:3,199:2,251:1,47:1,45:2,48:1,330:0,331:0,} custom=1 + +# Velen's Chosen +name="Guardian Greaves" card=GVG_010 tags={183:13,203:1,202:5,48:0,199:6,321:1,330:0,331:0,} custom=1 + +# Cabalist's Tome +name="Arcane Books" card=OG_090 tags={183:21,321:1,203:4,202:5,48:0,199:4,330:0,331:0,} custom=1 + +# Seal of Champions +name="Black King Bar" card=AT_074 tags={183:15,321:1,203:1,202:5,48:2,199:5,330:0,331:0,} custom=1 attachment=AT_074e2 + +# Seal of Champions E +name="Magic Immunity" card=AT_074e2 tags={183:15,202:6,199:5,330:0,331:0,} custom=1 flags=(CARD_ATTACHMENT) + +# Dagon +name="Dagon" card=BRMA11_3 tags={183:14,202:5,48:1,47:1,330:0,331:0,} custom=1 + +# Sparring Partner +[AT_069] + +# Divine Rapier E +name="Divine Rapier" card=FP1_020e tags={183:12,202:6,199:5,330:1,331:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Desolator +name="Desolator" card=LOEA06_03 tags={183:20,202:5,48:2,330:0,331:0,} custom=1 attachment=LOEA06_03e + +# Desolator E +name="Desolate" card=LOEA06_03e tags={183:20,202:6,330:0,331:0,} custom=1 flags=(CARD_ATTACHMENT) + +# Rooted +name="Level 2" card=EX1_178ae tags={183:3,202:6,199:2,330:1,331:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Inner Rage +name="Satanic" card=EX1_607 tags={183:3,203:5,202:5,48:3,201:3,199:10,321:1,} custom=1 attachment=EX1_607e + +# Angry Chicken +name="Courier" card=EX1_009 tags={321:1,183:3,203:3,202:4,48:1,47:2,45:1,330:0,331:0,200:20,212:1,} custom=1 + +# Repel +[LOEA16_20] + +# Cursed Blade +name="Echo Sabre " card=LOE_118 tags={183:20,321:1,203:3,202:7,48:2,47:0,187:3,199:10,330:0,331:0,} custom=1 + +# Shadowflame +name="Requiem of Souls" card=EX1_303 tags={183:3,202:5,201:3,199:9,203:3,48:4,251:1,268:2,321:1,330:0,331:0,370:1,} custom=1 + +# Demonfire E +name="Necromastery" card=EX1_596e tags={183:3,203:1,202:6,48:0,201:3,199:9,330:1,331:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Void Crusher +name="Eidolon" card=AT_023 tags={183:15,321:1,203:3,202:4,48:2,47:2,45:2,199:9,200:15,330:0,331:0,403:0,} custom=1 + +# Forbidden Shaping +name="Demonic Conversion" card=OG_101 tags={183:21,321:1,203:4,202:5,48:3,199:6,330:0,331:0,} custom=1 + +# Charge E +name="Level 1" card=CS2_103e2 tags={183:2,202:6,199:10,330:0,331:0,} custom=1 flags=(CARD_ATTACHMENT) + +# Inner Rage E +name="Satanic" card=EX1_607e tags={183:3,202:6,199:10,330:1,331:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Inner Fire E +name="Level 3" card=CS1_129e tags={183:3,202:6,199:6,330:1,331:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Twisting Nether +name="The Black Hole" card=EX1_312 tags={183:3,202:5,201:3,199:9,203:4,48:8,251:1,268:2,321:1,330:0,331:0,} custom=1 + +# Mal Ganis +[GVG_021] + +# Lay on Hands +name="Purification" card=EX1_354 tags={183:3,202:5,201:3,199:5,203:4,48:8,251:1,321:1,330:0,331:0,} custom=1 + +# Flame Lance +name="Laguna Blade" card=AT_001 tags={183:15,321:1,203:1,202:5,48:8,199:4,47:10,330:0,331:0,} custom=1 + +# Dragon's Breath +name="Dragon's Breath" card=BRM_003 tags={183:14,321:1,203:1,202:5,48:3,199:4,47:2,330:0,331:0,} custom=1 + +# Confessor Paletress +name="Lina" card=AT_018 tags={183:15,321:1,203:5,202:4,48:2,47:1,45:14,199:6,114:1,330:0,331:0,200:16,} custom=1 level2=BRM_003 level3=AT_001 + +# Lightning Storm +name="God's Wrath" card=EX1_259 tags={183:3,202:5,201:3,199:8,203:3,48:6,251:1,47:3,321:1,330:0,331:0,215:1,} custom=1 + +# Forked Lightning +name="Forked Lightning" card=EX1_251 tags={183:3,202:5,201:3,199:8,203:1,48:2,251:1,47:1,321:1,330:0,331:0,215:1,} custom=1 + +# Archmage Antonidas +name="Zeus" card=EX1_559 tags={183:3,203:5,202:4,48:3,47:1,45:15,201:3,251:3,199:4,114:1,321:1,330:0,331:0,32:1,} custom=1 level2=EX1_251 level3=EX1_259 + +# Commanding Shout +name="Warcry" card=NEW1_036 tags={183:3,203:3,202:5,48:1,199:10,321:1,330:0,331:0,} custom=1 attachment=NEW1_036e + +# Commanding Shout +name="Sven: Warcry" card=NEW1_036e tags={183:3,202:6,199:10,330:0,331:0,338:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Druid of the Claw +name="Ursa" card=EX1_165t2 tags={183:3,203:5,202:4,48:4,47:3,45:21,199:2,330:0,331:0,200:20,190:0,} custom=1 level2=CS2_012 level3=CS2_011 + +# Open Wounds +name="Wounded" card=AT_039e tags={183:15,202:6,199:2,330:0,331:0,338:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Divine Strength +name="God's Strength" card=OG_223 tags={183:21,321:1,203:1,202:5,48:3,199:5,} custom=1 attachment=OG_223e + +# Optimism +name="Sven: God's Strength" card=OG_223e tags={183:21,202:6,} custom=1 flags=(CARD_ATTACHMENT) + +# Tirion Fordring +name="Sven" card=EX1_383 tags={183:3,203:5,202:4,48:3,47:3,45:16,201:3,199:5,251:1,114:1,321:1,330:0,331:0,194:0,190:0,217:0,} custom=1 level2=NEW1_036 level3=OG_223 + +# Windfury +[CS2_039] + +# Corruption +name="Corruption" card=CS2_063 tags={183:2,202:5,201:3,199:9,203:1,48:1,251:1,321:1,330:0,331:0,} custom=1 attachment=CS2_063e +# Corruption E +name="Corruption" card=CS2_063e tags={183:2,202:6,199:9,330:2,331:2,} custom=1 flags=(CARD_ATTACHMENT) + +# Hunter's Mark +[CS2_084] attachment=CS2_084e +# Hunter's Mark E +name="Hunter's Mark E" card=CS2_084e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Assasinate +name="Assassinate" card=CS2_076 tags={183:2,202:5,201:3,199:7,203:2,48:5,251:6,268:2,321:1,330:0,331:0,} custom=1 + +# Shadow Word: Death +[EX1_622] + +# Shadow Word: Pain +name="Shadow Word: Pain" card=CS2_234 tags={321:1,183:2,203:2,202:5,48:2,199:6,330:0,331:0,} custom=1 + +# Execute +name="Culling Blade" card=CS2_108 tags={183:2,202:5,201:3,199:10,203:2,48:3,251:1,268:2,321:1,330:0,331:0,} custom=1 + +# Illidan +name="Terrorblade" card=EX1_614 tags={183:3,203:5,202:4,48:6,45:1,47:5,201:3,251:6,114:1,321:1,330:0,331:0,200:15,32:1,} custom=1 + +# Hand of Protection +name="Guardian Angel" card=EX1_371 tags={183:2,203:2,202:5,48:2,199:5,201:3,251:1,321:1,330:0,331:0,} custom=1 + +# Polymorph +[CS2_022] attachment=CS2_022e +name="Polymorph E" card=CS2_022e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Hex +[EX1_246] attachment=EX1_246e +# Hex E +name="Hex E" card="EX1_246e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Blessing of Kings +[CS2_092] attachment=CS2_092e +# Blessing of Kings E +name="Blessing of Kings E" card="CS2_092e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Blessing of Might +[CS2_087] attachment=CS2_087e +# Blessing of Might E +name="Blessing of Might E" card="CS2_087e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Power Word: Shield +[CS2_004] attachment=CS2_004e +# Power Word: Shield E +name="Power Word: Shield E" card="CS2_004e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Charge +[CS2_103] attachment=CS2_103e2 +# Charge E +#name="Charge E" card="CS2_103e2" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Mark of the Wild +[CS2_009] attachment=CS2_009e +# Mark of the Wild E +name="Mark of the Wild E" card="CS2_009e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Ancestral Healing +[CS2_041] attachment=CS2_041e +# Ancestral Infusion +name="Ancestral Infusion" card="CS2_041e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Rockbiter Weapon +[CS2_045] attachment=CS2_045e +# Rockbiter Weapon E +name="Rockbiter Weapon E" card=CS2_045e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Divine spirit +[CS2_236] + +# Bloodlust +[CS2_046] attachment=CS2_046e +# Bloodlust E +name="Bloodlust E" card=CS2_046e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Claw +[CS2_005] attachment=CS2_005o +# Claw E +name="Claw E" card=CS2_005o tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Heroic Strike +[CS2_105] attachment=CS2_105e +# Heroic Strike E +name="Heroic Strike E" card=CS2_105e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Savage Roar +name="Enrage" card=CS2_011 tags={183:2,202:5,201:3,199:2,203:1,48:3,251:1,321:1,330:0,331:0,} custom=1 attachment=CS2_011o +# Savage Roar E +name="Enraged" card=CS2_011o tags={183:2,202:6,199:2,330:1,331:1,338:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Warrior +name="Warrior" card=HERO_01 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Shamman +name="Shamman" card=HERO_02 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Rogue +#name="Rogue" card=TB_SPT_Boss tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Paladin +name="Paladin" card=HERO_04 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Hunter +name="Hunter" card=HERO_05 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Druid +name="Druid" card=HERO_06 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Warlock +name="Warlock" card=HERO_07 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Mage +name="Mage" card=HERO_08 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Priest +#name="Priest" card=LOEA04_01 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# King of Khaz Modan +name="King of Khaz Modan" card=HERO_01a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Blood Knight Matriarch +name="Blood Knight Matriarch" card=HERO_04a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Alleria Windranger +name="Alleria Windranger" card=HERO_05a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Guardian Medivh +name="Guardian Medivh" card=HERO_08a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Khadgar +name="Khadgar" card=HERO_08b tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) + +# Ice lance +#CS2_031 tags={12:1,47:0,48:1,49:3,201:3,202:5,203:2,264:1} flags=(CARD_SPELL|CARD_SPELL_DAMAGE|CARD_TARGETING|CARD_FREEZE|CARD_TARGET_FROZEN_4_DMG) + +# Holy Smite +[CS1_130] + +# Fireball +[CS2_029] + +# Swipe +name="Swipes" card=CS2_012 tags={183:2,202:5,201:3,199:2,203:1,48:2,251:1,47:2,321:1,330:0,331:0,} custom=1 attachment=AT_039e + +# Hammer of Wrath +[CS2_094] + +# Backstab +name="Backstab" card=CS2_072 tags={183:2,202:5,201:3,199:7,203:2,251:6,48:0,47:2,268:2,321:1,330:0,331:0,} custom=1 + +# Drain Life +[CS2_061] + +# Sacrificial Pact +[NEW1_003] + +# Arcane Shot +name="Arcane Shot" card=DS1_185 tags={183:2,202:5,201:3,199:3,203:2,48:1,251:8,47:2,321:1,} custom=1 + +# Soulfire +[EX1_308] + +# Mortal Coil +[EX1_302] + +# Shield Block +[EX1_606] + +# Shiv +[EX1_278] + +# Starfire +[EX1_173] + +# Moonfire +[CS2_008] + +# Kill Command +[EX1_539] + +# Frostbolt +name="Frostbolt" card=CS2_024 tags={183:2,202:5,201:3,199:4,203:1,48:2,251:1,47:3,268:2,321:1,208:1,} custom=1 + +# Frost Shock +[CS2_037] + +# Shadow Bolt +[CS2_057] + +# Feral Rage - choose one +#OG_047 tags={12:1,48:2,49:3,201:3,202:5,203:2,264:1} flags=(CARD_SPELL|CARD_SPELL_DAMAGE|CARD_NONTARGET) + +# Arcane intellect +name="Arcane Intellect" card=CS2_023 tags={183:2,202:5,201:3,199:4,203:2,48:3,251:1,268:2,321:1,330:0,331:0,} custom=1 + +# Sprint +name="Sprint" card=CS2_077 tags={183:2,202:5,201:3,199:7,203:1,48:7,251:1,268:2,321:1,330:0,331:0,} custom=1 + +# Arcane Explosion +[CS2_025] + +# Arcane Missiles +[EX1_277] + +# Tracking +[DS1_184] + +# Sinister Strike +[CS2_075] + +# Mind Blast +[DS1_233] + +# Frost Nova +name="Shiva's Guard" card=CS2_026 tags={183:2,202:5,201:3,199:4,203:1,48:3,251:1,47:1,268:2,321:1,330:0,331:0,208:1,} custom=1 + +# Fan of Knives +[EX1_129] + +# Cleave +[CS2_114] + +# Multishot +[DS1_183] + +# Mind Vision +[CS2_003] + +# Flamestrike +[CS2_032] + +# Whirlwind +name="Counter Helix" card=EX1_400 tags={183:2,202:5,201:3,199:10,203:1,48:0,251:1,47:1,321:1,330:0,331:0,} custom=1 + +# Consecration +[CS2_093] + +# Holy Nova +name="Mekansm" card=CS1_112 tags={183:2,202:5,201:3,199:6,203:1,48:4,251:5,321:1,330:0,331:0,} custom=1 + +# Hellfire +[CS2_062] + +# Water Elemental +[CS2_033] + +################ +# Aura +############### + +# Raid leader +[CS2_122] attachment=CS2_122e +# Enhanced +name="Enhanced" card=CS2_122e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Stormwind champion +name="Stormwind Champion" card=CS2_222 tags={183:2,202:4,201:2,203:1,48:7,47:6,45:6,251:1,321:1,330:0,331:0,362:1,} custom=1 attachment=CS2_222o +# Might of Stormwind +name="Might of Stormwind" card=CS2_222o tags={183:2,202:6,330:1,331:0,} custom=1 flags=(CARD_ATTACHMENT) + +# Warsong Commander +[EX1_084] attachment=EX1_084e +# Charge +name="Charge" card=EX1_084e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Timber Wolf +[DS1_175] attachment=DS1_175o +# Furious Howl +name="Furious Howl" card=DS1_175o tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Gurubashi Berserker +[EX1_399] attachment=EX1_399e +# Berserking +name="Berserking" card=EX1_399e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + + +################ +# Battlecry +############### + +# Dread Infernal +[CS2_064] + +# Novice engineer +[EX1_015] + +# Gnomish Inventor +[CS2_147] + +# Darkscale Healer +[DS1_055] + +# Guardian of Kings +name="Omniknight" card=CS2_088 tags={183:2,202:4,201:3,199:5,203:1,48:2,251:5,45:17,47:1,321:1,218:1,} custom=1 + +# Nightblade +name="Phantom Assassin" card=EX1_593 tags={183:2,203:2,202:4,48:4,45:2,47:4,201:3,321:1,218:1,} custom=1 + +# Acidic Swamp Ooze +[EX1_066] + +# Voodoo doctor +name="Witch Doctor" card=EX1_011 tags={183:2,202:4,201:1,203:2,48:1,47:2,45:1,251:6,321:1,218:1,} custom=1 + +# Elven Archer +[CS2_189] + +# Fire Elemental +name="Fire Elemental" card=CS2_042 tags={183:2,202:4,201:3,199:8,203:1,48:6,47:6,45:5,251:3,321:1,218:1,} custom=1 + +# Ironforge Rifleman +[CS2_141] + +# Stormpike Commando +[CS2_150] + +# Frostwolf Warlord +name="Legion Commander" card=CS2_226 tags={183:2,202:4,201:1,203:4,48:5,47:4,45:4,251:1,321:1,330:0,331:0,218:1,} custom=1 attachment=CS2_226e +# Frostwolf Banner +name="Frostwolf Banner" card=CS2_226e tags={183:2,202:6,330:1,331:1,} custom=1 flags=(CARD_ATTACHMENT) + +# Succubus +name="Queen of Pain" card=EX1_306 tags={183:2,202:4,201:3,199:9,200:15,203:2,48:3,47:4,45:3,251:1,268:2,321:1,218:1,} custom=1 + +# Sap +name="Sap" card=EX1_581 tags={183:2,203:2,202:5,48:2,201:3,199:7,268:2,321:1,330:0,331:0,} custom=1 + +# Mind Control +[CS1_113] attachment=CS1_113e +# Mind Control E +name="Mind Control E" card=CS1_113e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Vanish +[NEW1_004] + +################ +# Spell damage +############### + +# Archmage +[CS2_155] + +# Dalaran mage +[EX1_582] + +# Kobold geomancer +[CS2_142] + +# Ogre magi +[CS2_197] + +################ +# Charge +############### + +# Wolfirder +[CS2_124] + +# Bluegill warrior +[CS2_173] + +# Kor'kron elite +name="Mogul Khan, Axe" card=NEW1_011 tags={183:2,203:5,202:4,321:1,330:0,331:0,48:3,47:2,45:20,199:10,197:0,} custom=1 level3=CS2_108 + +# Stormwind knight +[CS2_131] + +# Reckless rocketeer +[CS2_213] + +# Stonetusk boar +name="Stonetusk Boar" card=CS2_171 tags={183:2,202:4,201:3,200:20,203:2,48:1,47:1,45:1,251:6,268:2,321:1,197:0,} custom=1 + +# Huffer +[NEW1_034] flags=(CARD_UNCOLLECTIBLE) + +################ +# Divine shield +############### + +# Scarlet Crusader +[EX1_020] + +################ +# Taunt +############### + +# Lord of the Arena +[CS2_162] + +# Booty bay bodyguard +[CS2_187] + +# Frostwolf Grunt +[CS2_121] + +# Goldshire footman +[CS1_042] + +# Ironbark protector +[CS2_232] + +# Sen'jin Shieldmasta +[CS2_179] + +# Voidwalker +name="Enigma" card=CS2_065 tags={183:2,202:4,201:3,199:9,200:15,203:5,48:2,45:15,251:9,47:1,268:2,321:1,190:0,} custom=1 level2=OG_101 level3=EX1_312 + +# Misha +[NEW1_032] flags=(CARD_UNCOLLECTIBLE) + +# Frog +[hexfrog] flags=(CARD_UNCOLLECTIBLE) + +################ +# Totem +############### + +# Wrath of Air Totem +[CS2_052] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Stoneclaw Totem +[CS2_051] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Searing Totem +[CS2_050] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Healing Totem +[NEW1_009] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Flametongue Totem +[EX1_565] attachment=EX1_565o +# Flametongue +name="Flametongue" card=EX1_565o tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +################ +# Summon +############### + +# Mirror Image +[CS2_027] +# Mirror Image +[CS2_mirror] + +# Animal Companion +[NEW1_031] + +# Dragonling Mechanic +[EX1_025] +# Mechanical Dragonling +[EX1_025t] flags=(CARD_UNCOLLECTIBLE) + +# Murloc Tidehunter +[EX1_506] +# Murloc Scout +name="Murloc Scout" card=EX1_506a tags={183:2,202:4,201:3,200:14,203:1,47:1,45:1,251:1,48:0,} custom=1 flags=(CARD_UNCOLLECTIBLE) + +# Razorfen Hunter +[CS2_196] + +# Leokk +[NEW1_033] flags=(CARD_UNCOLLECTIBLE) + +# Starving Buzzard +name="Vulture" card=CS2_237 tags={321:1,183:2,203:1,202:4,48:1,47:1,45:1,199:3,200:20,330:0,331:0,32:1,} custom=1 + +# Sheep +[CS2_tk1] flags=(CARD_UNCOLLECTIBLE) + +# Avator of the Coin +[GAME_002] flags=(CARD_UNCOLLECTIBLE) + +# Boar +name="Boar" card=CS2_boar tags={183:2,202:4,201:3,203:1,47:1,45:1,251:1,48:1,200:20,330:0,331:0,} custom=1 flags=(CARD_UNCOLLECTIBLE) +# Oasis Snapjaw +name="Oasis Snapjaw" card=CS2_119 tags={321:1,183:2,203:2,202:4,48:4,47:2,45:7,200:20,} custom=1 +# Bloodfen Raptor +name="Bloodfen Raptor" card=CS2_172 tags={183:2,203:2,202:4,48:2,45:2,47:3,201:1,251:1,268:2,321:1,200:20,} custom=1 +# Magma Rager +name="Shadow Fiend" card=CS2_118 tags={321:1,183:2,203:5,202:4,48:2,47:1,45:14,330:0,331:0,} custom=1 level3=EX1_303 + +# Puddlestomper +#GVG_064 tags={12:1,45:2,47:3,48:2,49:3,202:4,203:2} flags=(CARD_MINION) +# Wisp +name="Wisp" card=CS2_231 tags={183:3,203:1,202:4,48:2,45:2,47:0,201:3,251:7,} custom=1 attachment=NAX12_04e + +# Core Hound +name="Core Hound" card=CS2_201 tags={321:1,183:2,203:1,202:4,48:7,47:9,45:5,200:20,} custom=1 + +# Murloc Raider +name="Murloc Raider" card=CS2_168 tags={183:2,202:4,201:2,203:2,48:1,47:2,45:1,251:1,321:1,200:14,} custom=1 + +# River Crocolisk +name="River Crocolisk" card=CS2_120 tags={321:1,183:2,203:2,202:4,48:2,47:2,45:3,200:20,} custom=1 + +# Boulderfist Ogre +name="Boulderfist Ogre" card=CS2_200 tags={321:1,183:2,203:2,202:4,48:6,47:6,45:7,} custom=1 + +# Chillwind Yeti +name="Chillwind Yeti" card=CS2_182 tags={183:2,202:4,201:3,203:1,48:4,47:4,45:5,251:6,268:2,321:1,330:0,331:0,} custom=1 + +# Fireblast +name="Fireblast" card=CS2_034 tags={12:1,47:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_TARGETING|CARD_SPELL|CARD_HP_SPELL_DAMAGE) + +# Lesser Heal +# name="Lesser Heal" card=CS1h_001 tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_TARGETING|CARD_SPELL|CARD_SPELL_HEAL) + +# Lesser Heal +name="Lesser Heal" card=CS1h_001 tags={183:2,202:10,201:3,199:6,203:2,48:2,251:1,} custom=1 + +# Healing Touch +[CS2_007] + +# Holy Light +[CS2_089] + +# Reinforce +name="Reinforce" card=CS2_101 tags={12:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_REINFORCE|CARD_SUMMON) +# Silverhand Recruit +[CS2_101t] flags=(CARD_MINION|CARD_UNCOLLECTIBLE) + +# Dagger Mastery +name="Dagger Mastery" card=CS2_083b tags={12:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_DAGGERMASTERY|CARD_SUMMON) + +################ +# Weapon +############### + +# Wicked Knife +[CS2_082] flags=(CARD_UNCOLLECTIBLE) + +# Assassin's Blade +[CS2_080] + +# Truesilver Champion +name="Divine Rapier" card=CS2_097 tags={183:2,202:7,201:3,199:5,203:1,48:5,47:8,187:1,251:6,321:1,330:0,331:0,32:1,} custom=1 + +# Fiery War Axe +[CS2_106] + +# Light's Justice +[CS2_091] + +# Arcanite reaper +[CS2_112] + +############## + +# Totemic Call +[CS2_049] tags={12:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_SUMMON|CARD_HP_TOTEMIC_CALL) + +# Shapeshift +[CS2_017] tags={12:1,47:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_SHAPESHIFT|CARD_SUMMON) + +# Armor Up +[CS2_102] tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_ARMORUP|CARD_SUMMON) + +# Life Tap +[CS2_056] tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_LIFETAP|CARD_SUMMON) + +# Steady Shot +[DS1h_292] tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_TARGETING|CARD_SPELL|CARD_HP_SPELL_DAMAGE|CARD_TARGET_HERO) + +# Empty mana card +name="Empty card" card=MANA_CARD tags={12:1,49:3,263:5} flags=(CARD_UNCOLLECTIBLE) + +# No card +name="No Card" card=NO_CARD tags={49:2} flags=(CARD_UNCOLLECTIBLE) diff --git a/hm_gameserver/script/entities.py b/hm_gameserver/script/entities.py new file mode 100644 index 0000000..511da45 --- /dev/null +++ b/hm_gameserver/script/entities.py @@ -0,0 +1,274 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +import os +import sys +import shlex + +allflags = [] +index = 0 + +def parse(src): + global allflags + global index + entities = [] + f = open(src, "r") + + ri = 0 + + lines = f.readlines(); + for l in lines: + ri = ri + 1 + if(len(l) < 10): # new lines + continue + if(l[0] == "#"): # comment + continue + + arr = shlex.split(l) + + f = '' + att = '' + custom = '' + c = '' + t = '' + level2 = '' + level3 = '' + + for a in arr: + sub = a.split("=") + if(len(sub) != 2): + continue + + if(sub[0] == "name"): + n = sub[1] + elif(sub[0] == "card"): + c = sub[1] + elif(sub[0] == "tags"): + t = sub[1] + elif(sub[0] == "flags"): + f = sub[1] + elif(sub[0] == "attachment"): + att = sub[1] + elif(sub[0] == "custom"): + custom = sub[1] + elif(sub[0] == "level2"): + level2 = sub[1] + elif(sub[0] == "level3"): + level3 = sub[1] + else: + print 'parsing %s failed' % sub[0] + exit(1) + + if(len(c) == 0 or len(t) == 0): + continue + + d = {} + + if(len(level2) > 0): + d['level2'] = level2 + + if(len(level3) > 0): + d['level3'] = level3 + + d['desc'] = n + d['name'] = c + + if(len(f) > 0): + flags = f.replace("\n", "") + allflags.append([index, flags, d['name']]) + d['rawflags'] = flags + + d['flags'] = '{{0, 0, 0, 0, 0, 0, 0, 0}}' + + if(len(att) > 0): + d['attachment'] = att + + d['tags'] = {} + if(len(t) > 0): + properties = t.replace(",}", "}").split(",") + for p in properties: + a = p.split(":") + idx = a[0].replace("{", "") + tz = a[1].replace("\n", "").replace("}", "") + d['tags'][idx] = tz + + if(len(custom) > 0): + d['custom'] = custom + print 'Active card: ' + d['desc'] + ' [' + d['name'] + ']' + + entities.append(d) + + index = index + 1 + return entities + +def gen_js_cards(e): + out = 'var cards = [\n' + for d in e : + for key in d: + if(key == 'rawflags'): + if((d[key].find("CARD_MINION") > -1 or d[key].find("CARD_SPELL") > -1) and\ + d[key].find("CARD_UNCOLLECTIBLE") == -1 and d[key].find("CARD_HERO") == -1 and\ + d[key].find("CARD_HEROPOWER") == -1 + ): + out += '["%s", "%s"], \n' % (d['name'], d['desc']) + + out += '];' + + f = open("cards.js", "w") + f.write(out) + f.close() + +def gen_js_hp(e): + out = 'var cards_hp = [\n' + for d in e : + for key in d: + if(key == 'rawflags'): + if(d[key].find("CARD_HEROPOWER") > -1): + out += '["%s", "%s"], \n' % (d['name'], d['desc']) + + out += '];' + + f = open("cards_hp.js", "w") + f.write(out) + f.close() + +def gen_js_hero(e): + out = 'var cards_hero = [\n' + for d in e : + for key in d: + if(key == 'rawflags'): + if(d[key] == "(CARD_HERO)"): + out += '["%s", "%s"], \n' % (d['name'], d['desc']) + + out += '];' + + f = open("cards_hero.js", "w") + f.write(out) + f.close() + +def gen(e): + out = '#include \n' + out += '#include \n' + header = '#ifndef ENTGEN_H_\n#define ENTGEN_H_\n\n#define MAX_ENTITIES %d\n' % len(e) + out += 'struct ent_s entities[MAX_ENTITIES] = {' + index = 0 + beasts = [] + totems = [] + totemic_call = [] + hp = [] + + for d in e: + flags = '' + attch = '(void *)0, ' + val = '{' + level2 = "(void *)0, " + level3 = "(void *)0, " + + for key in d: + if(key == 'name'): + start = '{ "%s", %d, %d, ' % (d[key], len(d[key]), len(d['tags'])) + elif(key == 'desc'): + desc = '"%s", ' % d[key] + elif(key == 'level2'): + level2 = '"%s", ' % d[key] + elif(key == 'level3'): + level3 = '"%s", ' % d[key] + elif(key == 'flags'): + flags = '%s, ' % d[key] + elif(key == 'attachment'): + attch = "\"%s\", " % d[key] + elif(key == 'rawflags'): + tt = 1 + elif(key == 'custom'): + tt = 1 + elif(key == 'tags'): + for k, v in d[key].items(): + val += '{ %s, %s }, ' % (k, v) + + val += ' }} // %d \n, ' % index + + out += start + level2 + level3 + desc + flags + attch + val + index = index + 1 + + out += '};' + + out += '\n\nvoid entities_init() {\n' + for i in allflags: + arr = i[1].split("|") + for a in arr: + cm = a.replace("(", "").replace(")", "") + if(cm == "CARD_RACE_BEAST"): + beasts.append(i[2]) + if(cm == "CARD_RACE_TOTEM"): + totems.append(i[2]) + if(cm == "CARD_TOTEMIC_CALL_CHILD"): + totemic_call.append(i[2]) + if(cm == "CARD_HEROPOWER"): + hp.append(i[2]) + + out += '\tflag(&entities[%s].flags, %s, FLAG_SET);\n' % (i[0], cm) + + out += '}\n' + header += "#define MAX_BEASTS %d\n" % len(beasts) + header += "#define MAX_TOTEMS %d\n" % len(totems) + header += "#define MAX_TOTEMIC_CALL %d\n" % len(totemic_call) + header += "#define MAX_HEROPOWER %d\n" % len(hp) + + out += "const char *race_beast[MAX_BEASTS] = {\n" + for b in beasts: + out += "\t\"%s\",\n" % b + out += "};\n" + + out += "const char *race_totems[MAX_TOTEMS] = {\n" + for b in totems: + out += "\t\"%s\",\n" % b + out += "};\n" + + out += "const char *totemic_call[MAX_TOTEMIC_CALL] = {\n" + for b in totemic_call: + out += "\t\"%s\",\n" % b + out += "};\n" + + out += "const char *hp_list[MAX_HEROPOWER] = {\n" + for b in hp: + out += "\t\"%s\",\n" % b + out += "};\n" + + f = open("../src/proto/ent.c", "w") + f.write(out) + f.close() + + header += "const char *totemic_call[MAX_TOTEMIC_CALL];\n" + header += "const char *race_beast[MAX_BEASTS];\n" + header += "const char *race_totems[MAX_TOTEMS];\n" + header += "\n#endif" + f = open("../src/include/proto/ent_gen.h", "w") + f.write(header) + f.close() + +if __name__ == '__main__': + basic = parse("custom_mod") + #classic = parse("cards/classic") + + #e = basic + classic + e = basic + + gen(e) + #gen_js_cards(e) + #gen_js_hp(e) + #gen_js_hero(e) + print 'total entities: %d' % len(e) diff --git a/hm_gameserver/script/flags b/hm_gameserver/script/flags new file mode 100644 index 0000000..2127340 --- /dev/null +++ b/hm_gameserver/script/flags @@ -0,0 +1,188 @@ + MECHANICS_DAMAGE , 1000 + MECHANICS_HEALTH , 1000 + MECHANICS_ATTACK , 1000 + MECHANICS_ATTACK_DAMAGE, 1000 + MECHANICS_ATTACK_HEAL, 1000 + MECHANICS_HEROPOWER, 1000 + MECHANICS_BATTLECRY_TRIGGER , 1000 + MECHANICS_CHANGESIDES, 1000 + MECHANICS_ARMOR, 1000 + MECHANICS_DURABILITY, 1000 + MECHANICS_DETACH, 1000 + MECHANICS_SELECTED, 1000 + MECHANICS_DESTROY_WEAPON, 1000 + MECHANICS_TURN_TRIGGER, 1000 + MECHANICS_COST, 1000 + CARD_HAND , 1000 + CARD_DESTROYED , 1001 + CARD_BOARD , 1000 + CARD_EXHAUSTED , 1000 + CARD_HERO , 1000 + CARD_HEROPOWER , 1000 + CARD_HEROWEAPON, 1000 + CARD_BOSS, 1000 + CARD_TARGETING , 1000 + CARD_NONTARGET , 1000 + CARD_NONTARGET_BC , 1000 + CARD_SPELL , 1000 + CARD_SPELL_HEAL , 1000 + CARD_SPELL_DAMAGE , 1000 + CARD_HP_REINFORCE , 1000 + CARD_HP_DAGGERMASTERY , 1000 + CARD_HP_ARMORUP , 1000 + CARD_HP_LIFETAP , 1000 + CARD_HP_SHAPESHIFT , 1000 + CARD_WINDFURY , 1000 + CARD_DECK , 1000 + CARD_TARGET_HERO , 1000 + CARD_TARGET_MINIONS , 1000 + CARD_TARGET_ENEMY_HERO , 1000 + CARD_TARGET_ENEMY_MINIONS , 1000 + CARD_TARGET_ALLY_HERO , 1000 + CARD_TARGET_ALLY_MINIONS , 1000 + CARD_TARGET_ALLY, 1000 + CARD_TARGET_ENEMY, 1000 + CARD_TARGET_ALL, 1000 + CARD_HP_SPELL_DAMAGE , 1000 + CARD_INNERFIRE , 1000 + CARD_AOE_ENEMY_MINIONS , 1000 + CARD_AOE_ALLENEMY , 1000 + CARD_CHARGE , 1000 + CARD_DIVINE_SHIELD , 1000 + CARD_FREEZE , 1000 + CARD_FROZEN , 1000 + CARD_TARGET_FROZEN_4_DMG , 1000 + CARD_BATTLECRY , 1000 + CARD_BATTLECRY_DAMAGE3_ENEMY_HERO , 1000 + CARD_BATTLECRY_TARGET , 1000 + CARD_BATTLECRY_HEAL2_TARGET , 1000 + CARD_BATTLECRY_DRAW1_CARD, 1000 + CARD_DRAW2_CARD, 1000 + CARD_DRAW4_CARD, 1000 + CARD_DRAW_CARD, 1000 + CARD_MINION, 1000 + CARD_BUFF , 1000 + CARD_DIVINESPIRIT, 1000 + CARD_AOE, 1000 + CARD_AOE_TARGET_ALL, 1000 + CARD_HEAL_ALLIES, 1000 + CARD_BATTLECRY_DAMAGE1_ALL, 1000 + CARD_AOE_MINIONS, 1000 + CARD_SUMMON, 1000 + CARD_WEAPON_ROCKBITER, 1000 + CARD_WEAPON, 1000 + CARD_BOARD_WEAPON, 1000 + CARD_SUMMON_CS2_MIRROR, 1000 + CARD_BLESSING_OF_KINGS, 1000 + CARD_BLOODLUST, 1000 + CARD_BUFF_AOE, 1000 + CARD_CORRUPTION, 1000 + CARD_CORRUPTED, 1000 + CARD_ATTACHMENT, 1000 + CARD_RAID_LEADER, 1000 + CARD_AURA, 1000 + CARD_STORMWIND_CHAMPION, 1000 + CARD_RACE_BEAST, 1000 + CARD_RACE_MURLOC, 1000 + CARD_TAUNT, 1000 + CARD_SPELLPOWER, 1000 + CARD_SAP, 1000 + CARD_VANISH, 1000 + CARD_SUMMON_ANIMAL_COMPANION, 1000 + CARD_UNCOLLECTIBLE, 1000 + CARD_BATTLECRY_SUMMON_DRAGONLING_MECHANIC, 1000 + CARD_RACE_MECH, 1000 + CARD_LEOKK, 1000 + CARD_BATTLECRY_SUMMON_MURLOC_SCOUT, 1000 + CARD_BATTLECRY_SUMMON_BOAR, 1000 + CARD_BATTLECRY_SUMMON, 1000 + CARD_RACE_TOTEM, 1000 + CARD_RACE_DEMON, 1000 + CARD_TURN_HEAL1_MINIONS, 1000 + CARD_TOTEMIC_CALL_CHILD, 1000 + CARD_HP_TOTEMIC_CALL, 1000 + CARD_BATTLECRY_HEAL2_ALIES, 1000 + CARD_BATTLECRY_HEAL6_ALLY_HERO, 1000 + CARD_BATTLECRY_DAMAGE1_TARGET, 1000 + CARD_BATTLECRY_DAMAGE2_TARGET, 1000 + CARD_BATTLECRY_DAMAGE3_TARGET, 1000 + CARD_BATTLECRY_FROSTWOLF_WARLORD, 1000 + CARD_BATTLECRY_DISCARD1_CARD, 1000 + CARD_DISCARD, 1000 + CARD_MIND_CONTROL, 1000 + CARD_AOE_CLEAVE, 1000 + CARD_FAN_OF_KNIVES, 1000 + CARD_KILL_COMMAND, 1000 + CARD_MIND_VISION, 1000 + CARD_DAMAGE_DRAW_CARD, 1000 + CARD_SOULFIRE, 1000 + CARD_MORTAL_COIL, 1000 + CARD_DRAW1_CARD, 1000 + CARD_ARMOR5, 1000 + CARD_TRUESILVER_CHAMPION, 1000 + CARD_STARVING_BUZZARD, 1000 + CARD_SAVAGE_ROAR, 1000 + CARD_WARSONG_COMMANDER, 1000 + CARD_TIMBER_WOLF, 1000 + CARD_FLAMETONGUE_TOTEM, 1000 + CARD_GURU_BERSERKER, 1000 + CARD_CLAW, 1000 + CARD_MARK_OF_THE_WILD, 1000 + CARD_HUNTERS_MARK, 1000 + CARD_AOE_MULTISHOT, 1000 + CARD_ANCESTRAL_HEALING, 1000 + CARD_ROCKBITER_WEAPON, 1000 + CARD_DRAIN_LIFE, 1000 + CARD_SINISTER_STRIKE, 1000 + CARD_ASSASINATE, 1000 + CARD_MIND_BLAST, 1000 + CARD_HAND_OF_PROTECTION, 1000 + CARD_CHARGE_BUFF, 1000 + CARD_HEROIC_STRIKE, 1000 + CARD_EXECUTE, 1000 + CARD_SHADOW_WORD_DEATH, 1000 + CARD_SHADOW_WORD_PAIN, 1000 + CARD_SACRIFITIAL_PACT, 1000 + CARD_BATTLECRY_DESTROY_ENEMY_WEAPON, 1000 + CARD_POWER_WORD_SHIELD, 1000 + CARD_SWIPE, 1000 + CARD_ARCANE_MISSILES, 1000 + CARD_TRACKING, 1000 + CARD_TRANSFORM, 1000 + CARD_POLYMORPH, 1000 + CARD_HIDE, 1000 + CARD_LINKED, 1000 + CARD_HEX, 1000 + CARD_TARGET_UNDAMAGED_MINION, 1000 + CARD_TARGET_DAMAGED_MINION, 1000 + CARD_TARGET_3ATTACK_LESS, 1000 + CARD_TARGET_5ATTACK_MORE, 1000 + CARD_TARGET_30PERCENT_LESS, 1000 + CARD_TARGET_DEMON, 1000 + CARD_BLESSING_OF_MIGHT, 1000 + CARD_TARGET_UNDAMAGED, 1000 + CARD_ARCHMAGE_ANTONIDAS, 1000 + CARD_TARGET_BC_AUTO, 1000 + CARD_TARGET_BC_MANUAL, 1000 + CARD_TARGET_BC_ALL, 1000 + CARD_TARGETING_BC, 1000 + CARD_TARGET_BC_ALLY, 1000 + CARD_TARGET_BC_ENEMY, 1000 + CARD_TARGET_BC_ENEMY_MINIONS, 1000 + CARD_TARGET_BC_HERO, 1000 + CARD_TARGET_BC_ENEMY_HERO, 1000 + CARD_TARGET_BC_MINIONS, 1000 + CARD_TARGET_BC_ALLY_MINIONS, 1000 + CARD_TARGET_BC_ALLY_HERO, 1000 + CARD_STEALTH, 1000 + CARD_ATTACK, 1000 + CARD_TARGET_URSA, 1000 + CARD_TARGET_SVEN, 1000 + CARD_LEVELUP, 1000 + CARD_PIERCE_MAGIC_IMMUNITY, 1000 + CARD_TARGET_ALLY_BOARD, 1000 + CARD_TARGET_BOARD, 1000 + CARD_TARGET_ENEMY_BOARD, 1000 + CARD_TARGET_ALLY_BOSSES, 1000 + CARD_TARGET_ENEMY_BOSSES, 1000 + CARD_TARGET_BOSSES, 1000 diff --git a/hm_gameserver/script/flags.py b/hm_gameserver/script/flags.py new file mode 100644 index 0000000..fea5e70 --- /dev/null +++ b/hm_gameserver/script/flags.py @@ -0,0 +1,67 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +import os + +def fwrite(f, content): + f = open(f, "w") + f.write(content) + f.close() + +def parse(): + f = open("./flags", "r") + lines = f.readlines(); + f.close() + + f = open("./flags_sections", "r") + lines = lines + f.readlines() + f.close() + + ae = [] + for l in lines: + + elements = [] + for ele in l.split(","): + elements.append(ele.replace(" ", "").replace("\n", "")) + + ae.append(elements) + + header = '#ifndef FLAG_DEF_H_\n#define FLAG_DEF_H_\n\n' + + header += '#define MAX_FLAGS_DEF %d\n\n' % len(ae) + header += 'int flag_defs[MAX_FLAGS_DEF];\n' + header += 'enum flags_e {\n' + i = 0 + for a in ae: + header += '\t%s = %s,\n' % (a[0], i) + i = i + 1 + header += '};\n' + header += '#endif' + + body = '#include \n\n' + body += 'int flag_defs[MAX_FLAGS_DEF] = {\n' + i = 0 + for a in ae: + body += '%d, // index %d\n' % (int(a[1]), i) + i = i + 1 + body += '};\n' + + fwrite("../src/include/flag_def.h", header) + fwrite("../src/flag_def.c", body) + +if __name__ == '__main__': + e = parse() diff --git a/hm_gameserver/script/mechanics/allowed b/hm_gameserver/script/mechanics/allowed new file mode 100644 index 0000000..e3d2dc2 --- /dev/null +++ b/hm_gameserver/script/mechanics/allowed @@ -0,0 +1,18 @@ +@section +buff:code,target +battlecry:code,target +defender:code +properties:all,levelup +spell_aoe:code,target +spell:code,target +attack:code,target +attack_effect:code +weapon:code +endturn:code +onboard:code +destroyed:code +weapon_destroyed:code +idle:code +weapon_attack:code +attachment_attack:code +attack_effect_attachment:code diff --git a/hm_gameserver/script/mechanics/cards/CS1_042.card b/hm_gameserver/script/mechanics/cards/CS1_042.card new file mode 100644 index 0000000..e445dbd --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS1_042.card @@ -0,0 +1,14 @@ +# Goldshire Footman +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$minions" + }, + + ".section properties" : { + "all": [ "taunt" ] + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS1_112.card b/hm_gameserver/script/mechanics/cards/CS1_112.card new file mode 100644 index 0000000..c48eb1b --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS1_112.card @@ -0,0 +1,23 @@ +# Holy Nova +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, allcards) + allcards = hsl_board_all_cards($attacker, $heroes_included); + + def(card_list_s, cl) + foreach(cl, allcards) { + if(cl->card->controller == $attacker->controller) { + cl->card->receive.heal = 2; + } else { + cl->card->receive.damage = 2; + } + } + + hsl_attack_aoe($attacker, allcards) + + hsl_link_target($attacker, allcards) + ", + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS1_130.card b/hm_gameserver/script/mechanics/cards/CS1_130.card new file mode 100644 index 0000000..f4ba91a --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS1_130.card @@ -0,0 +1,11 @@ +# Holy Smite +{ + ".section spell" : { + "code" : " + $defender->receive.damage = 2; + hsl_attack($attacker, $defenders); + ", + + "target": "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_003.card b/hm_gameserver/script/mechanics/cards/CS2_003.card new file mode 100644 index 0000000..db1c4fe --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_003.card @@ -0,0 +1,13 @@ +# Mind Vision +{ + ".section buff" : { + "code": " + def(card_s, card) + card = hsl_cards_get_hand_random($deck_opponent); + if(card) { + hsl_add_new_card_hand($deck_player, card->entity->name, holder) + } + ", + "target" : "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_004.card b/hm_gameserver/script/mechanics/cards/CS2_004.card new file mode 100644 index 0000000..9e03301 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_004.card @@ -0,0 +1,15 @@ +# Power Word: Shield +{ + ".section buff" : { + "code": " + hsl_change_health($defender, 2) + hsl_add_signle_attachment($player, $deck_player, $attacker, $defender); + + hsl_draw_cards($player, $deck_player, draw_card, 1) + + /* hsl_link_target($attacker, $defenders) */ + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_005.card b/hm_gameserver/script/mechanics/cards/CS2_005.card new file mode 100644 index 0000000..da56de7 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_005.card @@ -0,0 +1,14 @@ +# Claw +{ + ".section buff" : { + "code": " + int change = 2; + hsl_buff_attack_expire(1, $ally_hero, change); + hsl_change_armor($ally_hero, change) + hsl_add_attachment($player, $attacker, $ally_hero, 1); + hsl_add_target($ally_hero, holder) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_007.card b/hm_gameserver/script/mechanics/cards/CS2_007.card new file mode 100644 index 0000000..aeed8aa --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_007.card @@ -0,0 +1,12 @@ +# Healing Touch +{ + ".section buff" : { + "code" : " + $defender->receive.heal = 8; + hsl_attack($attacker, $defenders); + hsl_link_target($attacker, $defenders); + ", + + "target": "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_008.card b/hm_gameserver/script/mechanics/cards/CS2_008.card new file mode 100644 index 0000000..107b849 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_008.card @@ -0,0 +1,12 @@ +# Moonfire +{ + ".section spell" : { + "code" : " + /* defender is linked by default */ + $defender->receive.damage = 1; + hsl_attack($attacker, $defenders); + ", + + "target": "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_009.card b/hm_gameserver/script/mechanics/cards/CS2_009.card new file mode 100644 index 0000000..5f8207f --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_009.card @@ -0,0 +1,12 @@ +# Mark of the Wild +{ + ".section buff" : { + "code": " + hsl_change_attack($defender, 2) + hsl_set_taunt($defender) + hsl_add_signle_attachment($player, $deck_player, $attacker, $defender); + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_011.card b/hm_gameserver/script/mechanics/cards/CS2_011.card new file mode 100644 index 0000000..6a79345 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_011.card @@ -0,0 +1,18 @@ +# Savage Roar +{ + ".section buff" : { + "code": " + def(card_list_s, all) + all = hsl_board_friendly_cards($attacker, $heroes_included); + + def(card_list_s, itm) + foreach(itm, all) { + hsl_buff_attack_expire(1, itm->card, 2); + hsl_add_attachment($player, $attacker, itm->card, 1); + hsl_add_defender(itm->card, holder) + } + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_012.card b/hm_gameserver/script/mechanics/cards/CS2_012.card new file mode 100644 index 0000000..b86f4f0 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_012.card @@ -0,0 +1,21 @@ +# Swipe +{ + ".section spell_aoe" : { + "code": " + def(card_list_s, all) + all = hsl_board_enemy_cards($defender, $heroes_included); + $defender->receive.damage = 4; + + def(card_list_s, itm) + foreach(itm, all) { + itm->card->receive.damage = 1; + hsl_add_target(itm->card, holder); + } + + hsl_attack($attacker, $defenders) + ", + + "target": "$enemy" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_022.card b/hm_gameserver/script/mechanics/cards/CS2_022.card new file mode 100644 index 0000000..e63b858 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_022.card @@ -0,0 +1,10 @@ +# Polymorph +{ + ".section buff" : { + "code": " + hsl_transform($attacker, $defender, \"CS2_tk1\"); + ", + + "target": "$enemy_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_023.card b/hm_gameserver/script/mechanics/cards/CS2_023.card new file mode 100644 index 0000000..05e7b1d --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_023.card @@ -0,0 +1,9 @@ +# Arcane Intellect +{ + ".section buff" : { + "code": " + hsl_draw_cards($player, $deck_player, draw_card, 2) + ", + "target" : "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_024.card b/hm_gameserver/script/mechanics/cards/CS2_024.card new file mode 100644 index 0000000..f8277ae --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_024.card @@ -0,0 +1,22 @@ +# Frostbolt +{ + ".section spell" : { + "code" : " + $defender->receive.damage = 3; + hsl_attack($attacker, $defenders); + ", + + "target": "$all" + }, + + ".section attack_effect" : { + "code" : " + hsl_freeze($attacker, $defender) + " + }, + + ".section properties" : { + "all": [ "freeze" ] + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_025.card b/hm_gameserver/script/mechanics/cards/CS2_025.card new file mode 100644 index 0000000..1673e5f --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_025.card @@ -0,0 +1,19 @@ +# Arcane Explosion +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, e) + e = hsl_board_enemy_cards($attacker, $heroes_excluded); + + def(card_list_s, cl) + foreach(cl, e) { + cl->card->receive.damage = 1; + } + + hsl_attack_aoe($attacker, e) + hsl_link_target($attacker, e) + ", + "target": "$auto" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_026.card b/hm_gameserver/script/mechanics/cards/CS2_026.card new file mode 100644 index 0000000..60b9bcb --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_026.card @@ -0,0 +1,15 @@ +# Frost Nova +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, e) + e = hsl_board_enemy_cards($attacker, $heroes_excluded); + + hsl_attack_aoe($attacker, e) + hsl_link_target($attacker, e) + ", + "target": "$auto" + } +} + + diff --git a/hm_gameserver/script/mechanics/cards/CS2_027.card b/hm_gameserver/script/mechanics/cards/CS2_027.card new file mode 100644 index 0000000..32c54af --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_027.card @@ -0,0 +1,17 @@ +# Mirror Image +{ + ".section spell_aoe" : { + "code": " + int i; + for(i = 0; i < 2; i++) { + hsl_summon_card($deck_player, \"CS2_mirror\", cardholder) + } + + /* this just does the routine (destroying it etc..) with a played card */ + hsl_attack_aoe($attacker, $defenders) + ", + + "target": "$auto" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_029.card b/hm_gameserver/script/mechanics/cards/CS2_029.card new file mode 100644 index 0000000..16690c4 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_029.card @@ -0,0 +1,12 @@ +# Fireball +{ + ".section spell" : { + "code" : " + $defender->receive.damage = 6; + hsl_attack($attacker, $defenders); + ", + + "target": "$all" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_032.card b/hm_gameserver/script/mechanics/cards/CS2_032.card new file mode 100644 index 0000000..88a4b24 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_032.card @@ -0,0 +1,19 @@ +# Flamestrike +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, e) + e = hsl_board_enemy_cards($attacker, $heroes_excluded); + + def(card_list_s, cl) + foreach(cl, e) { + cl->card->receive.damage = 4; + } + + hsl_attack_aoe($attacker, e) + hsl_link_target($attacker, e) + ", + "target": "$auto" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_033.card b/hm_gameserver/script/mechanics/cards/CS2_033.card new file mode 100644 index 0000000..baa68a1 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_033.card @@ -0,0 +1,21 @@ +# Water Elemental +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$minions" + }, + + ".section attack_effect" : { + "code" : " + hsl_freeze($attacker, $defender) + " + }, + + ".section properties" : { + "all": [ "freeze" ] + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_037.card b/hm_gameserver/script/mechanics/cards/CS2_037.card new file mode 100644 index 0000000..d179afc --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_037.card @@ -0,0 +1,22 @@ +# Frost Shock +{ + ".section spell" : { + "code" : " + $defender->receive.damage = 1; + hsl_attack($attacker, $defenders); + ", + + "target": "$all" + }, + + ".section attack_effect" : { + "code" : " + hsl_freeze($attacker, $defender) + " + }, + + ".section properties" : { + "all": [ "freeze" ] + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_039.card b/hm_gameserver/script/mechanics/cards/CS2_039.card new file mode 100644 index 0000000..5041cc8 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_039.card @@ -0,0 +1,10 @@ +# Windfury +{ + ".section buff" : { + "code": " + setflag($defender, CARD_WINDFURY) + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_041.card b/hm_gameserver/script/mechanics/cards/CS2_041.card new file mode 100644 index 0000000..983e42b --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_041.card @@ -0,0 +1,12 @@ +# Ancestral Healing +{ + ".section buff" : { + "code": " + hsl_set_fullhealth($defender) + hsl_set_taunt($defender) + ", + + "target": "$minions" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_042.card b/hm_gameserver/script/mechanics/cards/CS2_042.card new file mode 100644 index 0000000..466a6bb --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_042.card @@ -0,0 +1,14 @@ +# Fire Elemental +{ + ".section battlecry" : { + "code" : " + def(card_s, def) + def = hsl_card($target); + if(def) { + hsl_attack_bc($attacker, def, 3) + } + ", + + "target": "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_045.card b/hm_gameserver/script/mechanics/cards/CS2_045.card new file mode 100644 index 0000000..a7575b0 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_045.card @@ -0,0 +1,12 @@ +# Rockbiter Weapon +{ + ".section buff" : { + "code": " + hsl_buff_attack_expire(1, $defender, 3); + hsl_add_attachment($player, $attacker, $defender, 1); + ", + + "target": "$auto" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_046.card b/hm_gameserver/script/mechanics/cards/CS2_046.card new file mode 100644 index 0000000..bb47484 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_046.card @@ -0,0 +1,17 @@ +# Bloodlust +{ + ".section buff" : { + "code": " + def(card_list_s, all) + all = hsl_board_friendly_cards($attacker, $heroes_excluded) + + def(card_list_s, itm) + foreach(itm, all) { + hsl_buff_attack_expire(1, itm->card, 3); + hsl_add_attachment($player, $attacker, itm->card, 1); + } + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_057.card b/hm_gameserver/script/mechanics/cards/CS2_057.card new file mode 100644 index 0000000..8cf76ab --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_057.card @@ -0,0 +1,11 @@ +# Shadow Bolt +{ + ".section spell" : { + "code" : " + $defender->receive.damage = 4; + hsl_attack($attacker, $defenders); + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_061.card b/hm_gameserver/script/mechanics/cards/CS2_061.card new file mode 100644 index 0000000..a40dd62 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_061.card @@ -0,0 +1,16 @@ +# Drain Life +{ + ".section spell_aoe" : { + "code": " + hsl_receive_damage($defender, 2); + + hsl_receive_heal($ally_hero, 2); + hsl_add_target($ally_hero, holder); + + hsl_attack($attacker, $defenders) + ", + + "target": "$enemy" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_062.card b/hm_gameserver/script/mechanics/cards/CS2_062.card new file mode 100644 index 0000000..ad36c49 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_062.card @@ -0,0 +1,20 @@ +# Hellfire +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, allcards) + allcards = hsl_board_all_cards($attacker, $heroes_included); + + def(card_list_s, cl) + foreach(cl, allcards) { + cl->card->receive.damage = 3; + } + + hsl_attack_aoe($attacker, allcards) + + hsl_link_target($attacker, allcards) + ", + "target": "$auto" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_063.card b/hm_gameserver/script/mechanics/cards/CS2_063.card new file mode 100644 index 0000000..d1d5880 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_063.card @@ -0,0 +1,11 @@ +# Corruption +{ + ".section buff" : { + "code": " + hsl_buff_corrupt_expire(2, $defender); + hsl_add_attachment($player, $attacker, $defender, 2); + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_064.card b/hm_gameserver/script/mechanics/cards/CS2_064.card new file mode 100644 index 0000000..474be4a --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_064.card @@ -0,0 +1,20 @@ +# Dread Infernal +{ + ".section battlecry" : { + "code" : " + def(card_list_s, allcards) + allcards = hsl_board_all_cards($attacker, $heroes_included); + + def(card_list_s, cl) + foreach(cl, allcards) { + cl->card->receive.damage = 1; + } + + hsl_attack_aoe(attacker, allcards) + + hsl_link_target(attacker, allcards) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_065.card b/hm_gameserver/script/mechanics/cards/CS2_065.card new file mode 100644 index 0000000..c960b05 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_065.card @@ -0,0 +1,15 @@ +# Voidwalker +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$minions" + }, + + ".section properties" : { + "all": [ "taunt" ] + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_072.card b/hm_gameserver/script/mechanics/cards/CS2_072.card new file mode 100644 index 0000000..92ecf74 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_072.card @@ -0,0 +1,11 @@ +# Backstab +{ + ".section spell" : { + "code" : " + hsl_receive_damage($defender, 2); + hsl_attack($attacker, $defenders); + ", + + "target": "$undamaged_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_075.card b/hm_gameserver/script/mechanics/cards/CS2_075.card new file mode 100644 index 0000000..f3bbd62 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_075.card @@ -0,0 +1,11 @@ +# Sinister Strike +{ + ".section battlecry" : { + "code" : " + hsl_attack_bc($attacker, $enemy_hero, 3) + ", + + "target": "$auto" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_076.card b/hm_gameserver/script/mechanics/cards/CS2_076.card new file mode 100644 index 0000000..501f8db --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_076.card @@ -0,0 +1,10 @@ +# Assassinate +{ + ".section buff" : { + "code" : " + hsl_destroy($defender); + ", + + "target": "$enemy_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_077.card b/hm_gameserver/script/mechanics/cards/CS2_077.card new file mode 100644 index 0000000..7b4c66b --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_077.card @@ -0,0 +1,9 @@ +# Sprint +{ + ".section buff" : { + "code": " + hsl_draw_cards($player, $deck_player, draw_card, 4) + ", + "target" : "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_080.card b/hm_gameserver/script/mechanics/cards/CS2_080.card new file mode 100644 index 0000000..b298324 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_080.card @@ -0,0 +1,9 @@ +# Assassin's Blade +{ + ".section weapon" : { + "code" : " + hsl_give_weapon($deck_player); + " + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_082.card b/hm_gameserver/script/mechanics/cards/CS2_082.card new file mode 100644 index 0000000..5ba74f9 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_082.card @@ -0,0 +1,8 @@ +# Wicked Knife +{ + ".section weapon" : { + "code" : " + hsl_give_weapon($deck_player); + " + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_087.card b/hm_gameserver/script/mechanics/cards/CS2_087.card new file mode 100644 index 0000000..2fc684c --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_087.card @@ -0,0 +1,12 @@ +# Blessing of Might +{ + ".section buff" : { + "code": " + hsl_change_attack($defender, 3) + hsl_add_signle_attachment($player, $deck_player, $attacker, $defender); + ", + + "target": "$minions" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_088.card b/hm_gameserver/script/mechanics/cards/CS2_088.card new file mode 100644 index 0000000..8493c05 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_088.card @@ -0,0 +1,10 @@ +# Guardian of Kings +{ + ".section battlecry" : { + "code" : " + hsl_heal($attacker, $ally_hero, 6) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_089.card b/hm_gameserver/script/mechanics/cards/CS2_089.card new file mode 100644 index 0000000..0fec66c --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_089.card @@ -0,0 +1,13 @@ +# Holy Light +{ + ".section buff" : { + "code" : " + $defender->receive.heal = 6; + hsl_attack($attacker, $defenders); + hsl_link_target($attacker, $defenders); + ", + + "target": "$all" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_091.card b/hm_gameserver/script/mechanics/cards/CS2_091.card new file mode 100644 index 0000000..94e2ecf --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_091.card @@ -0,0 +1,9 @@ +# Light's Justice +{ + ".section weapon" : { + "code" : " + hsl_give_weapon($deck_player); + " + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_092.card b/hm_gameserver/script/mechanics/cards/CS2_092.card new file mode 100644 index 0000000..18bff23 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_092.card @@ -0,0 +1,12 @@ +# Blessing of Kings +{ + ".section buff" : { + "code": " + hsl_change_attack($defender, 4) + hsl_change_health($defender, 4) + hsl_add_signle_attachment($player, $deck_player, $attacker, $defender); + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_093.card b/hm_gameserver/script/mechanics/cards/CS2_093.card new file mode 100644 index 0000000..a548b33 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_093.card @@ -0,0 +1,18 @@ +# Consecration +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, e) + e = hsl_board_enemy_cards($attacker, $heroes_included); + + def(card_list_s, cl) + foreach(cl, e) { + cl->card->receive.damage = 2; + } + + hsl_attack_aoe($attacker, e) + hsl_link_target($attacker, e) + ", + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_094.card b/hm_gameserver/script/mechanics/cards/CS2_094.card new file mode 100644 index 0000000..61add25 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_094.card @@ -0,0 +1,13 @@ +# Hammer of Wrath +{ + ".section spell" : { + "code" : " + $defender->receive.damage = 3; + hsl_attack($attacker, $defenders); + + hsl_draw_cards($player, $deck_player, draw_card, 1) + ", + + "target": "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_105.card b/hm_gameserver/script/mechanics/cards/CS2_105.card new file mode 100644 index 0000000..da2fedc --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_105.card @@ -0,0 +1,11 @@ +# Heroic Strike +{ + ".section buff" : { + "code": " + hsl_buff_attack_expire(1, $ally_hero, 4); + hsl_add_attachment($player, $attacker, $ally_hero, 1); + + ", + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_106.card b/hm_gameserver/script/mechanics/cards/CS2_106.card new file mode 100644 index 0000000..dcce0de --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_106.card @@ -0,0 +1,8 @@ +# Fiery War Axe +{ + ".section weapon" : { + "code" : " + hsl_give_weapon($deck_player); + " + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_108.card b/hm_gameserver/script/mechanics/cards/CS2_108.card new file mode 100644 index 0000000..e236694 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_108.card @@ -0,0 +1,10 @@ +# Execute +{ + ".section buff" : { + "code" : " + hsl_destroy($defender); + ", + + "target": "$damaged_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_112.card b/hm_gameserver/script/mechanics/cards/CS2_112.card new file mode 100644 index 0000000..c4c20c5 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_112.card @@ -0,0 +1,9 @@ +# Arcanite Reaper +{ + ".section weapon" : { + "code" : " + hsl_give_weapon($deck_player); + " + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_118.card b/hm_gameserver/script/mechanics/cards/CS2_118.card new file mode 100644 index 0000000..adf951d --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_118.card @@ -0,0 +1,10 @@ +# Magma Rager +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_141.card b/hm_gameserver/script/mechanics/cards/CS2_141.card new file mode 100644 index 0000000..5c7df08 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_141.card @@ -0,0 +1,14 @@ +# Ironforge Rifleman +{ + ".section battlecry" : { + "code" : " + def(card_s, def) + def = hsl_card($target); + if(def) { + hsl_attack_bc($attacker, def, 1) + } + ", + + "target": "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_142.card b/hm_gameserver/script/mechanics/cards/CS2_142.card new file mode 100644 index 0000000..a6a479e --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_142.card @@ -0,0 +1,11 @@ +# Kobold Geomancer +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_172.card b/hm_gameserver/script/mechanics/cards/CS2_172.card new file mode 100644 index 0000000..4d585c2 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_172.card @@ -0,0 +1,10 @@ +# Bloodfen Raptor +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_196.card b/hm_gameserver/script/mechanics/cards/CS2_196.card new file mode 100644 index 0000000..3dcbd96 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_196.card @@ -0,0 +1,10 @@ +# Razorfen Hunter +{ + ".section battlecry" : { + "code" : " + hsl_summon_card($deck_player, \"CS2_boar\", cardholder) + ", + + "target" : "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_222.card b/hm_gameserver/script/mechanics/cards/CS2_222.card new file mode 100644 index 0000000..240cd3a --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_222.card @@ -0,0 +1,11 @@ +# Stormwind Champion +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/CS2_226.card b/hm_gameserver/script/mechanics/cards/CS2_226.card new file mode 100644 index 0000000..93a9fb4 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_226.card @@ -0,0 +1,16 @@ +# Frostwolf Warlord +{ + ".section battlecry" : { + "code" : " + int num_minions = hsl_board_minions_count($deck_player, $attacker); + if(num_minions > 0) { + hsl_change_health($attacker, num_minions) + hsl_change_attack($attacker, num_minions) + + hsl_add_signle_attachment($player, $deck_player, $attacker, $attacker); + } + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_234.card b/hm_gameserver/script/mechanics/cards/CS2_234.card new file mode 100644 index 0000000..5f3e61d --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_234.card @@ -0,0 +1,10 @@ +# Shadow Word: Pain +{ + ".section buff" : { + "code" : " + hsl_destroy($defender); + ", + + "target": "$attack3less_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_236.card b/hm_gameserver/script/mechanics/cards/CS2_236.card new file mode 100644 index 0000000..0afb8c6 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_236.card @@ -0,0 +1,10 @@ +# Divine Spirit +{ + ".section buff" : { + "code": " + buff_health($defender, $defender->health * 2); + ", + + "target": "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_mirror.card b/hm_gameserver/script/mechanics/cards/CS2_mirror.card new file mode 100644 index 0000000..1183185 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_mirror.card @@ -0,0 +1,14 @@ +# Mirror Image +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$minions" + }, + + ".section properties" : { + "all": [ "taunt" ] + } +} diff --git a/hm_gameserver/script/mechanics/cards/CS2_tk1.card b/hm_gameserver/script/mechanics/cards/CS2_tk1.card new file mode 100644 index 0000000..8b92898 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/CS2_tk1.card @@ -0,0 +1,10 @@ +# Sheep +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/DS1_055.card b/hm_gameserver/script/mechanics/cards/DS1_055.card new file mode 100644 index 0000000..9a35b99 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/DS1_055.card @@ -0,0 +1,20 @@ +# Darkscale Healer +{ + ".section battlecry" : { + "code" : " + def(card_list_s, allcards) + allcards = hsl_board_friendly_cards($attacker, $heroes_included); + + def(card_list_s, cl) + foreach(cl, allcards) { + cl->card->receive.heal = 2; + } + + hsl_attack_aoe(attacker, allcards) + + hsl_link_target(attacker, allcards) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_015.card b/hm_gameserver/script/mechanics/cards/EX1_015.card new file mode 100644 index 0000000..3b76dc5 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_015.card @@ -0,0 +1,10 @@ +# Novice Engineer +{ + ".section battlecry" : { + "code" : " + hsl_draw_cards($player, $deck_player, draw_card, 1) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_020.card b/hm_gameserver/script/mechanics/cards/EX1_020.card new file mode 100644 index 0000000..98f9953 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_020.card @@ -0,0 +1,14 @@ +# Scarlet Crusader +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + }, + + ".section properties" : { + "all": [ "divine_shield" ] + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_025.card b/hm_gameserver/script/mechanics/cards/EX1_025.card new file mode 100644 index 0000000..e02d777 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_025.card @@ -0,0 +1,10 @@ +# Dragonling Mechanic +{ + ".section battlecry" : { + "code" : " + hsl_summon_card($deck_player, \"EX1_025t\", cardholder) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_066.card b/hm_gameserver/script/mechanics/cards/EX1_066.card new file mode 100644 index 0000000..156eb09 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_066.card @@ -0,0 +1,10 @@ +# Acidic Swamp Ooze +{ + ".section battlecry" : { + "code" : " + hsl_destroy_weapon($attacker, $player, holder) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_246.card b/hm_gameserver/script/mechanics/cards/EX1_246.card new file mode 100644 index 0000000..f7769a7 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_246.card @@ -0,0 +1,11 @@ +# Hex +{ + ".section buff" : { + "code": " + hsl_transform($attacker, $defender, \"hexfrog\"); + ", + + "target": "$enemy_minions" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/EX1_306.card b/hm_gameserver/script/mechanics/cards/EX1_306.card new file mode 100644 index 0000000..2e121f9 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_306.card @@ -0,0 +1,10 @@ +# Succubus +{ + ".section battlecry" : { + "code" : " + hsl_discard_random_hand($deck_player, 1, holder) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_400.card b/hm_gameserver/script/mechanics/cards/EX1_400.card new file mode 100644 index 0000000..c4a09a4 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_400.card @@ -0,0 +1,18 @@ +# Whirlwind +{ + ".section spell_aoe" : { + "code" : " + def(card_list_s, e) + e = hsl_board_enemy_cards($attacker, $heroes_excluded); + + def(card_list_s, cl) + foreach(cl, e) { + cl->card->receive.damage = 1; + } + + hsl_attack_aoe($attacker, e) + hsl_link_target($attacker, e) + ", + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_506.card b/hm_gameserver/script/mechanics/cards/EX1_506.card new file mode 100644 index 0000000..91167a7 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_506.card @@ -0,0 +1,10 @@ +# Murloc Tidehunter +{ + ".section battlecry" : { + "code" : " + hsl_summon_card($deck_player, \"EX1_506a\", cardholder) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_581.card b/hm_gameserver/script/mechanics/cards/EX1_581.card new file mode 100644 index 0000000..009bdf6 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_581.card @@ -0,0 +1,13 @@ +# Sap +{ + ".section buff" : { + "code": " + unsetflag($defender, CARD_BOARD) + setflag($defender, CARD_HAND) + + $defender->zone_position = ++($deck_opponent->handposition); + ", + + "target": "$enemy_minions" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_593.card b/hm_gameserver/script/mechanics/cards/EX1_593.card new file mode 100644 index 0000000..d88e8be --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_593.card @@ -0,0 +1,10 @@ +# Sinister Strike +{ + ".section battlecry" : { + "code" : " + hsl_attack_bc($attacker, $enemy_hero, 3) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_606.card b/hm_gameserver/script/mechanics/cards/EX1_606.card new file mode 100644 index 0000000..879de8d --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_606.card @@ -0,0 +1,12 @@ +# Shield Block +{ + ".section buff" : { + "code": " + hsl_change_armor($ally_hero, 5); + hsl_add_target($ally_hero, holder); + hsl_draw_cards($player, $deck_player, draw_card, 1) + ", + + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/EX1_614.card b/hm_gameserver/script/mechanics/cards/EX1_614.card new file mode 100644 index 0000000..6c42687 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_614.card @@ -0,0 +1,12 @@ +# Illidan +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + } + +} + diff --git a/hm_gameserver/script/mechanics/cards/EX1_622.card b/hm_gameserver/script/mechanics/cards/EX1_622.card new file mode 100644 index 0000000..aeb12a7 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/EX1_622.card @@ -0,0 +1,11 @@ +# Shadow Word: Death +{ + ".section buff" : { + "code" : " + hsl_destroy($defender); + ", + + "target": "$attack5more_minions" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/HERO_01.card b/hm_gameserver/script/mechanics/cards/HERO_01.card new file mode 100644 index 0000000..f6409f0 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/HERO_01.card @@ -0,0 +1,10 @@ +# HERO_01 +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/HERO_03.card b/hm_gameserver/script/mechanics/cards/HERO_03.card new file mode 100644 index 0000000..21ce5ca --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/HERO_03.card @@ -0,0 +1,10 @@ +# HERO_03 +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$all" + } +} diff --git a/hm_gameserver/script/mechanics/cards/NEW1_003.card b/hm_gameserver/script/mechanics/cards/NEW1_003.card new file mode 100644 index 0000000..ed77fa4 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/NEW1_003.card @@ -0,0 +1,16 @@ +# Sacrificial Pact +{ + ".section spell_aoe" : { + "code": " + hsl_destroy($defender); + + hsl_receive_heal($ally_hero, 5); + hsl_add_target($ally_hero, holder); + + hsl_attack($attacker, $defenders) + ", + + "target": "$demon" + } +} + diff --git a/hm_gameserver/script/mechanics/cards/NEW1_004.card b/hm_gameserver/script/mechanics/cards/NEW1_004.card new file mode 100644 index 0000000..988bb72 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/NEW1_004.card @@ -0,0 +1,22 @@ +# Vanish +{ + ".section buff" : { + "code": " + /* + def(card_list_s, itm) + foreach(itm, $defenders) { + unsetflag(itm->card, CARD_BOARD) + setflag(itm->card, CARD_HAND) + + if(controller_player(itm->card)) { + itm->card->zone_position = ++($deck_player->handposition); + } else { + itm->card->zone_position = ++($deck_opponent->handposition); + } + } + */ + + ", + "target": "$auto" + } +} diff --git a/hm_gameserver/script/mechanics/cards/NEW1_009.card b/hm_gameserver/script/mechanics/cards/NEW1_009.card new file mode 100644 index 0000000..5fcbb9e --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/NEW1_009.card @@ -0,0 +1,37 @@ +# Healing Totem +{ + ".section endturn" : { + "code" : " + def(card_list_s, all); + all = hsl_board_friendly_cards_wattacker($heroes_excluded); + + def(card_s, found); + + def(card_list_s, c); + foreach(c, all) { + if(hsl_cmp_cardname(c, \"NEW1_009\")) { + found = c->card; + break; + } + } + + if(found != NULL) { + def(card_list_s, filter); + filter = hsl_board_friendly_cards(found, $heroes_excluded); + + foreach(c, filter) { + /* exclude self */ + if(c->card == found) continue; + + hsl_receive_heal(c->card, 1); + entity_attack(p, found, c->card); + } + + found->target.card = all; + + flag(&found->state, MECHANICS_TURN_TRIGGER, FLAG_SET); + } + " + } +} + diff --git a/hm_gameserver/script/mechanics/cards/NEW1_011.card b/hm_gameserver/script/mechanics/cards/NEW1_011.card new file mode 100644 index 0000000..e5d1dab --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/NEW1_011.card @@ -0,0 +1,20 @@ +# Kor'kron Elite +{ + ".section battlecry" : { + "code" : " + def(card_s, def) + def = hsl_card($target); + if(def) { + hsl_attack_bc($attacker, def, 1) + } + ", + + "target": "$auto" + }, + + ".section defender" : { + "code" : " + hsl_add_new_card_hand($deck_opponent, \"CS2_boar\", holder) + " + } +} diff --git a/hm_gameserver/script/mechanics/cards/NEW1_032.card b/hm_gameserver/script/mechanics/cards/NEW1_032.card new file mode 100644 index 0000000..9149e46 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/NEW1_032.card @@ -0,0 +1,14 @@ +# Misha +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + }, + + ".section properties" : { + "all": [ "taunt" ] + } +} diff --git a/hm_gameserver/script/mechanics/cards/NEW1_034.card b/hm_gameserver/script/mechanics/cards/NEW1_034.card new file mode 100644 index 0000000..c310874 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/NEW1_034.card @@ -0,0 +1,14 @@ +# Huffer +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$enemy_minions" + }, + + ".section properties" : { + "all": [ "charge" ] + } +} diff --git a/hm_gameserver/script/mechanics/cards/hexfrog.card b/hm_gameserver/script/mechanics/cards/hexfrog.card new file mode 100644 index 0000000..ce6fc78 --- /dev/null +++ b/hm_gameserver/script/mechanics/cards/hexfrog.card @@ -0,0 +1,14 @@ +# Hex +{ + ".section attack" : { + "code" : " + hsl_attack($attacker, $defenders); + ", + + "target" : "$minions" + }, + + ".section properties" : { + "all": [ "taunt" ] + } +} diff --git a/hm_gameserver/script/mechanics/config.py b/hm_gameserver/script/mechanics/config.py new file mode 100644 index 0000000..8feb530 --- /dev/null +++ b/hm_gameserver/script/mechanics/config.py @@ -0,0 +1,45 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +RF_SECTION = 1 + +no_levelup = 0 + +file_entities = "../../src/proto/ent.c" +file_flags_sections = "../flags_sections" +file_ent_sections = "../../src/proto/ent_sections.c" +file_levelup_c = "../../src/levelup.c" +file_levelup_h = "../../src/include/levelup.h" + +sections = { + "buff": ["./include/section_buff.h", "BUFF", []], + "battlecry": ["./include/section_battlecry.h", "BATTLECRY", []], + "defender": ["./include/section_defender.h", "DEFENDER", []], + "spell_aoe": ["./include/section_spell_aoe.h", "SPELL_AOE", []], + "spell": ["./include/section_spell.h", "SPELL", []], + "attack": ["./include/section_attack.h", "ATTACK", []], + "attack_effect": ["./include/section_attack_effect.h", "ATTACK_EFFECT", []], + "weapon": ["./include/section_weapon.h", "WEAPON", []], + "endturn": ["./include/section_endturn.h", "ENDTURN", []], + "onboard": ["./include/section_onboard.h", "ONBOARD", []], + "destroyed": ["./include/section_destroyed.h", "DESTROYED", []], + "weapon_destroyed": ["./include/section_weapon_destroyed.h", "WEAPON_DESTROYED", []], + "idle": ["./include/section_idle.h", "IDLE", []], + "weapon_attack": ["./include/section_weapon_attack.h", "WEAPON_ATTACK", []], + "attachment_attack": ["./include/section_attachment_attack.h", "ATTACHMENT_ATTACK", []], + "attack_effect_attachment": ["./include/section_attack_effect_attachment.h", "ATTACK_EFFECT_ATTACHMENT", []], +} diff --git a/hm_gameserver/script/mechanics/func.hsl b/hm_gameserver/script/mechanics/func.hsl new file mode 100644 index 0000000..ab6706c --- /dev/null +++ b/hm_gameserver/script/mechanics/func.hsl @@ -0,0 +1,14 @@ +#!/bin/sh + +@globals +$player, $opponent +$player_deck, $opponent_deck +$none, $all, $minions, $enemy_minions, $enemy_hero, $enemies, $ally_minions, $ally_hero, $allies, $aoe +#.random: $r_all, $r_enemy_minions, $r_enemies, $r_ally_minions, $r_allies +$zone_play, $zone_deck, $zone_hand, $zone_graveyard, $zone_discard, $zone_setaside, $zone_secret +$attacker, $defenders, $turn + +@functions +struct card_s *draw_card(dst, name, amount) +void buff_attack_expire(round, defender, attack) +void add_attachment(player) diff --git a/hm_gameserver/script/mechanics/include/.gitkeep b/hm_gameserver/script/mechanics/include/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hm_gameserver/script/mechanics/main.py b/hm_gameserver/script/mechanics/main.py new file mode 100644 index 0000000..3a3143b --- /dev/null +++ b/hm_gameserver/script/mechanics/main.py @@ -0,0 +1,101 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +import os +from couchbase.bucket import Bucket + +import config, util, target, parser + +def start_sections(): + os.system("rm %s" % config.file_flags_sections) + + util.write(config.file_ent_sections, "#include \n#include \n\n", "w") + util.write(config.file_ent_sections, "void entities_init2() {\n", "a") + + print 'Starting sections:' + for s in config.sections: + b = "#ifndef SECTION_%s_H_\n" % config.sections[s][1].upper() + b += "#define SECTION_%s_H_\n\n" % config.sections[s][1].upper() + util.write(config.sections[s][0], b, "w") + print '\t%s' % config.sections[s][0] + + util.write(config.file_levelup_c, "#include \n#include \n\nstruct levelup_s levelup[MAX_LEVELUP] = {\n", "w") + +def end_sections(): + print 'Ending sections:' + for s in config.sections: + b = '#define __SECTION_%s\\\n' % s.upper() + for t in config.sections[s][2]: + b += '\t%s\\\n' % t + + util.write(config.sections[s][0], b, "a") + b = "\n#endif" + util.write(config.sections[s][0], b, "a") + + print '\t%s' % config.sections[s][0] + + util.write(config.file_ent_sections, "}\n", "a") + + util.write(config.file_levelup_c, "};", "a") + + lh = "#ifndef LEVELUP_H_\n#define LEVELUP_H_\n\ +#define MAX_LEVELUP %d\n\ +struct levelup_s {\n\ + const char *dst;\n\ + const char *src;\n\ +};\n\ +extern struct levelup_s levelup[MAX_LEVELUP];\n\ +#endif" % config.no_levelup + util.write(config.file_levelup_h, lh, "w") + +if __name__ == "__main__": + start_sections() + + rootDir = './cards/' + + p = parser.parser() + + cb = Bucket('couchbase://localhost/hbs', password='aci') + loaded = cb.get('u:mod_dota').value + + + for c in loaded['cards']: + name = '' + for k in c: + if k[0] == '__name': + name = k[1] + if k[0] == '__code': # code comes later than name + p.parse_card(k[1], name) + + ''' + for c in loaded: + for r in loaded[c]: + for i in loaded[c][r]: + print i + + # files + for dir_, dirnames, files in os.walk(rootDir): + dirnames.sort() + files.sort() + for fileName in files: + if(fileName.endswith(".card")): + relDir = os.path.relpath(dir_, rootDir) + relFile = os.path.join(relDir, fileName) + p.parse_card(rootDir + relFile) + ''' + + end_sections() diff --git a/hm_gameserver/script/mechanics/parser.py b/hm_gameserver/script/mechanics/parser.py new file mode 100644 index 0000000..389d9aa --- /dev/null +++ b/hm_gameserver/script/mechanics/parser.py @@ -0,0 +1,303 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +import json, re + +import util, target, config + +class parser: + def __init__(self): + self.allowed = self.allowed_sections() + + def allowed_sections(self): + loaded = util.read("allowed", 0) + + read = 0 + al = {} + + for a in loaded: + if a.startswith('#'): + continue + elif a.startswith('@'): + if(a.find('section') > -1): + read |= config.RF_SECTION + continue + elif a.startswith('\n'): + read = 0 + continue + else: + if((read & config.RF_SECTION) == config.RF_SECTION): + n = a.split(":") + al[n[0]] = n[1].replace("\n", "") + return al + + def match_allowed_section(self, dst, src, parent): + for d in dst: + cx = src.split(" ") + if(len(cx) > 1): + if(cx[1] == d): + return [dst[d], src, d] + return [] + + def match_allowed_sub(self, dst, src): + sub = [] + a = src.replace("\n", "").split(",") + for d in dst: + for e in a: + if(e == d): + sub.append([e, dst[d]]) + return sub + + def card_battlecry_target(self, obj, card): + type = obj[0] + target = obj[1] + print type + + def parse_card(self, b, name): + + ''' + # files + f = util.read(c, 0) + b = '' + for l in f: + b += l.replace("\n","").replace("\t","") + ''' + + # ignore first line + b = b[b.find('\n') + 1:b.rfind('\n')] + b = b.replace("\n","").replace("\t","") + + try: + j = json.loads(b) + except: + print 'parsing json failed %s [%s]' % (name, b) + exit(1) + + p = [] + + for i in j: + f = self.match_allowed_section(self.allowed, i, j) + if(len(f) > 0): + s = self.match_allowed_sub(j[f[1]], f[0]) + p.append([f[2], s]) + + #crd = re.findall("[\w]+.card", c) + #crd = name.split(".") + + for i in p: + #print i + for s in i: + if s != 'battlecry' and i[0] == 'battlecry': + util.store_flag(config.file_ent_sections, 'CARD_BATTLECRY', name) + + for ms in s: + if 'target' in ms: + for t in target.battlecry[ms[1]]: + util.store_flag(config.file_ent_sections, t, name) + + elif 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + + elif s != 'weapon' and i[0] == 'weapon': + util.store_flag(config.file_ent_sections, 'CARD_SPELL', name) + util.store_flag(config.file_ent_sections, 'CARD_AOE', name) + util.store_flag(config.file_ent_sections, 'CARD_WEAPON', name) + util.store_flag(config.file_ent_sections, 'CARD_NONTARGET', name) + + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + + elif s != 'endturn' and i[0] == 'endturn': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + + elif s != 'spell_aoe' and i[0] == 'spell_aoe': + util.store_flag(config.file_ent_sections, 'CARD_SPELL', name) + util.store_flag(config.file_ent_sections, 'CARD_AOE', name) + + for ms in s: + if 'target' in ms: + for t in target.regular[ms[1]]: + util.store_flag(config.file_ent_sections, t, name) + + elif 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + elif s != 'spell' and i[0] == 'spell': + util.store_flag(config.file_ent_sections, 'CARD_SPELL', name) + for ms in s: + if 'target' in ms: + for t in target.regular[ms[1]]: + util.store_flag(config.file_ent_sections, t, name) + + elif 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + elif s != 'attack' and i[0] == 'attack': + util.store_flag(config.file_ent_sections, 'CARD_MINION', name) + util.store_flag(config.file_ent_sections, 'CARD_TARGETING', name) + + for ms in s: + if 'target' in ms: + for t in target.regular[ms[1]]: + util.store_flag(config.file_ent_sections, t, name) + + elif 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + + elif s != 'attack_effect' and i[0] == 'attack_effect': + util.store_flag(config.file_ent_sections, 'CARD_MINION', name) + + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + elif s != 'onboard' and i[0] == 'onboard': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + + elif s != 'destroyed' and i[0] == 'destroyed': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_defender") + + elif s != 'defender' and i[0] == 'defender': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_defender") + + elif s != 'weapon_destroyed' and i[0] == 'weapon_destroyed': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_weapon") + + elif s != 'idle' and i[0] == 'idle': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_attacker") + + + elif s != 'weapon_attack' and i[0] == 'weapon_attack': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_weapon") + + elif s != 'attachment_attack' and i[0] == 'attachment_attack': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_attacker") + + elif s != 'attack_effect_attachment' and i[0] == 'attack_effect_attachment': + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "fake_attacker") + + elif s != 'properties' and i[0] == 'properties': + for ms in s: + if 'all' in ms: + for mss in ms[1]: + util.store_flag(config.file_ent_sections, "CARD_%s" % mss.upper(), name) + + if 'levelup' in ms: + self.levelup(config.file_levelup_c, name, ms[1]) + #for mss in ms[1]: + # util.store_flag(config.file_ent_sections, "CARD_%s" % mss.upper(), name) + + elif s != 'buff' and i[0] == 'buff': + util.store_flag(config.file_ent_sections, 'CARD_BUFF', name) + util.store_flag(config.file_ent_sections, 'CARD_SPELL', name) + + for ms in s: + if 'code' in ms: + ms[1] = ms[1].replace("$", "HSL_") + self.store(name, i[0], ms[1], config.sections[i[0]][0], "attacker") + elif 'target' in ms: + for t in target.regular[ms[1]]: + util.store_flag(config.file_ent_sections, t, name) + + + def levelup(self, f, dst, src): + util.write(f, "\t{%s, \"%s\"},\n" % (src, dst), "a") + config.no_levelup = config.no_levelup + 1 + + def store(self, card, section, code, path, entity): + #c = re.findall("[\w]+.card", card) + #c = c[0].split(".") + + if(section == 'endturn'): + buf = '#define %s_%s\\\n\ + {\\\n\ + %s\\\n\ + }\n\n' % (section, card, code) + + elif(section == 'idle'): + buf = '#define %s_%s\\\n\ + { %s }\\\n\ + \n\n' % (section, card, code) + + elif(section == 'attack_effect_attachment'): + buf = '#define %s_%s\\\n\ + {\\\n\ + %s\\\n\ + }\n\n' % (section, card,code) + + elif(section == 'attachment_attack'): + buf = '#define %s_%s\\\n\ + {\\\n\ + int count = hsl_count_attachments(HSL_fake_deck, NULL, HSL_fake_attacker, "%s");\\\n\ + if(count == 1) {\\\n\ + %s\\\n\ + }}\n\n' % (section, card, card, code) + + else: + buf = '#define %s_%s\\\n\ + if(HSL_%s && flag(&(HSL_%s->state), %s_%s_FLAG, FLAG_ISSET)) {\\\n\ + %s\\\n\ + }\n\n' % (section, card, entity, entity, section, card, code) + + + util.write(path, buf, "a") + + config.sections[section][2].append("%s_%s" % (section, card)) + + flag = "%s_%s_FLAG, 1000\n" % (section, card) + util.write(config.file_flags_sections, flag, "a") + + flag1 = "%s_%s_FLAG" % (section, card) + util.store_flag(config.file_ent_sections, flag1, card) diff --git a/hm_gameserver/script/mechanics/target.py b/hm_gameserver/script/mechanics/target.py new file mode 100644 index 0000000..5dc084f --- /dev/null +++ b/hm_gameserver/script/mechanics/target.py @@ -0,0 +1,63 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +regular = { +"$all" : ["CARD_TARGET_ALL", "CARD_TARGETING"], +"$minions" : ["CARD_TARGET_MINIONS", "CARD_TARGETING"], +"$hero" : ["CARD_TARGET_HERO", "CARD_TARGETING"], +"$enemy_hero" : ["CARD_TARGET_ENEMY_HERO", "CARD_TARGETING"], +"$enemy_minions" : ["CARD_TARGET_ENEMY_MINIONS", "CARD_TARGETING"], +"$ally_hero" : ["CARD_TARGET_ALLY_HERO", "CARD_TARGETING"], +"$ally_minions" : ["CARD_TARGET_ALLY_MINIONS", "CARD_TARGETING"], +"$ally_bosses" : ["CARD_TARGET_ALLY_BOSSES", "CARD_TARGETING"], +"$enemy_bosses" : ["CARD_TARGET_ENEMY_BOSSES", "CARD_TARGETING"], +"$bosses" : ["CARD_TARGET_BOSSES", "CARD_TARGETING"], +"$ally_board" : ["CARD_TARGET_ALLY_BOARD", "CARD_TARGETING"], +"$enemy_board" : ["CARD_TARGET_ENEMY_BOARD", "CARD_TARGETING"], +"$board" : ["CARD_TARGET_BOARD", "CARD_TARGETING"], +"$ally" : ["CARD_TARGET_ALLY", "CARD_TARGETING"], +"$enemy" : ["CARD_TARGET_ENEMY", "CARD_TARGETING"], +"$auto" : ["CARD_NONTARGET"], +"$undamaged_minions":["CARD_TARGET_UNDAMAGED_MINION", "CARD_TARGETING"], +"$damaged_minions":["CARD_TARGET_DAMAGED_MINION", "CARD_TARGETING"], +"$attack5more_minions":["CARD_TARGET_5ATTACK_MORE", "CARD_TARGETING"], +"$attack3less_minions":["CARD_TARGET_3ATTACK_LESS", "CARD_TARGETING"], +"$health_below_30p_minions":["CARD_TARGET_30PERCENT_LESS", "CARD_TARGETING"], +"$URSA":["CARD_TARGET_URSA", "CARD_TARGETING"], +"$SVEN":["CARD_TARGET_SVEN", "CARD_TARGETING"], +} + +battlecry = { +"$all" : ["CARD_TARGET_ALL", "CARD_TARGETING_BC"], +"$minions" : ["CARD_TARGET_MINIONS", "CARD_TARGETING_BC"], +"$hero" : ["CARD_TARGET_HERO", "CARD_TARGETING_BC"], +"$enemy_hero" : ["CARD_TARGET_ENEMY_HERO", "CARD_TARGETING_BC"], +"$enemy_minions" : ["CARD_TARGET_ENEMY_MINIONS", "CARD_TARGETING_BC"], +"$ally_hero" : ["CARD_TARGET_ALLY_HERO", "CARD_TARGETING_BC"], +"$ally_minions" : ["CARD_TARGET_ALLY_MINIONS", "CARD_TARGETING_BC"], +"$ally" : ["CARD_TARGET_ALLY", "CARD_TARGETING_BC"], +"$enemy" : ["CARD_TARGET_ENEMY", "CARD_TARGETING_BC"], +"$ally_bosses" : ["CARD_TARGET_ALLY_BOSSES", "CARD_TARGETING_BC"], +"$enemy_bosses" : ["CARD_TARGET_ENEMY_BOSSES", "CARD_TARGETING_BC"], +"$bosses" : ["CARD_TARGET_BOSSES", "CARD_TARGETING_BC"], +"$ally_board" : ["CARD_TARGET_ALLY_BOARD", "CARD_TARGETING_BC"], +"$enemy_board" : ["CARD_TARGET_ENEMY_BOARD", "CARD_TARGETING_BC"], +"$board" : ["CARD_TARGET_BOARD", "CARD_TARGETING_BC"], +"$auto" : ["CARD_NONTARGET_BC"], +"$undamaged_minions":["CARD_TARGET_UNDAMAGED_MINION", "CARD_TARGETING_BC"], +"$damaged_minions":["CARD_TARGET_DAMAGED_MINION", "CARD_TARGETING_BC"], +} diff --git a/hm_gameserver/script/mechanics/util.py b/hm_gameserver/script/mechanics/util.py new file mode 100644 index 0000000..4c6dc81 --- /dev/null +++ b/hm_gameserver/script/mechanics/util.py @@ -0,0 +1,52 @@ +''' +hm_gameserver - hearthmod gameserver +Copyright (C) 2016 Filip Pancik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' +import re + +import config + +def write(f, buf, m): + l = open(f, m) + l.write(buf) + l.close() + +def read(f, t): + f = open(f, "r") + if(t == 0): + b = [] + c = f.readlines() + for l in c: + if l.startswith('#'): + continue + b.append(l) + return b + else: + b = f.read() + f.close() + + return b + +def store_flag(dst, f, i): + if(f.find("ENABLED") > -1): + return + + lines = read(config.file_entities, 0) + for l in lines: + if(l.find("{ \"%s\"" % i) > -1): + index = re.findall("// [\w]+", l)[0].split(" ")[1] + write(dst, "\tflag(&entities[%s].flags, %s, FLAG_SET);\n" % (index, f), "a") + break diff --git a/hm_gameserver/src/choose_entities.c b/hm_gameserver/src/choose_entities.c new file mode 100644 index 0000000..c8e5a3f --- /dev/null +++ b/hm_gameserver/src/choose_entities.c @@ -0,0 +1,323 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +/* + static void summon_obelisk(struct powerhistory_data_s **data, struct deck_s *deck, struct card_s *new_card) + { + struct powerhistory_tag_s *card_tags; + struct powerhistory_entity_s *show; + + + add_powerstart(data, 3, -1, new_card->id, 0, NULL, 0); + int pos = cards_board_last(deck, new_card); + card_tags = default_tags(new_card, new_card->entity, 0); + + add_tag(&card_tags, CONTROLLER, deck->controller); + add_tag(&card_tags, ENTITY_ID, new_card->id); + + add_full_entity(&show, card_tags, new_card->id, new_card->entity->name, new_card->entity->nname); + add_ph_data_full(data, show); + + add_tagchange(data, ZONE_POSITION, pos, new_card->id); + add_tagchange(data, ZONE, 1, new_card->id); + add_powerend(data); + } + */ + +static int get_card_start_play(int entity_id, struct deck_s *deck, char *output, const int noutput, int *drawn_card, struct deck_s *opponent, struct card_s ***obelisk, struct hs_holder_s *h) +{ + // FIXME: send this to both players?? + struct card_s *new_card; + struct powerhistory_tag_s *card_tags; + struct powerhistory_entity_s *show; + + struct powerhistory_data_s *data = NULL; + struct powerhistory_s *ph = NULL; + struct packet_s *p = NULL; + + char *ptr; + + add_tagchange(&data, STEP, 6, 1); + add_powerstart(&data, 5, 1, entity_id, 0, NULL, 0); + //add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 66); // hero + //add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 67); // hero power + add_tagchange(&data, RESOURCES, 1, entity_id); + add_tagchange(&data, 399, 0, entity_id); + add_tagchange(&data, NEXT_STEP, 17, 1); + add_powerend(&data); + add_tagchange(&data, STEP, 17, 1); + add_powerstart(&data, 5, 8, entity_id, 0, NULL, 0); + add_tagchange(&data, NEXT_STEP, 9, 1); + add_powerend(&data); + add_tagchange(&data, STEP, 9, 1); + + /* + if((*obelisk)[0] == NULL && (*obelisk)[1] == NULL) { + (*obelisk)[0] = add_new_card(h->game, deck, -1, "EX1_614", -1); + (*obelisk)[1] = add_new_card(h->game, opponent, -1, "EX1_614", -1); + flag(&((*obelisk)[0])->state, CARD_BOARD, FLAG_SET); + flag(&((*obelisk)[1])->state, CARD_BOARD, FLAG_SET); + + deck->board_position[0] = (*obelisk)[0]->id; + opponent->board_position[0] = (*obelisk)[1]->id; + + summon_obelisk(&data, deck, (*obelisk)[0]); + summon_obelisk(&data, opponent, (*obelisk)[1]); + } else { + summon_obelisk(&data, opponent, (*obelisk)[0]); + summon_obelisk(&data, deck, (*obelisk)[1]); + } + + assert((*obelisk)[0] && (*obelisk)[1]); + +*/ + + add_powerstart(&data, 5, 0, entity_id, 0, NULL, 0); + + if(*drawn_card != 0) { + add_tagchange(&data, ZONE_POSITION, 4, *drawn_card); + add_tagchange(&data, ZONE, ZONE_HAND, *drawn_card); + } else { + hm_log(LOG_DEBUG, lg, "about to draw card player %d", entity_id); + new_card = draw_random_card(deck, entity_id, -1); + card_tags = default_tags(new_card, new_card->entity, 0); + add_full_entity(&show, card_tags, new_card->id, new_card->entity->name, new_card->entity->nname); + add_ph_data_show(&data, show); + add_tagchange(&data, ZONE, ZONE_HAND, new_card->id); + add_tagchange(&data, ZONE_POSITION, new_card->zone_position, new_card->id); + *drawn_card = new_card->id; + + hm_log(LOG_DEBUG, lg, "p2: zone position: %d card: %d", new_card->zone_position, new_card->id); + } + + add_tagchange(&data, 399, 1, entity_id); + add_tagchange(&data, NEXT_STEP, 10, 1); + add_powerend(&data); + add_tagchange(&data, STEP, 10, 1); + add_powerstart(&data, 5, 2, entity_id, 0, NULL, 0); + add_tagchange(&data, NEXT_STEP, 12, 1); + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&p, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + ptr = output; + int n = serialize(p, &ptr, ptr + noutput); + + packet_free(p); + + int o = 0; + // only player needs options + if(entity_id == 3) { + o = set_options(deck, opponent, output + n, ptr + noutput - n, 1); + } + + return n + o; +} + +void choose_one_entity(struct conn_client_s *c, struct chooseentities_s *e) +{ + int id = 0; + struct chooseentities_ent_s *ent; + + for(ent = e->entity; ent != NULL; ent = ent->next) { + id = ent->entity; + break; + } + + assert(id > 0); + + //card = card_get(); + + //flag(&card->state, CARD_DECK, FLAG_UNSET); + //flag(&card->state, CARD_HAND, FLAG_SET); + //card->zone_position = ++deck->handposition; + +} + +void choose_entities(struct conn_client_s *c, struct chooseentities_s *e) +{ + struct chooseentities_ent_s *ent; + struct hs_holder_s *h; + //struct card_s *unwanted[4]; + int nunwanted = 0; + //struct card_s *new_card; + //struct powerhistory_tag_s *card_tags; + //struct powerhistory_entity_s *show; + + struct powerhistory_data_s *data = NULL, *data1 = NULL; + struct powerhistory_s *ph = NULL, *ph1 = NULL; + struct packet_s *p = NULL, *p1 = NULL; + char out[2048], *ptr, out1[2048], *ptr1; + int i, cw; + + h = c->data; + assert(h); + + + if(h->id == 1) { + //max = 4; // p1 4 cards + assert(e->nentity <= 4); + } else { + //max = 3; // p2 3 cards + assert(e->nentity <= 3); + } + + hm_log(LOG_EMERG, lg, "Unwanted cards"); + + for(i = 0; i < h->deck->ncards; i++) { + if(flag(&h->deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) { + + hm_log(LOG_ALERT, c->log, "player %d hand card: %d zone_position: %d", h->entity_id, h->deck->cards[i]->id, h->deck->cards[i]->zone_position); + + cw = 0; + + for(ent = e->entity; ent != NULL; ent = ent->next) { + if(ent->entity == h->deck->cards[i]->id) { + hm_log(LOG_ALERT, c->log, "breaking with card: %d", h->deck->cards[i]->id); + cw = 1; + break; + } + } + + if(cw == 0 && h->deck->cards[i]->id != 68) { + //unwanted[nunwanted++] = h->deck->cards[i]; + + hm_log(LOG_EMERG, c->log, "player %d unwanted card: %d zone_position: %d", h->entity_id, h->deck->cards[i]->id, h->deck->cards[i]->zone_position); + } + } + } + + add_tagchange(&data, MULLIGAN_STATE, 2, h->entity_id); + add_tagchange(&data1, MULLIGAN_STATE, 2, h->entity_id); + + add_powerstart(&data, 5, 6, h->entity_id, 0, NULL, 0); + add_powerstart(&data1, 5, 6, h->entity_id, 0, NULL, 0); + + for(i = 0; i < nunwanted; i++) { + + /* + new_card = draw_random_card(h->deck, h->entity_id, unwanted[i]->zone_position); + + hm_log(LOG_DEBUG, c->log, "playerID: %d new card: %d position: %d", h->entity_id, new_card->id, new_card->zone_position); + + card_tags = default_tags(new_card, new_card->entity, 0); + add_full_entity(&show, card_tags, new_card->id, new_card->entity->name, new_card->entity->nname); + add_ph_data_show(&data, show); + + add_tagchange(&data1, ZONE, 3, new_card->id); + + add_tagchange(&data, ZONE_POSITION, new_card->zone_position, new_card->id); + add_tagchange(&data1, ZONE_POSITION, new_card->zone_position, new_card->id); + + add_hide(&data, unwanted[i]->id, 2); + + add_tagchange(&data, ZONE, 2, unwanted[i]->id); + add_tagchange(&data1, ZONE, 2, unwanted[i]->id); + + add_tagchange(&data, ZONE_POSITION, 0, unwanted[i]->id); + add_tagchange(&data1, ZONE_POSITION, 0, unwanted[i]->id); + + flag(&unwanted[i]->state, CARD_HAND, FLAG_UNSET); + flag(&unwanted[i]->state, CARD_DECK, FLAG_SET); + */ + } + + add_tagchange(&data, MULLIGAN_STATE, 3, h->entity_id); + add_tagchange(&data1, MULLIGAN_STATE, 3, h->entity_id); + + add_powerend(&data); + add_powerend(&data1); + + add_powerstart(&data, 5, 7, h->entity_id, 0, NULL, 0); + add_powerstart(&data1, 5, 7, h->entity_id, 0, NULL, 0); + + add_tagchange(&data, MULLIGAN_STATE, 4, h->entity_id); + add_tagchange(&data1, MULLIGAN_STATE, 4, h->entity_id); + + if(h->id == 1) { + h->game->flags |= G_P1_CARDS_CHOSEN; + } else { + h->game->flags |= G_P2_CARDS_CHOSEN; + } + + if(EQFLAG(h->game->flags, (G_P1_CARDS_CHOSEN|G_P2_CARDS_CHOSEN))) { + add_tagchange(&data, NEXT_STEP, 6, 1); + add_tagchange(&data1, NEXT_STEP, 6, 1); + } + + add_powerend(&data); + add_powerend(&data1); + + add_ph(&ph, data); + add_packet(&p, ph, P_POWERHISTORY); + + add_ph(&ph1, data1); + add_packet(&p1, ph1, P_POWERHISTORY); + + powerhistory_dump(ph); + powerhistory_dump(ph1); + + ptr = out; + int n = serialize(p, &ptr, ptr + sizeof(out)); + + packet_free(p); + + ptr1 = out1; + int n1 = serialize(p1, &ptr1, ptr1 + sizeof(out1)); + + packet_free(p1); + + //powerhistory_dump(ph); + //powerhistory_dump(ph1); + + // p2 draws a card and notifies p1 + if(EQFLAG(h->game->flags, (G_P1_CARDS_CHOSEN|G_P2_CARDS_CHOSEN))) { + char out2[2048], out3[2048]; + int new_card_id = 0; + int enc, enc3; + struct card_s **obelisk; + + obelisk = malloc(sizeof(void *) * 2); + memset(obelisk, 0, sizeof(void *) * 2); + + if(h->entity_id == 3) { + enc = get_card_start_play(3, h->deck, out2, sizeof(out2), &new_card_id, h->opponent.deck, &obelisk, h); + enc3 = get_card_start_play(2, h->opponent.deck, out3, sizeof(out3), &new_card_id, h->deck, &obelisk, h); + } else { + enc3 = get_card_start_play(3, h->opponent.deck, out3, sizeof(out3), &new_card_id, h->deck, &obelisk, h); + enc = get_card_start_play(2, h->deck, out2, sizeof(out2), &new_card_id, h->opponent.deck, &obelisk, h); + } + + memcpy(out + n, out2, enc); + memcpy(out1 + n1, out3, enc3); + + + hm_send(c, out, n + enc); + hm_send(h->opponent.client, out1, n1 + enc3); + + register_turntimer(c); + } else { + hm_send(c, out, n); + hm_send(h->opponent.client, out1, n1); + } + +} diff --git a/hm_gameserver/src/choose_option.c b/hm_gameserver/src/choose_option.c new file mode 100644 index 0000000..6ffd410 --- /dev/null +++ b/hm_gameserver/src/choose_option.c @@ -0,0 +1,917 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +enum metatype_e { + METATYPE_DAMAGE = 1, + METATYPE_HEAL = 2, +}; + +void cards_reorder(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, u64 position, int summoned) +{ + if(summoned == 0) { + cards_reorder_hand_owner(deck, attacker->id); + } + + // spell card is never placed on board + if(!flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) { + cards_reorder_board_owner(deck, attacker->id, position); + } +} + +struct packet_s *choose_option_player1(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + //struct deck_s *deck; + + p = c->data; + //deck = p->deck; + + add_powerstart(&data, 7, 0, p->held_card, opt->target, NULL, 0); + add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id); + add_tagchange(&data, RESOURCES_USED, p->deck->mana_used, p->entity_id); + add_tagchange(&data, 418, 3, p->entity_id); + add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + add_tagchange(&data, NUM_MINIONS_PLAYED_THIS_TURN, 1, p->entity_id); + + //cards_reorder(deck, &data, attacker, opt, player); + /* + // set new zone positions for owner + if(player == 1) { + cards_reorder_hand_owner(p->deck, p->held_card); + cards_reorder_board_owner(&data, p->deck, p->held_card, opt->position); + + for(i = 0; i < deck->ncards; i++) { + if(EQFLAG(deck->cards[i]->state, CARD_HAND)) { + hm_log(LOG_DEBUG, lg, "new position %d for card: %d", deck->cards[i]->zone_position, deck->cards[i]->id); + add_tagchange(&data, ZONE_POSITION, deck->cards[i]->zone_position, deck->cards[i]->id); + } + } + } + + if(player == 2) { + cards_reorder_hand_opponent(&data, p->deck); + cards_reorder_board_opponent(&data, p->deck); + + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == p->held_card) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i]->entity); + add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data_show(&data, show); + + break; + } + } + } + */ + + add_tagchange(&data, ZONE, 1, p->held_card); + + add_tagchange(&data, JUST_PLAYED, 1, p->held_card); + add_tagchange(&data, ZONE_POSITION, opt->position, p->held_card); + add_tagchange(&data, 397, p->held_card, p->entity_id); + + hm_log(LOG_DEBUG, lg, "board zone position %lld for card: %d", opt->position, p->held_card); + + add_powerstart(&data, 3, -1, p->held_card, opt->target, NULL, 0); + add_powerend(&data); + + add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id); + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + //powerhistory_dump(ph); + + return packet; +} + +struct packet_s *nontarget(struct conn_client_s *c, struct card_s *attacker) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + + p = c->data; + + add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0); + add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id); + add_tagchange(&data, RESOURCES_USED, 1, p->entity_id); + add_tagchange(&data, 418, 2, p->entity_id); + + add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0); + struct powerhistory_entity_s *full = NULL; + struct card_s *card = NULL; + + if(flag(&attacker->state, CARD_HP_REINFORCE, FLAG_ISSET)) { + card = add_new_card(p->game, p->deck, -1, "CS2_101t", -1); + struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0); + int zone_position = zone_position_last(p->deck); + add_tag(&card_tags, ZONE_POSITION, zone_position); + add_tag(&card_tags, CONTROLLER, p->id); + add_tag(&card_tags, ENTITY_ID, card->id); + add_tag(&card_tags, CREATOR, attacker->id); + add_full_entity(&full, card_tags, card->id, card->entity->name, card->entity->nname); + add_ph_data_full(&data, full); + + card->zone_position = zone_position; + //card->state |= (CARD_BOARD|CARD_EXHAUSTED); + flag(&card->state, CARD_BOARD, FLAG_SET); + flag(&card->state, CARD_EXHAUSTED, FLAG_SET); + + } else if(flag(&attacker->state, CARD_HP_DAGGERMASTERY, FLAG_ISSET)) { + card = add_new_card(p->game, p->deck, -1, "CS2_082", -1); + struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0); + add_tag(&card_tags, CONTROLLER, p->id); + add_tag(&card_tags, ENTITY_ID, card->id); + add_tag(&card_tags, CREATOR, attacker->id); + add_full_entity(&full, card_tags, card->id, card->entity->name, card->entity->nname); + add_ph_data_full(&data, full); + + add_tagchange(&data, 334, attacker->id, p->entity_id); + + p->deck->heroweapon = card; + //card->state |= CARD_EXHAUSTED; + flag(&card->state, CARD_EXHAUSTED, FLAG_SET); + } else if(flag(&attacker->state, CARD_HP_SHAPESHIFT, FLAG_ISSET)) { + p->deck->hero->armor += attacker->attack; + p->deck->hero->attack = attacker->attack; + + add_tagchange(&data, ARMOR, p->deck->hero->armor, p->deck->hero->id); + add_tagchange(&data, ATK, attacker->attack, p->deck->hero->id); + } else if(flag(&attacker->state, CARD_HP_ARMORUP, FLAG_ISSET)) { + p->deck->hero->armor += attacker->attack; + add_tagchange(&data, ARMOR, p->deck->hero->armor, p->deck->hero->id); + } else if(flag(&attacker->state, CARD_HP_LIFETAP, FLAG_ISSET)) { + // FIXME: don't let enemy know what card we have + struct powerhistory_entity_s *show = NULL; + struct card_s *drawn_card = draw_random_card(p->deck, p->entity_id, -1); + struct powerhistory_tag_s *card_tags = default_tags(drawn_card, drawn_card->entity, 0); + + p->deck->hero->health -= attacker->attack; + + add_meta(&data, 1, attacker->attack, p->deck->hero->id); + add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, p->deck->hero->id); + add_tagchange(&data, DAMAGE, p->deck->hero->total_health - p->deck->hero->health, p->deck->hero->id); + + hm_log(LOG_DEBUG, lg, "drawn card zone position %d for card: %d", drawn_card->zone_position, drawn_card->id); + add_full_entity(&show, card_tags, drawn_card->id, drawn_card->entity->name, drawn_card->entity->nname); + + add_tagchange(&data, ZONE_POSITION, drawn_card->zone_position, drawn_card->id); + add_ph_data_show(&data, show); + } + + add_powerend(&data); + + add_tagchange(&data, 406, 1, p->entity_id); + add_tagchange(&data, EXHAUSTED, 1, attacker->id); + + if(flag(&attacker->state, CARD_HP_DAGGERMASTERY, FLAG_ISSET)) { + add_tagchange(&data, ATK, card->attack, p->deck->hero->id); + p->deck->hero->attack = card->attack; + } + + add_powerstart(&data, 5, -1, p->entity_id, 0, NULL, 0); + + add_tagchange(&data, 394, 1, p->entity_id); + + add_powerend(&data); + + add_tagchange(&data, 358, 2, p->entity_id); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + //card_set_exhausted(attacker); + + powerhistory_dump(ph); + + return packet; +} + +struct packet_s *spell_hp_damage(struct conn_client_s *c, struct card_s *defender, struct card_s *attacker) +{ + + /* + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + + p = c->data; + + game_attack(p, attacker, defender); + + add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0); + add_tagchange(&data, RESOURCES_USED, p->deck->mana_used, p->entity_id); + add_tagchange(&data, 418, 36, p->entity_id); + add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0); + add_meta(&data, 0, 0, defender->id); + add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id); + add_tagchange(&data, PREDAMAGE, 0, defender->id); + + add_meta(&data, METATYPE_DAMAGE, attacker->attack, defender->id); + add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id); + add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id); + add_powerend(&data); + + add_tagchange(&data, 406, 1, p->entity_id); + add_tagchange(&data, EXHAUSTED, 1, attacker->id); + + check_remove_divine_shield(&data, defender); + + if(defender->health == 0) { + add_tagchange(&data, EXHAUSTED, 0, defender->id); // 43 + add_tagchange(&data, DAMAGE, 0, defender->id); + add_tagchange(&data, ZONE, 4, defender->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, defender->id); + + if(flag(&defender->state, CARD_HERO, FLAG_ISSET)) { + add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PLAYSTATE, 4, p->entity_id); + } else { + cards_board_destroyed_reorder(&data, p->opponent.deck, defender->zone_position); + } + } + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + card_set_exhausted(attacker); + + return packet; + */ + return NULL; +} + +struct packet_s *heal(struct conn_client_s *c, struct card_s *defender, struct card_s *attacker) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + + if(defender->total_health - defender->health > attacker->attack) { + hm_log(LOG_DEBUG, lg, "card: %d healed for %d", defender->id, attacker->attack); + defender->health += attacker->attack; + } else { + hm_log(LOG_DEBUG, lg, "card: %d hp fully restored", defender->id); + defender->health = defender->total_health; + } + + p = c->data; + + add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0); + add_tagchange(&data, RESOURCES_USED, p->deck->mana_used, p->entity_id); + add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0); + add_meta(&data, 0, 0, defender->id); + + add_tagchange(&data, 425, attacker->attack, defender->id); + add_tagchange(&data, 425, 0, defender->id); + + add_meta(&data, 0, attacker->attack, defender->id); + add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id); + + add_powerend(&data); + + add_tagchange(&data, 406, 1, defender->id); + add_tagchange(&data, EXHAUSTED, 1, attacker->id); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + //card_set_exhausted(attacker); + + return packet; +} + +struct packet_s *attack(struct conn_client_s *c, struct chooseoption_s *opt) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct card_s *attacker, *defender; + //struct deck_s *deck; + + p = c->data; + //deck = p->deck; + + attacker = card_get(p->deck, NULL, p->arroworigin); + defender = card_get(p->opponent.deck, p->deck, opt->target); + + assert(attacker && defender); + + //game_attack(p, attacker, defender); + + add_powerstart(&data, 1, -1, attacker->id, defender->id, NULL, 0); + add_tagchange(&data, 417, 1, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PROPOSED_ATTACKER, attacker->id, 1); + add_tagchange(&data, PROPOSED_DEFENDER, opt->target, 1); + add_tagchange(&data, ATTACKING, 1, p->arroworigin); + add_tagchange(&data, NEXT_STEP, 10, 1); + add_tagchange(&data, STEP, 11, 1); + add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id == 2 ? 3 : 2); + + add_tagchange(&data, DEFENDING, 1, opt->target); + add_tagchange(&data, PREDAMAGE, attacker->attack, opt->target); + add_tagchange(&data, PREDAMAGE, 0, opt->target); + add_meta(&data, 1, attacker->attack, opt->target); + + add_tagchange(&data, LAST_AFFECTED_BY, p->arroworigin, opt->target); + add_tagchange(&data, DAMAGE, defender->total_health - defender->health, opt->target); // total damaged caused from beginning + add_tagchange(&data, PREDAMAGE, 1, p->arroworigin); + add_tagchange(&data, PREDAMAGE, 0, p->arroworigin); + + add_meta(&data, 1, defender->attack, p->arroworigin); + + add_tagchange(&data, NUM_ATTACKS_THIS_TURN, 1, p->arroworigin); + + /* + if(--(attacker->actions_number) == 0) { + hm_log(LOG_DEBUG, lg, "setting card %d to EXHAUSTED", attacker->id); + add_tagchange(&data, EXHAUSTED, 1, p->arroworigin); + } + */ + + add_tagchange(&data, PROPOSED_ATTACKER, 0, 1); + add_tagchange(&data, PROPOSED_DEFENDER, 0, 1); + add_tagchange(&data, ATTACKING, 0, p->arroworigin); + add_tagchange(&data, DEFENDING, 0, opt->target); + + //check_remove_divine_shield(&data, defender); + + add_powerend(&data); + + add_powerstart(&data, 6, 0, 1, 0, NULL, 0); + //add_tagchange(&data, NUM_MINIONS_PLAYER_KILLED_THIS_TURN, 1, p->entity_id); // 368 + //add_tagchange(&data, NUM_MINIONS_KILLED_THIS_TURN, 1, 1); // 369 + add_tagchange(&data, 398, 1, p->entity_id); + add_tagchange(&data, 412, 1, p->entity_id); + + //damage_done(p, attacker, defender); + /* + if(attacker->health == 0) { + cards_board_destroyed_reorder(&data, p->deck, attacker->zone_position); + + add_tagchange(&data, EXHAUSTED, 0, attacker->id); // 43 + add_tagchange(&data, DAMAGE, 0, attacker->id); + add_tagchange(&data, ZONE, 4, attacker->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + } else { + add_tagchange(&data, DAMAGE, attacker->total_health - attacker->health, attacker->id); // total damaged caused from beginning + card_set_exhausted(attacker); + } + + add_tagchange(&data, ARMOR, defender->armor, defender->id); + add_tagchange(&data, ARMOR, attacker->armor, attacker->id); + + if(defender->health == 0) { + add_tagchange(&data, EXHAUSTED, 0, defender->id); // 43 + add_tagchange(&data, DAMAGE, 0, defender->id); + add_tagchange(&data, ZONE, 4, defender->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, defender->id); + + if(EQFLAG(defender->state, CARD_HERO)) { + add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PLAYSTATE, 4, p->entity_id); + } else { + cards_board_destroyed_reorder(&data, p->opponent.deck, defender->zone_position); + } + } + */ + + + /** destroy both */ + /* + add_tagchange(&data, ZONE, 4, attacker->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + add_tagchange(&data, ZONE, 4, defender->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, defender->id); + attacker->state = CARD_DESTROYED; + defender->state = CARD_DESTROYED; + */ + + add_powerend(&data); + + add_tagchange(&data, STEP, 10, 1); + add_powerstart(&data, 5, 2, p->entity_id, 0, NULL, 0); + + if(flag(&attacker->state, CARD_HERO, FLAG_ISSET) && p->deck->heroweapon) { + + p->deck->heroweapon->durability--; + + add_meta(&data, 1, p->deck->heroweapon->attack, p->deck->heroweapon->id); + add_tagchange(&data, LAST_AFFECTED_BY, p->deck->hero->id, p->deck->heroweapon->id); + + add_tagchange(&data, DAMAGE, p->deck->heroweapon->maxdurability - p->deck->heroweapon->durability, p->deck->heroweapon->id); + add_tagchange(&data, EXHAUSTED, 1, p->deck->heroweapon->id); + + if(p->deck->heroweapon->durability == 0) { + add_tagchange(&data, ZONE, 4, p->deck->heroweapon->id); + add_tagchange(&data, ATK, 0, attacker->id); + + //p->deck->heroweapon->state |= CARD_DESTROYED; + flag(&p->deck->heroweapon->state, CARD_DESTROYED, FLAG_SET); + p->deck->hero->attack = 0; + + hm_log(LOG_DEBUG, lg, "heroweapon destroyed %d", p->deck->heroweapon->id); + + p->deck->heroweapon = NULL; + } + + } + + add_tagchange(&data, NEXT_STEP, 12, 1); + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + + return packet; +} + +struct packet_s *buff(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_s *defender) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct deck_s *deck; + int i; + + p = c->data; + deck = p->deck; + + + add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0); + add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost + add_tagchange(&data, 418, 26, p->entity_id); + add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + add_tagchange(&data, 430, 1, p->entity_id); + + add_tagchange(&data, ZONE, 1, attacker->id); + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + add_tagchange(&data, JUST_PLAYED, 1, attacker->id); + + add_tagchange(&data, 397, attacker->id, p->entity_id); + add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + //cards_reorder(deck, &data, attacker, opt, player); + + if(player == 2) { + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == p->held_card) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0); + add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data_show(&data, show); + + break; + } + } + } + + add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0); + + add_meta(&data, 0, 0, defender->id); + //add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id); + //add_tagchange(&data, PREDAMAGE, 0, opt->target); + add_meta(&data, 3, 0, opt->target); + + add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id); + //add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id); + add_powerend(&data); + + add_tagchange(&data, ZONE, 4, attacker->id); + add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id); + + add_tagchange(&data, WINDFURY, 1, defender->id); + //damage_done(&data, p, attacker, defender); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; +} + +/* + static void defender_attacked(struct hs_holder_s *p, struct powerhistory_data_s **data, struct card_s *attacker, struct card_s *defender, struct chooseoption_s *opt) + { + add_meta(data, 0, 0, defender->id); + add_tagchange(data, PREDAMAGE, attacker->attack, defender->id); + add_tagchange(data, PREDAMAGE, 0, opt->target); + add_meta(data, 1, attacker->attack, opt->target); + + add_tagchange(data, LAST_AFFECTED_BY, attacker->id, defender->id); + add_tagchange(data, DAMAGE, defender->total_health - defender->health, defender->id); + add_powerend(data); + + add_tagchange(data, ZONE, 4, attacker->id); + add_tagchange(data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id); + +//damage_done(p, attacker, defender); +} +*/ + +struct packet_s *spell_damage_aoe(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct deck_s *deck; + struct card_list_s *def; + + p = c->data; + deck = p->deck; + + add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0); + add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost + add_tagchange(&data, 418, 26, p->entity_id); + add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + add_tagchange(&data, 430, 1, p->entity_id); + + add_tagchange(&data, ZONE, 1, attacker->id); + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + add_tagchange(&data, JUST_PLAYED, 1, attacker->id); + + add_tagchange(&data, 397, attacker->id, p->entity_id); + + //cards_reorder(deck, &data, attacker, opt, player); + + /* + if(player == 2) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(attacker->entity); + add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname); + add_ph_data_show(&data, show); + } + */ + + if(defenders != NULL) { + add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0); + + struct powerhistory_info_s *info = NULL; + + for(def = defenders; def != NULL; def = def->next) { + add_info(&info, def->card->id); + } + + add_meta_info(&data, 0, 0, info); + } + + for(def = defenders; def != NULL; def = def->next) { + hm_log(LOG_DEBUG, lg, "AOE spell %d attacking %d", attacker->id, def->card->id); + add_tagchange(&data, PREDAMAGE, attacker->attack, def->card->id); + add_tagchange(&data, PREDAMAGE, 0, def->card->id); + add_meta(&data, 1, attacker->attack, def->card->id); + + //check_remove_divine_shield(&data, def); + + add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, def->card->id); + + add_tagchange(&data, DAMAGE, def->card->total_health - def->card->health, def->card->id); + + //damage_done(p, attacker, def->card); + + } + + if(defenders != NULL) { + add_powerend(&data); + } + + add_tagchange(&data, ZONE, 4, attacker->id); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + flag(&attacker->state, CARD_BOARD, FLAG_UNSET); + + return packet; +} + +struct packet_s *spell_damage(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_s *defender) +{ + /* + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct deck_s *deck; + + p = c->data; + deck = p->deck; + + add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0); + add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost + add_tagchange(&data, 418, 26, p->entity_id); + add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + add_tagchange(&data, 430, 1, p->entity_id); + + add_tagchange(&data, ZONE, 1, attacker->id); + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + add_tagchange(&data, JUST_PLAYED, 1, attacker->id); + + add_tagchange(&data, 397, attacker->id, p->entity_id); + add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + //cards_reorder(deck, &data, attacker, opt, player); + + //check_remove_divine_shield(&data, defender); + + + if(player == 2) { + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == p->held_card) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i]->entity); + add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data_show(&data, show); + + break; + } + } + } + + if(EQFLAG(attacker->state, CARD_NONTARGET)) { + struct deck_s *opp = p->opponent.deck; + for(i = 0; i < opp->ncards; i++) { + if(EQFLAG(opp->cards[i]->state, CARD_BOARD)) { + + add_powerstart(&data, 3, -1, attacker->id, opp->cards[i]->id, NULL, 0); + defender_attacked(p, &data, attacker, opp->cards[i], opt); + add_powerend(&data); + } + } + } else { + add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0); + defender_attacked(p, &data, attacker, defender, opt); + add_powerend(&data); + } + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; + */ + return NULL; +} + + +int choose_option(struct conn_client_s *c, struct chooseoption_s *opt) +{ + //struct packet_s *p1 = NULL, *p2 = NULL; + //struct hs_holder_s *p; + //char output[1024 * 8], *ptr; + //int n; + //const char opt1[14] = { 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x08, 0x12, 0x02, 0x08, 0x02, }; + + game(c, opt); + + /* + + chooseoption_dump(opt, p->held_card); + + // aoe spell + if(p->held_card > 0) { + struct card_s *attacker = card_get(p->deck, NULL, p->held_card); + if(attacker && flag(&attacker->state, CARD_AOE_ENEMY_MINIONS, FLAG_ISSET)) { + struct card_list_s *defenders = NULL; + + //attacker->state &= ~CARD_DECK; + flag(&attacker->state, CARD_DECK, FLAG_UNSET); + + ///< get opponent's board cards + defenders = cards_get_board(NULL, p->opponent.deck); + + hm_log(LOG_INFO, c->log, "Casting AOE %d against enemy minions", p->held_card); + assert(attacker); + game_attack_aoe(p, attacker, defenders); + + p1 = spell_damage_aoe(c, opt, 1, attacker, defenders); + p2 = spell_damage_aoe(c, opt, 2, attacker, defenders); + + ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + + hm_log(LOG_INFO, c->log, "Serialized %d bytes", n); + hm_send(c, output, n); + + if(p2) { + ptr = output; + n = serialize(p2, &ptr, ptr + sizeof(output)); + } + + hm_send(p->opponent.client, output, n); + + + int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn); + hm_send(c, output, so); + + goto skip; + } + } + + // play nontarget hero power + if(p->held_card > 0 && p->held_card == p->deck->heropower->id && + flag(&p->deck->heropower->state, CARD_NONTARGET, FLAG_ISSET)) { + + hm_log(LOG_ERR, c->log, "playing nontarget hero power %d", p->held_card); + + struct card_s *attacker = p->deck->heropower; + + assert(attacker); + + p1 = nontarget(c, attacker); + + ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + hm_send(c, output, n); + hm_send(p->opponent.client, output, n); + + int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn); + hm_send(c, output, so); + + // next turn + } else if(opt->index == 0) { + struct card_s *drawn_card = NULL; + int zone = 0; + + if(p->game->turn % 2 == 0 && p->deck->mana < 10) { + p->deck->mana++; + p->opponent.deck->mana++; +} + +p->game->turn++; + +cards_unset_flag(p->opponent.deck, CARD_EXHAUSTED); + +hm_log(LOG_INFO, c->log, "Next turn: %d", p->game->turn); +p1 = next_turn(c, opt, &drawn_card, &zone); +p2 = next_turn(c, opt, &drawn_card, &zone); + +ptr = output; +n = serialize(p1, &ptr, ptr + sizeof(output)); +hm_send(c, output, n); + +ptr = output; +n = serialize(p2, &ptr, ptr + sizeof(output)); + +int so = set_options(p->opponent.deck, p->deck, output + n, output + sizeof(output) - n, p->game->turn); + +//memcpy(output + n + so, opt1, sizeof(opt1)); + +hm_send(p->opponent.client, output, n + so); + +// attack or spell damage +} else if((opt->target != 0 && p->arroworigin != 0)) { + struct card_s *attacker = card_get(p->deck, NULL, p->arroworigin); + struct card_s *defender; + + hm_log(LOG_ERR, c->log, "origin: %d target: %lld id %d", p->arroworigin, opt->target, attacker->id); + + defender = card_get(p->deck, p->opponent.deck, opt->target); + assert(attacker && defender); + + if(flag(&attacker->state, (CARD_SPELL_DAMAGE), FLAG_ISSET)) { + hm_log(LOG_INFO, c->log, "Casting spell damage %d > %lld", p->arroworigin, opt->target); + assert(attacker && defender); + game_attack(p, attacker, defender); + + //attacker->state &= ~CARD_DECK; + flag(&attacker->state, CARD_DECK, FLAG_UNSET); + + p1 = spell_damage(c, opt, 1, attacker, defender); + p2 = spell_damage(c, opt, 2, attacker, defender); + } else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_SPELL_HEAL, FLAG_ISSET)) { + hm_log(LOG_INFO, c->log, "Healing %d > %lld", p->arroworigin, opt->target); + p1 = heal(c, defender, attacker); + } else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_HP_SPELL_DAMAGE, FLAG_ISSET)) { + hm_log(LOG_INFO, c->log, "Casting HP spell %d > %lld", p->arroworigin, opt->target); + p1 = spell_hp_damage(c, defender, attacker); + } else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_WINDFURY, FLAG_ISSET)) { + hm_log(LOG_INFO, c->log, "Casting windfury spell %d > %lld", p->arroworigin, opt->target); + p1 = buff(c, opt, 1, attacker, defender); + p2 = buff(c, opt, 2, attacker, defender); + } else { + hm_log(LOG_INFO, c->log, "Attacking %d > %lld", p->arroworigin, opt->target); + p1 = attack(c, opt); + } + + ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + + hm_log(LOG_INFO, c->log, "Serialized %d bytes", n); + hm_send(c, output, n); + + if(p2) { + ptr = output; + n = serialize(p2, &ptr, ptr + sizeof(output)); + } + + hm_send(p->opponent.client, output, n); + + + int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn); + hm_send(c, output, so); + + + // put card on board +} else if(p->held_card > 0) { + struct card_s *attacker = card_get(p->deck, NULL, p->held_card); + assert(attacker); + + hm_log(LOG_INFO, lg, "Putting card %d on board", attacker->id); + + flag(&attacker->state, CARD_HAND, FLAG_UNSET); + flag(&attacker->state, CARD_BOARD, FLAG_SET); + if(!flag(&attacker->state, CARD_CHARGE, FLAG_ISSET)) { + flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET); + } + + hm_log(LOG_INFO, lg, "Flags for card %d:", attacker->id); + flag(&attacker->state, -1, FLAG_DUMP); + + p1 = choose_option_player(c, opt, 1, attacker); + p2 = choose_option_player(c, opt, 2, attacker); + + ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + + int so = set_options(p->deck, p->opponent.deck, output + n, output + sizeof(output) - n, p->game->turn); + + //hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator", n + so); + hm_send(c, output, (int)(n + so)); + + char output2[2048]; + ptr = output2; + int n2 = serialize(p2, &ptr, ptr + sizeof(output2)); + + //hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator's opponent", n); + hm_send(p->opponent.client, output2, n2); +} + +skip: + +// unset origin +p->arroworigin = 0; + +// unset +p->held_card = 0; + +hm_log(LOG_INFO, c->log, "Unsetting held card %d arroworigin %d", p->held_card, p->arroworigin); +*/ + +return 0; +} diff --git a/hm_gameserver/src/common.c b/hm_gameserver/src/common.c new file mode 100644 index 0000000..df28add --- /dev/null +++ b/hm_gameserver/src/common.c @@ -0,0 +1,464 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +const struct ent_s *find_entity(const char *name, const int nname) +{ + int i; + + for(i = 0; i < MAX_ENTITIES; i++) { + if(nname == entities[i].nname && memcmp(entities[i].name, name, nname) == 0) { + return &entities[i]; + } + } + + hm_log(LOG_EMERG, lg, "Entity [%.*s] not found", nname, name); + + return NULL; +} + +struct powerhistory_tag_s *add_tag(struct powerhistory_tag_s **dst, const int key, const int value) +{ + struct powerhistory_tag_s *t; + + t = malloc(sizeof(*t)); + if(t == NULL) { + return NULL; + } + + t->name = key; + t->value = value; + + t->next = *dst; + *dst = t; + + return t; +} + +struct powerhistory_game_entity_s *add_game_entity(struct powerhistory_game_entity_s **dst, struct powerhistory_tag_s *tag, const int id) +{ + struct powerhistory_game_entity_s *g; + + g = malloc(sizeof(*g)); + if(g == NULL) { + return NULL; + } + + g->id = id; + g->tag = g->tag_tail = tag; + + *dst = g; + + return g; +} + +struct powerhistory_tag_s *default_tags(struct card_s *card, const struct ent_s *ent, int zone_override) +{ + int i; + struct powerhistory_tag_s *tag = NULL; + + for(i = 0; i < ent->nprop; i++) { + //#define TEST_COST_ +#undef TEST_COST_ +#ifdef TEST_COST_ + if(ent->p[i].key == COST) { + add_tag(&tag, COST, 0); + continue; + } +#endif + + // buffed summoned unit + if(ent->p[i].key == HEALTH && card->health != ent->p[i].value) { + add_tag(&tag, ent->p[i].key, card->health); + continue; + } + + // buffed summoned unit + if(ent->p[i].key == ATK && card->attack != ent->p[i].value) { + add_tag(&tag, ent->p[i].key, card->attack); + continue; + } + + // don't add default zone 3 + if(ent->p[i].key == ZONE && zone_override > 0) { + add_tag(&tag, ent->p[i].key, zone_override); + } else { + add_tag(&tag, ent->p[i].key, ent->p[i].value); + } + } + + if(card) { + int *f = NULL; + int c; + c = flag_get(&card->state, &f); + + for(i = 0; i < c; i++) { + switch(f[i]) { + case CARD_TAUNT: + add_tag(&tag, TAUNT, 1); + break; + case CARD_WINDFURY: + add_tag(&tag, WINDFURY, 1); + break; + case CARD_DIVINE_SHIELD: + add_tag(&tag, DIVINE_SHIELD, 1); + break; + case CARD_STEALTH: + add_tag(&tag, STEALTH, 1); + break; + case CARD_FREEZE: + add_tag(&tag, FREEZE, 1); + break; + case CARD_SPELLPOWER: + add_tag(&tag, SPELLPOWER, 1); + break; + + } + } + + if(flag(&card->state, CARD_HEROPOWER, FLAG_ISSET) || flag(&card->state, CARD_HEROPOWER, FLAG_ISSET)) { + add_tag(&tag, ZONE, 1); + } + // add Premium + //add_tag(&tag, PREMIUM, 1); + + if(f) free(f); + } + + return tag; +} + +void add_hide(struct powerhistory_data_s **dst, u64 entity, u64 zone) +{ + struct powerhistory_data_s *data; + struct powerhistory_hide_s *hide = NULL; + + hide = malloc(sizeof(*hide)); + hide->entity = entity; + hide->zone = zone; + + data = malloc(sizeof(*data)); + memset(data, 0, sizeof(*data)); + data->hide = hide; + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = data; + (*dst)->tail = data; + } else { + *dst = data; + (*dst)->tail = (*dst)->next = data; + } + + /* + data->next = *dst; + *dst = data; + */ +} + +void add_info(struct powerhistory_info_s **dst, u64 infoid) +{ + struct powerhistory_info_s *info = NULL; + + info = malloc(sizeof(*info)); + info->id = infoid; + info->next = *dst; + + if(dst) *dst = info; +} + +void add_meta_info(struct powerhistory_data_s **dst, u64 type, u64 d, struct powerhistory_info_s *info) +{ + struct powerhistory_data_s *data; + struct powerhistory_meta_s *meta = NULL; + + meta = malloc(sizeof(*meta)); + meta->type = type; + meta->data = d; + + meta->info = info; + + data = malloc(sizeof(*data)); + memset(data, 0, sizeof(*data)); + data->meta = meta; + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = data; + (*dst)->tail = data; + } else { + *dst = data; + (*dst)->tail = (*dst)->next = data; + } +} + +void add_meta(struct powerhistory_data_s **dst, u64 type, u64 d, u64 infoid) +{ + struct powerhistory_data_s *data; + struct powerhistory_meta_s *meta = NULL; + struct powerhistory_info_s *info = NULL; + + meta = malloc(sizeof(*meta)); + meta->type = type; + meta->data = d; + + info = malloc(sizeof(*info)); + memset(info, 0, sizeof(*info)); + info->id = infoid; + + meta->info = info; + + data = malloc(sizeof(*data)); + memset(data, 0, sizeof(*data)); + data->meta = meta; + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = data; + (*dst)->tail = data; + } else { + *dst = data; + (*dst)->tail = (*dst)->next = data; + } +} + +void add_tagchange(struct powerhistory_data_s **dst, u64 key, u64 value, u64 id) +{ + struct powerhistory_data_s *data; + struct powerhistory_tagchange_s *tag = NULL; + + tag = malloc(sizeof(*tag)); + tag->entity = id; + tag->tag = key; + tag->value = value; + + data = malloc(sizeof(*data)); + memset(data, 0, sizeof(*data)); + data->tagchange = tag; + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = data; + (*dst)->tail = data; + } else { + *dst = data; + (*dst)->tail = (*dst)->next = data; + } + + /* + data->next = *dst; + *dst = data; + */ +} + +void add_powerend(struct powerhistory_data_s **dst) +{ + struct powerhistory_data_s *data; + struct powerhistory_powerend_s *ps = NULL; + + ps = malloc(sizeof(*ps)); + memset(ps, 0, sizeof(*ps)); + + data = malloc(sizeof(*data)); + memset(data, 0, sizeof(*data)); + data->powerend = ps; + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = data; + (*dst)->tail = data; + } else { + *dst = data; + (*dst)->tail = (*dst)->next = data; + } + + /* + data->next = *dst; + *dst = data; + */ +} + +void add_powerstart(struct powerhistory_data_s **dst, u64 type, u64 index, u64 source, u64 target, char *card_id, int ncard_id) +{ + struct powerhistory_data_s *data; + struct powerhistory_powerstart_s *ps = NULL; + + ps = malloc(sizeof(*ps)); + ps->type = type; + ps->index = index; + ps->source = source; + ps->target = target; + ps->ncard_id = ncard_id; + ps->card_id = card_id; + + data = malloc(sizeof(*data)); + memset(data, 0, sizeof(*data)); + data->powerstart = ps; + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = data; + (*dst)->tail = data; + } else { + *dst = data; + (*dst)->tail = (*dst)->next = data; + } + + /* + data->next = *dst; + *dst = data; + */ +} + +void add_tagschange(struct powerhistory_data_s **dst, const struct ent_s *ent, u64 id) +{ + int i; + + for(i = 0; i < ent->nprop; i++) { + add_tagchange(dst, ent->p[i].key, ent->p[i].value, id); + } + + add_tagchange(dst, ENTITY_ID, id, id); +} + +void add_player(struct powerhistory_player_s **dst, u64 id, u64 bhi, u64 blo, u64 cardback, struct powerhistory_game_entity_s *ent) +{ + struct powerhistory_player_s *p; + + p = malloc(sizeof(*p)); + + p->id = id; + p->bnet_hi = bhi; + p->bnet_lo = blo; + p->cardback = cardback; + + p->entity = ent; + p->next = *dst; + *dst = p; +} + +void add_game_start(struct powerhistory_creategame_s **dst, struct powerhistory_game_entity_s *ge, struct powerhistory_player_s *p) +{ + *dst = malloc(sizeof(**dst)); + + (*dst)->game_entity = ge; + (*dst)->player = p; +} + +void add_ph_data_full(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full) +{ + struct powerhistory_data_s *p; + + p = malloc(sizeof(*p)); + memset(p, 0, sizeof(*p)); + + if(full) { + p->full = full; + } + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = p; + (*dst)->tail = p; + } else { + *dst = p; + (*dst)->tail = (*dst)->next = p; + } +} + + +void add_ph_data_show(struct powerhistory_data_s **dst, struct powerhistory_entity_s *show) +{ + struct powerhistory_data_s *p; + + p = malloc(sizeof(*p)); + memset(p, 0, sizeof(*p)); + + if(show) { + p->show = show; + } + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = p; + (*dst)->tail = p; + } else { + *dst = p; + (*dst)->tail = (*dst)->next = p; + } +} + +void add_ph_data(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full, struct powerhistory_creategame_s *cg) +{ + struct powerhistory_data_s *p; + + p = malloc(sizeof(*p)); + memset(p, 0, sizeof(*p)); + + if(cg) { + p->creategame = cg; + } + + if(full) { + p->full = full; + } + + if(*dst && (*dst)->tail) { + (*dst)->tail->next = p; + (*dst)->tail = p; + } else { + *dst = p; + (*dst)->tail = (*dst)->next = p; + } + /* + *dst->tail = p; + p->next = *dst; + *dst = p; + */ +} + +void add_full_entity(struct powerhistory_entity_s **full, struct powerhistory_tag_s *tags, u64 id, const char *name, const int nname) +{ + *full = malloc(sizeof(**full)); + memset(*full, 0, sizeof(**full)); + + (*full)->entity = id; + (*full)->tag = tags; + (*full)->nname = nname; + (*full)->name = (char *)name; +} + +void add_ph(struct powerhistory_s **dst, struct powerhistory_data_s *data) +{ + *dst = malloc(sizeof(**dst)); + memset(*dst, 0, sizeof(**dst)); + + (*dst)->data = data; +} + +void add_packet(struct packet_s **dst, void *ph, enum packet_e n) +{ + *dst = malloc(sizeof(**dst)); + memset(*dst, 0, sizeof(**dst)); + + (*dst)->data = ph; + (*dst)->id = n; +} + +void bin_dump(char *buf, const int len) +{ + int i; + + printf("binary dump of %d:\n", len); + for(i = 0; i < len; i++) { + printf("%x|", (unsigned char)buf[i]); + } + printf("\n"); +} diff --git a/hm_gameserver/src/entitychoices.c b/hm_gameserver/src/entitychoices.c new file mode 100644 index 0000000..9cf06f9 --- /dev/null +++ b/hm_gameserver/src/entitychoices.c @@ -0,0 +1,75 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct entitychoices_s *chooseone_choices(struct card_list_s *defenders, int player_id, int attacker_id) +{ + struct entitychoices_s *ec; + struct entitychoices_entities_s *etmp; + struct card_list_s *def; + + ec = malloc(sizeof(*ec)); + + ec->id = 3; + ec->type = 2; + ec->countmin = 1; + ec->countmax = 1; + ec->source = attacker_id; + ec->player_id = player_id; + ec->entities = NULL; + + for(def = defenders; def != NULL; def = def->next) { + etmp = malloc(sizeof(*etmp)); + etmp->entity = def->card->id; + etmp->next = ec->entities; + ec->entities = etmp; + } + + + return ec; +} + +struct entitychoices_s *prepare_choices(struct deck_s *deck, int player_id) +{ + struct entitychoices_s *ec; + struct entitychoices_entities_s *etmp; + int i, drawn = 0; + + ec = malloc(sizeof(*ec)); + + ec->id = 1; + ec->type = 1; + ec->countmin = 0; + ec->source = 1; + ec->player_id = player_id; + ec->entities = NULL; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) { + etmp = malloc(sizeof(*etmp)); + etmp->entity = deck->cards[i]->id; + etmp->next = ec->entities; + ec->entities = etmp; + drawn++; + } + } + + ec->countmax = drawn; + + return ec; +} diff --git a/hm_gameserver/src/game/card.c b/hm_gameserver/src/game/card.c new file mode 100644 index 0000000..ea7be95 --- /dev/null +++ b/hm_gameserver/src/game/card.c @@ -0,0 +1,998 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void card_to_deck(struct card_s *card) +{ + flag(&card->state, CARD_HAND, FLAG_UNSET); +} + +struct card_s *card_get_levelup_boss(struct deck_s *deck, struct card_s *card) +{ + const char *bossname = NULL; + int i; + + for(i = 0; i < MAX_LEVELUP; i++) { + + hm_log(LOG_DEBUG, lg, "Levelup boss: [%s] [%s]", card->entity->name, levelup[i].src); + if(strcmp(card->entity->name, levelup[i].src) == 0) { + bossname = levelup[i].dst; + break; + } + } + + if(bossname == NULL) { + return NULL; + } + + for(i = 0; deck != NULL && i < deck->ncards; i++) { + if((flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)) && + flag(&deck->cards[i]->state, CARD_BOSS, FLAG_ISSET)) { + return deck->cards[i]; + } + } + + return NULL; +} + +struct card_s *card_get_hero(struct deck_s *deck) +{ + int i; + + for(i = 0; deck != NULL && i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET)) { + return deck->cards[i]; + } + } + + return NULL; +} + + +struct card_s *card_get(struct deck_s *deck, struct deck_s *opponent, const int id) +{ + int i; + + +#define FCARD(m__d)\ + for(i = 0; m__d != NULL && i < m__d->ncards; i++) {\ + if(id == m__d->cards[i]->id) {\ + hm_log(LOG_DEBUG, lg, "card [%s](%d) found in deck %d", m__d->cards[i]->entity->desc, m__d->cards[i]->id, m__d->controller);\ + assert(m__d->cards[i]->parent);\ + return m__d->cards[i];\ + }\ + } + + FCARD(deck) + FCARD(opponent) + + hm_log(LOG_DEBUG, lg, "card (%d) not found in any deck (%d %d)", id, (deck ? deck->ncards : -1), (opponent ? opponent->ncards : -1));\ + return NULL; +} + +struct card_list_s *cards_get_board_boss(struct deck_s *deck) +{ + int i; + struct card_list_s *list = NULL, *item; + + for(i = 0; deck != NULL && i < deck->ncards; i++) { + if((flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)) && + flag(&deck->cards[i]->state, CARD_BOSS, FLAG_ISSET)) { + LIST_ADD(list, item, deck->cards[i]); + } + } + + return list; +} + +struct card_list_s *cards_get_hand(struct deck_s *deck) +{ + int i; + struct card_list_s *list = NULL, *item; + + for(i = 0; deck != NULL && i < deck->ncards; i++) { + if((flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET))) { + LIST_ADD(list, item, deck->cards[i]); + } + } + + return list; +} + + +struct card_list_s *cards_get_board(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude, int magic_immunity, int boss) +{ + int i; + struct card_list_s *list = NULL, *item; + +#define CBOARD(d)\ + for(i = 0; d != NULL && i < d->ncards; i++) {\ + if(d->cards[i]->id == exclude) continue;\ + if((flag(&d->cards[i]->state, CARD_DIVINE_SHIELD, FLAG_ISSET)) && magic_immunity == 0) continue;\ + if((flag(&d->cards[i]->state, CARD_BOSS, FLAG_ISSET)) && boss == 0) continue;\ + if((flag(&d->cards[i]->state, CARD_BOARD, FLAG_ISSET) && !flag(&d->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && !flag(&d->cards[i]->state, CARD_HEROWEAPON, FLAG_ISSET)) || \ + (flag(&d->cards[i]->state, CARD_HERO, FLAG_ISSET) && hero == 1)\ + ) {\ + hm_log(LOG_DEBUG, lg, "Card [%s](%d) found in deck %d", d->cards[i]->entity->desc, d->cards[i]->id, d->controller);\ + LIST_ADD(list, item, d->cards[i]);\ + }\ + } + + CBOARD(deck) + CBOARD(opponent) + + return list; +} + +int cards_get_board_count(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude) +{ + int i; + int total = 0; + +#define CBOARD1(d)\ + for(i = 0; d != NULL && i < d->ncards; i++) {\ + if(d->cards[i]->id == exclude) continue;\ + if((flag(&d->cards[i]->state, CARD_BOARD, FLAG_ISSET) && !flag(&d->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)) || \ + (flag(&d->cards[i]->state, CARD_HERO, FLAG_ISSET) && hero == 1)\ + ) {\ + total++;\ + /*hm_log(LOG_DEBUG, lg, "Card [%s](%d) found in deck %d", d->cards[i]->entity->desc, d->cards[i]->id, d->controller);*/\ + \ + }\ + } + + CBOARD1(deck) + CBOARD1(opponent) + + return total; +} + +struct card_s *card_random(struct card_list_s *l) +{ + struct card_list_s *c; + int count; + + for(count = 0, c = l; c != NULL; c = c->next, count++); + + if(count < 1) { + return NULL; + } + + int r = random_number(count); + + for(count = 0, c = l; c != NULL && count != r; c = c->next, count++); + + return c ? c->card : NULL; +} + +int cards_count(struct card_list_s *l) +{ + struct card_list_s *c; + int count; + + for(count = 0, c = l; c != NULL; c = c->next, count++); + + return count; +} + +void cards_board_destroyed_reorder(struct deck_s *deck, int position) +{ + int i; + + hm_log(LOG_DEBUG, lg, "Destroying zone position %d from deck %d", position, deck->controller); + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) && + deck->cards[i]->zone_position > position) { + --(deck->cards[i]->zone_position); + hm_log(LOG_DEBUG, lg, "Decreased board zone position %d for card: %d", deck->cards[i]->zone_position, deck->cards[i]->id); + } + } +} + +void card_free(struct card_s *card, unsigned int flags) +{ + + struct card_link_s *children, *del; + struct card_list_s *t, *tdel; + struct card_expire_s *ce, *ced; + + if(EQFLAG(flags, FREE_CARD_CHILDREN)) { + for(children = card->attached_children; children != NULL; ) { + del = children; + children = children->next; + free(del); + } + } + + if(EQFLAG(flags, FREE_CARD_EXPIRE)) { + for(ce = card->expire; ce != NULL; ) { + ced = ce; + ce = ce->next; + free(ced); + } + } + + for(t = card->target.card; t != NULL; ) { + tdel = t; + t = t->next; + free(tdel); + } + + free(card); +} + +int deck_get_taunts(struct deck_s *deck) +{ + int i, c = 0; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_TAUNT, FLAG_ISSET) && flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET)) { + c++; + } + } + + hm_log(LOG_DEBUG, lg, "Deck %d taunt cards: %d", deck->controller, c); + + return c; +} + +void cards_unset_flag(struct deck_s *deck, enum flags_e flags) +{ + int i; + + for(i = 0; i < deck->ncards; i++) { + flag(&deck->cards[i]->state, flags, FLAG_UNSET); + } +} + + +void reset_turn_plays(struct deck_s *deck) +{ + int i; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET)) { + deck->cards[i]->turn_plays = 0; + } + } +} + +void unset_mechanics_flags(struct hs_holder_s *p) +{ + struct deck_s *deck; + int i; + +#define clr\ + for(i = 0; i < deck->ncards; i++) {\ + flag(&deck->cards[i]->state, MECHANICS_ATTACK, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_DAMAGE, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_HEALTH, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_ATTACK_HEAL, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_ATTACK_DAMAGE, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_HEROPOWER, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_CHANGESIDES, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_ARMOR, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_DURABILITY, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_DETACH, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_SELECTED, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_DESTROY_WEAPON, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_TURN_TRIGGER, FLAG_UNSET);\ + flag(&deck->cards[i]->state, MECHANICS_COST, FLAG_UNSET);\ + } + + deck = p->deck; + clr + deck = p->opponent.deck; + clr +} + +int zone_position_last(struct deck_s *deck) +{ + int i, position = 0; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + deck->cards[i]->zone_position > position) { + position = deck->cards[i]->zone_position; + } + } + + return ++position; +} + +int cards_get_board_count_flag(struct deck_s *deck, struct card_s *card, int f) +{ + int i; + int count = 0; + + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == card->id) { + continue; + } + + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + flag(&deck->cards[i]->state, f, FLAG_ISSET)) { + count++; + } + } + + hm_log(LOG_DEBUG, lg, "Found %d cards for flag %d", count, f); + + return count; +} + +int cards_board_last(struct deck_s *deck) +{ + int i; + int position = 1; + + for(i = 0; i < deck->ncards; i++) { + /* + if(deck->cards[i]->id == card->id) { + continue; + } + */ + + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) && + deck->cards[i]->zone_position >= position) { + + hm_log(LOG_DEBUG, lg, "Zone position increased with card %d position %d", deck->cards[i]->id, deck->cards[i]->zone_position); + position = deck->cards[i]->zone_position + 1; + } + } + + return position; +} + +static void add_child_link(struct card_s *dst, int id, const char *name) +{ + struct card_link_s *a; + + a = malloc(sizeof(*a)); + a->id = id; + a->name = name; + a->next = dst->attached_children; + dst->attached_children = a; +} + +void cards_dump(struct deck_s *deck, struct deck_s *opponent) +{ + int i; + + hm_log(LOG_DEBUG, lg, "Cards dump started"); + +#define dump(d)\ + hm_log(LOG_DEBUG, lg, "Cards dump for deck %d:", d->controller);\ + for(i = 0; i < d->ncards; i++) {\ + if(flag(&d->cards[i]->state, CARD_BOARD, FLAG_ISSET) || \ + flag(&d->cards[i]->state, CARD_HAND, FLAG_ISSET) \ + ) {\ + hm_log(LOG_DEBUG, lg, "\t\tName[%s](%d) zone position[%d] attack[%d] health[%d] totalhealth[%d]", d->cards[i]->entity->desc, d->cards[i]->id, d->cards[i]->zone_position, d->cards[i]->attack, d->cards[i]->health, d->cards[i]->total_health);\ + flag(&d->cards[i]->state, -1, FLAG_DUMP);\ + }\ + } + + dump(deck) + dump(opponent) + + hm_log(LOG_DEBUG, lg, "Cards dump finished"); +} + +void cards_reorder_board_owner(struct deck_s *deck, u64 held, u64 position) +{ + int i; + + if(position - 1 >= MAX_BOARD) { + position = MAX_BOARD; + } + + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == held) { + + deck->cards[i]->zone_position = position; + deck->board_position[position - 1] = deck->cards[i]->id; + + continue; + } + + // when card on board is positioned equally or higher than new card + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) && + deck->cards[i]->zone_position >= position) { + ++(deck->cards[i]->zone_position); + + deck->board_position[ (deck->cards[i]->zone_position - 1) ] = deck->cards[i]->id; + } + } +} + +void cards_reorder_hand_owner(struct deck_s *deck, u64 id) +{ + int i, pos = 0; + struct card_s *card; + + card = card_get(deck, NULL, id); + + pos = card->zone_position - 1; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && deck->cards[i]->id != id) { + if(deck->cards[i]->zone_position > card->zone_position) { + hm_log(LOG_DEBUG, lg, "Hand card position %d board card position %d", deck->cards[i]->zone_position, card->zone_position); + deck->cards[i]->zone_position--; + if(deck->cards[i]->zone_position > pos) { + pos = deck->cards[i]->zone_position; + } + } + } + } + + card->zone_position = 0; + + hm_log(LOG_DEBUG, lg, "Reordering zone positions %d", pos); + deck->handposition = pos; +} + +int cards_get_board_flag(struct deck_s *deck, int f, int exclude) +{ + int i; + int count = 0; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + flag(&deck->cards[i]->state, f, FLAG_ISSET) && + deck->cards[i]->id != exclude ) + { + count++; + } + } + + hm_log(LOG_DEBUG, lg, "Found %d entities of flag %d while excluded %d", count, f, exclude); + + return count; +} + +struct card_s *card_get_board_zoneposition(struct deck_s *deck, u64 position) +{ + int i; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + deck->cards[i]->zone_position == position) + { + + hm_log(LOG_DEBUG, lg, "Card zone positon %lld card [%s](%d) found", position, deck->cards[i]->entity->desc, deck->cards[i]->id); + return deck->cards[i]; + } + } + + return NULL; +} + +void card_discard_by_name(struct hs_holder_s *p, struct card_s *card, const char *name) +{ + int i; + + struct deck_s *deck; + + + hm_log(LOG_DEBUG, lg, "Discarding attacker's [%s](%d) associates: name %s", card->entity->desc, card->id, name); + + deck = card->controller == p->deck_copy->controller ? p->deck_copy : p->opponent.deck_copy; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + strcmp(name, deck->cards[i]->entity->name) == 0) { + + flag(&deck->cards[i]->state, CARD_DISCARD, FLAG_SET);\ + cards_reorder_hand_owner(deck, deck->cards[i]->id);\ + + } + } +} + +int board_count_by_name(struct deck_s *deck, const char *name) +{ + int i, count = 0; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + strcmp(name, deck->cards[i]->entity->name) == 0) { + count++; + } + } + + return count; +} + +struct card_list_s *cards_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f) +{ + int i; + struct card_list_s *list = NULL, *item; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, f, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + strcmp(name, deck->cards[i]->entity->name) == 0) { + LIST_ADD(list, item, deck->cards[i]); + } + } + + return list; +} + + +struct card_s *card_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f) +{ + int i; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, f, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + strcmp(name, deck->cards[i]->entity->name) == 0) { + return deck->cards[i]; + } + } + + return NULL; +} + + +struct card_list_s *cards_get_random(struct deck_s *deck, int number, struct card_s *attacker, int zone) +{ + int count = 0, r, r1, i, total; + struct card_list_s *list = NULL, *item, *i1; + struct card_list_s *output = NULL; + + hm_log(LOG_DEBUG, lg, "Getting %d random cards", number); + + for(i = 0; i < deck->ncards; i++) { + + + if( (zone == 1 && + ( + ( + flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) + ) || + flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) + ) + ) + + || + + (zone == 6 && + ( + flag(&deck->cards[i]->state, CARD_DECK, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) + ) + ) + ) { + LIST_ADD(list, item, deck->cards[i]); + count++; + } + } + + assert(count > 0); + + if(count <= number && !flag(&attacker->state, CARD_ARCANE_MISSILES, FLAG_ISSET)) { + return list; + } + + total = 0; + r1 = -1; + +again: + r = random_number(count); + + // arcane missiles can hit the same target multiple times + if(r1 == r && !flag(&attacker->state, CARD_ARCANE_MISSILES, FLAG_ISSET)) goto again; + + for(i = 0, item = list; item != NULL; item = item->next, i++) { + if(i == r) { + hm_log(LOG_DEBUG, lg, "Random card [%s](%d) added", item->card->entity->desc, item->card->id); + LIST_ADD(output, i1, item->card); + r1 = r; + if(number == ++total) break; + else goto again; + } + } + + // TODO: free list + + return output; +} + +struct card_s *cards_get_hand_random(struct deck_s *deck) +{ + int count = 0, r, i, count_all; + struct card_list_s *list = NULL, *item; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET)) { + LIST_ADD(list, item, deck->cards[i]); + + hm_log(LOG_DEBUG, lg, "\tGetting random inhand card %d", deck->cards[i]->id); + count++; + } + } + + hm_log(LOG_DEBUG, lg, "Getting random card from total count of %d", count); + + if(count == 0) { + return NULL; + } + + count_all = count; + r = random_number(count); + + count = 0; + for(item = list; item != NULL; item = item->next, count++) { + if(count == r) { + hm_log(LOG_DEBUG, lg, "Returning random card [%s](%d) from %d cards", item->card->entity->desc, item->card->id, count_all); + return item->card; + } + } + + return NULL; +} + +int card_deck_count(struct deck_s *deck) +{ + int count = 0, i; + + for(i = 0; i < deck->ncards; i++) { + assert(deck); + assert(deck->cards); + assert(deck->cards[i]); + if(flag(&deck->cards[i]->state, CARD_DECK, FLAG_ISSET) + ) { + count++; + } + } + + hm_log(LOG_DEBUG, lg, "Found %d cards in deck %d", count, deck->controller); + + return count; +} + +struct card_s *draw_first_boss(struct deck_s *deck) +{ + int i, r, count = 0; + + r = random_number(MAX_BOSS); + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_BOSS, FLAG_ISSET)) { + if((count++) == r) { + hm_log(LOG_DEBUG, lg, "Start Hand Random Boss %d", r); + flag(&deck->cards[i]->state, CARD_DECK, FLAG_UNSET); + flag(&deck->cards[i]->state, CARD_HAND, FLAG_SET); + deck->cards[i]->zone_position = ++deck->handposition; + deck->cards[i]->cost = 0; // first boss costs 0 + return deck->cards[i]; + } + } + } + + return NULL; +} + +struct card_s *draw_random_card(struct deck_s *deck, int entity_id, int zone_position) +{ + int r; + + if(card_deck_count(deck) == 0) { + return NULL; + } + +again: + + r = random_number(deck->ncards); + + // exclude drawn, board and mana card + if(!flag(&deck->cards[r]->state, CARD_DECK, FLAG_ISSET) || + deck->cards[r]->id == 68) { + goto again; + } + + flag(&deck->cards[r]->state, CARD_DECK, FLAG_UNSET); + flag(&deck->cards[r]->state, CARD_HAND, FLAG_SET); + + deck->cards[r]->zone_position = zone_position >= 1 ? zone_position : ++deck->handposition; + + hm_log(LOG_DEBUG, lg, "Drawn random card %d [%s], hand zone position %d player entity: %d", deck->cards[r]->id, deck->cards[r]->entity->desc, deck->handposition, entity_id); + return deck->cards[r]; +} + +struct card_s *new_card(const int id, const char *name, int controller) +{ + struct card_s *card; + int i; +#ifdef SPELL_ZERO_MANA + int cardtype = 0; +#endif + + card = malloc(sizeof(*card)); + memset(card, 0, sizeof(*card)); + + card->id = id; + card->entity = find_entity(name, strlen(name)); + assert(card->entity); + + for(i = 0; i < card->entity->nprop; i++) { + if(card->entity->p[i].key == HEALTH) { + card->health = card->total_health = card->default_health = card->entity->p[i].value; + } else if(card->entity->p[i].key == COST) { + card->cost = card->default_cost = card->entity->p[i].value; + } else if(card->entity->p[i].key == ATK) { + card->attack = card->default_attack = card->entity->p[i].value; + } else if(card->entity->p[i].key == CARDTYPE) { +#ifdef SPELL_ZERO_MANA + card->cardtype = card->entity->p[i].value; + cardtype = card->entity->p[i].value; +#endif + } else if(card->entity->p[i].key == DURABILITY) { + card->durability = card->maxdurability = card->entity->p[i].value; + } else if(card->entity->p[i].key == SPELLPOWER) { + card->spellpower = card->entity->p[i].value; + } + } + +#ifdef MANA_ZERO + card->cost = 0; +#endif + +#ifdef SPELL_ZERO_MANA + if(cardtype == 5) { + card->cost = 0; + } +#endif + + if(card->entity->attachment) { + card->attachment = card->entity->attachment; + } + + card->controller = controller; + + flags_copy(&card->state, &card->entity->flags); + + return card; +} + +void deck_add_attachment(struct deck_s *deck, const char *name, enum flags_e f) +{ + struct attachment_list_s *a; + + abort(); + + a = malloc(sizeof(*a)); + a->name = name; + a->group = f; + + a->next = deck->attachments; + deck->attachments = a; +} + +int card_count_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name) +{ + struct card_link_s *child; + struct card_s *child_card; + int count; + + for(count = 0, child = card->attached_children; child != NULL; child = child->next, count++); + + hm_log(LOG_DEBUG, lg, "Total attachments on card [%s](%d) is %d", card->entity->desc, card->id, count); + + for(count = 0, child = card->attached_children; child != NULL; child = child->next) { + child_card = card_get(deck, opponent, child->id); + + assert(child_card); + if(strcmp(child_card->entity->name, name) == 0) { + count++; + } else { + hm_log(LOG_DEBUG, lg, "Comparisson [%s] to [%s] failed", child_card->entity->name, name); + } + } + + hm_log(LOG_DEBUG, lg, "Total of %d attachments %s on card [%s](%d)", count, name, card->entity->name, card->id); + + return count; +} + +void card_remove_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name) +{ + struct card_link_s *child, *prev_child; + struct card_s *child_card; + + hm_log(LOG_DEBUG, lg, "Removing attachments on card [%s](%d)", card->entity->name, card->id); + + for(prev_child = NULL, child = card->attached_children; child != NULL; prev_child = child, child = child->next) { + child_card = card_get(deck, opponent, child->id); + + assert(child_card); + hm_log(LOG_DEBUG, lg, "\t\t - checking attachment [%s] [%s](%d)", name, child_card->entity->name, child_card->id); + if(name == NULL || strcmp(child_card->entity->name, name) == 0) { + if(prev_child == NULL) { + card->attached_children = child->next; + } else { + prev_child->next = child->next; + } + + flag(&(child_card->state), MECHANICS_DETACH, FLAG_SET); + flag(&(child_card->state), CARD_DESTROYED, FLAG_SET); + + hm_log(LOG_DEBUG, lg, "Removing attachment [%s](%d) for card [%s](%d)", child_card->entity->desc, child_card->id, card->entity->desc, card->id); + + flag(&(child_card->state), -1, FLAG_DUMP); + + free(child); + break; + } + } +} + +void deck_remove_attachment(struct deck_s *deck, struct deck_s *opponent, const char *name) +{ + struct attachment_list_s *a, *prev; + struct card_list_s *cards, *card; + + cards = cards_get_board(deck, NULL, -1, 0, -1, 1); + + hm_log(LOG_DEBUG, lg, "Starting attachments removal"); + + for(prev = NULL, a = deck->attachments; a != NULL; prev = a, a = a->next) { + if(strcmp(name, a->name) == 0) { + if(prev == NULL) { + deck->attachments = a->next; + } else { + prev->next = a->next; + } + + hm_log(LOG_DEBUG, lg, "Removing attachment [%s] from deck %p", a->name, deck); + free(a); + break; + } + } + + for(card = cards; card != NULL; card = card->next) { + card_remove_attachment(deck, opponent, card->card, name); + } +} + +void add_single_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, struct card_s *defender) +{ + if(attacker && attacker->attachment) { + // FIXME: deck might be opponent's too + struct card_s *att = add_new_card(p->game, deck, -1, attacker->attachment, -1); + att->attached_to = defender->id; + + add_child_link(defender, att->id, att->entity->name); + + hm_log(LOG_DEBUG, lg, "Adding attachment [%s](%d) to card [%s]%d", att->entity->desc, att->id, defender->entity->desc, defender->id); + } else { + hm_log(LOG_ALERT, lg, "Attacker [%s](%d) has no attachment", attacker->entity->desc, attacker->id); + abort(); + } +} + +void card_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst, const char *attachment) +{ + struct card_s *card; + + card = add_new_card(p->game, deck, -1, attachment, -1); + card->attached_to = dst->id; + + add_child_link(dst, card->id, card->entity->name); + + hm_log(LOG_DEBUG, lg, "Adding attachment [%s](%d) to card [%s]%d", card->entity->desc, card->id, dst->entity->desc, dst->id); +} + +void card_apply_attachments(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst) +{ + struct attachment_list_s *c; + + assert(deck); + assert(dst); + + // applying current attachments to card + for(c = deck->attachments; c != NULL; c = c->next) { + //cards_dump_board(deck); + abort(); + if(c->group > 0 && !flag(&dst->state, c->group, FLAG_ISSET)) { + continue; + } + + card_apply_attachment(p, deck, dst, c->name); + } +} + +void cards_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, enum flags_e f) +{ + struct card_list_s *c, *cards; + struct card_s *att; + + cards = cards_get_board(deck, NULL, -1, attacker->id, -1, 1); + + for(c = cards; c != NULL; c = c->next) { + if(f > 0 && !flag(&c->card->state, f, FLAG_ISSET)) { + continue; + } + + att = add_new_card(p->game, deck, -1, attacker->attachment, -1); + att->attached_to = c->card->id; + + add_child_link(c->card, att->id, att->entity->name); + + hm_log(LOG_DEBUG, lg, "Adding attachment [%s](%d) to card [%s]%d", att->entity->desc, att->id, c->card->entity->desc, c->card->id); + } +} + +void card_destroy(struct card_s *card, struct deck_s *deck, int to_hand) +{ + struct hs_holder_s *p = deck->parent; + struct conn_client_s *c = p->client; + + if(flag(&card->state, CARD_BOARD, FLAG_ISSET)) { + flag(&card->state, CARD_BOARD, FLAG_UNSET); + } + + if(flag(&card->state, CARD_SPELLPOWER, FLAG_ISSET)) { + //deck->spellpower -= card->spellpower; + deck->spellpower--; + } + + if(!to_hand) { + flag(&card->state, CARD_DESTROYED, FLAG_SET); + } + + cards_board_destroyed_reorder(deck, card->zone_position); + + { + struct card_s *__fake_defender = card; + __SECTION_DESTROYED + } +} + +void card_dump(struct card_s *card) +{ + hm_log(LOG_DEBUG, lg, "Dumping card %d:\ + \n\tParent: %p\n\ + \tController: %d\n\ + \tID: %d\n\ + \tHealth: %d\n", card->id, card->parent, card->controller, card->id, card->health);\ +} + diff --git a/hm_gameserver/src/game/deck.c b/hm_gameserver/src/game/deck.c new file mode 100644 index 0000000..3c0575f --- /dev/null +++ b/hm_gameserver/src/game/deck.c @@ -0,0 +1,441 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +#define TEST_DECK_MAX 2 +const char *test_deck[TEST_DECK_MAX] = { "EX1_581", "EX1_306" }; + +struct card_s *add_new_card(struct game_s *game, struct deck_s *deck, int index, const char *card, enum flags_e flags) +{ + int n; + struct card_s *c; + + n = ++(deck->ncards); + + deck->cards = realloc(deck->cards, sizeof(void *) * deck->ncards); + + game->maxentity_id++; + + if(index == -1) { + c = new_card(game->maxentity_id, card, deck->controller); + } else { + c = new_card(index, card, deck->controller); + } + + if(flags != -1) { + //c->state |= flags; + flag(&c->state, flags, FLAG_SET); + } + + assert(deck); + assert(deck->parent); + c->parent = deck->parent; + + deck->cards[n - 1] = c; + + hm_log(LOG_DEBUG, lg, "Added new card to deck: %p controller: %d card: %d properties: %d total cards: %d game maxentity_id: %d", deck, deck->controller, c->id, c->entity->nprop, deck->ncards, game->maxentity_id); + + return c; +} + +static struct deck_s *create_deck(struct conn_client_s *c, const int controller, int *counter) +{ + struct deck_s *deck; + int i, j; + struct hs_holder_s *p; + struct game_s *game; + + p = c->data; + game = p->game; + + deck = malloc(sizeof(*deck)); + if(deck == NULL) { + return NULL; + } + memset(deck, 0, sizeof(*deck)); + + deck->controller = controller; + assert(p); + deck->parent = p; + +#ifdef TEST_DECK +#define DEFAULT_DECK_MAX 30 + + int id; + + deck->ncards = DEFAULT_DECK_MAX; + + deck->cards = malloc(sizeof(void *) * deck->ncards); + + for(j = 0, i = 0, j = 0; i < deck->ncards; i++, j++ ) { + if(controller == 1) { + id = i + 4; + } else { + id = i + 4 + DEFAULT_DECK_MAX; + } + + if(j == TEST_DECK_MAX) j = 0; + + //j = (controller == 1 ? 0 : 1); + deck->cards[i] = new_card(id, test_deck[j], controller); + assert(deck); + deck->cards[i]->parent = deck->parent; + + //deck->cards[i]->state |= CARD_DECK; + flag(&deck->cards[i]->state, CARD_DECK, FLAG_SET); + game->maxentity_id++; + } +#else + struct player_deck_s *pdc; + + deck->ncards = c->ncards; + + deck->cards = malloc(sizeof(void *) * deck->ncards); + + for(j = 0, pdc = c->cards; pdc != NULL; pdc = pdc->next) { + for(i = 0; i < pdc->count; i++) { + deck->cards[j] = new_card((*counter)++, pdc->code, controller); + deck->cards[j]->parent = deck->parent; + + flag(&deck->cards[j]->state, CARD_DECK, FLAG_SET); + + hm_log(LOG_DEBUG, lg, "Added card (%d)[%s]", deck->cards[j]->id, deck->cards[j]->entity->desc); + + game->maxentity_id++; + j++; + } + } + + assert(j == deck->ncards); +#endif + + hm_log(LOG_DEBUG, lg, "Created deck: %p controller: %d ncards: %d", deck, controller, deck->ncards); + + return deck; +} + +void prepare_decks(struct conn_client_s *c) +{ + struct hs_holder_s *p1; + struct deck_s *p2_deck; + int i; + + p1 = c->data; + + assert(p1); + + if(p1->opponent.accessible == 1) { + p2_deck = p1->opponent.deck; + } + + assert(p2_deck); + + if(EQFLAG(p1->deck->flags, DECK_INIT)) { + return; + } + + p1->deck->flags |= DECK_INIT; + p2_deck->flags |= DECK_INIT; + + + // randomly select 4 cards for p1 - 2nd turn + // randomly select 3 cards for p2 - 1st turn + + // put one random boss + draw_first_boss(p1->deck); + + for(i = 0; i < 3; i++) { + draw_random_card(p1->deck, p1->entity_id, -1); + } + + for(i = 0; i < p1->deck->ncards; i++) { + if(p1->deck->cards[i]->entity->nname == strlen("GAME_005") && + memcmp(p1->deck->cards[i]->entity->name, "GAME_005", strlen("GAME_005")) == 0) { + flag(&p1->deck->cards[i]->state, CARD_HAND, FLAG_SET); + + p1->deck->cards[i]->zone_position = ++p1->deck->handposition; + } + } + + hm_log(LOG_DEBUG, lg, "P1 deck default zone position: %d", p1->deck->handposition); + + // put one random boss + draw_first_boss(p2_deck); + + for(i = 0; i < 2; i++) { + draw_random_card(p2_deck, 3, -1); + } + + hm_log(LOG_DEBUG, lg, "P2 deck default zone position: %d", p2_deck->handposition); +} + +void holder_free(struct hs_holder_s *h) +{ + deck_free(h->deck, (FREE_DECK_ATTACHMENT | FREE_CARD_CHILDREN | FREE_CARD_EXPIRE)); + deck_free(h->deck_copy, (FREE_DECK_ATTACHMENT | FREE_CARD_CHILDREN | FREE_CARD_EXPIRE)); + + free(h); +} + +int append_decks(struct conn_client_s *p1, struct conn_client_s *p2) +{ + struct hs_holder_s *p1_holder, *p2_holder; + struct game_s *g; + + p1_holder = malloc(sizeof(*p1)); + p2_holder = malloc(sizeof(*p2)); + + memset(p1_holder, 0, sizeof(*p1_holder)); + memset(p2_holder, 0, sizeof(*p2_holder)); + + p1->data = p1_holder; + p2->data = p2_holder; + + p1_holder->client = p1; + p2_holder->client = p2; + + g = malloc(sizeof(*g)); + + memset(g, 0, sizeof(*g)); + + g->entity_id = 1; + g->flags = 0; + g->turn = 1; + g->maxentity_id = 3; ///< start with offset 4, as 1 - game entity, 2/3 - players + + p1_holder->game = p2_holder->game = g; + + assert(p1_holder->game && p2_holder->game); + + int counter = 4; + p1_holder->deck = create_deck(p1, 1, &counter); + p2_holder->deck = create_deck(p2, 2, &counter); + + p1_holder->opponent.accessible = 1; + p2_holder->opponent.accessible = 1; + + p1_holder->opponent.deck = p2_holder->deck; + p2_holder->opponent.deck = p1_holder->deck; + + p1_holder->deck->bnet_hi = 0x4ab3967; + p2_holder->deck->bnet_hi = 0x49E8Eb5; + + p1_holder->id = 1; + p2_holder->id = 2; + + p1_holder->entity_id = 2; + p2_holder->entity_id = 3; + + p1_holder->opponent.client = p2; + p2_holder->opponent.client = p1; + + p1_holder->deck->mana = p2_holder->deck->mana = 1; + + p1_holder->deck->hero = add_new_card(p1_holder->game, p1_holder->deck, -1, "TB_SPT_Boss" /*p1->hero*/, -1); + p1_holder->deck->heropower = add_new_card(p1_holder->game, p1_holder->deck, -1, p1->hp, -1); + + p2_holder->deck->hero = add_new_card(p1_holder->game, p2_holder->deck, -1, "LOEA04_01"/*p2->hero*/, -1); + p2_holder->deck->heropower = add_new_card(p1_holder->game, p2_holder->deck, -1, p2->hp, -1); + + (void)add_new_card(p1_holder->game, p1_holder->deck, -1, "GAME_005", CARD_HAND); + + prepare_decks(p1); + + return 0; +} + +void game_free(struct game_s *g) +{ + ev_timer_stop(loop, &g->turntimer); + ev_timer_stop(loop, &g->force_next_turn); + free(g); +} + +void copy_card(struct card_s **dst, struct card_s *src) +{ + if(src == NULL) { + *dst = NULL; + return; + } + + *dst = malloc(sizeof(**dst)); + memset(*dst, 0, sizeof(**dst)); + +#define cpyc(m_ele)\ + (*dst)->m_ele = src->m_ele; + + cpyc(parent); + cpyc(id); + cpyc(controller); + memcpy(&(*dst)->state, &src->state, sizeof(src->state)); + + cpyc(attachment); + cpyc(attached_to); + cpyc(attached_children); + + cpyc(entity); + cpyc(zone_position); + + cpyc(total_health); + cpyc(health); + cpyc(default_health); + cpyc(buff_health); + + cpyc(attack); + cpyc(default_attack); + + cpyc(cost); + cpyc(default_cost); + + cpyc(cardtype); + cpyc(durability); + cpyc(maxdurability); + cpyc(armor); + cpyc(actions_number); + cpyc(spellpower); + + // do not copy 'target' and 'receive' + + memcpy(&(*dst)->boss, &src->boss, sizeof(src->boss)); + + cpyc(linked); + cpyc(expire); + cpyc(total_plays); + cpyc(turn_plays); +} + +void deck_free(struct deck_s *deck, unsigned int flags) +{ + int i; + struct attachment_list_s *a, *del; + + if(deck == NULL) { + return; + } + + if(EQFLAG(flags, FREE_DECK_ATTACHMENT)) { + for(a = deck->attachments; a != NULL; ) { + del = a; + a = a->next; + free(del); + } + } + + for(i = 0; i < deck->ncards; i++) { + card_free(deck->cards[i], flags); + } + + free(deck); +} + +struct deck_s *copy_deck(struct deck_s *src) +{ + struct deck_s *dst; + int i; + + dst = malloc(sizeof(*dst)); + + dst->hero = dst->heropower = dst->heroweapon = NULL; +#define cpy(m_ele)\ + dst->m_ele = src->m_ele; + + assert(src->parent); + cpy(parent); + cpy(bnet_hi); + cpy(controller); + cpy(mana); + cpy(mana_used); + cpy(spellpower); + cpy(handposition); + cpy(ncards); + + memcpy(&dst->modifiers, &src->modifiers, sizeof(src->modifiers)); + + dst->cards = malloc(sizeof(void *) * dst->ncards); + for(i = 0; i < dst->ncards; i++) { + + copy_card(&dst->cards[i], src->cards[i]); + + if(flag(&dst->cards[i]->state, CARD_HERO, FLAG_ISSET)) { + dst->hero = dst->cards[i]; + } else if(flag(&dst->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) { + dst->heropower = dst->cards[i]; + } else if(flag(&dst->cards[i]->state, CARD_HEROWEAPON, FLAG_ISSET)) { + dst->heroweapon = dst->cards[i]; + } + } + + memcpy(&dst->board_position, &src->board_position, sizeof(src->board_position)); + cpy(attachments); + + cpy(fatigue); + cpy(gameover); + cpy(flags); + + return dst; +} + +void decks_copy(struct hs_holder_s *p) +{ + struct hs_holder_s *opponent; + + opponent = p->opponent.client->data; + + assert(p->deck_copy == NULL); + assert(p->opponent.deck_copy == NULL); + assert(opponent->deck_copy == NULL); + assert(opponent->opponent.deck_copy == NULL); + + ///< make copies of our and opponent's deck + p->deck_copy = copy_deck(p->deck); + opponent->opponent.deck_copy = p->deck_copy; + + p->opponent.deck_copy = copy_deck(p->opponent.deck); + opponent->deck_copy = p->opponent.deck_copy; + + hm_log(LOG_DEBUG, lg, "Deck old %p new %p Opponeng old %p new %p", p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy); + +} + +void decks_swap(struct hs_holder_s *p) +{ + struct hs_holder_s *o; + + o = p->opponent.client->data; + + hm_log(LOG_DEBUG, lg, "Freeing decks %p %p", p->deck, p->opponent.deck); + hm_log(LOG_DEBUG, lg, "Decks copies to swap %p %p", p->deck_copy, p->opponent.deck_copy); + + // free old decks + deck_free(p->deck, 0); + deck_free(p->opponent.deck, 0); + o->deck = NULL; + o->opponent.deck = NULL; + + // swap current player + p->deck = p->deck_copy; + p->opponent.deck = p->opponent.deck_copy; + p->deck_copy = NULL; + p->opponent.deck_copy = NULL; + + // swap opponent + o->deck = p->opponent.deck; + o->opponent.deck = p->deck; + o->deck_copy = NULL; + o->opponent.deck_copy = NULL; +} diff --git a/hm_gameserver/src/game/interface/next_turn.c b/hm_gameserver/src/game/interface/next_turn.c new file mode 100644 index 0000000..beb6ac2 --- /dev/null +++ b/hm_gameserver/src/game/interface/next_turn.c @@ -0,0 +1,63 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void next_turn(struct conn_client_s *c, struct hs_holder_s *p/*, struct chooseoption_s *opt*/) +{ + struct packet_s *p1; + struct packet_s *p2; + struct card_s *drawn_card = NULL; + int zone = 0; + + decks_copy(p); + + // refresh resources + update_resources(p->opponent.deck_copy, NULL, 1); + + mechanics_next_turn(c, p); + + hm_log(LOG_INFO, c->log, "Next turn: %d", p->game->turn); + p1 = net_next_turn(c, &drawn_card, &zone); + p2 = net_next_turn(c, &drawn_card, &zone); + + decks_swap(p); + + net_send(c, p1); + + net_send(p->opponent.client, p2); + net_send_options(p->opponent.client, p->opponent.deck, p->deck, p->game->turn); + + packet_free(p1); + packet_free(p2); + + /* + + ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + hm_send(c, output, n); + + ptr = output; + n = serialize(p2, &ptr, ptr + sizeof(output)); + + int so = set_options(p->opponent.deck, p->deck, output + n, output + sizeof(output) - n, p->game->turn); + + //memcpy(output + n + so, opt1, sizeof(opt1)); + + hm_send(p->opponent.client, output, n + so); + */ +} diff --git a/hm_gameserver/src/game/interface/power.c b/hm_gameserver/src/game/interface/power.c new file mode 100644 index 0000000..f600143 --- /dev/null +++ b/hm_gameserver/src/game/interface/power.c @@ -0,0 +1,262 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void power_attack(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt) +{ + struct card_s *attacker = NULL, *defender; + struct deck_s *deck, *opponent; + struct packet_s *p1 = NULL, *p2 = NULL, *extra = NULL; + struct card_list_s *defenders = NULL, *clitem, *def; + + decks_copy(p); + + deck = p->deck_copy; + opponent = p->opponent.deck_copy; + + attacker = card_get(deck, NULL, p->arroworigin); + if(!attacker) attacker = card_get(deck, NULL, p->held_card); + + assert(attacker); + + if(flag(&attacker->state, CARD_HAND, FLAG_ISSET)) { + flag(&attacker->state, CARD_HAND, FLAG_UNSET); + } + + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) { + // update resources + update_resources(deck, attacker, 0); + + // put spell on board + if(!flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) { + flag(&attacker->state, CARD_BOARD, FLAG_SET); + } + } + + defender = card_get(deck, opponent, opt->target); + + // there can only be none or one defender here + if(defender) { + LIST_ADD(defenders, clitem, defender); + } + + hm_log(LOG_ERR, c->log, "Power attack: origin: %d target: %lld held: %d attacker: [%s](%d) defenders: %p", p->arroworigin, opt->target, p->held_card, attacker->entity->desc, attacker->id, defenders); + + if(/*p->held_card > 0 && */flag(&attacker->state, CARD_AOE, FLAG_ISSET)) { + + hm_log(LOG_INFO, c->log, "Attacker AOE [%s](%d)", attacker->entity->desc, attacker->id); + /* + ///< get opponent's board cards + if(flag(&attacker_aoe->state, CARD_AOE_ENEMY_MINIONS, FLAG_ISSET)) { + defenders = cards_get_board(NULL, p->opponent.deck_copy, 0, -1); + } else if(flag(&attacker_aoe->state, CARD_AOE_ALLENEMY, FLAG_ISSET)) { + defenders = cards_get_board(NULL, p->opponent.deck_copy, 1, -1); + } else if(flag(&attacker_aoe->state, CARD_AOE_TARGET_ALL, FLAG_ISSET)) { + defenders = cards_get_board(p->deck_copy, p->opponent.deck_copy, 1, -1); + } else if(flag(&attacker_aoe->state, CARD_AOE_MINIONS, FLAG_ISSET)) { + defenders = cards_get_board(p->deck_copy, p->opponent.deck_copy, 0, -1); + } else if(flag(&attacker_aoe->state, CARD_AOE_CLEAVE, FLAG_ISSET) || flag(&attacker_aoe->state, CARD_AOE_MULTISHOT, FLAG_ISSET)) { + defenders = cards_get_random(p->opponent.deck_copy, 2, attacker, 1); + } else if(flag(&attacker_aoe->state, CARD_TRACKING, FLAG_ISSET)) { + defenders = cards_get_random(p->deck_copy, 3, attacker_aoe, 6); + flag(&attacker_aoe->state, MECHANICS_SELECTED, FLAG_SET); + + } else if(flag(&attacker_aoe->state, CARD_ARCANE_MISSILES, FLAG_ISSET)) { + int tsp = attacker_aoe->attack + p->deck_copy->spellpower; + defenders = cards_get_random(p->opponent.deck_copy, tsp, attacker_aoe, 1); + + } else if(flag(&attacker_aoe->state, CARD_SINISTER_STRIKE, FLAG_ISSET) || + flag(&attacker_aoe->state, CARD_MIND_BLAST, FLAG_ISSET)) { + LIST_ADD(defenders, clitem, opponent->hero); + } + + hm_log(LOG_INFO, c->log, "Casting AOE card [%s](%d) against:", attacker_aoe->entity->desc, attacker_aoe->id); + for(def = defenders; def != NULL; def = def->next) { + hm_log(LOG_INFO, c->log, "\t[%s](%d)", def->card->entity->desc, def->card->id); + } + + mechanics_attack_aoe(c, opt->position, attacker_aoe, &defenders); + */ + { + struct card_s *__fake_levelup = NULL; + __SECTION_SPELL_AOE + } + + { + struct card_s *__fake_defender = attacker; + __SECTION_DESTROYED + } + + p1 = net_spell_aoe(c, opt, deck->controller, attacker); + p2 = net_spell_aoe(c, opt, opponent->controller, attacker); + + if(flag(&attacker->state, CARD_TRACKING, FLAG_ISSET)) { + struct entitychoices_s *ec; + ec = chooseone_choices(defenders, p->id, attacker->id); + add_packet(&extra, ec, P_ENTITYCHOICES); + + entitychoices_dump(ec); + + // set client to choose one + p->choose_one = 1; + } + + + } else if( + attacker && flag(&attacker->state, CARD_BUFF, FLAG_ISSET) && flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) { + + /* + if(flag(&attacker->state, CARD_BLOODLUST, FLAG_ISSET)) { + defenders = cards_get_board(p->deck_copy, NULL, 0, attacker->id); + } else if(flag(&attacker->state, CARD_VANISH, FLAG_ISSET)) { + defenders = cards_get_board(p->deck_copy, p->opponent.deck_copy, 0, attacker->id); + } else if(flag(&attacker->state, CARD_SAVAGE_ROAR, FLAG_ISSET)) { + defenders = cards_get_board(p->deck_copy, NULL, 1, attacker->id); + } else if(flag(&attacker->state, CARD_CLAW, FLAG_ISSET) || + flag(&attacker->state, CARD_HEROIC_STRIKE, FLAG_ISSET)) { + LIST_ADD(defenders, clitem, deck->hero); + } else if(flag(&attacker->state, CARD_MIND_VISION, FLAG_ISSET)) { + defenders = NULL; + } else { + LIST_ADD(defenders, clitem, defender); + } + */ + + hm_log(LOG_INFO, c->log, "Buff [%s)(%d)", attacker->entity->desc, attacker->id); + + mechanics_buff(c, opt, attacker, &defenders); + + for(def = defenders; def != NULL; def = def->next) { + hm_log(LOG_INFO, c->log, "Buffing [%s)(%d) > [%s](%d)", attacker->entity->desc, attacker->id, def->card->entity->desc, def->card->id); + } + + p1 = net_buff(c, opt, deck->controller, attacker, defenders); + p2 = net_buff(c, opt, opponent->controller, attacker, defenders); + + /* + } else if(attacker && flag(&attacker->state, CARD_BATTLECRY_TARGET, FLAG_ISSET) && ( + (attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_HEAL2_TARGET, FLAG_ISSET)) || + (attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_DAMAGE1_TARGET, FLAG_ISSET)) || + (attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_DAMAGE2_TARGET, FLAG_ISSET)) || + (attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_DAMAGE3_TARGET, FLAG_ISSET))) + ) { + + flag(&attacker->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_SET); + + LIST_ADD(defenders, clitem, defender); + + hm_log(LOG_INFO, c->log, "Battlecry target %d > %lld, total plays %d", p->arroworigin, opt->target, attacker->total_plays); + mechanics_attack(c, opt, attacker, defenders); + + p1 = net_spell(c, opt, 1, attacker, defenders); + */ + } else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_HP_SPELL_DAMAGE, FLAG_ISSET)) { + + //LIST_ADD(defenders, clitem, defender); + + //mechanics_attack(c, opt, attacker, defenders); + hm_log(LOG_INFO, c->log, "Casting HP spell %d > %lld", p->arroworigin, opt->target); + p1 = net_spell_hp_damage(c, defenders, attacker); + + } else if(flag(&attacker->state, (CARD_SPELL), FLAG_ISSET)) { + + hm_log(LOG_INFO, c->log, "Casting spell %d > %lld", p->arroworigin, opt->target); + + assert(attacker); + + /* + LIST_ADD(defenders, clitem, defender); + + if(flag(&attacker->state, CARD_SWIPE, FLAG_ISSET)) { + mechanics_attack_swipe(c, opt->position, attacker, &defenders); + } else { + mechanics_attack(c, opt, attacker, defenders); + } + +*/ + + struct card_s *__fake_levelup = NULL; + __SECTION_SPELL + + { + struct card_s *__fake_defender = attacker; + __SECTION_DESTROYED + } + + p1 = net_spell(c, opt, deck->controller, attacker, defenders, __fake_levelup); + if(!flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) { + p2 = net_spell(c, opt, opponent->controller, attacker, defenders, __fake_levelup); + } + } else { + hm_log(LOG_INFO, c->log, "Attacking %d > %lld", p->arroworigin, opt->target); + + struct card_s *__fake_levelup = NULL; + __SECTION_ATTACK + + p1 = net_attack(c, opt, attacker, defender, deck->controller); + p2 = net_attack(c, opt, attacker, defender, opponent->controller); + } + + decks_swap(p); + + net_send(c, p1); + + if(p2) { + net_send(p->opponent.client, p2); + } else { + net_send(p->opponent.client, p1); + } + + if(extra) { + net_send(c, extra); + //net_send(p->opponent.client, extra); + } else { + net_send_options(c, p->deck, p->opponent.deck, p->game->turn); + } + + packet_free(p1); + if(p2) packet_free(p2); + if(extra) packet_free(extra); + + /* + if(p->em) + em_fire(p); + if(player2->em) + em_fire(player2); + */ + + + /* + ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + + hm_log(LOG_INFO, c->log, "Serialized %d bytes", n); + hm_send(c, output, n); + + if(p2) { + ptr = output; + n = serialize(p2, &ptr, ptr + sizeof(output)); + } + + hm_send(p->opponent.client, output, n); + + + int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn); + hm_send(c, output, so); + */ +} diff --git a/hm_gameserver/src/game/interface/put_card_onboard.c b/hm_gameserver/src/game/interface/put_card_onboard.c new file mode 100644 index 0000000..10b74f1 --- /dev/null +++ b/hm_gameserver/src/game/interface/put_card_onboard.c @@ -0,0 +1,69 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void put_card_onboard(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt) +{ + struct packet_s *p1; + struct packet_s *p2; + struct card_s *attacker; + + decks_copy(p); + + ///< get attacker from copied deck + attacker = card_get(p->deck_copy, NULL, p->held_card); + assert(attacker); + + update_resources(p->deck_copy, attacker, 0); + + hm_log(LOG_INFO, lg, "Putting card %d on board", attacker->id); + + mechanics_put_card_onboard(c, opt->position, attacker, 0, NULL, opt, p->deck_copy); + + p1 = net_card_onboard(p, opt, attacker, p->deck_copy->controller); + p2 = net_card_onboard(p, opt, attacker, p->opponent.deck_copy->controller); + + decks_swap(p); + + net_send(c, p1); + net_send_options(c, p->deck, p->opponent.deck, p->game->turn); + + net_send(p->opponent.client, p2); + + packet_free(p1); + packet_free(p2); + + /* + int n; + char output[8192]; + char *ptr = output; + n = serialize(p1, &ptr, ptr + sizeof(output)); + + int so = set_options(p->deck, p->opponent.deck, output + n, output + sizeof(output) - n, p->game->turn); + + //hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator", n + so); + hm_send(c, output, (int)(n + so)); + + char output2[2048]; + ptr = output2; + int n2 = serialize(p2, &ptr, ptr + sizeof(output2)); + + //hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator's opponent", n); + hm_send(p->opponent.client, output2, n2); + */ +} diff --git a/hm_gameserver/src/game/interface/user_choice.c b/hm_gameserver/src/game/interface/user_choice.c new file mode 100644 index 0000000..e4d6730 --- /dev/null +++ b/hm_gameserver/src/game/interface/user_choice.c @@ -0,0 +1,74 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int game(struct conn_client_s *c, struct chooseoption_s *opt) +{ + struct hs_holder_s *p; + struct card_s *attacker = NULL; + + p = c->data; + + if(p->held_card > 0) { + attacker = card_get(p->deck, NULL, p->held_card); + } + + if(opt->index == 0) { + next_turn(c, p); + } else if( + (!(attacker && flag(&attacker->state, CARD_BATTLECRY, FLAG_ISSET))) && + (!(attacker && flag(&attacker->state, CARD_WEAPON, FLAG_ISSET))) && + ( + (opt->target != 0 && p->arroworigin != 0) || + (p->held_card > 0 && flag(&attacker->state, CARD_SPELL, FLAG_ISSET))) + + /* + (p->held_card > 0 && flag(&attacker->state, CARD_BUFF_AOE, FLAG_ISSET)) || + (p->held_card > 0 && flag(&attacker->state, CARD_VANISH, FLAG_ISSET)) || + (p->held_card > 0 && flag(&attacker->state, CARD_SUMMON, FLAG_ISSET)) || + (p->held_card > 0 && flag(&attacker->state, CARD_DRAW_CARD, FLAG_ISSET)) || + (p->held_card > 0 && flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) + */ + ) { + + // attack or spell damage + hm_log(LOG_INFO, c->log, "Power attack held: %d, attacker: %p, target: %lld, arroworigin: %d", p->held_card, attacker, opt->target, p->arroworigin); + power_attack(c, p, opt); + } else if(p->held_card > 0) { + // put card on board + put_card_onboard(c, p, opt); + } + + //skip: + + // unset origin + p->arroworigin = 0; + + // unset + p->held_card = 0; + + cards_dump(p->deck, p->opponent.deck); + + unset_mechanics_flags(p); + + hm_log(LOG_INFO, c->log, "Unsetting held card %d arroworigin %d", p->held_card, p->arroworigin); + + return 0; + + +} diff --git a/hm_gameserver/src/game/mechanics/attack_aoe.c b/hm_gameserver/src/game/mechanics/attack_aoe.c new file mode 100644 index 0000000..0d40595 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/attack_aoe.c @@ -0,0 +1,52 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mechanics_attack_aoe(struct conn_client_s *c, u64 position, struct card_s *attacker, struct card_list_s **defenders, struct card_s **fake_levelup) +{ + struct hs_holder_s *p; + struct deck_s *deck; + struct card_list_s *item; + + p = c->data; + deck = p->deck_copy; + + assert(deck); + + hm_log(LOG_DEBUG, c->log, "Attack %d > defenders", attacker->id); + + if(!flag(&attacker->state, CARD_TRACKING, FLAG_ISSET)) { + game_attack_aoe(p, attacker, *defenders, fake_levelup); + } else { + if(defenders) attacker->target.card = *defenders; + } + + if(flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) { + flag(&attacker->state, MECHANICS_HEROPOWER, FLAG_SET); + flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET); + hm_log(LOG_DEBUG, c->log, "Card [%s](%d) heropower triggered", attacker->entity->desc, attacker->id); + } else { + hm_log(LOG_DEBUG, c->log, "Card [%s](%d) heropower not triggered", attacker->entity->desc, attacker->id); + } + + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && !flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) { + flag(&attacker->state, CARD_DESTROYED, FLAG_SET); + cards_reorder(p, deck, attacker, position, 0); + } +} + diff --git a/hm_gameserver/src/game/mechanics/buff.c b/hm_gameserver/src/game/mechanics/buff.c new file mode 100644 index 0000000..c73bef4 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/buff.c @@ -0,0 +1,53 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mechanics_buff(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **d) +{ + struct hs_holder_s *p; + struct deck_s *deck; + struct card_list_s *def; + + p = c->data; + deck = p->deck_copy; +#define defender ((*d != NULL) ? (*d)->card : NULL) +#define defenders (*d) + + if(defender) { + hm_log(LOG_DEBUG, c->log, "Buff [%s](%d) to [%s](%d)", attacker->entity->desc, attacker->id, defender->entity->desc, defender->id); + } + + // set destroyed if spell + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) { + + { + struct card_s *__fake_defender = attacker; + __SECTION_DESTROYED + } + + flag(&attacker->state, CARD_DESTROYED, FLAG_SET); + cards_reorder(p, deck, attacker, opt->position, 0); + } + + __SECTION_BUFF + + // set exhausted if minion + if(flag(&attacker->state, CARD_MINION, FLAG_ISSET)) { + flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET); + } +} diff --git a/hm_gameserver/src/game/mechanics/draw_card.c b/hm_gameserver/src/game/mechanics/draw_card.c new file mode 100644 index 0000000..3347c83 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/draw_card.c @@ -0,0 +1,48 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mechanics_draw_card(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, int cards, struct card_list_s **defenders) +{ + struct hs_holder_s *p; + struct deck_s *deck; + int i; + struct card_s *card; + struct card_list_s *clitem; + + p = c->data; + deck = p->deck_copy; + + assert(deck); + + hm_log(LOG_DEBUG, c->log, "%s Drawing %d cards:", LOG_MECHANICS, cards); + for(i = 0; i < cards; i++) { + card = draw_random_card(deck, p->entity_id, -1); + flag(&card->state, CARD_HAND, FLAG_SET); + + LIST_ADD(*defenders, clitem, card); + + hm_log(LOG_DEBUG, c->log, "%s Drawing card %d from deck %d", LOG_MECHANICS, card->id, card->parent->deck_copy->controller); + } + + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && !flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) { + flag(&attacker->state, CARD_DESTROYED, FLAG_SET); + cards_reorder(p, deck, attacker, opt->position, 0); + } +} + diff --git a/hm_gameserver/src/game/mechanics/entity/aoe.c b/hm_gameserver/src/game/mechanics/entity/aoe.c new file mode 100644 index 0000000..5c1985f --- /dev/null +++ b/hm_gameserver/src/game/mechanics/entity/aoe.c @@ -0,0 +1,139 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +#ifdef TEST_DECK +#define LEVEL3_EXP 2 +#define LEVEL2_EXP 1 +#else +//#define LEVEL3_EXP 10 +//#define LEVEL2_EXP 5 +#define LEVEL3_EXP 2 +#define LEVEL2_EXP 1 +#endif + +#define LEVEL2 2 +#define LEVEL3 3 + +static void level_up(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst, struct card_s *target) +{ + assert(dst && target); + + dst->boss.experience += target->cost; + + if(dst->boss.experience >= LEVEL3_EXP && dst->boss.level < LEVEL3) { + + card_remove_attachment(deck, NULL, dst, LEVEL_1); + card_remove_attachment(deck, NULL, dst, LEVEL_2); + card_apply_attachment(p, deck, dst, LEVEL_3); + + if(dst->entity->level3) { + hsl_add_new_card_hand(deck, dst->entity->level3, holder); + } + + // when we bypass level 2 + if(dst->boss.level == 0 && dst->entity->level2) { + hsl_add_new_card_hand(deck, dst->entity->level2, holder); + } + + dst->boss.level = LEVEL3; + + hm_log(LOG_DEBUG, lg, "Boss [%s](%d) reached level 3", dst->entity->desc, dst->id); + } else if(dst->boss.experience >= LEVEL2_EXP && dst->boss.level < LEVEL2) { + + dst->boss.level = LEVEL2; + + card_remove_attachment(deck, NULL, dst, LEVEL_1); + card_apply_attachment(p, deck, dst, LEVEL_2); + + if(dst->entity->level2) { + hsl_add_new_card_hand(deck, dst->entity->level2, holder); + } + + hm_log(LOG_DEBUG, lg, "Boss [%s](%d) reached level 2", dst->entity->desc, dst->id); + } else { + hm_log(LOG_DEBUG, lg, "No leveling up for boss [%s](%d) exp %d", dst->entity->desc, dst->id, dst->boss.experience); + } +} + +int game_attack_aoe(struct hs_holder_s *p, struct card_s *attacker, struct card_list_s *defenders, struct card_s **fake_levelup) +{ + struct card_list_s *def; + +#define WEAPON_ATTACK(m_attacker, m_deck)\ + if(flag(&m_attacker->state, CARD_BOSS, FLAG_ISSET)) {\ + {\ + struct card_s *__fake_weapon = m_deck->heroweapon;\ + struct deck_s *__fake_deck = m_deck;\ + __SECTION_WEAPON_ATTACK\ + }\ + } + +#define ATTACHMENT_ATTACK(m_attacker, m_deck)\ + {\ + struct card_s *__fake_attacker = m_attacker;\ + struct deck_s *__fake_deck = m_deck;\ + \ + if(flag(&attacker->state, CARD_BOSS, FLAG_ISSET) ||\ + flag(&attacker->state, CARD_MINION, FLAG_ISSET)) {\ + \ + __SECTION_ATTACHMENT_ATTACK\ + \ + }\ + } + + for(def = defenders; def != NULL; def = def->next) { + entity_attack(p, attacker, def->card); + + ATTACHMENT_ATTACK(def->card, p->opponent.deck_copy); + + // add experience + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && + flag(&attacker->state, CARD_LEVELUP, FLAG_ISSET) && + flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET)) { + + // spell experience association + struct card_s *boss = card_get_levelup_boss(p->deck_copy, attacker); + if(boss) { + level_up(p, p->deck_copy, boss, def->card); + } else { + hm_log(LOG_DEBUG, lg, "CARD_LEVELUP specified for card %d but boss not found", attacker->id); + abort(); + } + } else if(flag(&attacker->state, CARD_BOSS, FLAG_ISSET) && + !flag(&attacker->state, CARD_DESTROYED, FLAG_ISSET) && + flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET)) { + + level_up(p, p->deck_copy, attacker, def->card); + + } else if(flag(&def->card->state, CARD_BOSS, FLAG_ISSET) && + !flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET) && + flag(&attacker->state, CARD_DESTROYED, FLAG_ISSET)) { + + level_up(p, p->opponent.deck_copy, def->card, attacker); + + } else { + hm_log(LOG_DEBUG, lg, "No boss involved or destroyed: Attacker [%s](%d) > Defender [%s](%d) %d %d %d", attacker->entity->desc, attacker->id, def->card->entity->desc, def->card->id, flag(&attacker->state, CARD_SPELL, FLAG_ISSET), flag(&attacker->state, CARD_LEVELUP, FLAG_ISSET), flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET)); + } + } + + WEAPON_ATTACK(attacker, p->deck_copy); + ATTACHMENT_ATTACK(attacker, p->deck_copy); + + return 0; +} diff --git a/hm_gameserver/src/game/mechanics/entity/attack.c b/hm_gameserver/src/game/mechanics/entity/attack.c new file mode 100644 index 0000000..36d1de2 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/entity/attack.c @@ -0,0 +1,210 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +#define F_ENRAGED 0x1 + +static void consider_attachments(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, int *heal, int *damage) +{ + // check buffs + struct card_link_s *child; + struct card_s *child_card; + + int flag = 0; + + for(child = card->attached_children; child != NULL; child = child->next) { + child_card = card_get(deck, opponent, child->id); + + assert(child_card); + + // Enraged - 80% damage reduction + if(!EQFLAG(flag, F_ENRAGED) && strcmp(child_card->entity->name, "CS2_011o") == 0 && *damage > 0) { + flag |= F_ENRAGED; + int d = *damage; + if((*damage *= .2) < 1) *damage = 1; + hm_log(LOG_DEBUG, lg, "Defender [%s](%d) incoming damage reduced from %d to %d", card->entity->desc, card->id, d, *damage); + } + } +} + +static int tags_change(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender) +{ + int attack = 0, heal = 0; + int defender_health; + int defender_armor; + /* + int a_side; + int d_side; + + a_side = attacker->controller; + d_side = defender->controller; + */ + + defender_health = defender->health; + defender_armor = defender->armor; + + if(defender->receive.damage > 0) { + attack = defender->receive.damage; + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && p->deck_copy->spellpower > 0) { + attack += p->deck_copy->spellpower; + } + } else if(defender->receive.heal > 0) { + heal = defender->receive.heal; + } + + consider_attachments(p->deck_copy, p->opponent.deck_copy, defender, &heal, &attack); + + __SECTION_ATTACK_EFFECT + + // heal + if(heal > 0) { + hm_log(LOG_DEBUG, lg, "Attacker [%s](%d) healing [%s](%d) healpower: %d", attacker->entity->desc, attacker->id, defender->entity->desc, defender->id, heal); + if(defender->health + heal > defender->total_health) { + defender->health = defender->total_health; + } else { + defender->health += heal; + } + + defender->receive.heal = heal; + // attack + } else { + if(attack == 0) { + attack = attacker->attack; + } + + __SECTION_ATTACK_EFFECT_ATTACHMENT + + hm_log(LOG_DEBUG, lg, "Attacker [%s](%d) attacking [%s](%d) power: %d", attacker->entity->desc, attacker->id, defender->entity->desc, defender->id, attack); + + defender->receive.damage = attack; + + if(attack >= (defender->health + defender->armor)) { + defender->health = 0; + defender->armor = 0; + flag(&defender->state, CARD_DESTROYED, FLAG_SET); + } else { + defender->armor -= attack; + if(defender->armor < 0) { + defender->health += defender->armor; + defender->armor = 0; + } + } + } + + if(defender_health != defender->health) { + flag(&defender->state, MECHANICS_DAMAGE, FLAG_SET); + + if(defender_health > defender->health) { + flag(&defender->state, MECHANICS_ATTACK_DAMAGE, FLAG_SET); + + if(flag(&defender->state, CARD_GURU_BERSERKER, FLAG_ISSET) && defender->health != 0) { + defender->attack += 3; + flag(&defender->state, MECHANICS_ATTACK, FLAG_SET); + add_single_attachment(p, p->deck_copy, defender, defender); + } + + hm_log(LOG_DEBUG, lg, "Defender: %d set to be damaged", defender->id); + + } else { + flag(&defender->state, MECHANICS_ATTACK_HEAL, FLAG_SET); + + hm_log(LOG_DEBUG, lg, "Defender: %d set to be healed", defender->id); + + //attacker->target.heal = attacker->attack; + //defender->receive.heal = attacker->attack; + } + } else { + hm_log(LOG_DEBUG, lg, "Defender: %d health unchanged", defender->id); + } + + if(defender->armor != defender_armor) { + flag(&defender->state, MECHANICS_ARMOR, FLAG_SET); + } + + return 0; +} + +int entity_attack(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender) +{ + struct card_list_s *item; + + hm_log(LOG_DEBUG, lg, "Attack"); + hm_log(LOG_DEBUG, lg, "Attacker: %d Health: %d Attack: %d Deck: %d", attacker->id, attacker->health, attacker->attack, attacker->controller); + hm_log(LOG_DEBUG, lg, "Defender: %d Health: %d Attack: %d Deck: %d", defender->id, defender->health, defender->attack, defender->controller); + + LIST_ADD(attacker->target.card, item, defender); + + // increase total plays of attacker + attacker->total_plays++; + attacker->turn_plays++; + + tags_change(p, attacker, defender); + + ///< defender strikes back + if(!flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && + !flag(&attacker->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_ISSET) && + // FIXME: !!! do friendly minions ever attack each other physically? + attacker->parent->deck_copy->controller != defender->parent->deck_copy->controller + ) { + tags_change(p, defender, attacker); + } + + if(!flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) { + if(attacker->health == 0) { + + hm_log(LOG_DEBUG, lg, "Destroying attacker %d from deck %d", attacker->id, p->deck_copy->controller); + card_destroy(attacker, p->deck_copy, 0); + + } else { + if(!(attacker->turn_plays == 1 && flag(&attacker->state, CARD_WINDFURY, FLAG_ISSET))) { + flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET); + } + } + } + + if(defender->health == 0) { + if(flag(&defender->state, CARD_HERO, FLAG_ISSET)) { + // TODO: game over + hm_log(LOG_DEBUG, lg, "Game over"); + } else { + hm_log(LOG_DEBUG, lg, "Destroying defender %d from deck %d", defender->id, p->opponent.deck_copy->controller); + card_destroy(defender, p->opponent.deck_copy, 0); + } + } + + { + struct card_s *__fake_defender = attacker; + struct card_s *__fake_attacker = defender; + if(__fake_attacker->attack > 0) { + __SECTION_DEFENDER + } + } + + { + struct card_s *__fake_defender = defender; + struct card_s *__fake_attacker = attacker; + if(__fake_attacker->attack > 0) { + __SECTION_DEFENDER + } + } + + hm_log(LOG_DEBUG, lg, "Post Attacker: [%s](%d) Health: %d", attacker->entity->desc, attacker->id, attacker->health); + hm_log(LOG_DEBUG, lg, "Post Defender: [%s](%d) Health: %d", defender->entity->desc, defender->id, defender->health); + + return 0; +} diff --git a/hm_gameserver/src/game/mechanics/entity/update_resources.c b/hm_gameserver/src/game/mechanics/entity/update_resources.c new file mode 100644 index 0000000..6857941 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/entity/update_resources.c @@ -0,0 +1,35 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int update_resources(struct deck_s *deck, struct card_s *attacker, int refresh) +{ + // refresh resources + if(refresh == 1) { + hm_log(LOG_DEBUG, lg, "Mana refreshed to %d", deck->mana); + deck->mana_used = 0; + return 0; + } + + deck->mana_used += attacker->cost; + + hm_log(LOG_DEBUG, lg, "Card cost: %d", attacker->cost); + hm_log(LOG_DEBUG, lg, "Mana used: %d Mana total: %d", deck->mana_used, deck->mana); + + return 0; +} diff --git a/hm_gameserver/src/game/mechanics/expire.c b/hm_gameserver/src/game/mechanics/expire.c new file mode 100644 index 0000000..eff3c51 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/expire.c @@ -0,0 +1,131 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mechanics_expire(int game_turn, struct card_s *card, enum expire_e key, int value, const char *attachment) +{ + struct card_expire_s *ce; + + ce = malloc(sizeof(*ce)); + memset(ce, 0, sizeof(*ce)); + + ce->turn = game_turn; + + switch(key) { + case EXPIRE_ATTACK: + ce->attack = value; + break; + + case EXPIRE_FROZEN: + ce->frozen = value; + break; + + case EXPIRE_MAGIC_IMMUNITY: + ce->magic_immunity = value; + break; + + case EXPIRE_DESTROY: + ce->destroy = value; + break; + + case EXPIRE_ATTACHMENT: + ce->attachment = attachment; + break; + + default: + abort(); + break; + } + + ce->next = card->expire; + card->expire = ce; +} + +static void expiration_list(struct hs_holder_s *p, struct deck_s *deck, struct deck_s *deck_opponent, struct card_s *card, int *unfreeze, int *mimmunity) +{ + struct card_expire_s *ce; + + for(ce = card->expire; ce != NULL; ce = ce->next) { + + if(ce->frozen > 0 && *unfreeze < ce->turn) { + *unfreeze = ce->turn; // get the highest unfreeze turn + } + + if(ce->magic_immunity > 0 && *mimmunity < ce->turn) { + *mimmunity = ce->turn; // get the highest magic immunity turn + } + + if(ce->turn == p->game->turn) { + if(ce->attack != 0) { + card->attack += ce->attack; + hm_log(LOG_DEBUG, lg, "%s Changed attack of card %d to %d", LOG_MECHANICS, card->id, card->attack); + flag(&card->state, MECHANICS_ATTACK, FLAG_SET); + } else if(ce->destroy == 1) { + hm_log(LOG_DEBUG, lg, "%s Card %d set to be destroyed", LOG_MECHANICS, card->id); + flag(&card->state, CARD_DESTROYED, FLAG_SET); + } + + if(ce->attachment != NULL) { + card_remove_attachment(deck, p->opponent.deck_copy, card, ce->attachment); + ce->attachment = NULL; + } + } + } +} + +void mechanics_expired(struct hs_holder_s *p, struct deck_s *deck) +{ + int i; + int unfreeze_turn, magic_immunity_turn; + + for(i = 0; i < deck->ncards; i++) { + + unfreeze_turn = magic_immunity_turn = 0; + + expiration_list(p, deck, p->opponent.deck_copy, deck->cards[i], &unfreeze_turn, &magic_immunity_turn); + + if(p->game->turn == unfreeze_turn) { + hm_log(LOG_DEBUG, lg, "%s Unfreezing card: %d", LOG_MECHANICS, deck->cards[i]->id); + flag(&deck->cards[i]->state, CARD_FROZEN, FLAG_UNSET); + } + + if(p->game->turn == magic_immunity_turn) { + hm_log(LOG_DEBUG, lg, "%s Removing magic immunity from card: %d", LOG_MECHANICS, deck->cards[i]->id); + flag(&deck->cards[i]->state, CARD_DIVINE_SHIELD, FLAG_UNSET); + } + } +} + +void force_expire(struct hs_holder_s *p, struct deck_s *deck, struct card_s *card) +{ + struct card_expire_s *ce; + struct deck_s *deck_opponent = p->opponent.deck_copy; + +#define ATT\ + if(ce->attachment != NULL) {\ + card_remove_attachment(deck, deck_opponent, card, ce->attachment);\ + } + + for(ce = card->expire; ce != NULL; ce = ce->next) { + + if(ce->frozen == 1) { + ATT + flag(&card->state, CARD_FROZEN, FLAG_UNSET); + } + } +} diff --git a/hm_gameserver/src/game/mechanics/next_turn.c b/hm_gameserver/src/game/mechanics/next_turn.c new file mode 100644 index 0000000..738361b --- /dev/null +++ b/hm_gameserver/src/game/mechanics/next_turn.c @@ -0,0 +1,70 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +static void summon_npc(struct conn_client_s *c, struct hs_holder_s *p, struct deck_s *opponent) +{ + hsl_summon_card(opponent, "EX1_158t", holder); +} + +void mechanics_next_turn(struct conn_client_s *c, struct hs_holder_s *p) +{ + struct deck_s *opponent, *deck; + + deck = p->deck_copy; + opponent = p->opponent.deck_copy; + + if(p->game->turn % 2 == 0 && p->deck->mana < 10) { + deck->mana++; + opponent->mana++; + } + + p->game->turn++; + + reset_turn_plays(opponent); + + summon_npc(c, p, opponent); + + mechanics_expired(p, deck); + mechanics_expired(p, opponent); + + cards_unset_flag(opponent, CARD_EXHAUSTED); + + register_turntimer(p->opponent.client); + + // fatigue? + if(card_deck_count(opponent) == 0) { + struct card_s *card = p->opponent.deck_copy->hero; + assert(card); + + hm_log(LOG_DEBUG, lg, "Opponent's deck empty: Fatigue %d to hero [%s](%d)", p->opponent.deck_copy->fatigue, card->entity->desc, card->id); + + ++(opponent->fatigue); + + card->health -= opponent->fatigue; + + if(card->health <= 0) { + opponent->gameover = 1; + } + } + + { + struct deck_s *__fake_deck = deck; + __SECTION_ENDTURN + } +} diff --git a/hm_gameserver/src/game/mechanics/put_card_onboard.c b/hm_gameserver/src/game/mechanics/put_card_onboard.c new file mode 100644 index 0000000..4a36273 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/put_card_onboard.c @@ -0,0 +1,76 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mechanics_put_card_onboard(struct conn_client_s *c, u64 position, struct card_s *attacker, int summoned, struct card_list_s **d, struct chooseoption_s *opt, struct deck_s *deck) +{ + struct hs_holder_s *p; + struct card_s *card; + struct card_list_s *defenders = NULL; + + p = c->data; + + assert(deck); + + hm_log(LOG_DEBUG, c->log, "%s Putting card %d onboard summoned %d defenders %p", LOG_MECHANICS, attacker->id, summoned, defenders); + flag(&attacker->state, CARD_HAND, FLAG_UNSET); + + // if charge or battlecry target + if(!flag(&attacker->state, CARD_CHARGE, FLAG_ISSET) && + !flag(&attacker->state, CARD_BATTLECRY_TARGET, FLAG_ISSET) && + !flag(&attacker->state, CARD_WEAPON, FLAG_ISSET) + ) { + flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET); + } + + // spellpower + if(flag(&attacker->state, CARD_SPELLPOWER, FLAG_ISSET)) { + deck->spellpower++; //attacker->spellpower; + hm_log(LOG_DEBUG, c->log, "%s Player %d spellpower %d", LOG_MECHANICS, p->entity_id, deck->spellpower); + } + + // regular minion or weapon + if(flag(&attacker->state, CARD_WEAPON, FLAG_ISSET)) { + __SECTION_WEAPON + } else { + flag(&attacker->state, CARD_BOARD, FLAG_SET); + } + + cards_reorder(p, deck, attacker, position, summoned); + + // battlecries + if(flag(&attacker->state, CARD_BATTLECRY, FLAG_ISSET) && + !flag(&attacker->state, MECHANICS_CHANGESIDES, FLAG_ISSET) // captured minions do not trigger BC + ) { + flag(&attacker->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_SET); + + { + struct card_s *__fake_levelup = NULL; + __SECTION_BATTLECRY + } + } + + { + struct card_s *__fake_attacker = attacker; + __SECTION_IDLE + } + + { + __SECTION_ONBOARD + } +} diff --git a/hm_gameserver/src/game/mechanics/summon.c b/hm_gameserver/src/game/mechanics/summon.c new file mode 100644 index 0000000..40aeb95 --- /dev/null +++ b/hm_gameserver/src/game/mechanics/summon.c @@ -0,0 +1,40 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mechanics_summon(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **defenders) +{ + struct hs_holder_s *p; + struct deck_s *deck; + + p = c->data; + deck = p->deck_copy; + + assert(deck); + + assert(attacker); + + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) { + if(!flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) { + flag(&attacker->state, CARD_DESTROYED, FLAG_SET); + cards_reorder(p, deck, attacker, opt->position, 0); + } else { + flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET); + } + } +} diff --git a/hm_gameserver/src/game/net/attack.c b/hm_gameserver/src/game/net/attack.c new file mode 100644 index 0000000..9a8bc20 --- /dev/null +++ b/hm_gameserver/src/game/net/attack.c @@ -0,0 +1,173 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_attack(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_s *defender, int target_player) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + //struct card_s *attacker, *defender; + //struct deck_s *deck; + + p = c->data; + //deck = p->deck; + //attacker = card_get(p->deck, NULL, p->arroworigin); + //defender = card_get(p->opponent.deck, p->deck, opt->target); + //assert(attacker && defender); + + //game_attack(p, attacker, defender); + + add_powerstart(&data, 1, -1, attacker->id, defender->id, NULL, 0); + //add_tagchange(&data, 417, 1, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PROPOSED_ATTACKER, attacker->id, 1); + add_tagchange(&data, PROPOSED_DEFENDER, opt->target, 1); + add_tagchange(&data, ATTACKING, 1, p->arroworigin); + add_tagchange(&data, NEXT_STEP, 10, 1); + add_tagchange(&data, STEP, 11, 1); + add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id == 2 ? 3 : 2); + + add_tagchange(&data, DEFENDING, 1, opt->target); + add_tagchange(&data, PREDAMAGE, defender->receive.damage, opt->target); + add_tagchange(&data, PREDAMAGE, 0, opt->target); + add_meta(&data, 1, defender->receive.damage, opt->target); + + add_tagchange(&data, LAST_AFFECTED_BY, p->arroworigin, opt->target); + //add_tagchange(&data, DAMAGE, defender->total_health - defender->health, opt->target); // total damaged caused from beginning + add_tagchange(&data, PREDAMAGE, attacker->receive.damage, p->arroworigin); + add_tagchange(&data, PREDAMAGE, 0, p->arroworigin); + + add_meta(&data, 1, attacker->receive.damage, p->arroworigin); + + add_tagchange(&data, NUM_ATTACKS_THIS_TURN, 1, p->arroworigin); + + /* + if(--(attacker->actions_number) == 0) { + hm_log(LOG_DEBUG, lg, "setting card %d to EXHAUSTED", attacker->id); + add_tagchange(&data, EXHAUSTED, 1, p->arroworigin); + } + */ + + add_tagchange(&data, PROPOSED_ATTACKER, 0, 1); + add_tagchange(&data, PROPOSED_DEFENDER, 0, 1); + add_tagchange(&data, ATTACKING, 0, p->arroworigin); + add_tagchange(&data, DEFENDING, 0, opt->target); + + // pass old deck + //LIST_ADD(cl, clitem, attacker); + //LIST_ADD(cl, clitem, defender); + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, target_player, NET_ATTACK); + + add_powerend(&data); + + //add_powerstart(&data, 6, 0, 1, 0, NULL, 0); + //add_tagchange(&data, NUM_MINIONS_PLAYER_KILLED_THIS_TURN, 1, p->entity_id); // 368 + //add_tagchange(&data, NUM_MINIONS_KILLED_THIS_TURN, 1, 1); // 369 + //add_tagchange(&data, 398, 1, p->entity_id); + //add_tagchange(&data, 412, 1, p->entity_id); + + //damage_done(&data, p, attacker, defender); + + //update_zone_position_attack(&data, p); + + /* + if(attacker->health == 0) { + cards_board_destroyed_reorder(&data, p->deck, attacker->zone_position); + + add_tagchange(&data, EXHAUSTED, 0, attacker->id); // 43 + add_tagchange(&data, DAMAGE, 0, attacker->id); + add_tagchange(&data, ZONE, 4, attacker->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + } else { + add_tagchange(&data, DAMAGE, attacker->total_health - attacker->health, attacker->id); // total damaged caused from beginning + card_set_exhausted(attacker); + } + + add_tagchange(&data, ARMOR, defender->armor, defender->id); + add_tagchange(&data, ARMOR, attacker->armor, attacker->id); + + if(defender->health == 0) { + add_tagchange(&data, EXHAUSTED, 0, defender->id); // 43 + add_tagchange(&data, DAMAGE, 0, defender->id); + add_tagchange(&data, ZONE, 4, defender->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, defender->id); + + if(EQFLAG(defender->state, CARD_HERO)) { + add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); + add_tagchange(&data, PLAYSTATE, 4, p->entity_id); + } else { + cards_board_destroyed_reorder(&data, p->opponent.deck, defender->zone_position); + } + } + */ + + /** destroy both */ + /* + add_tagchange(&data, ZONE, 4, attacker->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + add_tagchange(&data, ZONE, 4, defender->id); // 49 + add_tagchange(&data, ZONE_POSITION, 0, defender->id); + attacker->state = CARD_DESTROYED; + defender->state = CARD_DESTROYED; + */ + + //add_powerend(&data); + + //add_tagchange(&data, STEP, 10, 1); + //add_powerstart(&data, 5, 2, p->entity_id, 0, NULL, 0); + + /* + if(flag(&attacker->state, CARD_HERO, FLAG_ISSET) && p->deck->heroweapon) { + + p->deck->heroweapon->durability--; + + add_meta(&data, 1, p->deck->heroweapon->attack, p->deck->heroweapon->id); + add_tagchange(&data, LAST_AFFECTED_BY, p->deck->hero->id, p->deck->heroweapon->id); + + add_tagchange(&data, DAMAGE, p->deck->heroweapon->maxdurability - p->deck->heroweapon->durability, p->deck->heroweapon->id); + add_tagchange(&data, EXHAUSTED, 1, p->deck->heroweapon->id); + + if(p->deck->heroweapon->durability == 0) { + add_tagchange(&data, ZONE, 4, p->deck->heroweapon->id); + add_tagchange(&data, ATK, 0, attacker->id); + + //p->deck->heroweapon->state |= CARD_DESTROYED; + flag(&p->deck->heroweapon->state, CARD_DESTROYED, FLAG_SET); + p->deck->hero->attack = 0; + + hm_log(LOG_DEBUG, lg, "heroweapon destroyed %d", p->deck->heroweapon->id); + + p->deck->heroweapon = NULL; + } + + } + */ + + //add_tagchange(&data, NEXT_STEP, 12, 1); + //add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + + return packet; +} diff --git a/hm_gameserver/src/game/net/buff.c b/hm_gameserver/src/game/net/buff.c new file mode 100644 index 0000000..d4e46ca --- /dev/null +++ b/hm_gameserver/src/game/net/buff.c @@ -0,0 +1,109 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_buff(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct deck_s *deck; + int i; + struct card_list_s *def; + int count = 0; + + p = c->data; + deck = p->deck; + + for(count = 0, def = defenders; def != NULL; def = def->next, count++); + if(defenders && count == 1) { + add_powerstart(&data, 7, 0, attacker->id, defenders->card->id, NULL, 0); + } else { + add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0); + } + + add_tagchange(&data, 418, 26, p->entity_id); + add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + add_tagchange(&data, 430, 1, p->entity_id); + + add_tagchange(&data, ZONE, 1, attacker->id); + add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + add_tagchange(&data, JUST_PLAYED, 1, attacker->id); + + add_tagchange(&data, 397, attacker->id, p->entity_id); + //add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + //cards_reorder(deck, &data, attacker, opt, player); + + if(attacker->controller != player) { + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == p->held_card) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0); + add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data_show(&data, show); + + break; + } + } + } + + if(defenders) { + if(count == 1) { + add_powerstart(&data, 3, -1, attacker->id, defenders->card->id, NULL, 0); + } else { + add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0); + } + + struct powerhistory_info_s *info = NULL; + for(def = defenders; def != NULL; def = def->next) { + add_info(&info, def->card->id); + } + assert(info); + add_meta_info(&data, 0, 0, info); + + //add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id); + //add_tagchange(&data, PREDAMAGE, 0, opt->target); + //add_meta(&data, 3, 0, opt->target); + + //add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id); + //add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id); + add_powerend(&data); + } + + if(count == 1) { + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_BUFF); + } else { + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_BUFFAOE); + } + + //add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id); + + //add_tagchange(&data, WINDFURY, 1, defender->id); + //damage_done(&data, p, attacker, defender); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/game/net/card_flags.c b/hm_gameserver/src/game/net/card_flags.c new file mode 100644 index 0000000..8069c67 --- /dev/null +++ b/hm_gameserver/src/game/net/card_flags.c @@ -0,0 +1,603 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +static void net_card_summon_entity(struct powerhistory_data_s **data, struct card_s *card, int id, int zone, int target_player) +{ + struct powerhistory_entity_s *full = NULL; + + // if summon to hand, only show it to owner + if(zone == 1 || (zone == 3 && target_player == card->parent->deck_copy->controller) || zone == 6) { + struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0); + add_tag(&card_tags, CONTROLLER, card->parent->deck_copy->controller); + add_tag(&card_tags, ENTITY_ID, card->id); + if(id != 0) { + add_tag(&card_tags, CREATOR, id); + } + add_full_entity(&full, card_tags, card->id, card->entity->name, card->entity->nname); + add_ph_data_full(data, full); + + hm_log(LOG_ALERT, lg, "Generating full entity zone %d for card [%s](%d) player %d card parent %d", zone, card->entity->desc, card->id, target_player, card->parent->deck_copy->controller); + } else { + struct powerhistory_tag_s *card_tags = NULL; + add_tag(&card_tags, CONTROLLER, card->parent->deck_copy->controller); + add_tag(&card_tags, ENTITY_ID, card->id); + if(id != 0) { + add_tag(&card_tags, CREATOR, id); + } + add_full_entity(&full, card_tags, card->id, NULL, 0); + add_ph_data_full(data, full); + + hm_log(LOG_ALERT, lg, "Generating full enemy entity zone %d for card [%s](%d) player %d card parent %d", zone, card->entity->desc, card->id, target_player, card->parent->deck_copy->controller); + } + + // if card is attached to any other + /* + for(att = card->attachments; att != NULL; att = att->next) { + add_tagchange(data, ATTACHED, att->id, card->id); + } + */ + if(card->attached_to > 0) { + add_tagchange(data, ATTACHED, card->attached_to, card->id); + } + + add_tagchange(data, ZONE_POSITION, card->zone_position, card->id); + add_tagchange(data, ZONE, zone, card->id); + if(id != 0) { + add_tagchange(data, 334, id, card->parent->deck_copy->controller); + } +} + +static void net_card_to_hand(struct powerhistory_data_s **data, struct card_s *card, int target_player, struct hs_holder_s *p) +{ + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0); + + assert(card); + assert(card->parent); + assert(card->parent->deck_copy); + assert(card->parent->deck_copy->controller); + + hm_log(LOG_ALERT, lg, "Card to hand deck controller %d target %d p->id %d", card->parent->deck_copy->controller, target_player, p->id); + + if(target_player == card->controller) { + add_full_entity(&show, card_tags, card->id, card->entity->name, card->entity->nname); + add_ph_data_show(data, show); + } +} + +static void net_spell_tracking(struct powerhistory_data_s **data, struct card_s *card, int target_player) +{ + struct card_list_s *t; + + if(card->target.card != NULL) { + add_powerstart(data, 3, -1, card->id, 0, NULL, 0); + } + + if(card->target.card != NULL) { + add_meta(data, 0, 0, card->id); + } + + if(target_player != 1) { + for(t = card->target.card; t != NULL; t = t->next) { + /* + struct powerhistory_entity_s *full = NULL; + struct powerhistory_tag_s *card_tags = NULL; + add_tag(&card_tags, CONTROLLER, t->card->parent->controller); + add_tag(&card_tags, ENTITY_ID, t->card->id); + add_tag(&card_tags, ZONE, 6); + add_full_entity(&full, card_tags, t->card->id, NULL, 0); + add_ph_data_full(data, full); + */ + + add_tagchange(data, ZONE, 6, t->card->id); + } + } else { + for(t = card->target.card; t != NULL; t = t->next) { + struct powerhistory_entity_s *full = NULL; + struct powerhistory_tag_s *card_tags = default_tags(t->card, t->card->entity, 6); + add_tag(&card_tags, CONTROLLER, t->card->parent->deck_copy->controller); + add_tag(&card_tags, ENTITY_ID, t->card->id); + add_full_entity(&full, card_tags, t->card->id, t->card->entity->name, t->card->entity->nname); + add_ph_data_show(data, full); + } + } + + if(card->target.card != NULL) { + // add_powerend(data); + } +} + +static void net_spell_type(struct powerhistory_data_s **data, struct card_s *card) +{ + struct card_list_s *t; + + if(card->target.card && card->target.card->next == NULL) { + add_powerstart(data, 3, -1, card->id, card->target.card->card->id, NULL, 0); + } else { + add_powerstart(data, 3, -1, card->id, 0, NULL, 0); + } + + if(card->target.card != NULL) { + struct powerhistory_info_s *info = NULL; + + for(t = card->target.card; t != NULL; t = t->next) { + add_info(&info, t->card->id); + } + assert(info); + add_meta_info(data, 0, 0, info); + } + + for(t = card->target.card; t != NULL; t = t->next) { + if(flag(&t->card->state, MECHANICS_ATTACK_HEAL, FLAG_ISSET)) { + add_tagchange(data, 425, t->card->receive.heal, t->card->id); + add_tagchange(data, 425, 0, t->card->id); + add_meta(data, 2, t->card->receive.heal, t->card->id); + add_tagchange(data, LAST_AFFECTED_BY, card->id, t->card->id); + } else if(flag(&t->card->state, MECHANICS_ATTACK_DAMAGE, FLAG_ISSET)) { + add_tagchange(data, PREDAMAGE, t->card->receive.damage, t->card->id); + add_tagchange(data, PREDAMAGE, 0, t->card->id); + add_meta(data, 1, t->card->receive.damage, t->card->id); + add_tagchange(data, LAST_AFFECTED_BY, card->id, t->card->id); + } else if(flag(&t->card->state, MECHANICS_DESTROY_WEAPON, FLAG_ISSET)) { + + add_tagchange(data, DURABILITY, 0, t->card->id); + add_tagchange(data, LAST_AFFECTED_BY, card->id, t->card->id); + add_tagchange(data, EXHAUSTED, 0, t->card->id); + add_tagchange(data, ZONE, 4, t->card->id); + } + } + + + add_powerend(data); +} + +static int qscb(const struct flag_pr_s **src, const struct flag_pr_s **dst) +{ + return ((*src)->priority - (*dst)->priority); +} + +static int merge(struct flag_pr_s ***dst, int ndst, struct flag_pr_s **src, int nsrc) +{ + int i; + + if(src == NULL && *dst != NULL) { + return ndst; + } else if(src != NULL && *dst == NULL) { + *dst = src; + return nsrc; + } else { + assert(dst && src); + } + + *dst = realloc(*dst, (ndst + nsrc) * sizeof(void *)); + + for(i = 0; i < nsrc; i++) { + (*dst)[i + ndst] = src[i]; + } + + free(src); + + return (ndst + nsrc); +} + +static void net_card_flags_iter(struct powerhistory_data_s **data, struct flag_pr_s **src, int nsrc, int target_player, struct hs_holder_s *p) +{ + int i; + +#define TAG(m_id, m_num)\ + add_tagchange(data, m_id, m_num, src[i]->parent_card->id); + + for(i = 0; i < nsrc; i++) { + switch(src[i]->flag) { + case MECHANICS_DAMAGE: + if(src[i]->type == F_ADDED) { + TAG(DAMAGE, src[i]->parent_card->total_health - src[i]->parent_card->health) + } + break; + + case MECHANICS_HEALTH: + if(src[i]->type == F_ADDED) { + TAG(HEALTH, src[i]->parent_card->total_health) + TAG(DAMAGE, src[i]->parent_card->total_health - src[i]->parent_card->health); + } + break; + + case MECHANICS_ATTACK: + if(src[i]->type == F_ADDED) { + TAG(ATK, src[i]->parent_card->attack) + } + break; + + case MECHANICS_ARMOR: + if(src[i]->type == F_ADDED) { + TAG(ARMOR, src[i]->parent_card->armor) + } + break; + + case MECHANICS_DETACH: + if(src[i]->type == F_ADDED) { + TAG(ATTACHED, 0) + //TAG(314, 0) + //TAG(323, 0) + //TAG(324, 0) + } + break; + + case MECHANICS_DURABILITY: + if(src[i]->type == F_ADDED) { + TAG(DAMAGE, src[i]->parent_card->maxdurability - src[i]->parent_card->durability) + } + break; + + case MECHANICS_CHANGESIDES: + if(src[i]->type == F_ADDED) { + TAG(CONTROLLER, src[i]->parent_card->controller) + } + break; + + case MECHANICS_COST: + if(src[i]->type == F_ADDED) { + TAG(COST, src[i]->parent_card->cost) + } + break; + + + case MECHANICS_SELECTED: + if(src[i]->type == F_ADDED) { + net_spell_tracking(data, src[i]->parent_card, target_player); + } + break; + + case CARD_WINDFURY: + if(src[i]->type == F_ADDED) { + TAG(WINDFURY, 1) + } else { + TAG(WINDFURY, 0) + } + break; + + case CARD_DIVINE_SHIELD: + if(src[i]->type == F_REMOVED) { + TAG(DIVINE_SHIELD, 0) + } else { + TAG(DIVINE_SHIELD, 1) + } + break; + + case CARD_TAUNT: + if(src[i]->type == F_REMOVED) { + TAG(TAUNT, 0) + } else { + TAG(TAUNT, 1) + } + break; + + case CARD_EXHAUSTED: + if(src[i]->type == F_REMOVED) { + TAG(EXHAUSTED, 0) + } else { + TAG(EXHAUSTED, 1) + } + break; + + case CARD_FROZEN: + if(src[i]->type == F_REMOVED) { + TAG(FROZEN, 0) + } else { + TAG(FROZEN, 1) + } + break; + + case CARD_HIDE: + if(src[i]->type == F_ADDED) { + add_hide(data, src[i]->parent_card->id, 6); + } + break; + + case CARD_LINKED: + if(src[i]->type == F_ADDED) { + TAG(LINKEDCARD, src[i]->parent_card->linked) + } + break; + + case CARD_DESTROYED: + if(src[i]->type == F_ADDED) { + add_powerstart(data, 6, 0, 1, 0, NULL, 0); + TAG(ZONE, 4) + TAG(ZONE_POSITION, 0) + TAG(DAMAGE, 0) + add_powerend(data); + } + break; + + case CARD_DISCARD: + if(src[i]->type == F_ADDED) { + TAG(ZONE, 4) + } + break; + + case CARD_HAND: + if(src[i]->type == F_ADDED) { + net_card_to_hand(data, src[i]->parent_card, target_player, p); + TAG(ZONE, 3) + TAG(ZONE_POSITION, src[i]->parent_card->zone_position) // force new position as well + } + break; + + case CARD_BOARD: + if(src[i]->type == F_ADDED) { + TAG(ZONE, 1) + TAG(ZONE_POSITION, src[i]->parent_card->zone_position) // force new position as well + if(flag(&src[i]->parent_card->state, CARD_SPELL, FLAG_ISSET) && + !flag(&src[i]->parent_card->state, CARD_BUFF, FLAG_ISSET) && + !flag(&src[i]->parent_card->state, CARD_WEAPON, FLAG_ISSET) + /* + !flag(&src[i]->parent_card->state, CARD_SUMMON_CS2_MIRROR, FLAG_ISSET) && // FIXME: tmp + + + !flag(&src[i]->parent_card->state, CARD_DRAW_CARD, FLAG_ISSET) && // FIXME: tmp + + !flag(&src[i]->parent_card->state, CARD_TRACKING, FLAG_ISSET) // FIXME: tmp + */ + ) { + net_spell_type(data, src[i]->parent_card); + } + } + break; + + case MECHANICS_BATTLECRY_TRIGGER: + if(src[i]->type == F_ADDED) { + /* + if( + // non-target + flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE3_ENEMY_HERO, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_DESTROY_ENEMY_WEAPON, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE1_ALL, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_HEAL2_ALIES, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_HEAL6_ALLY_HERO, FLAG_ISSET) || + + // targetable + flag(&src[i]->parent_card->state, CARD_BATTLECRY_HEAL2_TARGET, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE1_TARGET, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE2_TARGET, FLAG_ISSET) || + flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE3_TARGET, FLAG_ISSET) + ) { + */ + net_spell_type(data, src[i]->parent_card); + //} + } + break; + + case MECHANICS_TURN_TRIGGER: + if(src[i]->type == F_ADDED) { + // TODO; fix this + /* + if( + // non-target + flag(&src[i]->parent_card->state, CARD_TURN_HEAL1_MINIONS, FLAG_ISSET) + ) { + net_spell_type(data, src[i]->parent_card); + } + */ + + net_spell_type(data, src[i]->parent_card); + } + break; + + + case MECHANICS_HEROPOWER: + if(src[i]->type == F_ADDED) { + net_spell_type(data, src[i]->parent_card); + } + break; + + + default: + hm_log(LOG_DEBUG, lg, "Flag %d not supported", src[i]->flag); + break; + } + } +} + +static void change_zone_positions(struct powerhistory_data_s **data, struct deck_s *old, struct deck_s *new) +{ + int i; + + for(i = 0; i < old->ncards && i < new->ncards; i++) { + if(old->cards[i]->zone_position != new->cards[i]->zone_position) { + add_tagchange(data, ZONE_POSITION, new->cards[i]->zone_position, new->cards[i]->id); + } + } +} + +static void net_card_flags_step(struct powerhistory_data_s **data, struct card_s *old_card, struct card_s *new_card, struct hs_holder_s *p, struct flag_pr_s ***dst, int *ndst) +{ + struct flag_pr_s **old = NULL; + struct flag_pr_s **new = NULL; + int nold = 0, nnew = 0; + int n; + + //flag(&new_card->state, -1, FLAG_DUMP); + flags_diff(&old_card->state, &new_card->state, &new, &nnew, &old, &nold, new_card); + if(nnew != 0 || nold != 0) { + hm_log(LOG_DEBUG, lg, "Considering card [%s](%d)", new_card->entity->desc, new_card->id); + n = merge(&new, nnew, old, nold); + *ndst = merge(dst, *ndst, new, n); + + assert(new); + } + + // game over FIXME: wrong position + if(flag(&new_card->state, CARD_HERO, FLAG_ISSET) && new_card->health == 0) { + add_tagchange(data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); // needed + add_tagchange(data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); // needed + add_tagchange(data, PLAYSTATE, 4, p->entity_id); // needed + } +} + +static void net_card_summon(struct powerhistory_data_s **data, struct deck_s *deck_old, struct deck_s *deck_new, struct card_list_s *attacker, int target_player, int nettype) +{ + int i; + int att; + + hm_log(LOG_DEBUG, lg, "Attempt to summon from deck %p:%p", deck_old, deck_new); + + if(!(deck_old && deck_new && deck_new->ncards != deck_old->ncards)) { + if(deck_new && deck_old) { + hm_log(LOG_DEBUG, lg, "Not summoning from deck %p:%p:%d new: %d old: %d", deck_new, deck_old, deck_new->controller, deck_new->ncards, deck_old->ncards); + } + return; + } + + + hm_log(LOG_DEBUG, lg, "Summoning as deck new %p:%d and deck old %p:%d", deck_new, deck_new->ncards, deck_old, deck_old->ncards); + + if(attacker && attacker->card) { + att = attacker->card->id; + } else { + att = 0; + } + + // it's very important to set this when various user actions summon units + if(nettype == NET_PUTONBOARD || nettype == NET_BUFFAOE) { + add_powerstart(data, 3, -1, att, 0, NULL, 0); + } else if(nettype == NET_SPELL || nettype == NET_SPELLAOE) { + add_powerstart(data, 6, 0, att, 0, NULL, 0); + } + // NET_BUFF, NET_SPELLAOE - no power start + + // we never remove cards, so diff is always up + for(i = deck_old->ncards; i < deck_new->ncards; i++) { + // if card just changed sides, ignore it + if(flag(&deck_new->cards[i]->state, MECHANICS_CHANGESIDES, FLAG_ISSET)) { + continue; + } + + // summon attachment + if(flag(&deck_new->cards[i]->state, CARD_ATTACHMENT, FLAG_ISSET)) { + //hm_log(LOG_DEBUG, lg, "Summoning attachment card [%s](%d)", deck_new->cards[i]->entity->name, deck_new->cards[i]->id); + //net_card_summon_entity(data, deck_new->cards[i], att, 6, target_player); + // summon cards on board + } else if(flag(&deck_new->cards[i]->state, CARD_BOARD, FLAG_ISSET)) { + hm_log(LOG_DEBUG, lg, "Summoning card [%s](%d) to board", deck_new->cards[i]->entity->name, deck_new->cards[i]->id); + net_card_summon_entity(data, deck_new->cards[i], att, 1, target_player); + // summon cards in hand + } else if(flag(&deck_new->cards[i]->state, CARD_HAND, FLAG_ISSET) + ) { + hm_log(LOG_DEBUG, lg, "Summoning card [%s](%d) to hand", deck_new->cards[i]->entity->name, deck_new->cards[i]->id); + net_card_summon_entity(data, deck_new->cards[i], att, 3, target_player); + } else { + hm_log(LOG_DEBUG, lg, "Card [%s](%d) set to be summoned, but no destination set, aborting", deck_new->cards[i]->entity->name, deck_new->cards[i]->id); + abort(); + } + } + + if(nettype == NET_PUTONBOARD || nettype == NET_SPELL || nettype == NET_BUFFAOE || nettype == NET_SPELLAOE) { + add_powerend(data); + } + + for(i = deck_old->ncards; i < deck_new->ncards; i++) { + // if card just changed sides, ignore it + if(flag(&deck_new->cards[i]->state, MECHANICS_CHANGESIDES, FLAG_ISSET)) { + continue; + } + + // summon attachment + if(flag(&deck_new->cards[i]->state, CARD_ATTACHMENT, FLAG_ISSET)) { + hm_log(LOG_DEBUG, lg, "Summoning attachment card [%s](%d)", deck_new->cards[i]->entity->name, deck_new->cards[i]->id); + net_card_summon_entity(data, deck_new->cards[i], att, 6, target_player); + } + } + + // NET_BUFF, NET_SPELLAOE - no power end +} + +void net_card_flags(struct powerhistory_data_s **data, struct deck_s *deck_old, struct deck_s *deck_new, + struct deck_s *opp_old, struct deck_s *opp_new, struct card_list_s *src, struct hs_holder_s *p, int target_player, int nettype) +{ + struct card_s *old_card = NULL; + struct card_list_s *c; + int i; + struct flag_pr_s **summary = NULL; + int nsummary = 0; + + //add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id); + +#define d1 (p->deck) +#define c1 (p->deck_copy) +#define d2 (p->opponent.deck) +#define c2 (p->opponent.deck_copy) + + assert(p); + + assert(deck_old && deck_new); + + change_zone_positions(data, d1, c1); + change_zone_positions(data, d2, c2); + + if(deck_old->mana_used != deck_new->mana_used) { + add_tagchange(data, RESOURCES_USED, deck_new->mana_used, p->entity_id); + } + + if(deck_old->spellpower != deck_new->spellpower) { + add_tagchange(data, CURRENT_SPELLPOWER, deck_new->spellpower, p->entity_id); + } + + if(opp_old && opp_new && opp_old->spellpower != opp_new->spellpower) { + add_tagchange(data, CURRENT_SPELLPOWER, opp_new->spellpower, p->entity_id == 3 ? 2 : 3); + } + + if(src != NULL) { + for(c = src; c != NULL; c = c->next) { + old_card = card_get(deck_old, opp_old, c->card->id); + + assert(old_card); + + net_card_flags_step(data, old_card, c->card, p, &summary, &nsummary); + } + + net_card_summon(data, deck_old, deck_new, src, target_player, nettype); + net_card_summon(data, opp_old, opp_new, src, target_player, nettype); + + } else { + + for(i = 0; i < deck_old->ncards && i < deck_new->ncards; i++) { + net_card_flags_step(data, deck_old->cards[i], deck_new->cards[i], p, &summary, &nsummary); + } + + for(i = 0; i < opp_old->ncards && i < opp_new->ncards; i++) { + net_card_flags_step(data, opp_old->cards[i], opp_new->cards[i], p, &summary, &nsummary); + } + + net_card_summon(data, deck_old, deck_new, NULL, target_player, nettype); + net_card_summon(data, opp_old, opp_new, NULL, target_player, nettype); + } + + if(summary) { + qsort(summary, nsummary, sizeof(*summary), (int (*)(const void *, const void *))qscb); + net_card_flags_iter(data, summary, nsummary, target_player, p); + } + + if(nsummary > 0) { + for(i = 0; i < nsummary; i++) { + free(summary[i]); + } + free(summary); + } +} diff --git a/hm_gameserver/src/game/net/card_onboard.c b/hm_gameserver/src/game/net/card_onboard.c new file mode 100644 index 0000000..26244e4 --- /dev/null +++ b/hm_gameserver/src/game/net/card_onboard.c @@ -0,0 +1,64 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_card_onboard(struct hs_holder_s *p, struct chooseoption_s *opt, struct card_s *attacker, int player) +{ + //struct deck_s *deck; + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + + assert(p); + + add_powerstart(&data, 7, 0, p->held_card, opt->target, NULL, 0); + //add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id); + //add_tagchange(&data, RESOURCES_USED, p->deck_copy->mana_used, p->entity_id); + + if(!flag(&attacker->state, CARD_CHARGE, FLAG_ISSET)) { + add_tagchange(&data, EXHAUSTED, 1, p->held_card); + } + + if(player != attacker->controller) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(attacker, attacker->entity, 0); + add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname); + add_ph_data_show(&data, show); + /* + if(flag(&attacker->state, CARD_BATTLECRY_DRAW1_CARD, FLAG_ISSET)) { + add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0); + add_meta(&data, 0, 0, attacker->id); + add_powerend(&data); + } + */ + } + + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_PUTONBOARD); + + hm_log(LOG_DEBUG, lg, "board zone position %lld for card: %d", opt->position, p->held_card); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + hm_log(LOG_DEBUG, lg, "Card onboard for player: %d", player); + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/game/net/game_over.c b/hm_gameserver/src/game/net/game_over.c new file mode 100644 index 0000000..ff07fa5 --- /dev/null +++ b/hm_gameserver/src/game/net/game_over.c @@ -0,0 +1,40 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_game_over(struct hs_holder_s *p, int loser) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + + add_powerstart(&data, 5, 0, 2, 0, NULL, 0); + + add_tagchange(&data, PLAYSTATE, 3, loser == 2 ? 3 : 2); // needed + add_tagchange(&data, PLAYSTATE, 5, loser == 2 ? 3 : 2); // needed + add_tagchange(&data, PLAYSTATE, 4, loser); // needed + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/game/net/next_turn.c b/hm_gameserver/src/game/net/next_turn.c new file mode 100644 index 0000000..11cf1b9 --- /dev/null +++ b/hm_gameserver/src/game/net/next_turn.c @@ -0,0 +1,166 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_next_turn(struct conn_client_s *c, struct card_s **drawn_card, int *zoneposition) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + + p = c->data; + + add_tagchange(&data, STEP, 12, 1); + add_powerstart(&data, 5, 4, 3, 0, NULL, 0); + add_tagchange(&data, NEXT_STEP, 16, 1); + add_powerend(&data); + + add_tagchange(&data, STEP, 16, 1); + add_powerstart(&data, 5, 5, 3, 0, NULL, 0); + add_tagchange(&data, NEXT_STEP, 13, 1); + add_powerend(&data); + + add_tagchange(&data, STEP, 13, 1); + add_powerstart(&data, 5, -1, 1, 0, NULL, 0); + add_tagchange(&data, NUM_TURNS_LEFT, 0, p->entity_id); + add_tagchange(&data, NUM_TURNS_LEFT, 1, p->entity_id); + add_tagchange(&data, CURRENT_PLAYER, 0, p->entity_id); + add_tagchange(&data, CURRENT_PLAYER, 1, (p->entity_id == 2 ? 3 : 2)); + add_tagchange(&data, TURN, p->game->turn, 1); + add_tagchange(&data, NEXT_STEP, 6, 1); + add_powerend(&data); + + add_tagchange(&data, STEP, 6, 1); + add_powerstart(&data, 5, 1, 2, 0, NULL, 0); + + /* + if(p->entity_id == 3) { + add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 64); + add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 65); + } else { + add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 66); + add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 67); + } + */ + + add_tagchange(&data, RESOURCES_USED, 0, (p->entity_id == 2 ? 3 : 2)); + add_tagchange(&data, RESOURCES, p->deck_copy->mana, (p->entity_id == 2 ? 3 : 2)); + add_tagchange(&data, 399, 0, (p->entity_id == 2 ? 3 : 2)); + add_tagchange(&data, NEXT_STEP, 17, 1); + add_powerend(&data); + + add_tagchange(&data, STEP, 17, 1); + add_powerstart(&data, 5, 8, 2, 0, NULL, 0); + add_tagchange(&data, NEXT_STEP, 9, 1); + add_powerend(&data); + + add_tagchange(&data, STEP, 9, 1); + add_powerstart(&data, 5, 0, 2, 0, NULL, 0); + + //card_used_reorder(p->deck, p->held_card); + if(*drawn_card == NULL) { + // player who just finished his move + struct deck_s *deck = p->opponent.deck_copy; + + *drawn_card = draw_random_card(deck, p->entity_id == 2 ? 3 : 2, -1); + if(*drawn_card) { + *zoneposition = (*drawn_card)->zone_position; + + hm_log(LOG_DEBUG, lg, "drawn card zone position %d for card: %d", (*drawn_card)->zone_position, (*drawn_card)->id); + + add_tagchange(&data, ZONE, 3, (*drawn_card)->id); + add_tagchange(&data, ZONE_POSITION, *zoneposition, (*drawn_card)->id); + } else { + struct card_s *card = p->opponent.deck_copy->hero; + assert(card); + + add_powerstart(&data, 8, 0, card->id, 0, NULL, 0); + + add_tagchange(&data, FATIGUE, p->opponent.deck_copy->fatigue, p->entity_id); + + add_tagchange(&data, PREDAMAGE, p->opponent.deck_copy->fatigue, p->entity_id); + + add_tagchange(&data, PREDAMAGE, 0, p->entity_id); + + add_meta(&data, 1, p->opponent.deck_copy->fatigue, card->id); + + add_tagchange(&data, LAST_AFFECTED_BY, 0, card->id); + + add_tagchange(&data, DAMAGE, card->total_health - card->health, card->id); + + add_powerend(&data); + + } + } else { + // next player to move + if(*drawn_card) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(*drawn_card, (*drawn_card)->entity, 0); + add_full_entity(&show, card_tags, (*drawn_card)->id, (*drawn_card)->entity->name, (*drawn_card)->entity->nname); + + add_tagchange(&data, ZONE_POSITION, *zoneposition, (*drawn_card)->id); + add_ph_data_show(&data, show); + } + } + + if(p->deck_copy->gameover == 1 || p->opponent.deck_copy->gameover == 1) { + add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); // needed + add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); // needed + add_tagchange(&data, PLAYSTATE, 4, p->entity_id); // needed + } + + //net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, p->id); + + add_tagchange(&data, EXHAUSTED, 0, p->opponent.deck_copy->heropower->id); + + if(p->opponent.deck_copy->heroweapon) { + add_tagchange(&data, EXHAUSTED, 0, p->opponent.deck_copy->heroweapon->id); + } + + add_tagchange(&data, 399, 1, (p->entity_id == 2 ? 3 : 2)); + add_tagchange(&data, 198, 10, 1); + add_powerend(&data); + + /* + struct powerhistory_entity_s *show = NULL; + struct ent_s *ent = find_entity("CS2_119", 7); + add_full_entity(&show, card_tags, p->entity_id == 2 ? 24 + 30 : 24, "CS2_119", 7); + add_ph_data_show(&data, show); + add_tagchange(&data, 263, (p->entity_id == 2 ? 5 : 6), p->entity_id == 2 ? 24 + 30 : 24); + add_tagchange(&data, 399, 1, (p->entity_id == 2 ? 3 : 2)); + add_tagchange(&data, 198, 10, 1); + add_powerend(&data); + */ + + add_tagchange(&data, STEP, 10, 1); + add_powerstart(&data, 5, 2, 2, 0, NULL, 0); + add_tagchange(&data, NEXT_STEP, 12, 1); + + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, p->id, NET_NEXTTURN); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + hm_log(LOG_DEBUG, lg, "Next turn %d dump", p->game->turn); + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/game/net/send.c b/hm_gameserver/src/game/net/send.c new file mode 100644 index 0000000..1ebbb25 --- /dev/null +++ b/hm_gameserver/src/game/net/send.c @@ -0,0 +1,82 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void net_send_turntimer(struct conn_client_s *c, int seconds, int turn, int show) +{ + int n; + char output[8192]; + char *ptr = output; + struct turntimer_s *all; + struct packet_s *packet; + + struct hs_holder_s *p; + + p = c->data; + + all = malloc(sizeof(*all)); + + all->seconds = seconds; + all->turn = turn; + all->show = show; + + add_packet(&packet, all, P_TURNTIMER); + + ptr = output; + n = serialize(packet, &ptr, output + sizeof(output)); + + turntimer_dump(all); + + hm_send(c, output, n); + hm_send(p->opponent.client, output, n); +} + +int net_send(struct conn_client_s *c, struct packet_s *packet) +{ + int n; + char output[8192]; + char *ptr = output; + n = serialize(packet, &ptr, ptr + sizeof(output)); + + hm_send(c, output, n); + + return 0; +} + +int net_send_options(struct conn_client_s *c, struct deck_s *deck, struct deck_s *opponent, int turn) +{ + int n; + char output[8192]; + + n = set_options(deck, opponent, output, output + sizeof(output), turn); + + hm_send(c, output, n); + + return 0; +} + +int net_send_cl_options(struct conn_client_s *c, struct card_list_s *cl, int turn) +{ + int n; + char output[8192]; + + n = set_options_cards(cl, output, output + sizeof(output), turn); + hm_send(c, output, n); + + return 0; +} diff --git a/hm_gameserver/src/game/net/spell.c b/hm_gameserver/src/game/net/spell.c new file mode 100644 index 0000000..a63159d --- /dev/null +++ b/hm_gameserver/src/game/net/spell.c @@ -0,0 +1,125 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +static void net_defender_attacked(struct hs_holder_s *p, struct powerhistory_data_s **data, struct card_s *attacker, struct card_s *defender, struct chooseoption_s *opt) +{ + add_meta(data, 0, 0, defender->id); + add_tagchange(data, PREDAMAGE, attacker->attack, defender->id); + add_tagchange(data, PREDAMAGE, 0, opt->target); + add_meta(data, 1, attacker->attack, opt->target); + + add_tagchange(data, LAST_AFFECTED_BY, attacker->id, defender->id); + add_tagchange(data, DAMAGE, defender->total_health - defender->health, defender->id); + add_powerend(data); + + //add_tagchange(data, ZONE, 4, attacker->id); + //add_tagchange(data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id); +} + +struct packet_s *net_spell(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders, struct card_s *fake_levelup) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct deck_s *deck; + int i; + struct card_list_s *cl = NULL, *clitem, *def; + struct card_s *defender; + + p = c->data; + deck = p->deck_copy; + + defender = defenders->card; + + add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0); + //add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost + //add_tagchange(&data, 418, 26, p->entity_id); + //add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + //add_tagchange(&data, 430, 1, p->entity_id); + + //add_tagchange(&data, ZONE, 1, attacker->id); + //add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + //add_tagchange(&data, JUST_PLAYED, 1, attacker->id); + + //add_tagchange(&data, 397, attacker->id, p->entity_id); + add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + + if(player != attacker->controller) { + for(i = 0; i < deck->ncards; i++) { + if(deck->cards[i]->id == p->held_card) { + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0); + add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data_show(&data, show); + + break; + } + } + } + + if(flag(&attacker->state, CARD_NONTARGET, FLAG_ISSET)) { + struct deck_s *opp = p->opponent.deck_copy; + for(i = 0; i < opp->ncards; i++) { + if(flag(&opp->cards[i]->state, CARD_BOARD, FLAG_ISSET)) { + + add_powerstart(&data, 3, -1, attacker->id, opp->cards[i]->id, NULL, 0); + net_defender_attacked(p, &data, attacker, opp->cards[i], opt); + add_powerend(&data); + } + } + } else { + /* + add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0); + //net_defender_attacked(p, &data, attacker, defender, opt); + + add_meta(&data, 0, 0, defender->id); + add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id); + add_tagchange(&data, PREDAMAGE, 0, opt->target); + add_meta(&data, 1, attacker->attack, opt->target); + + add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id); + //add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id); + add_powerend(&data); + */ + //damage_done(&data, p, attacker, defender); + + //update_zone_position_attack(&data, p); + + // pass old deck + LIST_ADD(cl, clitem, attacker); + for(def = defenders; def != NULL; def = def->next) { + LIST_ADD(cl, clitem, def->card); + } + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_SPELL); + + //net_card_flags(&data, p->deck, NULL, attacker, p); + //net_card_flags(&data, p->opponent.deck, NULL, defender, p); + + add_powerend(&data); + } + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/game/net/spell_aoe.c b/hm_gameserver/src/game/net/spell_aoe.c new file mode 100644 index 0000000..c7cb165 --- /dev/null +++ b/hm_gameserver/src/game/net/spell_aoe.c @@ -0,0 +1,109 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_spell_aoe(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct card_list_s *def; + struct card_list_s *cl = NULL, *clitem; + struct card_list_s *defenders; + + p = c->data; + + defenders = attacker->target.card; + + LIST_ADD(cl, clitem, attacker); + + for(def = defenders; def != NULL; def = def->next) { + LIST_ADD(cl, clitem, def->card); + } + + add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0); + + if(flag(&attacker->state, CARD_TRACKING, FLAG_ISSET)) { + + if(player == 2) { + + add_tagchange(&data, 418, 41, p->entity_id); + add_tagchange(&data, 269, 1, p->entity_id); + add_tagchange(&data, 430, 1, p->entity_id); + + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(attacker, attacker->entity, 1); + add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname); + add_ph_data_show(&data, show); + + add_tagchange(&data, 397, attacker->id, p->entity_id); + } + + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_SPELLAOE); + + } else { + /* + add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost + add_tagchange(&data, 418, 26, p->entity_id); + add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id); + add_tagchange(&data, 430, 1, p->entity_id); + + //add_tagchange(&data, ZONE, 1, attacker->id); + //add_tagchange(&data, ZONE_POSITION, 0, attacker->id); + //add_tagchange(&data, JUST_PLAYED, 1, attacker->id); + + //add_tagchange(&data, 397, attacker->id, p->entity_id); + + //cards_reorder(deck, &data, attacker, opt, player); + */ + if(player != attacker->controller) { + hm_log(LOG_DEBUG, lg, "Spell aoe attacker [%s](%d) showing full entity player %d controller %d", attacker->entity->desc, attacker->id, player, attacker->controller); + struct powerhistory_entity_s *show = NULL; + struct powerhistory_tag_s *card_tags = default_tags(attacker, attacker->entity, 0); + add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname); + add_ph_data_show(&data, show); + } + + // draw cards + /* + if(player == 1 && defenders != NULL) { + add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0); + add_meta(&data, 0, 0, attacker->id); + } + */ + + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_SPELLAOE); + + // draw cards + /* + if(player == 1 && defenders != NULL) { + add_powerend(&data); + } + */ + + add_powerend(&data); + } + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/game/net/spell_hp_damage.c b/hm_gameserver/src/game/net/spell_hp_damage.c new file mode 100644 index 0000000..0ee7c72 --- /dev/null +++ b/hm_gameserver/src/game/net/spell_hp_damage.c @@ -0,0 +1,65 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +struct packet_s *net_spell_hp_damage(struct conn_client_s *c, struct card_list_s *defenders, struct card_s *attacker) +{ + struct packet_s *packet = NULL; + struct powerhistory_s *ph = NULL; + struct powerhistory_data_s *data = NULL; + struct hs_holder_s *p; + struct card_list_s *cl = NULL, *clitem, *def; + struct card_s *defender; + + p = c->data; + defender = defenders->card; + + add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0); + //add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); + //add_tagchange(&data, 418, 36, p->entity_id); + /* + add_tagchange(&data, CARD_TARGET, defender->id, attacker->id); + + add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0); + add_meta(&data, 0, 0, defender->id); + add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id); + add_tagchange(&data, PREDAMAGE, 0, defender->id); + + add_meta(&data, 1, attacker->attack, defender->id); + add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id); + */ + // pass old deck + LIST_ADD(cl, clitem, attacker); + for(def = defenders; def != NULL; def = def->next) { + LIST_ADD(cl, clitem, def->card); + } + net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, cl, p, p->id, NET_SPELLHP_DAMAGE); + + add_powerend(&data); + + //add_tagchange(&data, 406, 1, p->entity_id); + + add_powerend(&data); + + add_ph(&ph, data); + add_packet(&packet, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + return packet; +} diff --git a/hm_gameserver/src/gamestart.c b/hm_gameserver/src/gamestart.c new file mode 100644 index 0000000..9dae81e --- /dev/null +++ b/hm_gameserver/src/gamestart.c @@ -0,0 +1,277 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int game_start(struct conn_client_s *c) +{ + struct powerhistory_entity_s *full, *mana_card = NULL; + struct powerhistory_game_entity_s *ge1, *ge2, *ge_main; + struct powerhistory_tag_s *p1_tags, *p2_tags, *game_tags, *card_tags; + struct powerhistory_player_s *players = NULL; + struct powerhistory_creategame_s *game_start; + struct powerhistory_data_s *data = NULL; + struct powerhistory_s *ph; + struct packet_s *p, *p1; + const struct ent_s *ent1, *ent2, *ent_game, *ent_nocard; + char out[8192], *ptr; + int i; + + ent1 = find_entity("PLAYER1", 7); + ent2 = find_entity("PLAYER2", 7); + + if(ent1 == NULL || ent2 == NULL) { + return -1; + } + + p1_tags = default_tags(NULL, ent1, 0); + p2_tags = default_tags(NULL, ent2, 0); + add_tag(&p1_tags, ENTITY_ID, 2); + add_tag(&p2_tags, ENTITY_ID, 3); + add_tag(&p1_tags, CONTROLLER, 1); + add_tag(&p2_tags, CONTROLLER, 2); + add_game_entity(&ge1, p1_tags, 2); + add_game_entity(&ge2, p2_tags, 3); + + struct hs_holder_s *holder; + struct deck_s *deck; + holder = c->data; + + add_player(&players, 1, 0x200000257544347, holder->deck->bnet_hi, 0, ge1); + add_player(&players, 2, 0x200000257544347, holder->opponent.deck->bnet_hi, 0, ge2); + + //add_player(&players, 1, 0x200000257544347, 0x4ab3967, 0, ge1); + //add_player(&players, 2, 0x200000257544347, 0x49E8Eb5, 0, ge2); + + ent_game = find_entity("GAME_ENTITY", 11); + game_tags = default_tags(NULL, ent_game, 0); + add_tag(&game_tags, ENTITY_ID, 1); + add_game_entity(&ge_main, game_tags, 1); + + add_game_start(&game_start, ge_main, players); + + add_ph_data(&data, NULL, game_start); + + //prepare_decks(c); + //setup_cards(c); + + + assert(holder->deck != holder->opponent.deck); + + ent_nocard = find_entity("NO_CARD", 7); + assert(ent_nocard); + + deck = holder->deck; + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) { + continue; + } + + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) { + assert(deck->cards[i]->entity); + card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0); + add_tag(&card_tags, ZONE, ZONE_HAND); + add_tag(&card_tags, ZONE_POSITION, deck->cards[i]->zone_position); + } else { + card_tags = default_tags(NULL, ent_nocard, 0); + } + + add_tag(&card_tags, CONTROLLER, deck->controller); + add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id); + + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) { + add_full_entity(&full, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + } else { + add_full_entity(&full, card_tags, deck->cards[i]->id, NULL, 0); + } + + if(deck->cards[i]->id == 68) { + mana_card = full; + } else { + add_ph_data(&data, full, NULL); + } + } + + deck = holder->opponent.deck; + + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) { + continue; + } + + card_tags = NULL; + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) { + add_tag(&card_tags, ZONE, ZONE_HAND); + add_tag(&card_tags, ZONE_POSITION, deck->cards[i]->zone_position); + } else { + add_tag(&card_tags, ZONE, ZONE_DECK); + } + add_tag(&card_tags, CONTROLLER, deck->controller); + add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id); + + add_full_entity(&full, card_tags, deck->cards[i]->id, NULL, 0); + + if(deck->cards[i]->id == 68) { + mana_card = full; + } else { + add_ph_data(&data, full, NULL); + } + } + + deck = holder->deck; + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) { + card_tags = NULL; + card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0); + add_tag(&card_tags, CONTROLLER, deck->controller); + add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id); + add_tag(&card_tags, ZONE, 1); + + if(flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) add_tag(&card_tags, CREATOR, deck->hero->id); + + add_full_entity(&full, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data(&data, full, NULL); + } + + } + + deck = holder->opponent.deck; + for(i = 0; i < deck->ncards; i++) { + if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) { + card_tags = NULL; + card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0); + add_tag(&card_tags, CONTROLLER, deck->controller); + add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id); + add_tag(&card_tags, ZONE, 1); + + if(flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) add_tag(&card_tags, CREATOR, deck->hero->id); + + add_full_entity(&full, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname); + add_ph_data(&data, full, NULL); + } + + } + + /* + ent_nocard = find_entity("HERO_08", 7); + card_tags = default_tags(ent_nocard); + add_tag(&card_tags, CONTROLLER, 1); + add_tag(&card_tags, ENTITY_ID, 64); + add_full_entity(&full, card_tags, 64, "TU4e_001", 8); + add_ph_data(&data, full, NULL); + + ent_nocard = find_entity("HERO_09", 7); + card_tags = default_tags(ent_nocard); + add_tag(&card_tags, CONTROLLER, 2); + add_tag(&card_tags, ENTITY_ID, 66); + add_full_entity(&full, card_tags, 66, "HERO_09", 7); + add_ph_data(&data, full, NULL); + */ + + /* + ent_nocard = find_entity("CS2_034", 7); + card_tags = default_tags(ent_nocard); + add_tag(&card_tags, CONTROLLER, 1); + add_tag(&card_tags, ENTITY_ID, 65); + add_full_entity(&full, card_tags, 65, "CS2_034", 7); + add_ph_data(&data, full, NULL); + + ent_nocard = find_entity("CS1h_001", 8); + card_tags = default_tags(ent_nocard); + add_tag(&card_tags, CONTROLLER, 2); + add_tag(&card_tags, ENTITY_ID, 67); + add_full_entity(&full, card_tags, 67, "CS1h_001", 8); + add_ph_data(&data, full, NULL); + */ + + /* + ent_nocard = find_entity("GAME_005", 8); + card_tags = default_tags(ent_nocard); + add_tag(&card_tags, CONTROLLER, 1); + add_tag(&card_tags, ENTITY_ID, 68); + + + if(holder->id == 1) { + add_tag(&card_tags, CREATOR, 1); + add_tag(&card_tags, CARDTYPE, 5); + add_full_entity(&full, card_tags, 68, "GAME_005", 8); + } else { + add_full_entity(&full, card_tags, 68, NULL, 0); + } + add_ph_data(&data, full, NULL); + */ + + add_ph_data(&data, mana_card, NULL); + + add_ph(&ph, data); + add_packet(&p, ph, P_POWERHISTORY); + + powerhistory_dump(ph); + + ptr = out; + int n = serialize(p, &ptr, ptr + sizeof(out)); + packet_free(p); + + data = NULL; + ph = NULL; + add_tagschange(&data, ent_game, 1); + add_tagchange(&data, STEP, 4, 1); + + add_tagschange(&data, ent1, 2); + add_tagchange(&data, CONTROLLER, 1, 2); + add_tagchange(&data, MULLIGAN_STATE, 1, 2); + + add_tagschange(&data, ent2, 3); + add_tagchange(&data, CONTROLLER, 2, 3); + + add_powerstart(&data, 5, -1, 1, 0, NULL, 0); + + add_ph(&ph, data); + add_packet(&p1, ph, P_POWERHISTORY); + + ptr = out + n; + int n1 = serialize(p1, &ptr, ptr + sizeof(out) - n); + packet_free(p1); + + struct entitychoices_s *ec; + ec = prepare_choices(holder->deck, holder->id); + add_packet(&p1, ec, P_ENTITYCHOICES); + + ptr = out + n + n1; + int n2 = serialize(p1, &ptr, ptr + sizeof(out) - n - n1); + packet_free(p1); + + //bin_dump(ptr - n2, n2); + + if(holder->id == 1) { + ec = prepare_choices(holder->opponent.deck, 2); + } else { + ec = prepare_choices(holder->opponent.deck, 1); + } + add_packet(&p1, ec, P_ENTITYCHOICES); + ptr = out + n + n1 + n2; + int n3 = serialize(p1, &ptr, ptr + sizeof(out) - n - n1 - n2); + packet_free(p1); + + //bin_dump(ptr - n3, n3); + const char common[19] = { 0x13, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x09, 0x22, 0x07, 0x08, 0x03, 0x10, 0xb1, 0x02, 0x18, 0x01 }; + memcpy(out + n + n1 + n2 + n3, common, sizeof(common)); + + hm_send(c, out, (int)(n + n1 + n2 + n3 + sizeof(common))); + + return 0; +} diff --git a/hm_gameserver/src/hs.c b/hm_gameserver/src/hs.c new file mode 100644 index 0000000..771e6db --- /dev/null +++ b/hm_gameserver/src/hs.c @@ -0,0 +1,346 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include + +enum board_e { + BOARD_RANDOM = 0x0c, +}; + +extern struct ht_s **games; + +int ping(struct conn_client_s *c) +{ + struct packet_s *p; + char output[512], *ptr; + int len; + + ptr = output; + p = packet_init(P_PONG, NULL); + + len = serialize(p, &ptr, ptr + sizeof(output)); + + packet_free(p); + + hm_send(c, output, len); + + return 0; +} + +int game_setup(struct conn_client_s *p1, struct conn_client_s *p2, const int id) +{ + struct gamesetup_s *g; + struct packet_s *p; + char output[512], *ptr; + int len; + + ptr = output; + g = malloc(sizeof(*g)); + + int rand = random_number(12); + // board indexes 0 and 9 not supported + g->board = (rand == 0 || rand == 9) ? 1 : rand; + g->maxsecrets = 5; + g->maxfriendlyminions = 7; + g->keepalive = 900; + g->stuckdisconnect = 25; + + p = packet_init(P_GAMESETUP, g); + + len = serialize(p, &ptr, ptr + sizeof(output)); + + packet_free(p); + + hm_log(LOG_DEBUG, p1->log, "starting game %d", id); + + assert(p1->data == NULL && p2->data == NULL); + + append_decks(p1, p2); + + hm_send(p1, output, len); + hm_send(p2, output, len); + + return 0; +} + +static void retrieve_deck_cb(struct cbop_s *cbop) +{ + struct watcher_s *w = cbop->data; + int cards_count = 0; + const char *hp = NULL; + + if(cbop->lcb_error == LCB_SUCCESS) { + json_tokener *tok; + struct json_object *obj; + int i; + struct player_deck_s *pd = NULL; + + tok = json_tokener_new(); + obj = json_tokener_parse_ex(tok, CBGR(bytes), CBGR(nbytes)); + + json_object_object_foreach(obj, key, val) { + if(strcmp(key, "hero") == 0) { + int type = json_object_get_type(val); + if(type == json_type_string) { + } + } else if(strcmp(key, "hp") == 0) { + int type = json_object_get_type(val); + if(type == json_type_string) { + hp = json_object_get_string(val); + } + } else if(strcmp(key, "cards") == 0) { + int type = json_object_get_type(val); + if(type == json_type_array) { + int l = json_object_array_length(val); + + for(i = 0; i < l; i++) { + struct player_deck_s *pdc = malloc(sizeof(*pdc)); + pdc->next = pd; + pd = pdc; + + json_object *o = json_object_array_get_idx(val, i); + int subtype = json_object_get_type(o); + if(subtype == json_type_object) { + json_object *code; + json_object_object_get_ex(o, "code", &code); + if(json_object_get_type(code) == json_type_string) { + snprintf(pdc->code, sizeof(pdc->code), "%s", json_object_get_string(code)); + } + + json_object *count; + json_object_object_get_ex(o, "count", &count); + if(json_object_get_type(count) == json_type_int) { + pdc->count = json_object_get_int(count); + cards_count += pdc->count; + } + } + } + } + } + } + + + char key1[128], key2[128]; + snprintf(key1, sizeof(key1), "u:deck_%s_%s", MOD_URL, w->p1->hbs_id); + snprintf(key2, sizeof(key2), "u:deck_%s_%s", MOD_URL, w->p2->hbs_id); + + assert(hp); + + if(CBGR(nkey) == strlen(key1) && memcmp(key1, CBGR(key), strlen(key1)) == 0 && !(w->p1->cards)) { + hm_log(LOG_DEBUG, lg, "Player1 deck: %d", cards_count); + w->p1->cards = pd; + w->p1->ncards = cards_count; + snprintf(w->p1->hp, sizeof(w->p1->hp), "%s", hp); + //snprintf(w->p1->hero, sizeof(w->p1->hero), "%s", hero); + } else if(CBGR(nkey) == strlen(key2) && memcmp(key2, CBGR(key), strlen(key2)) == 0 && !(w->p2->cards)) { + hm_log(LOG_DEBUG, lg, "Player2 deck: %d", cards_count); + w->p2->cards = pd; + w->p2->ncards = cards_count; + snprintf(w->p2->hp, sizeof(w->p2->hp), "%s", hp); + //snprintf(w->p2->hero, sizeof(w->p2->hero), "%s", hero); + } else { + abort(); + } + + json_object_put(obj); + json_tokener_free(tok); + } else { + hm_log(LOG_DEBUG, lg, "Couchbase key [%.*s] failed with error 0x%x", (int)CBGR(nkey), (char *)CBGR(key), cbop->lcb_error); + } + + if(++(w->counter) == 2) { + //assert(w->p1->cards && w->p2->cards); + //assert(w->p1->ncards != 0); + //assert(w->p2->ncards != 0); + if(w->p1->cards == NULL || w->p2->cards == NULL || + w->p1->ncards != 30 || w->p2->ncards != 30) { + hm_log(LOG_DEBUG, lg, "Droping both players as deck1: %p:%d deck2: %p:%d", w->p1->cards, w->p1->ncards, w->p2->cards, w->p2->ncards); + async_shutdown_client(w->p1); + async_shutdown_client(w->p2); + //FIXME: memory leak if any of the players has deck allocated + } else { + + hm_log(LOG_DEBUG, lg, "Retrieved deck(30 cards) for both players"); + game_setup(w->p1, w->p2, 0); + } + free(w); + } + + free(cbop); +} + +void retrieve_deck(struct watcher_s *w, int player) +{ + struct cbop_s *cbop; + char key[128]; + char *k; + + cbop = malloc(sizeof(*cbop)); + + memset(cbop, 0, sizeof(*cbop)); + + cbop->data = w; + + if(player == 0) { + k = w->p1->hbs_id; + } else { + k = w->p2->hbs_id; + } + + snprintf(key, sizeof(key), "u:deck_%s_%s", MOD_URL, k); + + hm_log(LOG_DEBUG, lg, "Retrieving deck for player: %d", player); + + CBGQ_V0(0, key, strlen(key), retrieve_deck_cb, 0, 0) +} + + +void get_decks(struct conn_client_s *p1, struct conn_client_s *p2, const int id) +{ + struct watcher_s *watcher; + int i; + + watcher = malloc(sizeof(*watcher)); + + watcher->p1 = p1; + watcher->p2 = p2; + watcher->counter = 0; + watcher->target = 2; + + for(i = 0; i < 2; i++) { + retrieve_deck(watcher, i); + } +} + +void find_game(struct conn_client_s *p1, struct handshake_s *h) +{ + char key[32]; + struct ht_s *opponent; + struct conn_client_s *p2; + int n, k; + + handshake_dump(h); + + // client id + snprintf(p1->hbs_id, sizeof(p1->hbs_id), "%.*s", h->nversion, h->version); + + k = *(int *)h->password; + n = snprintf(key, sizeof(key), "%d", k); + + opponent = ht_get(games, key, strlen(key)); + + if(opponent == NULL) { + HT_ADD_WA(games, key, n, p1, sizeof(p1), p1->pool); + } else { + p2 = (struct conn_client_s *)(opponent->s); + HT_REM(games, key, n, p1->pool); + + // bind clients + snprintf(p1->foreign_client_index, sizeof(p1->foreign_client_index), "%s", p2->client_index); + snprintf(p2->foreign_client_index, sizeof(p2->foreign_client_index), "%s", p1->client_index); + + get_decks(p1, p2, k); + } +} + +void hs(struct conn_client_s *c, const char *buf, const int len) +{ + int l = 8; + struct packet_s *p; + char *ptr, *next = NULL; + int player = 0; + struct hs_holder_s *pd; + struct ht_s *opponent; + + ptr = (char *)buf; + + if(len > 8) { + l += *(int *)(buf + 4); + } + + if(l < len) { + next = (char *)buf + l; + } + + p = deserialize(&ptr, ptr + l); + if(p == NULL) { + hm_log(LOG_DEBUG, lg, "Parsing %d bytes from fd %d failed, removing client", len, c->fd); + async_shutdown_client(c); + return; + } + + if(c->data) { + pd = c->data; + player = pd->entity_id; + } + + if(strlen(c->foreign_client_index) > 0) { + opponent = ht_get(async_clients, c->foreign_client_index, strlen(c->foreign_client_index)); + if(opponent) { + + hm_log(LOG_DEBUG, lg, "Opponent found for fd %d", c->fd); + if(opponent->n != sizeof(void *) || (void *)opponent->s != pd->opponent.client) { + abort(); + } + } else { + hm_log(LOG_DEBUG, lg, "Opponent not found for fd %d, exitting", c->fd); + packet_free(p); + memset(&pd->opponent, 0, sizeof(pd->opponent)); + async_shutdown_client(c); + return; + } + } else { + hm_log(LOG_DEBUG, lg, "Foreign client not specified for client fd %d", c->fd); + //async_shutdown_client(c); + //return; + } + + if(p->id == P_PING) { + ping(c); + } else if(p->id == P_HANDSHAKE) { + find_game(c, p->data); + } else if(p->id == P_GETGAMESTATE) { + hm_log(LOG_DEBUG, lg, "Client command: gamestate player entity: %d", player); + game_start(c); + } else if(p->id == P_USERUI) { + hm_log(LOG_DEBUG, lg, "Client command: userui player entity: %d", player); + user_ui(c, p->data); + } else if(p->id == P_CHOOSEENTITIES) { + hm_log(LOG_ALERT, lg, "Client command: choose entities player entity: %d", player); + if(pd && pd->choose_one == 1) { + pd->choose_one = 0; + choose_one_entity(c, p->data); + } else { + choose_entities(c, p->data); + } + } else if(p->id == P_CHOOSEOPTION) { + chooseoption_dump(p->data, ((struct hs_holder_s *)(c->data))->held_card); + hm_log(LOG_DEBUG, lg, "Client command: choose option player entity: %d", player); + choose_option(c, p->data); + } else { + hm_log(LOG_DEBUG, lg, "Client command: unsupported command"); + async_shutdown_client(c); + return; + } + + if(p->id != P_USERUI) packet_free(p); + + if(next) { + hs(c, next, len - l); + } +} diff --git a/hm_gameserver/src/include/choose_entities.h b/hm_gameserver/src/include/choose_entities.h new file mode 100644 index 0000000..e4517c0 --- /dev/null +++ b/hm_gameserver/src/include/choose_entities.h @@ -0,0 +1,24 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CHOOSE_ENTITIES_H_ +#define CHOOSE_ENTITIES_H_ + +void choose_one_entity(struct conn_client_s *c, struct chooseentities_s *e); +void choose_entities(struct conn_client_s *c, struct chooseentities_s *e); + +#endif diff --git a/hm_gameserver/src/include/choose_option.h b/hm_gameserver/src/include/choose_option.h new file mode 100644 index 0000000..8a1da99 --- /dev/null +++ b/hm_gameserver/src/include/choose_option.h @@ -0,0 +1,23 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CHOOSE_OPTION_H_ +#define CHOOSE_OPTION_H_ + +int choose_option(struct conn_client_s *c, struct chooseoption_s *opt); + +#endif diff --git a/hm_gameserver/src/include/common.h b/hm_gameserver/src/include/common.h new file mode 100644 index 0000000..901594f --- /dev/null +++ b/hm_gameserver/src/include/common.h @@ -0,0 +1,50 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef COMMON_H_ +#define COMMON_H_ + +const struct ent_s *find_entity(const char *name, const int nname); +struct powerhistory_tag_s *add_tag(struct powerhistory_tag_s **dst, const int key, const int value); +struct powerhistory_game_entity_s *add_game_entity(struct powerhistory_game_entity_s **dst, struct powerhistory_tag_s *tag, const int id); +struct powerhistory_tag_s *default_tags(struct card_s *card, const struct ent_s *ent, int zone_override); +void add_tagchange(struct powerhistory_data_s **dst, u64 key, u64 value, u64 id); +void add_powerstart(struct powerhistory_data_s **dst, u64 type, u64 index, u64 source, u64 target, char *card_id, int ncard_id); +void add_tagschange(struct powerhistory_data_s **dst, const struct ent_s *ent, u64 id); +void add_player(struct powerhistory_player_s **dst, u64 id, u64 bhi, u64 blo, u64 cardback, struct powerhistory_game_entity_s *ent); +void add_game_start(struct powerhistory_creategame_s **dst, struct powerhistory_game_entity_s *ge, struct powerhistory_player_s *p); +void add_ph_data(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full, struct powerhistory_creategame_s *cg); +void add_ph_data(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full, struct powerhistory_creategame_s *cg); +void add_ph(struct powerhistory_s **dst, struct powerhistory_data_s *data); +void add_packet(struct packet_s **dst, void *ph, enum packet_e n); +void add_hide(struct powerhistory_data_s **dst, u64 entity, u64 zone); +void add_powerend(struct powerhistory_data_s **dst); +void add_full_entity(struct powerhistory_entity_s **full, struct powerhistory_tag_s *tags, u64 id, const char *name, const int nname); +void add_ph_data_show(struct powerhistory_data_s **dst, struct powerhistory_entity_s *show); +void add_meta(struct powerhistory_data_s **dst, u64 type, u64 d, u64 infoid); +void add_info(struct powerhistory_info_s **dst, u64 infoid); +void add_meta_info(struct powerhistory_data_s **dst, u64 type, u64 d, struct powerhistory_info_s *info); +void add_ph_data_full(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full); + +void bin_dump(char *buf, const int len); +int random_number(int max); +void register_turntimer(struct conn_client_s *c); + +extern struct ht_s **clients; +extern struct ev_loop *loop; + +#endif diff --git a/hm_gameserver/src/include/deck.h b/hm_gameserver/src/include/deck.h new file mode 100644 index 0000000..6173ff4 --- /dev/null +++ b/hm_gameserver/src/include/deck.h @@ -0,0 +1,270 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef DECK_H_ +#define DECK_H_ + +#define DECK_INIT 0x1 + +#define G_P1_CARDS_CHOSEN 0x1 +#define G_P2_CARDS_CHOSEN 0x2 + +#define MAX_BOSS 2 +#define MAX_BOARD 7 + +#define LIST_ADD(list__, item__, src__)\ + item__ = malloc(sizeof(*item__));\ +item__->card = src__;\ +item__->next = NULL;\ +if(list__ != NULL && (list__)->tail) {\ + (list__)->tail->next = item__;\ + (list__)->tail = item__;\ +} else {\ + (list__) = item__;\ + (list__)->tail = item__;\ +} + +#define LIST_ADD_LINK(list__, src__)\ + list__ = src__; + +enum deck_mod_e { + DECK_MODIFIER_ATTACK = 1, + DECK_MODIFIER_HEALTH, + DECK_MODIFIER_ATTACK_CHARGE, + DECK_MODIFIER_ATTACK_BEAST, +}; + +enum deck_free_e { + FREE_DECK_ATTACHMENT = (1<<1), + FREE_CARD_CHILDREN = (1<<2), + FREE_CARD_EXPIRE = (1<<3), +}; + +struct card_expire_s { + int turn; + int attack; + int frozen; + int destroy; + int magic_immunity; + const char *attachment; + + struct card_expire_s *next; +}; + +struct attachment_list_s { + const char *name; + enum flags_e group; + struct attachment_list_s *next; +}; + +struct card_link_s { + int id; + const char *name; + struct card_link_s *next, *tail; +}; + +struct card_s { + struct hs_holder_s *parent; + + int controller; + int id; + struct flags_s state; + + const char *attachment; // name of CARD_ATTACHMENT + int attached_to; // only for CARD_ATTACHMENT + struct card_link_s *attached_children; // children + + const struct ent_s *entity; + int zone_position; + + int total_health; + int health; + int default_health; + int buff_health; + + int attack; + int default_attack; + + int cost; + int default_cost; + + int cardtype; + int durability; + int maxdurability; + int armor; + int actions_number; + int spellpower; + + struct { + unsigned int flags; + + struct card_list_s *card; + } target; + + struct { + int damage; + int heal; + } receive; + + struct { + char level; + int experience; + } boss; + + int linked; + + struct card_expire_s *expire; + + int priority_override; + int total_plays; // total number of plays with this card, zero'd when returned to hand + int turn_plays; // total number of plays since turn started +}; + +struct deck_s { + struct hs_holder_s *parent; + + u64 bnet_hi; + int controller; + + int mana; + int mana_used; + int spellpower; + + int handposition; + int ncards; + struct card_s **cards; + + struct { + int attack; + int attack_charge; + int attack_beast; + int health; + } modifiers; + + + struct card_s *hero; + struct card_s *heropower; + struct card_s *heroweapon; + + int board_position[MAX_BOARD]; + struct attachment_list_s *attachments; + + int fatigue; + int gameover; + unsigned int flags; +}; + +struct card_list_s { + struct card_s *card; + struct card_list_s *tail, *next; +}; + +struct game_s { + int entity_id; + unsigned int flags; + int turn; + int maxentity_id; + + struct ev_timer turntimer, force_next_turn; +}; + +struct hs_holder_s { + struct conn_client_s *client; + + struct deck_s *deck; + struct deck_s *deck_copy; + int id; + int entity_id; + int held_card; + int arroworigin; + int choose_one; + + struct { + int accessible; + struct deck_s *deck; + struct deck_s *deck_copy; + struct conn_client_s *client; + } opponent; + + struct game_s *game; + + unsigned int flags; +}; + +void holder_free(struct hs_holder_s *h); +int append_decks(struct conn_client_s *p1, struct conn_client_s *p2); +int append_game(struct conn_client_s *p1, struct conn_client_s *p2); +void card_to_deck(struct card_s *card); +struct card_s *draw_random_card(struct deck_s *deck, int entity_id, int zone_position); +struct card_s *new_card(const int id, const char *name, int controller); +void card_used_reorder(struct deck_s *deck, u64 id); +void cards_reorder_board_opponent(struct powerhistory_data_s **data, struct deck_s *deck); +void cards_reorder_board_owner(struct deck_s *deck, u64 held, u64 position); +struct card_s *card_get(struct deck_s *deck, struct deck_s *opponent, const int id); +struct card_list_s *cards_get_board(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude, int magic_immunity, int boss); +struct card_s *card_get_hero(struct deck_s *deck); +void cards_reorder_hand_owner(struct deck_s *deck, u64 id); +void cards_reorder_hand_opponent(struct powerhistory_data_s **data, struct deck_s *deck); +void cards_board_destroyed_reorder(struct deck_s *deck, int position); +int game_attack(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender); +int update_resources(struct deck_s *deck, struct card_s *attacker, int refresh); +void cards_unset_flag(struct deck_s *deck, enum flags_e flags); +void card_set_exhausted(struct card_s *card); +int cards_board_last(struct deck_s *deck); +struct card_s *add_new_card(struct game_s *game, struct deck_s *deck, int index, const char *card, unsigned int flags); +int zone_position_last(struct deck_s *deck); +void unset_mechanics_flags(struct hs_holder_s *p); +void cards_reorder(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, u64 position, int summoned); +int cards_get_board_count(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude); +void decks_copy(struct hs_holder_s *p); +void decks_swap(struct hs_holder_s *p); +void deck_modifier(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, enum deck_mod_e key, int value); +void deck_apply_modifiers(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, u64 position); +void card_destroy(struct card_s *card, struct deck_s *deck, int to_hand); +void deck_destroy_modifier(struct deck_s *deck, struct card_s *defender); +struct card_s *cards_get_hand_random(struct deck_s *deck); +void copy_card(struct card_s **dst, struct card_s *src); +struct card_list_s *cards_get_random(struct deck_s *deck, int number, struct card_s *attacker, int zone); +int cards_get_board_count_flag(struct deck_s *deck, struct card_s *card, int f); +int cards_get_board_flag(struct deck_s *deck, int f, int exclude); +void card_apply_attachments(struct hs_holder_s *p, struct deck_s *deck, struct card_s *card); +void deck_add_attachment(struct deck_s *deck, const char *attachment, enum flags_e f); +void cards_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, enum flags_e f); +int card_count_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name); +void add_single_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, struct card_s *defender); +void card_remove_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name); +struct card_s *card_get_board_zoneposition(struct deck_s *deck, u64 position); +void card_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst, const char *attachment); +void cards_adjacent(struct hs_holder_s *p, struct deck_s *deck); +int deck_get_taunts(struct deck_s *deck); +void card_discard_by_name(struct hs_holder_s *p, struct card_s *card, const char *name); +struct card_s *card_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f); +struct card_list_s *cards_get_board_boss(struct deck_s *deck); +void reset_turn_plays(struct deck_s *deck); +void card_free(struct card_s *card, unsigned int flags); +int card_deck_count(struct deck_s *deck); +void deck_free(struct deck_s *deck, unsigned int flags); +struct card_s *card_get_levelup_boss(struct deck_s *deck, struct card_s *card); +int cards_count(struct card_list_s *l); +struct card_s *card_random(struct card_list_s *l); +struct card_s *draw_first_boss(struct deck_s *deck); +struct card_list_s *cards_get_hand(struct deck_s *deck); +int board_count_by_name(struct deck_s *deck, const char *name); +void cards_dump(struct deck_s *deck, struct deck_s *opponent); +struct card_list_s *cards_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f); + +#endif diff --git a/hm_gameserver/src/include/entity_choices.h b/hm_gameserver/src/include/entity_choices.h new file mode 100644 index 0000000..16d6471 --- /dev/null +++ b/hm_gameserver/src/include/entity_choices.h @@ -0,0 +1,24 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ENTITY_CHOICES_H_ +#define ENTITY_CHOICES_H_ + +struct entitychoices_s *prepare_choices(struct deck_s *deck, int player_id); +struct entitychoices_s *chooseone_choices(struct card_list_s *defenders, int player_id, int attacker_id); + +#endif diff --git a/hm_gameserver/src/include/flags.h b/hm_gameserver/src/include/flags.h new file mode 100644 index 0000000..48f9b7c --- /dev/null +++ b/hm_gameserver/src/include/flags.h @@ -0,0 +1,56 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef FLAGS_H_ +#define FLAGS_H_ + +#define MAX_FLAGS_ARRAY 16 +#define LL_BITS 64 + +enum flag_type_e { + F_ADDED = 1, + F_REMOVED = 2, +}; + +struct flag_pr_s { + enum flags_e flag; + int priority; + enum flag_type_e type; + struct card_s *parent_card; +}; + +// 64 * MAX_FLAGS_ARRAY flags +struct flags_s { + unsigned long long nibble[MAX_FLAGS_ARRAY]; +}; + +enum flags_action_e { + FLAG_SET = 0, + FLAG_UNSET = 1, + FLAG_ISSET = 2, + FLAG_DUMP = 3, +}; + +int flag(struct flags_s *flags, enum flags_e src, enum flags_action_e action); +int flags_copy(struct flags_s *dst, const struct flags_s *src); +void flags_diff(struct flags_s *old, struct flags_s *new, + struct flag_pr_s ***src_added, int *nsrc_added, + struct flag_pr_s ***src_removed, int *nsrc_removed, + struct card_s *parent_card); +int flag_get(struct flags_s *flags, int **f); + +#endif diff --git a/hm_gameserver/src/include/game.h b/hm_gameserver/src/include/game.h new file mode 100644 index 0000000..ee5243f --- /dev/null +++ b/hm_gameserver/src/include/game.h @@ -0,0 +1,67 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef GAME_H_ +#define GAME_H_ + +#define LOG_MECHANICS "{Mechanics}: " + +#define HM_GAMESERVER + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct packet_s *game_reply(struct hs_holder_s *p, struct chooseoption_s *opt, struct card_s *attacker, int player); +int game_attack_aoe(struct hs_holder_s *p, struct card_s *attacker, struct card_list_s *defenders, struct card_s **fake_levelup); +void user_ui(struct conn_client_s *c, struct userui_s *u); +int game(struct conn_client_s *c, struct chooseoption_s *opt); +void game_free(struct game_s *g); +void next_turn(struct conn_client_s *c, struct hs_holder_s *p/*, struct chooseoption_s *opt*/); +void mechanics_attack(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s *defenders); +void mechanics_next_turn(struct conn_client_s *c, struct hs_holder_s *p); +void mechanics_put_card_onboard(struct conn_client_s *c, u64 position, struct card_s *attacker, int summoned, struct card_list_s **defenders, struct chooseoption_s *opt, struct deck_s *deck); +void mechanics_attack_aoe(struct conn_client_s *c, u64 position, struct card_s *attacker, struct card_list_s **defenders, struct card_s **fake_levelup); +void mechanics_buff(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **defenders); +void mechanics_summon(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **defenders); +void mechanics_draw_card(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, int cards, struct card_list_s **defenders); +void mechanics_expire(int game_turn, struct card_s *card, enum expire_e key, int value, const char *name); +void force_expire(struct hs_holder_s *p, struct deck_s *deck, struct card_s *card); +void mechanics_attack_swipe(struct conn_client_s *c, u64 position, struct card_s *attacker, struct card_list_s **defenders); +int entity_attack(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender); +void put_card_onboard(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt); +void power_attack(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt); + +extern struct hm_log_s *lg; + +#endif diff --git a/hm_gameserver/src/include/game_options.h b/hm_gameserver/src/include/game_options.h new file mode 100644 index 0000000..77377c3 --- /dev/null +++ b/hm_gameserver/src/include/game_options.h @@ -0,0 +1,24 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef GAME_OPTIONS_H_ +#define GAME_OPTIONS_H_ + +int set_options(struct deck_s *deck, struct deck_s *opponent, char *buffer, char *endbuffer, int turn); +int set_options_cards(struct card_list_s *cl, char *buffer, char *endbuffer, int turn); + +#endif diff --git a/hm_gameserver/src/include/hs.h b/hm_gameserver/src/include/hs.h new file mode 100644 index 0000000..3420061 --- /dev/null +++ b/hm_gameserver/src/include/hs.h @@ -0,0 +1,25 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef HS_H_ +#define HS_H_ + +void hs(struct conn_client_s *c, const char *buf, const int len); +int game_start(struct conn_client_s *c); +void handshake_dump(struct handshake_s *h); + +#endif diff --git a/hm_gameserver/src/include/hsl_cardname.h b/hm_gameserver/src/include/hsl_cardname.h new file mode 100644 index 0000000..2518a48 --- /dev/null +++ b/hm_gameserver/src/include/hsl_cardname.h @@ -0,0 +1,57 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CARDNAME_H_ +#define CARDNAME_H_ + +#define CN_BOAR "CS2_boar" +#define CN_VULTURE "CS2_237" +#define CN_BLACK_HOLE "EX1_312" +#define CN_DEMONIC_CONVERSION "OG_101" +#define CN_EIDOLON "AT_023" +#define CN_COUNTER_HELIX "EX1_400" +#define CN_CULLING_BLADE "CS2_108" +#define CN_WARCRY "NEW1_036" +#define CN_GODS_WRATH "EX1_259" +#define CN_FORKED_LIGHTNING "EX1_251" +#define CN_DRAGONS_BREATH "BRM_003" +#define CN_ENRAGE "CS2_011" +#define CN_REQUIEM_OF_SOULS "EX1_303" +#define CN_SHADOW_FIEND "CS2_118" +#define CN_NECROMASTERY "EX1_596e" +#define CN_LAGUNA_BLADE "AT_001" +#define CN_WOUNDED "AT_039e" +#define CN_SWIPES "CS2_012" +#define CN_GODS_STRENGTH "OG_223" +#define CN_URSA "EX1_165t2" +#define CN_SVEN "EX1_383" +#define CN_ECHO_SABRE "LOE_118" +#define CN_DIVINE_RAPIER "CS2_097" +#define CN_DIVINE_RAPIER_BONUS "FP1_020e" +#define CN_LINA "AT_018" +#define CN_ZEUS "EX1_559" +#define CN_ENIGMA "CS2_065" +#define CN_AXE "NEW1_011" +#define CN_STORMWIND_CHAMP "CS2_222" +#define CN_STORMWIND_CHAMP_BONUS "CS2_222o" +#define CN_SKELETON "NAX4_03H" +#define CN_TINY "EX1_105" +#define CN_WISP_BONUS "NAX12_04e" +#define CN_WISP "CS2_231" +#define CN_DESOLATOR_BONUS "LOEA06_03e" + +#endif diff --git a/hm_gameserver/src/include/level.h b/hm_gameserver/src/include/level.h new file mode 100644 index 0000000..6883659 --- /dev/null +++ b/hm_gameserver/src/include/level.h @@ -0,0 +1,25 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef LEVEL_H_ +#define LEVEL_H_ + +#define LEVEL_1 "CS2_103e2" +#define LEVEL_2 "EX1_178ae" +#define LEVEL_3 "CS1_129e" + +#endif diff --git a/hm_gameserver/src/include/mechanics.h b/hm_gameserver/src/include/mechanics.h new file mode 100644 index 0000000..41446f5 --- /dev/null +++ b/hm_gameserver/src/include/mechanics.h @@ -0,0 +1,32 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef MECHANICS_H_ +#define MECHANICS_H_ + +enum expire_e { + EXPIRE_ATTACK = 1, + EXPIRE_FROZEN = 2, + EXPIRE_DESTROY = 3, + EXPIRE_ATTACHMENT = 4, + EXPIRE_MAGIC_IMMUNITY = 5, +}; + +void mechanics_expire(int game_turn, struct card_s *card, enum expire_e key, int value, const char *attachment); +void mechanics_expired(struct hs_holder_s *p, struct deck_s *deck); + +#endif diff --git a/hm_gameserver/src/include/net.h b/hm_gameserver/src/include/net.h new file mode 100644 index 0000000..495b31e --- /dev/null +++ b/hm_gameserver/src/include/net.h @@ -0,0 +1,47 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef NET_H_ +#define NET_H_ + +enum nettype_e { + NET_BUFF = 1, + NET_BUFFAOE, + NET_PUTONBOARD, + NET_ATTACK, + NET_SPELL, + NET_SPELLAOE, + NET_NEXTTURN, + NET_SPELLHP_DAMAGE, +}; + +void net_card_flags(struct powerhistory_data_s **data, struct deck_s *deck_old, struct deck_s *deck_new, + struct deck_s *opp_old, struct deck_s *opp_new, struct card_list_s *src, struct hs_holder_s *p, int target_player, int nettype); +struct packet_s *net_attack(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_s *defender, int target_player); +int net_send(struct conn_client_s *c, struct packet_s *packet); +int net_send_options(struct conn_client_s *c, struct deck_s *deck, struct deck_s *opponent, int turn); +int net_send_cl_options(struct conn_client_s *c, struct card_list_s *cl, int turn); +struct packet_s *net_next_turn(struct conn_client_s *c, struct card_s **drawn_card, int *zoneposition); +struct packet_s *net_card_onboard(struct hs_holder_s *p, struct chooseoption_s *opt, struct card_s *attacker, int player); +struct packet_s *net_spell_aoe(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker); +struct packet_s *net_buff(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders); +struct packet_s *net_spell(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders, struct card_s *fake_levelup); +struct packet_s *net_spell_hp_damage(struct conn_client_s *c, struct card_list_s *defenders, struct card_s *attacker); +void net_send_turntimer(struct conn_client_s *c, int seconds, int turn, int show); +struct packet_s *net_game_over(struct hs_holder_s *p, int loser); + +#endif diff --git a/hm_gameserver/src/include/proto/chooseentities.h b/hm_gameserver/src/include/proto/chooseentities.h new file mode 100644 index 0000000..b135e0f --- /dev/null +++ b/hm_gameserver/src/include/proto/chooseentities.h @@ -0,0 +1,35 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CHOOSEENTITIES_H_ +#define CHOOSEENTITIES_H_ + +struct chooseentities_ent_s { + u64 entity; + struct chooseentities_ent_s *next; +}; + +struct chooseentities_s { + u64 id; + int nentity; + struct chooseentities_ent_s *entity; +}; + +void chooseentities_free(struct chooseentities_s *c); +void *chooseentities_deserialize(char **dst, const char *maxdst); + +#endif diff --git a/hm_gameserver/src/include/proto/ent.h b/hm_gameserver/src/include/proto/ent.h new file mode 100644 index 0000000..ec2301c --- /dev/null +++ b/hm_gameserver/src/include/proto/ent.h @@ -0,0 +1,50 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ENT_S_ +#define ENT_S_ + +#include +#include + +#define MAX_PROPERTIES 16 + +struct ent_property_s { + int key; + int value; +}; + +struct ent_s { + const char *name; + int nname; + int nprop; + + const char *level2; + const char *level3; + + const char *desc; + + struct flags_s flags; + const char *attachment; + struct ent_property_s p[MAX_PROPERTIES]; +}; + +extern struct ent_s entities[MAX_ENTITIES]; +void entities_init(); +void entities_init2(); + +#endif diff --git a/hm_gameserver/src/include/proto/entitychoices.h b/hm_gameserver/src/include/proto/entitychoices.h new file mode 100644 index 0000000..acc9472 --- /dev/null +++ b/hm_gameserver/src/include/proto/entitychoices.h @@ -0,0 +1,42 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ENTITYCHOICES_H_ +#define ENTITYCHOICES_H_ + +struct entitychoices_entities_s { + u64 entity; + struct entitychoices_entities_s *next; +}; + +struct entitychoices_s { + u64 id; + u64 type; + u64 countmin; + u64 countmax; + + u64 source; + u64 player_id; + + struct entitychoices_entities_s *entities; +}; + +void entitychoices_free(struct entitychoices_s *ec); +int entitychoices_serialize(void *ep, char **dst, const char *maxdst); +void entitychoices_dump(struct entitychoices_s *es); + +#endif diff --git a/hm_gameserver/src/include/proto/gametag.h b/hm_gameserver/src/include/proto/gametag.h new file mode 100644 index 0000000..03f47dc --- /dev/null +++ b/hm_gameserver/src/include/proto/gametag.h @@ -0,0 +1,250 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef TAG_H_ +#define TAG_H_ + +enum gametag_e { + TAG_SCRIPT_DATA_NUM_1 = 2, + TAG_SCRIPT_DATA_NUM_2 = 3, + TAG_SCRIPT_DATA_ENT_1 = 4, + TAG_SCRIPT_DATA_ENT_2 = 5, + MISSION_EVENT = 6, + TIMEOUT = 7, + TURN_START = 8, + TURN_TIMER_SLUSH = 9, + PREMIUM = 12, + GOLD_REWARD_STATE = 13, + PLAYSTATE = 17, + LAST_AFFECTED_BY = 18, + STEP = 19, + TURN = 20, + FATIGUE = 22, + CURRENT_PLAYER = 23, + FIRST_PLAYER = 24, + RESOURCES_USED = 25, + RESOURCES = 26, + HERO_ENTITY = 27, + MAXHANDSIZE = 28, + STARTHANDSIZE = 29, + PLAYER_ID = 30, + TEAM_ID = 31, + TRIGGER_VISUAL = 32, + RECENTLY_ARRIVED = 33, + PROTECTING = 34, + PROTECTED = 35, + DEFENDING = 36, + PROPOSED_DEFENDER = 37, + ATTACKING = 38, + PROPOSED_ATTACKER = 39, + ATTACHED = 40, + EXHAUSTED = 43, + DAMAGE = 44, + HEALTH = 45, + ATK = 47, + COST = 48, + ZONE = 49, + CONTROLLER = 50, + OWNER = 51, + DEFINITION = 52, + ENTITY_ID = 53, + HISTORY_PROXY = 54, + COPY_DEATHRATTLE = 55, + ELITE = 114, + MAXRESOURCES = 176, + CARD_SET = 183, + CARDTEXT_INHAND = 184, + CARDNAME = 185, + CARD_ID = 186, + DURABILITY = 187, + SILENCED = 188, + WINDFURY = 189, + TAUNT = 190, + STEALTH = 191, + SPELLPOWER = 192, + DIVINE_SHIELD = 194, + CHARGE = 197, + NEXT_STEP = 198, + CLASS = 199, + CARDRACE = 200, + FACTION = 201, + CARDTYPE = 202, + RARITY = 203, + STATE = 204, + SUMMONED = 205, + FREEZE = 208, + ENRAGED = 212, + OVERLOAD = 215, + LOYALTY = 216, + DEATHRATTLE = 217, + BATTLECRY = 218, + SECRET = 219, + COMBO = 220, + CANT_HEAL = 221, + CANT_DAMAGE = 222, + CANT_SET_ASIDE = 223, + CANT_REMOVE_FROM_GAME = 224, + CANT_READY = 225, + CANT_EXHAUST = 226, + CANT_ATTACK = 227, + CANT_TARGET = 228, + CANT_DESTROY = 229, + CANT_DISCARD = 230, + CANT_PLAY = 231, + CANT_DRAW = 232, + INCOMING_HEALING_MULTIPLIER = 233, + INCOMING_HEALING_ADJUSTMENT = 234, + INCOMING_HEALING_CAP = 235, + INCOMING_DAMAGE_MULTIPLIER = 236, + INCOMING_DAMAGE_ADJUSTMENT = 237, + INCOMING_DAMAGE_CAP = 238, + CANT_BE_HEALED = 239, + CANT_BE_DAMAGED = 240, + CANT_BE_SET_ASIDE = 241, + CANT_BE_REMOVED_FROM_GAME = 242, + CANT_BE_READIED = 243, + CANT_BE_EXHAUSTED = 244, + CANT_BE_ATTACKED = 245, + CANT_BE_TARGETED = 246, + CANT_BE_DESTROYED = 247, + CANT_BE_SUMMONING_SICK = 253, + FROZEN = 260, + JUST_PLAYED = 261, + LINKEDCARD = 262, + ZONE_POSITION = 263, + CANT_BE_FROZEN = 264, + COMBO_ACTIVE = 266, + CARD_TARGET = 267, + NUM_CARDS_PLAYED_THIS_TURN = 269, + CANT_BE_TARGETED_BY_OPPONENTS = 270, + NUM_TURNS_IN_PLAY = 271, + NUM_TURNS_LEFT = 272, + OUTGOING_DAMAGE_CAP = 273, + OUTGOING_DAMAGE_ADJUSTMENT = 274, + OUTGOING_DAMAGE_MULTIPLIER = 275, + OUTGOING_HEALING_CAP = 276, + OUTGOING_HEALING_ADJUSTMENT = 277, + OUTGOING_HEALING_MULTIPLIER = 278, + INCOMING_ABILITY_DAMAGE_ADJUSTMENT = 279, + INCOMING_COMBAT_DAMAGE_ADJUSTMENT = 280, + OUTGOING_ABILITY_DAMAGE_ADJUSTMENT = 281, + OUTGOING_COMBAT_DAMAGE_ADJUSTMENT = 282, + OUTGOING_ABILITY_DAMAGE_MULTIPLIER = 283, + OUTGOING_ABILITY_DAMAGE_CAP = 284, + INCOMING_ABILITY_DAMAGE_MULTIPLIER = 285, + INCOMING_ABILITY_DAMAGE_CAP = 286, + OUTGOING_COMBAT_DAMAGE_MULTIPLIER = 287, + OUTGOING_COMBAT_DAMAGE_CAP = 288, + INCOMING_COMBAT_DAMAGE_MULTIPLIER = 289, + INCOMING_COMBAT_DAMAGE_CAP = 290, + CURRENT_SPELLPOWER = 291, + ARMOR = 292, + MORPH = 293, + IS_MORPHED = 294, + TEMP_RESOURCES = 295, + OVERLOAD_OWED = 296, + NUM_ATTACKS_THIS_TURN = 297, + NEXT_ALLY_BUFF = 302, + MAGNET = 303, + FIRST_CARD_PLAYED_THIS_TURN = 304, + MULLIGAN_STATE = 305, + TAUNT_READY = 306, + STEALTH_READY = 307, + CHARGE_READY = 308, + CANT_BE_TARGETED_BY_ABILITIES = 311, + SHOULDEXITCOMBAT = 312, + CREATOR = 313, + CANT_BE_DISPELLED = 314, + PARENT_CARD = 316, + NUM_MINIONS_PLAYED_THIS_TURN = 317, + PREDAMAGE = 318, + TARGETING_ARROW_TEXT = 325, + ENCHANTMENT_BIRTH_VISUAL = 330, + ENCHANTMENT_IDLE_VISUAL = 331, + CANT_BE_TARGETED_BY_HERO_POWERS = 332, + HEALTH_MINIMUM = 337, + TAG_ONE_TURN_EFFECT = 338, + SILENCE = 339, + COUNTER = 340, + ARTISTNAME = 342, + HAND_REVEALED = 348, + ADJACENT_BUFF = 350, + FLAVORTEXT = 351, + FORCED_PLAY = 352, + LOW_HEALTH_THRESHOLD = 353, + SPELLPOWER_DOUBLE = 356, + HEALING_DOUBLE = 357, + NUM_OPTIONS_PLAYED_THIS_TURN = 358, + TO_BE_DESTROYED = 360, + AURA = 362, + POISONOUS = 363, + HOW_TO_EARN = 364, + HOW_TO_EARN_GOLDEN = 365, + HERO_POWER_DOUBLE = 366, + AI_MUST_PLAY = 367, + NUM_MINIONS_PLAYER_KILLED_THIS_TURN = 368, + NUM_MINIONS_KILLED_THIS_TURN = 369, + AFFECTED_BY_SPELL_POWER = 370, + EXTRA_DEATHRATTLES = 371, + START_WITH_1_HEALTH = 372, + IMMUNE_WHILE_ATTACKING = 373, + MULTIPLY_HERO_DAMAGE = 374, + MULTIPLY_BUFF_VALUE = 375, + CUSTOM_KEYWORD_EFFECT = 376, + TOPDECK = 377, + CANT_BE_TARGETED_BY_BATTLECRIES = 379, + SHOWN_HERO_POWER = 380, + DEATHRATTLE_RETURN_ZONE = 382, + STEADY_SHOT_CAN_TARGET = 383, + DISPLAYED_CREATOR = 385, + POWERED_UP = 386, + SPARE_PART = 388, + FORGETFUL = 389, + CAN_SUMMON_MAXPLUSONE_MINION = 390, + OBFUSCATED = 391, + BURNING = 392, + OVERLOAD_LOCKED = 393, + NUM_TIMES_HERO_POWER_USED_THIS_GAME = 394, + CURRENT_HEROPOWER_DAMAGE_BONUS = 395, + HEROPOWER_DAMAGE = 396, + LAST_CARD_PLAYED = 397, + NUM_FRIENDLY_MINIONS_THAT_DIED_THIS_TURN = 398, + NUM_CARDS_DRAWN_THIS_TURN = 399, + AI_ONE_SHOT_KILL = 400, + EVIL_GLOW = 401, + HIDE_COST = 402, + INSPIRE = 403, + RECEIVES_DOUBLE_SPELLDAMAGE_BONUS = 404, + HEROPOWER_ADDITIONAL_ACTIVATIONS = 405, + HEROPOWER_ACTIVATIONS_THIS_TURN = 406, + REVEALED = 410, + NUM_FRIENDLY_MINIONS_THAT_DIED_THIS_GAME = 412, + CANNOT_ATTACK_HEROES = 413, + LOCK_AND_LOAD = 414, + TREASURE = 415, + SHADOWFORM = 416, + NUM_FRIENDLY_MINIONS_THAT_ATTACKED_THIS_TURN = 417, + NUM_RESOURCES_SPENT_THIS_GAME = 418, + CHOOSE_BOTH = 419, + ELECTRIC_CHARGE_LEVEL = 420, + HEAVILY_ARMORED = 421, + DONT_SHOW_IMMUNE = 422, + HISTORY_PROXY_NO_BIG_CARD = 432, + TRANSFORMED_FROM_CARD = 435, +}; + +#endif diff --git a/hm_gameserver/src/include/proto/misc.h b/hm_gameserver/src/include/proto/misc.h new file mode 100644 index 0000000..7d87858 --- /dev/null +++ b/hm_gameserver/src/include/proto/misc.h @@ -0,0 +1,70 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef MISC_H_ +#define MISC_H_ + +struct gamesetup_s { + u64 board; + u64 maxsecrets; + u64 maxfriendlyminions; + u64 keepalive; + u64 stuckdisconnect; +}; + +struct handshake_s { + u64 gamehandle; + char *password; + int npassword; + u64 clienthandle; + u64 mission; + char *version; + int nversion; + + struct platform_s *platform; +}; + +struct platform_s { + u64 os; + u64 screen; + int nname; + char *name; + u64 store; +}; + +struct chooseoption_s { + u64 id; + u64 index; + u64 target; + u64 suboption; + u64 position; +}; + +void gamesetup_free(struct gamesetup_s *g); +int gamesetup_serialize(void *data, char **dst, const char *maxdst); + +void handshake_free(struct handshake_s *h); +void *handshake_deserialize(char **dst, const char *maxdst); + +void platform_free(struct platform_s *p); +struct platform_s *platform_deserialize(char **dst, const char *maxdst); + +void chooseoption_free(struct chooseoption_s *c); +void *chooseoption_deserialize(char **dst, const char *maxdst); +void chooseoption_dump(struct chooseoption_s *o, u64 local_held_card); + +#endif diff --git a/hm_gameserver/src/include/proto/mouseinfo.h b/hm_gameserver/src/include/proto/mouseinfo.h new file mode 100644 index 0000000..195c799 --- /dev/null +++ b/hm_gameserver/src/include/proto/mouseinfo.h @@ -0,0 +1,34 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef MOUSEINFO_H_ +#define MOUSEINFO_H_ + +struct mouseinfo_s { + u64 arroworigin; + u64 heldcard; + u64 overcard; + u64 x; + u64 y; +}; + +void mouseinfo_free(struct mouseinfo_s *p); +void *mouseinfo_deserialize(char **dst, const char *maxdst); +int mouseinfo_serialize(void *ao, char **dst, const char *maxdst); +int mouseinfo_size(struct mouseinfo_s *p); + +#endif diff --git a/hm_gameserver/src/include/proto/options.h b/hm_gameserver/src/include/proto/options.h new file mode 100644 index 0000000..33881b2 --- /dev/null +++ b/hm_gameserver/src/include/proto/options.h @@ -0,0 +1,60 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef OPTIONS_H_ +#define OPTIONS_H_ + +struct suboption_target_s { + u64 value; + struct suboption_target_s *next; +}; + +struct suboption_s { + u64 id; + struct suboption_target_s *target; + + struct suboption_s *next; +}; + +struct option_s { + u64 type; + struct suboption_s *mainoption; + struct suboption_s *suboptions; + + struct option_s *next; +}; + +struct alloptions_s { + u64 id; + struct option_s *options; +}; + +void alloptions_free(struct alloptions_s *a); +int alloptions_serialize(void *s, char **dst, const char *maxdst); +int alloptions_size(struct alloptions_s *p); + +void option_free(struct option_s *p); +int option_serialize(struct option_s *s, char **dst, const char *maxdst); +int option_size(struct option_s *p); + +void suboption_free(struct suboption_s *p); +int suboption_serialize(struct suboption_s *s, char **dst, const char *maxdst); +int suboption_size(struct suboption_s *p); + +void alloptions_dump(struct alloptions_s *a); + +#endif diff --git a/hm_gameserver/src/include/proto/packet.h b/hm_gameserver/src/include/proto/packet.h new file mode 100644 index 0000000..680f8e8 --- /dev/null +++ b/hm_gameserver/src/include/proto/packet.h @@ -0,0 +1,56 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef PACKET_H_ +#define PACKET_H_ + +enum packet_e { + P_GETGAMESTATE = 0x01, + P_CHOOSEOPTION = 0x02, + P_CHOOSEENTITIES = 0x03, + P_TURNTIMER = 0x09, + P_ENTITIESCHOSEN = 0x0D, + P_ALLOPTIONS = 0x0E, + P_USERUI = 0x0F, + P_GAMESETUP = 0x10, + P_ENTITYCHOICES = 0x11, + P_POWERHISTORY = 0x13, + P_SPECTATORNOTIFY = 0x18, + P_PING = 0x73, + P_PONG = 0x74, + P_HANDSHAKE = 0xA8, +}; + +struct packet_s { + int id; + int len; + void *data; +}; + +struct packet_deserialize_s { + int id; + void *(*deserialize)(char **dst, const char *end); + int (*serialize)(void *p, char **dst, const char *end); + int (*free)(void *p); +}; + +void packet_free(struct packet_s *p); +struct packet_s *deserialize(char **dst, const char *maxdst); +int serialize(struct packet_s *p, char **dst, const char *maxdst); +struct packet_s *packet_init(enum packet_e id, void *data); + +#endif diff --git a/hm_gameserver/src/include/proto/powerhistory.h b/hm_gameserver/src/include/proto/powerhistory.h new file mode 100644 index 0000000..f1195ab --- /dev/null +++ b/hm_gameserver/src/include/proto/powerhistory.h @@ -0,0 +1,178 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef DEF_H_ +#define DEF_H_ + +#define error()\ + hm_log(LOG_EMERG, lg, "dst: %p end: %p n: %d", *dst, maxdst, n);\ +abort(); + +struct powerhistory_tag_s { + u64 name; + u64 value; + + struct powerhistory_tag_s *next; +}; + +struct powerhistory_hide_s { + u64 entity; + u64 zone; +}; + +struct powerhistory_tagchange_s { + u64 entity; + u64 tag; + u64 value; +}; + +struct powerhistory_entity_s { + u64 entity; + char *name; + int nname; + + struct powerhistory_tag_s *tag, *tag_tail; +}; + +struct powerhistory_powerstart_s { + u64 type; + u64 index; + u64 source; + u64 target; + + int ncard_id; + char *card_id; +}; + +struct powerhistory_powerend_s { + int i; +}; + +struct powerhistory_game_entity_s { + u64 id; + struct powerhistory_tag_s *tag, *tag_tail; +}; + +struct powerhistory_s { + struct powerhistory_data_s *data, *data_tail; +}; + +struct powerhistory_info_s { + u64 id; + struct powerhistory_info_s *next; +}; + +struct powerhistory_meta_s { + u64 type; + u64 data; + struct powerhistory_info_s *info, *info_tail; +}; + +struct powerhistory_player_s { + u64 id; + u64 bnet_hi; + u64 bnet_lo; + u64 cardback; + struct powerhistory_game_entity_s *entity; + + struct powerhistory_player_s *next; +}; + +struct powerhistory_creategame_s { + struct powerhistory_game_entity_s *game_entity; + struct powerhistory_player_s *player, *player_tail; +}; + +struct powerhistory_data_s { + struct powerhistory_entity_s *full; + struct powerhistory_entity_s *show; + struct powerhistory_hide_s *hide; + struct powerhistory_tagchange_s *tagchange; + struct powerhistory_creategame_s *creategame; + struct powerhistory_powerstart_s *powerstart; + struct powerhistory_powerend_s *powerend; + struct powerhistory_entity_s *change_entity; + struct powerhistory_meta_s *meta; + + struct powerhistory_data_s *next, *tail; +}; + +void powerhistory_free(struct powerhistory_s *p); +void *powerhistory_deserialize(char **dst, const char *maxdst); +int powerhistory_serialize(void *data, char **dst, const char *maxdst); +int powerhistory_size(struct powerhistory_s *ph); + +struct powerhistory_data_s *powerhistory_data_deserialize(char **dst, const char *maxdst); +int powerhistorydata_serialize(struct powerhistory_data_s *ph, char **dst, const char *maxdst); +int powerhistorydata_size(struct powerhistory_data_s *ph); +void powerhistory_data_free(struct powerhistory_data_s *d); + +struct powerhistory_meta_s *meta_deserialize(char **dst, const char *maxdst); +int meta_serialize(struct powerhistory_meta_s *ph, char **dst, const char *maxdst); +int meta_size(struct powerhistory_meta_s *ph); +void meta_free(struct powerhistory_meta_s *t); + +struct powerhistory_powerend_s *powerend_deserialize(char **dst, const char *maxdst); +int powerend_serialize(struct powerhistory_powerend_s *ph, char **dst, const char *maxdst); +int powerend_size(struct powerhistory_powerend_s *ph); +void powerend_free(struct powerhistory_powerend_s *p); + +struct powerhistory_powerstart_s *powerstart_deserialize(char **dst, const char *maxdst); +int powerstart_serialize(struct powerhistory_powerstart_s *ph, char **dst, const char *maxdst); +int powerstart_size(struct powerhistory_powerstart_s *ph); +void powerstart_free(struct powerhistory_powerstart_s *p); + +struct powerhistory_creategame_s *creategame_deserialize(char **dst, const char *maxdst); +int creategame_serialize(struct powerhistory_creategame_s *ph, char **dst, const char *maxdst); +int creategame_size(struct powerhistory_creategame_s *ph); +void creategame_free(struct powerhistory_creategame_s *c); + +struct powerhistory_tagchange_s *tagchange_deserialize(char **dst, const char *maxdst); +int tagchange_serialize(struct powerhistory_tagchange_s *ph, char **dst, const char *maxdst); +int tagchange_size(struct powerhistory_tagchange_s *ph); +void tagchange_free(struct powerhistory_tagchange_s *t); + +struct powerhistory_hide_s *hide_deserialize(char **dst, const char *maxdst); +int hide_serialize(struct powerhistory_hide_s *ph, char **dst, const char *maxdst); +int hide_size(struct powerhistory_hide_s *ph); +void hide_free(struct powerhistory_hide_s *t); + +struct powerhistory_game_entity_s *game_entity_deserialize(char **dst, const char *maxdst); +int game_entity_serialize(struct powerhistory_game_entity_s *ph, char **dst, const char *maxdst); +int game_entity_size(struct powerhistory_game_entity_s *ph); +void game_entity_free(struct powerhistory_game_entity_s *g); + +struct powerhistory_entity_s *entity_deserialize(char **dst, const char *maxdst); +int entity_serialize(struct powerhistory_entity_s *ph, char **dst, const char *maxdst); +int entity_size(struct powerhistory_entity_s *ph); +void entity_free(struct powerhistory_entity_s *e); + +struct powerhistory_tag_s *tag_deserialize(char **dst, const char *maxdst); +int tag_serialize(struct powerhistory_tag_s *ph, char **dst, const char *maxdst); +int tag_size(struct powerhistory_tag_s *ph); +void tag_free(struct powerhistory_tag_s *t); + +void player_free(struct powerhistory_player_s *p); +struct powerhistory_player_s *player_deserialize(char **dst, const char *maxdst); +int player_serialize(struct powerhistory_player_s *ph, char **dst, const char *maxdst); +int player_size(struct powerhistory_player_s *ph); + +int bnet_size(struct powerhistory_player_s *ph); + +void powerhistory_dump(struct powerhistory_s *p); + +#endif diff --git a/hm_gameserver/src/include/proto/proto.h b/hm_gameserver/src/include/proto/proto.h new file mode 100644 index 0000000..5ec5ad0 --- /dev/null +++ b/hm_gameserver/src/include/proto/proto.h @@ -0,0 +1,72 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef PROTO_H_ +#define PROTO_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +typedef unsigned long long u64; + +int sizeofu64(u64 v); +int sizeofu32(int v); +int stream_write(const char **dst, const char *end, const void *src, const int nsrc); +int write_byte(char **dst, const char *end, const char src); +int write_bytes(char **dst, const char *end, const char *src, const int nsrc); +void write_uint(char **dst, const char *end, int src); +void write_uint64(char **dst, const char *end, u64 src); +int write_mem_int(char **dst, const char *end, const int src); + +char read_byte(char **dst, const char *end); +int read_uint(char **dst, const char *end); +u64 read_uint64(char **dst, const char *end); +int read_mem_int(char **dst, const char *end); +char *read_bytes(char **dst, const char *end, int *ndst); + +int skip(char **dst, const char *end, const int jump); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct hm_log_s *lg; + +#endif diff --git a/hm_gameserver/src/include/proto/turntimer.h b/hm_gameserver/src/include/proto/turntimer.h new file mode 100644 index 0000000..a1e89a1 --- /dev/null +++ b/hm_gameserver/src/include/proto/turntimer.h @@ -0,0 +1,31 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef TURNTIMER_H_ +#define TURNTIMER_H_ + +struct turntimer_s { + u64 seconds; + u64 turn; + char show; +}; + +void turntimer_free(struct turntimer_s *t); +int turntimer_serialize(void *ao, char **dst, const char *maxdst); +void turntimer_dump(struct turntimer_s *t); + +#endif diff --git a/hm_gameserver/src/include/proto/userui.h b/hm_gameserver/src/include/proto/userui.h new file mode 100644 index 0000000..ec03734 --- /dev/null +++ b/hm_gameserver/src/include/proto/userui.h @@ -0,0 +1,33 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef USERUI_H_ +#define USERUI_H_ + +struct userui_s { + struct mouseinfo_s *mouseinfo; + u64 emote; + u64 player_id; +}; + +void userui_free(struct userui_s *u); +int userui_serialize(void *ao, char **dst, const char *maxdst); +void *userui_deserialize(char **dst, const char *maxdst); +int userui_size(struct userui_s *p); +void userui_dump(struct userui_s *u); + +#endif diff --git a/hm_gameserver/src/include/proto/zone.h b/hm_gameserver/src/include/proto/zone.h new file mode 100644 index 0000000..e1d6134 --- /dev/null +++ b/hm_gameserver/src/include/proto/zone.h @@ -0,0 +1,33 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ZONE_H_ +#define ZONE_H_ + +enum zone_e { + ZONE_INVALID = 0, + ZONE_PLAY = 1, + ZONE_DECK = 2, + ZONE_HAND = 3, + ZONE_GRAVEYARD = 4, + ZONE_REMOVEDFROMGAME = 5, + ZONE_SETASIDE = 6, + ZONE_SECRET = 7, + ZONE_DISCARD = -2, +}; + +#endif diff --git a/hm_gameserver/src/include/sections.h b/hm_gameserver/src/include/sections.h new file mode 100644 index 0000000..30e46dc --- /dev/null +++ b/hm_gameserver/src/include/sections.h @@ -0,0 +1,538 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef SECTIONS_H_ +#define SECTIONS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// built-in variables +#define HSL_attacker (attacker) +#define HSL_defender (defender) +#define HSL_defenders (defenders) +#define HSL_player (p) +#define HSL_opponent ((struct hs_holder_s *)(p->opponent.client->data)) +#define HSL_deck_player (p->deck_copy) +#define HSL_deck_opponent (p->opponent.deck_copy) +#define HSL_target (opt->target) +#define HSL_ally_hero (p->deck_copy->hero) +#define HSL_enemy_hero (p->opponent.deck_copy->hero) +#define HSL_weapon_player (p->deck_copy->heroweapon) +#define HSL_weapon_opponent (p->opponent.deck_copy->heroweapon) +#define HSL_deck_defender (defender->parent) +#define HSL_fake_defender (__fake_defender) +#define HSL_fake_attacker (__fake_attacker) +#define HSL_fake_weapon (__fake_weapon) +#define HSL_fake_deck (__fake_deck) +#define HSL_fake_levelup (&__fake_levelup) +#define HSL_no_attacker (-1) +#define HSL_heroes_included 1 +#define HSL_heroes_excluded 0 +#define HSL_magic_immunity_included 1 +#define HSL_magic_immunity_excluded 0 + +// generic macros +#define def(m_type, m_dst) struct m_type *m_dst = NULL; + +#define is_spell(m_dst) (flag(&m_dst->state, CARD_SPELL, FLAG_ISSET)) + +#define cmp_cardname(m_card, m_src) (strcmp(m_card->entity->name, m_src) == 0) + +#define hsl_set_windfury(m_dst)\ + flag(&m_dst->state, CARD_WINDFURY, FLAG_SET) + +#define hsl_set_taunt(m_dst)\ + flag(&m_dst->state, CARD_TAUNT, FLAG_SET); + +#define hsl_refresh_mana(m_deck, m_amount)\ + deck->mana_used = (m_amount > deck->mana_used) ? 0 : deck->mana_used - m_amount ; + +#define turn_plays(m_card) (m_card->turn_plays) + +/** + * @brief Foreach + * + * @param m_alias iterator + * @param m_src source + */ +#define foreach(m_alias, m_src)\ + for(m_alias = m_src; m_alias != NULL; m_alias = m_alias->next) + +/** + * @brief Find out if controller is current player + * + * @param m_card played card + */ +#define is_controller_player(m_card)\ + (p->id == m_card->parent->deck_copy->controller) + +// hsl_* macros + +// only works on friendly deck +#define hsl_set_magic_immunity(m_dst)\ + force_expire(p, HSL_deck_player, m_dst);\ +mechanics_expire(p->game->turn + 2, m_dst, EXPIRE_MAGIC_IMMUNITY, 1, NULL);\ +flag(&m_dst->state, CARD_DIVINE_SHIELD, FLAG_SET); + +#define hsl_set_fullhealth(m_dst)\ + m_dst->health = m_dst->total_health;\ +flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET); + +#define hsl_swap_health(m_dst, m_src)\ + int hp = m_dst->health;\ +m_dst->health = m_dst->total_health = m_src->health - m_src->buff_health;\ +m_src->health = m_src->total_health = hp + m_src->buff_health;\ +flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);\ +flag(&m_src->state, MECHANICS_HEALTH, FLAG_SET); + +#define hsl_set_health(m_dst, m_change)\ + m_dst->health = m_dst->total_health = (m_change + m_dst->buff_health);\ +flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET); + +#define hsl_decrease_health(m_dst, m_change)\ + m_dst->buff_health -= m_change;\ +m_dst->total_health -= m_change;\ +flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);\ +if(m_dst->health > m_dst->total_health) {\ + m_dst->health = m_dst->total_health;\ +} + +#define hsl_increase_health(m_dst, m_change)\ + m_dst->buff_health += m_change;\ +m_dst->health += m_change;\ +m_dst->total_health += m_change;\ +flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET); + +#define hsl_replenish_health(m_dst, m_change)\ + if(m_dst->total_health >= (m_dst->health + m_change)) {\ + m_dst->health += m_change;\ + flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);\ + } + + +#define hsl_change_armor(m_dst, m_change)\ + m_dst->armor += m_change;\ +flag(&m_dst->state, MECHANICS_ARMOR, FLAG_SET); + +#define hsl_change_attack(m_dst, m_change)\ + m_dst->attack += m_change;\ +flag(&m_dst->state, MECHANICS_ATTACK, FLAG_SET); + + +#define hsl_cards_by_name(m_deck, m_name) (cards_by_name(HSL_player, m_deck, m_name, CARD_BOARD)) + +#define hsl_board_count_by_name(m_deck, m_name) (board_count_by_name(m_deck, m_name)) + +#define hsl_board_minions_count(m_deck, m_attacker) cards_get_board_count(m_deck, NULL, 0, m_attacker->id) + +#define hsl_add_single_attachment(m_player, m_deck, m_dst, m_src) add_single_attachment(m_player, m_deck, m_dst, m_src) + +#define hsl_remove_attachment(m_deck, m_opponent, m_card, m_name) (card_remove_attachment(m_deck, m_opponent, m_card, m_name)) + +#define level(m_dst) (m_dst->boss.level) + +#define is_destroyed(m_dst) (flag(&m_dst->state, CARD_DESTROYED, FLAG_ISSET)) + +#define is_boss(m_dst) (flag(&m_dst->state, CARD_BOSS, FLAG_ISSET)) + +#define hsl_apply_attachment(m_player, m_deck, m_dst, m_src) (card_apply_attachment(m_player, m_deck, m_dst, m_src)) + +#define hsl_cards_get_hand_random(m_deck) (cards_get_hand_random(m_deck)) + +#define hsl_cards_get_hand(m_deck) (cards_get_hand(m_deck)) + +#define hsl_receive_damage(m_dst, m_dmg)\ + if(m_dst) { m_dst->receive.damage = m_dmg; } + +#define hsl_receive_heal(m_dst, m_heal)\ + if(m_dst) { m_dst->receive.heal = m_heal; } + +#define hsl_freeze(m_src, m_dst)\ + hm_log(LOG_DEBUG, lg, "Attacker [%s](%d) froze [%s](%d)", m_src->entity->desc, m_src->id, m_dst->entity->desc, m_dst->id);\ +mechanics_expire(p->game->turn + 3, m_dst, EXPIRE_FROZEN, 1, NULL);\ +flag(&m_dst->state, CARD_FROZEN, FLAG_SET); + +#define hsl_add_defender(m_src, m_holder)\ + struct card_list_s *m_holder;\ +LIST_ADD(defenders, m_holder, m_src) + +#define hsl_return_to_hand(m_card)\ + flag(&m_card->state, CARD_BOARD, FLAG_UNSET);\ +flag(&m_card->state, CARD_HAND, FLAG_SET);\ +flag(&m_card->state, CARD_EXHAUSTED, FLAG_UNSET);\ +m_card->health = m_card->total_health = m_card->default_health;\ +flag(&m_card->state, MECHANICS_HEALTH, FLAG_SET);\ +m_card->attack = m_card->default_attack;\ +flag(&m_card->state, MECHANICS_ATTACK, FLAG_SET);\ +card_remove_attachment(hsl_deck(m_card), NULL, m_card, NULL);\ +card_destroy(m_card, hsl_deck(m_card), 1);\ +/* order is importatnt here, new zone position must come after card is destroyed */\ +if(m_card->controller == HSL_deck_player->controller) {\ + m_card->zone_position = ++(HSL_deck_player->handposition);\ +} else {\ + m_card->zone_position = ++(HSL_deck_opponent->handposition);\ +}\ + +#define hsl_cards_get_hand(m_deck) (cards_get_hand(m_deck)) + +#define hsl_add_new_card_hand(m_deck, m_card, m_holder)\ + struct card_s *m_holder = add_new_card(m_deck->parent->game, m_deck, -1, m_card, -1);\ +flag(&m_holder->state, CARD_HAND, FLAG_SET);\ +m_holder->zone_position = ++(m_deck->handposition); + +#define hsl_destroy(m_deck, m_dst)\ +{\ + struct card_s *__fake_defender = m_dst;\ + __SECTION_DESTROYED\ +}\ +flag(&m_dst->state, CARD_DESTROYED, FLAG_SET);\ +cards_board_destroyed_reorder(m_deck, m_dst->zone_position); + +#define hsl_destroy_inhand(m_dst) card_discard_by_name(HSL_player, HSL_fake_defender, m_dst) + +#define hsl_set_weapon_durability(m_dst, m_value)\ + m_dst->durability += m_value;\ +flag(&m_dst->state, MECHANICS_DURABILITY, FLAG_SET); + +#define hsl_weapon_durability(m_dst) m_dst->durability + +#define hsl_destroy_weapon(m_attacker, m_deck)\ + if(m_deck->heroweapon) {\ + /*struct card_list_s *itm;*/\ + __SECTION_WEAPON_DESTROYED;\ + flag(&m_deck->heroweapon->state, CARD_DESTROYED, FLAG_SET);\ + flag(&m_deck->heroweapon->state, CARD_BOARD, FLAG_UNSET);\ + flag(&m_deck->heroweapon->state, CARD_HEROWEAPON, FLAG_UNSET);\ + flag(&m_deck->heroweapon->state, CARD_EXHAUSTED, FLAG_UNSET);\ + \ + /*LIST_ADD(m_attacker->target.card, itm, m_holder->deck_copy->heroweapon);*/\ + \ + flag(&m_deck->heroweapon->state, MECHANICS_DESTROY_WEAPON, FLAG_SET);\ + m_deck->heroweapon = NULL;\ + } + +#define is_weapon(m_deck, m_src) (m_deck && m_deck->heroweapon && strcmp(m_deck->heroweapon->entity->name, m_src) == 0) + +#define hsl_change_cost(m_card, m_change)\ + (m_card->cost = (m_card->default_cost - m_change >= 0) ? (m_card->default_cost - m_change) : 0);\ +flag(&(m_card->state), MECHANICS_COST, FLAG_SET); + +#define hsl_card_spell_by_name(m_player, m_deck, m_name) (card_by_name(m_player, m_deck, m_name, CARD_SPELL)) +#define hsl_card_board_by_name(m_player, m_deck, m_name) (card_by_name(m_player, m_deck, m_name, CARD_BOARD)) +#define hsl_card_hand_by_name(m_player, m_deck, m_name) (card_by_name(m_player, m_deck, m_name, CARD_HAND)) + +#define hsl_count_attachments(m_deck, m_opponent, m_card, m_name) (card_count_attachment(m_deck, m_opponent, m_card, m_name)) + +#define hsl_discard_random_hand(m_deck, m_amount, m_holder)\ + int m_holder;\ +for(m_holder = 0; m_holder < m_amount; m_holder++) {\ + struct card_s *m_card = cards_get_hand_random(m_deck);\ + if(m_card) {\ + flag(&m_card->state, CARD_DISCARD, FLAG_SET);\ + flag(&m_card->state, CARD_HAND, FLAG_UNSET);\ + cards_reorder_hand_owner(m_deck, m_card->id);\ + }\ +} + +#define hsl_discard_hand(m_deck, m_all)\ + struct card_list_s *m_holder;\ +for(m_holder = m_all; m_holder != NULL; m_holder = m_holder->next) {\ + flag(&m_holder->card->state, CARD_DISCARD, FLAG_SET);\ + cards_reorder_hand_owner(m_deck, m_holder->card->id);\ +} + +#define card(m_list) (m_list->card) + +#define hsl_card(m_target)\ + card_get(HSL_deck_player, HSL_deck_opponent, m_target) + +#define hsl_deck(m_card) ((m_card->controller == HSL_deck_player->controller) ? HSL_deck_player : HSL_deck_opponent) + +#define default_health(m_card) (m_card->default_health) + +#define default_attack(m_card) (m_card->default_attack) + +#define hsl_board_all_cards(m_attacker, m_hero) cards_get_board(p->deck_copy, p->opponent.deck_copy, m_hero, m_attacker->id, HSL_magic_immunity_included, 1) + +#define hsl_board_all_cards_no_boss(m_attacker, m_hero) (cards_get_board(p->deck_copy, p->opponent.deck_copy, m_hero, m_attacker->id, HSL_magic_immunity_included, 0)) + +#define hsl_board_friendly_cards(m_deck, m_attacker, m_hero) (cards_get_board(m_deck, NULL, m_hero, m_attacker, HSL_magic_immunity_included, 1)) + +#define hsl_board_friendly_cards_wattacker(m_hero) cards_get_board(p->deck_copy, NULL, m_hero, -1, HSL_magic_immunity_included, 1); + +#define hsl_board_enemy_cards(m_attacker, m_hero, m_mi) cards_get_board(NULL, p->opponent.deck_copy, m_hero, m_attacker->id, m_mi, 1); + +#define hsl_board_friendly_no_boss(m_attacker, m_hero, m_mi) cards_get_board(NULL, p->opponent.deck_copy, m_hero, m_attacker->id, m_mi, 0); + +#define hsl_board_boss_cards(m_deck) (cards_get_board_boss(m_deck)) + +#define hsl_attack_aoe(m_dst, m_src, m_fake_levelup) mechanics_attack_aoe(c, opt->position, m_dst, &m_src, m_fake_levelup) +#define hsl_attack(m_dst, m_src, m_fake_levelup) hsl_attack_aoe(m_dst, m_src, m_fake_levelup) + +/** + * @brief Summon card for deck + * + * @param m_deck deck to summon to + * @param m_name name of the card + * @param m_card card holder + **/ +#define hsl_summon_card(m_deck, m_name, m_card)\ + int m_card##pos = cards_board_last(m_deck);\ +if(m_card##pos <= MAX_BOARD) {\ + struct card_s *m_card = add_new_card(p->game, m_deck, -1, m_name, -1);\ + mechanics_put_card_onboard(c, m_card##pos, m_card, 1, NULL, NULL, m_deck);\ +} + +/** + * @brief Count number of cards in list of cards + * + * @param m_cards list of cards + **/ +#define hsl_count_cards(m_cards) (cards_count(m_cards)) + +/** + * @brief Get random card from list of cards + * + * @param m_cards list of cards + **/ +#define hsl_random_card(m_cards) (card_random(m_cards)) + +/** + * @brief Draw number of cards from player's deck + * + * @param m_player deck owner + * @param m_deck deck to draw from + * @param m_card card's holder + * @param m_amount number of cards to draw + **/ +#define hsl_draw_cards(m_player, m_deck, m_card, m_amount)\ + int m_card##idx;\ +struct card_s *m_card;\ +for(m_card##idx = 0; m_card##idx < m_amount; m_card##idx++) {\ + m_card = draw_random_card(m_deck, m_player->entity_id, 0);\ + if(m_card) {\ + flag(&m_card->state, CARD_HAND, FLAG_SET);\ + struct card_list_s *m_card##itm;\ + LIST_ADD(defenders, m_card##itm, m_card);\ + }\ +} + +/** + * @brief Link card to another card's targets + * + * @param m_dst destination card + * @param m_src source card + **/ +#define hsl_link_target(m_dst, m_src)\ + LIST_ADD_LINK(m_dst->target.card, m_src) + +/** + * @brief Add target to defenders + * + * @param m_src source card + * @param m_holder variable placeholder + **/ +#define hsl_add_target(m_src, m_holder)\ + struct card_list_s *m_holder##item;\ +LIST_ADD(defenders, m_holder##item, m_src);\ + +/** + * @brief Attack as battlecry + * + * @param m_attacker attacking card + * @param m_defender defending card + * @param m_damage damage caused + **/ +#define hsl_attack_bc(m_attacker, m_defender, m_damage)\ + m_defender->receive.damage = m_damage;\ +entity_attack(p, m_attacker, m_defender); + +/** + * @brief Heal defender by certain amount (alias) + **/ +#define hsl_heal_bc(m_attacker, m_defender, m_damage)\ + hsl_heal(m_attacker, m_defender, m_damage); +/* + m_defender->receive.heal = m_damage;\ +#entity_attack(p, m_attacker, m_defender);\ +#struct card_list_s *item;\ +LIST_ADD(m_attacker->target.card, item, m_defender); +*/ + +/** + * @brief Heal defender by certain amount + * + * @param m_attacker healer card + * @param m_defender receiver card + * @param m_damage amount of healing + **/ +#define hsl_heal(m_attacker, m_defender, m_damage)\ + m_defender->receive.heal = m_damage;\ +entity_attack(p, m_attacker, m_defender);\ +struct card_list_s *item;\ +LIST_ADD(m_attacker->target.card, item, m_defender); + +/** + * @brief Mark target as corrupted + * + * Corrupted target is destroyed after m_turn turns + * + * @param m_turn number of turns from current turn when card is destroyed + * @param m_defender destination card + */ +#define hsl_buff_corrupt_expire(m_turn, m_defender)\ + flag(&(m_defender->state), CARD_CORRUPTED, FLAG_SET);\ +mechanics_expire(p->game->turn + m_turn, m_defender, EXPIRE_DESTROY, 1, NULL) + +/** + * @brief Change attack for m_turn turns + * + * @param m_turn expiration turn + * @param m_defender destination card + * @param m_attack value to change + */ +#define hsl_buff_attack_expire(m_turn, m_defender, m_attack)\ + m_defender->attack += m_attack;\ +flag(&(m_defender->state), MECHANICS_ATTACK, FLAG_SET);\ +mechanics_expire(p->game->turn + m_turn, m_defender, EXPIRE_ATTACK, -(m_attack), NULL); + +/** + * @brief Change health of card + * + * @param m_card destination card + * @param m_health health value + */ +#define hsl_add_attachment(m_player, m_attacker, m_defender, m_turn)\ + add_single_attachment(m_player, hsl_deck(m_defender), m_attacker, m_defender);\ +mechanics_expire(p->game->turn + m_turn, m_defender, EXPIRE_ATTACHMENT, 0, m_attacker->attachment); + +/** + * @brief Change health of card + * + * @param m_card destination card + * @param m_health health value + */ +#define buff_health(m_card, m_health)\ + defenders->card->health = m_health;\ +flag(&(m_card->state), MECHANICS_HEALTH, FLAG_SET); + +/** + * @brief Set divine shield to card + * + * @param m_card destination card + */ +#define hsl_divine_shield(m_card)\ + flag(&(m_card->state), CARD_DIVINE_SHIELD, FLAG_SET); + +/** + * @brief Set flag to card + * + * @param m_card destination card + * @param m_flag flag to set + */ +#define setflag(m_card, m_flag)\ + flag(&(m_card->state), m_flag, FLAG_SET); + +/** + * @brief Unset flag from card + * + * @param m_card destination card + * @param m_flag flag to unset + */ +#define unsetflag(m_card, m_flag)\ + flag(&(m_card->state), m_flag, FLAG_UNSET); + +/** + * @brief Unset windfury flag from card + * + * @param m_card destination card + */ +#define hsl_unset_windfury(m_card) (flag(&(m_card->state), CARD_WINDFURY, FLAG_UNSET)) + +/** + * @brief Set exhausted flag to card + * + * @param m_card destination card + */ +#define hsl_set_exhausted(m_card) (flag(&(m_card->state), CARD_EXHAUSTED, FLAG_SET)) + +/** + * @brief Unset exhausted flag from card + * + * @param m_card destination card + */ +#define hsl_unset_exhausted(m_card) (flag(&(m_card->state), CARD_EXHAUSTED, FLAG_UNSET)) + +/** + * @brief Transform defender to m_name + * + * Any mechanics like polymorph + * + * @param m_attacker card with ability to transform target + * @param m_defender card being attacked + * @param m_name card code name + */ +#define hsl_transform(m_attacker, m_defender,m_name)\ + struct card_s *card;\ +card = add_new_card(p->game, p->opponent.deck_copy, -1, m_name, -1);\ +card->zone_position = m_defender->zone_position;\ +mechanics_put_card_onboard(c, card->zone_position, card, 1, NULL, NULL);\ +m_defender->linked = card->id;\ +flag(&m_defender->state, CARD_LINKED, FLAG_SET);\ +flag(&m_defender->state, CARD_HIDE, FLAG_SET);\ +flag(&m_defender->state, CARD_BOARD, FLAG_UNSET); + +/** + * @brief Give weapon to player + * + * Called only in '.section onboard'. There is no need to linked destroyed weapon to defenders + * + * @param m_dst hero card + */ +#define hsl_give_weapon(m_dst)\ + if(m_dst->heroweapon != NULL) {\ + /* destroy weapon first */\ + {\ + struct card_s *__fake_weapon = m_dst->heroweapon;\ + __SECTION_WEAPON_DESTROYED;\ + }\ + \ + m_dst->heroweapon->priority_override = 900;\ + flag(&(m_dst->heroweapon->state), CARD_DESTROYED, FLAG_SET);\ + flag(&(m_dst->heroweapon->state), CARD_BOARD, FLAG_UNSET);\ + flag(&(m_dst->heroweapon->state), CARD_HEROWEAPON, FLAG_UNSET);\ + }\ +flag(&attacker->state, CARD_BOARD, FLAG_SET);\ +flag(&attacker->state, CARD_HEROWEAPON, FLAG_SET);\ +m_dst->heroweapon = attacker; + +#endif diff --git a/hm_gameserver/src/main.c b/hm_gameserver/src/main.c new file mode 100644 index 0000000..1947ddf --- /dev/null +++ b/hm_gameserver/src/main.c @@ -0,0 +1,269 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include + +#include + +struct ht_s **games = NULL; + +struct conn_server_s *user_cs; +struct hm_log_s *lg; + +struct ev_loop *loop = NULL; +static struct hm_log_s l; +static struct hm_pool_s *pool; + +void set_result(const char *k, int r); + +static void client_disconnected(void *data, const char *foreign_client_index, const char *hbs_id) +{ + struct hs_holder_s *p = data; + struct game_s *g; + + if(p == NULL) { + return; + } + + struct packet_s *packet = net_game_over(p, p->entity_id == 2 ? 3 : 2); + + struct ht_s *opponent = ht_get(async_clients, foreign_client_index, strlen(foreign_client_index)); + + if(opponent && opponent->n == sizeof(void *)) { + // loser + hm_log(LOG_DEBUG, lg, "Client disconnect callback, opponent exists"); + net_send((void *)opponent->s, packet); + set_result(hbs_id, 0); + } else { + // winner + hm_log(LOG_DEBUG, lg, "Client disconnect callback, opponent doesn't exist, cleaning game"); + set_result(hbs_id, 1); + g = p->game; + game_free(g); + } + + packet_free(packet); + holder_free(p); +} + +static void hm_recv(struct conn_client_s *cs, const char *buf, const int len) +{ + hs(cs, buf, len); +} + +static void server_shutdown() +{ + shutdown_server(user_cs); + + couchbase_deinit(); + + ht_free(games, pool); + ht_free(async_clients, pool); +} + +int start_server() +{ + struct conn_server_s *cs; + + entities_init(); + entities_init2(); + + lg = &l; + games = ht_init(pool); + async_clients = ht_init(pool); + + cs = malloc(sizeof(*cs)); + memset(cs, 0, sizeof(*cs)); + + cs->loop = loop; + cs->host = "0.0.0.0"; + cs->port = "3724"; + cs->log = &l; + cs->pool = pool; + cs->recv = hm_recv; + cs->client_dc = client_disconnected; + cs->shutdown = server_shutdown; + connector_server(cs); + + user_cs = cs; + + return 0; +} + +void callback(struct instance_s *data) +{ + struct instance_s *i; + + if(data == NULL) { + couchbase_deinit(); + hm_log(LOG_DEBUG, lg, "{Connector}: all destinations are offline"); + return; + } + + for(i = data; i != NULL; i = i->next) { + hm_log(LOG_DEBUG, lg, "{Connector}: connstr: [%s] online: %d group: %d bucket index: %d", i->connstr, i->status, i->group, i->index); + } + + start_server(); +} + +static void sigh_terminate(int __attribute__ ((unused)) signo) +{ + user_cs->shutdown(); +} + +static void initsignals() +{ + struct sigaction act; + + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SIG_IGN; + + if(sigaction(SIGPIPE, &act, NULL) < 0) { + hm_log(LOG_CRIT, lg, "{Connector}: sigaction sigpipe"); + } + + /** We don't care if someone stops and starts a child process with kill (1) */ + act.sa_flags = SA_NOCLDSTOP; + + /* catch INT and TERM signals */ + act.sa_flags = 0; + act.sa_handler = sigh_terminate; + if(sigaction(SIGINT, &act, NULL) < 0) { + hm_log(LOG_CRIT, lg, "{Connector}: Unable to register SIGINT signal handler: %s", strerror(errno)); + exit(1); + } + + if(sigaction(SIGTERM, &act, NULL) < 0) { + hm_log(LOG_CRIT, lg, "{Connector}: Unable to register SIGTERM signal handler: %s", strerror(errno)); + exit(1); + } +} + +void daemonize () { + if(chdir("/") != 0) { + hm_log(LOG_DEBUG, lg, "Unable change directory to /: %s", strerror(errno)); + exit(1); + } + + pid_t pid = fork(); + if(pid < 0) { + hm_log(LOG_DEBUG, lg, "Unable to daemonize: fork failed: %s", strerror(errno)); + exit(1); + } + + if(pid != 0) { + hm_log(LOG_DEBUG, lg, "Daemonized as pid %d.", pid); + exit(0); + } + + fclose(stdin); + fclose(stdout); + fclose(stderr); + +#define NULL_DEV "/dev/null" + + stdin = fopen(NULL_DEV, "r"); + if(stdin == NULL) { + hm_log(LOG_EMERG, lg, "Unable to reopen stdin to %s: %s", NULL_DEV, strerror(errno)); + exit(1); + } + + stdout = fopen(NULL_DEV, "w"); + if(stdout == NULL) { + hm_log(LOG_EMERG, lg, "Unable to reopen stdout to %s: %s", NULL_DEV, strerror(errno)); + exit(1); + } + + stderr = fopen(NULL_DEV, "w"); + if(stderr == NULL) { + hm_log(LOG_EMERG, lg, "Unable to reopen stderr to %s: %s", NULL_DEV, strerror(errno)); + exit(1); + } + + pid_t s = setsid(); + if(s < 0) { + hm_log(LOG_EMERG, lg, "Unable to create new session, setsid(2) failed: %s :: %d", strerror(errno), s); + exit(1); + } + + hm_log(LOG_DEBUG, lg, "Successfully daemonized as pid %d.", getpid()); +} + +int main(int argc, char **argv) +{ + struct couchbase_data_s cd; + const char *hosts[1] = { "localhost" }; + const int groups[1] = { 0 }; // Must start with 0 + const char *buckets[1] = { "hbs" }; + const char *passwd[1] = { "aci" }; + int i, daemon = 0; + + memset(&l, 0, sizeof(l)); + + for(i = 1; i < argc; i++) { + if(strlen(argv[i]) > 6 && memcmp(argv[i], "--log=", 6) == 0) { + daemon = 1; + hm_log_open(&l, argv[i] + 6, LOG_DEBUG); + } + } + + if(daemon == 0) { + hm_log_open(&l, NULL, LOG_DEBUG); + } + + lg = &l; + + loop = ev_default_loop(0); + pool = hm_create_pool(&l); + + hm_log(LOG_DEBUG, lg, "\nhm_gameserver Copyright (C) 2016 Filip Pancik\n\ + This program comes with ABSOLUTELY NO WARRANTY.\n\ + This is free software, and you are welcome to redistribute it\n\ + under certain conditions."); + + initsignals(); + + if(daemon == 1) { + daemonize(); + } + + cd.loop = loop; + cd.log = &l; + cd.pool = pool; + cd.callback = callback; + + cd.hosts = hosts; + cd.hgroups = groups; + cd.nhosts = 1; + cd.buckets = buckets; + cd.bpasswd = passwd; + cd.nbuckets = 1; + + couchbase_init(&cd); + + ev_run(loop, 0); + + hm_destroy_pool(pool); + hm_log_close(&l); + + ev_default_destroy(); + + return 0; +} diff --git a/hm_gameserver/src/options.c b/hm_gameserver/src/options.c new file mode 100644 index 0000000..f1a1e93 --- /dev/null +++ b/hm_gameserver/src/options.c @@ -0,0 +1,487 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +static int log_enable = 1; + +static struct option_s *fill_option(u64 type, u64 id, struct suboption_target_s *targets) +{ + struct option_s *option; + + option = malloc(sizeof(*option)); + memset(option, 0, sizeof(*option)); + + option->type = type; + + if(id != -1) { + option->mainoption = malloc(sizeof(*(option->mainoption))); + + memset(option->mainoption, 0, sizeof(*(option->mainoption))); + option->mainoption->id = id; + option->mainoption->target = targets; + } + + return option; +} + +static void add_suboption_target(struct suboption_target_s **so, u64 id) +{ + struct suboption_target_s *s; + s = malloc(sizeof(*s)); + + s->value = id; + + s->next = *so; + *so = s; +} + +int set_options_cards(struct card_list_s *cl, char *buffer, char *endbuffer, int turn) +{ + struct packet_s *packet; + struct alloptions_s *all; + struct option_s *option = NULL, *o; + struct card_list_s *c; + + for(c = cl; c != NULL; c = c->next) { + o = fill_option(6, c->card->id, NULL); + o->next = option; + option = o; + } + + o = fill_option(2, -1, NULL); + o->next = option; + option = o; + + all = malloc(sizeof(*all)); + + all->id = turn; + all->options = option; + + alloptions_dump(all); + + add_packet(&packet, all, P_ALLOPTIONS); + + char *ptr = buffer; + int n = serialize(packet, &ptr, endbuffer); + + //hm_log(LOG_NOTICE, lg, "set options:"); + //bin_dump(buffer, n); + + return n; + +} + +static void set_options_board(struct option_s **option, struct card_s *card, struct deck_s *opponent, const int taunt_count) +{ + struct option_s *o; + int j; + struct suboption_target_s *so = NULL; + + if( + + (flag(&card->state, CARD_BOARD, FLAG_ISSET) && + !flag(&card->state, CARD_DESTROYED, FLAG_ISSET) && + !flag(&card->state, CARD_SPELL, FLAG_ISSET) && + !flag(&card->state, CARD_FROZEN, FLAG_ISSET) ) && + /*( flag(&card->state, CARD_HERO, FLAG_ISSET) && card->attack > 0) */ + card->attack > 0 + ) { + + if(!flag(&card->state, CARD_TARGETING, FLAG_ISSET) && !flag(&card->state, CARD_TARGETING_BC, FLAG_ISSET)) { + goto add; + } + + if(log_enable) hm_log(LOG_NOTICE, lg, "setting targets for card %d", card->id); + for(j = 0; j < opponent->ncards; j++) { + + if((flag(&opponent->cards[j]->state, CARD_BOARD, FLAG_ISSET) || + flag(&opponent->cards[j]->state, CARD_HERO, FLAG_ISSET) ) && + !flag(&opponent->cards[j]->state, CARD_DESTROYED, FLAG_ISSET) + ) { + + // if taunt cards on board, does enemy have taunt + if(taunt_count > 0 && !flag(&card->state, CARD_HEROPOWER, FLAG_ISSET)) { + if(flag(&opponent->cards[j]->state, CARD_TAUNT, FLAG_ISSET)) { + hm_log(LOG_DEBUG, lg, "\tadding opponent taunt card %d as a target", opponent->cards[j]->id); + add_suboption_target(&so, opponent->cards[j]->id); + } + } else { + hm_log(LOG_DEBUG, lg, "\tadding opponent card %d as a target", opponent->cards[j]->id); + + add_suboption_target(&so, opponent->cards[j]->id); + } + } + } + +add: + o = fill_option(3, card->id, so); + o->next = *option; + *option = o; + } /*else { + hm_log(LOG_ALERT, lg, "Card %d: board %d desttroyed %d frozen %d spell %d", card->id, + flag(&card->state, CARD_BOARD, FLAG_ISSET), + flag(&card->state, CARD_DESTROYED, FLAG_ISSET), + flag(&card->state, CARD_FROZEN, FLAG_ISSET), + flag(&card->state, CARD_SPELL, FLAG_ISSET) + ); + } */ +} + +enum side_e { + SIDE_PLAYER = 0, + SIDE_OPPONENT +}; + +static void calc_targets(struct deck_s *deck, struct card_s *attacker, enum side_e side, struct suboption_target_s **so) +{ + int i; + struct card_s *defender; + int debug = 0; + + for(i = 0; i < deck->ncards; i++) { + + defender = deck->cards[i]; + + // ignore destroyed, spell, not board and not hero + if(flag(&defender->state, CARD_SPELL, FLAG_ISSET) || + (!flag(&defender->state, CARD_BOARD, FLAG_ISSET) && !flag(&defender->state, CARD_HERO, FLAG_ISSET)) || + flag(&defender->state, CARD_DESTROYED, FLAG_ISSET) + ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", defender->id); + continue; + } + + // culling blade + if(flag(&attacker->state, CARD_TARGET_30PERCENT_LESS, FLAG_ISSET) && + (defender->health * 3) > defender->total_health) { + continue; + } + + // magic immunity + if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && + !flag(&attacker->state, CARD_PIERCE_MAGIC_IMMUNITY, FLAG_ISSET) && + flag(&defender->state, CARD_DIVINE_SHIELD, FLAG_ISSET)) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // battlecry + /* + if(flag(&attacker->state, CARD_TARGET_BC_AUTO, FLAG_ISSET)) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + */ + + // allies + if(flag(&attacker->state, CARD_TARGET_ALLY, FLAG_ISSET) && side == SIDE_OPPONENT ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // enemies + if(flag(&attacker->state, CARD_TARGET_ENEMY, FLAG_ISSET) && side == SIDE_PLAYER) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // ally bosses + if(flag(&attacker->state, CARD_TARGET_ALLY_BOSSES, FLAG_ISSET) && + (side == SIDE_OPPONENT || !flag(&defender->state, CARD_BOSS, FLAG_ISSET)) + ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // enemy bosses + if(flag(&attacker->state, CARD_TARGET_ENEMY_BOSSES, FLAG_ISSET) && + (side == SIDE_PLAYER || !flag(&defender->state, CARD_BOSS, FLAG_ISSET)) + ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // bosses + if(flag(&attacker->state, CARD_TARGET_BOSSES, FLAG_ISSET) && + (!flag(&defender->state, CARD_BOSS, FLAG_ISSET)) + ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // board target (exc. heroes) + if(flag(&attacker->state, CARD_TARGET_BOARD, FLAG_ISSET) && + (flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // ally board target (exc. heroes) + if(flag(&attacker->state, CARD_TARGET_ALLY_BOARD, FLAG_ISSET) && + (side == SIDE_OPPONENT || flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // enemy board target (exc. heroes) + if(flag(&attacker->state, CARD_TARGET_ENEMY_BOARD, FLAG_ISSET) && + (side == SIDE_PLAYER || flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // skip non-hero targets if only heroes are valid targets + if(flag(&attacker->state, CARD_TARGET_HERO, FLAG_ISSET) && + !flag(&defender->state, CARD_HERO, FLAG_ISSET)) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // enemy hero + if(flag(&attacker->state, CARD_TARGET_ENEMY_HERO, FLAG_ISSET) && + (side == SIDE_PLAYER || !flag(&defender->state, CARD_HERO, FLAG_ISSET)) + ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // ally hero + if(flag(&attacker->state, CARD_TARGET_ALLY_HERO, FLAG_ISSET) && + (side == SIDE_OPPONENT || !flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // minions + if(flag(&attacker->state, CARD_TARGET_MINIONS, FLAG_ISSET) && + (flag(&defender->state, CARD_HERO, FLAG_ISSET) || flag(&defender->state, CARD_BOSS, FLAG_ISSET))) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // enemy minions + if(flag(&attacker->state, CARD_TARGET_ENEMY_MINIONS, FLAG_ISSET) && + (side == SIDE_PLAYER || flag(&defender->state, CARD_HERO, FLAG_ISSET) || flag(&defender->state, CARD_BOSS, FLAG_ISSET))) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // ally minions + if(flag(&attacker->state, CARD_TARGET_ALLY_MINIONS, FLAG_ISSET) && + (side == SIDE_OPPONENT || flag(&defender->state, CARD_HERO, FLAG_ISSET) || flag(&defender->state, CARD_BOSS, FLAG_ISSET)) + ) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // allies + if((flag(&attacker->state, CARD_TARGET_ALLY, FLAG_ISSET) && side == SIDE_OPPONENT)) { + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // undamaged minion eg. backstab + if(flag(&attacker->state, CARD_TARGET_UNDAMAGED_MINION, FLAG_ISSET) + && + (defender->total_health != defender->health || + flag(&defender->state, CARD_HERO, FLAG_ISSET)) ) { + + continue; + } + + // undamaged minion eg. execute + if(flag(&attacker->state, CARD_TARGET_DAMAGED_MINION, FLAG_ISSET) + && + (defender->total_health == defender->health || + flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // shadow word: pain + if(flag(&attacker->state, CARD_TARGET_3ATTACK_LESS, FLAG_ISSET) && + ( defender->attack > 3 || + flag(&defender->state, CARD_HERO, FLAG_ISSET) )) { + + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // shadow word: death + if(flag(&attacker->state, CARD_TARGET_5ATTACK_MORE, FLAG_ISSET) && + (defender->attack < 5 || + flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // Ursa + if(flag(&attacker->state, CARD_TARGET_URSA, FLAG_ISSET) && + strcmp(defender->entity->name, CN_URSA) != 0) { + + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // Sven + if(flag(&attacker->state, CARD_TARGET_SVEN, FLAG_ISSET) && + strcmp(defender->entity->name, CN_SVEN) != 0) { + + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + // sacr. pact + if(flag(&attacker->state, CARD_TARGET_DEMON, FLAG_ISSET) && + ( !flag(&defender->state, CARD_RACE_DEMON, FLAG_ISSET) || + flag(&defender->state, CARD_HERO, FLAG_ISSET))) { + + if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id); + continue; + } + + if(debug) hm_log(LOG_DEBUG, lg, "\tadding card %d as a target of [%s](%d)", defender->id, attacker->entity->desc, attacker->id); + add_suboption_target(so, defender->id); + } +} + +int set_options(struct deck_s *deck, struct deck_s *opponent, char *buffer, char *endbuffer, int turn) +{ + int i; + int taunt_count; + + struct packet_s *packet; + struct alloptions_s *all; + struct option_s *option = NULL, *o = NULL; + + assert(opponent); + + // does enemy board contain taunt? + taunt_count = deck_get_taunts(opponent); + + // find playable cards + for(i = 0; i < deck->ncards; i++) { + // exhausted or frozen + if(flag(&deck->cards[i]->state, CARD_EXHAUSTED, FLAG_ISSET) || + flag(&deck->cards[i]->state, CARD_FROZEN, FLAG_ISSET)) { + if(log_enable) hm_log(LOG_DEBUG, lg, "skipping card %d as it's exhausted or frozen", deck->cards[i]->id); + continue; + } + + // not on board, in hand, heropower or frozen + if(!flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET)) { + if(log_enable) hm_log(LOG_DEBUG, lg, "skipping card %d as it's not: on board, in hand, heropower or hero with attack", deck->cards[i]->id); + continue; + } + + // set options to cards placed on board + if(!flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) { + set_options_board(&option, deck->cards[i], opponent, taunt_count); + } + + int board_count = cards_get_board_count(deck, NULL, 0, -1); + + // set playable in hand cards that are not spells/bc + if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) && + !flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET) && + deck->cards[i]->cost <= (deck->mana - deck->mana_used) && + board_count < MAX_BOARD + ) { + + o = fill_option(3, deck->cards[i]->id, NULL); + o->next = option; + option = o; + + if(log_enable) hm_log(LOG_DEBUG, lg, "setting playable card [%s](%d) in hand and it's not a spell, board count %d", deck->cards[i]->entity->desc, deck->cards[i]->id, board_count); + continue; + } + + // set in-hand spells, targeting battlecries + if((flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) && + flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) + || + (flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && + flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET)) + || + flag(&deck->cards[i]->state, CARD_WEAPON, FLAG_ISSET) + || + flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET) + ) { + + if(log_enable) hm_log(LOG_DEBUG, lg, "Considering Spell/Battlecry card %d", deck->cards[i]->id); + + if(flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET) && board_count >= MAX_BOARD) { + if(log_enable) hm_log(LOG_DEBUG, lg, "Battlecry card %d igrnoed as board is full", deck->cards[i]->id); + continue; + } + + if(deck->cards[i]->cost > (deck->mana - deck->mana_used)) { + if(log_enable) hm_log(LOG_DEBUG, lg, "Spell card %d too expensive", deck->cards[i]->id); + continue; + } + + if(log_enable) hm_log(LOG_DEBUG, lg, "Card [%s](%d) with cost %d accepted", deck->cards[i]->entity->desc, deck->cards[i]->id, deck->cards[i]->cost); + + struct suboption_target_s *so = NULL; + if(flag(&deck->cards[i]->state, CARD_TARGETING, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET)) { + + if(log_enable) hm_log(LOG_NOTICE, lg, "setting targets for card [%s](%d)", deck->cards[i]->entity->desc, deck->cards[i]->id); + + calc_targets(deck, deck->cards[i], SIDE_PLAYER, &so); + calc_targets(opponent, deck->cards[i], SIDE_OPPONENT, &so); + } + + if(so != NULL || + flag(&deck->cards[i]->state, CARD_NONTARGET, FLAG_ISSET) + ) { + o = fill_option(/*deck->cards[i]->cardtype*/ 3, deck->cards[i]->id, so); + o->next = option; + option = o; + } + } + } + + o = fill_option(2, -1, NULL); + o->next = option; + option = o; + + all = malloc(sizeof(*all)); + + all->id = turn; + all->options = option; + + alloptions_dump(all); + + add_packet(&packet, all, P_ALLOPTIONS); + + char *ptr = buffer; + int n = serialize(packet, &ptr, endbuffer); + + packet_free(packet); + + //hm_log(LOG_NOTICE, lg, "set options:"); + //bin_dump(buffer, n); + + return n; +} diff --git a/hm_gameserver/src/proto/alloptions.c b/hm_gameserver/src/proto/alloptions.c new file mode 100644 index 0000000..bef5485 --- /dev/null +++ b/hm_gameserver/src/proto/alloptions.c @@ -0,0 +1,87 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void alloptions_free(struct alloptions_s *a) +{ + struct option_s *o, *del; + + for(o = a->options; o != NULL; del = o, o = o->next, option_free(del)); + + free(a); +} + +int alloptions_serialize(void *ao, char **dst, const char *maxdst) +{ + int n = 0; + struct option_s *m; + struct alloptions_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->id); + + for(m = s->options; m != NULL; m = m->next) { + write_byte(dst, maxdst, 18); + n = option_size(m); + write_uint(dst, maxdst, n); + option_serialize(m, dst, maxdst); + } + + return (*dst - start); +} + +int alloptions_size(struct alloptions_s *p) +{ + int num = 0, n; + struct option_s *s; + + num += 1; + num += sizeofu64(p->id); + + for(s = p->options; s != NULL; s = s->next) { + num += 1; + n = option_size(s); + num += sizeofu32(n) + n; + } + + return num; +} + +void alloptions_dump(struct alloptions_s *a) +{ + struct suboption_target_s *t; + struct suboption_s *m; + struct option_s *o; + + hm_log(LOG_DEBUG, lg, "Dumping alloptions:"); + hm_log(LOG_DEBUG, lg, "id: %lld", a->id); + for(o = a->options; o != NULL; o = o->next) { + hm_log(LOG_DEBUG, lg, "\tOption type: %lld", o->type); + for(m = o->mainoption; m != NULL; m = m->next) { + hm_log(LOG_DEBUG, lg, "\t\tMainoption id: %lld", m->id); + for(t = m->target; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\t\tTarget id: %lld", t->value); + } + } + assert(o->suboptions == NULL); + } +} diff --git a/hm_gameserver/src/proto/bnet.c b/hm_gameserver/src/proto/bnet.c new file mode 100644 index 0000000..21010d5 --- /dev/null +++ b/hm_gameserver/src/proto/bnet.c @@ -0,0 +1,31 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int bnet_size(struct powerhistory_player_s *player) +{ + int size = 0; + + if(player) { + size += 2; + size += sizeofu64(player->bnet_hi); + size += sizeofu64(player->bnet_lo); + } + + return size; +} diff --git a/hm_gameserver/src/proto/chooseentities.c b/hm_gameserver/src/proto/chooseentities.c new file mode 100644 index 0000000..b27abb2 --- /dev/null +++ b/hm_gameserver/src/proto/chooseentities.c @@ -0,0 +1,65 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void chooseentities_free(struct chooseentities_s *c) +{ + struct chooseentities_ent_s *e, *del; + + for(e = c->entity; e != NULL; del = e, e = e->next, free(del)); + + free(c); +} + +void *chooseentities_deserialize(char **dst, const char *maxdst) +{ + int n, i; + struct chooseentities_s *c; + struct chooseentities_ent_s *e; + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + + c->id = read_uint64(dst, maxdst); + c->entity = NULL; + + n = read_byte(dst, maxdst); + if(n != 18) { + return c; + } + + c->nentity = read_uint(dst, maxdst); + if(c->nentity > 5 || c->nentity < 0) { + free(c); + return NULL; + } + + for(i = 0; i < c->nentity && *dst < maxdst; i++) { + e = malloc(sizeof(*e)); + e->entity = read_uint(dst, maxdst); + e->next = c->entity; + c->entity = e; + } + + return c; +} diff --git a/hm_gameserver/src/proto/chooseoption.c b/hm_gameserver/src/proto/chooseoption.c new file mode 100644 index 0000000..ce2a189 --- /dev/null +++ b/hm_gameserver/src/proto/chooseoption.c @@ -0,0 +1,69 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void chooseoption_free(struct chooseoption_s *c) +{ + free(c); +} + +void *chooseoption_deserialize(char **dst, const char *maxdst) +{ + int n; + struct chooseoption_s *o; + + o = malloc(sizeof(*o)); + memset(o, 0, sizeof(*o)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + o->id = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + o->index = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + o->target = read_uint64(dst, maxdst); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 32) { + o->suboption = read_uint64(dst, maxdst); + } else if(n == 40) { + o->position = read_uint64(dst, maxdst); + } else { + error(); + } + } + + return o; +} + +void chooseoption_dump(struct chooseoption_s *o, u64 local_held_card) +{ + hm_log(LOG_ALERT, lg, "Choose options dump: option id: %lld index: %lld target: %lld suboption: %lld position: %lld local held card: %lld", o->id, o->index, o->target, o->suboption, o->position, local_held_card); + +} diff --git a/hm_gameserver/src/proto/creategame.c b/hm_gameserver/src/proto/creategame.c new file mode 100644 index 0000000..2abf48a --- /dev/null +++ b/hm_gameserver/src/proto/creategame.c @@ -0,0 +1,109 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void creategame_free(struct powerhistory_creategame_s *c) +{ + struct powerhistory_player_s *player, *del; + + for(player = c->player; player != NULL; del = player, player = player->next, player_free(del)); + + free(c); +} + +struct powerhistory_creategame_s *creategame_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_creategame_s *t; + struct powerhistory_player_s *player; + + t = malloc(sizeof(*t)); + t->player = t->player_tail = NULL; + + n = read_byte(dst, maxdst); + + if(n != 10) { + error(); + } + len = read_uint(dst, maxdst); + + t->game_entity = game_entity_deserialize(dst, *dst + len); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + + len = read_uint(dst, maxdst); + + player = player_deserialize(dst, *dst + len); + player->next = NULL; + + if(t->player == NULL && t->player_tail == NULL) { + t->player = player; + t->player_tail = player; + } else { + t->player_tail->next = player; + t->player_tail = player; + } + } + + return t; +} + +int creategame_size(struct powerhistory_creategame_s *cg) +{ + struct powerhistory_player_s *p; + int num = 0; + int n; + + if(cg) { + num += 1; + n = game_entity_size(cg->game_entity); + num += sizeofu32(n) + n; + + for(p = cg->player; p != NULL; p = p->next) { + num += 1; + n = player_size(p); + num += sizeofu32(n) + n; + } + } + + return num; +} + +int creategame_serialize(struct powerhistory_creategame_s *cg, char **dst, const char *maxdst) +{ + int n; + struct powerhistory_player_s *p; + + write_byte(dst, maxdst, 10); + n = game_entity_size(cg->game_entity); + write_uint(dst, maxdst, n); + game_entity_serialize(cg->game_entity, dst, maxdst); + + for(p = cg->player; p != NULL; p = p->next) { + write_byte(dst, maxdst, 18); + n = player_size(p); + write_uint(dst, maxdst, n); + player_serialize(p, dst, maxdst); + } + + return 0; +} diff --git a/hm_gameserver/src/proto/deserialize.c b/hm_gameserver/src/proto/deserialize.c new file mode 100644 index 0000000..9786b84 --- /dev/null +++ b/hm_gameserver/src/proto/deserialize.c @@ -0,0 +1,120 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +#define MAP_PACKET_MAX 12 + +typedef int (*f)(void *c); + +static struct packet_deserialize_s map_packet[MAP_PACKET_MAX] = { + {P_GETGAMESTATE, NULL, NULL, NULL}, + {P_CHOOSEOPTION, chooseoption_deserialize, NULL, (f)chooseoption_free}, + {P_TURNTIMER, NULL, turntimer_serialize, (f)turntimer_free}, + {P_CHOOSEENTITIES, chooseentities_deserialize, NULL, (f)chooseentities_free}, + {P_ALLOPTIONS, NULL, alloptions_serialize, (f)alloptions_free}, + {P_ENTITYCHOICES, NULL, entitychoices_serialize, (f)entitychoices_free}, + {P_GAMESETUP, NULL, gamesetup_serialize, (f)gamesetup_free}, + {P_USERUI, userui_deserialize, userui_serialize, (f)userui_free}, + {P_POWERHISTORY, powerhistory_deserialize, powerhistory_serialize, (f)powerhistory_free}, + {P_HANDSHAKE, handshake_deserialize, NULL, (f)handshake_free}, + {P_PING, NULL, NULL, NULL}, + {P_PONG, NULL, NULL, NULL}, +}; + +struct packet_s *deserialize(char **dst, const char *maxdst) +{ + struct packet_s *p; + int i; + + if(!(dst != NULL && *dst != NULL && *dst < maxdst)) { + return NULL; + } + + p = malloc(sizeof(*p)); + + p->id = read_mem_int(dst, maxdst); + p->len = read_mem_int(dst, maxdst); + + for(i = 0; i < MAP_PACKET_MAX; i++) { + if(map_packet[i].id == p->id) { + if(map_packet[i].deserialize) { + p->data = map_packet[i].deserialize(dst, maxdst); + assert(p->data); + } + return p; + } + } + + free(p); + + return NULL; +} + +void packet_free(struct packet_s *p) +{ + int i; + + for(i = 0; i < MAP_PACKET_MAX; i++) { + if(map_packet[i].id == p->id) { + if(map_packet[i].free) { + map_packet[i].free(p->data); + } + + free(p); + break; + } + } +} + +int serialize(struct packet_s *p, char **dst, const char *maxdst) +{ + int i, n = 0; + char *off_len; + + write_mem_int(dst, maxdst, p->id); + off_len = *dst; + write_mem_int(dst, maxdst, 0); // make space for length + + n += 2 * sizeof(int); + + for(i = 0; i < MAP_PACKET_MAX; i++) { + if(map_packet[i].id == p->id) { + if(map_packet[i].serialize) { + n += map_packet[i].serialize(p->data, dst, maxdst); + } + + write_mem_int(&off_len, maxdst, n - (2 * sizeof(int))); + + return n; + } + } + + return -1; +} + +struct packet_s *packet_init(enum packet_e id, void *data) +{ + struct packet_s *p; + + p = malloc(sizeof(*p)); + + p->id = id; + p->data = data; + + return p; +} diff --git a/hm_gameserver/src/proto/entity.c b/hm_gameserver/src/proto/entity.c new file mode 100644 index 0000000..4ae9d3d --- /dev/null +++ b/hm_gameserver/src/proto/entity.c @@ -0,0 +1,119 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void entity_free(struct powerhistory_entity_s *e) +{ + struct powerhistory_tag_s *tag, *del; + + for(tag = e->tag; tag != NULL; del = tag, tag = tag->next, tag_free(del)); + + //free(e->name); + + free(e); +} + +struct powerhistory_entity_s *entity_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_entity_s *p; + struct powerhistory_tag_s *t; + + p = malloc(sizeof(*p)); + + p->tag = p->tag_tail = NULL; + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + + p->entity = read_uint64(dst, maxdst); + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + + p->name = read_bytes(dst, maxdst, &p->nname); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + len = read_uint(dst, maxdst); + + if(n == 26) { + t = tag_deserialize(dst, *dst + len); + t->next = NULL; + + if(p->tag == NULL && p->tag_tail == NULL) { + p->tag = t; + p->tag_tail = t; + } else { + p->tag_tail->next = t; + p->tag_tail = t; + } + } else { + error(); + return NULL; + } + } + + return p; +} + + +int entity_size(struct powerhistory_entity_s *ent) +{ + int num = 0; + int ts; + struct powerhistory_tag_s *tag; + + num += 2; + num += sizeofu64(ent->entity); + num += sizeofu32(ent->nname) + ent->nname; + + for(tag = ent->tag; tag != NULL; tag = tag->next) { + num += 1; + ts = tag_size(tag); + num += sizeofu32(ts) + ts; + } + + return num; +} + +int entity_serialize(struct powerhistory_entity_s *ent, char **dst, const char *maxdst) +{ + int ts; + struct powerhistory_tag_s *t; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->entity); + + write_byte(dst, maxdst, 18); + write_bytes(dst, maxdst, ent->name, ent->nname); + + if(ent->tag) { + for(t = ent->tag; t != NULL; t = t->next) { + write_byte(dst, maxdst, 26); + ts = tag_size(t); + write_uint(dst, maxdst, ts); + tag_serialize(t, dst, maxdst); + } + } + + return 0; +} diff --git a/hm_gameserver/src/proto/entitychoices.c b/hm_gameserver/src/proto/entitychoices.c new file mode 100644 index 0000000..c5faa5a --- /dev/null +++ b/hm_gameserver/src/proto/entitychoices.c @@ -0,0 +1,89 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void entitychoices_free(struct entitychoices_s *ec) +{ + struct entitychoices_entities_s *e, *del; + + for(e = ec->entities; e != NULL; del = e, e = e->next, free(del)); + + free(ec); +} + +int entitychoices_serialize(void *ep, char **dst, const char *maxdst) +{ + int n = 0; + struct entitychoices_entities_s *es; + struct entitychoices_s *e = ep; + char *start; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, e->id); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, e->type); + + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, e->countmin); + + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, e->countmax); + + if(e->entities) { + write_byte(dst, maxdst, 50); + for(es = e->entities; es != NULL; es = es->next) { + n += sizeofu64(es->entity); + } + + write_uint(dst, maxdst, n); + + for(es = e->entities; es != NULL; es = es->next) { + write_uint64(dst, maxdst, es->entity); + } + } + + if(e->source > 0) { + write_byte(dst, maxdst, 56); + write_uint64(dst, maxdst, e->source); + } + + write_byte(dst, maxdst, 64); + write_uint64(dst, maxdst, e->player_id); + + return (*dst - start); +} + +void entitychoices_dump(struct entitychoices_s *es) +{ + struct entitychoices_entities_s *ent; + + hm_log(LOG_DEBUG, lg, "Entity Choices dump:"); + hm_log(LOG_DEBUG, lg, "\t\tID: %lld", es->id); + hm_log(LOG_DEBUG, lg, "\t\tType: %lld", es->type); + hm_log(LOG_DEBUG, lg, "\t\tCountMin: %lld", es->countmin); + hm_log(LOG_DEBUG, lg, "\t\tCountMax: %lld", es->countmax); + hm_log(LOG_DEBUG, lg, "\t\tSource: %lld", es->source); + hm_log(LOG_DEBUG, lg, "\t\tPlayer: %lld", es->player_id); + + for(ent = es->entities; ent != NULL; ent = ent->next) { + hm_log(LOG_DEBUG, lg, "\t\t\tChild entity: %lld", ent->entity); + } +} diff --git a/hm_gameserver/src/proto/game_entity.c b/hm_gameserver/src/proto/game_entity.c new file mode 100644 index 0000000..3b332d1 --- /dev/null +++ b/hm_gameserver/src/proto/game_entity.c @@ -0,0 +1,105 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void game_entity_free(struct powerhistory_game_entity_s *g) +{ + struct powerhistory_tag_s *tag, *del; + + for(tag = g->tag; tag != NULL; del = tag, tag = tag->next, tag_free(del)); + + free(g); +} + +struct powerhistory_game_entity_s *game_entity_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_game_entity_s *t; + struct powerhistory_tag_s *tag; + + t = malloc(sizeof(*t)); + memset(t, 0, sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + + t->id = read_uint64(dst, maxdst); + + while(*dst < maxdst) { + + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + + len = read_uint(dst, maxdst); + + tag = tag_deserialize(dst, *dst + len); + tag->next = NULL; + + if(t->tag == NULL && t->tag_tail == NULL) { + t->tag = tag; + t->tag_tail = tag; + } else { + t->tag_tail->next = tag; + t->tag_tail = tag; + } + } + + return t; +} + +int game_entity_serialize(struct powerhistory_game_entity_s *ent, char **dst, const char *maxdst) +{ + int ts; + struct powerhistory_tag_s *t; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->id); + + if(ent->tag) { + for(t = ent->tag; t != NULL; t = t->next) { + write_byte(dst, maxdst, 18); + ts = tag_size(t); + write_uint(dst, maxdst, ts); + tag_serialize(t, dst, maxdst); + } + } + + return 0; +} + +int game_entity_size(struct powerhistory_game_entity_s *ent) +{ + int ts; + struct powerhistory_tag_s *tag; + int num = 0; + + num += 1; + num += sizeofu64(ent->id); + + for(tag = ent->tag; tag != NULL; tag = tag->next) { + num += 1; + ts = tag_size(tag); + num += sizeofu32(ts) + ts; + } + + return num; +} diff --git a/hm_gameserver/src/proto/gamesetup.c b/hm_gameserver/src/proto/gamesetup.c new file mode 100644 index 0000000..b8d4daa --- /dev/null +++ b/hm_gameserver/src/proto/gamesetup.c @@ -0,0 +1,81 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void gamesetup_free(struct gamesetup_s *g) +{ + free(g); +} + +struct gamesetup_s *gamesetup_deserialize(char **dst, const char *maxdst) +{ + abort(); + return NULL; +} + +int gamesetup_serialize(void *data, char **dst, const char *maxdst) +{ + char *start; + struct gamesetup_s *g = data; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, g->board); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, g->maxsecrets); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, g->maxfriendlyminions); + + + if(g->keepalive > 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, g->keepalive); + } + + if(g->stuckdisconnect > 0) { + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, g->stuckdisconnect); + } + + return (*dst - start); +} + +int gamesetup_size(struct gamesetup_s *g) +{ + int num = 0; + + num += 3; + num += sizeofu64(g->board); + num += sizeofu64(g->maxsecrets); + num += sizeofu64(g->maxfriendlyminions); + + if(g->keepalive > 0) { + num += 1; + num += sizeofu64(g->keepalive); + } + + if(g->stuckdisconnect > 0) { + num += 1; + num += sizeofu64(g->stuckdisconnect); + } + + return num; +} diff --git a/hm_gameserver/src/proto/handshake.c b/hm_gameserver/src/proto/handshake.c new file mode 100644 index 0000000..c89d295 --- /dev/null +++ b/hm_gameserver/src/proto/handshake.c @@ -0,0 +1,83 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void handshake_free(struct handshake_s *h) +{ + platform_free(h->platform); + + free(h->version); + free(h->password); + + free(h); +} + +void *handshake_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct handshake_s *h; + + h = malloc(sizeof(*h)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + h->gamehandle = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + h->password = read_bytes(dst, maxdst, &h->npassword); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + h->clienthandle = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n == 32) { + h->mission = read_uint64(dst, maxdst); + n = read_byte(dst, maxdst); + } + + if(n != 42) { + error(); + } + h->version = read_bytes(dst, maxdst, &h->nversion); + + n = read_byte(dst, maxdst); + if(n != 58) { + error(); + } + len = read_uint(dst, maxdst); + h->platform = platform_deserialize(dst, *dst + len); + + return h; +} + +void handshake_dump(struct handshake_s *h) +{ + hm_log(LOG_DEBUG, lg, "Gamehandle: %lld password: [%.*s] clienthandle: %lld mission: %lld verion: [%.*s] ", h->gamehandle, h->npassword, h->password, h->clienthandle, h->mission, h->nversion, h->version); + if(h->platform) { + hm_log(LOG_DEBUG, lg, "Os: %lld screen: %lld name: [%.*s] store: %lld", h->platform->os, h->platform->screen, h->platform->nname, h->platform->name, h->platform->store); + + } +} diff --git a/hm_gameserver/src/proto/hide.c b/hm_gameserver/src/proto/hide.c new file mode 100644 index 0000000..d1bc19f --- /dev/null +++ b/hm_gameserver/src/proto/hide.c @@ -0,0 +1,69 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void hide_free(struct powerhistory_hide_s *t) +{ + free(t); +} + +struct powerhistory_hide_s *hide_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_hide_s *t; + + t = malloc(sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + t->entity = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + t->zone = read_uint64(dst, maxdst); + + return t; +} + +int hide_serialize(struct powerhistory_hide_s *ent, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->entity); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, ent->zone); + + return 0; +} + +int hide_size(struct powerhistory_hide_s *hide) +{ + int size = 0; + + if(hide) { + size += 2; + size += sizeofu64(hide->entity); + size += sizeofu64(hide->zone); + } + + return size; +} diff --git a/hm_gameserver/src/proto/meta.c b/hm_gameserver/src/proto/meta.c new file mode 100644 index 0000000..fb47069 --- /dev/null +++ b/hm_gameserver/src/proto/meta.c @@ -0,0 +1,126 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void meta_free(struct powerhistory_meta_s *t) +{ + struct powerhistory_info_s *info, *del; + + for(info = t->info; info != NULL; del = info, info = info->next, free(del)); + + free(t); +} + +struct powerhistory_meta_s *meta_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_meta_s *t; + struct powerhistory_info_s *info; + int i; + + t = malloc(sizeof(*t)); + memset(t, 0, sizeof(*t)); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 18) { + len = read_uint(dst, maxdst); + + for(i = 0; i < len; i++) { + info = malloc(sizeof(*info)); + info->id = read_uint64(dst, maxdst); + info->next = NULL; + + if(t->info == NULL && t->info_tail == NULL) { + t->info = info; + t->info_tail = info; + } else { + t->info_tail->next = info; + t->info_tail = info; + } + } + } else if(n == 24) { + t->type = read_uint64(dst, maxdst); + } else if(n == 32) { + t->data = read_uint64(dst, maxdst); + } else { + error(); + } + } + + return t; +} + + +int meta_size(struct powerhistory_meta_s *p) +{ + int num = 0, num2; + struct powerhistory_info_s *m; + + if(p->info) { + num += 1; + num2 = num; + for(m = p->info; m != NULL; m = m->next) { + num += sizeofu64(m->id); + } + num += sizeofu32(num - num2); + } + + if(p->type != 0) { + num += 1; + num += sizeofu64(p->type); + } + + if(p->data != 0) { + num += 1; + num += sizeofu64(p->data); + } + + return num; +} + +int meta_serialize(struct powerhistory_meta_s *p, char **dst, const char *maxdst) +{ + int num = 0; + struct powerhistory_info_s *m; + + if(p->info) { + write_byte(dst, maxdst, 18); + for(m = p->info; m != NULL; m = m->next) { + num += sizeofu64(m->id); + } + + write_uint(dst, maxdst, num); + + for(m = p->info; m != NULL; m = m->next) { + write_uint64(dst, maxdst, m->id); + } + } + + if(p->type != 0) { + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, p->type); + } + + if(p->data != 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, p->data); + } + + return 0; +} diff --git a/hm_gameserver/src/proto/mouseinfo.c b/hm_gameserver/src/proto/mouseinfo.c new file mode 100644 index 0000000..2ab3dcf --- /dev/null +++ b/hm_gameserver/src/proto/mouseinfo.c @@ -0,0 +1,104 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mouseinfo_free(struct mouseinfo_s *m) +{ + free(m); +} + +void *mouseinfo_deserialize(char **dst, const char *maxdst) +{ + int n; + struct mouseinfo_s *c; + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + c->arroworigin = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + c->heldcard = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + c->overcard = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 32) { + error(); + } + c->x = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 40) { + error(); + } + c->y = read_uint64(dst, maxdst); + + return c; +} + +int mouseinfo_serialize(void *ao, char **dst, const char *maxdst) +{ + struct mouseinfo_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->arroworigin); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->heldcard); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, s->overcard); + + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, s->x); + + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, s->y); + + return (*dst - start); +} + +int mouseinfo_size(struct mouseinfo_s *p) +{ + int num = 0; + + num += 5; + num += sizeofu64(p->arroworigin); + num += sizeofu64(p->heldcard); + num += sizeofu64(p->overcard); + num += sizeofu64(p->x); + num += sizeofu64(p->y); + + return num; +} diff --git a/hm_gameserver/src/proto/option.c b/hm_gameserver/src/proto/option.c new file mode 100644 index 0000000..0c974d9 --- /dev/null +++ b/hm_gameserver/src/proto/option.c @@ -0,0 +1,84 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void option_free(struct option_s *o) +{ + struct suboption_s *s, *del; + + for(s = o->mainoption; s != NULL; del = s, s = s->next, suboption_free(del)); + + for(s = o->suboptions; s != NULL; del = s, s = s->next, suboption_free(del)); + + free(o); +} + +int option_serialize(struct option_s *s, char **dst, const char *maxdst) +{ + int n = 0; + struct suboption_s *m; + char *start; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->type); + + if(s->mainoption) { + write_byte(dst, maxdst, 18); + n = suboption_size(s->mainoption); + write_uint(dst, maxdst, n); + suboption_serialize(s->mainoption, dst, maxdst); + } + + if(s->suboptions) { + for(m = s->suboptions; m != NULL; m = m->next) { + write_byte(dst, maxdst, 26); + n = suboption_size(m); + write_uint(dst, maxdst, n); + suboption_serialize(m, dst, maxdst); + } + } + + return (*dst - start); +} + +int option_size(struct option_s *p) +{ + int num = 0, n; + struct suboption_s *s; + + num += 1; + num += sizeofu64(p->type); + + if(p->mainoption) { + num += 1; + n = suboption_size(p->mainoption); + num += sizeofu32(n) + n; + } + + if(p->suboptions) { + for(s = p->suboptions; s != NULL; s = s->next) { + num += 1; + n = suboption_size(s); + num += sizeofu32(n) + n; + } + } + + return num; +} diff --git a/hm_gameserver/src/proto/platform.c b/hm_gameserver/src/proto/platform.c new file mode 100644 index 0000000..dd23019 --- /dev/null +++ b/hm_gameserver/src/proto/platform.c @@ -0,0 +1,61 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void platform_free(struct platform_s *p) +{ + free(p->name); + + free(p); +} + +struct platform_s *platform_deserialize(char **dst, const char *maxdst) +{ + int n; + struct platform_s *h; + + h = malloc(sizeof(*h)); + h->store = 0; + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + h->os = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + h->screen = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 26) { + error(); + } + h->name = read_bytes(dst, maxdst, &h->nname); + + if(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 32) { + h->store = read_uint64(dst, maxdst); + } + } + + return h; +} diff --git a/hm_gameserver/src/proto/player.c b/hm_gameserver/src/proto/player.c new file mode 100644 index 0000000..cf5a167 --- /dev/null +++ b/hm_gameserver/src/proto/player.c @@ -0,0 +1,116 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void player_free(struct powerhistory_player_s *p) +{ + game_entity_free(p->entity); + + free(p); +} + +struct powerhistory_player_s *player_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_player_s *player; + + player = malloc(sizeof(*player)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + player->id = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + len = read_uint(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + player->bnet_hi = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + player->bnet_lo = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + player->cardback = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 34) { + error(); + } + len = read_uint(dst, maxdst); + player->entity = game_entity_deserialize(dst, *dst + len); + + return player; +} + +int player_serialize(struct powerhistory_player_s *player, char **dst, const char *maxdst) +{ + int n; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, player->id); + + // bnet + write_byte(dst, maxdst, 18); + n = bnet_size(player); + write_uint(dst, maxdst, n); + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, player->bnet_hi); + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, player->bnet_lo); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, player->cardback); + + write_byte(dst, maxdst, 34); + n = game_entity_size(player->entity); + write_uint(dst, maxdst, n); + game_entity_serialize(player->entity, dst, maxdst); + + return 0; +} + +int player_size(struct powerhistory_player_s *p) +{ + int size = 0, ts; + + if(p) { + size += 4; + size += sizeofu64(p->id); + ts = bnet_size(p); + size += sizeofu32(ts) + ts; + size += sizeofu64(p->cardback); + ts = game_entity_size(p->entity); + size += sizeofu32(ts) + ts; + } + + return size; +} diff --git a/hm_gameserver/src/proto/powerend.c b/hm_gameserver/src/proto/powerend.c new file mode 100644 index 0000000..3aa161f --- /dev/null +++ b/hm_gameserver/src/proto/powerend.c @@ -0,0 +1,42 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerend_free(struct powerhistory_powerend_s *p) +{ + free(p); +} + +struct powerhistory_powerend_s *powerend_deserialize(char **dst, const char *maxdst) +{ + struct powerhistory_powerend_s *t; + + t = malloc(sizeof(*t)); + + return t; +} + +int powerend_serialize(struct powerhistory_powerend_s *t, char **dst, const char *maxdst) +{ + return 0; +} + +int powerend_size(struct powerhistory_powerend_s *p) +{ + return 0; +} diff --git a/hm_gameserver/src/proto/powerhistory.c b/hm_gameserver/src/proto/powerhistory.c new file mode 100644 index 0000000..ec28c9c --- /dev/null +++ b/hm_gameserver/src/proto/powerhistory.c @@ -0,0 +1,183 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerhistory_free(struct powerhistory_s *p) +{ + struct powerhistory_data_s *d, *del; + + for(d = p->data; d != NULL; del = d, d = d->next, powerhistory_data_free(del)); + + free(p); +} + +void *powerhistory_deserialize(char **dst, const char *maxdst) +{ + struct powerhistory_s *p; + struct powerhistory_data_s *d; + int n, len; + + p = malloc(sizeof(*p)); + p->data = NULL; + p->data_tail = NULL; + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + len = read_uint(dst, maxdst); + + if(n == 10) { + d = powerhistory_data_deserialize(dst, *dst + len); + d->next = NULL; + + if(p->data == NULL && p->data_tail == NULL) { + p->data = d; + p->data_tail = d; + } else { + p->data_tail->next = d; + p->data_tail = d; + } + + } else { + error(); + return NULL; + } + } + + return p; +} + +int powerhistory_serialize(void *data, char **dst, const char *maxdst) +{ + int n, o = 0; + struct powerhistory_data_s *d; + struct powerhistory_s *ph = data; + + if(ph->data) { + for(d = ph->data; d != NULL; d = d->next) { + write_byte(dst, maxdst, 10); + o += 1; + n = powerhistorydata_size(d); + write_uint(dst, maxdst, n); + o += sizeofu32(n) + n; + powerhistorydata_serialize(d, dst, maxdst); + } + } + + return o; +} + +int powerhistory_size(struct powerhistory_s *ph) +{ + struct powerhistory_data_s *d; + int n, num = 0; + + if(ph->data) { + for(d = ph->data; d != NULL; d = d->next) { + num += 1; + n = powerhistorydata_size(d); + num += n + sizeofu32(n); + } + } + + return num; +} + +void powerhistory_dump(struct powerhistory_s *p) +{ + struct powerhistory_tag_s *t; + struct powerhistory_data_s *d; + struct powerhistory_game_entity_s *ge; + struct powerhistory_player_s *player; + struct powerhistory_info_s *i; + int it = 0; + + assert(p); + + for(d = p->data; d != NULL; d = d->next) { + hm_log(LOG_DEBUG, lg, "Data %d", it++); + + if(d->full) { + hm_log(LOG_DEBUG, lg, "data->full:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->full->entity, d->full->nname, d->full->name); + for(t = d->full->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + + if(d->show) { + hm_log(LOG_DEBUG, lg, "data->show:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->show->entity, d->show->nname, d->show->name); + for(t = d->show->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + + if(d->hide) { + hm_log(LOG_DEBUG, lg, "data->hide:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld zone: %lld", d->hide->entity, d->hide->zone); + } + + if(d->tagchange) { + hm_log(LOG_DEBUG, lg, "data->tagchange:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld tag: %lld value: %lld", d->tagchange->entity, d->tagchange->tag, d->tagchange->value); + } + + if(d->creategame) { + ge = d->creategame->game_entity; + hm_log(LOG_DEBUG, lg, "game entity id: %lld", ge->id); + for(t = ge->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\ttag name: %lld value: %lld", t->name, t->value); + } + + for(player = d->creategame->player; player != NULL; player = player->next) { + hm_log(LOG_DEBUG, lg, "\t\tdata->creategame->player:"); + hm_log(LOG_DEBUG, lg, "\t\t\tid: %lld bhi: %lld blo: %lld cardback: %lld", player->id, player->bnet_hi, player->bnet_lo, player->cardback); + ge = player->entity; + hm_log(LOG_DEBUG, lg, "\t\t\tplayer->entity: %lld", ge->id); + for(t = ge->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\t\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + } + + if(d->powerstart) { + hm_log(LOG_DEBUG, lg, "data->powerstart"); + hm_log(LOG_DEBUG, lg, "\ttype: %lld index: %lld source: %lld target: %lld card: [%.*s]", d->powerstart->type, d->powerstart->index, d->powerstart->source, d->powerstart->target, d->powerstart->ncard_id, d->powerstart->card_id); + } + + if(d->powerend) { + hm_log(LOG_DEBUG, lg, "data->powerend"); + } + + if(d->change_entity) { + hm_log(LOG_DEBUG, lg, "data->change_entity:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->change_entity->entity, d->change_entity->nname, d->change_entity->name); + for(t = d->change_entity->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + + if(d->meta) { + hm_log(LOG_DEBUG, lg, "data->meta:"); + hm_log(LOG_DEBUG, lg, "\ttype: %lld data: %lld", d->meta->type, d->meta->data); + for(i = d->meta->info; i != NULL; i = i->next) { + hm_log(LOG_DEBUG, lg, "\t\t\tinfo id: %lld", i->id); + } + } + } +} diff --git a/hm_gameserver/src/proto/powerhistorydata.c b/hm_gameserver/src/proto/powerhistorydata.c new file mode 100644 index 0000000..1554643 --- /dev/null +++ b/hm_gameserver/src/proto/powerhistorydata.c @@ -0,0 +1,200 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerhistory_data_free(struct powerhistory_data_s *d) +{ + if(d->full) entity_free(d->full); + if(d->show) entity_free(d->show); + if(d->hide) hide_free(d->hide); + if(d->tagchange) tagchange_free(d->tagchange); + if(d->creategame) creategame_free(d->creategame); + if(d->powerstart) powerstart_free(d->powerstart); + if(d->powerend) powerend_free(d->powerend); + if(d->change_entity) entity_free(d->change_entity); + if(d->meta) meta_free(d->meta); + + free(d); +} + +struct powerhistory_data_s *powerhistory_data_deserialize(char **dst, const char *maxdst) +{ + struct powerhistory_data_s *p; + int n, len; + + p = malloc(sizeof(*p)); + memset(p, 0, sizeof(*p)); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + len = read_uint(dst, maxdst); + + if(n == 10) { + p->full = entity_deserialize(dst, *dst + len); + } else if(n == 18) { + p->show = entity_deserialize(dst, *dst + len); + } else if(n == 26) { + p->hide = hide_deserialize(dst, *dst + len); + } else if(n == 34) { + p->tagchange = tagchange_deserialize(dst, *dst + len); + } else if(n == 42) { + p->creategame = creategame_deserialize(dst, *dst + len); + } else if(n == 50) { + p->powerstart = powerstart_deserialize(dst, *dst + len); + } else if(n == 58) { + p->powerend = powerend_deserialize(dst, *dst + len); + } else if(n == 66) { + p->meta = meta_deserialize(dst, *dst + len); + } else { + return NULL; + } + } + + return p; +} + +int powerhistorydata_serialize(struct powerhistory_data_s *phd, char **dst, const char *maxdst) +{ + int n; + + if(phd->full) { + write_byte(dst, maxdst, 10); + n = entity_size(phd->full); + write_uint(dst, maxdst, n); + entity_serialize(phd->full, dst, maxdst); + } + + if(phd->show) { + write_byte(dst, maxdst, 18); + n = entity_size(phd->show); + write_uint(dst, maxdst, n); + entity_serialize(phd->show, dst, maxdst); + } + + if(phd->hide) { + write_byte(dst, maxdst, 26); + n = hide_size(phd->hide); + write_uint(dst, maxdst, n); + hide_serialize(phd->hide, dst, maxdst); + } + + if(phd->tagchange) { + write_byte(dst, maxdst, 34); + n = tagchange_size(phd->tagchange); + write_uint(dst, maxdst, n); + tagchange_serialize(phd->tagchange, dst, maxdst); + } + + if(phd->creategame) { + write_byte(dst, maxdst, 42); + n = creategame_size(phd->creategame); + write_uint(dst, maxdst, n); + creategame_serialize(phd->creategame, dst, maxdst); + } + + if(phd->powerstart) { + write_byte(dst, maxdst, 50); + n = powerstart_size(phd->powerstart); + write_uint(dst, maxdst, n); + powerstart_serialize(phd->powerstart, dst, maxdst); + } + + if(phd->powerend) { + write_byte(dst, maxdst, 58); + n = powerend_size(phd->powerend); + write_uint(dst, maxdst, n); + powerend_serialize(phd->powerend, dst, maxdst); + } + + if(phd->meta) { + write_byte(dst, maxdst, 66); + n = meta_size(phd->meta); + write_uint(dst, maxdst, n); + meta_serialize(phd->meta, dst, maxdst); + } + + if(phd->change_entity) { + write_byte(dst, maxdst, 74); + n = entity_size(phd->change_entity); + write_uint(dst, maxdst, n); + entity_serialize(phd->change_entity, dst, maxdst); + } + + return 0; +} + +int powerhistorydata_size(struct powerhistory_data_s *phd) +{ + int num = 0, n; + + if(phd->full) { + num += 1; + n = entity_size(phd->full); + num += n + sizeofu32(n); + } + + if(phd->show) { + num += 1; + n = entity_size(phd->show); + num += n + sizeofu32(n); + } + + if(phd->hide) { + num += 1; + n = hide_size(phd->hide); + num += n + sizeofu32(n); + } + + if(phd->tagchange) { + num += 1; + n = tagchange_size(phd->tagchange); + num += n + sizeofu32(n); + } + + if(phd->creategame) { + num += 1; + n = creategame_size(phd->creategame); + num += n + sizeofu32(n); + } + + if(phd->powerstart) { + num += 1; + n = powerstart_size(phd->powerstart); + num += n + sizeofu32(n); + } + + if(phd->powerend) { + num += 1; + n = powerend_size(phd->powerend); + num += n + sizeofu32(n); + } + + if(phd->meta) { + num += 1; + n = meta_size(phd->meta); + num += n + sizeofu32(n); + } + + if(phd->change_entity) { + num += 1; + n = entity_size(phd->change_entity); + num += n + sizeofu32(n); + } + + return num; +} diff --git a/hm_gameserver/src/proto/powerstart.c b/hm_gameserver/src/proto/powerstart.c new file mode 100644 index 0000000..883637e --- /dev/null +++ b/hm_gameserver/src/proto/powerstart.c @@ -0,0 +1,112 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerstart_free(struct powerhistory_powerstart_s *p) +{ + free(p->card_id); + + free(p); +} + +struct powerhistory_powerstart_s *powerstart_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_powerstart_s *t; + + t = malloc(sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + t->type = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + t->index = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + t->source = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 32) { + error(); + } + t->target = read_uint64(dst, maxdst); + + t->ncard_id = 0; + t->card_id = NULL; + // optional + n = read_byte(dst, maxdst); + if(n != 42) { + return t; + } + + t->card_id = read_bytes(dst, maxdst, &t->ncard_id); + + return t; +} + +int powerstart_serialize(struct powerhistory_powerstart_s *p, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, p->type); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, p->index); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, p->source); + + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, p->target); + + if(p->ncard_id > 0) { + write_byte(dst, maxdst, 42); + write_bytes(dst, maxdst, p->card_id, p->ncard_id); + } + + return 0; +} + +int powerstart_size(struct powerhistory_powerstart_s *p) +{ + int size = 0; + int n; + + if(p) { + size += 4; + size += sizeofu64(p->type); + size += sizeofu64(p->index); + size += sizeofu64(p->source); + size += sizeofu64(p->target); + if(p->ncard_id > 0) { + size += 1; + n = sizeofu64(p->ncard_id); + size += sizeofu32(n) + n; + } + } + + return size; +} diff --git a/hm_gameserver/src/proto/proto.c b/hm_gameserver/src/proto/proto.c new file mode 100644 index 0000000..5033032 --- /dev/null +++ b/hm_gameserver/src/proto/proto.c @@ -0,0 +1,231 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int sizeofu64(u64 val) +{ + unsigned int num = 1u; + + while(1 == 1) { + val >>= 7; + if(val == 0) { + break; + } + num++; + } + + return num; +} + +int sizeofu32(int val) +{ + unsigned int num = 1u; + + while(1 == 1) { + val >>= 7; + if(val == 0) { + break; + } + num++; + } + + return num; +} + +int read_mem_int(char **dst, const char *end) +{ + int n; + + if(*dst + sizeof(int) > end) { + return -1; + } + + n = *(int *)(*dst); + (*dst) += sizeof(int); + return n; +} + +int write_mem_int(char **dst, const char *end, const int src) +{ + if(*dst + sizeof(src) > end) { + hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", src, *dst, end); + abort(); + } + + memcpy(*dst, &src, sizeof(src)); + (*dst) += sizeof(src); + return 0; +} + + +int write_byte(char **dst, const char *end, char src) +{ + if(*dst + sizeof(src) > end) { + hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", src, *dst, end); + abort(); + } + + memcpy(*dst, &src, sizeof(src)); + (*dst)++; + return 0; +} + +char read_byte(char **dst, const char *end) +{ + char out; + + if(*dst + sizeof(char) > end) { + return -1; + } + + out = *((char *)(*dst)); + + (*dst)++; + return out; +} + +int skip(char **dst, const char *end, const int jump) +{ + if((*dst + jump) > end) { + hm_log(LOG_ALERT, lg, "Invalid skip %p %p %d", *dst, end, jump); + return -1; + } + + *dst += jump; + + return 0; +} + +int read_uint(char **dst, const char *end) +{ + int num = 0, num2; + int i; + + for(i = 0; (i < 5 && *dst < end); i++) { + num2 = read_byte(dst, end); + + if(i == 4 && (num2 & 240) != 0) { + hm_log(LOG_EMERG, lg, "Incorrect num size"); + abort(); + } + + if((num2 & 128) == 0) { + return num | (unsigned int)((unsigned int)num2 << 7 * i); + } + + num |= (unsigned int)((unsigned int)(num2 & 127) << 7 * i); + } + + return num; +} + +u64 read_uint64(char **dst, const char *end) +{ + u64 num = 0; + int num2; + int i; + + for(i = 0; (i < 10 && *dst < end); i++) { + num2 = read_byte(dst, end); + + if(i == 9 && (num2 & 254) != 0) { + hm_log(LOG_EMERG, lg, "Incorrect num size"); + abort(); + } + + if((num2 & 128) == 0) { + return num | (unsigned long long)((unsigned long long)num2 << 7 * i); + } + + num |= (unsigned long long)((unsigned long long)(num2 & 127) << 7 * i); + } + + return num; +} + +void write_uint(char **dst, const char *end, int src) +{ + char b; + + while(1 == 1) { + b = (char)(src & 127); + src >>= 7; + + if(src == 0) { + break; + } + + b |= 128; + + write_byte(dst, end, b); + } + + write_byte(dst, end, b); +} + +char *read_bytes(char **dst, const char *end, int *ndst) +{ + char *out; + + *ndst = read_uint(dst, end); + + if(*dst + *ndst > end) { + hm_log(LOG_EMERG, lg, "Dst read bytes %p %p %d", end, *dst + *ndst, *ndst); + abort(); + } + + out = malloc(*ndst); + memcpy(out, *dst, *ndst); + *dst += *ndst; + + return out; +} + +int write_bytes(char **dst, const char *end, const char *src, const int nsrc) +{ + if(*dst + nsrc > end) { + hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", nsrc, *dst, end); + abort(); + } + + write_uint(dst, end, nsrc); + + memcpy(*dst, src, nsrc); + (*dst) += nsrc; + return 0; +} + +void write_uint64(char **dst, const char *end, u64 src) +{ + char b; + + while(1 == 1) { + b = (char)(src & 127); + src >>= 7; + + if(src == 0) { + break; + } + + b |= 128; + + write_byte(dst, end, b); + } + + write_byte(dst, end, b); +} diff --git a/hm_gameserver/src/proto/suboption.c b/hm_gameserver/src/proto/suboption.c new file mode 100644 index 0000000..4e6e751 --- /dev/null +++ b/hm_gameserver/src/proto/suboption.c @@ -0,0 +1,75 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void suboption_free(struct suboption_s *s) +{ + struct suboption_target_s *t, *del; + + for(t = s->target; t != NULL; del = t, t = t->next, free(del)); + + free(s); +} + +int suboption_size(struct suboption_s *p) +{ + int num = 0, num2; + struct suboption_target_s *m; + + num += sizeofu64(p->id); + + if(p->target) { + num += 1; + num2 = num; + for(m = p->target; m != NULL; m = m->next) { + num += sizeofu64(m->value); + } + num += sizeofu32(num - num2); + } + + num += 1; + + return num; +} + +int suboption_serialize(struct suboption_s *s, char **dst, const char *maxdst) +{ + int num = 0; + struct suboption_target_s *m; + char *start; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->id); + + if(s->target) { + write_byte(dst, maxdst, 26); + for(m = s->target; m != NULL; m = m->next) { + num += sizeofu64(m->value); + } + + write_uint(dst, maxdst, num); + + for(m = s->target; m != NULL; m = m->next) { + write_uint64(dst, maxdst, m->value); + } + } + + return (*dst - start); +} diff --git a/hm_gameserver/src/proto/tag.c b/hm_gameserver/src/proto/tag.c new file mode 100644 index 0000000..6ed24ec --- /dev/null +++ b/hm_gameserver/src/proto/tag.c @@ -0,0 +1,73 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void tag_free(struct powerhistory_tag_s *t) +{ + free(t); +} + +struct powerhistory_tag_s *tag_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_tag_s *t; + + t = malloc(sizeof(*t)); + + + n = read_byte(dst, maxdst); + + if(n != 8) { + error(); + } + t->name = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + + if(n != 16) { + error(); + } + t->value = read_uint64(dst, maxdst); + + return t; +} + + +int tag_size(struct powerhistory_tag_s *tag) +{ + int size = 0; + + if(tag) { + size += 2; + size += sizeofu64(tag->name); + size += sizeofu64(tag->value); + } + + return size; +} + +int tag_serialize(struct powerhistory_tag_s *t, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, t->name); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, t->value); + + return 0; +} diff --git a/hm_gameserver/src/proto/tagchange.c b/hm_gameserver/src/proto/tagchange.c new file mode 100644 index 0000000..719dbbd --- /dev/null +++ b/hm_gameserver/src/proto/tagchange.c @@ -0,0 +1,79 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void tagchange_free(struct powerhistory_tagchange_s *t) +{ + free(t); +} + +struct powerhistory_tagchange_s *tagchange_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_tagchange_s *t; + + t = malloc(sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + t->entity = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + t->tag = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + t->value = read_uint64(dst, maxdst); + + return t; +} + +int tagchange_serialize(struct powerhistory_tagchange_s *ent, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->entity); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, ent->tag); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, ent->value); + + return 0; +} + +int tagchange_size(struct powerhistory_tagchange_s *t) +{ + int size = 0; + + if(t) { + size += 3; + size += sizeofu64(t->entity); + size += sizeofu64(t->tag); + size += sizeofu64(t->value); + } + + return size; +} diff --git a/hm_gameserver/src/proto/turntimer.c b/hm_gameserver/src/proto/turntimer.c new file mode 100644 index 0000000..2286e09 --- /dev/null +++ b/hm_gameserver/src/proto/turntimer.c @@ -0,0 +1,51 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void turntimer_free(struct turntimer_s *t) +{ + free(t); +} + +int turntimer_serialize(void *ao, char **dst, const char *maxdst) +{ + struct turntimer_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->seconds); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->turn); + + write_byte(dst, maxdst, 24); + write_byte(dst, maxdst, s->show); + + return (*dst - start); +} + +void turntimer_dump(struct turntimer_s *t) +{ + hm_log(LOG_DEBUG, lg, "Turn timer dump:"); + hm_log(LOG_DEBUG, lg, "\t\tseconds: %lld", t->seconds); + hm_log(LOG_DEBUG, lg, "\t\tturn: %lld", t->turn); + hm_log(LOG_DEBUG, lg, "\t\tshow: %d", t->show); +} diff --git a/hm_gameserver/src/proto/userui.c b/hm_gameserver/src/proto/userui.c new file mode 100644 index 0000000..25710be --- /dev/null +++ b/hm_gameserver/src/proto/userui.c @@ -0,0 +1,124 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void userui_free(struct userui_s *u) +{ + mouseinfo_free(u->mouseinfo); + + free(u); +} + +void *userui_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct userui_s *c; + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 10) { + len = read_uint(dst, maxdst); + c->mouseinfo = mouseinfo_deserialize(dst, *dst + len); + } + else if(n == 16) { + c->emote = read_uint64(dst, maxdst); + } + else if(n == 24) { + c->player_id = read_uint64(dst, maxdst); + } + } + + return c; +} + +int userui_serialize(void *ao, char **dst, const char *maxdst) +{ + struct userui_s *s; + char *start; + int n; + + start = *dst; + s = ao; + + if(s->mouseinfo) { + write_byte(dst, maxdst, 10); + n = mouseinfo_size(s->mouseinfo); + write_uint(dst, maxdst, n); + mouseinfo_serialize(s->mouseinfo, dst, maxdst); + } + + if(s->emote != -1) { + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->emote); + } + + if(s->player_id != -1) { + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, s->player_id); + } + + return (*dst - start); +} + +int userui_size(struct userui_s *p) +{ + int num = 0, n; + + if(p->mouseinfo) { + num += 1; + n = mouseinfo_size(p->mouseinfo); + num += n + sizeofu32(n); + } + + if(p->emote != 0) { + num += 1; + num += sizeofu64(p->emote); + } + + if(p->player_id != 0) { + num += 1; + num += sizeofu64(p->player_id); + } + + return num; +} + +void userui_dump(struct userui_s *u) +{ + if(u) { + if(u->mouseinfo) { + hm_log(LOG_DEBUG, lg, "arrow origin: %lld", u->mouseinfo->arroworigin); + hm_log(LOG_DEBUG, lg, "heldcard: %lld", u->mouseinfo->heldcard); + hm_log(LOG_DEBUG, lg, "overcard: %lld", u->mouseinfo->overcard); + hm_log(LOG_DEBUG, lg, "x: %lld", u->mouseinfo->x); + hm_log(LOG_DEBUG, lg, "y: %lld", u->mouseinfo->y); + } + + if(u->emote != 0) { + hm_log(LOG_DEBUG, lg, "emote: %lld", u->emote); + } + + if(u->player_id != 0) { + hm_log(LOG_DEBUG, lg, "player_id: %lld", u->player_id); + } + + } +} diff --git a/hm_gameserver/src/result.c b/hm_gameserver/src/result.c new file mode 100644 index 0000000..0f49549 --- /dev/null +++ b/hm_gameserver/src/result.c @@ -0,0 +1,95 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +static void result2(struct cbop_s *cbop) +{ + if(cbop->lcb_error == LCB_SUCCESS) { + hm_log(LOG_DEBUG, lg, "Key [%.*s] updated successfully", (int )CBSR(nkey), (char *)CBSR(key)); + } else { + hm_log(LOG_DEBUG, lg, "Key[%.*s] update failed, lcb error: %d", (int )CBSR(nkey), (char *)CBSR(key), cbop->lcb_error); + } + + free(cbop); +} + +static void result1(struct cbop_s *cbop) +{ + if(cbop->lcb_error == LCB_SUCCESS) { + struct json_object *obj; + + struct json_tokener *tok = json_tokener_new(); + obj = json_tokener_parse_ex(tok, CBGR(bytes), CBGR(nbytes)); + + if(obj == NULL) { + hm_log(LOG_DEBUG, lg, "Parsing [%.*s] failed", (int)CBGR(nkey), (char *)CBGR(key)); + free(cbop); + return; + } + + json_object *count; + const char *type; + + if((long long)cbop->data == 1) { + hm_log(LOG_DEBUG, lg, "Player [%.*s] set as winner", (int)CBGR(nkey), (char *)CBGR(key)); + type = "w"; + } else { + hm_log(LOG_DEBUG, lg, "Player [%.*s] set as loser", (int)CBGR(nkey), (char *)CBGR(key)); + type = "l"; + } + + json_object_object_get_ex(obj, type, &count); + if(json_object_get_type(count) == json_type_int) { + int new_count = json_object_get_int(count) + 1; + json_object_object_add(obj, type, json_object_new_int(new_count)); + + const char *updated = json_object_to_json_string(obj); + char key[128]; + snprintf(key, sizeof(key), "%.*s", (int )CBGR(nkey), (char *)CBGR(key)); + + memset(cbop, 0, sizeof(*cbop)); + CBSQ_V0(couchbase_bucket_index("hbs"), LCB_SET, key, strlen(key), updated, strlen(updated), result2, 0, 0, 0, 0) + + return; + } + + free(cbop); + + } else { + hm_log(LOG_DEBUG, lg, "Key [%.*s] lcb error %d", (int)CBGR(nkey), (char *)CBGR(key), cbop->lcb_error); + free(cbop); + } +} + +void set_result(const char *k, long long r) +{ + struct cbop_s *cbop; + char key[128]; + + cbop = malloc(sizeof(*cbop)); + + memset(cbop, 0, sizeof(*cbop)); + + cbop->data = (void *)r; + + snprintf(key, sizeof(key), "u:%s", k); + + hm_log(LOG_DEBUG, lg, "Updating player: [%s]", key); + + CBGQ_V0(couchbase_bucket_index("hbs"), key, strlen(key), result1, 0, 0) +} diff --git a/hm_gameserver/src/user_ui.c b/hm_gameserver/src/user_ui.c new file mode 100644 index 0000000..a173059 --- /dev/null +++ b/hm_gameserver/src/user_ui.c @@ -0,0 +1,73 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +enum ct_e { + C_HELD = 0, + C_ARROWORIGIN = 1, +}; + +static void set_card(struct conn_client_s *c, struct userui_s *u, enum ct_e type) +{ + struct hs_holder_s *p; + + p = c->data; + + if(u && u->mouseinfo) { + if(type == C_HELD) { + if(u->mouseinfo->heldcard > 0) p->held_card = u->mouseinfo->heldcard; + else if(u->mouseinfo->overcard > 0) p->held_card = u->mouseinfo->overcard; + else p->held_card = 0; + + hm_log(LOG_INFO, lg, "Setting heldcard %d based on held %lld over %lld", p->held_card, u->mouseinfo->heldcard, u->mouseinfo->overcard); + } + if(type == C_ARROWORIGIN) { + p->arroworigin = u->mouseinfo->arroworigin; + } + } +} + +void user_ui(struct conn_client_s *c, struct userui_s *u) +{ + struct packet_s *packet = NULL; + struct hs_holder_s *p; + char output[1024]; + char *ptr; + + p = c->data; + + // update arroworigin + set_card(c, u, C_ARROWORIGIN); + + // update held card + set_card(c, u, C_HELD); + + // add player id + u->player_id = p->id; + + add_packet(&packet, u, P_USERUI); + ptr = output; + int n = serialize(packet, &ptr, ptr + sizeof(output)); + + userui_dump(u); + + packet_free(packet); + + // let the opponent know what player is thinking + hm_send(p->opponent.client, output, n); +} diff --git a/hm_gameserver/src/utils/flags.c b/hm_gameserver/src/utils/flags.c new file mode 100644 index 0000000..5d68716 --- /dev/null +++ b/hm_gameserver/src/utils/flags.c @@ -0,0 +1,134 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void flags_diff(struct flags_s *old, struct flags_s *new, + struct flag_pr_s ***src_added, int *nsrc_added, + struct flag_pr_s ***src_removed, int *nsrc_removed, + struct card_s *card) +{ + int i, j; + unsigned long long t; + + for(i = 0; i < MAX_FLAGS_ARRAY; i++) { + for(j = 0; j < LL_BITS; j++) { + t = 1; + t <<= j; +#define FFILL(f_s, f_n, f_t)\ + *f_s = realloc(*f_s, ++(*f_n) * sizeof(void *));\ + (*f_s)[*f_n - 1] = malloc(sizeof(***f_s));\ + (*f_s)[*f_n - 1]->flag = (i * LL_BITS + j);\ + if(card->priority_override > 0) {\ + (*f_s)[*f_n - 1]->priority = card->priority_override;\ + } else {\ + (*f_s)[*f_n - 1]->priority = flag_defs[(i * LL_BITS + j)];\ + }\ + (*f_s)[*f_n - 1]->type = f_t;\ + (*f_s)[*f_n - 1]->parent_card = card; + + if((old->nibble[i] & t) == t && (new->nibble[i] & t) == 0) { + FFILL(src_removed, nsrc_removed, F_REMOVED) + } else if((old->nibble[i] & t) == 0 && (new->nibble[i] & t) == t) { + FFILL(src_added, nsrc_added, F_ADDED) + } + } + } +} + +int flags_copy(struct flags_s *dst, const struct flags_s *src) +{ + int i, j; + unsigned long long t; + + for(i = 0; i < MAX_FLAGS_ARRAY; i++) { + for(j = 0; j < LL_BITS; j++) { + t = 1; + t <<= j; + if((src->nibble[i] & t) == t) { + dst->nibble[i] |= t; + } + } + } + return 0; + +} + +int flag_get(struct flags_s *flags, int **f) +{ + assert(flags); + + if(flags == NULL) { + return -1; + } + + int i, j, c = 0; + unsigned long long t; + for(i = 0; i < MAX_FLAGS_ARRAY; i++) { + for(j = 0; j < LL_BITS; j++) { + t = 1; + t <<= j; + if((flags->nibble[i] & t) == t) { + *f = realloc(*f, ++c * sizeof(int)); + (*f)[c - 1] = i * LL_BITS + j; + } + } + } + + return c; +} + +int flag(struct flags_s *flags, enum flags_e src, enum flags_action_e action) +{ + int index; + unsigned long long mod = 1; + + assert(flags); + + if(flags == NULL) { + return -1; + } + + if(action == FLAG_DUMP && src == -1) { + int i, j; + unsigned long long t; + for(i = 0; i < MAX_FLAGS_ARRAY; i++) { + for(j = 0; j < LL_BITS; j++) { + t = 1; + t <<= j; + if((flags->nibble[i] & t) == t) { + hm_log(LOG_DEBUG, lg, "flag %p set: %d", flags, i * LL_BITS + j); + } + } + } + return 0; + } + + if(src > (MAX_FLAGS_ARRAY * LL_BITS) || src < 0) return -1; + + index = src / LL_BITS; + mod <<= (src % LL_BITS); + + if(action == FLAG_SET) flags->nibble[index] |= mod; + else if(action == FLAG_UNSET) flags->nibble[index] &= ~(mod); + else if(action == FLAG_ISSET) { + if((flags->nibble[index] & mod) == mod) return 1; + else return 0; + } else return -1; + + return 0; +} diff --git a/hm_gameserver/src/utils/timer.c b/hm_gameserver/src/utils/timer.c new file mode 100644 index 0000000..4a88736 --- /dev/null +++ b/hm_gameserver/src/utils/timer.c @@ -0,0 +1,71 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +static void force_next_turn(struct ev_loop *loop, ev_timer *w, int revents) +{ + struct conn_client_s *c; + struct hs_holder_s *p; + + c = w->data; + p = c->data; + + //c = p->opponent.client; + //p = c->data; + + ev_timer_stop(loop, &p->game->force_next_turn); + + next_turn(c, p); +} + +static void countdown(struct ev_loop *loop, ev_timer *w, int revents) +{ + struct conn_client_s *c; + struct hs_holder_s *p; + + c = w->data; + p = c->data; + + ev_timer_stop(loop, &p->game->turntimer); + + net_send_turntimer(c, 15, p->game->turn, 1); +} + +void register_turntimer(struct conn_client_s *c) +{ + struct hs_holder_s *p; + +#ifdef TURNOFF_TIMER + return; +#endif + + p = c->data; + + // stop first + ev_timer_stop(c->loop, &p->game->turntimer); + ev_timer_stop(c->loop, &p->game->force_next_turn); + + p->game->turntimer.data = c; + p->game->force_next_turn.data = c; + + ev_timer_init(&p->game->turntimer, countdown, 30, 0); + ev_timer_start(c->loop, &p->game->turntimer); + + ev_timer_init(&p->game->force_next_turn, force_next_turn, 45, 0); + ev_timer_start(c->loop, &p->game->force_next_turn); +} diff --git a/hm_lobbyserver/LICENSE b/hm_lobbyserver/LICENSE new file mode 100644 index 0000000..e0345c0 --- /dev/null +++ b/hm_lobbyserver/LICENSE @@ -0,0 +1,622 @@ + GNU GENERAL PUBLIC LICENSE + + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/hm_lobbyserver/Makefile b/hm_lobbyserver/Makefile new file mode 100644 index 0000000..ca0cb9a --- /dev/null +++ b/hm_lobbyserver/Makefile @@ -0,0 +1,15 @@ +INCS=-Isrc/include -I../hm_base/src/include -I/usr/include/json-c/ +LIB_PATH=-L../hm_base/lib +LIB=-lhmbase -lm -lev -ljson-c -lcouchbase + +all: base mods + $(CC) -g -DMOD_$(mod) $(INCS) $(LIB_PATH) src/*.c $(LIB) -o hm_lobbyserver + +base: + $(MAKE) -C ../hm_base target=lobby + +mods: + cd script/ && python main.py + +clean: + rm hm_lobbyserver diff --git a/hm_lobbyserver/README.md b/hm_lobbyserver/README.md new file mode 100644 index 0000000..df5db97 --- /dev/null +++ b/hm_lobbyserver/README.md @@ -0,0 +1,7 @@ +# hm_lobbyserver + +hearthmod lobby server + +# This is not a standalone project! + +[hm_lobbyserver](https://github.com/farb3yonddriv3n/hm_lobbyserver) is part of [hearthmod software stack](https://github.com/hearthmod/hearthmod) diff --git a/hm_lobbyserver/script/main.py b/hm_lobbyserver/script/main.py new file mode 100644 index 0000000..e574a09 --- /dev/null +++ b/hm_lobbyserver/script/main.py @@ -0,0 +1,37 @@ +try: + import couchbase + from couchbase.bucket import Bucket + from couchbase.views.iterator import View +except: + import couchbase_ffi + from couchbase_ffi.bucket import Bucket + from couchbase_ffi.views.iterator import View + +cb = Bucket('couchbase://localhost/hbs', password='aci') + +def prepare_mods(): + l = [] + for result in View(cb, "dev_mods", "mods"): + l.append({ "url": result.value["url"], "name": result.value["name"] }) + + out = '#ifndef MODS_H_\n' + out += '#define MODS_H_\n\n' + + for i in l: + out += '#ifdef MOD_%s\n' % i['url'].upper() + out += '#define MOD_NAME "%s"\n' % i['name'] + out += '#define MOD_URL "%s"\n' % i['url'] + out += '#endif // MOD_%s\n\n' % i['url'] + + out += '#endif' + + f = open("../src/include/mods.h", "w") + f.write(out) + f.close() + + f = open("../../hm_gameserver/src/include/mods.h", "w") + f.write(out) + f.close() + +if __name__ == '__main__': + prepare_mods() diff --git a/hm_lobbyserver/src/client.c b/hm_lobbyserver/src/client.c new file mode 100644 index 0000000..1af5488 --- /dev/null +++ b/hm_lobbyserver/src/client.c @@ -0,0 +1,171 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include + +#include + +#define HM_LOBBYSERVER + +#include +#include + +#include + +char *read_str(char **buf, char *end, int *len); + +void login_reply(struct conn_client_s *cs, int error) +{ + struct json_object *obj; + + obj = json_object_new_object(); + json_object_object_add(obj, "type", json_object_new_int(CLIENT_LOGIN)); + json_object_object_add(obj, "error", json_object_new_int(error)); + json_object_object_add(obj, "secret", json_object_new_string(cs->login.secret)); + json_object_object_add(obj, "mod_name", json_object_new_string(MOD_NAME)); + json_object_object_add(obj, "mod_url", json_object_new_string(MOD_URL)); + const char *str = json_object_get_string(obj); + + hm_send(cs, str, strlen(str)); +} + +void client_login_3(struct cbop_s *cbop) +{ + struct conn_client_s *cs = cbop->data; + + if(cbop->lcb_error == LCB_SUCCESS) { + hm_log(LOG_DEBUG, cs->log, "{Client}: Deck [%.*s] retrieval succeeded", (int)CBGR(nkey), (char *)CBGR(key)); + login_reply(cs, 0); + } else { + hm_log(LOG_DEBUG, cs->log, "{Client}: Deck [%.*s] retrieval failed with error %d", (int)CBGR(nkey), (char *)CBGR(key), cbop->lcb_error); + login_reply(cs, 3); + } + + free(cbop); +} + +void client_login_2(struct cbop_s *cbop) +{ + struct conn_client_s *cs = cbop->data; + + if(cbop->lcb_error == LCB_SUCCESS) { + struct json_object *obj; + + struct json_tokener *tok = json_tokener_new(); + obj = json_tokener_parse_ex(tok, CBGR(bytes), CBGR(nbytes)); + + if(obj == NULL) { + hm_log(LOG_DEBUG, cs->log, "Parsing [%.*s] failed", (int)CBGR(nkey), (char *)CBGR(key)); + free(cbop); + return; + } + + hm_log(LOG_DEBUG, cs->log, "{Client}: requesting key [%s] succeeded", cs->login.user); + + json_object_object_foreach(obj, key0, val0) { + int type = json_object_get_type(val0); + if(type == json_type_string) { + const char *v = json_object_get_string(val0); + if(strcmp(key0, "secret") == 0) { + snprintf(cs->login.secret, sizeof(cs->login.secret), "%s", v); + } + } + } + + json_object_object_foreach(obj, key, val) { + int type = json_object_get_type(val); + if(type == json_type_string) { + const char *v = json_object_get_string(val); + if(strcmp(key, "password") == 0) { + if(strcmp(v, cs->login.pass) == 0) { + memset(cbop, 0, sizeof(*cbop)); + cbop->data = cs; + + char k1[128]; + snprintf(k1, sizeof(k1), "u:deck_%s_%s", MOD_URL, cs->login.secret); + CBGQ_V0(0, k1, strlen(k1), client_login_3, 0, 0); + return; + } else { + hm_log(LOG_DEBUG, cs->log, "{Client}: passwords do not match %s %s", cs->login.pass, v); + free(cbop); + login_reply(cs, 2); + return; + } + } + } + } + + hm_log(LOG_DEBUG, cs->log, "{Client}: password doesn't match"); + free(cbop); + login_reply(cs, 2); + + } else { + hm_log(LOG_DEBUG, cs->log, "{Client}: requesting key [%s] failed with error %d", cs->login.user, cbop->lcb_error); + free(cbop); + login_reply(cs, 1); + } +} + +void client_login(struct conn_client_s *cs, const char *buf, int len) +{ + const char *username, *password; + struct cbop_s *cbop; + + json_tokener *tok; + struct json_object *obj; + + tok = json_tokener_new(); + obj = json_tokener_parse_ex(tok, buf, len); + + if(obj == NULL) { + return; + } + + json_object_object_foreach(obj, key, val) { + if(strcmp(key, "user") == 0) { + int type = json_object_get_type(val); + if(type == json_type_string) { + username = json_object_get_string(val); + } + } else if(strcmp(key, "pass") == 0) { + int type = json_object_get_type(val); + if(type == json_type_string) { + password = json_object_get_string(val); + } + } + } + + if(!(strlen(username) > 0 && strlen(username) < 32 && strlen(password) > 0 && strlen(password) < 32)) { + return; + } + + char k[128]; + snprintf(k, sizeof(k), "u:%s", username); + snprintf(cs->login.user, sizeof(cs->login.user), "%s", username); + snprintf(cs->login.pass, sizeof(cs->login.pass), "%s", password); + + cbop = malloc(sizeof(*cbop)); + memset(cbop, 0, sizeof(*cbop)); + cbop->data = cs; + CBGQ_V0(0, k, strlen(k), client_login_2, 0, 0); + + json_object_put(obj); + json_tokener_free(tok); +} diff --git a/hm_lobbyserver/src/game.c b/hm_lobbyserver/src/game.c new file mode 100644 index 0000000..3174d27 --- /dev/null +++ b/hm_lobbyserver/src/game.c @@ -0,0 +1,80 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +#include + +#include + +struct playerlist_s { + struct conn_client_s *player; + struct playerlist_s *next; +}; + +static struct playerlist_s *queue = NULL; +static int gamehandle = 0; + +void mm_push(struct conn_client_s *c) +{ + struct playerlist_s *p; + + p = malloc(sizeof(*p)); + + p->player = c; + p->next = queue; + + queue = p; +} + +struct conn_client_s *mm_pop() +{ + struct conn_client_s *c; + struct playerlist_s *p; + + p = queue; + c = queue->player; + + queue = queue->next; + free(p); + + return c; +} + +int matchmaking(struct conn_client_s *player1) +{ + struct conn_client_s *player2; + + // first player + if(queue == NULL) { + mm_push(player1); + return 0; + } + + player2 = mm_pop(); + + if(player1 && player2) { + start_game(player1, player2, gamehandle++); + return 0; + } + + return -1; +} diff --git a/hm_lobbyserver/src/include/client.h b/hm_lobbyserver/src/include/client.h new file mode 100644 index 0000000..e11bbc0 --- /dev/null +++ b/hm_lobbyserver/src/include/client.h @@ -0,0 +1,37 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CLIENT_H_ +#define CLIENT_H_ + +enum packet_e { + CLIENT_CREATEACCOUNT = 1, + CLIENT_LOGIN = 2, + CLIENT_DECK = 3, +}; + +int proto_add(char **dst, const char *maxdst, const void *src, const int nsrc); +int proto_packet(char *dst, enum packet_e packet, char *src, const int nsrc); +char *read_str(char **buf, char *end, int *len); + +void start_game(struct conn_client_s *p1, struct conn_client_s *p2, const int gamehandle); + +void client_login(struct conn_client_s *cs, const char *buf, int len); + +int matchmaking(struct conn_client_s *player1); + +#endif diff --git a/hm_lobbyserver/src/include/step.h b/hm_lobbyserver/src/include/step.h new file mode 100644 index 0000000..9ba369c --- /dev/null +++ b/hm_lobbyserver/src/include/step.h @@ -0,0 +1,128 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef STEP_H_ +#define STEP_H_ + +int step11_0(char *dst, int ndst); +int step11_1(char *dst, int ndst); +int step11_2(char *dst, int ndst); +int step11_3(char *dst, int ndst); +int step11_4(char *dst, int ndst); +int step11_5(char *dst, int ndst); +int step11_6(char *dst, int ndst); +int step11_7(char *dst, int ndst); +int step11_8(char *dst, int ndst); +int step11_9(char *dst, int ndst); +int step11_10(char *dst, int ndst); +int step11_11(char *dst, int ndst); +int step11_12(char *dst, int ndst); +int step11_13(char *dst, int ndst); +int step11_14(char *dst, int ndst); +int step11_15(char *dst, int ndst); +int step11_16(char *dst, int ndst); +int step11_17(char *dst, int ndst); +int step11_18(char *dst, int ndst); +int step11_19(char *dst, int ndst); +int step11_20(char *dst, int ndst); +int step11_21(char *dst, int ndst); +int step11_22(char *dst, int ndst); +int step11_23(char *dst, int ndst); +int step11_24(char *dst, int ndst); +int step11_25(char *dst, int ndst); +int step11_26(char *dst, int ndst); +int step11_27(char *dst, int ndst); +int step11_28(char *dst, int ndst); +int step11_29(char *dst, int ndst); +int step11_30(char *dst, int ndst); +int step11_31(char *dst, int ndst); +int step11_32(char *dst, int ndst); +int step11_33(char *dst, int ndst); +int step11_34(char *dst, int ndst); +int step11_35(char *dst, int ndst); +int step11_36(char *dst, int ndst); +int step11_37(char *dst, int ndst); +int step11_38(char *dst, int ndst); +int step11_39(char *dst, int ndst); +int step11_40(char *dst, int ndst); + +int step12_0(char *dst, int ndst); +int step12_1(char *dst, int ndst); + +int step13_0(char *dst, int ndst); +int step13_1(char *dst, int ndst); +int step13_2(char *dst, int ndst); + +int step14_0(char *dst, int ndst); +int step14_1(char *dst, int ndst); +int step14_2(char *dst, int ndst); + +int step15_0(char *dst, int ndst); +int step15_1(char *dst, int ndst); + +int step16_0(char *dst, int ndst); +int step16_1(char *dst, int ndst); +int step16_2(char *dst, int ndst); + +int step17_0(char *dst, int ndst); +int step17_1(char *dst, int ndst); +int step17_2(char *dst, int ndst); +int step17_3(char *dst, int ndst); + +int step18_0(char *dst, int ndst); +int step18_1(char *dst, int ndst); +int step18_2(char *dst, int ndst); +int step18_3(char *dst, int ndst); + +int step19_0(char *dst, int ndst); +int step19_1(char *dst, int ndst); +int step19_2(char *dst, int ndst); +int step19_3(char *dst, int ndst); +int step19_4(char *dst, int ndst); + +int step20_0(char *dst, int ndst); + +int step21_0(char *dst, int ndst); +int step21_1(char *dst, int ndst); + +int step25_0(char *dst, int ndst); +int step25_1(char *dst, int ndst); +int step25_2(char *dst, int ndst); + +int step24_0(char *dst, int ndst); +int step24_1(char *dst, int ndst); +int step24_2(char *dst, int ndst); + +int step23_0(char *dst, int ndst); +int step23_1(char *dst, int ndst); +int step23_2(char *dst, int ndst); + +int step22_0(char *dst, int ndst); +int step22_1(char *dst, int ndst); +int step22_2(char *dst, int ndst); +int step22_3(char *dst, int ndst); +int step22_4(char *dst, int ndst); +int step22_5(char *dst, int ndst); +int step22_6(char *dst, int ndst); +int step22_7(char *dst, int ndst); +int step22_8(char *dst, int ndst); + +int step22_9_1(char *dst, int ndst, int iplen); +int step22_9_2(char *dst, int ndst, int port); +int step22_9_ip(char *dst, int ndst, const char *ip, const int iplen); + +#endif diff --git a/hm_lobbyserver/src/main.c b/hm_lobbyserver/src/main.c new file mode 100644 index 0000000..bdafd60 --- /dev/null +++ b/hm_lobbyserver/src/main.c @@ -0,0 +1,840 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include + +#define HM_LOBBYSERVER +#include + +#include +#include + +#define HS_MAX 26 + +struct hsmap_s { + int service; + int method; + int token; + void (*reply)(struct conn_client_s *c, const char *buf, const int lenlen); +}; + +static struct hm_log_s l; +static struct hm_pool_s *pool; +static struct ev_loop *loop; + +char ip[32]; +int iplen = 0; +int gameserver_port = 0; + +void dump_binary(char *buf, int len) +{ + int i; + + printf("dumping binary:\n"); + for(i = 0; i < len; i++) { + printf("%x|", buf[i]); + } + printf("\n"); +} + +static int step0_build(char *dst, int ndst) {const char src[163] = { 0x00, 0x0C, 0x08, 0xFE, 0x01, 0x18, 0x00, 0x20, 0x00, 0x28, 0x95, 0x01, 0x30, 0x00, 0x0A, 0x0C, 0x08, 0xF4, 0xC9, 0xCC, 0xF3, 0x0D, 0x10, 0xC6, 0x87, 0xBC, 0xB8, 0x05, 0x12, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x18, 0x00, 0x22, 0x0E, 0x0A, 0x0C, 0x01, 0x09, 0x08, 0x0A, 0x04, 0x03, 0x05, 0x07, 0x06, 0x02, 0x11, 0x10, 0x2A, 0x2E, 0x0A, 0x2C, 0x0D, 0x55, 0x45, 0x00, 0x00, 0x15, 0x7A, 0x72, 0x74, 0x6D, 0x1A, 0x20, 0x6F, 0xF4, 0xFD, 0xD5, 0xFA, 0x5F, 0x6D, 0x62, 0xA2, 0x78, 0xA0, 0x44, 0x03, 0xE0, 0x75, 0xD6, 0x9D, 0x73, 0x4C, 0xD4, 0x88, 0x07, 0x32, 0xDC, 0xE8, 0xED, 0xC6, 0xA3, 0xF5, 0x28, 0x08, 0x92, 0x30, 0xA0, 0x8A, 0x95, 0xF4, 0xCE, 0xBD, 0xCC, 0x02, 0x42, 0x2E, 0x0A, 0x2C, 0x0D, 0x55, 0x45, 0x00, 0x00, 0x15, 0x7A, 0x72, 0x74, 0x6D, 0x1A, 0x20, 0xB4, 0xBD, 0x0F, 0x00, 0x96, 0xA7, 0x64, 0x8D, 0xE1, 0xD1, 0x90, 0x42, 0xFB, 0x7A, 0x79, 0xB9, 0x6C, 0x0D, 0xF4, 0x8E, 0xEA, 0x34, 0x88, 0xF4, 0x98, 0xB0, 0x8A, 0xD3, 0xD3, 0x8F, 0xB2, 0xCC, }; +if(ndst >= 163) { memcpy(dst, src, 163); } +return 163;} + +static int step1_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x01, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step1_1(char *dst, int ndst) {const char src[27] = { 0x00, 0x0C, 0x08, 0x01, 0x10, 0x0C, 0x18, 0x00, 0x20, 0x00, 0x28, 0x0D, 0x30, 0x00, 0x08, 0x01, 0x10, 0xC3, 0x83, 0xA8, 0xF4, 0xCE, 0xBD, 0xCC, 0x02, 0x18, 0x00, }; +if(ndst >= 27) { memcpy(dst, src, 27); } +return 27;} + +static int step1_2(char *dst, int ndst) {const char src[14] = { 0x00, 0x0C, 0x08, 0x01, 0x10, 0x0D, 0x18, 0x01, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 14) { memcpy(dst, src, 14); } +return 14;} + +static int step1_3(char *dst, int ndst) {const char src[52] = { 0x00, 0x0C, 0x08, 0x08, 0x10, 0x03, 0x18, 0x02, 0x20, 0x00, 0x28, 0x26, 0x30, 0x00, 0x12, 0x0C, 0x77, 0x65, 0x62, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x5F, 0x75, 0x72, 0x6C, 0x1A, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x68, 0x73, 0x2F, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2F, 0x7a, 0x2e, 0x68, 0x74, 0x6d, 0x6c }; +if(ndst >= 52) { memcpy(dst, src, 52); } +return 52;} + +static int step2_0(char *dst, int ndst) {const char src[23] = { 0x00, 0x0C, 0x08, 0x00, 0x10, 0x03, 0x18, 0x03, 0x20, 0x00, 0x28, 0x09, 0x30, 0x00, 0x09, 0x85, 0x2B, 0x96, 0xEE, 0xEC, 0x31, 0x05, 0x00, }; +if(ndst >= 23) { memcpy(dst, src, 23); } +return 23;} + +static int step3_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x02, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step3_1(char *dst, int ndst) {const char src[16] = { 0x00, 0x0C, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x04, 0x20, 0x00, 0x28, 0x02, 0x30, 0x00, 0x08, 0x00, }; +if(ndst >= 16) { memcpy(dst, src, 16); } +return 16;} + +static int step3_2(char *dst, int ndst) {const char src[16] = { 0x00, 0x0C, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x05, 0x20, 0x00, 0x28, 0x02, 0x30, 0x00, 0x08, 0x00, }; +if(ndst >= 16) { memcpy(dst, src, 16); } +return 16;} + +static int step3_3(char *dst, int ndst) {const char src[160] = { 0x00, 0x0D, 0x08, 0x01, 0x10, 0x05, 0x18, 0x06, 0x20, 0x00, 0x28, 0x91, 0x01, 0x30, 0x00, 0x08, 0x00, 0x12, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x28, 0x01, 0x28, 0x02, 0x28, 0x03, 0x28, 0x06, 0x28, 0x62, 0x30, 0x02, 0x3A, 0x0F, 0x51, 0x75, 0x69, 0x72, 0x6B, 0x79, 0x4F, 0x72, 0x63, 0x23, 0x32, 0x39, 0x36, 0x38, 0x38, 0x42, 0x02, 0x53, 0x4B, 0x4A, 0x40, 0xAA, 0x15, 0x06, 0x17, 0x71, 0x93, 0x8C, 0x77, 0x90, 0xCD, 0xA5, 0x9B, 0xD5, 0x00, 0xBF, 0x2A, 0xA3, 0x20, 0x59, 0x12, 0x14, 0x80, 0x98, 0xF8, 0xB6, 0x8A, 0xDA, 0x80, 0x2F, 0x11, 0x22, 0xB2, 0x79, 0x2D, 0x90, 0xFA, 0x29, 0x52, 0xA3, 0x38, 0x03, 0x2A, 0x03, 0x89, 0x53, 0x22, 0xDD, 0x02, 0xC4, 0xE2, 0xF3, 0xCF, 0xE6, 0xCD, 0x72, 0x41, 0x54, 0x66, 0xB3, 0x79, 0x8C, 0x9A, 0xDB, 0x01, 0x50, 0x00, }; +if(ndst >= 160) { memcpy(dst, src, 160); } +return 160;} + +static int step4_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x03, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step4_1(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x04, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step4_2(char *dst, int ndst) {const char src[129] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x01, 0x18, 0x07, 0x20, 0x01, 0x28, 0x73, 0x30, 0x00, 0x1A, 0x71, 0xAA, 0x06, 0x6E, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x12, 0x19, 0x0A, 0x17, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x01, 0x18, 0x06, 0x20, 0x00, 0x12, 0x09, 0x18, 0x9A, 0xB1, 0xD8, 0xB4, 0x99, 0xBC, 0xCC, 0x02, 0x12, 0x1A, 0x0A, 0x18, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x01, 0x18, 0x01, 0x20, 0x00, 0x12, 0x0A, 0x2A, 0x08, 0x6A, 0x6F, 0x68, 0x6E, 0x20, 0x62, 0x6F, 0x6E, 0x12, 0x21, 0x0A, 0x1F, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x01, 0x18, 0x04, 0x20, 0x00, 0x12, 0x11, 0x2A, 0x0F, 0x51, 0x75, 0x69, 0x72, 0x6B, 0x79, 0x4F, 0x72, 0x63, 0x23, 0x32, 0x39, 0x36, 0x38, 0x38, }; +if(ndst >= 129) { memcpy(dst, src, 129); } +return 129;} + +static int step4_3(char *dst, int ndst) {const char src[237] = { 0x00, 0x0D, 0x08, 0x05, 0x10, 0x01, 0x18, 0x08, 0x20, 0x02, 0x28, 0xDE, 0x01, 0x30, 0x00, 0x1A, 0xDB, 0x01, 0xAA, 0x06, 0xD7, 0x01, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x0A, 0x1F, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x05, 0x20, 0x00, 0x12, 0x11, 0x2A, 0x0F, 0x51, 0x75, 0x69, 0x72, 0x6B, 0x79, 0x4F, 0x72, 0x63, 0x23, 0x32, 0x39, 0x36, 0x38, 0x38, 0x12, 0x24, 0x0A, 0x22, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x07, 0x20, 0x00, 0x12, 0x14, 0x52, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x12, 0x19, 0x0A, 0x17, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x04, 0x20, 0x00, 0x12, 0x09, 0x18, 0x9A, 0xB1, 0xD8, 0xB4, 0x99, 0xBC, 0xCC, 0x02, 0x12, 0x12, 0x0A, 0x10, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x0C, 0x20, 0x00, 0x12, 0x02, 0x10, 0x00, 0x12, 0x12, 0x0A, 0x10, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x01, 0x20, 0x00, 0x12, 0x02, 0x10, 0x00, 0x12, 0x16, 0x0A, 0x14, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x03, 0x20, 0x00, 0x12, 0x06, 0x42, 0x04, 0x57, 0x54, 0x43, 0x47, 0x12, 0x1D, 0x0A, 0x1B, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x06, 0x20, 0x00, 0x12, 0x0D, 0x2A, 0x0B, 0x34, 0x33, 0x37, 0x31, 0x35, 0x34, 0x31, 0x39, 0x35, 0x23, 0x31, }; +if(ndst >= 237) { memcpy(dst, src, 237); } +return 237;} + +static int step4_4(char *dst, int ndst) {const char src[106] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x09, 0x20, 0x01, 0x28, 0x5C, 0x30, 0x00, 0x12, 0x5A, 0xAA, 0x06, 0x57, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x08, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x01, 0x18, 0x06, 0x12, 0x09, 0x18, 0xF1, 0x82, 0xEA, 0xF5, 0xCE, 0xBD, 0xCC, 0x02, 0x12, 0x28, 0x0A, 0x26, 0x0A, 0x0E, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x01, 0x18, 0x03, 0x20, 0x95, 0x94, 0xE0, 0x81, 0x09, 0x12, 0x14, 0x52, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, }; +if(ndst >= 106) { memcpy(dst, src, 106); } +return 106;} + +static int step4_5(char *dst, int ndst) {const char src[82] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x0A, 0x20, 0x02, 0x28, 0x44, 0x30, 0x00, 0x12, 0x42, 0xAA, 0x06, 0x3F, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x08, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x04, 0x12, 0x09, 0x18, 0xF1, 0x82, 0xEA, 0xF5, 0xCE, 0xBD, 0xCC, 0x02, 0x12, 0x10, 0x0A, 0x0E, 0x0A, 0x08, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x01, 0x12, 0x02, 0x10, 0x01, }; +if(ndst >= 82) { memcpy(dst, src, 82); } +return 82;} + +static int step4_6(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x05, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step5_0(char *dst, int ndst) {const char src[65] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x06, 0x20, 0x00, 0x28, 0x34, 0x30, 0x00, 0x08, 0xC8, 0x01, 0x10, 0xC8, 0x01, 0x18, 0xC8, 0x01, 0x22, 0x15, 0x08, 0x01, 0x12, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x5F, 0x74, 0x61, 0x67, 0x5F, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x22, 0x12, 0x08, 0x02, 0x12, 0x0E, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x69, 0x64, 0x5F, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, }; +if(ndst >= 65) { memcpy(dst, src, 65); } +return 65;} + +static int step5_1(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x07, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step5_2(char *dst, int ndst) {const char src[57] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x09, 0x20, 0x00, 0x28, 0x2C, 0x30, 0x00, 0x0D, 0x55, 0x45, 0x00, 0x00, 0x15, 0x79, 0x74, 0x66, 0x70, 0x1A, 0x20, 0x5B, 0x2F, 0x9B, 0x39, 0x43, 0x4A, 0x1C, 0x4E, 0x3F, 0x97, 0x0A, 0x76, 0xC1, 0xE9, 0x7A, 0x85, 0x48, 0xC9, 0x5D, 0xA2, 0xAD, 0x52, 0xA6, 0xD3, 0x7C, 0xF9, 0xD7, 0x93, 0xDE, 0xDD, 0x88, 0x7D, }; +if(ndst >= 57) { memcpy(dst, src, 57); } +return 57;} + +static int step5_3(char *dst, int ndst) {const char src[82] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x08, 0x20, 0x00, 0x28, 0x45, 0x30, 0x00, 0x0A, 0x3C, 0x0A, 0x3A, 0x25, 0x52, 0x55, 0x45, 0x00, 0x2A, 0x03, 0x53, 0x56, 0x4B, 0x30, 0x02, 0x3A, 0x08, 0x6A, 0x6F, 0x68, 0x6E, 0x20, 0x62, 0x6F, 0x6E, 0x42, 0x0F, 0x51, 0x75, 0x69, 0x72, 0x6B, 0x79, 0x4F, 0x72, 0x63, 0x23, 0x32, 0x39, 0x36, 0x38, 0x38, 0x6A, 0x11, 0x53, 0x4F, 0x4E, 0x49, 0x43, 0x51, 0x41, 0x40, 0x47, 0x4D, 0x41, 0x49, 0x4C, 0x2E, 0x43, 0x4F, 0x4D, 0x12, 0x05, 0x15, 0x73, 0x70, 0x8F, 0xDD, }; +if(ndst >= 82) { memcpy(dst, src, 82); } +return 82;} + +static int step6_0(char *dst, int ndst) {const char src[50] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x0A, 0x20, 0x00, 0x28, 0x25, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xBB, 0x02, 0x0A, 0x18, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x0F, 0x32, 0x0D, 0x08, 0x49, 0x18, 0xAC, 0x02, 0x20, 0x00, 0x28, 0x00, 0x30, 0x0F, 0x40, 0x78, }; +if(ndst >= 50) { memcpy(dst, src, 50); } +return 50;} + +static int step7_0(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x0B, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x88, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x80, 0x01, 0x01, 0xA8, 0x01, 0xAC, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } +return 230;} + +static int step7_1(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x0B, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xAF, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } +return 42;} + +static int step7_2(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x0C, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x88, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x80, 0x01, 0x01, 0xA8, 0x01, 0xAC, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } +return 230;} + +static int step7_3(char *dst, int ndst) {const char src[226] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x0D, 0x20, 0x00, 0x28, 0xD3, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xB0, 0x02, 0x22, 0x15, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x05, 0x32, 0x03, 0x08, 0xA6, 0x56, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x03, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 226) { memcpy(dst, src, 226); } +return 226;} + +static int step8_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x0C, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step9_0(char *dst, int ndst) {const char src[67] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x0E, 0x20, 0x02, 0x28, 0x35, 0x30, 0x00, 0x12, 0x33, 0xAA, 0x06, 0x30, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x1A, 0x0A, 0x18, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x13, 0x12, 0x0A, 0x2A, 0x08, 0x38, 0x33, 0x38, 0x38, 0x36, 0x30, 0x38, 0x30, }; +if(ndst >= 67) { memcpy(dst, src, 67); } +return 67;} + +static int step9_1(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x0D, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step9_2(char *dst, int ndst) {const char src[79] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x0F, 0x20, 0x02, 0x28, 0x41, 0x30, 0x00, 0x12, 0x3F, 0xAA, 0x06, 0x3C, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x26, 0x0A, 0x24, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x14, 0x12, 0x16, 0x2A, 0x14, 0x65, 0x75, 0x2E, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6C, 0x2E, 0x62, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x2E, 0x6E, 0x65, 0x74, }; +if(ndst >= 79) { memcpy(dst, src, 79); } +return 79;} + +static int step9_3(char *dst, int ndst) {const char src[66] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x0E, 0x20, 0x00, 0x28, 0x35, 0x30, 0x00, 0x12, 0x33, 0x18, 0x80, 0xB5, 0xB9, 0xF5, 0x0E, 0x22, 0x1F, 0x0A, 0x0D, 0x36, 0x32, 0x2E, 0x31, 0x39, 0x37, 0x2E, 0x32, 0x34, 0x33, 0x2E, 0x38, 0x38, 0x10, 0xCB, 0xA6, 0x01, 0x1A, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, 0x28, 0x00, 0x30, 0x00, 0x38, 0x00, 0x40, 0x9A, 0xE5, 0xA1, 0xB9, 0x05, }; +if(ndst >= 66) { memcpy(dst, src, 66); } +return 66;} + +static int step9_4(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x0F, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0x8B, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } +return 42;} + +static int step9_5(char *dst, int ndst) {const char src[228] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x10, 0x20, 0x00, 0x28, 0xD5, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x17, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0x8B, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x05, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 228) { memcpy(dst, src, 228); } +return 228;} + +static int step9_6(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x12, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } +return 13;} + +static int step9_7(char *dst, int ndst) {const char src[59] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x11, 0x20, 0x02, 0x28, 0x2D, 0x30, 0x00, 0x12, 0x2B, 0xAA, 0x06, 0x28, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0A, 0x10, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x01, 0x12, 0x02, 0x10, 0x00, }; +if(ndst >= 59) { memcpy(dst, src, 59); } +return 59;} + +static int step9_8(char *dst, int ndst) {const char src[50] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x11, 0x20, 0x00, 0x28, 0x25, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xBB, 0x02, 0x0A, 0x18, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x0F, 0x32, 0x0D, 0x08, 0x1E, 0x18, 0xAC, 0x02, 0x20, 0x00, 0x28, 0x00, 0x30, 0x0F, 0x40, 0x78, }; +if(ndst >= 50) { memcpy(dst, src, 50); } +return 50;} + +static int step10_0(char *dst, int ndst) {const char src[225] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x12, 0x20, 0x00, 0x28, 0xD2, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xCA, 0x02, 0x22, 0x14, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x04, 0x32, 0x02, 0x08, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x02, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 225) { memcpy(dst, src, 225); } +return 225;} + +static int step10_1(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x10, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xCD, 0x01, }; +if(ndst >= 42) { memcpy(dst, src, 42); } +return 42;} + +static int step10_2(char *dst, int ndst) {const char src[228] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x13, 0x20, 0x00, 0x28, 0xD5, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x17, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xCD, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x05, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 228) { memcpy(dst, src, 228); } +return 228;} + +static int step10_3(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x13, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0x94, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } +return 42;} + +static int step10_4(char *dst, int ndst) {const char src[228] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x14, 0x20, 0x00, 0x28, 0xD5, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x17, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0x94, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x05, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 228) { memcpy(dst, src, 228); } +return 228;} + +static int step10_5(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x15, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xB3, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } +return 203;} + +static int step10_6(char *dst, int ndst) {const char src[225] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x16, 0x20, 0x00, 0x28, 0xD2, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xCB, 0x02, 0x22, 0x14, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x04, 0x32, 0x02, 0x08, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x02, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 225) { memcpy(dst, src, 225); } +return 225;} + +void step0(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int n; + + n = step0_build(out, sizeof(out)); + + hm_send(c, out, n); +} + +void step1(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int n, a, b, x; + + n = step1_0(out, sizeof(out)); + a = step1_1(out + n, sizeof(out)); + b = step1_2(out + n + a, sizeof(out)); + x = step1_3(out + n + a + b, sizeof(out)); + hm_send(c, out, n + a + b + x); +} + +void step2(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int n; + + // 12 is offet, length of token is 16 + if(len < (12 + 6)) { + return; + } + + snprintf(c->token, sizeof(c->token), "%.*s", len - 12, buf + 12); + c->ntoken = len - 12; + + n = step2_0(out, sizeof(out)); + + hm_send(c, out, n); +} + +void step3(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int n, a, b, x; + + n = step3_0(out, sizeof(out)); + a = step3_1(out + n, sizeof(out)); + b = step3_2(out + n + a, sizeof(out)); + x = step3_3(out + n + a + b, sizeof(out)); + hm_send(c, out, n + a + b + x); +} + +void step4(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t; + + t = step4_0(out, sizeof(out)); + t += step4_1(out + t, sizeof(out)); + t += step4_2(out + t, sizeof(out)); + t += step4_3(out + t, sizeof(out)); + t += step4_5(out + t, sizeof(out)); + t += step4_6(out + t, sizeof(out)); + hm_send(c, out, t); +} + +void step5(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int t; + + t = step5_0(out, sizeof(out)); + t += step5_1(out + t, sizeof(out)); + t += step5_2(out + t, sizeof(out)); + t += step5_3(out + t, sizeof(out)); + hm_send(c, out, t); +} + +void step6(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int n; + + n = step6_0(out, sizeof(out)); + + hm_send(c, out, n); +} + +void step7(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t; + + t = step7_0(out, sizeof(out)); + t += step7_1(out + t, sizeof(out)); + t += step7_2(out + t, sizeof(out)); + t += step7_3(out + t, sizeof(out)); + hm_send(c, out, t); +} + +void step8(struct conn_client_s *c, const char *buf, const int len) +{ + char out[1024]; + int n; + + n = step0_build(out, sizeof(out)); + + hm_send(c, out, n); +} + +void step9(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t; + + t = step9_0(out, sizeof(out)); + t += step9_1(out + t, sizeof(out)); + t += step9_2(out + t, sizeof(out)); + t += step9_3(out + t, sizeof(out)); + t += step9_4(out + t, sizeof(out)); + t += step9_5(out + t, sizeof(out)); + t += step9_6(out + t, sizeof(out)); + t += step9_7(out + t, sizeof(out)); + t += step9_8(out + t, sizeof(out)); + hm_send(c, out, t); +} + +void step10(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t; + + t = step10_0(out, sizeof(out)); + t += step10_1(out + t, sizeof(out)); + t += step10_2(out + t, sizeof(out)); + t += step10_3(out + t, sizeof(out)); + t += step10_4(out + t, sizeof(out)); + t += step10_5(out + t, sizeof(out)); + t += step10_6(out + t, sizeof(out)); + hm_send(c, out, t); +} + + +void step11(struct conn_client_s *c, const char *buf, const int len) +{ + char out[65536]; + int t = 0; + t += step11_0(out + t, sizeof(out) - t); + t += step11_0(out + t, sizeof(out) - t); + t += step11_1(out + t, sizeof(out) - t); + t += step11_2(out + t, sizeof(out) - t); + t += step11_3(out + t, sizeof(out) - t); + t += step11_4(out + t, sizeof(out) - t); + t += step11_5(out + t, sizeof(out) - t); + t += step11_6(out + t, sizeof(out) - t); + t += step11_7(out + t, sizeof(out) - t); + t += step11_8(out + t, sizeof(out) - t); + t += step11_9(out + t, sizeof(out) - t); + t += step11_10(out + t, sizeof(out) - t); + t += step11_11(out + t, sizeof(out) - t); + t += step11_12(out + t, sizeof(out) - t); + t += step11_13(out + t, sizeof(out) - t); + t += step11_14(out + t, sizeof(out) - t); + t += step11_15(out + t, sizeof(out) - t); + t += step11_16(out + t, sizeof(out) - t); + t += step11_17(out + t, sizeof(out) - t); + t += step11_18(out + t, sizeof(out) - t); + t += step11_19(out + t, sizeof(out) - t); + t += step11_20(out + t, sizeof(out) - t); + t += step11_21(out + t, sizeof(out) - t); + t += step11_22(out + t, sizeof(out) - t); + t += step11_23(out + t, sizeof(out) - t); + t += step11_24(out + t, sizeof(out) - t); + t += step11_25(out + t, sizeof(out) - t); + t += step11_26(out + t, sizeof(out) - t); + t += step11_27(out + t, sizeof(out) - t); + t += step11_28(out + t, sizeof(out) - t); + t += step11_29(out + t, sizeof(out) - t); + t += step11_30(out + t, sizeof(out) - t); + t += step11_31(out + t, sizeof(out) - t); + t += step11_32(out + t, sizeof(out) - t); + t += step11_33(out + t, sizeof(out) - t); + t += step11_34(out + t, sizeof(out) - t); + t += step11_35(out + t, sizeof(out) - t); + t += step11_36(out + t, sizeof(out) - t); + t += step11_37(out + t, sizeof(out) - t); + t += step11_38(out + t, sizeof(out) - t); + t += step11_39(out + t, sizeof(out) - t); + t += step11_40(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step12(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step12_0(out + t, sizeof(out) - t); + t += step12_1(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step13(struct conn_client_s *c, const char *buf, const int len) +{ + char out[16384]; + int t = 0; + t += step13_0(out + t, sizeof(out) - t); + t += step13_1(out + t, sizeof(out) - t); + t += step13_2(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step14(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step14_0(out + t, sizeof(out) - t); + t += step14_1(out + t, sizeof(out) - t); + t += step14_2(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step15(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step15_0(out + t, sizeof(out) - t); + t += step15_1(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step16(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step16_0(out + t, sizeof(out) - t); + t += step16_1(out + t, sizeof(out) - t); + t += step16_2(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step17(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step17_0(out + t, sizeof(out) - t); + t += step17_1(out + t, sizeof(out) - t); + t += step17_2(out + t, sizeof(out) - t); + t += step17_3(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step18(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step18_0(out + t, sizeof(out) - t); + t += step18_1(out + t, sizeof(out) - t); + t += step18_2(out + t, sizeof(out) - t); + t += step18_3(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step19(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step19_0(out + t, sizeof(out) - t); + t += step19_1(out + t, sizeof(out) - t); + t += step19_2(out + t, sizeof(out) - t); + t += step19_3(out + t, sizeof(out) - t); + t += step19_4(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step20(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step20_0(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step21(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step21_0(out + t, sizeof(out) - t); + t += step21_1(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void start_game(struct conn_client_s *p1, struct conn_client_s *p2, const int gamehandle) +{ + char buf1[2048], buf2[2048]; + char *out; + int t; + + t = 0; + out = buf1; + t += step22_0(out + t, sizeof(buf2) - t); + t += step22_1(out + t, sizeof(buf2) - t); + t += step22_2(out + t, sizeof(buf2) - t); + t += step22_3(out + t, sizeof(buf2) - t); + t += step22_4(out + t, sizeof(buf2) - t); + t += step22_5(out + t, sizeof(buf2) - t); + t += step22_6(out + t, sizeof(buf2) - t); + t += step22_7(out + t, sizeof(buf2) - t); + t += step22_8(out + t, sizeof(buf2) - t); + t += step22_9_1(out + t, sizeof(buf2) - t, iplen); + t += step22_9_ip(out + t, sizeof(buf2) - t, ip, iplen); + t += step22_9_2(out + t, sizeof(buf2) - t, gameserver_port); + + t = 0; + out = buf2; + t += step22_0(out + t, sizeof(buf2) - t); + t += step22_1(out + t, sizeof(buf2) - t); + t += step22_2(out + t, sizeof(buf2) - t); + t += step22_3(out + t, sizeof(buf2) - t); + t += step22_4(out + t, sizeof(buf2) - t); + t += step22_5(out + t, sizeof(buf2) - t); + t += step22_6(out + t, sizeof(buf2) - t); + t += step22_7(out + t, sizeof(buf2) - t); + t += step22_8(out + t, sizeof(buf2) - t); + t += step22_9_1(out + t, sizeof(buf2) - t, iplen); + t += step22_9_ip(out + t, sizeof(buf2) - t, ip, iplen); + t += step22_9_2(out + t, sizeof(buf2) - t, gameserver_port); + + memcpy(buf1 + 1343 + (iplen - 14), p1->token, p1->ntoken); + memcpy(buf2 + 1343 + (iplen - 14), p2->token, p2->ntoken); + + hm_send(p1, buf1, t); + hm_send(p2, buf2, t); +} + +void step22(struct conn_client_s *c, const char *buf, const int len) +{ + c->skip = 1; + matchmaking(c); +} + +void step23(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step23_0(out + t, sizeof(out) - t); + t += step23_1(out + t, sizeof(out) - t); + t += step23_2(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step24(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step24_0(out + t, sizeof(out) - t); + t += step24_1(out + t, sizeof(out) - t); + t += step24_2(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +void step25(struct conn_client_s *c, const char *buf, const int len) +{ + char out[2048]; + int t = 0; + t += step25_0(out + t, sizeof(out) - t); + t += step25_1(out + t, sizeof(out) - t); + t += step25_2(out + t, sizeof(out) - t); + + hm_send(c, out, t); +} + +static struct hsmap_s hsmap[HS_MAX] = { + {0, 1, 0, step0}, + {1, 1, 1, step1}, + {1, 7, 2, step2}, + {-2, 0, 3, step3}, + {4, 1, 4, step4}, + {0x10, 1, 9, step5}, + {9, 1, 0xa, step6}, + {9, 1, 0xb, step7}, + {9, 1, 0x11, step8}, + {4, 3, 0x12, step9}, + {9, 1, 0x13, step10}, + {9, 1, 0x19, step11}, + {9, 1, 0x1b, step12}, + {9, 1, 0x1c, step13}, + {9, 1, 0x1d, step14}, + {4, 3, 0x1f, step15}, + {0x10, 1, 0x20, step16}, + {9, 1, 0x22, step17}, + {4, 3, 0x24, step18}, + + // handshake end + + {9, 1, 0x25, step19}, + {9, 1, 0x26, step20}, + {4, 3, 0x27, step21}, // swapped with 0x25 + + {8, 3, 0x29, step22}, //{4, 3, 0x2a, step22}, + + //0|8|8|0|10|5|18|26|28|0| + + /* + {9, 1, 0x2c, step23}, + {4, 1, 0x2d, step24}, + {4, 3, 0x2e, step25}, + */ +}; + + +void hm_recv(struct conn_client_s *cs, const char *buf, const int len) +{ + int i, service, method, token, token1; + + if(cs->skip == 1) { + hm_log(LOG_DEBUG, &l, "Skipping for %d bytes", len); + return; + } + + if(len < 10) { + hm_log(LOG_DEBUG, &l, "Ignoring as received only %d bytes", len); + return; + } + + service = buf[3]; + method = buf[5]; + token = buf[7]; + token1 = buf[8]; + + for(i = 0; i < HS_MAX; i++) { + if(len > 12 && *(int *)buf == -1 && *(int *)(buf + 4) == CLIENT_LOGIN ) { + client_login(cs, buf + 12, len - 12); + return; + } else if(service == hsmap[i].service && method == hsmap[i].method && token == hsmap[i].token) { + hm_log(LOG_DEBUG, &l, "Hsmap iter: %d", i); + hsmap[i].reply(cs, buf, len); + return; + } else if(service == hsmap[i].service && token1 == hsmap[i].token) { + hm_log(LOG_DEBUG, &l, "Hsmap iter: %d", i); + hsmap[i].reply(cs, buf, len); + return; + } else { + //hm_log(LOG_DEBUG, &l, "Ignoring: %d %d %d %d %d %d", service, hsmap[i].service, method, hsmap[i].method, token, hsmap[i].token); + } + } +} + +int start_server() +{ + struct conn_server_s *cs; + + cs = malloc(sizeof(*cs)); + memset(cs, 0, sizeof(*cs)); + + cs->loop = loop; + cs->host = "0.0.0.0"; + cs->port = "45678"; + cs->log = &l; + cs->pool = pool; + cs->recv = hm_recv; + connector_server(cs); + + return 0; +} + +void callback(struct instance_s *data) +{ + struct instance_s *i; + + if(data == NULL) { + couchbase_deinit(); + hm_log(LOG_DEBUG, &l, "{Connector}: all destinations are offline"); + return; + } + + for(i = data; i != NULL; i = i->next) { + hm_log(LOG_DEBUG, &l, "{Connector}: connstr: [%s] online: %d group: %d bucket index: %d", i->connstr, i->status, i->group, i->index); + } + + start_server(); +} + +void daemonize () +{ + if (chdir("/") != 0) { + hm_log(LOG_EMERG, &l, "Unable change directory to /: %s", strerror(errno)); + exit(1); + } + + pid_t pid = fork(); + if (pid < 0) { + hm_log(LOG_EMERG, &l, "Unable to daemonize: fork failed: %s", strerror(errno)); + exit(1); + } + + if (pid != 0) { + hm_log(LOG_DEBUG, &l, "{core} Daemonized as pid %d.", pid); + exit(0); + } + + fclose(stdin); + fclose(stdout); + fclose(stderr); + +#define NULL_DEV "/dev/null" + + stdin = fopen(NULL_DEV, "r"); + if (stdin == NULL) { + hm_log(LOG_EMERG, &l, "Unable to reopen stdin to %s: %s", NULL_DEV, strerror(errno)); + exit(1); + } + stdout = fopen(NULL_DEV, "w"); + if (stdout == NULL) { + hm_log(LOG_EMERG, &l, "Unable to reopen stdout to %s: %s", NULL_DEV, strerror(errno)); + exit(1); + } + stderr = fopen(NULL_DEV, "w"); + if (stderr == NULL) { + hm_log(LOG_EMERG, &l, "Unable to reopen stderr to %s: %s", NULL_DEV, strerror(errno)); + exit(1); + } + + pid_t s = setsid(); + if (s < 0) { + hm_log(LOG_EMERG, &l, "Unable to create new session, setsid(2) failed: %s :: %d", strerror(errno), s); + exit(1); + } + + hm_log(LOG_DEBUG, &l, "Successfully daemonized as pid %d", getpid()); +} + +int main(int argc, char **argv) +{ + struct couchbase_data_s cd; + const char *hosts[1] = { "localhost" }; + const int groups[1] = { 0 }; // Must start with 0 + const char *buckets[1] = { "hbs" }; + const char *passwd[1] = { "aci" }; + int i; + int daemon = 0; + + for(i = 1; i < argc; i++) { + if(strlen(argv[i]) > 6 && memcmp(argv[i], "--log=", 6) == 0) { + daemon = 1; + hm_log_open(&l, argv[i] + 6, LOG_DEBUG); + } + + if(strlen(argv[i]) > 13 && memcmp(argv[i], "--gameserver=", 13) == 0) { + snprintf(ip, sizeof(ip), "%s", argv[i] + 13); + iplen = strlen(ip); + } + + if(strlen(argv[i]) > 18 && memcmp(argv[i], "--gameserver_port=", 18) == 0) { + char gp[32]; + snprintf(gp, sizeof(gp), "%s", argv[i] + 18); + gameserver_port = atoi(gp); + } + } + + assert(iplen != 0); + // gameserver port number must occupy exactly 2 protobuf bytes + assert(gameserver_port > (1 << 10) && gameserver_port < (1 << 14)); + + if(daemon == 0) { + hm_log_open(&l, NULL, LOG_DEBUG); + } else { + daemonize(); + } + + hm_log(LOG_DEBUG, &l, "Associated with gameserver [%s:%d]", ip, gameserver_port); + + loop = ev_default_loop(0); + pool = hm_create_pool(&l); + + cd.loop = loop; + cd.log = &l; + cd.pool = pool; + cd.callback = callback; + + cd.hosts = hosts; + cd.hgroups = groups; + cd.nhosts = 1; + cd.buckets = buckets; + cd.bpasswd = passwd; + cd.nbuckets = 1; + + couchbase_init(&cd); + + ev_run(loop, 0); + + hm_destroy_pool(pool); + hm_log_close(&l); + ev_default_destroy(); + + return 0; +} diff --git a/hm_lobbyserver/src/proto.c b/hm_lobbyserver/src/proto.c new file mode 100644 index 0000000..361f6ad --- /dev/null +++ b/hm_lobbyserver/src/proto.c @@ -0,0 +1,87 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include + +#include + +#include + +int proto_add(char **dst, const char *maxdst, const void *src, const int nsrc) +{ + char *start; + + if(maxdst < *dst + nsrc + sizeof(nsrc)) { + return -1; + } + + start = *dst; + + memcpy(*dst, &nsrc, sizeof(nsrc)); + *dst += sizeof(nsrc); + + memcpy(*dst, src, nsrc); + *dst += nsrc; + + return (*dst - start); +} + +int proto_packet(char *dst, enum packet_e packet, char *src, const int nsrc) +{ + int len; + int magic = 0xffffffff; + + len = 3 * sizeof(packet) + nsrc; + + memcpy(dst, &magic, sizeof(magic)); + dst += sizeof(magic); + + memcpy(dst, &packet, sizeof(packet)); + dst += sizeof(packet); + + memcpy(dst, &len, sizeof(len)); + dst += sizeof(len); + + memcpy(dst, src, nsrc); + dst += nsrc; + + return len; + +} + +char *read_str(char **buf, char *end, int *len) +{ + char *r; + + if(end < (*buf + 4)) { + return NULL; + } + + *len = *(int *)(*buf); + *buf += sizeof(int); + + if(*len + *buf > end) { + return NULL; + } + + r = *buf; + + *buf += *len; + + return r; +} diff --git a/hm_lobbyserver/src/step11.c b/hm_lobbyserver/src/step11.c new file mode 100644 index 0000000..e4f0e52 --- /dev/null +++ b/hm_lobbyserver/src/step11.c @@ -0,0 +1,146 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step11_0(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x14, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xC7, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step11_1(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x17, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x0B, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_2(char *dst, int ndst) {const char src[227] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x18, 0x20, 0x00, 0x28, 0xD4, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xE9, 0x01, 0x22, 0x16, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x06, 0x32, 0x04, 0x08, 0x06, 0x10, 0x00, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x04, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 227) { memcpy(dst, src, 227); } else { abort(); } +return 227;} +int step11_3(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x19, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xED, 0x01, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step11_4(char *dst, int ndst) {const char src[228] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x19, 0x20, 0x00, 0x28, 0xD5, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x17, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xED, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x05, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 228) { memcpy(dst, src, 228); } else { abort(); } +return 228;} +int step11_5(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x1A, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_6(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x15, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xC7, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step11_7(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x1B, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x03, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_8(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x1C, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x0F, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_9(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x17, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xB1, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step11_10(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x1D, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x11, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_11(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x1E, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x0E, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_12(char *dst, int ndst) {const char src[371] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x1F, 0x20, 0x00, 0x28, 0xE4, 0x02, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xCA, 0x01, 0x22, 0xA4, 0x01, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x93, 0x01, 0x32, 0x90, 0x01, 0x0A, 0x26, 0x08, 0xCF, 0xED, 0x81, 0xFB, 0x02, 0x12, 0x00, 0x18, 0x00, 0x20, 0xFD, 0x04, 0x28, 0x01, 0x30, 0xFF, 0x05, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x50, 0xA2, 0xA4, 0xF2, 0xB8, 0x05, 0x60, 0xA2, 0xA4, 0xF2, 0xB8, 0x05, 0x70, 0x03, 0x0A, 0x25, 0x08, 0x96, 0x97, 0x87, 0xFB, 0x02, 0x12, 0x00, 0x18, 0x00, 0x20, 0x1F, 0x28, 0x01, 0x30, 0xFF, 0x05, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x50, 0x95, 0xA7, 0xF2, 0xB8, 0x05, 0x60, 0x95, 0xA7, 0xF2, 0xB8, 0x05, 0x70, 0x03, 0x0A, 0x1E, 0x08, 0xA5, 0xC2, 0x0A, 0x12, 0x06, 0x70, 0x72, 0x65, 0x63, 0x6F, 0x6E, 0x18, 0x00, 0x20, 0x1F, 0x28, 0x05, 0x30, 0x1F, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x60, 0x00, 0x70, 0x00, 0x0A, 0x1F, 0x08, 0xC9, 0xBC, 0x0A, 0x12, 0x06, 0x70, 0x72, 0x65, 0x63, 0x6F, 0x6E, 0x18, 0x00, 0x20, 0xFD, 0x04, 0x28, 0x05, 0x30, 0x1F, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x60, 0x00, 0x70, 0x00, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x03, 0x18, 0x90, 0x01, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 371) { memcpy(dst, src, 371); } else { abort(); } +return 371;} +int step11_13(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x20, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x06, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_14(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x16, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xC7, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step11_15(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x21, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x04, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_16(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x22, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x17, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_17(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x23, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x13, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_18(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x24, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x08, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_19(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x25, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x14, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_20(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x18, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xC7, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step11_21(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x26, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x1B, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_22(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x27, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x07, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_23(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x28, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x1C, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_24(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x29, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xE0, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } else { abort(); } +return 203;} +int step11_25(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x2A, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xCF, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } else { abort(); } +return 203;} +int step11_26(char *dst, int ndst) {const char src[263] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x2B, 0x20, 0x00, 0x28, 0xF8, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xE8, 0x01, 0x22, 0x3A, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x2A, 0x32, 0x28, 0x0A, 0x12, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x40, 0x01, 0x48, 0x01, 0x50, 0x03, 0x58, 0x00, 0x70, 0x01, 0x78, 0x00, 0x12, 0x12, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x40, 0x01, 0x48, 0x01, 0x50, 0x03, 0x58, 0x00, 0x70, 0x01, 0x78, 0x00, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x28, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 263) { memcpy(dst, src, 263); } else { abort(); } +return 263;} +int step11_27(char *dst, int ndst) {const char src[769] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x2C, 0x20, 0x00, 0x28, 0xF2, 0x05, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xAC, 0x02, 0x22, 0xB2, 0x04, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0xA1, 0x04, 0x32, 0x9E, 0x04, 0x52, 0x08, 0x0A, 0x06, 0x6C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x52, 0x0A, 0x0A, 0x06, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x31, 0x10, 0x00, 0x52, 0x0A, 0x0A, 0x06, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x32, 0x10, 0x00, 0x52, 0x0A, 0x0A, 0x06, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x33, 0x10, 0x00, 0x52, 0x0A, 0x0A, 0x06, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x34, 0x10, 0x00, 0x52, 0x0A, 0x0A, 0x06, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x35, 0x10, 0x00, 0x52, 0x11, 0x0A, 0x0B, 0x67, 0x76, 0x67, 0x5F, 0x70, 0x72, 0x6F, 0x6D, 0x6F, 0x74, 0x65, 0x10, 0x01, 0x18, 0x00, 0x52, 0x0F, 0x0A, 0x09, 0x67, 0x76, 0x67, 0x5F, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x10, 0x01, 0x18, 0x00, 0x52, 0x0D, 0x0A, 0x09, 0x67, 0x76, 0x67, 0x5F, 0x61, 0x72, 0x65, 0x6E, 0x61, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x62, 0x72, 0x6D, 0x5F, 0x31, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x62, 0x72, 0x6D, 0x5F, 0x32, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x62, 0x72, 0x6D, 0x5F, 0x33, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x62, 0x72, 0x6D, 0x5F, 0x34, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x62, 0x72, 0x6D, 0x5F, 0x35, 0x10, 0x00, 0x52, 0x12, 0x0A, 0x0C, 0x62, 0x72, 0x6D, 0x5F, 0x70, 0x72, 0x65, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x10, 0x01, 0x18, 0x00, 0x52, 0x13, 0x0A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x10, 0x00, 0x52, 0x12, 0x0A, 0x0C, 0x74, 0x67, 0x74, 0x5F, 0x70, 0x72, 0x65, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x10, 0x01, 0x18, 0x00, 0x52, 0x13, 0x0A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x32, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x33, 0x10, 0x00, 0x52, 0x09, 0x0A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x34, 0x10, 0x00, 0x52, 0x1A, 0x0A, 0x14, 0x66, 0x65, 0x61, 0x73, 0x74, 0x5F, 0x6F, 0x66, 0x5F, 0x77, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x5F, 0x76, 0x65, 0x69, 0x6C, 0x10, 0x01, 0x18, 0x00, 0x52, 0x15, 0x0A, 0x11, 0x73, 0x65, 0x74, 0x5F, 0x72, 0x6F, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x32, 0x30, 0x31, 0x36, 0x10, 0x00, 0x52, 0x15, 0x0A, 0x0F, 0x6F, 0x67, 0x5F, 0x70, 0x72, 0x65, 0x5F, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x10, 0x01, 0x18, 0x00, 0x52, 0x12, 0x0A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x10, 0x00, 0x52, 0x1E, 0x0A, 0x18, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x5F, 0x63, 0x68, 0x61, 0x72, 0x69, 0x74, 0x79, 0x5F, 0x70, 0x72, 0x6F, 0x6D, 0x6F, 0x5F, 0x32, 0x30, 0x31, 0x36, 0x10, 0x01, 0x18, 0x00, 0x52, 0x1E, 0x0A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x10, 0x01, 0x18, 0x00, 0x52, 0x24, 0x0A, 0x1B, 0x73, 0x65, 0x74, 0x5F, 0x72, 0x6F, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x32, 0x30, 0x31, 0x36, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x70, 0x61, 0x63, 0x6B, 0x73, 0x10, 0x00, 0x18, 0xD6, 0xE3, 0xB4, 0x02, 0x52, 0x24, 0x0A, 0x1B, 0x73, 0x65, 0x74, 0x5F, 0x72, 0x6F, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x32, 0x30, 0x31, 0x36, 0x5F, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x10, 0x00, 0x18, 0xD4, 0xE3, 0xB4, 0x02, 0x5A, 0x04, 0x10, 0xEE, 0xCB, 0x07, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x03, 0x18, 0x9E, 0x04, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 769) { memcpy(dst, src, 769); } else { abort(); } +return 769;} +int step11_28(char *dst, int ndst) {const char src[22545] = { 0x00, 0x0E, 0x08, 0x04, 0x10, 0x01, 0x18, 0x2D, 0x20, 0x00, 0x28, 0x81, 0xB0, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x84, 0x02, 0x22, 0xBF, 0xAE, 0x01, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0xAD, 0xAE, 0x01, 0x32, 0xA9, 0xAE, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA2, 0x02, 0x10, 0x28, 0x18, 0x28, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA2, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x90, 0x03, 0x20, 0x01, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xF9, 0x0C, 0x10, 0x90, 0x03, 0x18, 0x90, 0x03, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF9, 0x0C, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0xC0, 0x0C, 0x20, 0x01, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xED, 0x03, 0x10, 0x90, 0x03, 0x18, 0x90, 0x03, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xED, 0x03, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0xC0, 0x0C, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD9, 0x04, 0x10, 0x64, 0x18, 0x64, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD9, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0xA0, 0x06, 0x20, 0x01, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x98, 0x07, 0x10, 0x90, 0x03, 0x18, 0x90, 0x03, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x98, 0x07, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0xC0, 0x0C, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB1, 0x08, 0x10, 0x64, 0x18, 0x64, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB1, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0xA0, 0x06, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x92, 0x05, 0x10, 0x28, 0x18, 0x28, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x92, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x90, 0x03, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x06, 0x10, 0x64, 0x18, 0x64, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF7, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0xA0, 0x06, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x03, 0x10, 0x64, 0x18, 0x64, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD2, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0xA0, 0x06, 0x20, 0x01, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xDC, 0x0A, 0x10, 0x90, 0x03, 0x18, 0x90, 0x03, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xDC, 0x0A, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0xC0, 0x0C, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA8, 0x08, 0x10, 0x64, 0x18, 0x64, 0x20, 0x01, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA8, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0xA0, 0x06, 0x20, 0x01, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDF, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB4, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xBE, 0xAE, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFF, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xB8, 0x08, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAE, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF9, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC6, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8A, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE5, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x88, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE2, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFA, 0x06, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE1, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xFD, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA8, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF1, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC1, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFB, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF1, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD5, 0x0A, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x20, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF9, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBA, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xD3, 0xAA, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF5, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAC, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x90, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x80, 0xAD, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x90, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDB, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFD, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD5, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xCD, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA4, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x93, 0x47, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF6, 0x08, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9E, 0x01, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE3, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x88, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDC, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC2, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF9, 0xAB, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF9, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB9, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xE9, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x83, 0x05, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAF, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x86, 0xB1, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC1, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x90, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x95, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEC, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xDB, 0xAF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9E, 0x01, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE1, 0x15, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xF8, 0x0C, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8D, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA1, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x4B, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x97, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x9D, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x24, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xE2, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA4, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x56, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8E, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB3, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x90, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9B, 0x03, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE2, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x8D, 0xAE, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xEF, 0xAF, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE9, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x83, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF6, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD9, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCB, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x71, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD9, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xD9, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD7, 0x06, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x81, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x85, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9E, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x80, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x93, 0x01, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xDB, 0x06, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x98, 0x0D, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x88, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x83, 0x05, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFD, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD8, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8A, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8F, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xA8, 0xAB, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCC, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE7, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE0, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEF, 0x08, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF8, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF6, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x89, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA2, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x91, 0xAD, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDC, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB1, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x94, 0x17, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xFE, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9C, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD5, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x3D, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE1, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xC0, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xF6, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x97, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x86, 0x01, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x8A, 0x01, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB6, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xED, 0x01, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xA1, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFA, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9D, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x82, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x71, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8D, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8D, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x9A, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC5, 0x08, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xB9, 0x11, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE1, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xDA, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xA9, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB8, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x99, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xDB, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xB2, 0x06, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xDD, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x99, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x9F, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBA, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xB4, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x9A, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xED, 0x08, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xE0, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB5, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x83, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xE1, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x8D, 0xAC, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x25, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x90, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x93, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB7, 0x6C, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEC, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF4, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDD, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB3, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xD9, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBF, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x0C, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x02, 0x08, 0x17, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBD, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xA2, 0x04, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDC, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCB, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x86, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB8, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xEC, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD0, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDE, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFF, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF7, 0xAA, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF9, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x9A, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC1, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD2, 0x04, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x97, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xE9, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBF, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xE6, 0xAE, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCE, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD1, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x90, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xCE, 0xB1, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBA, 0x11, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD9, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCB, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x81, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC3, 0x16, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8C, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xED, 0x09, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDF, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xEE, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE9, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF9, 0x46, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE6, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC3, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB2, 0x06, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA2, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC2, 0x0E, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEC, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x92, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFE, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC5, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBF, 0x17, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFF, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBF, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC8, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF6, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x86, 0x09, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA8, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x86, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x92, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x09, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAD, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDB, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x85, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB5, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC8, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xBE, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x82, 0x12, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC8, 0x03, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF0, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x97, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF4, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF6, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x16, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD2, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE6, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xCE, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xDA, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xCF, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF6, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB4, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB2, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x80, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8A, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC2, 0x08, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB1, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x83, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA7, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCE, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x85, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEB, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC8, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEE, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF0, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x89, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xCB, 0x15, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8E, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x88, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x80, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAE, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAE, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD3, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC2, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9A, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD3, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x2D, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB3, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8B, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xBD, 0xAC, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFA, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8B, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCF, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF4, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8C, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA0, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC5, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB9, 0x0D, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x5F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x1E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x96, 0x09, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x8A, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x9D, 0x0D, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB6, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCC, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x86, 0x09, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF8, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8B, 0xAF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x93, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE9, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xCE, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xD0, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE3, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA9, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xDC, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD3, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xDD, 0xAD, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC4, 0xAB, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF6, 0xAA, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x93, 0xAD, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDF, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xCF, 0xB1, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF1, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF0, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xC9, 0xAF, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF2, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xB4, 0x03, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x84, 0x17, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x81, 0x0E, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFD, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA6, 0x15, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF9, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x86, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC0, 0x01, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBE, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA0, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x96, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x02, 0x08, 0x09, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF5, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC8, 0x03, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE4, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEE, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x93, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9F, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xDE, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBB, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB7, 0x17, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD6, 0x11, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF2, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xAF, 0x04, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x95, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8E, 0x17, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xBA, 0x04, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD1, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xA8, 0x05, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8F, 0x06, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF9, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x80, 0x05, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF9, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE4, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x83, 0x09, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA0, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x87, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xBB, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x90, 0x07, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x82, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC5, 0x08, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC1, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB9, 0x11, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDF, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x99, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD5, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8C, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB0, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8C, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8C, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x87, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xED, 0x08, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC7, 0x03, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCE, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8C, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA6, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8D, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xDE, 0x16, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF6, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDD, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xED, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA2, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8F, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD3, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB7, 0x17, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC5, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x0C, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC3, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE0, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBF, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB7, 0x6C, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x83, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8F, 0x09, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC7, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8A, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x44, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9F, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x0C, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCC, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8F, 0x9A, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB2, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA2, 0x09, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFF, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x84, 0x0E, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF2, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x80, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEE, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xE4, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC2, 0x06, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCE, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDA, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF9, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA2, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF0, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8F, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD9, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD4, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE9, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x87, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x99, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFE, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x87, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD7, 0x13, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA4, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD5, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE5, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA6, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDE, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCE, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF5, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xD4, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFB, 0x0E, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xE9, 0x15, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE2, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC8, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE8, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFD, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x97, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDF, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9F, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xC0, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD6, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAD, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8E, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x89, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA3, 0x15, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x93, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8B, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8C, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD4, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x02, 0x08, 0x20, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD1, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAE, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xCE, 0xB1, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x8B, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA5, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x84, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xB1, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x93, 0x01, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x89, 0x06, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x88, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA7, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x86, 0xB1, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x92, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x87, 0x0E, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD4, 0x0A, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xA6, 0x15, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCF, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA3, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xF5, 0x08, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB9, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD4, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB9, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE5, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE3, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE2, 0x0C, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE9, 0x12, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xB7, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD8, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCD, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xBD, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x95, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xA0, 0xAB, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9A, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAE, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDB, 0x0A, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x90, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFB, 0x08, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCD, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC3, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE1, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8D, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xE1, 0x15, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD2, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD1, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x99, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF2, 0x0B, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xC5, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x85, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEA, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAD, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA0, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xE0, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x9F, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE8, 0x12, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x98, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xD3, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x9A, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x94, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC3, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xCE, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9A, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x85, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8A, 0x01, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x87, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF1, 0xAF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x90, 0x07, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xD0, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xDE, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xD4, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB4, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xCD, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF7, 0xAA, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD5, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8B, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBB, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x94, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x2D, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCD, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD7, 0x06, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB7, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x80, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFC, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEB, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA5, 0x09, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8D, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDB, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xAF, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x81, 0x0A, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xBB, 0x03, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x84, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC5, 0x09, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE2, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x90, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x88, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x91, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8B, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xDA, 0x0D, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEB, 0x16, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x95, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xBD, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE1, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC9, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xCE, 0xAE, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE8, 0x12, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEA, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF8, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x84, 0x12, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xF2, 0xAE, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBA, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xEC, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD6, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x83, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA8, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFB, 0x0E, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB4, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xCE, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x99, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9A, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xB9, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE2, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFB, 0xAA, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA5, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x91, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9B, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAF, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xDB, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE5, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xF8, 0x08, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x90, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB8, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC3, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xA3, 0x15, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x86, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8F, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x85, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xEF, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xA7, 0xAD, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x97, 0x68, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8A, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC9, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF2, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA7, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xA6, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x87, 0xAB, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC1, 0x15, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC6, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB0, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xB1, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x88, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x81, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDE, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF9, 0x46, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x85, 0x0E, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x80, 0x12, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD9, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC5, 0x04, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC8, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC3, 0x16, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xCD, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xCB, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBA, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC7, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD2, 0x04, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFA, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x95, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xA9, 0xAD, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xED, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE7, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC0, 0x01, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x88, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x96, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE9, 0x12, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA6, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE0, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x16, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFA, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD8, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xED, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF5, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCD, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF6, 0xAA, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xE1, 0x07, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xDB, 0x06, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF9, 0xAB, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB7, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9D, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x81, 0x0A, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xE8, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xB0, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF8, 0x0D, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x88, 0xAF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8D, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8A, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xF2, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9E, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFE, 0x0D, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xED, 0x16, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFF, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBC, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x80, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF2, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBB, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xBE, 0xAB, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xCF, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x82, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE3, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD8, 0x0A, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD3, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x84, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE4, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xAE, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF5, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x93, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xC4, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8E, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xD1, 0x91, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCA, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x81, 0x0E, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9B, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC2, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xF9, 0xAA, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x86, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCF, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xD9, 0xAE, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x83, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF5, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xFF, 0xAD, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA4, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9A, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE2, 0x08, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDA, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEA, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xBB, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF8, 0x0C, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA3, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x02, 0x08, 0x4B, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x56, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA3, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAB, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xCB, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCB, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x3D, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x86, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB4, 0x03, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8F, 0x9A, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x81, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCE, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD5, 0x0A, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x82, 0x0E, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCB, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF5, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD9, 0x0D, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFB, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xB0, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA7, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xBF, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xCB, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xD8, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFA, 0xAA, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF9, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x90, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xAF, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC0, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xAC, 0x04, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xC5, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCD, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE9, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x9E, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x9B, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF8, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF9, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBA, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE2, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD3, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x82, 0x12, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x02, 0x08, 0x24, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFA, 0x0C, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE6, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB8, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE9, 0x11, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFF, 0x0D, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x94, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD6, 0x0A, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x96, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC5, 0x09, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x84, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF5, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBC, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xE6, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA4, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xED, 0x09, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x0C, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8F, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x94, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC7, 0x03, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEA, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xA0, 0xAB, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xE8, 0x11, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xFE, 0xAA, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xEF, 0x08, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x92, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x9B, 0x03, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC9, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x81, 0xB1, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD0, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEF, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xD2, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xC4, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD1, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE9, 0x15, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xF8, 0x0D, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x84, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x82, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBE, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF2, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB2, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC0, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEE, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFE, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCB, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE6, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x25, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA4, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x94, 0x17, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA1, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA1, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE7, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8D, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFF, 0x0D, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC0, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCA, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA8, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBB, 0x03, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x96, 0x09, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF4, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC7, 0x17, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x89, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8A, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF8, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x9C, 0x10, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x91, 0x17, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA7, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x0D, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xAE, 0xAB, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x91, 0x01, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x5F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xCF, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA8, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x89, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xBA, 0x11, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC3, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x0C, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFA, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8E, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCB, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x17, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBE, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x8B, 0x08, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF8, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE6, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x87, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBD, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC8, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA4, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE5, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xE9, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x9D, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xEF, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF4, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x86, 0x16, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x94, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA4, 0x03, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEE, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x82, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFC, 0x13, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAE, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xDF, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF2, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC7, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x80, 0x05, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD2, 0x0A, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD1, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xED, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDE, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCF, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x99, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x95, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBF, 0x17, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD3, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xED, 0x05, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8A, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x96, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE2, 0x0C, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC2, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xA1, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xC7, 0xAE, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xD3, 0xAE, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD5, 0x11, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEA, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA5, 0x09, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEC, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD4, 0x0A, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC1, 0x15, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE0, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x9D, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8E, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFD, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x84, 0x17, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA2, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE0, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x81, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD4, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEB, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA4, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD0, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF2, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xA9, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC2, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x80, 0x12, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD5, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDC, 0x01, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x80, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x87, 0x17, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD6, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD4, 0x08, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFA, 0x0C, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC3, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x93, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x91, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE6, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDD, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xE0, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x8A, 0xAE, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9D, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x87, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC1, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xF9, 0xAA, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x94, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xC4, 0xAC, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x89, 0x06, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9B, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x96, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB8, 0x08, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xF2, 0x13, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFA, 0x0D, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xA7, 0x08, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBA, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC5, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFB, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x89, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB1, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDC, 0x01, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF2, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF8, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xED, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF6, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEC, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x88, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE5, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9D, 0x0D, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF3, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC2, 0x07, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xEB, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xAF, 0x04, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xF0, 0x13, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x82, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD3, 0x01, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xDD, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC6, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8E, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDF, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDB, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xCA, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x86, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xD4, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD4, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF3, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x85, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF6, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x99, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDB, 0x0A, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x97, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xBC, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xA7, 0xAC, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xCF, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF4, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x89, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC2, 0x08, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xA9, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDC, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD9, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB4, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD9, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE2, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCC, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF1, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC0, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC7, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xDF, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCE, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xF3, 0x05, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD8, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x0D, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFE, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8E, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF8, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA8, 0x05, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF5, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF1, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xAE, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBC, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC2, 0x06, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD4, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE9, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDE, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFD, 0x0D, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xFD, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFF, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF9, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCE, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF8, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD8, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC5, 0x03, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x86, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD7, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xDC, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE8, 0x11, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB8, 0xAC, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFC, 0x13, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9D, 0x06, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xDA, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEA, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC3, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF9, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF1, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC0, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x92, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x89, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x95, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE8, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCE, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEC, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFD, 0x0D, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCA, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF7, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xFE, 0xAF, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8D, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFA, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x92, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC5, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x82, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8F, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xFF, 0xAD, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xA0, 0xB0, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x87, 0x17, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE1, 0x07, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBA, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x91, 0x17, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xBC, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x8D, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x98, 0x0D, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xFD, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xD8, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE7, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE6, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xD9, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9E, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA4, 0x03, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC9, 0x0D, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCB, 0x16, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFB, 0xAA, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE4, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x90, 0x03, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xAE, 0xB0, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xE8, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCB, 0x16, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBF, 0x08, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDD, 0x0A, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8A, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB2, 0x08, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCF, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD5, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDB, 0x09, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC0, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA1, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x91, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE7, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF6, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x93, 0x47, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB1, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x97, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xE2, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFA, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFB, 0xAB, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xED, 0x01, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFE, 0x0D, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB9, 0xAB, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB0, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDC, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF3, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x87, 0x0E, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x22, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xCB, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCA, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC8, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFA, 0x0E, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8B, 0x08, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x85, 0x17, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xAD, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF2, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xA4, 0xAC, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF5, 0x0D, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC5, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFF, 0xAF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xC4, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8E, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEB, 0x16, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x83, 0x09, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xF9, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x89, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xAA, 0x06, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xE9, 0x11, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEE, 0x01, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xDB, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA7, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xE2, 0xAF, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x81, 0x17, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB7, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF8, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD6, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xBA, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x83, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB7, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDE, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xA9, 0xAF, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFE, 0x0C, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC6, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE4, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xE0, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB6, 0xAC, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xBF, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFB, 0x08, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x91, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x91, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x81, 0xB1, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC0, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE7, 0x07, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC9, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xA4, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEE, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x86, 0x01, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB0, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x82, 0x08, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x88, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x9F, 0xB0, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCB, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x82, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA7, 0x08, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAB, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFD, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xCF, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD5, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8E, 0x17, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEE, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x84, 0x12, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x80, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9D, 0x06, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8C, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x8D, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF7, 0x03, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xB2, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8F, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFA, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBB, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xED, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xAC, 0x04, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC1, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFA, 0xB0, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC5, 0x04, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFC, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xFE, 0xAA, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xEC, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFE, 0x0C, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF3, 0x0C, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC4, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFD, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD3, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD5, 0x11, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x93, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xAD, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x90, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9D, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x8D, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x81, 0x17, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xD3, 0xAA, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF5, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xBF, 0x08, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8D, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x8D, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB0, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x84, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE2, 0x08, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x93, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE7, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9D, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD4, 0x08, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC6, 0x15, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x94, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8E, 0x05, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE8, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCE, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA4, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xBE, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xB9, 0x0D, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8C, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC8, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xCE, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC8, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBA, 0x04, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x85, 0x17, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB8, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x88, 0xAF, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFA, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xED, 0x13, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD1, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8D, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0x8A, 0xB0, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9F, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD3, 0x01, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xC2, 0x0E, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x86, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD9, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF5, 0x0D, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDE, 0x05, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x92, 0xAC, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF2, 0x13, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE6, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x81, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD6, 0x11, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x87, 0xAB, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD6, 0x0A, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x82, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8D, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDA, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD8, 0x0A, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8C, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA5, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xDE, 0x16, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF0, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xAB, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x89, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x80, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x87, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xA2, 0xAC, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xED, 0x05, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x97, 0x15, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA3, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEB, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x86, 0x16, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xBF, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFA, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xF9, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0xCF, 0xB1, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB9, 0x17, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x85, 0x0E, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8C, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x96, 0x68, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x82, 0x0E, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFE, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x91, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF7, 0x0D, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x91, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8B, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB9, 0x17, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA7, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDD, 0x0A, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x98, 0x10, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF6, 0x08, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD4, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE2, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB3, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x85, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x04, 0x08, 0xC2, 0xAE, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xBD, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD5, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x84, 0x0E, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8C, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDD, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8A, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD5, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFE, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD7, 0x13, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xED, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x9E, 0x07, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xC9, 0xB0, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x88, 0x0E, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8F, 0x09, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x93, 0x14, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x9F, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x97, 0x68, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x8C, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF8, 0x08, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC8, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xEC, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x10, 0x0A, 0x06, 0x08, 0x8A, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC2, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x8F, 0x06, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xE8, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF2, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEE, 0x06, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA4, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x93, 0x04, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB8, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB8, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC8, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF3, 0x05, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD4, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xE8, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xEB, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x8D, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE2, 0x11, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFC, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xBE, 0xAE, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x9A, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC9, 0x14, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB2, 0x08, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xDA, 0x06, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC1, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xD4, 0xAE, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xD0, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x82, 0x08, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB3, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x86, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x45, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEE, 0x11, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xB0, 0xAF, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xDA, 0x0F, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD0, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDC, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC5, 0x0E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9E, 0x10, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xEE, 0x01, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE7, 0x07, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xED, 0x16, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD9, 0x0D, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC1, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xCB, 0x15, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFB, 0x0C, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x45, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x84, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF4, 0xAF, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFB, 0xAB, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAD, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xCD, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xB4, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x96, 0x06, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD0, 0x02, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE7, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB3, 0x03, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA2, 0x09, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB7, 0x04, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xE0, 0xB0, 0x02, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xFA, 0x0E, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xAC, 0x01, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF5, 0x16, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xEB, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xD8, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xCD, 0x13, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xD3, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8C, 0x01, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xB2, 0x02, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x88, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x81, 0x05, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDB, 0x09, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDA, 0x04, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0x44, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x1E, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x83, 0x14, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA0, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFF, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF6, 0x07, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xDD, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD3, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD7, 0x0F, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFE, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDE, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF2, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0x8E, 0x04, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xB6, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xE9, 0xAB, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x81, 0x04, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x95, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB4, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFC, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC2, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xC7, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xE8, 0x0F, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xCA, 0x14, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x04, 0x08, 0xC4, 0xAB, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xBF, 0x13, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xB2, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x90, 0x14, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x91, 0x01, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x8F, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x91, 0x10, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x8E, 0x04, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xB9, 0xAB, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF6, 0xAE, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x87, 0xAC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF5, 0x05, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD7, 0x11, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC6, 0x15, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF3, 0x0C, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA7, 0x15, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xD2, 0x0A, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xDD, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC9, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xF7, 0xAB, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xD2, 0xAE, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xD1, 0x91, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC7, 0x17, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x87, 0x07, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x93, 0x04, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xC1, 0xAB, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x9B, 0x14, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xC2, 0x07, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF4, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x84, 0x10, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x87, 0x07, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xF5, 0x08, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x8D, 0xAD, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xFA, 0xAA, 0x02, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x22, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF3, 0x0F, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x88, 0x14, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xC1, 0xAB, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x9B, 0x14, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xF2, 0x0B, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xBC, 0x15, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xEB, 0x0F, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xE7, 0x11, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD7, 0x0F, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xFA, 0x06, 0x10, 0x01, 0x10, 0x80, 0x19, 0x18, 0xC0, 0x0C, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDD, 0x04, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x96, 0x68, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0xAA, 0x06, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xD1, 0x13, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC8, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0xA2, 0x04, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0xFA, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0x88, 0x10, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0D, 0x0A, 0x03, 0x08, 0xA5, 0x10, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xDC, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0x94, 0x10, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xC4, 0x16, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0xC9, 0xB0, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x06, 0x08, 0x82, 0xAD, 0x02, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x04, 0x08, 0x87, 0xAC, 0x02, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0C, 0x0A, 0x03, 0x08, 0x90, 0x02, 0x10, 0x90, 0x03, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0F, 0x0A, 0x05, 0x08, 0x92, 0x0F, 0x10, 0x01, 0x10, 0xC0, 0x0C, 0x18, 0x90, 0x03, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xFA, 0x0D, 0x10, 0x64, 0x18, 0x14, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xF1, 0x13, 0x10, 0x01, 0x10, 0xA0, 0x06, 0x18, 0x64, 0x20, 0x00, 0x0A, 0x0B, 0x0A, 0x03, 0x08, 0xC0, 0x15, 0x10, 0x28, 0x18, 0x05, 0x20, 0x00, 0x0A, 0x0E, 0x0A, 0x05, 0x08, 0xFE, 0x0F, 0x10, 0x01, 0x10, 0x90, 0x03, 0x18, 0x32, 0x20, 0x00, 0x10, 0x05, 0x22, 0x14, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x04, 0x18, 0xA9, 0xAE, 0x01, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 22545) { memcpy(dst, src, 22545); } else { abort(); } +return 22545;} +int step11_29(char *dst, int ndst) {const char src[270] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x2E, 0x20, 0x00, 0x28, 0xFF, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x8F, 0x02, 0x22, 0x41, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x31, 0x32, 0x2F, 0x0A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x05, 0x18, 0x1F, 0x20, 0x16, 0x28, 0x06, 0x30, 0x12, 0x10, 0x03, 0x18, 0x0A, 0x20, 0x64, 0x28, 0x1F, 0x48, 0x3C, 0x50, 0x3C, 0x5A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x05, 0x18, 0x03, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, 0x65, 0xAA, 0xAA, 0xAA, 0xBD, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x2F, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 270) { memcpy(dst, src, 270); } else { abort(); } +return 270;} +int step11_30(char *dst, int ndst) {const char src[272] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x2F, 0x20, 0x00, 0x28, 0x81, 0x02, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x8E, 0x02, 0x22, 0x43, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x33, 0x32, 0x31, 0x0A, 0x06, 0x08, 0x01, 0x18, 0x01, 0x20, 0x00, 0x0A, 0x09, 0x08, 0x01, 0x10, 0xFD, 0x04, 0x18, 0x01, 0x20, 0x00, 0x0A, 0x06, 0x08, 0x04, 0x18, 0x06, 0x20, 0x01, 0x0A, 0x09, 0x08, 0x04, 0x10, 0xFD, 0x04, 0x18, 0x01, 0x20, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x10, 0xAD, 0x0A, 0x18, 0x05, 0x20, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x31, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 272) { memcpy(dst, src, 272); } else { abort(); } +return 272;} +int step11_31(char *dst, int ndst) {const char src[225] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x30, 0x20, 0x00, 0x28, 0xD2, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x86, 0x02, 0x22, 0x14, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x04, 0x32, 0x02, 0x08, 0x00, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x02, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 225) { memcpy(dst, src, 225); } else { abort(); } +return 225;} +int step11_32(char *dst, int ndst) {const char src[234] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x31, 0x20, 0x00, 0x28, 0xDB, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x96, 0x02, 0x22, 0x1D, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x0D, 0x32, 0x0B, 0x08, 0x00, 0x10, 0x00, 0x18, 0xBF, 0x84, 0x3D, 0x20, 0xD0, 0x0F, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x0B, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 234) { memcpy(dst, src, 234); } else { abort(); } +return 234;} +int step11_33(char *dst, int ndst) {const char src[277] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x32, 0x20, 0x00, 0x28, 0x86, 0x02, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xF1, 0x01, 0x22, 0x48, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x38, 0x32, 0x36, 0x0A, 0x04, 0x08, 0x18, 0x18, 0x03, 0x0A, 0x0B, 0x08, 0x01, 0x30, 0x80, 0xE0, 0x83, 0x80, 0xC0, 0xE1, 0x80, 0x18, 0x0A, 0x09, 0x08, 0x02, 0x30, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x0A, 0x04, 0x08, 0x14, 0x18, 0x02, 0x0A, 0x04, 0x08, 0x15, 0x18, 0x01, 0x0A, 0x04, 0x08, 0x08, 0x18, 0x04, 0x0A, 0x04, 0x08, 0x0A, 0x18, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x36, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 277) { memcpy(dst, src, 277); } else { abort(); } +return 277;} +int step11_34(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x33, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xB2, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } else { abort(); } +return 203;} +int step11_35(char *dst, int ndst) {const char src[452] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x34, 0x20, 0x00, 0x28, 0xB5, 0x03, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x9B, 0x02, 0x22, 0xF5, 0x01, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0xE4, 0x01, 0x32, 0xE1, 0x01, 0x0A, 0x17, 0x08, 0x02, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xB7, 0x06, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x03, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xB5, 0x03, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x04, 0x10, 0x02, 0x18, 0x0C, 0x20, 0x50, 0x2A, 0x0D, 0x08, 0x04, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xBC, 0x08, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x05, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xCF, 0x06, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x06, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xD1, 0x0A, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x07, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xA5, 0x03, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x08, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0x93, 0x09, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x09, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xD6, 0x07, 0x10, 0x00, 0x10, 0x02, 0x0A, 0x17, 0x08, 0x0A, 0x10, 0x01, 0x18, 0x00, 0x20, 0x46, 0x2A, 0x0D, 0x08, 0x02, 0x1A, 0x09, 0x0A, 0x05, 0x08, 0xAC, 0x07, 0x10, 0x00, 0x10, 0x02, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x03, 0x18, 0xE1, 0x01, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 452) { memcpy(dst, src, 452); } else { abort(); } +return 452;} +int step11_36(char *dst, int ndst) {const char src[10418] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x35, 0x20, 0x00, 0x28, 0xA3, 0x51, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xEE, 0x01, 0x22, 0xE3, 0x4F, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0xD2, 0x4F, 0x32, 0xCF, 0x4F, 0x0A, 0xB4, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x35, 0x30, 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x37, 0x32, 0x33, 0x38, 0x32, 0x11, 0xA4, 0x70, 0x3D, 0x0A, 0xD7, 0xA3, 0xFC, 0x3F, 0x1A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x61, 0x72, 0x65, 0x6E, 0x61, 0x70, 0x61, 0x73, 0x73, 0x22, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x61, 0x72, 0x65, 0x6E, 0x61, 0x70, 0x61, 0x73, 0x73, 0x2A, 0x06, 0x08, 0x02, 0x10, 0x00, 0x18, 0x01, 0x3A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x61, 0x72, 0x65, 0x6E, 0x61, 0x70, 0x61, 0x73, 0x73, 0x0A, 0xB1, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x35, 0x30, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x37, 0x32, 0x33, 0x38, 0x33, 0x11, 0x85, 0xEB, 0x51, 0xB8, 0x1E, 0x85, 0x05, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x01, 0x18, 0x02, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x0A, 0xB1, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x35, 0x30, 0x34, 0x31, 0x30, 0x30, 0x30, 0x30, 0x37, 0x32, 0x33, 0x38, 0x34, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x01, 0x18, 0x07, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x0A, 0xB4, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x35, 0x30, 0x35, 0x31, 0x30, 0x30, 0x30, 0x30, 0x37, 0x32, 0x33, 0x38, 0x35, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x31, 0x40, 0x1A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x22, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x01, 0x18, 0x0F, 0x3A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x0A, 0xB4, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x35, 0x30, 0x36, 0x31, 0x30, 0x30, 0x30, 0x30, 0x37, 0x32, 0x33, 0x38, 0x36, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x46, 0x40, 0x1A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x22, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x01, 0x18, 0x28, 0x3A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x31, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x31, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x01, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x31, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x32, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x02, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x32, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x33, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x33, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x03, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x33, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x34, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x34, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x04, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x34, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xE2, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x31, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x31, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x01, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x03, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x02, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x04, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x05, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x31, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xDA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x32, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x03, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x02, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x04, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x05, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x32, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xD2, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x38, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x33, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x33, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x03, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x04, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x05, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x33, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x39, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x35, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x35, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x05, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x57, 0x30, 0x30, 0x35, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x31, 0x30, 0x30, 0x30, 0x31, 0x39, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x34, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x34, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x04, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x03, 0x10, 0x05, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x31, 0x42, 0x30, 0x30, 0x34, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xB6, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x31, 0x39, 0x32, 0x33, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x31, 0x36, 0x33, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x31, 0x22, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x31, 0x2A, 0x07, 0x08, 0x06, 0x10, 0x8C, 0x16, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x05, 0x10, 0x1A, 0x18, 0x01, 0x3A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x31, 0x4A, 0x06, 0x6C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x0A, 0xB6, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x31, 0x39, 0x32, 0x36, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x31, 0x36, 0x36, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x33, 0x22, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x33, 0x2A, 0x07, 0x08, 0x06, 0x10, 0x8D, 0x16, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x05, 0x10, 0x1B, 0x18, 0x01, 0x3A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x33, 0x4A, 0x06, 0x6C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x0A, 0xB6, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x31, 0x39, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x31, 0x37, 0x32, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x32, 0x22, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x32, 0x2A, 0x07, 0x08, 0x06, 0x10, 0x8A, 0x16, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x05, 0x10, 0x19, 0x18, 0x01, 0x3A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x32, 0x4A, 0x06, 0x6C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x0A, 0x27, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x33, 0x34, 0x35, 0x36, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x37, 0x35, 0x36, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x4F, 0x40, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x01, 0x18, 0x3C, 0x0A, 0xCB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x33, 0x34, 0x35, 0x39, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x37, 0x35, 0x39, 0x1A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x22, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x09, 0x18, 0x02, 0x3A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x33, 0x34, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x37, 0x36, 0x32, 0x1A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x22, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x09, 0x18, 0x07, 0x3A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCE, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x33, 0x34, 0x36, 0x35, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x37, 0x36, 0x35, 0x1A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x22, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x09, 0x18, 0x0F, 0x3A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCE, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x33, 0x34, 0x36, 0x38, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x37, 0x36, 0x38, 0x1A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x22, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x09, 0x18, 0x28, 0x3A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x31, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0x38, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x30, 0x33, 0x34, 0x37, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x37, 0x37, 0x31, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x09, 0x18, 0x3C, 0x5A, 0x18, 0x6E, 0x61, 0x78, 0x78, 0x5F, 0x67, 0x76, 0x67, 0x5F, 0x72, 0x65, 0x61, 0x6C, 0x5F, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x35, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x34, 0x34, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x31, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x31, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x06, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x31, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x35, 0x35, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x34, 0x37, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x32, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x07, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x32, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x35, 0x38, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x35, 0x30, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x33, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x33, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x08, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x33, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x36, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x35, 0x33, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x34, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x34, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x09, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x34, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC5, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x36, 0x34, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x35, 0x36, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x35, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x35, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x0A, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x57, 0x30, 0x30, 0x35, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xE2, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x36, 0x37, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x35, 0x39, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x35, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x31, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x31, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x06, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x07, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x08, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x09, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x0A, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x31, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xDA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x37, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x36, 0x32, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x31, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x32, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x07, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x08, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x09, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x0A, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x32, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xD2, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x37, 0x33, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x36, 0x35, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x2B, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x33, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x33, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x08, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x09, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x0A, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x33, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x37, 0x36, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x36, 0x38, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x34, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x34, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x09, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x0A, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x34, 0x4A, 0x0F, 0x62, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xEA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x31, 0x39, 0x37, 0x39, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x30, 0x37, 0x31, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x35, 0x40, 0x1A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x31, 0x70, 0x22, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x31, 0x70, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x06, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x07, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x08, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x09, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x04, 0x10, 0x0A, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x05, 0x10, 0x12, 0x18, 0x01, 0x3A, 0x2D, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x32, 0x42, 0x30, 0x30, 0x31, 0x70, 0x4A, 0x0C, 0x62, 0x72, 0x6D, 0x5F, 0x70, 0x72, 0x65, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xD6, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x32, 0x30, 0x30, 0x31, 0x35, 0x39, 0x38, 0x37, 0x32, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x34, 0x35, 0x37, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x46, 0x40, 0x1A, 0x31, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x35, 0x30, 0x70, 0x22, 0x31, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x35, 0x30, 0x70, 0x2A, 0x06, 0x08, 0x05, 0x10, 0x1F, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x32, 0x3A, 0x31, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x35, 0x30, 0x70, 0x4A, 0x0C, 0x74, 0x67, 0x74, 0x5F, 0x70, 0x72, 0x65, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x36, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x36, 0x11, 0x85, 0xEB, 0x51, 0xB8, 0x1E, 0x85, 0x05, 0x40, 0x1A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x22, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x02, 0x3A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x4A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x37, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x37, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x22, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x07, 0x3A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x4A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCE, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x38, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x38, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x31, 0x40, 0x1A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x22, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x0F, 0x3A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x4A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCE, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 0x39, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x39, 0x30, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x46, 0x40, 0x1A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x22, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x28, 0x3A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x32, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x4A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0x38, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 0x39, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x39, 0x31, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x4F, 0x40, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0A, 0x18, 0x3C, 0x4A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xC0, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x30, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x37, 0x36, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x33, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x33, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0D, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0E, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x33, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xBB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x35, 0x39, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x31, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x31, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0B, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x31, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xBB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x30, 0x38, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x36, 0x33, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x32, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0C, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x32, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xBB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x30, 0x39, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x38, 0x34, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x33, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x33, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0D, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x33, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xBB, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x38, 0x35, 0x11, 0xF6, 0x28, 0x5C, 0x8F, 0xC2, 0xF5, 0x17, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x34, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x34, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0E, 0x18, 0x01, 0x30, 0xBC, 0x05, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x57, 0x30, 0x30, 0x34, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xD0, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x31, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x38, 0x36, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x31, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x31, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x31, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0B, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0C, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0D, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0E, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x31, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xC8, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x33, 0x33, 0x31, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x38, 0x37, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x2B, 0x40, 0x1A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x32, 0x22, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x32, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0C, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0D, 0x18, 0x01, 0x2A, 0x06, 0x08, 0x07, 0x10, 0x0E, 0x18, 0x01, 0x3A, 0x2C, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x41, 0x30, 0x30, 0x33, 0x42, 0x30, 0x30, 0x32, 0x4A, 0x05, 0x6C, 0x6F, 0x65, 0x5F, 0x31, 0x0A, 0xCD, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x34, 0x31, 0x36, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x30, 0x32, 0x11, 0x3D, 0x0A, 0xD7, 0xA3, 0x70, 0xFD, 0x31, 0x40, 0x1A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x22, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0B, 0x18, 0x0F, 0x3A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x31, 0x35, 0x4A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCD, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x34, 0x31, 0x37, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x30, 0x33, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x46, 0x40, 0x1A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x22, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0B, 0x18, 0x28, 0x3A, 0x30, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x34, 0x30, 0x4A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0x37, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x34, 0x31, 0x38, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x31, 0x30, 0x34, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x4F, 0x40, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0B, 0x18, 0x3C, 0x4A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xD9, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x34, 0x37, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x38, 0x38, 0x11, 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x7E, 0x46, 0x40, 0x1A, 0x31, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x35, 0x30, 0x70, 0x22, 0x31, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x35, 0x30, 0x70, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0B, 0x18, 0x32, 0x2A, 0x06, 0x08, 0x05, 0x10, 0x2D, 0x18, 0x01, 0x3A, 0x31, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x35, 0x30, 0x70, 0x4A, 0x0F, 0x6F, 0x67, 0x5F, 0x70, 0x72, 0x65, 0x5F, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x0A, 0xCA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x34, 0x37, 0x37, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x39, 0x35, 0x11, 0x85, 0xEB, 0x51, 0xB8, 0x1E, 0x85, 0x05, 0x40, 0x1A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x22, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0B, 0x18, 0x02, 0x3A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x32, 0x4A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xCA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x34, 0x34, 0x37, 0x38, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x39, 0x36, 0x11, 0x7B, 0x14, 0xAE, 0x47, 0xE1, 0xFA, 0x21, 0x40, 0x1A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x22, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x2A, 0x06, 0x08, 0x01, 0x10, 0x0B, 0x18, 0x07, 0x3A, 0x2F, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x78, 0x33, 0x2E, 0x62, 0x6F, 0x6F, 0x73, 0x74, 0x65, 0x72, 0x37, 0x4A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x0A, 0xBA, 0x01, 0x0A, 0x14, 0x39, 0x39, 0x33, 0x30, 0x30, 0x30, 0x35, 0x30, 0x34, 0x34, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x36, 0x36, 0x35, 0x1A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x34, 0x22, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x34, 0x2A, 0x08, 0x08, 0x06, 0x10, 0xCD, 0xB1, 0x02, 0x18, 0x01, 0x3A, 0x28, 0x63, 0x6F, 0x6D, 0x2E, 0x62, 0x6C, 0x69, 0x7A, 0x7A, 0x61, 0x72, 0x64, 0x2E, 0x77, 0x74, 0x63, 0x67, 0x2E, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x2E, 0x69, 0x61, 0x70, 0x45, 0x55, 0x2E, 0x48, 0x30, 0x30, 0x34, 0x4A, 0x18, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x5F, 0x63, 0x68, 0x61, 0x72, 0x69, 0x74, 0x79, 0x5F, 0x70, 0x72, 0x6F, 0x6D, 0x6F, 0x5F, 0x32, 0x30, 0x31, 0x36, 0x50, 0x02, 0x10, 0x04, 0x28, 0xD8, 0x04, 0x32, 0x04, 0x08, 0x64, 0x10, 0x01, 0x32, 0x15, 0x08, 0x64, 0x10, 0x0A, 0x1A, 0x0F, 0x74, 0x67, 0x74, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x32, 0x14, 0x08, 0x64, 0x10, 0x0B, 0x1A, 0x0E, 0x6F, 0x67, 0x5F, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x5F, 0x73, 0x61, 0x6C, 0x65, 0x38, 0x96, 0x01, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x03, 0x18, 0xCF, 0x4F, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 10418) { memcpy(dst, src, 10418); } else { abort(); } +return 10418;} +int step11_37(char *dst, int ndst) {const char src[320] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x36, 0x20, 0x00, 0x28, 0xB1, 0x02, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xBE, 0x02, 0x22, 0x73, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x63, 0x32, 0x61, 0x0A, 0x09, 0x08, 0x02, 0x12, 0x05, 0x08, 0x92, 0x02, 0x10, 0x00, 0x0A, 0x08, 0x08, 0x03, 0x12, 0x04, 0x08, 0x1F, 0x10, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x12, 0x05, 0x08, 0xFD, 0x04, 0x10, 0x00, 0x0A, 0x09, 0x08, 0x05, 0x12, 0x05, 0x08, 0x9F, 0x05, 0x10, 0x00, 0x0A, 0x09, 0x08, 0x06, 0x12, 0x05, 0x08, 0xAD, 0x06, 0x10, 0x00, 0x0A, 0x09, 0x08, 0x07, 0x12, 0x05, 0x08, 0xA2, 0x07, 0x10, 0x00, 0x0A, 0x09, 0x08, 0x08, 0x12, 0x05, 0x08, 0xAA, 0x08, 0x10, 0x00, 0x0A, 0x09, 0x08, 0x09, 0x12, 0x05, 0x08, 0xFD, 0x06, 0x10, 0x00, 0x0A, 0x08, 0x08, 0x0A, 0x12, 0x04, 0x08, 0x07, 0x10, 0x00, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x61, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 320) { memcpy(dst, src, 320); } else { abort(); } +return 320;} +int step11_38(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x37, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x15, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step11_39(char *dst, int ndst) {const char src[225] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x38, 0x20, 0x00, 0x28, 0xD2, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xEC, 0x01, 0x22, 0x14, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x04, 0x32, 0x02, 0x08, 0x00, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x02, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 225) { memcpy(dst, src, 225); } else { abort(); } +return 225;} +int step11_40(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x39, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC5, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } else { abort(); } +return 203;} diff --git a/hm_lobbyserver/src/step12.c b/hm_lobbyserver/src/step12.c new file mode 100644 index 0000000..75dd959 --- /dev/null +++ b/hm_lobbyserver/src/step12.c @@ -0,0 +1,30 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step12_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x1A, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00 }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} + +int step12_1(char *dst, int ndst) {const char src[65] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x3A, 0x20, 0x02, 0x28, 0x33, 0x30, 0x00, 0x12, 0x31, 0xAA, 0x06, 0x2E, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x0A, 0x16, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x12, 0x12, 0x08, 0x32, 0x06, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, }; +if(ndst >= 65) { memcpy(dst, src, 65); } else { abort(); } +return 65;} diff --git a/hm_lobbyserver/src/step13.c b/hm_lobbyserver/src/step13.c new file mode 100644 index 0000000..695e8ca --- /dev/null +++ b/hm_lobbyserver/src/step13.c @@ -0,0 +1,38 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step13_0(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x1B, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xFD, 0x01, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} + int step13_1(char *dst, int ndst) {const char src[6263] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x3B, 0x20, 0x00, 0x28, 0xE8, 0x30, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xFC, 0x01, 0x22, 0xA8, 0x2F, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x97, 0x2F, 0x32, 0x94, 0x2F, 0x0A, 0x28, 0x08, 0x02, 0x10, 0x01, 0x18, 0x01, 0x20, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x0A, 0x28, 0x08, 0x03, 0x10, 0x01, 0x18, 0x01, 0x20, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x0A, 0x31, 0x08, 0x0F, 0x10, 0x01, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x0A, 0x31, 0x08, 0x18, 0x10, 0x01, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x0A, 0x31, 0x08, 0x3E, 0x10, 0x01, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x0A, 0x31, 0x08, 0x3F, 0x10, 0x01, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x24, 0x30, 0x15, 0x0A, 0x28, 0x08, 0x41, 0x10, 0x01, 0x18, 0x01, 0x20, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x0A, 0x31, 0x08, 0x4F, 0x10, 0x02, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x0A, 0x28, 0x08, 0x61, 0x10, 0x01, 0x18, 0x01, 0x20, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x0A, 0x29, 0x08, 0xD8, 0x01, 0x10, 0x01, 0x18, 0x01, 0x20, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x0A, 0x29, 0x08, 0xD9, 0x01, 0x10, 0x01, 0x18, 0x01, 0x28, 0x01, 0x30, 0x01, 0x3A, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x42, 0x0D, 0x08, 0xE0, 0x0F, 0x10, 0x04, 0x18, 0x18, 0x20, 0x09, 0x28, 0x1E, 0x30, 0x0A, 0x0A, 0x13, 0x08, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x04, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x05, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x06, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x07, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x08, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x09, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x0A, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x0D, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x0E, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x10, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x11, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x12, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x13, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x14, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x15, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x16, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x17, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x19, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x1A, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x1B, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x1C, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x1D, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x1E, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x37, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x39, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x3A, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x3B, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x3C, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x3D, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x42, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x43, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x44, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x46, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x47, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x48, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x49, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x4A, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x4B, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x4C, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x4D, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x4E, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x50, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x51, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x52, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x53, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x54, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x55, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x56, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x57, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x58, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x59, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x5A, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x5B, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x5C, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x5D, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x5E, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x5F, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x60, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x62, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x63, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x64, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x65, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x66, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x67, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x68, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x69, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x6A, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x6B, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x6C, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x6D, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x6E, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x70, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x71, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x72, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x73, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x74, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x75, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x76, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x77, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x78, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x79, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x13, 0x08, 0x7F, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x80, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x81, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x82, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x83, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x84, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x85, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x86, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x87, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x88, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x89, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8A, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8B, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8C, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8D, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8E, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8F, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x90, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x91, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x92, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x93, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x94, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x95, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x96, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x97, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x98, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x99, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9A, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9B, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9C, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9D, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9E, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9F, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA0, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA1, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA2, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA3, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA4, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA5, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA6, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA7, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA8, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA9, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAA, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAB, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAC, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAD, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAE, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAF, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB0, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB1, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB2, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB3, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB4, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB5, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB6, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB7, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB8, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB9, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBA, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBB, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBC, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBD, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBE, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBF, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC0, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC1, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC2, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC3, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC4, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC5, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC6, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC7, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC8, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC9, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCA, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCB, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCD, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCE, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCF, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD0, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD1, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD2, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD3, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD4, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD5, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD7, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xDA, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xDC, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xDD, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xE8, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xE9, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xEA, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xEB, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xEC, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xED, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xEE, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xEF, 0x01, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x84, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x85, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x86, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x87, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x88, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x89, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8A, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8B, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8C, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8D, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8E, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x8F, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x90, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x91, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x92, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x93, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x94, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x95, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x96, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x97, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x98, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x99, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9A, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9B, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0x9C, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA1, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA2, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA3, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA4, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA5, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA6, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA7, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA8, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xA9, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAA, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAB, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAC, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAD, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAE, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xAF, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB0, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB1, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB2, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB3, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB4, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB5, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB6, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB7, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB8, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xB9, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBA, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBB, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBC, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBD, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBE, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xBF, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC0, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC1, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC2, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC3, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC4, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC5, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC6, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC7, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC8, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xC9, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCA, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCB, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCC, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCD, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCE, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xCF, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD0, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD1, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x0A, 0x14, 0x08, 0xD2, 0x02, 0x10, 0x00, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x28, 0x01, 0x48, 0x01, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x03, 0x18, 0x94, 0x2F, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +#include +#include +#include +#include +#include + +if(ndst >= 6263) { memcpy(dst, src, 6263); } else { abort(); } +return 6263;} + int step13_2(char *dst, int ndst) {const char src[41] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x1C, 0x20, 0x00, 0x28, 0x1C, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0x89, 0x02, 0x0A, 0x0F, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x06, 0x32, 0x04, 0x08, 0x00, 0x20, 0x01, }; +if(ndst >= 41) { memcpy(dst, src, 41); } else { abort(); } +return 41;} diff --git a/hm_lobbyserver/src/step14.c b/hm_lobbyserver/src/step14.c new file mode 100644 index 0000000..91d7c6f --- /dev/null +++ b/hm_lobbyserver/src/step14.c @@ -0,0 +1,32 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step14_0(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x1D, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xC7, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step14_1(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x3C, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x0C, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step14_2(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x3D, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xD4, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } else { abort(); } +return 203;} diff --git a/hm_lobbyserver/src/step15.c b/hm_lobbyserver/src/step15.c new file mode 100644 index 0000000..a1bf382 --- /dev/null +++ b/hm_lobbyserver/src/step15.c @@ -0,0 +1,29 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step15_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x1E, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step15_1(char *dst, int ndst) {const char src[98] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x3E, 0x20, 0x02, 0x28, 0x54, 0x30, 0x00, 0x12, 0x52, 0xAA, 0x06, 0x4F, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x19, 0x0A, 0x17, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x09, 0x20, 0x00, 0x12, 0x09, 0x18, 0x84, 0xB6, 0xDA, 0xFC, 0xCE, 0xBD, 0xCC, 0x02, 0x12, 0x1E, 0x0A, 0x1C, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x08, 0x20, 0x00, 0x12, 0x0E, 0x3A, 0x0C, 0x0D, 0x47, 0x43, 0x54, 0x57, 0x15, 0x74, 0x61, 0x74, 0x73, 0x18, 0x04, }; +if(ndst >= 98) { memcpy(dst, src, 98); } else { abort(); } +return 98;} diff --git a/hm_lobbyserver/src/step16.c b/hm_lobbyserver/src/step16.c new file mode 100644 index 0000000..e9d8655 --- /dev/null +++ b/hm_lobbyserver/src/step16.c @@ -0,0 +1,32 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step16_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x1F, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step16_1(char *dst, int ndst) {const char src[64] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x3F, 0x20, 0x02, 0x28, 0x32, 0x30, 0x00, 0x12, 0x30, 0xAA, 0x06, 0x2D, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x11, 0x12, 0x07, 0x32, 0x05, 0x01, 0x03, 0x00, 0x00, 0x00, }; +if(ndst >= 64) { memcpy(dst, src, 64); } else { abort(); } +return 64;} +int step16_2(char *dst, int ndst) {const char src[57] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x20, 0x20, 0x00, 0x28, 0x2C, 0x30, 0x00, 0x0D, 0x55, 0x45, 0x00, 0x00, 0x15, 0x73, 0x73, 0x68, 0x00, 0x1A, 0x20, 0xBE, 0xC5, 0x29, 0x22, 0x31, 0xD7, 0x68, 0x6A, 0xF0, 0x0C, 0xE6, 0x4E, 0x0C, 0x58, 0xCC, 0x6E, 0x36, 0x0E, 0xA9, 0x50, 0xAA, 0xFF, 0xAC, 0x6A, 0x11, 0x4F, 0x03, 0xA9, 0x58, 0xE2, 0x75, 0xF3, }; +if(ndst >= 57) { memcpy(dst, src, 57); } else { abort(); } +return 57;} diff --git a/hm_lobbyserver/src/step17.c b/hm_lobbyserver/src/step17.c new file mode 100644 index 0000000..f90a6f1 --- /dev/null +++ b/hm_lobbyserver/src/step17.c @@ -0,0 +1,35 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step17_0(char *dst, int ndst) {const char src[44] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x23, 0x20, 0x00, 0x28, 0x1F, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x12, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x06, }; +if(ndst >= 44) { memcpy(dst, src, 44); } else { abort(); } +return 44;} + int step17_1(char *dst, int ndst) {const char src[203] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x40, 0x20, 0x00, 0x28, 0xBC, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xE0, 0x01, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x00, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 203) { memcpy(dst, src, 203); } else { abort(); } +return 203;} +int step17_2(char *dst, int ndst) {const char src[44] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x24, 0x20, 0x00, 0x28, 0x1F, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x12, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x12, }; +if(ndst >= 44) { memcpy(dst, src, 44); } else { abort(); } +return 44;} +int step17_3(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x41, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x88, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x80, 0x01, 0x01, 0xA8, 0x01, 0xAC, 0x02, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x89, 0xFF, 0x5C, 0x10, 0x92, 0xE5, 0xA1, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} diff --git a/hm_lobbyserver/src/step18.c b/hm_lobbyserver/src/step18.c new file mode 100644 index 0000000..4dbca31 --- /dev/null +++ b/hm_lobbyserver/src/step18.c @@ -0,0 +1,35 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step18_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x25, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00 }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step18_1(char *dst, int ndst) {const char src[59] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x42, 0x20, 0x02, 0x28, 0x2D, 0x30, 0x00, 0x12, 0x2B, 0xAA, 0x06, 0x28, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0A, 0x10, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x01, 0x12, 0x02, 0x10, 0x01, }; +if(ndst >= 59) { memcpy(dst, src, 59); } else { abort(); } +return 59;} +int step18_2(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x26, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step18_3(char *dst, int ndst) {const char src[64] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x43, 0x20, 0x02, 0x28, 0x32, 0x30, 0x00, 0x12, 0x30, 0xAA, 0x06, 0x2D, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x11, 0x12, 0x07, 0x32, 0x05, 0x01, 0x04, 0x00, 0x00, 0x00, }; +if(ndst >= 64) { memcpy(dst, src, 64); } else { abort(); } +return 64;} diff --git a/hm_lobbyserver/src/step19.c b/hm_lobbyserver/src/step19.c new file mode 100644 index 0000000..6535022 --- /dev/null +++ b/hm_lobbyserver/src/step19.c @@ -0,0 +1,38 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step19_0(char *dst, int ndst) {const char src[42] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x25, 0x20, 0x00, 0x28, 0x1D, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x0A, 0x10, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x07, 0x32, 0x05, 0x08, 0x01, 0x10, 0xC7, 0x02, }; +if(ndst >= 42) { memcpy(dst, src, 42); } else { abort(); } +return 42;} +int step19_1(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x44, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x04, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step19_2(char *dst, int ndst) {const char src[230] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x45, 0x20, 0x00, 0x28, 0xD7, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xC6, 0x02, 0x22, 0x19, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x09, 0x32, 0x07, 0x08, 0x01, 0x10, 0xC9, 0x01, 0x18, 0x16, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x07, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 230) { memcpy(dst, src, 230); } else { abort(); } +return 230;} +int step19_3(char *dst, int ndst) {const char src[263] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x46, 0x20, 0x00, 0x28, 0xF8, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0xE8, 0x01, 0x22, 0x3A, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x2A, 0x32, 0x28, 0x0A, 0x12, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x40, 0x01, 0x48, 0x01, 0x50, 0x03, 0x58, 0x00, 0x70, 0x01, 0x78, 0x00, 0x12, 0x12, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x40, 0x01, 0x48, 0x01, 0x50, 0x03, 0x58, 0x00, 0x70, 0x01, 0x78, 0x00, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x28, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 263) { memcpy(dst, src, 263); } else { abort(); } +return 263;} +int step19_4(char *dst, int ndst) {const char src[227] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x47, 0x20, 0x00, 0x28, 0xD4, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1C, 0x57, 0x54, 0x43, 0x47, 0x2E, 0x55, 0x74, 0x69, 0x6C, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0x18, 0x9E, 0x02, 0x22, 0x16, 0x0A, 0x0C, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x5F, 0x30, 0x30, 0x30, 0x12, 0x06, 0x32, 0x04, 0x0A, 0x02, 0x08, 0x09, 0x22, 0x12, 0x0A, 0x0C, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x12, 0x02, 0x18, 0x04, 0x2A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 227) { memcpy(dst, src, 227); } else { abort(); } +return 227;} diff --git a/hm_lobbyserver/src/step20.c b/hm_lobbyserver/src/step20.c new file mode 100644 index 0000000..5f27055 --- /dev/null +++ b/hm_lobbyserver/src/step20.c @@ -0,0 +1,26 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step20_0(char *dst, int ndst) {const char src[741] = { 0x00, 0x0C, 0x08, 0xFE, 0x01, 0x18, 0x26, 0x20, 0x00, 0x28, 0xD7, 0x05, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xD7, 0x01, 0x0A, 0xC9, 0x05, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0xBF, 0x05, 0x32, 0xBC, 0x05, 0x08, 0xCF, 0xED, 0x81, 0xFB, 0x02, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0x9E, 0x05, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xAB, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0C, 0x0A, 0x04, 0x08, 0x4D, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xFB, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xA1, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xBB, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0x9C, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xBF, 0x01, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xDA, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xBF, 0x03, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0x96, 0x0D, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xF9, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xD8, 0x01, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xD9, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x12, 0x0D, 0x0A, 0x05, 0x08, 0xB4, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0xE8, 0x01, 0x08, 0x01, 0x10, 0xCF, 0xED, 0x81, 0xFB, 0x02, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x9E, 0x05, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xAB, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0C, 0x0A, 0x04, 0x08, 0x4D, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xFB, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xA1, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xBB, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x9C, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xBF, 0x01, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xDA, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xBF, 0x03, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x96, 0x0D, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xF9, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xD8, 0x01, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xD9, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xB4, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0xE8, 0x01, 0x08, 0x01, 0x10, 0x96, 0x97, 0x87, 0xFB, 0x02, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xEB, 0x07, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xDE, 0x04, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x97, 0x08, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0C, 0x0A, 0x04, 0x08, 0x43, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x97, 0x0D, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xD3, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x88, 0x05, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x9D, 0x03, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0x81, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xDA, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xF9, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xA4, 0x02, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xD8, 0x01, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xED, 0x06, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, 0x1A, 0x0D, 0x0A, 0x05, 0x08, 0xD9, 0x0A, 0x10, 0x00, 0x10, 0x00, 0x18, 0x02, 0x28, 0x00, }; +if(ndst >= 741) { memcpy(dst, src, 741); } else { abort(); } +return 741;} diff --git a/hm_lobbyserver/src/step21.c b/hm_lobbyserver/src/step21.c new file mode 100644 index 0000000..a1a5dda --- /dev/null +++ b/hm_lobbyserver/src/step21.c @@ -0,0 +1,29 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step21_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x27, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00,}; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step21_1(char *dst, int ndst) {const char src[64] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x48, 0x20, 0x02, 0x28, 0x32, 0x30, 0x00, 0x12, 0x30, 0xAA, 0x06, 0x2D, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x11, 0x12, 0x07, 0x32, 0x05, 0x01, 0x0B, 0x00, 0x00, 0x00, }; +if(ndst >= 64) { memcpy(dst, src, 64); } else { abort(); } +return 64;} diff --git a/hm_lobbyserver/src/step22.c b/hm_lobbyserver/src/step22.c new file mode 100644 index 0000000..01419ed --- /dev/null +++ b/hm_lobbyserver/src/step22.c @@ -0,0 +1,160 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step22_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x28, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step22_1(char *dst, int ndst) {const char src[59] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x49, 0x20, 0x02, 0x28, 0x2D, 0x30, 0x00, 0x12, 0x2B, 0xAA, 0x06, 0x28, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0A, 0x10, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x01, 0x12, 0x02, 0x10, 0x00, }; +if(ndst >= 59) { memcpy(dst, src, 59); } else { abort(); } +return 59;} +int step22_2(char *dst, int ndst) {const char src[33] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x29, 0x20, 0x00, 0x28, 0x14, 0x30, 0x00, 0x09, 0x36, 0xE9, 0xE8, 0x48, 0xE2, 0x8B, 0xC2, 0xB9, 0x11, 0xF6, 0x42, 0x63, 0xF5, 0xD3, 0x34, 0x56, 0xC7, 0x18, 0x01, }; +if(ndst >= 33) { memcpy(dst, src, 33); } else { abort(); } +return 33;} +int step22_3(char *dst, int ndst) {const char src[272] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x4A, 0x20, 0x00, 0x28, 0x81, 0x02, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x08, 0x47, 0x51, 0x5F, 0x45, 0x4E, 0x54, 0x52, 0x59, 0x22, 0x1E, 0x0A, 0x0F, 0x67, 0x61, 0x6D, 0x65, 0x5F, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x12, 0x0B, 0x48, 0xB6, 0xD2, 0xA3, 0xC7, 0xA4, 0xFC, 0xA2, 0xE1, 0xB9, 0x01, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x69, 0x6E, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x61, 0x78, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x0E, 0x0A, 0x08, 0x61, 0x76, 0x67, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x19, 0x0A, 0x0C, 0x73, 0x74, 0x64, 0x5F, 0x64, 0x65, 0x76, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x09, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x24, 0x0A, 0x0C, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6F, 0x72, 0x5F, 0x69, 0x64, 0x12, 0x14, 0x52, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x22, 0x19, 0x0A, 0x0A, 0x66, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x5F, 0x69, 0x64, 0x12, 0x0B, 0x48, 0xF6, 0x85, 0x8D, 0xAB, 0xBF, 0x9A, 0x8D, 0xAB, 0xC7, 0x01, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 272) { memcpy(dst, src, 272); } else { abort(); } +return 272;} +int step22_4(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x2A, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step22_5(char *dst, int ndst) {const char src[64] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x4B, 0x20, 0x02, 0x28, 0x32, 0x30, 0x00, 0x12, 0x30, 0xAA, 0x06, 0x2D, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x11, 0x12, 0x07, 0x32, 0x05, 0x01, 0x0C, 0x00, 0x00, 0x00, }; +if(ndst >= 64) { memcpy(dst, src, 64); } else { abort(); } +return 64;} +int step22_6(char *dst, int ndst) {const char src[208] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x4C, 0x20, 0x00, 0x28, 0xC1, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x09, 0x47, 0x51, 0x5F, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x22, 0x1E, 0x0A, 0x0F, 0x67, 0x61, 0x6D, 0x65, 0x5F, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x12, 0x0B, 0x48, 0xB6, 0xD2, 0xA3, 0xC7, 0xA4, 0xFC, 0xA2, 0xE1, 0xB9, 0x01, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x69, 0x6E, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4A, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x61, 0x78, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4A, 0x22, 0x0E, 0x0A, 0x08, 0x61, 0x76, 0x67, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x19, 0x0A, 0x0C, 0x73, 0x74, 0x64, 0x5F, 0x64, 0x65, 0x76, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x09, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 208) { memcpy(dst, src, 208); } else { abort(); } +return 208;} +int step22_7(char *dst, int ndst) {const char src[227] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x4D, 0x20, 0x00, 0x28, 0xD4, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x09, 0x47, 0x51, 0x5F, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x22, 0x1E, 0x0A, 0x0F, 0x67, 0x61, 0x6D, 0x65, 0x5F, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x12, 0x0B, 0x48, 0xB6, 0xD2, 0xA3, 0xC7, 0xA4, 0xFC, 0xA2, 0xE1, 0xB9, 0x01, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x69, 0x6E, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x61, 0x78, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x0E, 0x0A, 0x08, 0x61, 0x76, 0x67, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x19, 0x0A, 0x0C, 0x73, 0x74, 0x64, 0x5F, 0x64, 0x65, 0x76, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x09, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x11, 0x0A, 0x0B, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x6D, 0x61, 0x6B, 0x69, 0x6E, 0x67, 0x12, 0x02, 0x10, 0x01, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 227) { memcpy(dst, src, 227); } else { abort(); } +return 227;} +int step22_8(char *dst, int ndst) {const char src[208] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x4E, 0x20, 0x00, 0x28, 0xC1, 0x01, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x09, 0x47, 0x51, 0x5F, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x22, 0x1E, 0x0A, 0x0F, 0x67, 0x61, 0x6D, 0x65, 0x5F, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x12, 0x0B, 0x48, 0xB6, 0xD2, 0xA3, 0xC7, 0xA4, 0xFC, 0xA2, 0xE1, 0xB9, 0x01, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x69, 0x6E, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x45, 0x22, 0x0E, 0x0A, 0x08, 0x6D, 0x61, 0x78, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x45, 0x22, 0x0E, 0x0A, 0x08, 0x61, 0x76, 0x67, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x02, 0x48, 0x4E, 0x22, 0x19, 0x0A, 0x0C, 0x73, 0x74, 0x64, 0x5F, 0x64, 0x65, 0x76, 0x5F, 0x77, 0x61, 0x69, 0x74, 0x12, 0x09, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 208) { memcpy(dst, src, 208); } else { abort(); } +return 208;} + +static int write_byte(char **dst, const char *end, char src) +{ + if(*dst + sizeof(src) > end) { + abort(); + } + + memcpy(*dst, &src, sizeof(src)); + (*dst)++; + return 0; +} + +static void write_uint(char **dst, const char *end, int src) +{ + char b; + + while(1 == 1) { + b = (char)(src & 127); + src >>= 7; + + if(src == 0) { + break; + } + + b |= 128; + + write_byte(dst, end, b); + } + + write_byte(dst, end, b); +} + +static char read_byte(char **dst, const char *end) +{ + char out; + + if(*dst + sizeof(char) > end) { + return -1; + } + + out = *((char *)(*dst)); + + (*dst)++; + return out; +} + +static int read_uint(char **dst, const char *end) +{ + int num = 0, num2; + int i; + + for(i = 0; (i < 5 && *dst < end); i++) { + num2 = read_byte(dst, end); + + if(i == 4 && (num2 & 240) != 0) { + abort(); + } + + if((num2 & 128) == 0) { + return num | (unsigned int)((unsigned int)num2 << 7 * i); + } + + num |= (unsigned int)((unsigned int)(num2 & 127) << 7 * i); + } + + return num; +} + +int step22_9_1(char *dst, int ndst, int iplen) { + const char src[205] = { 0x00, 0x0D, 0x08, 0x04, 0x10, 0x01, 0x18, 0x4F, 0x20, 0x00, 0x28, 0xEB, 0x02, 0x30, 0x00, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x08, 0x47, 0x5F, 0x52, 0x45, 0x53, 0x55, 0x4C, 0x54, 0x22, 0x1E, 0x0A, 0x0F, 0x67, 0x61, 0x6D, 0x65, 0x5F, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x12, 0x0B, 0x48, 0xB6, 0xD2, 0xA3, 0xC7, 0xA4, 0xFC, 0xA2, 0xE1, 0xB9, 0x01, 0x22, 0x0B, 0x0A, 0x05, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x12, 0x02, 0x48, 0x00, 0x22, 0x2E, 0x0A, 0x0B, 0x67, 0x61, 0x6D, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x12, 0x1F, 0x3A, 0x1D, 0x09, 0xF6, 0x42, 0x63, 0xF5, 0xD3, 0x34, 0x56, 0xC7, 0x12, 0x12, 0x09, 0xEE, 0xA6, 0x0D, 0x57, 0x03, 0x00, 0x00, 0x06, 0x11, 0x8C, 0x27, 0x0B, 0x00, 0x0A, 0x62, 0xA3, 0xAB, 0x22, 0xB6, 0x01, 0x0A, 0x0F, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x66, 0x6F, 0x12, 0xA2, 0x01, 0x3A, 0x9F, 0x01, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12 }; + + int pos[4] = {11, 159, 179, 182}; + char *ptr; + int i; + + for(i = 0; i < (sizeof(pos)/sizeof(int)); i++) { + ptr = &src[pos[i]]; + int l = read_uint(&ptr, ptr + 4); + l += (iplen - 14); + ptr = &src[pos[i]]; + write_uint(&ptr, ptr + 4, l); + } + + if(ndst >= 205) { memcpy(dst, src, 205); } else { abort(); } + return 205; +} + +int step22_9_2(char *dst, int ndst, int port) { + const char src[185] = { 0x18, 0x8C, 0x1D, 0x22, 0x06, 0x45, 0x6A, 0x63, 0x44, 0x65, 0x49, 0x2A, 0x13, 0x0A, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x12, 0x08, 0x2A, 0x06, 0x32, 0x30, 0x38, 0x38, 0x39, 0x31, 0x2A, 0x0D, 0x0A, 0x04, 0x67, 0x61, 0x6D, 0x65, 0x12, 0x05, 0x18, 0xAA, 0x80, 0xC4, 0x06, 0x2A, 0x0C, 0x0A, 0x06, 0x70, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x12, 0x02, 0x18, 0x01, 0x2A, 0x0B, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x05, 0x18, 0xB2, 0xB0, 0xAA, 0x1C, 0x2A, 0x0F, 0x0A, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6D, 0x61, 0x62, 0x6C, 0x65, 0x12, 0x02, 0x10, 0x01, 0x2A, 0x1E, 0x0A, 0x12, 0x73, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x6F, 0x72, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x12, 0x08, 0x2A, 0x06, 0x6F, 0x44, 0x69, 0x70, 0x49, 0x66, 0x4A, 0x0A, 0x08, 0x95, 0xA5, 0x67, 0x10, 0xE9, 0xE6, 0xAC, 0xB9, 0x05, 0x52, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; + char *ptr = (char *)&src[1]; + write_uint(&ptr, ptr + 2, port); + + if(ndst >= 158) { + memcpy(dst, src, 158); + } else { + abort(); + } + + return 158; +} + +int step22_9_ip(char *dst, int ndst, const char *ip, const int iplen) +{ + int i; + dst[0] = iplen; + for(i = 0; i < iplen; i++) { + dst[i + 1] = ip[i]; + } + return iplen + 1; +} diff --git a/hm_lobbyserver/src/step23.c b/hm_lobbyserver/src/step23.c new file mode 100644 index 0000000..36c6faf --- /dev/null +++ b/hm_lobbyserver/src/step23.c @@ -0,0 +1,32 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step23_0(char *dst, int ndst) {const char src[18] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x2B, 0x20, 0x00, 0x28, 0x05, 0x30, 0x00, 0x08, 0xCB, 0xA6, 0xBE, 0x0D, }; +if(ndst >= 18) { memcpy(dst, src, 18); } else { abort(); } +return 18;} +int step23_1(char *dst, int ndst) {const char src[311] = { 0x00, 0x0D, 0x08, 0x05, 0x10, 0x01, 0x18, 0x50, 0x20, 0x03, 0x28, 0xA8, 0x02, 0x30, 0x00, 0x0A, 0x68, 0x0A, 0x14, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x50, 0x12, 0x02, 0x65, 0x01, 0x18, 0xAA, 0x97, 0x60, 0x22, 0x46, 0x08, 0x00, 0x15, 0x4B, 0x53, 0x00, 0x00, 0x1A, 0x0F, 0x51, 0x75, 0x69, 0x72, 0x6B, 0x79, 0x4F, 0x72, 0x63, 0x23, 0x32, 0x39, 0x36, 0x38, 0x38, 0x20, 0x00, 0x2A, 0x28, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x12, 0x68, 0x0A, 0x14, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x50, 0x12, 0x02, 0x65, 0x01, 0x18, 0xAA, 0x97, 0x60, 0x22, 0x46, 0x08, 0x00, 0x15, 0x4B, 0x53, 0x00, 0x00, 0x1A, 0x0F, 0x51, 0x75, 0x69, 0x72, 0x6B, 0x79, 0x4F, 0x72, 0x63, 0x23, 0x32, 0x39, 0x36, 0x38, 0x38, 0x20, 0x00, 0x2A, 0x28, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x93, 0x71, 0x0E, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x1A, 0x24, 0x08, 0x02, 0x10, 0x00, 0x38, 0x04, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x5D, 0x47, 0x43, 0x54, 0x57, 0x68, 0x01, 0x70, 0x00, 0xC2, 0x06, 0x09, 0x11, 0xF6, 0x42, 0x63, 0xF5, 0xD3, 0x34, 0x56, 0xC7, 0x22, 0x15, 0x08, 0x03, 0x12, 0x0C, 0x08, 0x8A, 0xC4, 0x8D, 0xDD, 0x0A, 0x10, 0xEE, 0xCD, 0xB6, 0xB8, 0x05, 0x1D, 0x8C, 0x27, 0x0B, 0x00, 0x2A, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 311) { memcpy(dst, src, 311); } else { abort(); } +return 311;} +int step23_2(char *dst, int ndst) {const char src[165] = { 0x00, 0x0D, 0x08, 0x05, 0x10, 0x02, 0x18, 0x51, 0x20, 0x03, 0x28, 0x96, 0x01, 0x30, 0x00, 0x0A, 0x66, 0x0A, 0x14, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0xA5, 0x14, 0xB6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x4E, 0x12, 0x02, 0x64, 0x02, 0x18, 0x80, 0x97, 0x80, 0x03, 0x22, 0x43, 0x08, 0x00, 0x15, 0x5A, 0x43, 0x00, 0x00, 0x1A, 0x0C, 0x49, 0x6C, 0x66, 0x69, 0x72, 0x69, 0x6E, 0x23, 0x32, 0x38, 0x31, 0x32, 0x20, 0x00, 0x2A, 0x28, 0x0A, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0xB1, 0x27, 0xB0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0xA5, 0x14, 0xB6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x12, 0x15, 0x08, 0x03, 0x12, 0x0C, 0x08, 0x8A, 0xC4, 0x8D, 0xDD, 0x0A, 0x10, 0xEE, 0xCD, 0xB6, 0xB8, 0x05, 0x1D, 0x8C, 0x27, 0x0B, 0x00, 0x1A, 0x15, 0x0A, 0x05, 0x0D, 0x93, 0x71, 0x0E, 0x1A, 0x12, 0x0C, 0x0D, 0x67, 0x39, 0xAB, 0x04, 0x15, 0x47, 0x43, 0x54, 0x57, 0x18, 0x02, }; +if(ndst >= 165) { memcpy(dst, src, 165); } else { abort(); } +return 165;} diff --git a/hm_lobbyserver/src/step24.c b/hm_lobbyserver/src/step24.c new file mode 100644 index 0000000..cf983c5 --- /dev/null +++ b/hm_lobbyserver/src/step24.c @@ -0,0 +1,32 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step24_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x2D, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step24_1(char *dst, int ndst) {const char src[332] = { 0x00, 0x0D, 0x08, 0x05, 0x10, 0x01, 0x18, 0x52, 0x20, 0x04, 0x28, 0xBD, 0x02, 0x30, 0x00, 0x1A, 0xBA, 0x02, 0xAA, 0x06, 0xB6, 0x02, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0xA5, 0x14, 0xB6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x0A, 0x22, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x07, 0x20, 0x00, 0x12, 0x14, 0x52, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0xB1, 0x27, 0xB0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0A, 0x10, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x01, 0x20, 0x00, 0x12, 0x02, 0x10, 0x01, 0x12, 0x16, 0x0A, 0x14, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x03, 0x20, 0x00, 0x12, 0x06, 0x42, 0x04, 0x57, 0x54, 0x43, 0x47, 0x12, 0x1A, 0x0A, 0x18, 0x0A, 0x0C, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x12, 0x20, 0x00, 0x12, 0x08, 0x32, 0x06, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x12, 0x19, 0x0A, 0x17, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x04, 0x20, 0x00, 0x12, 0x09, 0x18, 0xC2, 0x8D, 0xD9, 0xAD, 0xED, 0xC2, 0xCC, 0x02, 0x12, 0x1E, 0x0A, 0x1C, 0x0A, 0x0A, 0x08, 0xCE, 0x84, 0x01, 0x10, 0x02, 0x18, 0x05, 0x20, 0x00, 0x12, 0x0E, 0x2A, 0x0C, 0x49, 0x6C, 0x66, 0x69, 0x72, 0x69, 0x6E, 0x23, 0x32, 0x38, 0x31, 0x32, 0x12, 0x19, 0x0A, 0x17, 0x0A, 0x0C, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x11, 0x20, 0x00, 0x12, 0x07, 0x32, 0x05, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x12, 0x28, 0x0A, 0x26, 0x0A, 0x0C, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x14, 0x20, 0x00, 0x12, 0x16, 0x2A, 0x14, 0x65, 0x75, 0x2E, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6C, 0x2E, 0x62, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x2E, 0x6E, 0x65, 0x74, 0x12, 0x14, 0x0A, 0x12, 0x0A, 0x0C, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x01, 0x20, 0x00, 0x12, 0x02, 0x10, 0x00, 0x12, 0x1C, 0x0A, 0x1A, 0x0A, 0x0C, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x13, 0x20, 0x00, 0x12, 0x0A, 0x2A, 0x08, 0x38, 0x33, 0x38, 0x38, 0x36, 0x30, 0x38, 0x30, }; +if(ndst >= 332) { memcpy(dst, src, 332); } else { abort(); } +return 332;} +int step24_2(char *dst, int ndst) {const char src[37] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x2C, 0x20, 0x00, 0x28, 0x18, 0x30, 0x00, 0x0A, 0x09, 0x0A, 0x02, 0x69, 0x64, 0x12, 0x03, 0x18, 0xFE, 0x01, 0x0A, 0x0B, 0x0A, 0x05, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x12, 0x02, 0x32, 0x00, }; +if(ndst >= 37) { memcpy(dst, src, 37); } else { abort(); } +return 37;} diff --git a/hm_lobbyserver/src/step25.c b/hm_lobbyserver/src/step25.c new file mode 100644 index 0000000..099919b --- /dev/null +++ b/hm_lobbyserver/src/step25.c @@ -0,0 +1,32 @@ +/* + hm_lobbyserver - HearthStone HearthMod lobbyserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include + +int step25_0(char *dst, int ndst) {const char src[13] = { 0x00, 0x0B, 0x08, 0xFE, 0x01, 0x18, 0x2E, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, }; +if(ndst >= 13) { memcpy(dst, src, 13); } else { abort(); } +return 13;} +int step25_1(char *dst, int ndst) {const char src[101] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x53, 0x20, 0x02, 0x28, 0x57, 0x30, 0x00, 0x12, 0x55, 0xAA, 0x06, 0x52, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0x67, 0x39, 0xAB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x3C, 0x0A, 0x3A, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x15, 0x12, 0x2C, 0x32, 0x2A, 0x0A, 0x0E, 0x31, 0x39, 0x32, 0x2E, 0x31, 0x36, 0x38, 0x2E, 0x31, 0x31, 0x2E, 0x31, 0x32, 0x34, 0x10, 0x8C, 0x1D, 0x18, 0xAA, 0x80, 0xC4, 0x06, 0x22, 0x06, 0x6F, 0x44, 0x69, 0x70, 0x49, 0x66, 0x28, 0x01, 0x30, 0x00, 0x38, 0x0A, 0x40, 0x08, 0x48, 0x02, }; +if(ndst >= 101) { memcpy(dst, src, 101); } else { abort(); } +return 101;} +int step25_2(char *dst, int ndst) {const char src[64] = { 0x00, 0x0C, 0x08, 0x05, 0x10, 0x06, 0x18, 0x54, 0x20, 0x04, 0x28, 0x32, 0x30, 0x00, 0x12, 0x30, 0xAA, 0x06, 0x2D, 0x0A, 0x12, 0x09, 0x47, 0x43, 0x54, 0x57, 0x02, 0x00, 0x00, 0x02, 0x11, 0xA5, 0x14, 0xB6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x17, 0x0A, 0x15, 0x0A, 0x0A, 0x08, 0xC7, 0x86, 0xD1, 0xBA, 0x05, 0x10, 0x02, 0x18, 0x11, 0x12, 0x07, 0x32, 0x05, 0x01, 0x0D, 0x00, 0x00, 0x00, }; +if(ndst >= 64) { memcpy(dst, src, 64); } else { abort(); } +return 64;} diff --git a/hm_nginx/CHANGES b/hm_nginx/CHANGES new file mode 100644 index 0000000..d0b475c --- /dev/null +++ b/hm_nginx/CHANGES @@ -0,0 +1,7083 @@ + +Changes with nginx 1.8.1 26 Jan 2016 + + *) Security: invalid pointer dereference might occur during DNS server + response processing if the "resolver" directive was used, allowing an + attacker who is able to forge UDP packets from the DNS server to + cause segmentation fault in a worker process (CVE-2016-0742). + + *) Security: use-after-free condition might occur during CNAME response + processing if the "resolver" directive was used, allowing an attacker + who is able to trigger name resolution to cause segmentation fault in + a worker process, or might have potential other impact + (CVE-2016-0746). + + *) Security: CNAME resolution was insufficiently limited if the + "resolver" directive was used, allowing an attacker who is able to + trigger arbitrary name resolution to cause excessive resource + consumption in worker processes (CVE-2016-0747). + + *) Bugfix: the "proxy_protocol" parameter of the "listen" directive did + not work if not specified in the first "listen" directive for a + listen socket. + + *) Bugfix: nginx might fail to start on some old Linux variants; the bug + had appeared in 1.7.11. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "try_files" and "alias" directives were used inside a location given + by a regular expression; the bug had appeared in 1.7.1. + + *) Bugfix: the "try_files" directive inside a nested location given by a + regular expression worked incorrectly if the "alias" directive was + used in the outer location. + + *) Bugfix: "header already sent" alerts might appear in logs when using + cache; the bug had appeared in 1.7.5. + + *) Bugfix: a segmentation fault might occur in a worker process if + different ssl_session_cache settings were used in different virtual + servers. + + *) Bugfix: the "expires" directive might not work when using variables. + + *) Bugfix: if nginx was built with the ngx_http_spdy_module it was + possible to use the SPDY protocol even if the "spdy" parameter of the + "listen" directive was not specified. + + +Changes with nginx 1.8.0 21 Apr 2015 + + *) 1.8.x stable branch. + + +Changes with nginx 1.7.12 07 Apr 2015 + + *) Feature: now the "tcp_nodelay" directive works with backend SSL + connections. + + *) Feature: now thread pools can be used to read cache file headers. + + *) Bugfix: in the "proxy_request_buffering" directive. + + *) Bugfix: a segmentation fault might occur in a worker process when + using thread pools on Linux. + + *) Bugfix: in error handling when using the "ssl_stapling" directive. + Thanks to Filipe da Silva. + + *) Bugfix: in the ngx_http_spdy_module. + + +Changes with nginx 1.7.11 24 Mar 2015 + + *) Change: the "sendfile" parameter of the "aio" directive is + deprecated; now nginx automatically uses AIO to pre-load data for + sendfile if both "aio" and "sendfile" directives are used. + + *) Feature: experimental thread pools support. + + *) Feature: the "proxy_request_buffering", "fastcgi_request_buffering", + "scgi_request_buffering", and "uwsgi_request_buffering" directives. + + *) Feature: request body filters experimental API. + + *) Feature: client SSL certificates support in mail proxy. + Thanks to Sven Peter, Franck Levionnois, and Filipe Da Silva. + + *) Feature: startup speedup when using the "hash ... consistent" + directive in the upstream block. + Thanks to Wai Keen Woon. + + *) Feature: debug logging into a cyclic memory buffer. + + *) Bugfix: in hash table handling. + Thanks to Chris West. + + *) Bugfix: in the "proxy_cache_revalidate" directive. + + *) Bugfix: SSL connections might hang if deferred accept or the + "proxy_protocol" parameter of the "listen" directive were used. + Thanks to James Hamlin. + + *) Bugfix: the $upstream_response_time variable might contain a wrong + value if the "image_filter" directive was used. + + *) Bugfix: in integer overflow handling. + Thanks to Régis Leroy. + + *) Bugfix: it was not possible to enable SSLv3 with LibreSSL. + + *) Bugfix: the "ignoring stale global SSL error ... called a function + you should not call" alerts appeared in logs when using LibreSSL. + + *) Bugfix: certificates specified by the "ssl_client_certificate" and + "ssl_trusted_certificate" directives were inadvertently used to + automatically construct certificate chains. + + +Changes with nginx 1.7.10 10 Feb 2015 + + *) Feature: the "use_temp_path" parameter of the "proxy_cache_path", + "fastcgi_cache_path", "scgi_cache_path", and "uwsgi_cache_path" + directives. + + *) Feature: the $upstream_header_time variable. + + *) Workaround: now on disk overflow nginx tries to write error logs once + a second only. + + *) Bugfix: the "try_files" directive did not ignore normal files while + testing directories. + Thanks to Damien Tournoud. + + *) Bugfix: alerts "sendfile() failed" if the "sendfile" directive was + used on OS X; the bug had appeared in 1.7.8. + + *) Bugfix: alerts "sem_post() failed" might appear in logs. + + *) Bugfix: nginx could not be built with musl libc. + Thanks to James Taylor. + + *) Bugfix: nginx could not be built on Tru64 UNIX. + Thanks to Goetz T. Fischer. + + +Changes with nginx 1.7.9 23 Dec 2014 + + *) Feature: variables support in the "proxy_cache", "fastcgi_cache", + "scgi_cache", and "uwsgi_cache" directives. + + *) Feature: variables support in the "expires" directive. + + *) Feature: loading of secret keys from hardware tokens with OpenSSL + engines. + Thanks to Dmitrii Pichulin. + + *) Feature: the "autoindex_format" directive. + + *) Bugfix: cache revalidation is now only used for responses with 200 + and 206 status codes. + Thanks to Piotr Sikora. + + *) Bugfix: the "TE" client request header line was passed to backends + while proxying. + + *) Bugfix: the "proxy_pass", "fastcgi_pass", "scgi_pass", and + "uwsgi_pass" directives might not work correctly inside the "if" and + "limit_except" blocks. + + *) Bugfix: the "proxy_store" directive with the "on" parameter was + ignored if the "proxy_store" directive with an explicitly specified + file path was used on a previous level. + + *) Bugfix: nginx could not be built with BoringSSL. + Thanks to Lukas Tribus. + + +Changes with nginx 1.7.8 02 Dec 2014 + + *) Change: now the "If-Modified-Since", "If-Range", etc. client request + header lines are passed to a backend while caching if nginx knows in + advance that the response will not be cached (e.g., when using + proxy_cache_min_uses). + + *) Change: now after proxy_cache_lock_timeout nginx sends a request to a + backend with caching disabled; the new directives + "proxy_cache_lock_age", "fastcgi_cache_lock_age", + "scgi_cache_lock_age", and "uwsgi_cache_lock_age" specify a time + after which the lock will be released and another attempt to cache a + response will be made. + + *) Change: the "log_format" directive can now be used only at http + level. + + *) Feature: the "proxy_ssl_certificate", "proxy_ssl_certificate_key", + "proxy_ssl_password_file", "uwsgi_ssl_certificate", + "uwsgi_ssl_certificate_key", and "uwsgi_ssl_password_file" + directives. + Thanks to Piotr Sikora. + + *) Feature: it is now possible to switch to a named location using + "X-Accel-Redirect". + Thanks to Toshikuni Fukaya. + + *) Feature: now the "tcp_nodelay" directive works with SPDY connections. + + *) Feature: new directives in vim syntax highliting scripts. + Thanks to Peter Wu. + + *) Bugfix: nginx ignored the "s-maxage" value in the "Cache-Control" + backend response header line. + Thanks to Piotr Sikora. + + *) Bugfix: in the ngx_http_spdy_module. + Thanks to Piotr Sikora. + + *) Bugfix: in the "ssl_password_file" directive when using OpenSSL + 0.9.8zc, 1.0.0o, 1.0.1j. + + *) Bugfix: alerts "header already sent" appeared in logs if the + "post_action" directive was used; the bug had appeared in 1.5.4. + + *) Bugfix: alerts "the http output chain is empty" might appear in logs + if the "postpone_output 0" directive was used with SSI includes. + + *) Bugfix: in the "proxy_cache_lock" directive with SSI subrequests. + Thanks to Yichun Zhang. + + +Changes with nginx 1.7.7 28 Oct 2014 + + *) Change: now nginx takes into account the "Vary" header line in a + backend response while caching. + + *) Feature: the "proxy_force_ranges", "fastcgi_force_ranges", + "scgi_force_ranges", and "uwsgi_force_ranges" directives. + + *) Feature: the "proxy_limit_rate", "fastcgi_limit_rate", + "scgi_limit_rate", and "uwsgi_limit_rate" directives. + + *) Feature: the "Vary" parameter of the "proxy_ignore_headers", + "fastcgi_ignore_headers", "scgi_ignore_headers", and + "uwsgi_ignore_headers" directives. + + *) Bugfix: the last part of a response received from a backend with + unbufferred proxy might not be sent to a client if "gzip" or "gunzip" + directives were used. + + *) Bugfix: in the "proxy_cache_revalidate" directive. + Thanks to Piotr Sikora. + + *) Bugfix: in error handling. + Thanks to Yichun Zhang and Daniil Bondarev. + + *) Bugfix: in the "proxy_next_upstream_tries" and + "proxy_next_upstream_timeout" directives. + Thanks to Feng Gu. + + *) Bugfix: nginx/Windows could not be built with MinGW-w64 gcc. + Thanks to Kouhei Sutou. + + +Changes with nginx 1.7.6 30 Sep 2014 + + *) Change: the deprecated "limit_zone" directive is not supported + anymore. + + *) Feature: the "limit_conn_zone" and "limit_req_zone" directives now + can be used with combinations of multiple variables. + + *) Bugfix: request body might be transmitted incorrectly when retrying a + FastCGI request to the next upstream server. + + *) Bugfix: in logging to syslog. + + +Changes with nginx 1.7.5 16 Sep 2014 + + *) Security: it was possible to reuse SSL sessions in unrelated contexts + if a shared SSL session cache or the same TLS session ticket key was + used for multiple "server" blocks (CVE-2014-3616). + Thanks to Antoine Delignat-Lavaud. + + *) Change: now the "stub_status" directive does not require a parameter. + + *) Feature: the "always" parameter of the "add_header" directive. + + *) Feature: the "proxy_next_upstream_tries", + "proxy_next_upstream_timeout", "fastcgi_next_upstream_tries", + "fastcgi_next_upstream_timeout", "memcached_next_upstream_tries", + "memcached_next_upstream_timeout", "scgi_next_upstream_tries", + "scgi_next_upstream_timeout", "uwsgi_next_upstream_tries", and + "uwsgi_next_upstream_timeout" directives. + + *) Bugfix: in the "if" parameter of the "access_log" directive. + + *) Bugfix: in the ngx_http_perl_module. + Thanks to Piotr Sikora. + + *) Bugfix: the "listen" directive of the mail proxy module did not allow + to specify more than two parameters. + + *) Bugfix: the "sub_filter" directive did not work with a string to + replace consisting of a single character. + + *) Bugfix: requests might hang if resolver was used and a timeout + occurred during a DNS request. + + *) Bugfix: in the ngx_http_spdy_module when using with AIO. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "set" directive was used to change the "$http_...", "$sent_http_...", + or "$upstream_http_..." variables. + + *) Bugfix: in memory allocation error handling. + Thanks to Markus Linnala and Feng Gu. + + +Changes with nginx 1.7.4 05 Aug 2014 + + *) Security: pipelined commands were not discarded after STARTTLS + command in SMTP proxy (CVE-2014-3556); the bug had appeared in 1.5.6. + Thanks to Chris Boulton. + + *) Change: URI escaping now uses uppercase hexadecimal digits. + Thanks to Piotr Sikora. + + *) Feature: now nginx can be build with BoringSSL and LibreSSL. + Thanks to Piotr Sikora. + + *) Bugfix: requests might hang if resolver was used and a DNS server + returned a malformed response; the bug had appeared in 1.5.8. + + *) Bugfix: in the ngx_http_spdy_module. + Thanks to Piotr Sikora. + + *) Bugfix: the $uri variable might contain garbage when returning errors + with code 400. + Thanks to Sergey Bobrov. + + *) Bugfix: in error handling in the "proxy_store" directive and the + ngx_http_dav_module. + Thanks to Feng Gu. + + *) Bugfix: a segmentation fault might occur if logging of errors to + syslog was used; the bug had appeared in 1.7.1. + + *) Bugfix: the $geoip_latitude, $geoip_longitude, $geoip_dma_code, and + $geoip_area_code variables might not work. + Thanks to Yichun Zhang. + + *) Bugfix: in memory allocation error handling. + Thanks to Tatsuhiko Kubo and Piotr Sikora. + + +Changes with nginx 1.7.3 08 Jul 2014 + + *) Feature: weak entity tags are now preserved on response + modifications, and strong ones are changed to weak. + + *) Feature: cache revalidation now uses If-None-Match header if + possible. + + *) Feature: the "ssl_password_file" directive. + + *) Bugfix: the If-None-Match request header line was ignored if there + was no Last-Modified header in a response returned from cache. + + *) Bugfix: "peer closed connection in SSL handshake" messages were + logged at "info" level instead of "error" while connecting to + backends. + + *) Bugfix: in the ngx_http_dav_module module in nginx/Windows. + + *) Bugfix: SPDY connections might be closed prematurely if caching was + used. + + +Changes with nginx 1.7.2 17 Jun 2014 + + *) Feature: the "hash" directive inside the "upstream" block. + + *) Feature: defragmentation of free shared memory blocks. + Thanks to Wandenberg Peixoto and Yichun Zhang. + + *) Bugfix: a segmentation fault might occur in a worker process if the + default value of the "access_log" directive was used; the bug had + appeared in 1.7.0. + Thanks to Piotr Sikora. + + *) Bugfix: trailing slash was mistakenly removed from the last parameter + of the "try_files" directive. + + *) Bugfix: nginx could not be built on OS X in some cases. + + *) Bugfix: in the ngx_http_spdy_module. + + +Changes with nginx 1.7.1 27 May 2014 + + *) Feature: the "$upstream_cookie_..." variables. + + *) Feature: the $ssl_client_fingerprint variable. + + *) Feature: the "error_log" and "access_log" directives now support + logging to syslog. + + *) Feature: the mail proxy now logs client port on connect. + + *) Bugfix: memory leak if the "ssl_stapling" directive was used. + Thanks to Filipe da Silva. + + *) Bugfix: the "alias" directive used inside a location given by a + regular expression worked incorrectly if the "if" or "limit_except" + directives were used. + + *) Bugfix: the "charset" directive did not set a charset to encoded + backend responses. + + *) Bugfix: a "proxy_pass" directive without URI part might use original + request after the $args variable was set. + Thanks to Yichun Zhang. + + *) Bugfix: in the "none" parameter in the "smtp_auth" directive; the bug + had appeared in 1.5.6. + Thanks to Svyatoslav Nikolsky. + + *) Bugfix: if sub_filter and SSI were used together, then responses + might be transferred incorrectly. + + *) Bugfix: nginx could not be built with the --with-file-aio option on + Linux/aarch64. + + +Changes with nginx 1.7.0 24 Apr 2014 + + *) Feature: backend SSL certificate verification. + + *) Feature: support for SNI while working with SSL backends. + + *) Feature: the $ssl_server_name variable. + + *) Feature: the "if" parameter of the "access_log" directive. + + +Changes with nginx 1.5.13 08 Apr 2014 + + *) Change: improved hash table handling; the default values of the + "variables_hash_max_size" and "types_hash_bucket_size" were changed + to 1024 and 64 respectively. + + *) Feature: the ngx_http_mp4_module now supports the "end" argument. + + *) Feature: byte ranges support in the ngx_http_mp4_module and while + saving responses to cache. + + *) Bugfix: alerts "ngx_slab_alloc() failed: no memory" no longer logged + when using shared memory in the "ssl_session_cache" directive and in + the ngx_http_limit_req_module. + + *) Bugfix: the "underscores_in_headers" directive did not allow + underscore as a first character of a header. + Thanks to Piotr Sikora. + + *) Bugfix: cache manager might hog CPU on exit in nginx/Windows. + + *) Bugfix: nginx/Windows terminated abnormally if the + "ssl_session_cache" directive was used with the "shared" parameter. + + *) Bugfix: in the ngx_http_spdy_module. + + +Changes with nginx 1.5.12 18 Mar 2014 + + *) Security: a heap memory buffer overflow might occur in a worker + process while handling a specially crafted request by + ngx_http_spdy_module, potentially resulting in arbitrary code + execution (CVE-2014-0133). + Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr. + Manuel Sadosky, Buenos Aires, Argentina. + + *) Feature: the "proxy_protocol" parameters of the "listen" and + "real_ip_header" directives, the $proxy_protocol_addr variable. + + *) Bugfix: in the "fastcgi_next_upstream" directive. + Thanks to Lucas Molas. + + +Changes with nginx 1.5.11 04 Mar 2014 + + *) Security: memory corruption might occur in a worker process on 32-bit + platforms while handling a specially crafted request by + ngx_http_spdy_module, potentially resulting in arbitrary code + execution (CVE-2014-0088); the bug had appeared in 1.5.10. + Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr. + Manuel Sadosky, Buenos Aires, Argentina. + + *) Feature: the $ssl_session_reused variable. + + *) Bugfix: the "client_max_body_size" directive might not work when + reading a request body using chunked transfer encoding; the bug had + appeared in 1.3.9. + Thanks to Lucas Molas. + + *) Bugfix: a segmentation fault might occur in a worker process when + proxying WebSocket connections. + + *) Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_spdy_module was used on 32-bit platforms; the bug had + appeared in 1.5.10. + + *) Bugfix: the $upstream_status variable might contain wrong data if the + "proxy_cache_use_stale" or "proxy_cache_revalidate" directives were + used. + Thanks to Piotr Sikora. + + *) Bugfix: a segmentation fault might occur in a worker process if + errors with code 400 were redirected to a named location using the + "error_page" directive. + + *) Bugfix: nginx/Windows could not be built with Visual Studio 2013. + + +Changes with nginx 1.5.10 04 Feb 2014 + + *) Feature: the ngx_http_spdy_module now uses SPDY 3.1 protocol. + Thanks to Automattic and MaxCDN for sponsoring this work. + + *) Feature: the ngx_http_mp4_module now skips tracks too short for a + seek requested. + + *) Bugfix: a segmentation fault might occur in a worker process if the + $ssl_session_id variable was used in logs; the bug had appeared in + 1.5.9. + + *) Bugfix: the $date_local and $date_gmt variables used wrong format + outside of the ngx_http_ssi_filter_module. + + *) Bugfix: client connections might be immediately closed if deferred + accept was used; the bug had appeared in 1.3.15. + + *) Bugfix: alerts "getsockopt(TCP_FASTOPEN) ... failed" appeared in logs + during binary upgrade on Linux; the bug had appeared in 1.5.8. + Thanks to Piotr Sikora. + + +Changes with nginx 1.5.9 22 Jan 2014 + + *) Change: now nginx expects escaped URIs in "X-Accel-Redirect" headers. + + *) Feature: the "ssl_buffer_size" directive. + + *) Feature: the "limit_rate" directive can now be used to rate limit + responses sent in SPDY connections. + + *) Feature: the "spdy_chunk_size" directive. + + *) Feature: the "ssl_session_tickets" directive. + Thanks to Dirkjan Bussink. + + *) Bugfix: the $ssl_session_id variable contained full session + serialized instead of just a session id. + Thanks to Ivan Ristić. + + *) Bugfix: nginx incorrectly handled escaped "?" character in the + "include" SSI command. + + *) Bugfix: the ngx_http_dav_module did not unescape destination URI of + the COPY and MOVE methods. + + *) Bugfix: resolver did not understand domain names with a trailing dot. + Thanks to Yichun Zhang. + + *) Bugfix: alerts "zero size buf in output" might appear in logs while + proxying; the bug had appeared in 1.3.9. + + *) Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_spdy_module was used. + + *) Bugfix: proxied WebSocket connections might hang right after + handshake if the select, poll, or /dev/poll methods were used. + + *) Bugfix: the "xclient" directive of the mail proxy module incorrectly + handled IPv6 client addresses. + + +Changes with nginx 1.5.8 17 Dec 2013 + + *) Feature: IPv6 support in resolver. + + *) Feature: the "listen" directive supports the "fastopen" parameter. + Thanks to Mathew Rodley. + + *) Feature: SSL support in the ngx_http_uwsgi_module. + Thanks to Roberto De Ioris. + + *) Feature: vim syntax highlighting scripts were added to contrib. + Thanks to Evan Miller. + + *) Bugfix: a timeout might occur while reading client request body in an + SSL connection using chunked transfer encoding. + + *) Bugfix: the "master_process" directive did not work correctly in + nginx/Windows. + + *) Bugfix: the "setfib" parameter of the "listen" directive might not + work. + + *) Bugfix: in the ngx_http_spdy_module. + + +Changes with nginx 1.5.7 19 Nov 2013 + + *) Security: a character following an unescaped space in a request line + was handled incorrectly (CVE-2013-4547); the bug had appeared in + 0.8.41. + Thanks to Ivan Fratric of the Google Security Team. + + *) Change: a logging level of auth_basic errors about no user/password + provided has been lowered from "error" to "info". + + *) Feature: the "proxy_cache_revalidate", "fastcgi_cache_revalidate", + "scgi_cache_revalidate", and "uwsgi_cache_revalidate" directives. + + *) Feature: the "ssl_session_ticket_key" directive. + Thanks to Piotr Sikora. + + *) Bugfix: the directive "add_header Cache-Control ''" added a + "Cache-Control" response header line with an empty value. + + *) Bugfix: the "satisfy any" directive might return 403 error instead of + 401 if auth_request and auth_basic directives were used. + Thanks to Jan Marc Hoffmann. + + *) Bugfix: the "accept_filter" and "deferred" parameters of the "listen" + directive were ignored for listen sockets created during binary + upgrade. + Thanks to Piotr Sikora. + + *) Bugfix: some data received from a backend with unbufferred proxy + might not be sent to a client immediately if "gzip" or "gunzip" + directives were used. + Thanks to Yichun Zhang. + + *) Bugfix: in error handling in ngx_http_gunzip_filter_module. + + *) Bugfix: responses might hang if the ngx_http_spdy_module was used + with the "auth_request" directive. + + *) Bugfix: memory leak in nginx/Windows. + + +Changes with nginx 1.5.6 01 Oct 2013 + + *) Feature: the "fastcgi_buffering" directive. + + *) Feature: the "proxy_ssl_protocols" and "proxy_ssl_ciphers" + directives. + Thanks to Piotr Sikora. + + *) Feature: optimization of SSL handshakes when using long certificate + chains. + + *) Feature: the mail proxy supports SMTP pipelining. + + *) Bugfix: in the ngx_http_auth_basic_module when using "$apr1$" + password encryption method. + Thanks to Markus Linnala. + + *) Bugfix: in MacOSX, Cygwin, and nginx/Windows incorrect location might + be used to process a request if locations were given using characters + in different cases. + + *) Bugfix: automatic redirect with appended trailing slash for proxied + locations might not work. + + *) Bugfix: in the mail proxy server. + + *) Bugfix: in the ngx_http_spdy_module. + + +Changes with nginx 1.5.5 17 Sep 2013 + + *) Change: now nginx assumes HTTP/1.0 by default if it is not able to + detect protocol reliably. + + *) Feature: the "disable_symlinks" directive now uses O_PATH on Linux. + + *) Feature: now nginx uses EPOLLRDHUP events to detect premature + connection close by clients if the "epoll" method is used. + + *) Bugfix: in the "valid_referers" directive if the "server_names" + parameter was used. + + *) Bugfix: the $request_time variable did not work in nginx/Windows. + + *) Bugfix: in the "image_filter" directive. + Thanks to Lanshun Zhou. + + *) Bugfix: OpenSSL 1.0.1f compatibility. + Thanks to Piotr Sikora. + + +Changes with nginx 1.5.4 27 Aug 2013 + + *) Change: the "js" extension MIME type has been changed to + "application/javascript"; default value of the "charset_types" + directive was changed accordingly. + + *) Change: now the "image_filter" directive with the "size" parameter + returns responses with the "application/json" MIME type. + + *) Feature: the ngx_http_auth_request_module. + + *) Bugfix: a segmentation fault might occur on start or during + reconfiguration if the "try_files" directive was used with an empty + parameter. + + *) Bugfix: memory leak if relative paths were specified using variables + in the "root" or "auth_basic_user_file" directives. + + *) Bugfix: the "valid_referers" directive incorrectly executed regular + expressions if a "Referer" header started with "https://". + Thanks to Liangbin Li. + + *) Bugfix: responses might hang if subrequests were used and an SSL + handshake error happened during subrequest processing. + Thanks to Aviram Cohen. + + *) Bugfix: in the ngx_http_autoindex_module. + + *) Bugfix: in the ngx_http_spdy_module. + + +Changes with nginx 1.5.3 30 Jul 2013 + + *) Change in internal API: now u->length defaults to -1 if working with + backends in unbuffered mode. + + *) Change: now after receiving an incomplete response from a backend + server nginx tries to send an available part of the response to a + client, and then closes client connection. + + *) Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_spdy_module was used with the "client_body_in_file_only" + directive. + + *) Bugfix: the "so_keepalive" parameter of the "listen" directive might + be handled incorrectly on DragonFlyBSD. + Thanks to Sepherosa Ziehau. + + *) Bugfix: in the ngx_http_xslt_filter_module. + + *) Bugfix: in the ngx_http_sub_filter_module. + + +Changes with nginx 1.5.2 02 Jul 2013 + + *) Feature: now several "error_log" directives can be used. + + *) Bugfix: the $r->header_in() embedded perl method did not return value + of the "Cookie" and "X-Forwarded-For" request header lines; the bug + had appeared in 1.3.14. + + *) Bugfix: in the ngx_http_spdy_module. + Thanks to Jim Radford. + + *) Bugfix: nginx could not be built on Linux with x32 ABI. + Thanks to Serguei Ivantsov. + + +Changes with nginx 1.5.1 04 Jun 2013 + + *) Feature: the "ssi_last_modified", "sub_filter_last_modified", and + "xslt_last_modified" directives. + Thanks to Alexey Kolpakov. + + *) Feature: the "http_403" parameter of the "proxy_next_upstream", + "fastcgi_next_upstream", "scgi_next_upstream", and + "uwsgi_next_upstream" directives. + + *) Feature: the "allow" and "deny" directives now support unix domain + sockets. + + *) Bugfix: nginx could not be built with the ngx_mail_ssl_module, but + without ngx_http_ssl_module; the bug had appeared in 1.3.14. + + *) Bugfix: in the "proxy_set_body" directive. + Thanks to Lanshun Zhou. + + *) Bugfix: in the "lingering_time" directive. + Thanks to Lanshun Zhou. + + *) Bugfix: the "fail_timeout" parameter of the "server" directive in the + "upstream" context might not work if "max_fails" parameter was used; + the bug had appeared in 1.3.0. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "ssl_stapling" directive was used. + Thanks to Piotr Sikora. + + *) Bugfix: in the mail proxy server. + Thanks to Filipe Da Silva. + + *) Bugfix: nginx/Windows might stop accepting connections if several + worker processes were used. + + +Changes with nginx 1.5.0 07 May 2013 + + *) Security: a stack-based buffer overflow might occur in a worker + process while handling a specially crafted request, potentially + resulting in arbitrary code execution (CVE-2013-2028); the bug had + appeared in 1.3.9. + Thanks to Greg MacManus, iSIGHT Partners Labs. + + +Changes with nginx 1.4.0 24 Apr 2013 + + *) Bugfix: nginx could not be built with the ngx_http_perl_module if the + --with-openssl option was used; the bug had appeared in 1.3.16. + + *) Bugfix: in a request body handling in the ngx_http_perl_module; the + bug had appeared in 1.3.9. + + +Changes with nginx 1.3.16 16 Apr 2013 + + *) Bugfix: a segmentation fault might occur in a worker process if + subrequests were used; the bug had appeared in 1.3.9. + + *) Bugfix: the "tcp_nodelay" directive caused an error if a WebSocket + connection was proxied into a unix domain socket. + + *) Bugfix: the $upstream_response_length variable has an incorrect value + "0" if buffering was not used. + Thanks to Piotr Sikora. + + *) Bugfix: in the eventport and /dev/poll methods. + + +Changes with nginx 1.3.15 26 Mar 2013 + + *) Change: opening and closing a connection without sending any data in + it is no longer logged to access_log with error code 400. + + *) Feature: the ngx_http_spdy_module. + Thanks to Automattic for sponsoring this work. + + *) Feature: the "limit_req_status" and "limit_conn_status" directives. + Thanks to Nick Marden. + + *) Feature: the "image_filter_interlace" directive. + Thanks to Ian Babrou. + + *) Feature: $connections_waiting variable in the + ngx_http_stub_status_module. + + *) Feature: the mail proxy module now supports IPv6 backends. + + *) Bugfix: request body might be transmitted incorrectly when retrying a + request to the next upstream server; the bug had appeared in 1.3.9. + Thanks to Piotr Sikora. + + *) Bugfix: in the "client_body_in_file_only" directive; the bug had + appeared in 1.3.9. + + *) Bugfix: responses might hang if subrequests were used and a DNS error + happened during subrequest processing. + Thanks to Lanshun Zhou. + + *) Bugfix: in backend usage accounting. + + +Changes with nginx 1.3.14 05 Mar 2013 + + *) Feature: $connections_active, $connections_reading, and + $connections_writing variables in the ngx_http_stub_status_module. + + *) Feature: support of WebSocket connections in the + ngx_http_uwsgi_module and ngx_http_scgi_module. + + *) Bugfix: in virtual servers handling with SNI. + + *) Bugfix: new sessions were not always stored if the "ssl_session_cache + shared" directive was used and there was no free space in shared + memory. + Thanks to Piotr Sikora. + + *) Bugfix: multiple X-Forwarded-For headers were handled incorrectly. + Thanks to Neal Poole for sponsoring this work. + + *) Bugfix: in the ngx_http_mp4_module. + Thanks to Gernot Vormayr. + + +Changes with nginx 1.3.13 19 Feb 2013 + + *) Change: a compiler with name "cc" is now used by default. + + *) Feature: support for proxying of WebSocket connections. + Thanks to Apcera and CloudBees for sponsoring this work. + + *) Feature: the "auth_basic_user_file" directive supports "{SHA}" + password encryption method. + Thanks to Louis Opter. + + +Changes with nginx 1.3.12 05 Feb 2013 + + *) Feature: variables support in the "proxy_bind", "fastcgi_bind", + "memcached_bind", "scgi_bind", and "uwsgi_bind" directives. + + *) Feature: the $pipe, $request_length, $time_iso8601, and $time_local + variables can now be used not only in the "log_format" directive. + Thanks to Kiril Kalchev. + + *) Feature: IPv6 support in the ngx_http_geoip_module. + Thanks to Gregor Kališnik. + + *) Bugfix: in the "proxy_method" directive. + + *) Bugfix: a segmentation fault might occur in a worker process if + resolver was used with the poll method. + + *) Bugfix: nginx might hog CPU during SSL handshake with a backend if + the select, poll, or /dev/poll methods were used. + + *) Bugfix: the "[crit] SSL_write() failed (SSL:)" error. + + *) Bugfix: in the "client_body_in_file_only" directive; the bug had + appeared in 1.3.9. + + *) Bugfix: in the "fastcgi_keep_conn" directive. + + +Changes with nginx 1.3.11 10 Jan 2013 + + *) Bugfix: a segmentation fault might occur if logging was used; the bug + had appeared in 1.3.10. + + *) Bugfix: the "proxy_pass" directive did not work with IP addresses + without port specified; the bug had appeared in 1.3.10. + + *) Bugfix: a segmentation fault occurred on start or during + reconfiguration if the "keepalive" directive was specified more than + once in a single upstream block. + + *) Bugfix: parameter "default" of the "geo" directive did not set + default value for IPv6 addresses. + + +Changes with nginx 1.3.10 25 Dec 2012 + + *) Change: domain names specified in configuration file are now resolved + to IPv6 addresses as well as IPv4 ones. + + *) Change: now if the "include" directive with mask is used on Unix + systems, included files are sorted in alphabetical order. + + *) Change: the "add_header" directive adds headers to 201 responses. + + *) Feature: the "geo" directive now supports IPv6 addresses in CIDR + notation. + + *) Feature: the "flush" and "gzip" parameters of the "access_log" + directive. + + *) Feature: variables support in the "auth_basic" directive. + + *) Bugfix: nginx could not be built with the ngx_http_perl_module in + some cases. + + *) Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_xslt_module was used. + + *) Bugfix: nginx could not be built on MacOSX in some cases. + Thanks to Piotr Sikora. + + *) Bugfix: the "limit_rate" directive with high rates might result in + truncated responses on 32-bit platforms. + Thanks to Alexey Antropov. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "if" directive was used. + Thanks to Piotr Sikora. + + *) Bugfix: a "100 Continue" response was issued with "413 Request Entity + Too Large" responses. + + *) Bugfix: the "image_filter", "image_filter_jpeg_quality" and + "image_filter_sharpen" directives might be inherited incorrectly. + Thanks to Ian Babrou. + + *) Bugfix: "crypt_r() failed" errors might appear if the "auth_basic" + directive was used on Linux. + + *) Bugfix: in backup servers handling. + Thanks to Thomas Chen. + + *) Bugfix: proxied HEAD requests might return incorrect response if the + "gzip" directive was used. + + +Changes with nginx 1.3.9 27 Nov 2012 + + *) Feature: support for chunked transfer encoding while reading client + request body. + + *) Feature: the $request_time and $msec variables can now be used not + only in the "log_format" directive. + + *) Bugfix: cache manager and cache loader processes might not be able to + start if more than 512 listen sockets were used. + + *) Bugfix: in the ngx_http_dav_module. + + +Changes with nginx 1.3.8 30 Oct 2012 + + *) Feature: the "optional_no_ca" parameter of the "ssl_verify_client" + directive. + Thanks to Mike Kazantsev and Eric O'Connor. + + *) Feature: the $bytes_sent, $connection, and $connection_requests + variables can now be used not only in the "log_format" directive. + Thanks to Benjamin Grössing. + + *) Feature: the "auto" parameter of the "worker_processes" directive. + + *) Bugfix: "cache file ... has md5 collision" alert. + + *) Bugfix: in the ngx_http_gunzip_filter_module. + + *) Bugfix: in the "ssl_stapling" directive. + + +Changes with nginx 1.3.7 02 Oct 2012 + + *) Feature: OCSP stapling support. + Thanks to Comodo, DigiCert and GlobalSign for sponsoring this work. + + *) Feature: the "ssl_trusted_certificate" directive. + + *) Feature: resolver now randomly rotates addresses returned from cache. + Thanks to Anton Jouline. + + *) Bugfix: OpenSSL 0.9.7 compatibility. + + +Changes with nginx 1.3.6 12 Sep 2012 + + *) Feature: the ngx_http_gunzip_filter_module. + + *) Feature: the "memcached_gzip_flag" directive. + + *) Feature: the "always" parameter of the "gzip_static" directive. + + *) Bugfix: in the "limit_req" directive; the bug had appeared in 1.1.14. + Thanks to Charles Chen. + + *) Bugfix: nginx could not be built by gcc 4.7 with -O2 optimization if + the --with-ipv6 option was used. + + +Changes with nginx 1.3.5 21 Aug 2012 + + *) Change: the ngx_http_mp4_module module no longer skips tracks in + formats other than H.264 and AAC. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "map" directive was used with variables as values. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "geo" directive was used with the "ranges" parameter but without the + "default" parameter; the bug had appeared in 0.8.43. + Thanks to Zhen Chen and Weibin Yao. + + *) Bugfix: in the -p command-line parameter handling. + + *) Bugfix: in the mail proxy server. + + *) Bugfix: of minor potential bugs. + Thanks to Coverity. + + *) Bugfix: nginx/Windows could not be built with Visual Studio 2005 + Express. + Thanks to HAYASHI Kentaro. + + +Changes with nginx 1.3.4 31 Jul 2012 + + *) Change: the "ipv6only" parameter is now turned on by default for + listening IPv6 sockets. + + *) Feature: the Clang compiler support. + + *) Bugfix: extra listening sockets might be created. + Thanks to Roman Odaisky. + + *) Bugfix: nginx/Windows might hog CPU if a worker process failed to + start. + Thanks to Ricardo Villalobos Guevara. + + *) Bugfix: the "proxy_pass_header", "fastcgi_pass_header", + "scgi_pass_header", "uwsgi_pass_header", "proxy_hide_header", + "fastcgi_hide_header", "scgi_hide_header", and "uwsgi_hide_header" + directives might be inherited incorrectly. + + +Changes with nginx 1.3.3 10 Jul 2012 + + *) Feature: entity tags support and the "etag" directive. + + *) Bugfix: trailing dot in a source value was not ignored if the "map" + directive was used with the "hostnames" parameter. + + *) Bugfix: incorrect location might be used to process a request if a + URI was changed via a "rewrite" directive before an internal redirect + to a named location. + + +Changes with nginx 1.3.2 26 Jun 2012 + + *) Change: the "single" parameter of the "keepalive" directive is now + ignored. + + *) Change: SSL compression is now disabled when using all versions of + OpenSSL, including ones prior to 1.0.0. + + *) Feature: it is now possible to use the "ip_hash" directive to balance + IPv6 clients. + + *) Feature: the $status variable can now be used not only in the + "log_format" directive. + + *) Bugfix: a segmentation fault might occur in a worker process on + shutdown if the "resolver" directive was used. + + *) Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_mp4_module was used. + + *) Bugfix: in the ngx_http_mp4_module. + + *) Bugfix: a segmentation fault might occur in a worker process if + conflicting wildcard server names were used. + + *) Bugfix: nginx might be terminated abnormally on a SIGBUS signal on + ARM platform. + + *) Bugfix: an alert "sendmsg() failed (9: Bad file number)" on HP-UX + while reconfiguration. + + +Changes with nginx 1.3.1 05 Jun 2012 + + *) Security: now nginx/Windows ignores trailing dot in URI path + component, and does not allow URIs with ":$" in it. + Thanks to Vladimir Kochetkov, Positive Research Center. + + *) Feature: the "proxy_pass", "fastcgi_pass", "scgi_pass", "uwsgi_pass" + directives, and the "server" directive inside the "upstream" block, + now support IPv6 addresses. + + *) Feature: the "resolver" directive now supports IPv6 addresses and an + optional port specification. + + *) Feature: the "least_conn" directive inside the "upstream" block. + + *) Feature: it is now possible to specify a weight for servers while + using the "ip_hash" directive. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "image_filter" directive was used; the bug had appeared in 1.3.0. + + *) Bugfix: nginx could not be built with ngx_cpp_test_module; the bug + had appeared in 1.1.12. + + *) Bugfix: access to variables from SSI and embedded perl module might + not work after reconfiguration. + Thanks to Yichun Zhang. + + *) Bugfix: in the ngx_http_xslt_filter_module. + Thanks to Kuramoto Eiji. + + *) Bugfix: memory leak if $geoip_org variable was used. + Thanks to Denis F. Latypoff. + + *) Bugfix: in the "proxy_cookie_domain" and "proxy_cookie_path" + directives. + + +Changes with nginx 1.3.0 15 May 2012 + + *) Feature: the "debug_connection" directive now supports IPv6 addresses + and the "unix:" parameter. + + *) Feature: the "set_real_ip_from" directive and the "proxy" parameter + of the "geo" directive now support IPv6 addresses. + + *) Feature: the "real_ip_recursive", "geoip_proxy", and + "geoip_proxy_recursive" directives. + + *) Feature: the "proxy_recursive" parameter of the "geo" directive. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "resolver" directive was used. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "fastcgi_pass", "scgi_pass", or "uwsgi_pass" directives were used and + backend returned incorrect response. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "rewrite" directive was used and new request arguments in a + replacement used variables. + + *) Bugfix: nginx might hog CPU if the open file resource limit was + reached. + + *) Bugfix: nginx might loop infinitely over backends if the + "proxy_next_upstream" directive with the "http_404" parameter was + used and there were backup servers specified in an upstream block. + + *) Bugfix: adding the "down" parameter of the "server" directive might + cause unneeded client redistribution among backend servers if the + "ip_hash" directive was used. + + *) Bugfix: socket leak. + Thanks to Yichun Zhang. + + *) Bugfix: in the ngx_http_fastcgi_module. + + +Changes with nginx 1.2.0 23 Apr 2012 + + *) Bugfix: a segmentation fault might occur in a worker process if the + "try_files" directive was used; the bug had appeared in 1.1.19. + + *) Bugfix: response might be truncated if there were more than IOV_MAX + buffers used. + + *) Bugfix: in the "crop" parameter of the "image_filter" directive. + Thanks to Maxim Bublis. + + +Changes with nginx 1.1.19 12 Apr 2012 + + *) Security: specially crafted mp4 file might allow to overwrite memory + locations in a worker process if the ngx_http_mp4_module was used, + potentially resulting in arbitrary code execution (CVE-2012-2089). + Thanks to Matthew Daley. + + *) Bugfix: nginx/Windows might be terminated abnormally. + Thanks to Vincent Lee. + + *) Bugfix: nginx hogged CPU if all servers in an upstream were marked as + "backup". + + *) Bugfix: the "allow" and "deny" directives might be inherited + incorrectly if they were used with IPv6 addresses. + + *) Bugfix: the "modern_browser" and "ancient_browser" directives might + be inherited incorrectly. + + *) Bugfix: timeouts might be handled incorrectly on Solaris/SPARC. + + *) Bugfix: in the ngx_http_mp4_module. + + +Changes with nginx 1.1.18 28 Mar 2012 + + *) Change: keepalive connections are no longer disabled for Safari by + default. + + *) Feature: the $connection_requests variable. + + *) Feature: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd and + $tcpinfo_rcv_space variables. + + *) Feature: the "worker_cpu_affinity" directive now works on FreeBSD. + + *) Feature: the "xslt_param" and "xslt_string_param" directives. + Thanks to Samuel Behan. + + *) Bugfix: in configure tests. + Thanks to Piotr Sikora. + + *) Bugfix: in the ngx_http_xslt_filter_module. + + *) Bugfix: nginx could not be built on Debian GNU/Hurd. + + +Changes with nginx 1.1.17 15 Mar 2012 + + *) Security: content of previously freed memory might be sent to a + client if backend returned specially crafted response. + Thanks to Matthew Daley. + + *) Bugfix: in the embedded perl module if used from SSI. + Thanks to Matthew Daley. + + *) Bugfix: in the ngx_http_uwsgi_module. + + +Changes with nginx 1.1.16 29 Feb 2012 + + *) Change: the simultaneous subrequest limit has been raised to 200. + + *) Feature: the "from" parameter of the "disable_symlinks" directive. + + *) Feature: the "return" and "error_page" directives can now be used to + return 307 redirections. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "resolver" directive was used and there was no "error_log" directive + specified at global level. + Thanks to Roman Arutyunyan. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "proxy_http_version 1.1" or "fastcgi_keep_conn on" directives were + used. + + *) Bugfix: memory leaks. + Thanks to Lanshun Zhou. + + *) Bugfix: in the "disable_symlinks" directive. + + *) Bugfix: on ZFS filesystem disk cache size might be calculated + incorrectly; the bug had appeared in 1.0.1. + + *) Bugfix: nginx could not be built by the icc 12.1 compiler. + + *) Bugfix: nginx could not be built by gcc on Solaris; the bug had + appeared in 1.1.15. + + +Changes with nginx 1.1.15 15 Feb 2012 + + *) Feature: the "disable_symlinks" directive. + + *) Feature: the "proxy_cookie_domain" and "proxy_cookie_path" + directives. + + *) Bugfix: nginx might log incorrect error "upstream prematurely closed + connection" instead of correct "upstream sent too big header" one. + Thanks to Feibo Li. + + *) Bugfix: nginx could not be built with the ngx_http_perl_module if the + --with-openssl option was used. + + *) Bugfix: the number of internal redirects to named locations was not + limited. + + *) Bugfix: calling $r->flush() multiple times might cause errors in the + ngx_http_gzip_filter_module. + + *) Bugfix: temporary files might be not removed if the "proxy_store" + directive was used with SSI includes. + + *) Bugfix: in some cases non-cacheable variables (such as the $args + variable) returned old empty cached value. + + *) Bugfix: a segmentation fault might occur in a worker process if too + many SSI subrequests were issued simultaneously; the bug had appeared + in 0.7.25. + + +Changes with nginx 1.1.14 30 Jan 2012 + + *) Feature: multiple "limit_req" limits may be used simultaneously. + + *) Bugfix: in error handling while connecting to a backend. + Thanks to Piotr Sikora. + + *) Bugfix: in AIO error handling on FreeBSD. + + *) Bugfix: in the OpenSSL library initialization. + + *) Bugfix: the "proxy_redirect" directives might be inherited + incorrectly. + + *) Bugfix: memory leak during reconfiguration if the "pcre_jit" + directive was used. + + +Changes with nginx 1.1.13 16 Jan 2012 + + *) Feature: the "TLSv1.1" and "TLSv1.2" parameters of the + "ssl_protocols" directive. + + *) Bugfix: the "limit_req" directive parameters were not inherited + correctly; the bug had appeared in 1.1.12. + + *) Bugfix: the "proxy_redirect" directive incorrectly processed + "Refresh" header if regular expression were used. + + *) Bugfix: the "proxy_cache_use_stale" directive with "error" parameter + did not return answer from cache if there were no live upstreams. + + *) Bugfix: the "worker_cpu_affinity" directive might not work. + + *) Bugfix: nginx could not be built on Solaris; the bug had appeared in + 1.1.12. + + *) Bugfix: in the ngx_http_mp4_module. + + +Changes with nginx 1.1.12 26 Dec 2011 + + *) Change: a "proxy_pass" directive without URI part now uses changed + URI after redirection with the "error_page" directive. + Thanks to Lanshun Zhou. + + *) Feature: the "proxy/fastcgi/scgi/uwsgi_cache_lock", + "proxy/fastcgi/scgi/uwsgi_cache_lock_timeout" directives. + + *) Feature: the "pcre_jit" directive. + + *) Feature: the "if" SSI command supports captures in regular + expressions. + + *) Bugfix: the "if" SSI command did not work inside the "block" command. + + *) Bugfix: the "limit_conn_log_level" and "limit_req_log_level" + directives might not work. + + *) Bugfix: the "limit_rate" directive did not allow to use full + throughput, even if limit value was very high. + + *) Bugfix: the "sendfile_max_chunk" directive did not work, if the + "limit_rate" directive was used. + + *) Bugfix: a "proxy_pass" directive without URI part always used + original request URI if variables were used. + + *) Bugfix: a "proxy_pass" directive without URI part might use original + request after redirection with the "try_files" directive. + Thanks to Lanshun Zhou. + + *) Bugfix: in the ngx_http_scgi_module. + + *) Bugfix: in the ngx_http_mp4_module. + + *) Bugfix: nginx could not be built on Solaris; the bug had appeared in + 1.1.9. + + +Changes with nginx 1.1.11 12 Dec 2011 + + *) Feature: the "so_keepalive" parameter of the "listen" directive. + Thanks to Vsevolod Stakhov. + + *) Feature: the "if_not_empty" parameter of the + "fastcgi/scgi/uwsgi_param" directives. + + *) Feature: the $https variable. + + *) Feature: the "proxy_redirect" directive supports variables in the + first parameter. + + *) Feature: the "proxy_redirect" directive supports regular expressions. + + *) Bugfix: the $sent_http_cache_control variable might contain a wrong + value if the "expires" directive was used. + Thanks to Yichun Zhang. + + *) Bugfix: the "read_ahead" directive might not work combined with + "try_files" and "open_file_cache". + + *) Bugfix: a segmentation fault might occur in a worker process if small + time was used in the "inactive" parameter of the "proxy_cache_path" + directive. + + *) Bugfix: responses from cache might hang. + + +Changes with nginx 1.1.10 30 Nov 2011 + + *) Bugfix: a segmentation fault occured in a worker process if AIO was + used on Linux; the bug had appeared in 1.1.9. + + +Changes with nginx 1.1.9 28 Nov 2011 + + *) Change: now double quotes are encoded in an "echo" SSI-command + output. + Thanks to Zaur Abasmirzoev. + + *) Feature: the "valid" parameter of the "resolver" directive. By + default TTL returned by a DNS server is used. + Thanks to Kirill A. Korinskiy. + + *) Bugfix: nginx might hang after a worker process abnormal termination. + + *) Bugfix: a segmentation fault might occur in a worker process if SNI + was used; the bug had appeared in 1.1.2. + + *) Bugfix: in the "keepalive_disable" directive; the bug had appeared in + 1.1.8. + Thanks to Alexander Usov. + + *) Bugfix: SIGWINCH signal did not work after first binary upgrade; the + bug had appeared in 1.1.1. + + *) Bugfix: backend responses with length not matching "Content-Length" + header line are no longer cached. + + *) Bugfix: in the "scgi_param" directive, if complex parameters were + used. + + *) Bugfix: in the "epoll" event method. + Thanks to Yichun Zhang. + + *) Bugfix: in the ngx_http_flv_module. + Thanks to Piotr Sikora. + + *) Bugfix: in the ngx_http_mp4_module. + + *) Bugfix: IPv6 addresses are now handled properly in a request line and + in a "Host" request header line. + + *) Bugfix: "add_header" and "expires" directives did not work if a + request was proxied and response status code was 206. + + *) Bugfix: nginx could not be built on FreeBSD 10. + + *) Bugfix: nginx could not be built on AIX. + + +Changes with nginx 1.1.8 14 Nov 2011 + + *) Change: the ngx_http_limit_zone_module was renamed to the + ngx_http_limit_conn_module. + + *) Change: the "limit_zone" directive was superseded by the + "limit_conn_zone" directive with a new syntax. + + *) Feature: support for multiple "limit_conn" limits on the same level. + + *) Feature: the "image_filter_sharpen" directive. + + *) Bugfix: a segmentation fault might occur in a worker process if + resolver got a big DNS response. + Thanks to Ben Hawkes. + + *) Bugfix: in cache key calculation if internal MD5 implementation was + used; the bug had appeared in 1.0.4. + + *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request + header lines might be passed to backend while caching; or not passed + without caching if caching was enabled in another part of the + configuration. + + *) Bugfix: the module ngx_http_mp4_module sent incorrect + "Content-Length" response header line if the "start" argument was + used. + Thanks to Piotr Sikora. + + +Changes with nginx 1.1.7 31 Oct 2011 + + *) Feature: support of several DNS servers in the "resolver" directive. + Thanks to Kirill A. Korinskiy. + + *) Bugfix: a segmentation fault occurred on start or during + reconfiguration if the "ssl" directive was used at http level and + there was no "ssl_certificate" defined. + + *) Bugfix: reduced memory consumption while proxying big files if they + were buffered to disk. + + *) Bugfix: a segmentation fault might occur in a worker process if + "proxy_http_version 1.1" directive was used. + + *) Bugfix: in the "expires @time" directive. + + +Changes with nginx 1.1.6 17 Oct 2011 + + *) Change in internal API: now module context data are cleared while + internal redirect to named location. + Requested by Yichun Zhang. + + *) Change: if a server in an upstream failed, only one request will be + sent to it after fail_timeout; the server will be considered alive if + it will successfully respond to the request. + + *) Change: now the 0x7F-0x1F characters are escaped as \xXX in an + access_log. + + *) Feature: "proxy/fastcgi/scgi/uwsgi_ignore_headers" directives support + the following additional values: X-Accel-Limit-Rate, + X-Accel-Buffering, X-Accel-Charset. + + *) Feature: decrease of memory consumption if SSL is used. + + *) Bugfix: some UTF-8 characters were processed incorrectly. + Thanks to Alexey Kuts. + + *) Bugfix: the ngx_http_rewrite_module directives specified at "server" + level were executed twice if no matching locations were defined. + + *) Bugfix: a socket leak might occurred if "aio sendfile" was used. + + *) Bugfix: connections with fast clients might be closed after + send_timeout if file AIO was used. + + *) Bugfix: in the ngx_http_autoindex_module. + + *) Bugfix: the module ngx_http_mp4_module did not support seeking on + 32-bit platforms. + + +Changes with nginx 1.1.5 05 Oct 2011 + + *) Feature: the "uwsgi_buffering" and "scgi_buffering" directives. + Thanks to Peter Smit. + + *) Bugfix: non-cacheable responses might be cached if + "proxy_cache_bypass" directive was used. + Thanks to John Ferlito. + + *) Bugfix: in HTTP/1.1 support in the ngx_http_proxy_module. + + *) Bugfix: cached responses with an empty body were returned + incorrectly; the bug had appeared in 0.8.31. + + *) Bugfix: 201 responses of the ngx_http_dav_module were incorrect; the + bug had appeared in 0.8.32. + + *) Bugfix: in the "return" directive. + + *) Bugfix: the "ssl_session_cache builtin" directive caused segmentation + fault; the bug had appeared in 1.1.1. + + +Changes with nginx 1.1.4 20 Sep 2011 + + *) Feature: the ngx_http_upstream_keepalive module. + + *) Feature: the "proxy_http_version" directive. + + *) Feature: the "fastcgi_keep_conn" directive. + + *) Feature: the "worker_aio_requests" directive. + + *) Bugfix: if nginx was built --with-file-aio it could not be run on + Linux kernel which did not support AIO. + + *) Bugfix: in Linux AIO error processing. + Thanks to Hagai Avrahami. + + *) Bugfix: reduced memory consumption for long-lived requests. + + *) Bugfix: the module ngx_http_mp4_module did not support 64-bit MP4 + "co64" atom. + + +Changes with nginx 1.1.3 14 Sep 2011 + + *) Feature: the module ngx_http_mp4_module. + + *) Bugfix: in Linux AIO combined with open_file_cache. + + *) Bugfix: open_file_cache did not update file info on retest if file + was not atomically changed. + + *) Bugfix: nginx could not be built on MacOSX 10.7. + + +Changes with nginx 1.1.2 05 Sep 2011 + + *) Change: now if total size of all ranges is greater than source + response size, then nginx disables ranges and returns just the source + response. + + *) Feature: the "max_ranges" directive. + + *) Bugfix: the "ssl_verify_client", "ssl_verify_depth", and + "ssl_prefer_server_ciphers" directives might work incorrectly if SNI + was used. + + *) Bugfix: in the "proxy/fastcgi/scgi/uwsgi_ignore_client_abort" + directives. + + +Changes with nginx 1.1.1 22 Aug 2011 + + *) Change: now cache loader processes either as many files as specified + by "loader_files" parameter or works no longer than time specified by + the "loader_threshold" parameter during each iteration. + + *) Change: now SIGWINCH signal works only in daemon mode. + + *) Feature: now shared zones and caches use POSIX semaphores on Solaris. + Thanks to Den Ivanov. + + *) Feature: accept filters are now supported on NetBSD. + + *) Bugfix: nginx could not be built on Linux 3.0. + + *) Bugfix: nginx did not use gzipping in some cases; the bug had + appeared in 1.1.0. + + *) Bugfix: request body might be processed incorrectly if client used + pipelining. + + *) Bugfix: in the "request_body_in_single_buf" directive. + + *) Bugfix: in "proxy_set_body" and "proxy_pass_request_body" directives + if SSL connection to backend was used. + + *) Bugfix: nginx hogged CPU if all servers in an upstream were marked as + "down". + + *) Bugfix: a segmentation fault might occur during reconfiguration if + ssl_session_cache was defined but not used in previous configuration. + + *) Bugfix: a segmentation fault might occur in a worker process if many + backup servers were used in an upstream. + + *) Bugfix: a segmentation fault might occur in a worker process if + "fastcgi/scgi/uwsgi_param" directives were used with values starting + with "HTTP_"; the bug had appeared in 0.8.40. + + +Changes with nginx 1.1.0 01 Aug 2011 + + *) Feature: cache loader run time decrease. + + *) Feature: "loader_files", "loader_sleep", and "loader_threshold" + options of the "proxy/fastcgi/scgi/uwsgi_cache_path" directives. + + *) Feature: loading time decrease of configuration with large number of + HTTPS sites. + + *) Feature: now nginx supports ECDHE key exchange ciphers. + Thanks to Adrian Kotelba. + + *) Feature: the "lingering_close" directive. + Thanks to Maxim Dounin. + + *) Bugfix: in closing connection for pipelined requests. + Thanks to Maxim Dounin. + + *) Bugfix: nginx did not disable gzipping if client sent "gzip;q=0" in + "Accept-Encoding" request header line. + + *) Bugfix: in timeout in unbuffered proxied mode. + Thanks to Maxim Dounin. + + *) Bugfix: memory leaks when a "proxy_pass" directive contains variables + and proxies to an HTTPS backend. + Thanks to Maxim Dounin. + + *) Bugfix: in parameter validaiton of a "proxy_pass" directive with + variables. + Thanks to Lanshun Zhou. + + *) Bugfix: SSL did not work on QNX. + Thanks to Maxim Dounin. + + *) Bugfix: SSL modules could not be built by gcc 4.6 without + --with-debug option. + + +Changes with nginx 1.0.5 19 Jul 2011 + + *) Change: now default SSL ciphers are "HIGH:!aNULL:!MD5". + Thanks to Rob Stradling. + + *) Feature: the "referer_hash_max_size" and "referer_hash_bucket_size" + directives. + Thanks to Witold Filipczyk. + + *) Feature: $uid_reset variable. + + *) Bugfix: a segmentation fault might occur in a worker process, if a + caching was used. + Thanks to Lanshun Zhou. + + *) Bugfix: worker processes may got caught in an endless loop during + reconfiguration, if a caching was used; the bug had appeared in + 0.8.48. + Thanks to Maxim Dounin. + + *) Bugfix: "stalled cache updating" alert. + Thanks to Maxim Dounin. + + +Changes with nginx 1.0.4 01 Jun 2011 + + *) Change: now regular expressions case sensitivity in the "map" + directive is given by prefixes "~" or "~*". + + *) Feature: now shared zones and caches use POSIX semaphores on Linux. + Thanks to Denis F. Latypoff. + + *) Bugfix: "stalled cache updating" alert. + + *) Bugfix: nginx could not be built --without-http_auth_basic_module; + the bug had appeared in 1.0.3. + + +Changes with nginx 1.0.3 25 May 2011 + + *) Feature: the "auth_basic_user_file" directive supports "$apr1", + "{PLAIN}", and "{SSHA}" password encryption methods. + Thanks to Maxim Dounin. + + *) Feature: the "geoip_org" directive and $geoip_org variable. + Thanks to Alexander Uskov, Arnaud Granal, and Denis F. Latypoff. + + *) Feature: ngx_http_geo_module and ngx_http_geoip_module support IPv4 + addresses mapped to IPv6 addresses. + + *) Bugfix: a segmentation fault occurred in a worker process during + testing IPv4 address mapped to IPv6 address, if access or deny rules + were defined only for IPv6; the bug had appeared in 0.8.22. + + *) Bugfix: a cached response may be broken if "proxy/fastcgi/scgi/ + uwsgi_cache_bypass" and "proxy/fastcgi/scgi/uwsgi_no_cache" directive + values were different; the bug had appeared in 0.8.46. + + +Changes with nginx 1.0.2 10 May 2011 + + *) Feature: now shared zones and caches use POSIX semaphores. + + *) Bugfix: in the "rotate" parameter of the "image_filter" directive. + Thanks to Adam Bocim. + + *) Bugfix: nginx could not be built on Solaris; the bug had appeared in + 1.0.1. + + +Changes with nginx 1.0.1 03 May 2011 + + *) Change: now the "split_clients" directive uses MurmurHash2 algorithm + because of better distribution. + Thanks to Oleg Mamontov. + + *) Change: now long strings starting with zero are not considered as + false values. + Thanks to Maxim Dounin. + + *) Change: now nginx uses a default listen backlog value 511 on Linux. + + *) Feature: the $upstream_... variables may be used in the SSI and perl + modules. + + *) Bugfix: now nginx limits better disk cache size. + Thanks to Oleg Mamontov. + + *) Bugfix: a segmentation fault might occur while parsing incorrect IPv4 + address; the bug had appeared in 0.9.3. + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not be built by gcc 4.6 without --with-debug + option. + + *) Bugfix: nginx could not be built on Solaris 9 and earlier; the bug + had appeared in 0.9.3. + Thanks to Dagobert Michelsen. + + *) Bugfix: $request_time variable had invalid values if subrequests were + used; the bug had appeared in 0.8.47. + Thanks to Igor A. Valcov. + + +Changes with nginx 1.0.0 12 Apr 2011 + + *) Bugfix: a cache manager might hog CPU after reload. + Thanks to Maxim Dounin. + + *) Bugfix: an "image_filter crop" directive worked incorrectly coupled + with an "image_filter rotate 180" directive. + + *) Bugfix: a "satisfy any" directive disabled custom 401 error page. + + +Changes with nginx 0.9.7 04 Apr 2011 + + *) Feature: now keepalive connections may be closed premature, if there + are no free worker connections. + Thanks to Maxim Dounin. + + *) Feature: the "rotate" parameter of the "image_filter" directive. + Thanks to Adam Bocim. + + *) Bugfix: a case when a backend in "fastcgi_pass", "scgi_pass", or + "uwsgi_pass" directives is given by expression and refers to a + defined upstream. + + +Changes with nginx 0.9.6 21 Mar 2011 + + *) Feature: the "map" directive supports regular expressions as value of + the first parameter. + + *) Feature: $time_iso8601 access_log variable. + Thanks to Michael Lustfield. + + +Changes with nginx 0.9.5 21 Feb 2011 + + *) Change: now nginx uses a default listen backlog value -1 on Linux. + Thanks to Andrei Nigmatulin. + + *) Feature: the "utf8" parameter of "geoip_country" and "geoip_city" + directives. + Thanks to Denis F. Latypoff. + + *) Bugfix: in a default "proxy_redirect" directive if "proxy_pass" + directive has no URI part. + Thanks to Maxim Dounin. + + *) Bugfix: an "error_page" directive did not work with nonstandard error + codes; the bug had appeared in 0.8.53. + Thanks to Maxim Dounin. + + +Changes with nginx 0.9.4 21 Jan 2011 + + *) Feature: the "server_name" directive supports the $hostname variable. + + *) Feature: 494 code for "Request Header Too Large" error. + + +Changes with nginx 0.9.3 13 Dec 2010 + + *) Bugfix: if there was a single server for given IPv6 address:port + pair, then captures in regular expressions in a "server_name" + directive did not work. + + *) Bugfix: nginx could not be built on Solaris; the bug had appeared in + 0.9.0. + + +Changes with nginx 0.9.2 06 Dec 2010 + + *) Feature: the "If-Unmodified-Since" client request header line + support. + + *) Workaround: fallback to accept() syscall if accept4() was not + implemented; the issue had appeared in 0.9.0. + + *) Bugfix: nginx could not be built on Cygwin; the bug had appeared in + 0.9.0. + + *) Bugfix: for OpenSSL vulnerability CVE-2010-4180. + Thanks to Maxim Dounin. + + +Changes with nginx 0.9.1 30 Nov 2010 + + *) Bugfix: "return CODE message" directives did not work; the bug had + appeared in 0.9.0. + + +Changes with nginx 0.9.0 29 Nov 2010 + + *) Feature: the "keepalive_disable" directive. + + *) Feature: the "map" directive supports variables as value of a defined + variable. + + *) Feature: the "map" directive supports empty strings as value of the + first parameter. + + *) Feature: the "map" directive supports expressions as the first + parameter. + + *) Feature: nginx(8) manual page. + Thanks to Sergey Osokin. + + *) Feature: Linux accept4() support. + Thanks to Simon Liu. + + *) Workaround: elimination of Linux linker warning about "sys_errlist" + and "sys_nerr"; the warning had appeared in 0.8.35. + + *) Bugfix: a segmentation fault might occur in a worker process, if the + "auth_basic" directive was used. + Thanks to Michail Laletin. + + *) Bugfix: compatibility with ngx_http_eval_module; the bug had appeared + in 0.8.42. + + +Changes with nginx 0.8.53 18 Oct 2010 + + *) Feature: now the "error_page" directive allows to change a status + code in a redirect. + + *) Feature: the "gzip_disable" directive supports special "degradation" + mask. + + *) Bugfix: a socket leak might occurred if file AIO was used. + Thanks to Maxim Dounin. + + *) Bugfix: if the first server had no "listen" directive and there was + no explicit default server, then a next server with a "listen" + directive became the default server; the bug had appeared in 0.8.21. + + +Changes with nginx 0.8.52 28 Sep 2010 + + *) Bugfix: nginx used SSL mode for a listen socket if any listen option + was set; the bug had appeared in 0.8.51. + + +Changes with nginx 0.8.51 27 Sep 2010 + + *) Change: the "secure_link_expires" directive has been canceled. + + *) Change: a logging level of resolver errors has been lowered from + "alert" to "error". + + *) Feature: now a listen socket "ssl" parameter may be set several + times. + + +Changes with nginx 0.8.50 02 Sep 2010 + + *) Feature: the "secure_link", "secure_link_md5", and + "secure_link_expires" directives of the ngx_http_secure_link_module. + + *) Feature: the -q switch. + Thanks to Gena Makhomed. + + *) Bugfix: worker processes may got caught in an endless loop during + reconfiguration, if a caching was used; the bug had appeared in + 0.8.48. + + *) Bugfix: in the "gzip_disable" directive. + Thanks to Derrick Petzold. + + *) Bugfix: nginx/Windows could not send stop, quit, reopen, and reload + signals to a process run in other session. + + +Changes with nginx 0.8.49 09 Aug 2010 + + *) Feature: the "image_filter_jpeg_quality" directive supports + variables. + + *) Bugfix: a segmentation fault might occur in a worker process, if the + $geoip_region_name variables was used; the bug had appeared in + 0.8.48. + + *) Bugfix: errors intercepted by error_page were cached only for next + request; the bug had appeared in 0.8.48. + + +Changes with nginx 0.8.48 03 Aug 2010 + + *) Change: now the "server_name" directive default value is an empty + name "". + Thanks to Gena Makhomed. + + *) Change: now the "server_name_in_redirect" directive default value is + "off". + + *) Feature: the $geoip_dma_code, $geoip_area_code, and + $geoip_region_name variables. + Thanks to Christine McGonagle. + + *) Bugfix: the "proxy_pass", "fastcgi_pass", "uwsgi_pass", and + "scgi_pass" directives were not inherited inside "limit_except" + blocks. + + *) Bugfix: the "proxy_cache_min_uses", "fastcgi_cache_min_uses" + "uwsgi_cache_min_uses", and "scgi_cache_min_uses" directives did not + work; the bug had appeared in 0.8.46. + + *) Bugfix: the "fastcgi_split_path_info" directive used incorrectly + captures, if only parts of an URI were captured. + Thanks to Yuriy Taraday and Frank Enderle. + + *) Bugfix: the "rewrite" directive did not escape a ";" character during + copying from URI to query string. + Thanks to Daisuke Murase. + + *) Bugfix: the ngx_http_image_filter_module closed a connection, if an + image was larger than "image_filter_buffer" size. + + +Changes with nginx 0.8.47 28 Jul 2010 + + *) Bugfix: $request_time variable had invalid values for subrequests. + + *) Bugfix: errors intercepted by error_page could not be cached. + + *) Bugfix: a cache manager process may got caught in an endless loop, if + max_size parameter was used; the bug had appeared in 0.8.46. + + +Changes with nginx 0.8.46 19 Jul 2010 + + *) Change: now the "proxy_no_cache", "fastcgi_no_cache", + "uwsgi_no_cache", and "scgi_no_cache" directives affect on a cached + response saving only. + + *) Feature: the "proxy_cache_bypass", "fastcgi_cache_bypass", + "uwsgi_cache_bypass", and "scgi_cache_bypass" directives. + + *) Bugfix: nginx did not free memory in cache keys zones if there was an + error during working with backend: the memory was freed only after + inactivity time or on memory low condition. + + +Changes with nginx 0.8.45 13 Jul 2010 + + *) Feature: ngx_http_xslt_filter improvements. + Thanks to Laurence Rowe. + + *) Bugfix: SSI response might be truncated after include with + wait="yes"; the bug had appeared in 0.7.25. + Thanks to Maxim Dounin. + + *) Bugfix: the "listen" directive did not support the "setfib=0" + parameter. + + +Changes with nginx 0.8.44 05 Jul 2010 + + *) Change: now nginx does not cache by default backend responses, if + they have a "Set-Cookie" header line. + + *) Feature: the "listen" directive supports the "setfib" parameter. + Thanks to Andrew Filonov. + + *) Bugfix: the "sub_filter" directive might change character case on + partial match. + + *) Bugfix: compatibility with HP/UX. + + *) Bugfix: compatibility with AIX xlC_r compiler. + + *) Bugfix: nginx treated large SSLv2 packets as plain requests. + Thanks to Miroslaw Jaworski. + + +Changes with nginx 0.8.43 30 Jun 2010 + + *) Feature: large geo ranges base loading speed-up. + + *) Bugfix: an error_page redirection to "location /zero {return 204;}" + without changing status code kept the error body; the bug had + appeared in 0.8.42. + + *) Bugfix: nginx might close IPv6 listen socket during reconfiguration. + Thanks to Maxim Dounin. + + *) Bugfix: the $uid_set variable may be used at any request processing + stage. + + +Changes with nginx 0.8.42 21 Jun 2010 + + *) Change: now nginx tests locations given by regular expressions, if + request was matched exactly by a location given by a prefix string. + The previous behavior has been introduced in 0.7.1. + + *) Feature: the ngx_http_scgi_module. + Thanks to Manlio Perillo. + + *) Feature: a text answer may be added to a "return" directive. + + +Changes with nginx 0.8.41 15 Jun 2010 + + *) Security: nginx/Windows worker might be terminated abnormally if a + requested file name has invalid UTF-8 encoding. + + *) Change: now nginx allows to use spaces in a request line. + + *) Bugfix: the "proxy_redirect" directive changed incorrectly a backend + "Refresh" response header line. + Thanks to Andrey Andreew and Max Sogin. + + *) Bugfix: nginx did not support path without host name in "Destination" + request header line. + + +Changes with nginx 0.8.40 07 Jun 2010 + + *) Security: now nginx/Windows ignores default file stream name. + Thanks to Jose Antonio Vazquez Gonzalez. + + *) Feature: the ngx_http_uwsgi_module. + Thanks to Roberto De Ioris. + + *) Feature: a "fastcgi_param" directive with value starting with "HTTP_" + overrides a client request header line. + + *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request + header lines were passed to FastCGI-server while caching. + + *) Bugfix: listen unix domain socket could not be changed during + reconfiguration. + Thanks to Maxim Dounin. + + +Changes with nginx 0.8.39 31 May 2010 + + *) Bugfix: an inherited "alias" directive worked incorrectly in + inclusive location. + + *) Bugfix: in "alias" with variables and "try_files" directives + combination. + + *) Bugfix: listen unix domain and IPv6 sockets did not inherit while + online upgrade. + Thanks to Maxim Dounin. + + +Changes with nginx 0.8.38 24 May 2010 + + *) Feature: the "proxy_no_cache" and "fastcgi_no_cache" directives. + + *) Feature: now the "rewrite" directive does a redirect automatically if + the $scheme variable is used. + Thanks to Piotr Sikora. + + *) Bugfix: now "limit_req" delay directive conforms to the described + algorithm. + Thanks to Maxim Dounin. + + *) Bugfix: the $uid_got variable might not be used in the SSI and perl + modules. + + +Changes with nginx 0.8.37 17 May 2010 + + *) Feature: the ngx_http_split_clients_module. + + *) Feature: the "map" directive supports keys more than 255 characters. + + *) Bugfix: nginx ignored the "private" and "no-store" values in the + "Cache-Control" backend response header line. + + *) Bugfix: a "stub" parameter of an "include" SSI directive was not + used, if empty response has 200 status code. + + *) Bugfix: if a proxied or FastCGI request was internally redirected to + another proxied or FastCGI location, then a segmentation fault might + occur in a worker process; the bug had appeared in 0.8.33. + Thanks to Yichun Zhang. + + *) Bugfix: IMAP connections may hang until they timed out while talking + to Zimbra server. + Thanks to Alan Batie. + + +Changes with nginx 0.8.36 22 Apr 2010 + + *) Bugfix: the ngx_http_dav_module handled incorrectly the DELETE, COPY, + and MOVE methods for symlinks. + + *) Bugfix: values of the $query_string, $arg_..., etc. variables cached + in main request were used by the SSI module in subrequests. + + *) Bugfix: a variable value was repeatedly encoded after each an "echo" + SSI-command output; the bug had appeared in 0.6.14. + + *) Bugfix: a worker process hung if a FIFO file was requested. + Thanks to Vicente Aguilar and Maxim Dounin. + + *) Bugfix: OpenSSL-1.0.0 compatibility on 64-bit Linux. + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not be built --without-http-cache; the bug had + appeared in 0.8.35. + + +Changes with nginx 0.8.35 01 Apr 2010 + + *) Change: now the charset filter runs before the SSI filter. + + *) Feature: the "chunked_transfer_encoding" directive. + + *) Bugfix: an "&" character was not escaped when it was copied in + arguments part in a rewrite rule. + + *) Bugfix: nginx might be terminated abnormally while a signal + processing or if the directive "timer_resolution" was used on + platforms which do not support kqueue or eventport notification + methods. + Thanks to George Xie and Maxim Dounin. + + *) Bugfix: if temporary files and permanent storage area resided at + different file systems, then permanent file modification times were + incorrect. + Thanks to Maxim Dounin. + + *) Bugfix: ngx_http_memcached_module might issue the error message + "memcached sent invalid trailer". + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not built zlib-1.2.4 library using the library + sources. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault occurred in a worker process, if there + was large stderr output before FastCGI response; the bug had appeared + in 0.8.34. + Thanks to Maxim Dounin. + + +Changes with nginx 0.8.34 03 Mar 2010 + + *) Bugfix: nginx did not support all ciphers and digests used in client + certificates. + Thanks to Innocenty Enikeew. + + *) Bugfix: nginx cached incorrectly FastCGI responses if there was large + stderr output before response. + + *) Bugfix: nginx did not support HTTPS referrers. + + *) Bugfix: nginx/Windows might not find file if path in configuration + was given in other character case; the bug had appeared in 0.8.33. + + *) Bugfix: the $date_local variable has an incorrect value, if the "%s" + format was used. + Thanks to Maxim Dounin. + + *) Bugfix: if ssl_session_cache was not set or was set to "none", then + during client certificate verify the error "session id context + uninitialized" might occur; the bug had appeared in 0.7.1. + + *) Bugfix: a geo range returned default value if the range included two + or more /16 networks and did not begin at /16 network boundary. + + *) Bugfix: a block used in a "stub" parameter of an "include" SSI + directive was output with "text/plain" MIME type. + + *) Bugfix: $r->sleep() did not work; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.33 01 Feb 2010 + + *) Security: now nginx/Windows ignores trailing spaces in URI. + Thanks to Dan Crowley, Core Security Technologies. + + *) Security: now nginx/Windows ignores short files names. + Thanks to Dan Crowley, Core Security Technologies. + + *) Change: now keepalive connections after POST requests are not + disabled for MSIE 7.0+. + Thanks to Adam Lounds. + + *) Workaround: now keepalive connections are disabled for Safari. + Thanks to Joshua Sierles. + + *) Bugfix: if a proxied or FastCGI request was internally redirected to + another proxied or FastCGI location, then $upstream_response_time + variable may have abnormally large value; the bug had appeared in + 0.8.7. + + *) Bugfix: a segmentation fault might occur in a worker process, while + discarding a request body; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.32 11 Jan 2010 + + *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module. + Thanks to Maxim Dounin. + + *) Bugfix: regular expression named captures worked for two names only. + Thanks to Maxim Dounin. + + *) Bugfix: now the "localhost" name is used in the "Host" request header + line, if an unix domain socket is defined in the "auth_http" + directive. + Thanks to Maxim Dounin. + + *) Bugfix: nginx did not support chunked transfer encoding for 201 + responses. + Thanks to Julian Reich. + + *) Bugfix: if the "expires modified" set date in the past, then a + negative number was set in the "Cache-Control" response header line. + Thanks to Alex Kapranoff. + + +Changes with nginx 0.8.31 23 Dec 2009 + + *) Feature: now the "error_page" directive may redirect the 301 and 302 + responses. + + *) Feature: the $geoip_city_continent_code, $geoip_latitude, and + $geoip_longitude variables. + Thanks to Arvind Sundararajan. + + *) Feature: now the ngx_http_image_filter_module deletes always EXIF and + other application specific data if the data consume more than 5% of a + JPEG file. + + *) Bugfix: nginx closed a connection if a cached response had an empty + body. + Thanks to Piotr Sikora. + + *) Bugfix: nginx might not be built by gcc 4.x if the -O2 or higher + optimization option was used. + Thanks to Maxim Dounin and Denis F. Latypoff. + + *) Bugfix: regular expressions in location were always tested in + case-sensitive mode; the bug had appeared in 0.8.25. + + *) Bugfix: nginx cached a 304 response if there was the "If-None-Match" + header line in a proxied request. + Thanks to Tim Dettrick and David Kostal. + + *) Bugfix: nginx/Windows tried to delete a temporary file twice if the + file should replace an already existent file. + + +Changes with nginx 0.8.30 15 Dec 2009 + + *) Change: now the default buffer size of the + "large_client_header_buffers" directive is 8K. + Thanks to Andrew Cholakian. + + *) Feature: the conf/fastcgi.conf for simple FastCGI configurations. + + *) Bugfix: nginx/Windows tried to rename a temporary file twice if the + file should replace an already existent file. + + *) Bugfix: of "double free or corruption" error issued if host could not + be resolved; the bug had appeared in 0.8.22. + Thanks to Konstantin Svist. + + *) Bugfix: in libatomic usage on some platforms. + Thanks to W-Mark Kubacki. + + +Changes with nginx 0.8.29 30 Nov 2009 + + *) Change: now the "009" status code is written to an access log for + proxied HTTP/0.9 responses. + + *) Feature: the "addition_types", "charset_types", "gzip_types", + "ssi_types", "sub_filter_types", and "xslt_types" directives support + an "*" parameter. + + *) Feature: GCC 4.1+ built-in atomic operations usage. + Thanks to W-Mark Kubacki. + + *) Feature: the --with-libatomic[=DIR] option in the configure. + Thanks to W-Mark Kubacki. + + *) Bugfix: listen unix domain socket had limited access rights. + + *) Bugfix: cached HTTP/0.9 responses were handled incorrectly. + + *) Bugfix: regular expression named captures given by "?P<...>" did not + work in a "server_name" directive. + Thanks to Maxim Dounin. + + +Changes with nginx 0.8.28 23 Nov 2009 + + *) Bugfix: nginx could not be built with the --without-pcre parameter; + the bug had appeared in 0.8.25. + + +Changes with nginx 0.8.27 17 Nov 2009 + + *) Bugfix: regular expressions did not work in nginx/Windows; the bug + had appeared in 0.8.25. + + +Changes with nginx 0.8.26 16 Nov 2009 + + *) Bugfix: in captures usage in "rewrite" directive; the bug had + appeared in 0.8.25. + + *) Bugfix: nginx could not be built without the --with-debug option; the + bug had appeared in 0.8.25. + + +Changes with nginx 0.8.25 16 Nov 2009 + + *) Change: now no message is written in an error log if a variable is + not found by $r->variable() method. + + *) Feature: the ngx_http_degradation_module. + + *) Feature: regular expression named captures. + + *) Feature: now URI part is not required a "proxy_pass" directive if + variables are used. + + *) Feature: now the "msie_padding" directive works for Chrome too. + + *) Bugfix: a segmentation fault occurred in a worker process on low + memory condition; the bug had appeared in 0.8.18. + + *) Bugfix: nginx sent gzipped responses to clients those do not support + gzip, if "gzip_static on" and "gzip_vary off"; the bug had appeared + in 0.8.16. + + +Changes with nginx 0.8.24 11 Nov 2009 + + *) Bugfix: nginx always added "Content-Encoding: gzip" response header + line in 304 responses sent by ngx_http_gzip_static_module. + + *) Bugfix: nginx could not be built without the --with-debug option; the + bug had appeared in 0.8.23. + + *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive + inherited incorrectly from previous level. + + *) Bugfix: in resolving empty name. + + +Changes with nginx 0.8.23 11 Nov 2009 + + *) Security: now SSL/TLS renegotiation is disabled. + Thanks to Maxim Dounin. + + *) Bugfix: listen unix domain socket did not inherit while online + upgrade. + + *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive did + not without yet another directive with any IP address. + + *) Bugfix: segmentation fault and infinite looping in resolver. + + *) Bugfix: in resolver. + Thanks to Artem Bokhan. + + +Changes with nginx 0.8.22 03 Nov 2009 + + *) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind" + directives. + + *) Feature: the "access" and the "deny" directives support IPv6. + + *) Feature: the "set_real_ip_from" directive supports IPv6 addresses in + request headers. + + *) Feature: the "unix:" parameter of the "set_real_ip_from" directive. + + *) Bugfix: nginx did not delete unix domain socket after configuration + testing. + + *) Bugfix: nginx deleted unix domain socket while online upgrade. + + *) Bugfix: the "!-x" operator did not work. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault might occur in a worker process, if + limit_rate was used in HTTPS server. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault might occur in a worker process while + $limit_rate logging. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault might occur in a worker process, if + there was no "listen" directive in "server" block; the bug had + appeared in 0.8.21. + + +Changes with nginx 0.8.21 26 Oct 2009 + + *) Feature: now the "-V" switch shows TLS SNI support. + + *) Feature: the "listen" directive of the HTTP module supports unix + domain sockets. + Thanks to Hongli Lai. + + *) Feature: the "default_server" parameter of the "listen" directive. + + *) Feature: now a "default" parameter is not required to set listen + socket options. + + *) Bugfix: nginx did not support dates in 2038 year on 32-bit platforms; + + *) Bugfix: socket leak; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.20 14 Oct 2009 + + *) Change: now default SSL ciphers are "HIGH:!ADH:!MD5". + + *) Bugfix: the ngx_http_autoindex_module did not show the trailing slash + in links to a directory; the bug had appeared in 0.7.15. + + *) Bugfix: nginx did not close a log file set by the --error-log-path + configuration option; the bug had appeared in 0.7.53. + + *) Bugfix: nginx did not treat a comma as separator in the + "Cache-Control" backend response header line. + + *) Bugfix: nginx/Windows might not create temporary file, a cache file, + or "proxy/fastcgi_store"d file if a worker had no enough access + rights for top level directories. + + *) Bugfix: the "Set-Cookie" and "P3P" FastCGI response header lines were + not hidden while caching if no "fastcgi_hide_header" directives were + used with any parameters. + + *) Bugfix: nginx counted incorrectly disk cache size. + + +Changes with nginx 0.8.19 06 Oct 2009 + + *) Change: now SSLv2 protocol is disabled by default. + + *) Change: now default SSL ciphers are "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM". + + *) Bugfix: a "limit_req" directive did not work; the bug had appeared in + 0.8.18. + + +Changes with nginx 0.8.18 06 Oct 2009 + + *) Feature: the "read_ahead" directive. + + *) Feature: now several "perl_modules" directives may be used. + + *) Feature: the "limit_req_log_level" and "limit_conn_log_level" + directives. + + *) Bugfix: now "limit_req" directive conforms to the leaky bucket + algorithm. + Thanks to Maxim Dounin. + + *) Bugfix: nginx did not work on Linux/sparc. + Thanks to Marcus Ramberg. + + *) Bugfix: nginx sent '\0' in a "Location" response header line on MKCOL + request. + Thanks to Xie Zhenye. + + *) Bugfix: zero status code was logged instead of 499 status code; the + bug had appeared in 0.8.11. + + *) Bugfix: socket leak; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.17 28 Sep 2009 + + *) Security: now "/../" are disabled in "Destination" request header + line. + + *) Change: now $host variable value is always low case. + + *) Feature: the $ssl_session_id variable. + + *) Bugfix: socket leak; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.16 22 Sep 2009 + + *) Feature: the "image_filter_transparency" directive. + + *) Bugfix: "addition_types" directive was incorrectly named + "addtion_types". + + *) Bugfix: resolver cache poisoning. + Thanks to Matthew Dempsky. + + *) Bugfix: memory leak in resolver. + Thanks to Matthew Dempsky. + + *) Bugfix: invalid request line in $request variable was written in + access_log only if error_log was set to "info" or "debug" level. + + *) Bugfix: in PNG alpha-channel support in the + ngx_http_image_filter_module. + + *) Bugfix: nginx always added "Vary: Accept-Encoding" response header + line, if both "gzip_static" and "gzip_vary" were on. + + *) Bugfix: in UTF-8 encoding support by "try_files" directive in + nginx/Windows. + + *) Bugfix: in "post_action" directive usage; the bug had appeared in + 0.8.11. + Thanks to Igor Artemiev. + + +Changes with nginx 0.8.15 14 Sep 2009 + + *) Security: a segmentation fault might occur in worker process while + specially crafted request handling. + Thanks to Chris Ries. + + *) Bugfix: if names .domain.tld, .sub.domain.tld, and .domain-some.tld + were defined, then the name .sub.domain.tld was matched by + .domain.tld. + + *) Bugfix: in transparency support in the ngx_http_image_filter_module. + + *) Bugfix: in file AIO. + + *) Bugfix: in X-Accel-Redirect usage; the bug had appeared in 0.8.11. + + *) Bugfix: in embedded perl module; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.14 07 Sep 2009 + + *) Bugfix: an expired cached response might stick in the "UPDATING" + state. + + *) Bugfix: a segmentation fault might occur in worker process, if + error_log was set to info or debug level. + Thanks to Sergey Bochenkov. + + *) Bugfix: in embedded perl module; the bug had appeared in 0.8.11. + + *) Bugfix: an "error_page" directive did not redirect a 413 error; the + bug had appeared in 0.6.10. + + +Changes with nginx 0.8.13 31 Aug 2009 + + *) Bugfix: in the "aio sendfile" directive; the bug had appeared in + 0.8.12. + + *) Bugfix: nginx could not be built without the --with-file-aio option + on FreeBSD; the bug had appeared in 0.8.12. + + +Changes with nginx 0.8.12 31 Aug 2009 + + *) Feature: the "sendfile" parameter in the "aio" directive on FreeBSD. + + *) Bugfix: in try_files; the bug had appeared in 0.8.11. + + *) Bugfix: in memcached; the bug had appeared in 0.8.11. + + +Changes with nginx 0.8.11 28 Aug 2009 + + *) Change: now directive "gzip_disable msie6" does not disable gzipping + for MSIE 6.0 SV1. + + *) Feature: file AIO support on FreeBSD and Linux. + + *) Feature: the "directio_alignment" directive. + + +Changes with nginx 0.8.10 24 Aug 2009 + + *) Bugfix: memory leaks if GeoIP City database was used. + + *) Bugfix: in copying temporary files to permanent storage area; the bug + had appeared in 0.8.9. + + +Changes with nginx 0.8.9 17 Aug 2009 + + *) Feature: now the start cache loader runs in a separate process; this + should improve large caches handling. + + *) Feature: now temporary files and permanent storage area may reside at + different file systems. + + +Changes with nginx 0.8.8 10 Aug 2009 + + *) Bugfix: in handling FastCGI headers split in records. + + *) Bugfix: a segmentation fault occurred in worker process, if a request + was handled in two proxied or FastCGIed locations and a caching was + enabled in the first location; the bug had appeared in 0.8.7. + + +Changes with nginx 0.8.7 27 Jul 2009 + + *) Change: minimum supported OpenSSL version is 0.9.7. + + *) Change: the "ask" parameter of the "ssl_verify_client" directive was + changed to the "optional" parameter and now it checks a client + certificate if it was offered. + Thanks to Brice Figureau. + + *) Feature: the $ssl_client_verify variable. + Thanks to Brice Figureau. + + *) Feature: the "ssl_crl" directive. + Thanks to Brice Figureau. + + *) Feature: the "proxy" parameter of the "geo" directive. + + *) Feature: the "image_filter" directive supports variables for setting + size. + + *) Bugfix: the $ssl_client_cert variable usage corrupted memory; the bug + had appeared in 0.7.7. + Thanks to Sergey Zhuravlev. + + *) Bugfix: "proxy_pass_header" and "fastcgi_pass_header" directives did + not pass to a client the "X-Accel-Redirect", "X-Accel-Limit-Rate", + "X-Accel-Buffering", and "X-Accel-Charset" lines from backend + response header. + Thanks to Maxim Dounin. + + *) Bugfix: in handling "Last-Modified" and "Accept-Ranges" backend + response header lines; the bug had appeared in 0.7.44. + Thanks to Maxim Dounin. + + *) Bugfix: the "[alert] zero size buf" error if subrequest returns an + empty response; the bug had appeared in 0.8.5. + + +Changes with nginx 0.8.6 20 Jul 2009 + + *) Feature: the ngx_http_geoip_module. + + *) Bugfix: XSLT filter may fail with message "not well formed XML + document" for valid XML document. + Thanks to Kuramoto Eiji. + + *) Bugfix: now in MacOSX, Cygwin, and nginx/Windows locations given by a + regular expression are always tested in case insensitive mode. + + *) Bugfix: now nginx/Windows ignores trailing dots in URI. + Thanks to Hugo Leisink. + + *) Bugfix: name of file specified in --conf-path was not honored during + installation; the bug had appeared in 0.6.6. + Thanks to Maxim Dounin. + + +Changes with nginx 0.8.5 13 Jul 2009 + + *) Bugfix: now nginx allows underscores in a request method. + + *) Bugfix: a 500 error code was returned for invalid login/password + while HTTP Basic authentication on Windows. + + *) Bugfix: ngx_http_perl_module responses did not work in subrequests. + + *) Bugfix: in ngx_http_limit_req_module. + Thanks to Maxim Dounin. + + +Changes with nginx 0.8.4 22 Jun 2009 + + *) Bugfix: nginx could not be built --without-http-cache; the bug had + appeared in 0.8.3. + + +Changes with nginx 0.8.3 19 Jun 2009 + + *) Feature: the $upstream_cache_status variable. + + *) Bugfix: nginx could not be built on MacOSX 10.6. + + *) Bugfix: nginx could not be built --without-http-cache; the bug had + appeared in 0.8.2. + + *) Bugfix: a segmentation fault occurred in worker process, if a backend + 401 error was intercepted and the backend did not set the + "WWW-Authenticate" response header line. + Thanks to Eugene Mychlo. + + +Changes with nginx 0.8.2 15 Jun 2009 + + *) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on + start up. + + *) Bugfix: open_file_cache might cache open file descriptors too long; + the bug had appeared in 0.7.4. + + +Changes with nginx 0.8.1 08 Jun 2009 + + *) Feature: the "updating" parameter in "proxy_cache_use_stale" and + "fastcgi_cache_use_stale" directives. + + *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request + header lines were passed to backend while caching if no + "proxy_set_header" directive was used with any parameters. + + *) Bugfix: the "Set-Cookie" and "P3P" response header lines were not + hidden while caching if no "proxy_hide_header/fastcgi_hide_header" + directives were used with any parameters. + + *) Bugfix: the ngx_http_image_filter_module did not support GIF87a + format. + Thanks to Denis Ilyinyh. + + *) Bugfix: nginx could not be built modules on Solaris 10 and early; the + bug had appeared in 0.7.56. + + +Changes with nginx 0.8.0 02 Jun 2009 + + *) Feature: the "keepalive_requests" directive. + + *) Feature: the "limit_rate_after" directive. + Thanks to Ivan Debnar. + + *) Bugfix: XLST filter did not work in subrequests. + + *) Bugfix: in relative paths handling in nginx/Windows. + + *) Bugfix: in proxy_store, fastcgi_store, proxy_cache, and fastcgi_cache + in nginx/Windows. + + *) Bugfix: in memory allocation error handling. + Thanks to Maxim Dounin and Kirill A. Korinskiy. + + +Changes with nginx 0.7.59 25 May 2009 + + *) Feature: the "proxy_cache_methods" and "fastcgi_cache_methods" + directives. + + *) Bugfix: socket leak; the bug had appeared in 0.7.25. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault occurred in worker process, if a request + had no body and the $request_body variable was used; + the bug had appeared in 0.7.58. + + *) Bugfix: the SSL modules might not built on Solaris and Linux; + the bug had appeared in 0.7.56. + + *) Bugfix: ngx_http_xslt_filter_module responses were not handled by + SSI, charset, and gzip filters. + + *) Bugfix: a "charset" directive did not set a charset to + ngx_http_gzip_static_module responses. + + +Changes with nginx 0.7.58 18 May 2009 + + *) Feature: a "listen" directive of the mail proxy module supports IPv6. + + *) Feature: the "image_filter_jpeg_quality" directive. + + *) Feature: the "client_body_in_single_buffer" directive. + + *) Feature: the $request_body variable. + + *) Bugfix: in ngx_http_autoindex_module in file name links having a ":" + symbol in the name. + + *) Bugfix: "make upgrade" procedure did not work; the bug had appeared + in 0.7.53. + Thanks to Denis F. Latypoff. + + +Changes with nginx 0.7.57 12 May 2009 + + *) Bugfix: a floating-point fault occurred in worker process, if the + ngx_http_image_filter_module errors were redirected to named + location; the bug had appeared in 0.7.56. + + +Changes with nginx 0.7.56 11 May 2009 + + *) Feature: nginx/Windows supports IPv6 in a "listen" directive of the + HTTP module. + + *) Bugfix: in ngx_http_image_filter_module. + + +Changes with nginx 0.7.55 06 May 2009 + + *) Bugfix: the http_XXX parameters in "proxy_cache_use_stale" and + "fastcgi_cache_use_stale" directives did not work. + + *) Bugfix: fastcgi cache did not cache header only responses. + + *) Bugfix: of "select() failed (9: Bad file descriptor)" error in + nginx/Unix and "select() failed (10038: ...)" error in nginx/Windows. + + *) Bugfix: a segmentation fault might occur in worker process, if an + "debug_connection" directive was used; the bug had appeared in + 0.7.54. + + *) Bugfix: fix ngx_http_image_filter_module building errors. + + *) Bugfix: the files bigger than 2G could not be transferred using + $r->sendfile. + Thanks to Maxim Dounin. + + +Changes with nginx 0.7.54 01 May 2009 + + *) Feature: the ngx_http_image_filter_module. + + *) Feature: the "proxy_ignore_headers" and "fastcgi_ignore_headers" + directives. + + *) Bugfix: a segmentation fault might occur in worker process, if an + "open_file_cache_errors off" directive was used; the bug had appeared + in 0.7.53. + + *) Bugfix: the "port_in_redirect off" directive did not work; the bug + had appeared in 0.7.39. + + *) Bugfix: improve handling of "select" method errors. + + *) Bugfix: of "select() failed (10022: ...)" error in nginx/Windows. + + *) Bugfix: in error text descriptions in nginx/Windows; the bug had + appeared in 0.7.53. + + +Changes with nginx 0.7.53 27 Apr 2009 + + *) Change: now a log set by --error-log-path is created from the very + start-up. + + *) Feature: now the start up errors and warnings are outputted to an + error_log and stderr. + + *) Feature: the empty --prefix= configure parameter forces nginx to use + a directory where it was run as prefix. + + *) Feature: the -p switch. + + *) Feature: the -s switch on Unix platforms. + + *) Feature: the -? and -h switches. + Thanks to Jerome Loyet. + + *) Feature: now switches may be set in condensed form. + + *) Bugfix: nginx/Windows did not work if configuration file was given by + the -c switch. + + *) Bugfix: temporary files might be not removed if the "proxy_store", + "fastcgi_store", "proxy_cache", or "fastcgi_cache" were used. + Thanks to Maxim Dounin. + + *) Bugfix: an incorrect value was passed to mail proxy authentication + server in "Auth-Method" header line; the bug had appeared + in 0.7.34. + Thanks to Simon Lecaille. + + *) Bugfix: system error text descriptions were not logged on Linux; + the bug had appeared in 0.7.45. + + *) Bugfix: the "fastcgi_cache_min_uses" directive did not work. + Thanks to Andrew Vorobyoff. + + +Changes with nginx 0.7.52 20 Apr 2009 + + *) Feature: the first native Windows binary release. + + *) Bugfix: in processing HEAD method while caching. + + *) Bugfix: in processing the "If-Modified-Since", "If-Range", etc. + client request header lines while caching. + + *) Bugfix: now the "Set-Cookie" and "P3P" header lines are hidden in + cacheable responses. + + *) Bugfix: if nginx was built with the ngx_http_perl_module and with a + perl which supports threads, then during a master process exit the + message "panic: MUTEX_LOCK" might be issued. + + *) Bugfix: nginx could not be built --without-http-cache; the bug had + appeared in 0.7.48. + + *) Bugfix: nginx could not be built on platforms different from i386, + amd64, sparc, and ppc; the bug had appeared in 0.7.42. + + +Changes with nginx 0.7.51 12 Apr 2009 + + *) Feature: the "try_files" directive supports a response code in the + fallback parameter. + + *) Feature: now any response code can be used in the "return" directive. + + *) Bugfix: the "error_page" directive made an external redirect without + query string; the bug had appeared in 0.7.44. + + *) Bugfix: if servers listened on several defined explicitly addresses, + then virtual servers might not work; the bug had appeared in 0.7.39. + + +Changes with nginx 0.7.50 06 Apr 2009 + + *) Bugfix: the $arg_... variables did not work; the bug had appeared in + 0.7.49. + + +Changes with nginx 0.7.49 06 Apr 2009 + + *) Bugfix: a segmentation fault might occur in worker process, if the + $arg_... variables were used; the bug had appeared in 0.7.48. + + +Changes with nginx 0.7.48 06 Apr 2009 + + *) Feature: the "proxy_cache_key" directive. + + *) Bugfix: now nginx takes into account the "X-Accel-Expires", + "Expires", and "Cache-Control" header lines in a backend response. + + *) Bugfix: now nginx caches responses for the GET requests only. + + *) Bugfix: the "fastcgi_cache_key" directive was not inherited. + + *) Bugfix: the $arg_... variables did not work with SSI subrequests. + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not be built with uclibc library. + Thanks to Timothy Redaelli. + + *) Bugfix: nginx could not be built on OpenBSD; the bug had + appeared in 0.7.46. + + +Changes with nginx 0.7.47 01 Apr 2009 + + *) Bugfix: nginx could not be built on FreeBSD 6 and early versions; the + bug had appeared in 0.7.46. + + *) Bugfix: nginx could not be built on MacOSX; the bug had + appeared in 0.7.46. + + *) Bugfix: if the "max_size" parameter was set, then the cache manager + might purge a whole cache; the bug had appeared in 0.7.46. + + *) Change: a segmentation fault might occur in worker process, if the + "proxy_cache"/"fastcgi_cache" and the "proxy_cache_valid"/ + "fastcgi_cache_valid" were set on different levels; the bug had + appeared in 0.7.46. + + *) Bugfix: a segmentation fault might occur in worker process, if a + request was redirected to a proxied or FastCGI server via error_page + or try_files; the bug had appeared in 0.7.44. + + +Changes with nginx 0.7.46 30 Mar 2009 + + *) Bugfix: the previous release tarball was incorrect. + + +Changes with nginx 0.7.45 30 Mar 2009 + + *) Change: now the "proxy_cache" and the "proxy_cache_valid" directives + can be set on different levels. + + *) Change: the "clean_time" parameter of the "proxy_cache_path" + directive is canceled. + + *) Feature: the "max_size" parameter of the "proxy_cache_path" + directive. + + *) Feature: the ngx_http_fastcgi_module preliminary cache support. + + *) Feature: now on shared memory allocation errors directive and zone + names are logged. + + *) Bugfix: the directive "add_header last-modified ''" did not delete a + "Last-Modified" response header line; the bug had appeared in 0.7.44. + + *) Bugfix: a relative path in the "auth_basic_user_file" directive given + without variables did not work; the bug had appeared in 0.7.44. + Thanks to Jerome Loyet. + + *) Bugfix: in an "alias" directive given using variables without + references to captures of regular expressions; the bug had appeared + in 0.7.42. + + +Changes with nginx 0.7.44 23 Mar 2009 + + *) Feature: the ngx_http_proxy_module preliminary cache support. + + *) Feature: the --with-pcre option in the configure. + + *) Feature: the "try_files" directive is now allowed on the server block + level. + + *) Bugfix: the "try_files" directive handled incorrectly a query string + in a fallback parameter. + + *) Bugfix: the "try_files" directive might test incorrectly directories. + + *) Bugfix: if there was a single server for given address:port pair, + then captures in regular expressions in a "server_name" directive did + not work. + + +Changes with nginx 0.7.43 18 Mar 2009 + + *) Bugfix: a request was handled incorrectly, if a "root" directive used + variables; the bug had appeared in 0.7.42. + + *) Bugfix: if a server listened on wildcard address, then the + $server_addr variable value was "0.0.0.0"; the bug had appeared in + 0.7.36. + + +Changes with nginx 0.7.42 16 Mar 2009 + + *) Change: now the "Invalid argument" error returned by + setsockopt(TCP_NODELAY) on Solaris, is ignored. + + *) Change: now if a file specified in a "auth_basic_user_file" directive + is absent, then the 403 error is returned instead of the 500 one. + + *) Feature: the "auth_basic_user_file" directive supports variables. + Thanks to Kirill A. Korinskiy. + + *) Feature: the "listen" directive supports the "ipv6only" parameter. + Thanks to Zhang Hua. + + *) Bugfix: in an "alias" directive with references to captures of + regular expressions; the bug had appeared in 0.7.40. + + *) Bugfix: compatibility with Tru64 UNIX. + Thanks to Dustin Marquess. + + *) Bugfix: nginx could not be built without PCRE library; the bug had + appeared in 0.7.41. + + +Changes with nginx 0.7.41 11 Mar 2009 + + *) Bugfix: a segmentation fault might occur in worker process, if a + "server_name" or a "location" directives had captures in regular + expressions; the issue had appeared in 0.7.40. + Thanks to Vladimir Sopot. + + +Changes with nginx 0.7.40 09 Mar 2009 + + *) Feature: the "location" directive supports captures in regular + expressions. + + *) Feature: an "alias" directive with capture references may be used + inside a location given by a regular expression with captures. + + *) Feature: the "server_name" directive supports captures in regular + expressions. + + *) Workaround: the ngx_http_autoindex_module did not show the trailing + slash in directories on XFS filesystem; the issue had appeared in + 0.7.15. + Thanks to Dmitry Kuzmenko. + + +Changes with nginx 0.7.39 02 Mar 2009 + + *) Bugfix: large response with SSI might hang, if gzipping was enabled; + the bug had appeared in 0.7.28. + Thanks to Artem Bokhan. + + *) Bugfix: a segmentation fault might occur in worker process, if short + static variants are used in a "try_files" directive. + + +Changes with nginx 0.7.38 23 Feb 2009 + + *) Feature: authentication failures logging. + + *) Bugfix: name/password in auth_basic_user_file were ignored after odd + number of empty lines. + Thanks to Alexander Zagrebin. + + *) Bugfix: a segmentation fault occurred in a master process, if long + path was used in unix domain socket; the bug had appeared in 0.7.36. + + +Changes with nginx 0.7.37 21 Feb 2009 + + *) Bugfix: directives using upstreams did not work; the bug had appeared + in 0.7.36. + + +Changes with nginx 0.7.36 21 Feb 2009 + + *) Feature: a preliminary IPv6 support; the "listen" directive of the + HTTP module supports IPv6. + + *) Bugfix: the $ancient_browser variable did not work for browsers + preset by a "modern_browser" directives. + + +Changes with nginx 0.7.35 16 Feb 2009 + + *) Bugfix: a "ssl_engine" directive did not use a SSL-accelerator for + asymmetric ciphers. + Thanks to Marcin Gozdalik. + + *) Bugfix: a "try_files" directive set MIME type depending on an + original request extension. + + *) Bugfix: "*domain.tld" names were handled incorrectly in + "server_name", "valid_referers", and "map" directives, if + ".domain.tld" and ".subdomain.domain.tld" wildcards were used; + the bug had appeared in 0.7.9. + + +Changes with nginx 0.7.34 10 Feb 2009 + + *) Feature: the "off" parameter of the "if_modified_since" directive. + + *) Feature: now nginx sends an HELO/EHLO command after a XCLIENT + command. + Thanks to Maxim Dounin. + + *) Feature: Microsoft specific "AUTH LOGIN with User Name" mode support + in mail proxy server. + Thanks to Maxim Dounin. + + *) Bugfix: in a redirect rewrite directive original arguments were + concatenated with new arguments by a "?" rather than an "&"; + the bug had appeared in 0.1.18. + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not be built on AIX. + + +Changes with nginx 0.7.33 02 Feb 2009 + + *) Bugfix: a double response might be returned if the epoll or rtsig + methods are used and a redirect was returned to a request with body. + Thanks to Eden Li. + + *) Bugfix: the $sent_http_location variable was empty for some redirects + types. + + *) Bugfix: a segmentation fault might occur in worker process if + "resolver" directive was used in SMTP proxy. + + +Changes with nginx 0.7.32 26 Jan 2009 + + *) Feature: now a directory existence testing can be set explicitly in + the "try_files" directive. + + *) Bugfix: fastcgi_store stored files not always. + + *) Bugfix: in geo ranges. + + *) Bugfix: in shared memory allocations if nginx was built without + debugging. + Thanks to Andrey Kvasov. + + +Changes with nginx 0.7.31 19 Jan 2009 + + *) Change: now the "try_files" directive tests files only and ignores + directories. + + *) Feature: the "fastcgi_split_path_info" directive. + + *) Bugfixes in an "Expect" request header line support. + + *) Bugfixes in geo ranges. + + *) Bugfix: in a miss case ngx_http_memcached_module returned the "END" + line as response body instead of default 404 page body; the bug had + appeared in 0.7.18. + Thanks to Maxim Dounin. + + *) Bugfix: while SMTP proxying nginx issued message "250 2.0.0 OK" + instead of "235 2.0.0 OK"; the bug had appeared in 0.7.22. + Thanks to Maxim Dounin. + + +Changes with nginx 0.7.30 24 Dec 2008 + + *) Bugfix: a segmentation fault occurred in worker process, if variables + were used in the "fastcgi_pass" or "proxy_pass" directives and host + name must be resolved; the bug had appeared in 0.7.29. + + +Changes with nginx 0.7.29 24 Dec 2008 + + *) Bugfix: the "fastcgi_pass" and "proxy_pass" directives did not + support variables if unix domain sockets were used. + + *) Bugfixes in subrequest processing; the bugs had appeared in 0.7.25. + + *) Bugfix: a "100 Continue" response was issued for HTTP/1.0 requests; + Thanks to Maxim Dounin. + + *) Bugfix: in memory allocation in the ngx_http_gzip_filter_module on + Cygwin. + + +Changes with nginx 0.7.28 22 Dec 2008 + + *) Change: in memory allocation in the ngx_http_gzip_filter_module. + + *) Change: the default "gzip_buffers" directive values have been changed + to 32 4k or 16 8k from 4 4k/8k. + + +Changes with nginx 0.7.27 15 Dec 2008 + + *) Feature: the "try_files" directive. + + *) Feature: variables support in the "fastcgi_pass" directive. + + *) Feature: now the $geo variable may get an address from a variable. + Thanks to Andrei Nigmatulin. + + *) Feature: now a location's modifier may be used without space before + name. + + *) Feature: the $upstream_response_length variable. + + *) Bugfix: now a "add_header" directive does not add an empty value. + + *) Bugfix: if zero length static file was requested, then nginx just + closed connection; the bug had appeared in 0.7.25. + + *) Bugfix: a MOVE method could not move file in non-existent directory. + + *) Bugfix: a segmentation fault occurred in worker process, if no one + named location was defined in server, but some one was used in an + error_page directive. + Thanks to Sergey Bochenkov. + + +Changes with nginx 0.7.26 08 Dec 2008 + + *) Bugfix: in subrequest processing; the bug had appeared in 0.7.25. + + +Changes with nginx 0.7.25 08 Dec 2008 + + *) Change: in subrequest processing. + + *) Change: now POSTs without "Content-Length" header line are allowed. + + *) Bugfix: now the "limit_req" and "limit_conn" directives log a + prohibition reason. + + *) Bugfix: in the "delete" parameter of the "geo" directive. + + +Changes with nginx 0.7.24 01 Dec 2008 + + *) Feature: the "if_modified_since" directive. + + *) Bugfix: nginx did not process a FastCGI server response, if the + server send too many messages to stderr before response. + + *) Bugfix: the "$cookie_..." variables did not work in the SSI and the + perl module. + + +Changes with nginx 0.7.23 27 Nov 2008 + + *) Feature: the "delete" and "ranges" parameters in the "geo" directive. + + *) Feature: speeding up loading of geo base with large number of values. + + *) Feature: decrease of memory required for geo base load. + + +Changes with nginx 0.7.22 20 Nov 2008 + + *) Feature: the "none" parameter in the "smtp_auth" directive. + Thanks to Maxim Dounin. + + *) Feature: the "$cookie_..." variables. + + *) Bugfix: the "directio" directive did not work in XFS filesystem. + + *) Bugfix: the resolver did not understand big DNS responses. + Thanks to Zyb. + + +Changes with nginx 0.7.21 11 Nov 2008 + + *) Changes in the ngx_http_limit_req_module. + + *) Feature: the EXSLT support in the ngx_http_xslt_module. + Thanks to Denis F. Latypoff. + + *) Workaround: compatibility with glibc 2.3. + Thanks to Eric Benson and Maxim Dounin. + + *) Bugfix: nginx could not run on MacOSX 10.4 and earlier; the bug had + appeared in 0.7.6. + + +Changes with nginx 0.7.20 10 Nov 2008 + + *) Changes in the ngx_http_gzip_filter_module. + + *) Feature: the ngx_http_limit_req_module. + + *) Bugfix: worker processes might exit on a SIGBUS signal on sparc and + ppc platforms; the bug had appeared in 0.7.3. + Thanks to Maxim Dounin. + + *) Bugfix: the "proxy_pass http://host/some:uri" directives did not + work; the bug had appeared in 0.7.12. + + *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" + error. + + *) Bugfix: the ngx_http_secure_link_module did not work inside + locations, whose names are less than 3 characters. + + *) Bugfix: $server_addr variable might have no value. + + +Changes with nginx 0.7.19 13 Oct 2008 + + *) Bugfix: version number update. + + +Changes with nginx 0.7.18 13 Oct 2008 + + *) Change: the "underscores_in_headers" directive; now nginx does not + allows underscores in a client request header line names. + + *) Feature: the ngx_http_secure_link_module. + + *) Feature: the "real_ip_header" directive supports any header. + + *) Feature: the "log_subrequest" directive. + + *) Feature: the $realpath_root variable. + + *) Feature: the "http_502" and "http_504" parameters of the + "proxy_next_upstream" directive. + + *) Bugfix: the "http_503" parameter of the "proxy_next_upstream" or + "fastcgi_next_upstream" directives did not work. + + *) Bugfix: nginx might send a "Transfer-Encoding: chunked" header line + for HEAD requests. + + *) Bugfix: now accept threshold depends on worker_connections. + + +Changes with nginx 0.7.17 15 Sep 2008 + + *) Feature: now the "directio" directive works on Linux. + + *) Feature: the $pid variable. + + *) Bugfix: the "directio" optimization that had appeared in 0.7.15 did + not work with open_file_cache. + + *) Bugfix: the "access_log" with variables did not work on Linux; the + bug had appeared in 0.7.7. + + *) Bugfix: the ngx_http_charset_module did not understand quoted charset + name received from backend. + + +Changes with nginx 0.7.16 08 Sep 2008 + + *) Bugfix: nginx could not be built on 64-bit platforms; the bug had + appeared in 0.7.15. + + +Changes with nginx 0.7.15 08 Sep 2008 + + *) Feature: the ngx_http_random_index_module. + + *) Feature: the "directio" directive has been optimized for file + requests starting from arbitrary position. + + *) Feature: the "directio" directive turns off sendfile if it is + necessary. + + *) Feature: now nginx allows underscores in a client request header line + names. + + +Changes with nginx 0.7.14 01 Sep 2008 + + *) Change: now the ssl_certificate and ssl_certificate_key directives + have no default values. + + *) Feature: the "listen" directive supports the "ssl" parameter. + + *) Feature: now nginx takes into account a time zone change while + reconfiguration on FreeBSD and Linux. + + *) Bugfix: the "listen" directive parameters such as "backlog", + "rcvbuf", etc. were not set, if a default server was not the first + one. + + *) Bugfix: if URI part captured by a "rewrite" directive was used as a + query string, then the query string was not escaped. + + *) Bugfix: configuration file validity test improvements. + + +Changes with nginx 0.7.13 26 Aug 2008 + + *) Bugfix: nginx could not be built on Linux and Solaris; the bug had + appeared in 0.7.12. + + +Changes with nginx 0.7.12 26 Aug 2008 + + *) Feature: the "server_name" directive supports empty name "". + + *) Feature: the "gzip_disable" directive supports special "msie6" mask. + + *) Bugfix: if the "max_fails=0" parameter was used in upstream with + several servers, then a worker process exited on a SIGFPE signal. + Thanks to Maxim Dounin. + + *) Bugfix: a request body was dropped while redirection via an + "error_page" directive. + + *) Bugfix: a full response was returned for request method HEAD while + redirection via an "error_page" directive. + + *) Bugfix: the $r->header_in() method did not return value of the + "Host", "User-Agent", and "Connection" request header lines; the bug + had appeared in 0.7.0. + + +Changes with nginx 0.7.11 18 Aug 2008 + + *) Change: now ngx_http_charset_module does not work by default with + text/css MIME type. + + *) Feature: now nginx returns the 405 status code for POST method + requesting a static file only if the file exists. + + *) Feature: the "proxy_ssl_session_reuse" directive. + + *) Bugfix: a "proxy_pass" directive without URI part might use original + request after the "X-Accel-Redirect" redirection was used. + + *) Bugfix: if a directory has search only rights and the first index + file was absent, then nginx returned the 500 status code. + + *) Bugfix: in inclusive locations; the bugs had appeared in 0.7.1. + + +Changes with nginx 0.7.10 13 Aug 2008 + + *) Bugfix: in the "addition_types", "charset_types", "gzip_types", + "ssi_types", "sub_filter_types", and "xslt_types" directives; the + bugs had appeared in 0.7.9. + + *) Bugfix: of recursive error_page for 500 status code. + + *) Bugfix: now the ngx_http_realip_module sets address not for whole + keepalive connection, but for each request passed via the connection. + + +Changes with nginx 0.7.9 12 Aug 2008 + + *) Change: now ngx_http_charset_module works by default with following + MIME types: text/html, text/css, text/xml, text/plain, + text/vnd.wap.wml, application/x-javascript, and application/rss+xml. + + *) Feature: the "charset_types" and "addition_types" directives. + + *) Feature: now the "gzip_types", "ssi_types", and "sub_filter_types" + directives use hash. + + *) Feature: the ngx_cpp_test_module. + + *) Feature: the "expires" directive supports daily time. + + *) Feature: the ngx_http_xslt_module improvements and bug fixing. + Thanks to Denis F. Latypoff and Maxim Dounin. + + *) Bugfix: the "log_not_found" directive did not work for index files + tests. + + *) Bugfix: HTTPS connections might hang, if kqueue, epoll, rtsig, or + eventport methods were used; the bug had appeared in 0.7.7. + + *) Bugfix: if the "server_name", "valid_referers", and "map" directives + used an "*.domain.tld" wildcard and exact name "domain.tld" was not + set, then the exact name was matched by the wildcard; the bug had + appeared in 0.3.18. + + +Changes with nginx 0.7.8 04 Aug 2008 + + *) Feature: the ngx_http_xslt_module. + + *) Feature: the "$arg_..." variables. + + *) Feature: Solaris directio support. + Thanks to Ivan Debnar. + + *) Bugfix: now if FastCGI server sends a "Location" header line without + status line, then nginx uses 302 status code. + Thanks to Maxim Dounin. + + +Changes with nginx 0.7.7 30 Jul 2008 + + *) Change: now the EAGAIN error returned by connect() is not considered + as temporary error. + + *) Change: now the $ssl_client_cert variable value is a certificate with + TAB character intended before each line except first one; an + unchanged certificate is available in the $ssl_client_raw_cert + variable. + + *) Feature: the "ask" parameter in the "ssl_verify_client" directive. + + *) Feature: byte-range processing improvements. + Thanks to Maxim Dounin. + + *) Feature: the "directio" directive. + Thanks to Jiang Hong. + + *) Feature: MacOSX 10.5 sendfile() support. + + *) Bugfix: now in MacOSX and Cygwin locations are tested in case + insensitive mode; however, the compare is provided by single-byte + locales only. + + *) Bugfix: mail proxy SSL connections hanged, if select, poll, or + /dev/poll methods were used. + + *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module. + + +Changes with nginx 0.7.6 07 Jul 2008 + + *) Bugfix: now if variables are used in the "access_log" directive a + request root existence is always tested. + + *) Bugfix: the ngx_http_flv_module did not support several values in a + query string. + + +Changes with nginx 0.7.5 01 Jul 2008 + + *) Bugfixes in variables support in the "access_log" directive; the bugs + had appeared in 0.7.4. + + *) Bugfix: nginx could not be built --without-http_gzip_module; the bug + had appeared in 0.7.3. + Thanks to Kirill A. Korinskiy. + + *) Bugfix: if sub_filter and SSI were used together, then responses + might were transferred incorrectly. + + +Changes with nginx 0.7.4 30 Jun 2008 + + *) Feature: variables support in the "access_log" directive. + + *) Feature: the "open_log_file_cache" directive. + + *) Feature: the -g switch. + + *) Feature: the "Expect" request header line support. + + *) Bugfix: large SSI inclusions might be truncated. + + +Changes with nginx 0.7.3 23 Jun 2008 + + *) Change: the "rss" extension MIME type has been changed to + "application/rss+xml". + + *) Change: now the "gzip_vary" directive turned on issues a + "Vary: Accept-Encoding" header line for uncompressed responses too. + + *) Feature: now the "rewrite" directive does a redirect automatically if + the "https://" protocol is used. + + *) Bugfix: the "proxy_pass" directive did not work with the HTTPS + protocol; the bug had appeared in 0.6.9. + + +Changes with nginx 0.7.2 16 Jun 2008 + + *) Feature: now nginx supports EDH key exchange ciphers. + + *) Feature: the "ssl_dhparam" directive. + + *) Feature: the $ssl_client_cert variable. + Thanks to Manlio Perillo. + + *) Bugfix: after changing URI via a "rewrite" directive nginx did not + search a new location; the bug had appeared in 0.7.1. + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not be built without PCRE library; the bug had + appeared in 0.7.1. + + *) Bugfix: when a request to a directory was redirected with the slash + added, nginx dropped a query string from the original request. + + +Changes with nginx 0.7.1 26 May 2008 + + *) Change: now locations are searched in a tree. + + *) Change: the "optimize_server_names" directive was canceled due to the + "server_name_in_redirect" directive introduction. + + *) Change: some long deprecated directives are not supported anymore. + + *) Change: the "none" parameter in the "ssl_session_cache" directive; + now this is default parameter. + Thanks to Rob Mueller. + + *) Bugfix: worker processes might not catch reconfiguration and log + rotation signals. + + *) Bugfix: nginx could not be built on latest Fedora 9 Linux. + Thanks to Roxis. + + +Changes with nginx 0.7.0 19 May 2008 + + *) Change: now the 0x00-0x1F, '"' and '\' characters are escaped as \xXX + in an access_log. + Thanks to Maxim Dounin. + + *) Change: now nginx allows several "Host" request header line. + + *) Feature: the "modified" flag in the "expires" directive. + + *) Feature: the $uid_got and $uid_set variables may be used at any + request processing stage. + + *) Feature: the $hostname variable. + Thanks to Andrei Nigmatulin. + + *) Feature: DESTDIR support. + Thanks to Todd A. Fisher and Andras Voroskoi. + + *) Bugfix: a segmentation fault might occur in worker process on Linux, + if keepalive was enabled. + + +Changes with nginx 0.6.31 12 May 2008 + + *) Bugfix: nginx did not process FastCGI response if header was at the + end of FastCGI record; the bug had appeared in 0.6.2. + Thanks to Sergey Serov. + + *) Bugfix: a segmentation fault might occur in worker process if a file + was deleted and the "open_file_cache_errors" directive was off. + + +Changes with nginx 0.6.30 29 Apr 2008 + + *) Change: now if an "include" directive pattern does not match any + file, then nginx does not issue an error. + + *) Feature: now the time in directives may be specified without spaces, + for example, "1h50m". + + *) Bugfix: memory leaks if the "ssl_verify_client" directive was on. + Thanks to Chavelle Vincent. + + *) Bugfix: the "sub_filter" directive might set text to change into + output. + + *) Bugfix: the "error_page" directive did not take into account + arguments in redirected URI. + + *) Bugfix: now nginx always opens files in binary mode under Cygwin. + + *) Bugfix: nginx could not be built on OpenBSD; the bug had appeared in + 0.6.15. + + +Changes with nginx 0.6.29 18 Mar 2008 + + *) Feature: the ngx_google_perftools_module. + + *) Bugfix: the ngx_http_perl_module could not be built on 64-bit + platforms; the bug had appeared in 0.6.27. + + +Changes with nginx 0.6.28 13 Mar 2008 + + *) Bugfix: the rtsig method could not be built; the bug had appeared in + 0.6.27. + + +Changes with nginx 0.6.27 12 Mar 2008 + + *) Change: now by default the rtsig method is not built on + Linux 2.6.18+. + + *) Change: now a request method is not changed while redirection to a + named location via an "error_page" directive. + + *) Feature: the "resolver" and "resolver_timeout" directives in SMTP + proxy. + + *) Feature: the "post_action" directive supports named locations. + + *) Bugfix: a segmentation fault occurred in worker process, if a request + was redirected from proxy, FastCGI, or memcached location to static + named locations. + + *) Bugfix: browsers did not repeat SSL handshake if there is no valid + client certificate in first handshake. + Thanks to Alexander V. Inyukhin. + + *) Bugfix: if response code 495-497 was redirected via an "error_page" + directive without code change, then nginx tried to allocate too many + memory. + + *) Bugfix: memory leak in long-lived non buffered connections. + + *) Bugfix: memory leak in resolver. + + *) Bugfix: a segmentation fault occurred in worker process, if a request + was redirected from proxy, FastCGI, or memcached location to static + named locations. + + *) Bugfix: in the $proxy_host and $proxy_port variables caching. + Thanks to Sergey Bochenkov. + + *) Bugfix: a "proxy_pass" directive with variables used incorrectly the + same port as in another "proxy_pass" directive with the same host + name and without variables. + Thanks to Sergey Bochenkov. + + *) Bugfix: an alert "sendmsg() failed (9: Bad file descriptor)" on some + 64-bit platforms while reconfiguration. + + *) Bugfix: a segmentation fault occurred in worker process, if empty + stub block was used second time in SSI. + + *) Bugfix: in copying URI part contained escaped symbols into arguments. + + +Changes with nginx 0.6.26 11 Feb 2008 + + *) Bugfix: the "proxy_store" and "fastcgi_store" directives did not + check a response length. + + *) Bugfix: a segmentation fault occurred in worker process, if big value + was used in a "expires" directive. + Thanks to Joaquin Cuenca Abela. + + *) Bugfix: nginx incorrectly detected cache line size on Pentium 4. + Thanks to Gena Makhomed. + + *) Bugfix: in proxied or FastCGI subrequests a client original method + was used instead of the GET method. + + *) Bugfix: socket leak in HTTPS mode if deferred accept was used. + Thanks to Ben Maurer. + + *) Bugfix: nginx issued the bogus error message "SSL_shutdown() failed + (SSL: )"; the bug had appeared in 0.6.23. + + *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" + error; the bug had appeared in 0.6.23. + + +Changes with nginx 0.6.25 08 Jan 2008 + + *) Change: now the "server_name_in_redirect" directive is used instead + of the "server_name" directive's special "*" parameter. + + *) Change: now wildcard and regex names can be used as main name in a + "server_name" directive. + + *) Change: the "satisfy_any" directive was replaced by the "satisfy" + directive. + + *) Workaround: old worker processes might hog CPU after reconfiguration + if they was run under Linux OpenVZ. + + *) Feature: the "min_delete_depth" directive. + + *) Bugfix: the COPY and MOVE methods did not work with single files. + + *) Bugfix: the ngx_http_gzip_static_module did not allow the + ngx_http_dav_module to work; the bug had appeared in 0.6.23. + + *) Bugfix: socket leak in HTTPS mode if deferred accept was used. + Thanks to Ben Maurer. + + *) Bugfix: nginx could not be built without PCRE library; the bug had + appeared in 0.6.23. + + +Changes with nginx 0.6.24 27 Dec 2007 + + *) Bugfix: a segmentation fault might occur in worker process if HTTPS + was used; the bug had appeared in 0.6.23. + + +Changes with nginx 0.6.23 27 Dec 2007 + + *) Change: the "off" parameter in the "ssl_session_cache" directive; now + this is default parameter. + + *) Change: the "open_file_cache_retest" directive was renamed to the + "open_file_cache_valid". + + *) Feature: the "open_file_cache_min_uses" directive. + + *) Feature: the ngx_http_gzip_static_module. + + *) Feature: the "gzip_disable" directive. + + *) Feature: the "memcached_pass" directive may be used inside the "if" + block. + + *) Bugfix: a segmentation fault occurred in worker process, if the + "memcached_pass" and "if" directives were used in the same location. + + *) Bugfix: if a "satisfy_any on" directive was used and not all access + and auth modules directives were set, then other given access and + auth directives were not tested; + + *) Bugfix: regex parameters in a "valid_referers" directive were not + inherited from previous level. + + *) Bugfix: a "post_action" directive did run if a request was completed + with 499 status code. + + *) Bugfix: optimization of 16K buffer usage in a SSL connection. + Thanks to Ben Maurer. + + *) Bugfix: the STARTTLS in SMTP mode did not work. + Thanks to Oleg Motienko. + + *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" + error; the bug had appeared in 0.5.13. + + +Changes with nginx 0.6.22 19 Dec 2007 + + *) Change: now all ngx_http_perl_module methods return values copied to + perl's allocated memory. + + *) Bugfix: if nginx was built with ngx_http_perl_module, the perl before + 5.8.6 was used, and perl supported threads, then during + reconfiguration the master process aborted; the bug had appeared in + 0.5.9. + Thanks to Boris Zhmurov. + + *) Bugfix: the ngx_http_perl_module methods may get invalid values of + the regex captures. + + *) Bugfix: a segmentation fault occurred in worker process, if the + $r->has_request_body() method was called for a request whose small + request body was already received. + + *) Bugfix: large_client_header_buffers did not freed before going to + keep-alive state. + Thanks to Olexander Shtepa. + + *) Bugfix: the last address was missed in the $upstream_addr variable; + the bug had appeared in 0.6.18. + + *) Bugfix: the "fastcgi_catch_stderr" directive did return error code; + now it returns 502 code, that can be rerouted to a next server using + the "fastcgi_next_upstream invalid_header" directive. + + *) Bugfix: a segmentation fault occurred in master process if the + "fastcgi_catch_stderr" directive was used; the bug had appeared in + 0.6.10. + Thanks to Manlio Perillo. + + +Changes with nginx 0.6.21 03 Dec 2007 + + *) Change: if variable values used in a "proxy_pass" directive contain + IP-addresses only, then a "resolver" directive is not mandatory. + + *) Bugfix: a segmentation fault might occur in worker process if a + "proxy_pass" directive with URI-part was used; the bug had appeared + in 0.6.19. + + *) Bugfix: if resolver was used on platform that does not support + kqueue, then nginx issued an alert "name is out of response". + Thanks to Andrei Nigmatulin. + + *) Bugfix: if the $server_protocol was used in FastCGI parameters and a + request line length was near to the "client_header_buffer_size" + directive value, then nginx issued an alert "fastcgi: the request + record is too big". + + *) Bugfix: if a plain text HTTP/0.9 version request was made to HTTPS + server, then nginx returned usual response. + + +Changes with nginx 0.6.20 28 Nov 2007 + + *) Bugfix: a segmentation fault might occur in worker process if a + "proxy_pass" directive with URI-part was used; the bug had appeared + in 0.6.19. + + +Changes with nginx 0.6.19 27 Nov 2007 + + *) Bugfix: the 0.6.18 version could not be built. + + +Changes with nginx 0.6.18 27 Nov 2007 + + *) Change: now the ngx_http_userid_module adds start time microseconds + to the cookie field contains a pid value. + + *) Change: now the full request line instead of URI only is written to + error_log. + + *) Feature: variables support in the "proxy_pass" directive. + + *) Feature: the "resolver" and "resolver_timeout" directives. + + *) Feature: now the directive "add_header last-modified ''" deletes a + "Last-Modified" response header line. + + *) Bugfix: the "limit_rate" directive did not allow to use full + throughput, even if limit value was very high. + + +Changes with nginx 0.6.17 15 Nov 2007 + + *) Feature: the "If-Range" request header line support. + Thanks to Alexander V. Inyukhin. + + *) Bugfix: URL double escaping in a redirect of the "msie_refresh" + directive; the bug had appeared in 0.6.4. + + *) Bugfix: the "autoindex" directive did not work with the "alias /" + directive. + + *) Bugfix: a segmentation fault might occur in worker process if + subrequests were used. + + *) Bugfix: the big responses may be transferred truncated if SSL and + gzip were used. + + *) Bugfix: the $status variable was equal to 0 if a proxied server + returned response in HTTP/0.9 version. + + +Changes with nginx 0.6.16 29 Oct 2007 + + *) Change: now the uname(2) is used on Linux instead of procfs. + Thanks to Ilya Novikov. + + *) Bugfix: if the "?" character was in a "error_page" directive, then it + was escaped in a proxied request; the bug had appeared in 0.6.11. + + *) Bugfix: compatibility with mget. + + +Changes with nginx 0.6.15 22 Oct 2007 + + *) Feature: Cygwin compatibility. + Thanks to Vladimir Kutakov. + + *) Feature: the "merge_slashes" directive. + + *) Feature: the "gzip_vary" directive. + + *) Feature: the "server_tokens" directive. + + *) Bugfix: nginx did not unescape URI in the "include" SSI command. + + *) Bugfix: the segmentation fault was occurred on start or while + reconfiguration if variable was used in the "charset" or + "source_charset" directives. + + *) Bugfix: nginx returned the 400 response on requests like + "GET http://www.domain.com HTTP/1.0". + Thanks to James Oakley. + + *) Bugfix: if request with request body was redirected using the + "error_page" directive, then nginx tried to read the request body + again; the bug had appeared in 0.6.7. + + *) Bugfix: a segmentation fault occurred in worker process if no + server_name was explicitly defined for server processing request; the + bug had appeared in 0.6.7. + + +Changes with nginx 0.6.14 15 Oct 2007 + + *) Change: now by default the "echo" SSI command uses entity encoding. + + *) Feature: the "encoding" parameter in the "echo" SSI command. + + *) Feature: the "access_log" directive may be used inside the + "limit_except" block. + + *) Bugfix: if all upstream servers were failed, then all servers had got + weight the was equal one until servers became alive; the bug had + appeared in 0.6.6. + + *) Bugfix: a segmentation fault occurred in worker process if + $date_local and $date_gmt were used outside the + ngx_http_ssi_filter_module. + + *) Bugfix: a segmentation fault might occur in worker process if debug + log was enabled. + Thanks to Andrei Nigmatulin. + + *) Bugfix: ngx_http_memcached_module did not set + $upstream_response_time. + Thanks to Maxim Dounin. + + *) Bugfix: a worker process may got caught in an endless loop, if the + memcached was used. + + *) Bugfix: nginx supported low case only "close" and "keep-alive" values + in the "Connection" request header line; the bug had appeared in + 0.6.11. + + *) Bugfix: sub_filter did not work with empty substitution. + + *) Bugfix: in sub_filter parsing. + + +Changes with nginx 0.6.13 24 Sep 2007 + + *) Bugfix: nginx did not close directory file on HEAD request if + autoindex was used. + Thanks to Arkadiusz Patyk. + + +Changes with nginx 0.6.12 21 Sep 2007 + + *) Change: mail proxy was split on three modules: pop3, imap and smtp. + + *) Feature: the --without-mail_pop3_module, --without-mail_imap_module, + and --without-mail_smtp_module configuration parameters. + + *) Feature: the "smtp_greeting_delay" and "smtp_client_buffer" + directives of the ngx_mail_smtp_module. + + *) Bugfix: the trailing wildcards did not work; the bug had appeared in + 0.6.9. + + *) Bugfix: nginx could not start on Solaris if the shared PCRE library + located in non-standard place was used. + + *) Bugfix: the "proxy_hide_header" and "fastcgi_hide_header" directives + did not hide response header lines whose name was longer than 32 + characters. + Thanks to Manlio Perillo. + + +Changes with nginx 0.6.11 11 Sep 2007 + + *) Bugfix: active connection counter always increased if mail proxy was + used. + + *) Bugfix: if backend returned response header only using non-buffered + proxy, then nginx closed backend connection on timeout. + + *) Bugfix: nginx did not support several "Connection" request header + lines. + + *) Bugfix: if the "max_fails" was set for upstream server, then after + first failure server weight was always one; the bug had appeared in + 0.6.6. + + +Changes with nginx 0.6.10 03 Sep 2007 + + *) Feature: the "open_file_cache", "open_file_cache_retest", and + "open_file_cache_errors" directives. + + *) Bugfix: socket leak; the bug had appeared in 0.6.7. + + *) Bugfix: a charset set by the "charset" directive was not appended to + the "Content-Type" header set by $r->send_http_header(). + + *) Bugfix: a segmentation fault might occur in worker process if + /dev/poll method was used. + + +Changes with nginx 0.6.9 28 Aug 2007 + + *) Bugfix: a worker process may got caught in an endless loop, if the + HTTPS protocol was used; the bug had appeared in 0.6.7. + + *) Bugfix: if server listened on two addresses or ports and trailing + wildcard was used, then nginx did not run. + + *) Bugfix: the "ip_hash" directive might incorrectly mark servers as + down. + + *) Bugfix: nginx could not be built on amd64; the bug had appeared in + 0.6.8. + + +Changes with nginx 0.6.8 20 Aug 2007 + + *) Change: now nginx tries to set the "worker_priority", + "worker_rlimit_nofile", "worker_rlimit_core", and + "worker_rlimit_sigpending" without super-user privileges. + + *) Change: now nginx escapes space and "%" in request to a mail proxy + authentication server. + + *) Change: now nginx escapes "%" in $memcached_key variable. + + *) Bugfix: nginx used path relative to configuration prefix for + non-absolute configuration file path specified in the "-c" key; the + bug had appeared in 0.6.6. + + *) Bugfix: nginx did not work on FreeBSD/sparc64. + + +Changes with nginx 0.6.7 15 Aug 2007 + + *) Change: now the paths specified in the "include", + "auth_basic_user_file", "perl_modules", "ssl_certificate", + "ssl_certificate_key", and "ssl_client_certificate" directives are + relative to directory of nginx configuration file nginx.conf, but not + to nginx prefix directory. + + *) Change: the --sysconfdir=PATH option in configure was canceled. + + *) Change: the special make target "upgrade1" was defined for online + upgrade of 0.1.x versions. + + *) Feature: the "server_name" and "valid_referers" directives support + regular expressions. + + *) Feature: the "server" directive in the "upstream" context supports + the "backup" parameter. + + *) Feature: the ngx_http_perl_module supports the + $r->discard_request_body. + + *) Feature: the "add_header Last-Modified ..." directive changes the + "Last-Modified" response header line. + + *) Bugfix: if a response different than 200 was returned to a request + with body and connection went to the keep-alive state after the + request, then nginx returned 400 for the next request. + + *) Bugfix: a segmentation fault occurred in worker process if invalid + address was set in the "auth_http" directive. + + *) Bugfix: now nginx uses default listen backlog value 511 on all + platforms except FreeBSD. + Thanks to Jiang Hong. + + *) Bugfix: a worker process may got caught in an endless loop, if a + "server" inside "upstream" block was marked as "down"; the bug had + appeared in 0.6.6. + + *) Bugfix: now Solaris sendfilev() is not used to transfer the client + request body to FastCGI-server via the unix domain socket. + + +Changes with nginx 0.6.6 30 Jul 2007 + + *) Feature: the --sysconfdir=PATH option in configure. + + *) Feature: named locations. + + *) Feature: the $args variable can be set with the "set" directive. + + *) Feature: the $is_args variable. + + *) Bugfix: fair big weight upstream balancer. + + *) Bugfix: if a client has closed connection to mail proxy then nginx + might not close connection to backend. + + *) Bugfix: if the same host without specified port was used as backend + for HTTP and HTTPS, then nginx used only one port - 80 or 443. + + *) Bugfix: fix building on Solaris/amd64 by Sun Studio 11 and early + versions; the bug had appeared in 0.6.4. + + +Changes with nginx 0.6.5 23 Jul 2007 + + *) Feature: $nginx_version variable. + Thanks to Nick S. Grechukh. + + *) Feature: the mail proxy supports AUTHENTICATE in IMAP mode. + Thanks to Maxim Dounin. + + *) Feature: the mail proxy supports STARTTLS in SMTP mode. + Thanks to Maxim Dounin. + + *) Bugfix: now nginx escapes space in $memcached_key variable. + + *) Bugfix: nginx was incorrectly built by Sun Studio on Solaris/amd64. + Thanks to Jiang Hong. + + *) Bugfix: of minor potential bugs. + Thanks to Coverity's Scan. + + +Changes with nginx 0.6.4 17 Jul 2007 + + *) Security: the "msie_refresh" directive allowed XSS. + Thanks to Maxim Boguk. + + *) Change: the "proxy_store" and "fastcgi_store" directives were + changed. + + *) Feature: the "proxy_store_access" and "fastcgi_store_access" + directives. + + *) Bugfix: nginx did not work on Solaris/sparc64 if it was built by Sun + Studio. + Thanks to Andrei Nigmatulin. + + *) Workaround: for Sun Studio 12. + Thanks to Jiang Hong. + + +Changes with nginx 0.6.3 12 Jul 2007 + + *) Feature: the "proxy_store" and "fastcgi_store" directives. + + *) Bugfix: a segmentation fault might occur in worker process if the + "auth_http_header" directive was used. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault occurred in worker process if the + CRAM-MD5 authentication method was used, but it was not enabled. + + *) Bugfix: a segmentation fault might occur in worker process when the + HTTPS protocol was used in the "proxy_pass" directive. + + *) Bugfix: a segmentation fault might occur in worker process if the + eventport method was used. + + *) Bugfix: the "proxy_ignore_client_abort" and + "fastcgi_ignore_client_abort" directives did not work; the bug had + appeared in 0.5.13. + + +Changes with nginx 0.6.2 09 Jul 2007 + + *) Bugfix: if the FastCGI header was split in records, then nginx passed + garbage in the header to a client. + + +Changes with nginx 0.6.1 17 Jun 2007 + + *) Bugfix: in SSI parsing. + + *) Bugfix: if remote SSI subrequest was used, then posterior local file + subrequest might transferred to client in wrong order. + + *) Bugfix: large SSI inclusions buffered in temporary files were + truncated. + + *) Bugfix: the perl $$ variable value in ngx_http_perl_module was equal + to the master process identification number. + + +Changes with nginx 0.6.0 14 Jun 2007 + + *) Feature: the "server_name", "map", and "valid_referers" directives + support the "www.example.*" wildcards. + + +Changes with nginx 0.5.25 11 Jun 2007 + + *) Bugfix: nginx could not be built with the + --without-http_rewrite_module parameter; the bug had appeared in + 0.5.24. + + +Changes with nginx 0.5.24 06 Jun 2007 + + *) Security: the "ssl_verify_client" directive did not work if request + was made using HTTP/0.9. + + *) Bugfix: a part of response body might be passed uncompressed if gzip + was used; the bug had appeared in 0.5.23. + + +Changes with nginx 0.5.23 04 Jun 2007 + + *) Feature: the ngx_http_ssl_module supports Server Name Indication TLS + extension. + + *) Feature: the "fastcgi_catch_stderr" directive. + Thanks to Nick S. Grechukh, OWOX project. + + *) Bugfix: a segmentation fault occurred in master process if two + virtual servers should bind() to the overlapping ports. + + *) Bugfix: if nginx was built with ngx_http_perl_module and perl + supported threads, then during second reconfiguration the error + messages "panic: MUTEX_LOCK" and "perl_parse() failed" were issued. + + *) Bugfix: in the HTTPS protocol in the "proxy_pass" directive. + + +Changes with nginx 0.5.22 29 May 2007 + + *) Bugfix: a big request body might not be passed to backend; the bug + had appeared in 0.5.21. + + +Changes with nginx 0.5.21 28 May 2007 + + *) Bugfix: if server has more than about ten locations, then regex + locations might be choosen not in that order as they were specified. + + *) Bugfix: a worker process may got caught in an endless loop on 64-bit + platform, if the 33-rd or next in succession backend has failed. + Thanks to Anton Povarov. + + *) Bugfix: a bus error might occur on Solaris/sparc64 if the PCRE + library was used. + Thanks to Andrei Nigmatulin. + + *) Bugfix: in the HTTPS protocol in the "proxy_pass" directive. + + +Changes with nginx 0.5.20 07 May 2007 + + *) Feature: the "sendfile_max_chunk" directive. + + *) Feature: the "$http_...", "$sent_http_...", and "$upstream_http_..." + variables may be changed using the "set" directive. + + *) Bugfix: a segmentation fault might occur in worker process if the SSI + command 'if expr="$var = /"' was used. + + *) Bugfix: trailing boundary of multipart range response was transferred + incorrectly. + Thanks to Evan Miller. + + *) Bugfix: nginx did not work on Solaris/sparc64 if it was built by Sun + Studio. + Thanks to Andrei Nigmatulin. + + *) Bugfix: the ngx_http_perl_module could not be built by Solaris make. + Thanks to Andrei Nigmatulin. + + +Changes with nginx 0.5.19 24 Apr 2007 + + *) Change: now the $request_time variable has millisecond precision. + + *) Change: the method $r->rflush of ngx_http_perl_module was renamed to + the $r->flush. + + *) Feature: the $upstream_addr variable. + + *) Feature: the "proxy_headers_hash_max_size" and + "proxy_headers_hash_bucket_size" directives. + Thanks to Volodymyr Kostyrko. + + *) Bugfix: the files more than 2G could not be transferred using + sendfile and limit_rate on 64-bit platforms. + + *) Bugfix: the files more than 2G could not be transferred using + sendfile on 64-bit Linux. + + +Changes with nginx 0.5.18 19 Apr 2007 + + *) Feature: the ngx_http_sub_filter_module. + + *) Feature: the "$upstream_http_..." variables. + + *) Feature: now the $upstream_status and $upstream_response_time + variables keep data about all upstreams before X-Accel-Redirect. + + *) Bugfix: a segmentation fault occurred in master process after first + reconfiguration and receiving any signal if nginx was built with + ngx_http_perl_module and perl did not support multiplicity; the bug + had appeared in 0.5.9. + + *) Bugfix: if perl did not support multiplicity, then after + reconfiguration perl code did not work; the bug had appeared in + 0.3.38. + + +Changes with nginx 0.5.17 02 Apr 2007 + + *) Change: now nginx always returns the 405 status for the TRACE method. + + *) Feature: now nginx supports the "include" directive inside the + "types" block. + + *) Bugfix: the $document_root variable usage in the "root" and "alias" + directives is disabled: this caused recursive stack overflow. + + *) Bugfix: in the HTTPS protocol in the "proxy_pass" directive. + + *) Bugfix: in some cases non-cachable variables (such as $uri variable) + returned old cached value. + + +Changes with nginx 0.5.16 26 Mar 2007 + + *) Bugfix: the C-class network was not used as hash key in the "ip_hash" + directive. + Thanks to Pavel Yarkovoy. + + *) Bugfix: a segmentation fault might occur in worker process if a + charset was set in the "Content-Type" header line and the line has + trailing ";"; the bug had appeared in 0.3.50. + + *) Bugfix: the "[alert] zero size buf" error when FastCGI server was + used and a request body written in a temporary file was multiple of + 32K. + + *) Bugfix: nginx could not be built on Solaris without the --with-debug + option; the bug had appeared in 0.5.15. + + +Changes with nginx 0.5.15 19 Mar 2007 + + *) Feature: the mail proxy supports authenticated SMTP proxying and the + "smtp_auth", "smtp_capablities", and "xclient" directives. + Thanks to Anton Yuzhaninov and Maxim Dounin. + + *) Feature: now the keep-alive connections are closed just after + receiving the reconfiguration signal. + + *) Change: the "imap" and "auth" directives were renamed to the "mail" + and "pop3_auth" directives. + + *) Bugfix: a segmentation fault occurred in worker process if the + CRAM-MD5 authentication method was used and the APOP method was + disabled. + + *) Bugfix: if the "starttls only" directive was used in POP3 protocol, + then nginx allowed authentication without switching to the SSL mode. + + *) Bugfix: worker processes did not exit after reconfiguration and did + not rotate logs if the eventport method was used. + + *) Bugfix: a worker process may got caught in an endless loop, if the + "ip_hash" directive was used. + + *) Bugfix: now nginx does not log some alerts if eventport or /dev/poll + methods are used. + + +Changes with nginx 0.5.14 23 Feb 2007 + + *) Bugfix: nginx ignored superfluous closing "}" in the end of + configuration file. + + +Changes with nginx 0.5.13 19 Feb 2007 + + *) Feature: the COPY and MOVE methods. + + *) Bugfix: the ngx_http_realip_module set garbage for requests passed + via keep-alive connection. + + *) Bugfix: nginx did not work on big-endian 64-bit Linux. + Thanks to Andrei Nigmatulin. + + *) Bugfix: now when IMAP/POP3 proxy receives too long command it closes + the connection right away, but not after timeout. + + *) Bugfix: if the "epoll" method was used and a client closed a + connection prematurely, then nginx closed the connection after a send + timeout only. + + *) Bugfix: nginx could not be built on platforms different from i386, + amd64, sparc, and ppc; the bug had appeared in 0.5.8. + + +Changes with nginx 0.5.12 12 Feb 2007 + + *) Bugfix: nginx could not be built on platforms different from i386, + amd64, sparc, and ppc; the bug had appeared in 0.5.8. + + *) Bugfix: a segmentation fault might occur in worker process if the + temporary files were used while working with FastCGI server; the bug + had appeared in 0.5.8. + + *) Bugfix: a segmentation fault might occur in worker process if the + $fastcgi_script_name variable was logged. + + *) Bugfix: ngx_http_perl_module could not be built on Solaris. + + +Changes with nginx 0.5.11 05 Feb 2007 + + *) Feature: now configure detects system PCRE library in MacPorts. + Thanks to Chris McGrath. + + *) Bugfix: the response was incorrect if several ranges were requested; + the bug had appeared in 0.5.6. + + *) Bugfix: the "create_full_put_path" directive could not create the + intermediate directories if no "dav_access" directive was set. + Thanks to Evan Miller. + + *) Bugfix: the "0" response code might be logged in the access_log + instead of the "400" and "408" error codes. + + *) Bugfix: a segmentation fault might occur in worker process if nginx + was built with -O2 optimization. + + +Changes with nginx 0.5.10 26 Jan 2007 + + *) Bugfix: while online executable file upgrade the new master process + did not inherit the listening sockets; the bug had appeared in 0.5.9. + + *) Bugfix: a segmentation fault might occur in worker process if nginx + was built with -O2 optimization; the bug had appeared in 0.5.1. + + +Changes with nginx 0.5.9 25 Jan 2007 + + *) Change: now the ngx_http_memcached_module uses the $memcached_key + variable value as a key. + + *) Feature: the $memcached_key variable. + + *) Feature: the "clean" parameter in the "client_body_in_file_only" + directive. + + *) Feature: the "env" directive. + + *) Feature: the "sendfile" directive is available inside the "if" block. + + *) Feature: now on failure of the writing to access nginx logs a message + to error_log, but not more often than once a minute. + + *) Bugfix: the "access_log off" directive did not always turn off the + logging. + + +Changes with nginx 0.5.8 19 Jan 2007 + + *) Bugfix: a segmentation fault might occur if + "client_body_in_file_only on" was used and a request body was small. + + *) Bugfix: a segmentation fault occurred if + "client_body_in_file_only on" and "proxy_pass_request_body off" or + "fastcgi_pass_request_body off" directives were used, and nginx + switched to a next upstream. + + *) Bugfix: if the "proxy_buffering off" directive was used and a client + connection was non-active, then the connection was closed after send + timeout; the bug had appeared in 0.4.7. + + *) Bugfix: if the "epoll" method was used and a client closed a + connection prematurely, then nginx closed the connection after a send + timeout only. + + *) Bugfix: the "[alert] zero size buf" error when FastCGI server was + used. + + *) Bugfixes in the "limit_zone" directive. + + +Changes with nginx 0.5.7 15 Jan 2007 + + *) Feature: the ssl_session_cache storage optimization. + + *) Bugfixes in the "ssl_session_cache" and "limit_zone" directives. + + *) Bugfix: the segmentation fault was occurred on start or while + reconfiguration if the "ssl_session_cache" or "limit_zone" directives + were used on 64-bit platforms. + + *) Bugfix: a segmentation fault occurred if the "add_before_body" or + "add_after_body" directives were used and there was no "Content-Type" + header line in response. + + *) Bugfix: the OpenSSL library was always built with the threads + support. + Thanks to Den Ivanov. + + *) Bugfix: the PCRE-6.5+ library and the icc compiler compatibility. + + +Changes with nginx 0.5.6 09 Jan 2007 + + *) Change: now the ngx_http_index_module ignores all methods except the + GET, HEAD, and POST methods. + + *) Feature: the ngx_http_limit_zone_module. + + *) Feature: the $binary_remote_addr variable. + + *) Feature: the "ssl_session_cache" directives of the + ngx_http_ssl_module and ngx_imap_ssl_module. + + *) Feature: the DELETE method supports recursive removal. + + *) Bugfix: the byte-ranges were transferred incorrectly if the + $r->sendfile() was used. + + +Changes with nginx 0.5.5 24 Dec 2006 + + *) Change: the -v switch does not show compiler information any more. + + *) Feature: the -V switch. + + *) Feature: the "worker_rlimit_core" directive supports size in K, M, + and G. + + *) Bugfix: the nginx.pm module now could be installed by an unprivileged + user. + + *) Bugfix: a segmentation fault might occur if the $r->request_body or + $r->request_body_file methods were used. + + *) Bugfix: the ppc platform specific bugs. + + +Changes with nginx 0.5.4 15 Dec 2006 + + *) Feature: the "perl" directive may be used inside the "limit_except" + block. + + *) Bugfix: the ngx_http_dav_module required the "Date" request header + line for the DELETE method. + + *) Bugfix: if one only parameter was used in the "dav_access" directive, + then nginx might report about configuration error. + + *) Bugfix: a segmentation fault might occur if the $host variable was + used; the bug had appeared in 0.4.14. + + +Changes with nginx 0.5.3 13 Dec 2006 + + *) Feature: the ngx_http_perl_module supports the $r->status, + $r->log_error, and $r->sleep methods. + + *) Feature: the $r->variable method supports variables that do not exist + in nginx configuration. + + *) Bugfix: the $r->has_request_body method did not work. + + +Changes with nginx 0.5.2 11 Dec 2006 + + *) Bugfix: if the "proxy_pass" directive used the name of the "upstream" + block, then nginx tried to resolve the name; the bug had appeared in + 0.5.1. + + +Changes with nginx 0.5.1 11 Dec 2006 + + *) Bugfix: the "post_action" directive might not run after a + unsuccessful completion of a request. + + *) Workaround: for Eudora for Mac; the bug had appeared in 0.4.11. + Thanks to Bron Gondwana. + + *) Bugfix: if the "upstream" name was used in the "fastcgi_pass", then + the message "no port in upstream" was issued; the bug had appeared in + 0.5.0. + + *) Bugfix: if the "proxy_pass" and "fastcgi_pass" directives used the + same servers but different ports, then these directives uses the + first described port; the bug had appeared in 0.5.0. + + *) Bugfix: if the "proxy_pass" and "fastcgi_pass" directives used the + unix domain sockets, then these directives used first described + socket; the bug had appeared in 0.5.0. + + *) Bugfix: ngx_http_auth_basic_module ignored the user if it was in the + last line in the password file and there was no the carriage return, + the line feed, or the ":" symbol after the password. + + *) Bugfix: the $upstream_response_time variable might be equal to + "0.000", although response time was more than 1 millisecond. + + +Changes with nginx 0.5.0 04 Dec 2006 + + *) Change: the parameters in the "%name" form in the "log_format" + directive are not supported anymore. + + *) Change: the "proxy_upstream_max_fails", + "proxy_upstream_fail_timeout", "fastcgi_upstream_max_fails", + "fastcgi_upstream_fail_timeout", "memcached_upstream_max_fails", and + "memcached_upstream_fail_timeout" directives are not supported + anymore. + + *) Feature: the "server" directive in the "upstream" context supports + the "max_fails", "fail_timeout", and "down" parameters. + + *) Feature: the "ip_hash" directive inside the "upstream" block. + + *) Feature: the WAIT status in the "Auth-Status" header line of the + IMAP/POP3 proxy authentication server response. + + *) Bugfix: nginx could not be built on 64-bit platforms; the bug had + appeared in 0.4.14. + + +Changes with nginx 0.4.14 27 Nov 2006 + + *) Feature: the "proxy_pass_error_message" directive in IMAP/POP3 proxy. + + *) Feature: now configure detects system PCRE library on FreeBSD, Linux, + and NetBSD. + + *) Bugfix: ngx_http_perl_module did not work with perl built with the + threads support; the bug had appeared in 0.3.38. + + *) Bugfix: ngx_http_perl_module did not work if perl was called + recursively. + + *) Bugfix: nginx ignored a host name in a request line. + + *) Bugfix: a worker process may got caught in an endless loop, if a + FastCGI server sent too many data to the stderr. + + *) Bugfix: the $upstream_response_time variable may be negative if the + system time was changed backward. + + *) Bugfix: the "Auth-Login-Attempt" parameter was not sent to IMAP/POP3 + proxy authentication server when POP3 was used. + + *) Bugfix: a segmentation fault might occur if connect to IMAP/POP3 + proxy authentication server failed. + + +Changes with nginx 0.4.13 15 Nov 2006 + + *) Feature: the "proxy_pass" directive may be used inside the + "limit_except" block. + + *) Feature: the "limit_except" directive supports all WebDAV methods. + + *) Bugfix: if the "add_before_body" directive was used without the + "add_after_body" directive, then a response did not transferred + complete. + + *) Bugfix: a large request body did not receive if the epoll method and + the deferred accept() were used. + + *) Bugfix: a charset could not be set for ngx_http_autoindex_module + responses; the bug had appeared in 0.3.50. + + *) Bugfix: the "[alert] zero size buf" error when FastCGI server was + used; + + *) Bugfix: the --group= configuration parameter was ignored. + Thanks to Thomas Moschny. + + *) Bugfix: the 50th subrequest in SSI response did not work; the bug had + appeared in 0.3.50. + + +Changes with nginx 0.4.12 31 Oct 2006 + + *) Feature: the ngx_http_perl_module supports the $r->variable method. + + *) Bugfix: if a big static file was included using SSI in a response, + then the response may be transferred incomplete. + + *) Bugfix: nginx did not omit the "#fragment" part in URI. + + +Changes with nginx 0.4.11 25 Oct 2006 + + *) Feature: the POP3 proxy supports the AUTH LOGIN PLAIN and CRAM-MD5. + + *) Feature: the ngx_http_perl_module supports the $r->allow_ranges + method. + + *) Bugfix: if the APOP was enabled in the POP3 proxy, then the USER/PASS + commands might not work; the bug had appeared in 0.4.10. + + +Changes with nginx 0.4.10 23 Oct 2006 + + *) Feature: the POP3 proxy supports the APOP command. + + *) Bugfix: if the select, poll or /dev/poll methods were used, then + while waiting authentication server response the IMAP/POP3 proxy + hogged CPU. + + *) Bugfix: a segmentation fault might occur if the $server_addr variable + was used in the "map" directive. + + *) Bugfix: the ngx_http_flv_module did not support the byte ranges for + full responses; the bug had appeared in 0.4.7. + + *) Bugfix: nginx could not be built on Debian amd64; the bug had + appeared in 0.4.9. + + +Changes with nginx 0.4.9 13 Oct 2006 + + *) Feature: the "set" parameter in the "include" SSI command. + + *) Feature: the ngx_http_perl_module now tests the nginx.pm module + version. + + +Changes with nginx 0.4.8 11 Oct 2006 + + *) Bugfix: if an "include" SSI command were before another "include" SSI + command with a "wait" parameter, then the "wait" parameter might not + work. + + *) Bugfix: the ngx_http_flv_module added the FLV header to the full + responses. + Thanks to Alexey Kovyrin. + + +Changes with nginx 0.4.7 10 Oct 2006 + + *) Feature: the ngx_http_flv_module. + + *) Feature: the $request_body_file variable. + + *) Feature: the "charset" and "source_charset" directives support the + variables. + + *) Bugfix: if an "include" SSI command were before another "include" SSI + command with a "wait" parameter, then the "wait" parameter might not + work. + + *) Bugfix: if the "proxy_buffering off" directive was used or while + working with memcached the connections might not be closed on + timeout. + + *) Bugfix: nginx did not run on 64-bit platforms except amd64, sparc64, + and ppc64. + + +Changes with nginx 0.4.6 06 Oct 2006 + + *) Bugfix: nginx did not run on 64-bit platforms except amd64, sparc64, + and ppc64. + + *) Bugfix: nginx sent the chunked response for HTTP/1.1 request, + if its length was set by text string in the + $r->headers_out("Content-Length", ...) method. + + *) Bugfix: after redirecting error by an "error_page" directive any + ngx_http_rewrite_module directive returned this error code; the bug + had appeared in 0.4.4. + + +Changes with nginx 0.4.5 02 Oct 2006 + + *) Bugfix: nginx could not be built on Linux and Solaris; the bug had + appeared in 0.4.4. + + +Changes with nginx 0.4.4 02 Oct 2006 + + *) Feature: the $scheme variable. + + *) Feature: the "expires" directive supports the "max" parameter. + + *) Feature: the "include" directive supports the "*" mask. + Thanks to Jonathan Dance. + + *) Bugfix: the "return" directive always overrode the "error_page" + response code redirected by the "error_page" directive. + + *) Bugfix: a segmentation fault occurred if zero-length body was in PUT + method. + + *) Bugfix: the redirect was changed incorrectly if the variables were + used in the "proxy_redirect" directive. + + +Changes with nginx 0.4.3 26 Sep 2006 + + *) Change: now the 499 error could not be redirected using an + "error_page" directive. + + *) Feature: the Solaris 10 event ports support. + + *) Feature: the ngx_http_browser_module. + + *) Bugfix: a segmentation fault may occur while redirecting the 400 + error to the proxied server using a "proxy_pass" directive. + + *) Bugfix: a segmentation fault occurred if an unix domain socket was + used in a "proxy_pass" directive; the bug had appeared in 0.3.47. + + *) Bugfix: SSI did work with memcached and nonbuffered responses. + + *) Workaround: of the Sun Studio PAUSE hardware capability bug. + + +Changes with nginx 0.4.2 14 Sep 2006 + + *) Bugfix: the O_NOATIME flag support on Linux was canceled; the bug had + appeared in 0.4.1. + + +Changes with nginx 0.4.1 14 Sep 2006 + + *) Bugfix: the DragonFlyBSD compatibility. + Thanks to Pavel Nazarov. + + *) Workaround: of bug in 64-bit Linux sendfile(), when file is more than + 2G. + + *) Feature: now on Linux nginx uses O_NOATIME flag for static requests. + Thanks to Yusuf Goolamabbas. + + +Changes with nginx 0.4.0 30 Aug 2006 + + *) Change in internal API: the HTTP modules initialization was moved + from the init module phase to the HTTP postconfiguration phase. + + *) Change: now the request body is not read beforehand for the + ngx_http_perl_module: it's required to start the reading using the + $r->has_request_body method. + + *) Feature: the ngx_http_perl_module supports the DECLINED return code. + + *) Feature: the ngx_http_dav_module supports the incoming "Date" header + line for the PUT method. + + *) Feature: the "ssi" directive is available inside the "if" block. + + *) Bugfix: a segmentation fault occurred if there was an "index" + directive with variables and the first index name was without + variables; the bug had appeared in 0.1.29. + + +Changes with nginx 0.3.61 28 Aug 2006 + + *) Change: now the "tcp_nodelay" directive is turned on by default. + + *) Feature: the "msie_refresh" directive. + + *) Feature: the "recursive_error_pages" directive. + + *) Bugfix: the "rewrite" directive returned incorrect redirect, if the + redirect had the captured escaped symbols from original URI. + + +Changes with nginx 0.3.60 18 Aug 2006 + + *) Bugfix: a worker process may got caught in an endless loop while an + error redirection; the bug had appeared in 0.3.59. + + +Changes with nginx 0.3.59 16 Aug 2006 + + *) Feature: now is possible to do several redirection using the + "error_page" directive. + + *) Bugfix: the "dav_access" directive did not support three parameters. + + *) Bugfix: the "error_page" directive did not changes the "Content-Type" + header line after the "X-Accel-Redirect" was used; the bug had + appeared in 0.3.58. + + +Changes with nginx 0.3.58 14 Aug 2006 + + *) Feature: the "error_page" directive supports the variables. + + *) Change: now the procfs interface instead of sysctl is used on Linux. + + *) Change: now the "Content-Type" header line is inherited from first + response when the "X-Accel-Redirect" was used. + + *) Bugfix: the "error_page" directive did not redirect the 413 error. + + *) Bugfix: the trailing "?" did not remove old arguments if no new + arguments were added to a rewritten URI. + + *) Bugfix: nginx could not run on 64-bit FreeBSD 7.0-CURRENT. + + +Changes with nginx 0.3.57 09 Aug 2006 + + *) Feature: the $ssl_client_serial variable. + + *) Bugfix: in the "!-e" operator of the "if" directive. + Thanks to Andrian Budanstov. + + *) Bugfix: while a client certificate verification nginx did not send to + a client the required certificates information. + + *) Bugfix: the $document_root variable did not support the variables in + the "root" directive. + + +Changes with nginx 0.3.56 04 Aug 2006 + + *) Feature: the "dav_access" directive. + + *) Feature: the "if" directive supports the "-d", "!-d", "-e", "!-e", + "-x", and "!-x" operators. + + *) Bugfix: a segmentation fault occurred if a request returned a + redirect and some sent to client header lines were logged in the + access log. + + +Changes with nginx 0.3.55 28 Jul 2006 + + *) Feature: the "stub" parameter in the "include" SSI command. + + *) Feature: the "block" SSI command. + + *) Feature: the unicode2nginx script was added to contrib. + + *) Bugfix: if a "root" was specified by variable only, then the root was + relative to a server prefix. + + *) Bugfix: if the request contained "//" or "/./" and escaped symbols + after them, then the proxied request was sent unescaped. + + *) Bugfix: the $r->header_in("Cookie") of the ngx_http_perl_module now + returns all "Cookie" header lines. + + *) Bugfix: a segmentation fault occurred if + "client_body_in_file_only on" was used and nginx switched to a next + upstream. + + *) Bugfix: on some condition while reconfiguration character codes + inside the "charset_map" may be treated invalid; the bug had appeared + in 0.3.50. + + +Changes with nginx 0.3.54 11 Jul 2006 + + *) Feature: nginx now logs the subrequest information to the error log. + + *) Feature: the "proxy_next_upstream", "fastcgi_next_upstream", and + "memcached_next_upstream" directives support the "off" parameter. + + *) Feature: the "debug_connection" directive supports the CIDR address + form. + + *) Bugfix: if a response of proxied server or FastCGI server was + converted from UTF-8 or back, then it may be transferred incomplete. + + *) Bugfix: the $upstream_response_time variable had the time of the + first request to a backend only. + + *) Bugfix: nginx could not be built on amd64 platform; the bug had + appeared in 0.3.53. + + +Changes with nginx 0.3.53 07 Jul 2006 + + *) Change: the "add_header" directive adds the string to 204, 301, and + 302 responses. + + *) Feature: the "server" directive in the "upstream" context supports + the "weight" parameter. + + *) Feature: the "server_name" directive supports the "*" wildcard. + + *) Feature: nginx supports the request body size more than 2G. + + *) Bugfix: if a client was successfully authorized using "satisfy_any + on", then anyway the message "access forbidden by rule" was written + in the log. + + *) Bugfix: the "PUT" method may erroneously not create a file and return + the 409 code. + + *) Bugfix: if the IMAP/POP3 backend returned an error, then nginx + continued proxying anyway. + + +Changes with nginx 0.3.52 03 Jul 2006 + + *) Change: the ngx_http_index_module behavior for the "POST /" requests + is reverted to the 0.3.40 version state: the module now does not + return the 405 error. + + *) Bugfix: the worker process may got caught in an endless loop if the + limit rate was used; the bug had appeared in 0.3.37. + + *) Bugfix: ngx_http_charset_module logged "unknown charset" alert, even + if the recoding was not needed; the bug had appeared in 0.3.50. + + *) Bugfix: if a code response of the PUT request was 409, then a + temporary file was not removed. + + +Changes with nginx 0.3.51 30 Jun 2006 + + *) Bugfix: the "<" symbols might disappeared some conditions in the SSI; + the bug had appeared in 0.3.50. + + +Changes with nginx 0.3.50 28 Jun 2006 + + *) Change: the "proxy_redirect_errors" and "fastcgi_redirect_errors" + directives was renamed to the "proxy_intercept_errors" and + "fastcgi_intercept_errors" directives. + + *) Feature: the ngx_http_charset_module supports the recoding from the + single byte encodings to the UTF-8 encoding and back. + + *) Feature: the "X-Accel-Charset" response header line is supported in + proxy and FastCGI mode. + + *) Bugfix: the "\" escape symbol in the "\"" and "\'" pairs in the SSI + command was removed only if the command also has the "$" symbol. + + *) Bugfix: the "" CRLF +"" CRLF +"" CRLF +"" CRLF +"" CRLF +"" CRLF +; + + +static u_char ngx_http_msie_refresh_head[] = +"" CRLF; + + +static char ngx_http_error_301_page[] = +"" CRLF +"301 Moved Permanently" CRLF +"" CRLF +"

301 Moved Permanently

" CRLF +; + + +static char ngx_http_error_302_page[] = +"" CRLF +"302 Found" CRLF +"" CRLF +"

302 Found

" CRLF +; + + +static char ngx_http_error_303_page[] = +"" CRLF +"303 See Other" CRLF +"" CRLF +"

303 See Other

" CRLF +; + + +static char ngx_http_error_307_page[] = +"" CRLF +"307 Temporary Redirect" CRLF +"" CRLF +"

307 Temporary Redirect

" CRLF +; + + +static char ngx_http_error_400_page[] = +"" CRLF +"400 Bad Request" CRLF +"" CRLF +"

400 Bad Request

" CRLF +; + + +static char ngx_http_error_401_page[] = +"" CRLF +"401 Authorization Required" CRLF +"" CRLF +"

401 Authorization Required

" CRLF +; + + +static char ngx_http_error_402_page[] = +"" CRLF +"402 Payment Required" CRLF +"" CRLF +"

402 Payment Required

" CRLF +; + + +static char ngx_http_error_403_page[] = +"" CRLF +"403 Forbidden" CRLF +"" CRLF +"

403 Forbidden

" CRLF +; + + +static char ngx_http_error_404_page[] = +"" CRLF +"404 Not Found" CRLF +"" CRLF +"

404 Not Found

" CRLF +; + + +static char ngx_http_error_405_page[] = +"" CRLF +"405 Not Allowed" CRLF +"" CRLF +"

405 Not Allowed

" CRLF +; + + +static char ngx_http_error_406_page[] = +"" CRLF +"406 Not Acceptable" CRLF +"" CRLF +"

406 Not Acceptable

" CRLF +; + + +static char ngx_http_error_408_page[] = +"" CRLF +"408 Request Time-out" CRLF +"" CRLF +"

408 Request Time-out

" CRLF +; + + +static char ngx_http_error_409_page[] = +"" CRLF +"409 Conflict" CRLF +"" CRLF +"

409 Conflict

" CRLF +; + + +static char ngx_http_error_410_page[] = +"" CRLF +"410 Gone" CRLF +"" CRLF +"

410 Gone

" CRLF +; + + +static char ngx_http_error_411_page[] = +"" CRLF +"411 Length Required" CRLF +"" CRLF +"

411 Length Required

" CRLF +; + + +static char ngx_http_error_412_page[] = +"" CRLF +"412 Precondition Failed" CRLF +"" CRLF +"

412 Precondition Failed

" CRLF +; + + +static char ngx_http_error_413_page[] = +"" CRLF +"413 Request Entity Too Large" CRLF +"" CRLF +"

413 Request Entity Too Large

" CRLF +; + + +static char ngx_http_error_414_page[] = +"" CRLF +"414 Request-URI Too Large" CRLF +"" CRLF +"

414 Request-URI Too Large

" CRLF +; + + +static char ngx_http_error_415_page[] = +"" CRLF +"415 Unsupported Media Type" CRLF +"" CRLF +"

415 Unsupported Media Type

" CRLF +; + + +static char ngx_http_error_416_page[] = +"" CRLF +"416 Requested Range Not Satisfiable" CRLF +"" CRLF +"

416 Requested Range Not Satisfiable

" CRLF +; + + +static char ngx_http_error_494_page[] = +"" CRLF +"400 Request Header Or Cookie Too Large" +CRLF +"" CRLF +"

400 Bad Request

" CRLF +"
Request Header Or Cookie Too Large
" CRLF +; + + +static char ngx_http_error_495_page[] = +"" CRLF +"400 The SSL certificate error" +CRLF +"" CRLF +"

400 Bad Request

" CRLF +"
The SSL certificate error
" CRLF +; + + +static char ngx_http_error_496_page[] = +"" CRLF +"400 No required SSL certificate was sent" +CRLF +"" CRLF +"

400 Bad Request

" CRLF +"
No required SSL certificate was sent
" CRLF +; + + +static char ngx_http_error_497_page[] = +"" CRLF +"400 The plain HTTP request was sent to HTTPS port" +CRLF +"" CRLF +"

400 Bad Request

" CRLF +"
The plain HTTP request was sent to HTTPS port
" CRLF +; + + +static char ngx_http_error_500_page[] = +"" CRLF +"500 Internal Server Error" CRLF +"" CRLF +"

500 Internal Server Error

" CRLF +; + + +static char ngx_http_error_501_page[] = +"" CRLF +"501 Not Implemented" CRLF +"" CRLF +"

501 Not Implemented

" CRLF +; + + +static char ngx_http_error_502_page[] = +"" CRLF +"502 Bad Gateway" CRLF +"" CRLF +"

502 Bad Gateway

" CRLF +; + + +static char ngx_http_error_503_page[] = +"" CRLF +"503 Service Temporarily Unavailable" CRLF +"" CRLF +"

503 Service Temporarily Unavailable

" CRLF +; + + +static char ngx_http_error_504_page[] = +"" CRLF +"504 Gateway Time-out" CRLF +"" CRLF +"

504 Gateway Time-out

" CRLF +; + + +static char ngx_http_error_507_page[] = +"" CRLF +"507 Insufficient Storage" CRLF +"" CRLF +"

507 Insufficient Storage

" CRLF +; + + +static ngx_str_t ngx_http_error_pages[] = { + + ngx_null_string, /* 201, 204 */ + +#define NGX_HTTP_LAST_2XX 202 +#define NGX_HTTP_OFF_3XX (NGX_HTTP_LAST_2XX - 201) + + /* ngx_null_string, */ /* 300 */ + ngx_string(ngx_http_error_301_page), + ngx_string(ngx_http_error_302_page), + ngx_string(ngx_http_error_303_page), + ngx_null_string, /* 304 */ + ngx_null_string, /* 305 */ + ngx_null_string, /* 306 */ + ngx_string(ngx_http_error_307_page), + +#define NGX_HTTP_LAST_3XX 308 +#define NGX_HTTP_OFF_4XX (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX) + + ngx_string(ngx_http_error_400_page), + ngx_string(ngx_http_error_401_page), + ngx_string(ngx_http_error_402_page), + ngx_string(ngx_http_error_403_page), + ngx_string(ngx_http_error_404_page), + ngx_string(ngx_http_error_405_page), + ngx_string(ngx_http_error_406_page), + ngx_null_string, /* 407 */ + ngx_string(ngx_http_error_408_page), + ngx_string(ngx_http_error_409_page), + ngx_string(ngx_http_error_410_page), + ngx_string(ngx_http_error_411_page), + ngx_string(ngx_http_error_412_page), + ngx_string(ngx_http_error_413_page), + ngx_string(ngx_http_error_414_page), + ngx_string(ngx_http_error_415_page), + ngx_string(ngx_http_error_416_page), + +#define NGX_HTTP_LAST_4XX 417 +#define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) + + ngx_string(ngx_http_error_494_page), /* 494, request header too large */ + ngx_string(ngx_http_error_495_page), /* 495, https certificate error */ + ngx_string(ngx_http_error_496_page), /* 496, https no certificate */ + ngx_string(ngx_http_error_497_page), /* 497, http to https */ + ngx_string(ngx_http_error_404_page), /* 498, canceled */ + ngx_null_string, /* 499, client has closed connection */ + + ngx_string(ngx_http_error_500_page), + ngx_string(ngx_http_error_501_page), + ngx_string(ngx_http_error_502_page), + ngx_string(ngx_http_error_503_page), + ngx_string(ngx_http_error_504_page), + ngx_null_string, /* 505 */ + ngx_null_string, /* 506 */ + ngx_string(ngx_http_error_507_page) + +#define NGX_HTTP_LAST_5XX 508 + +}; + + +static ngx_str_t ngx_http_get_name = { 3, (u_char *) "GET " }; + + +ngx_int_t +ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) +{ + ngx_uint_t i, err; + ngx_http_err_page_t *err_page; + ngx_http_core_loc_conf_t *clcf; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http special response: %i, \"%V?%V\"", + error, &r->uri, &r->args); + + r->err_status = error; + + if (r->keepalive) { + switch (error) { + case NGX_HTTP_BAD_REQUEST: + case NGX_HTTP_REQUEST_ENTITY_TOO_LARGE: + case NGX_HTTP_REQUEST_URI_TOO_LARGE: + case NGX_HTTP_TO_HTTPS: + case NGX_HTTPS_CERT_ERROR: + case NGX_HTTPS_NO_CERT: + case NGX_HTTP_INTERNAL_SERVER_ERROR: + case NGX_HTTP_NOT_IMPLEMENTED: + r->keepalive = 0; + } + } + + if (r->lingering_close) { + switch (error) { + case NGX_HTTP_BAD_REQUEST: + case NGX_HTTP_TO_HTTPS: + case NGX_HTTPS_CERT_ERROR: + case NGX_HTTPS_NO_CERT: + r->lingering_close = 0; + } + } + + r->headers_out.content_type.len = 0; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (!r->error_page && clcf->error_pages && r->uri_changes != 0) { + + if (clcf->recursive_error_pages == 0) { + r->error_page = 1; + } + + err_page = clcf->error_pages->elts; + + for (i = 0; i < clcf->error_pages->nelts; i++) { + if (err_page[i].status == error) { + return ngx_http_send_error_page(r, &err_page[i]); + } + } + } + + r->expect_tested = 1; + + if (ngx_http_discard_request_body(r) != NGX_OK) { + r->keepalive = 0; + } + + if (clcf->msie_refresh + && r->headers_in.msie + && (error == NGX_HTTP_MOVED_PERMANENTLY + || error == NGX_HTTP_MOVED_TEMPORARILY)) + { + return ngx_http_send_refresh(r); + } + + if (error == NGX_HTTP_CREATED) { + /* 201 */ + err = 0; + + } else if (error == NGX_HTTP_NO_CONTENT) { + /* 204 */ + err = 0; + + } else if (error >= NGX_HTTP_MOVED_PERMANENTLY + && error < NGX_HTTP_LAST_3XX) + { + /* 3XX */ + err = error - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX; + + } else if (error >= NGX_HTTP_BAD_REQUEST + && error < NGX_HTTP_LAST_4XX) + { + /* 4XX */ + err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_OFF_4XX; + + } else if (error >= NGX_HTTP_NGINX_CODES + && error < NGX_HTTP_LAST_5XX) + { + /* 49X, 5XX */ + err = error - NGX_HTTP_NGINX_CODES + NGX_HTTP_OFF_5XX; + switch (error) { + case NGX_HTTP_TO_HTTPS: + case NGX_HTTPS_CERT_ERROR: + case NGX_HTTPS_NO_CERT: + case NGX_HTTP_REQUEST_HEADER_TOO_LARGE: + r->err_status = NGX_HTTP_BAD_REQUEST; + break; + } + + } else { + /* unknown code, zero body */ + err = 0; + } + + return ngx_http_send_special_response(r, clcf, err); +} + + +ngx_int_t +ngx_http_filter_finalize_request(ngx_http_request_t *r, ngx_module_t *m, + ngx_int_t error) +{ + void *ctx; + ngx_int_t rc; + + ngx_http_clean_header(r); + + ctx = NULL; + + if (m) { + ctx = r->ctx[m->ctx_index]; + } + + /* clear the modules contexts */ + ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module); + + if (m) { + r->ctx[m->ctx_index] = ctx; + } + + r->filter_finalize = 1; + + rc = ngx_http_special_response_handler(r, error); + + /* NGX_ERROR resets any pending data */ + + switch (rc) { + + case NGX_OK: + case NGX_DONE: + return NGX_ERROR; + + default: + return rc; + } +} + + +void +ngx_http_clean_header(ngx_http_request_t *r) +{ + ngx_memzero(&r->headers_out.status, + sizeof(ngx_http_headers_out_t) + - offsetof(ngx_http_headers_out_t, status)); + + r->headers_out.headers.part.nelts = 0; + r->headers_out.headers.part.next = NULL; + r->headers_out.headers.last = &r->headers_out.headers.part; + + r->headers_out.content_length_n = -1; + r->headers_out.last_modified_time = -1; +} + + +static ngx_int_t +ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) +{ + ngx_int_t overwrite; + ngx_str_t uri, args; + ngx_table_elt_t *location; + ngx_http_core_loc_conf_t *clcf; + + overwrite = err_page->overwrite; + + if (overwrite && overwrite != NGX_HTTP_OK) { + r->expect_tested = 1; + } + + if (overwrite >= 0) { + r->err_status = overwrite; + } + + if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) { + return NGX_ERROR; + } + + if (uri.len && uri.data[0] == '/') { + + if (err_page->value.lengths) { + ngx_http_split_args(r, &uri, &args); + + } else { + args = err_page->args; + } + + if (r->method != NGX_HTTP_HEAD) { + r->method = NGX_HTTP_GET; + r->method_name = ngx_http_get_name; + } + + return ngx_http_internal_redirect(r, &uri, &args); + } + + if (uri.len && uri.data[0] == '@') { + return ngx_http_named_location(r, &uri); + } + + location = ngx_list_push(&r->headers_out.headers); + + if (location == NULL) { + return NGX_ERROR; + } + + if (overwrite != NGX_HTTP_MOVED_PERMANENTLY + && overwrite != NGX_HTTP_MOVED_TEMPORARILY + && overwrite != NGX_HTTP_SEE_OTHER + && overwrite != NGX_HTTP_TEMPORARY_REDIRECT) + { + r->err_status = NGX_HTTP_MOVED_TEMPORARILY; + } + + location->hash = 1; + ngx_str_set(&location->key, "Location"); + location->value = uri; + + ngx_http_clear_location(r); + + r->headers_out.location = location; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->msie_refresh && r->headers_in.msie) { + return ngx_http_send_refresh(r); + } + + return ngx_http_send_special_response(r, clcf, r->err_status + - NGX_HTTP_MOVED_PERMANENTLY + + NGX_HTTP_OFF_3XX); +} + + +static ngx_int_t +ngx_http_send_special_response(ngx_http_request_t *r, + ngx_http_core_loc_conf_t *clcf, ngx_uint_t err) +{ + u_char *tail; + size_t len; + ngx_int_t rc; + ngx_buf_t *b; + ngx_uint_t msie_padding; + ngx_chain_t out[3]; + + if (clcf->server_tokens) { + len = sizeof(ngx_http_error_full_tail) - 1; + tail = ngx_http_error_full_tail; + + } else { + len = sizeof(ngx_http_error_tail) - 1; + tail = ngx_http_error_tail; + } + + msie_padding = 0; + + if (ngx_http_error_pages[err].len) { + r->headers_out.content_length_n = ngx_http_error_pages[err].len + len; + if (clcf->msie_padding + && (r->headers_in.msie || r->headers_in.chrome) + && r->http_version >= NGX_HTTP_VERSION_10 + && err >= NGX_HTTP_OFF_4XX) + { + r->headers_out.content_length_n += + sizeof(ngx_http_msie_padding) - 1; + msie_padding = 1; + } + + r->headers_out.content_type_len = sizeof("text/html") - 1; + ngx_str_set(&r->headers_out.content_type, "text/html"); + r->headers_out.content_type_lowcase = NULL; + + } else { + r->headers_out.content_length_n = 0; + } + + if (r->headers_out.content_length) { + r->headers_out.content_length->hash = 0; + r->headers_out.content_length = NULL; + } + + ngx_http_clear_accept_ranges(r); + ngx_http_clear_last_modified(r); + ngx_http_clear_etag(r); + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || r->header_only) { + return rc; + } + + if (ngx_http_error_pages[err].len == 0) { + return ngx_http_send_special(r, NGX_HTTP_LAST); + } + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + b->memory = 1; + b->pos = ngx_http_error_pages[err].data; + b->last = ngx_http_error_pages[err].data + ngx_http_error_pages[err].len; + + out[0].buf = b; + out[0].next = &out[1]; + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + b->memory = 1; + + b->pos = tail; + b->last = tail + len; + + out[1].buf = b; + out[1].next = NULL; + + if (msie_padding) { + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + b->memory = 1; + b->pos = ngx_http_msie_padding; + b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1; + + out[1].next = &out[2]; + out[2].buf = b; + out[2].next = NULL; + } + + if (r == r->main) { + b->last_buf = 1; + } + + b->last_in_chain = 1; + + return ngx_http_output_filter(r, &out[0]); +} + + +static ngx_int_t +ngx_http_send_refresh(ngx_http_request_t *r) +{ + u_char *p, *location; + size_t len, size; + uintptr_t escape; + ngx_int_t rc; + ngx_buf_t *b; + ngx_chain_t out; + + len = r->headers_out.location->value.len; + location = r->headers_out.location->value.data; + + escape = 2 * ngx_escape_uri(NULL, location, len, NGX_ESCAPE_REFRESH); + + size = sizeof(ngx_http_msie_refresh_head) - 1 + + escape + len + + sizeof(ngx_http_msie_refresh_tail) - 1; + + r->err_status = NGX_HTTP_OK; + + r->headers_out.content_type_len = sizeof("text/html") - 1; + ngx_str_set(&r->headers_out.content_type, "text/html"); + r->headers_out.content_type_lowcase = NULL; + + r->headers_out.location->hash = 0; + r->headers_out.location = NULL; + + r->headers_out.content_length_n = size; + + if (r->headers_out.content_length) { + r->headers_out.content_length->hash = 0; + r->headers_out.content_length = NULL; + } + + ngx_http_clear_accept_ranges(r); + ngx_http_clear_last_modified(r); + ngx_http_clear_etag(r); + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || r->header_only) { + return rc; + } + + b = ngx_create_temp_buf(r->pool, size); + if (b == NULL) { + return NGX_ERROR; + } + + p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head, + sizeof(ngx_http_msie_refresh_head) - 1); + + if (escape == 0) { + p = ngx_cpymem(p, location, len); + + } else { + p = (u_char *) ngx_escape_uri(p, location, len, NGX_ESCAPE_REFRESH); + } + + b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail, + sizeof(ngx_http_msie_refresh_tail) - 1); + + b->last_buf = 1; + b->last_in_chain = 1; + + out.buf = b; + out.next = NULL; + + return ngx_http_output_filter(r, &out); +} diff --git a/hm_nginx/src/http/ngx_http_upstream.c b/hm_nginx/src/http/ngx_http_upstream.c new file mode 100644 index 0000000..e36cf0f --- /dev/null +++ b/hm_nginx/src/http/ngx_http_upstream.c @@ -0,0 +1,5990 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#if (NGX_HTTP_CACHE) +static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_cache_get(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_http_file_cache_t **cache); +static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#endif + +static void ngx_http_upstream_init_request(ngx_http_request_t *r); +static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); +static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); +static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); +static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, + ngx_event_t *ev); +static void ngx_http_upstream_connect(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_send_request(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_uint_t do_write); +static ngx_int_t ngx_http_upstream_send_request_body(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_uint_t do_write); +static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r); +static void ngx_http_upstream_process_header(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c); +static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_send_response(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_upgrade(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r); +static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r); +static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r, + ngx_uint_t from_upstream, ngx_uint_t do_write); +static void + ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r); +static void + ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void + ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r, + ngx_uint_t do_write); +static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data); +static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, + ssize_t bytes); +static void ngx_http_upstream_process_downstream(ngx_http_request_t *r); +static void ngx_http_upstream_process_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_process_request(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_store(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r, + ngx_http_upstream_t *u); +static void ngx_http_upstream_next(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_uint_t ft_type); +static void ngx_http_upstream_cleanup(void *data); +static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_int_t rc); + +static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t + ngx_http_upstream_process_cache_control(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t + ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_vary(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t + ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); + +#if (NGX_HTTP_GZIP) +static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +#endif + +static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_response_length_variable( + ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); + +static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy); +static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r, + ngx_http_upstream_local_t *local); + +static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf); +static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf); + +#if (NGX_HTTP_SSL) +static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, + ngx_http_upstream_t *u, ngx_connection_t *c); +static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c); +static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c); +#endif + + +ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { + + { ngx_string("Status"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, status), + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("Content-Type"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, content_type), + ngx_http_upstream_copy_content_type, 0, 1 }, + + { ngx_string("Content-Length"), + ngx_http_upstream_process_content_length, 0, + ngx_http_upstream_ignore_header_line, 0, 0 }, + + { ngx_string("Date"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, date), + ngx_http_upstream_copy_header_line, + offsetof(ngx_http_headers_out_t, date), 0 }, + + { ngx_string("Last-Modified"), + ngx_http_upstream_process_last_modified, 0, + ngx_http_upstream_copy_last_modified, 0, 0 }, + + { ngx_string("ETag"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, etag), + ngx_http_upstream_copy_header_line, + offsetof(ngx_http_headers_out_t, etag), 0 }, + + { ngx_string("Server"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, server), + ngx_http_upstream_copy_header_line, + offsetof(ngx_http_headers_out_t, server), 0 }, + + { ngx_string("WWW-Authenticate"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, www_authenticate), + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("Location"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, location), + ngx_http_upstream_rewrite_location, 0, 0 }, + + { ngx_string("Refresh"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_rewrite_refresh, 0, 0 }, + + { ngx_string("Set-Cookie"), + ngx_http_upstream_process_set_cookie, + offsetof(ngx_http_upstream_headers_in_t, cookies), + ngx_http_upstream_rewrite_set_cookie, 0, 1 }, + + { ngx_string("Content-Disposition"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_header_line, 0, 1 }, + + { ngx_string("Cache-Control"), + ngx_http_upstream_process_cache_control, 0, + ngx_http_upstream_copy_multi_header_lines, + offsetof(ngx_http_headers_out_t, cache_control), 1 }, + + { ngx_string("Expires"), + ngx_http_upstream_process_expires, 0, + ngx_http_upstream_copy_header_line, + offsetof(ngx_http_headers_out_t, expires), 1 }, + + { ngx_string("Accept-Ranges"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, accept_ranges), + ngx_http_upstream_copy_allow_ranges, + offsetof(ngx_http_headers_out_t, accept_ranges), 1 }, + + { ngx_string("Connection"), + ngx_http_upstream_process_connection, 0, + ngx_http_upstream_ignore_header_line, 0, 0 }, + + { ngx_string("Keep-Alive"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_ignore_header_line, 0, 0 }, + + { ngx_string("Vary"), + ngx_http_upstream_process_vary, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("X-Powered-By"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("X-Accel-Expires"), + ngx_http_upstream_process_accel_expires, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("X-Accel-Redirect"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect), + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("X-Accel-Limit-Rate"), + ngx_http_upstream_process_limit_rate, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("X-Accel-Buffering"), + ngx_http_upstream_process_buffering, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("X-Accel-Charset"), + ngx_http_upstream_process_charset, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + + { ngx_string("Transfer-Encoding"), + ngx_http_upstream_process_transfer_encoding, 0, + ngx_http_upstream_ignore_header_line, 0, 0 }, + +#if (NGX_HTTP_GZIP) + { ngx_string("Content-Encoding"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, content_encoding), + ngx_http_upstream_copy_content_encoding, 0, 0 }, +#endif + + { ngx_null_string, NULL, 0, NULL, 0, 0 } +}; + + +static ngx_command_t ngx_http_upstream_commands[] = { + + { ngx_string("upstream"), + NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1, + ngx_http_upstream, + 0, + 0, + NULL }, + + { ngx_string("server"), + NGX_HTTP_UPS_CONF|NGX_CONF_1MORE, + ngx_http_upstream_server, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_upstream_module_ctx = { + ngx_http_upstream_add_variables, /* preconfiguration */ + NULL, /* postconfiguration */ + + ngx_http_upstream_create_main_conf, /* create main configuration */ + ngx_http_upstream_init_main_conf, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_upstream_module = { + NGX_MODULE_V1, + &ngx_http_upstream_module_ctx, /* module context */ + ngx_http_upstream_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_http_variable_t ngx_http_upstream_vars[] = { + + { ngx_string("upstream_addr"), NULL, + ngx_http_upstream_addr_variable, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("upstream_status"), NULL, + ngx_http_upstream_status_variable, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("upstream_header_time"), NULL, + ngx_http_upstream_response_time_variable, 1, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("upstream_response_time"), NULL, + ngx_http_upstream_response_time_variable, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("upstream_response_length"), NULL, + ngx_http_upstream_response_length_variable, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + +#if (NGX_HTTP_CACHE) + + { ngx_string("upstream_cache_status"), NULL, + ngx_http_upstream_cache_status, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("upstream_cache_last_modified"), NULL, + ngx_http_upstream_cache_last_modified, 0, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("upstream_cache_etag"), NULL, + ngx_http_upstream_cache_etag, 0, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + +#endif + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = { + { 500, NGX_HTTP_UPSTREAM_FT_HTTP_500 }, + { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502 }, + { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503 }, + { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 }, + { 403, NGX_HTTP_UPSTREAM_FT_HTTP_403 }, + { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { 0, 0 } +}; + + +ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask[] = { + { ngx_string("GET"), NGX_HTTP_GET}, + { ngx_string("HEAD"), NGX_HTTP_HEAD }, + { ngx_string("POST"), NGX_HTTP_POST }, + { ngx_null_string, 0 } +}; + + +ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[] = { + { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT }, + { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES }, + { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE }, + { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING }, + { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET }, + { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES }, + { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL }, + { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE }, + { ngx_string("Vary"), NGX_HTTP_UPSTREAM_IGN_VARY }, + { ngx_null_string, 0 } +}; + + +ngx_int_t +ngx_http_upstream_create(ngx_http_request_t *r) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + + if (u && u->cleanup) { + r->main->count++; + ngx_http_upstream_cleanup(r); + } + + u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); + if (u == NULL) { + return NGX_ERROR; + } + + r->upstream = u; + + u->peer.log = r->connection->log; + u->peer.log_error = NGX_ERROR_ERR; + +#if (NGX_HTTP_CACHE) + r->cache = NULL; +#endif + + u->headers_in.content_length_n = -1; + u->headers_in.last_modified_time = -1; + + return NGX_OK; +} + + +void +ngx_http_upstream_init(ngx_http_request_t *r) +{ + ngx_connection_t *c; + + c = r->connection; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http init upstream, client timer: %d", c->read->timer_set); + +#if (NGX_HTTP_SPDY) + if (r->spdy_stream) { + ngx_http_upstream_init_request(r); + return; + } +#endif + + if (c->read->timer_set) { + ngx_del_timer(c->read); + } + + if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { + + if (!c->write->active) { + if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) + == NGX_ERROR) + { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + } + + ngx_http_upstream_init_request(r); +} + + +static void +ngx_http_upstream_init_request(ngx_http_request_t *r) +{ + ngx_str_t *host; + ngx_uint_t i; + ngx_resolver_ctx_t *ctx, temp; + ngx_http_cleanup_t *cln; + ngx_http_upstream_t *u; + ngx_http_core_loc_conf_t *clcf; + ngx_http_upstream_srv_conf_t *uscf, **uscfp; + ngx_http_upstream_main_conf_t *umcf; + + if (r->aio) { + return; + } + + u = r->upstream; + +#if (NGX_HTTP_CACHE) + + if (u->conf->cache) { + ngx_int_t rc; + + rc = ngx_http_upstream_cache(r, u); + + if (rc == NGX_BUSY) { + r->write_event_handler = ngx_http_upstream_init_request; + return; + } + + r->write_event_handler = ngx_http_request_empty_handler; + + if (rc == NGX_ERROR) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + if (rc == NGX_OK) { + rc = ngx_http_upstream_cache_send(r, u); + + if (rc == NGX_DONE) { + return; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_DECLINED; + r->cached = 0; + } + } + + if (rc != NGX_DECLINED) { + ngx_http_finalize_request(r, rc); + return; + } + } + +#endif + + u->store = u->conf->store; + + if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { + r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; + r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; + } + + if (r->request_body) { + u->request_bufs = r->request_body->bufs; + } + + if (u->create_request(r) != NGX_OK) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + u->peer.local = ngx_http_upstream_get_local(r, u->conf->local); + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + u->output.alignment = clcf->directio_alignment; + u->output.pool = r->pool; + u->output.bufs.num = 1; + u->output.bufs.size = clcf->client_body_buffer_size; + + if (u->output.output_filter == NULL) { + u->output.output_filter = ngx_chain_writer; + u->output.filter_ctx = &u->writer; + } + + u->writer.pool = r->pool; + + if (r->upstream_states == NULL) { + + r->upstream_states = ngx_array_create(r->pool, 1, + sizeof(ngx_http_upstream_state_t)); + if (r->upstream_states == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + } else { + + u->state = ngx_array_push(r->upstream_states); + if (u->state == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); + } + + cln = ngx_http_cleanup_add(r, 0); + if (cln == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + cln->handler = ngx_http_upstream_cleanup; + cln->data = r; + u->cleanup = &cln->handler; + + if (u->resolved == NULL) { + + uscf = u->conf->upstream; + + } else { + +#if (NGX_HTTP_SSL) + u->ssl_name = u->resolved->host; +#endif + + if (u->resolved->sockaddr) { + + if (ngx_http_upstream_create_round_robin_peer(r, u->resolved) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_http_upstream_connect(r, u); + + return; + } + + host = &u->resolved->host; + + umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); + + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + + uscf = uscfp[i]; + + if (uscf->host.len == host->len + && ((uscf->port == 0 && u->resolved->no_port) + || uscf->port == u->resolved->port) + && ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0) + { + goto found; + } + } + + if (u->resolved->port == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "no port in upstream \"%V\"", host); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + temp.name = *host; + + ctx = ngx_resolve_start(clcf->resolver, &temp); + if (ctx == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + if (ctx == NGX_NO_RESOLVER) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "no resolver defined to resolve %V", host); + + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); + return; + } + + ctx->name = *host; + ctx->handler = ngx_http_upstream_resolve_handler; + ctx->data = r; + ctx->timeout = clcf->resolver_timeout; + + u->resolved->ctx = ctx; + + if (ngx_resolve_name(ctx) != NGX_OK) { + u->resolved->ctx = NULL; + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + return; + } + +found: + + if (uscf == NULL) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "no upstream configuration"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + +#if (NGX_HTTP_SSL) + u->ssl_name = uscf->host; +#endif + + if (uscf->peer.init(r, uscf) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + u->peer.start_time = ngx_current_msec; + + if (u->conf->next_upstream_tries + && u->peer.tries > u->conf->next_upstream_tries) + { + u->peer.tries = u->conf->next_upstream_tries; + } + + ngx_http_upstream_connect(r, u); +} + + +#if (NGX_HTTP_CACHE) + +static ngx_int_t +ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ngx_int_t rc; + ngx_http_cache_t *c; + ngx_http_file_cache_t *cache; + + c = r->cache; + + if (c == NULL) { + + if (!(r->method & u->conf->cache_methods)) { + return NGX_DECLINED; + } + + rc = ngx_http_upstream_cache_get(r, u, &cache); + + if (rc != NGX_OK) { + return rc; + } + + if (r->method & NGX_HTTP_HEAD) { + u->method = ngx_http_core_get_method; + } + + if (ngx_http_file_cache_new(r) != NGX_OK) { + return NGX_ERROR; + } + + if (u->create_key(r) != NGX_OK) { + return NGX_ERROR; + } + + /* TODO: add keys */ + + ngx_http_file_cache_create_key(r); + + if (r->cache->header_start + 256 >= u->conf->buffer_size) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "%V_buffer_size %uz is not enough for cache key, " + "it should be increased to at least %uz", + &u->conf->module, u->conf->buffer_size, + ngx_align(r->cache->header_start + 256, 1024)); + + r->cache = NULL; + return NGX_DECLINED; + } + + u->cacheable = 1; + + c = r->cache; + + c->body_start = u->conf->buffer_size; + c->min_uses = u->conf->cache_min_uses; + c->file_cache = cache; + + switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) { + + case NGX_ERROR: + return NGX_ERROR; + + case NGX_DECLINED: + u->cache_status = NGX_HTTP_CACHE_BYPASS; + return NGX_DECLINED; + + default: /* NGX_OK */ + break; + } + + c->lock = u->conf->cache_lock; + c->lock_timeout = u->conf->cache_lock_timeout; + c->lock_age = u->conf->cache_lock_age; + + u->cache_status = NGX_HTTP_CACHE_MISS; + } + + rc = ngx_http_file_cache_open(r); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream cache: %i", rc); + + switch (rc) { + + case NGX_HTTP_CACHE_UPDATING: + + if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { + u->cache_status = rc; + rc = NGX_OK; + + } else { + rc = NGX_HTTP_CACHE_STALE; + } + + break; + + case NGX_OK: + u->cache_status = NGX_HTTP_CACHE_HIT; + } + + switch (rc) { + + case NGX_OK: + + return NGX_OK; + + case NGX_HTTP_CACHE_STALE: + + c->valid_sec = 0; + u->buffer.start = NULL; + u->cache_status = NGX_HTTP_CACHE_EXPIRED; + + break; + + case NGX_DECLINED: + + if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) { + u->buffer.start = NULL; + + } else { + u->buffer.pos = u->buffer.start + c->header_start; + u->buffer.last = u->buffer.pos; + } + + break; + + case NGX_HTTP_CACHE_SCARCE: + + u->cacheable = 0; + + break; + + case NGX_AGAIN: + + return NGX_BUSY; + + case NGX_ERROR: + + return NGX_ERROR; + + default: + + /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ + + u->cache_status = NGX_HTTP_CACHE_HIT; + + return rc; + } + + r->cached = 0; + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_http_upstream_cache_get(ngx_http_request_t *r, ngx_http_upstream_t *u, + ngx_http_file_cache_t **cache) +{ + ngx_str_t *name, val; + ngx_uint_t i; + ngx_http_file_cache_t **caches; + + if (u->conf->cache_zone) { + *cache = u->conf->cache_zone->data; + return NGX_OK; + } + + if (ngx_http_complex_value(r, u->conf->cache_value, &val) != NGX_OK) { + return NGX_ERROR; + } + + if (val.len == 0 + || (val.len == 3 && ngx_strncmp(val.data, "off", 3) == 0)) + { + return NGX_DECLINED; + } + + caches = u->caches->elts; + + for (i = 0; i < u->caches->nelts; i++) { + name = &caches[i]->shm_zone->shm.name; + + if (name->len == val.len + && ngx_strncmp(name->data, val.data, val.len) == 0) + { + *cache = caches[i]; + return NGX_OK; + } + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "cache \"%V\" not found", &val); + + return NGX_ERROR; +} + + +static ngx_int_t +ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ngx_int_t rc; + ngx_http_cache_t *c; + + r->cached = 1; + c = r->cache; + + if (c->header_start == c->body_start) { + r->http_version = NGX_HTTP_VERSION_9; + return ngx_http_cache_send(r); + } + + /* TODO: cache stack */ + + u->buffer = *c->buf; + u->buffer.pos += c->header_start; + + ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); + u->headers_in.content_length_n = -1; + u->headers_in.last_modified_time = -1; + + if (ngx_list_init(&u->headers_in.headers, r->pool, 8, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + rc = u->process_header(r); + + if (rc == NGX_OK) { + + if (ngx_http_upstream_process_headers(r, u) != NGX_OK) { + return NGX_DONE; + } + + return ngx_http_cache_send(r); + } + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */ + + /* TODO: delete file */ + + return rc; +} + +#endif + + +static void +ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_upstream_t *u; + ngx_http_upstream_resolved_t *ur; + + r = ctx->data; + c = r->connection; + + u = r->upstream; + ur = u->resolved; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream resolve: \"%V?%V\"", &r->uri, &r->args); + + if (ctx->state) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "%V could not be resolved (%i: %s)", + &ctx->name, ctx->state, + ngx_resolver_strerror(ctx->state)); + + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); + goto failed; + } + + ur->naddrs = ctx->naddrs; + ur->addrs = ctx->addrs; + +#if (NGX_DEBUG) + { + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_str_t addr; + ngx_uint_t i; + + addr.data = text; + + for (i = 0; i < ctx->naddrs; i++) { + addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen, + text, NGX_SOCKADDR_STRLEN, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "name was resolved to %V", &addr); + } + } +#endif + + if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + goto failed; + } + + ngx_resolve_name_done(ctx); + ur->ctx = NULL; + + u->peer.start_time = ngx_current_msec; + + if (u->conf->next_upstream_tries + && u->peer.tries > u->conf->next_upstream_tries) + { + u->peer.tries = u->conf->next_upstream_tries; + } + + ngx_http_upstream_connect(r, u); + +failed: + + ngx_http_run_posted_requests(c); +} + + +static void +ngx_http_upstream_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_upstream_t *u; + + c = ev->data; + r = c->data; + + u = r->upstream; + c = r->connection; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream request: \"%V?%V\"", &r->uri, &r->args); + + if (ev->write) { + u->write_event_handler(r, u); + + } else { + u->read_event_handler(r, u); + } + + ngx_http_run_posted_requests(c); +} + + +static void +ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r) +{ + ngx_http_upstream_check_broken_connection(r, r->connection->read); +} + + +static void +ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r) +{ + ngx_http_upstream_check_broken_connection(r, r->connection->write); +} + + +static void +ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, + ngx_event_t *ev) +{ + int n; + char buf[1]; + ngx_err_t err; + ngx_int_t event; + ngx_connection_t *c; + ngx_http_upstream_t *u; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0, + "http upstream check client, write event:%d, \"%V\"", + ev->write, &r->uri); + + c = r->connection; + u = r->upstream; + + if (c->error) { + if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) { + + event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT; + + if (ngx_del_event(ev, event, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + + if (!u->cacheable) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + } + + return; + } + +#if (NGX_HTTP_SPDY) + if (r->spdy_stream) { + return; + } +#endif + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + + if (!ev->pending_eof) { + return; + } + + ev->eof = 1; + c->error = 1; + + if (ev->kq_errno) { + ev->error = 1; + } + + if (!u->cacheable && u->peer.connection) { + ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, + "kevent() reported that client prematurely closed " + "connection, so upstream connection is closed too"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + + ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, + "kevent() reported that client prematurely closed " + "connection"); + + if (u->peer.connection == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + } + + return; + } + +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ev->pending_eof) { + socklen_t len; + + ev->eof = 1; + c->error = 1; + + err = 0; + len = sizeof(ngx_err_t); + + /* + * BSDs and Linux return 0 and set a pending error in err + * Solaris returns -1 and sets errno + */ + + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) + == -1) + { + err = ngx_socket_errno; + } + + if (err) { + ev->error = 1; + } + + if (!u->cacheable && u->peer.connection) { + ngx_log_error(NGX_LOG_INFO, ev->log, err, + "epoll_wait() reported that client prematurely closed " + "connection, so upstream connection is closed too"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + + ngx_log_error(NGX_LOG_INFO, ev->log, err, + "epoll_wait() reported that client prematurely closed " + "connection"); + + if (u->peer.connection == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + } + + return; + } + +#endif + + n = recv(c->fd, buf, 1, MSG_PEEK); + + err = ngx_socket_errno; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, err, + "http upstream recv(): %d", n); + + if (ev->write && (n >= 0 || err == NGX_EAGAIN)) { + return; + } + + if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) { + + event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT; + + if (ngx_del_event(ev, event, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + + if (n > 0) { + return; + } + + if (n == -1) { + if (err == NGX_EAGAIN) { + return; + } + + ev->error = 1; + + } else { /* n == 0 */ + err = 0; + } + + ev->eof = 1; + c->error = 1; + + if (!u->cacheable && u->peer.connection) { + ngx_log_error(NGX_LOG_INFO, ev->log, err, + "client prematurely closed connection, " + "so upstream connection is closed too"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + + ngx_log_error(NGX_LOG_INFO, ev->log, err, + "client prematurely closed connection"); + + if (u->peer.connection == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + } +} + + +static void +ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ngx_int_t rc; + ngx_time_t *tp; + ngx_connection_t *c; + + r->connection->log->action = "connecting to upstream"; + + if (u->state && u->state->response_sec) { + tp = ngx_timeofday(); + u->state->response_sec = tp->sec - u->state->response_sec; + u->state->response_msec = tp->msec - u->state->response_msec; + } + + u->state = ngx_array_push(r->upstream_states); + if (u->state == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); + + tp = ngx_timeofday(); + u->state->response_sec = tp->sec; + u->state->response_msec = tp->msec; + u->state->header_sec = (time_t) NGX_ERROR; + + rc = ngx_event_connect_peer(&u->peer); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream connect: %i", rc); + + if (rc == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + u->state->peer = u->peer.name; + + if (rc == NGX_BUSY) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams"); + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE); + return; + } + + if (rc == NGX_DECLINED) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + return; + } + + /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */ + + c = u->peer.connection; + + c->data = r; + + c->write->handler = ngx_http_upstream_handler; + c->read->handler = ngx_http_upstream_handler; + + u->write_event_handler = ngx_http_upstream_send_request_handler; + u->read_event_handler = ngx_http_upstream_process_header; + + c->sendfile &= r->connection->sendfile; + u->output.sendfile = c->sendfile; + + if (c->pool == NULL) { + + /* we need separate pool here to be able to cache SSL connections */ + + c->pool = ngx_create_pool(128, r->connection->log); + if (c->pool == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + + c->log = r->connection->log; + c->pool->log = c->log; + c->read->log = c->log; + c->write->log = c->log; + + /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */ + + u->writer.out = NULL; + u->writer.last = &u->writer.out; + u->writer.connection = c; + u->writer.limit = 0; + + if (u->request_sent) { + if (ngx_http_upstream_reinit(r, u) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + + if (r->request_body + && r->request_body->buf + && r->request_body->temp_file + && r == r->main) + { + /* + * the r->request_body->buf can be reused for one request only, + * the subrequests should allocate their own temporary bufs + */ + + u->output.free = ngx_alloc_chain_link(r->pool); + if (u->output.free == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + u->output.free->buf = r->request_body->buf; + u->output.free->next = NULL; + u->output.allocated = 1; + + r->request_body->buf->pos = r->request_body->buf->start; + r->request_body->buf->last = r->request_body->buf->start; + r->request_body->buf->tag = u->output.tag; + } + + u->request_sent = 0; + + if (rc == NGX_AGAIN) { + ngx_add_timer(c->write, u->conf->connect_timeout); + return; + } + +#if (NGX_HTTP_SSL) + + if (u->ssl && c->ssl == NULL) { + ngx_http_upstream_ssl_init_connection(r, u, c); + return; + } + +#endif + + ngx_http_upstream_send_request(r, u, 1); +} + + +#if (NGX_HTTP_SSL) + +static void +ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c) +{ + int tcp_nodelay; + ngx_int_t rc; + ngx_http_core_loc_conf_t *clcf; + + if (ngx_http_upstream_test_connect(c) != NGX_OK) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + return; + } + + if (ngx_ssl_create_connection(u->conf->ssl, c, + NGX_SSL_BUFFER|NGX_SSL_CLIENT) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + c->sendfile = 0; + u->output.sendfile = 0; + + if (u->conf->ssl_server_name || u->conf->ssl_verify) { + if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + + if (u->conf->ssl_session_reuse) { + if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + /* abbreviated SSL handshake may interact badly with Nagle */ + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + } + + r->connection->log->action = "SSL handshaking to upstream"; + + rc = ngx_ssl_handshake(c); + + if (rc == NGX_AGAIN) { + + if (!c->write->timer_set) { + ngx_add_timer(c->write, u->conf->connect_timeout); + } + + c->ssl->handler = ngx_http_upstream_ssl_handshake; + return; + } + + ngx_http_upstream_ssl_handshake(c); +} + + +static void +ngx_http_upstream_ssl_handshake(ngx_connection_t *c) +{ + long rc; + ngx_http_request_t *r; + ngx_http_upstream_t *u; + + r = c->data; + u = r->upstream; + + ngx_http_set_log_request(c->log, r); + + if (c->ssl->handshaked) { + + if (u->conf->ssl_verify) { + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + goto failed; + } + + if (ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate does not match \"%V\"", + &u->ssl_name); + goto failed; + } + } + + if (u->conf->ssl_session_reuse) { + u->peer.save_session(&u->peer, u->peer.data); + } + + c->write->handler = ngx_http_upstream_handler; + c->read->handler = ngx_http_upstream_handler; + + c = r->connection; + + ngx_http_upstream_send_request(r, u, 1); + + ngx_http_run_posted_requests(c); + return; + } + +failed: + + c = r->connection; + + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + + ngx_http_run_posted_requests(c); +} + + +static ngx_int_t +ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u, + ngx_connection_t *c) +{ + u_char *p, *last; + ngx_str_t name; + + if (u->conf->ssl_name) { + if (ngx_http_complex_value(r, u->conf->ssl_name, &name) != NGX_OK) { + return NGX_ERROR; + } + + } else { + name = u->ssl_name; + } + + if (name.len == 0) { + goto done; + } + + /* + * ssl name here may contain port, notably if derived from $proxy_host + * or $http_host; we have to strip it + */ + + p = name.data; + last = name.data + name.len; + + if (*p == '[') { + p = ngx_strlchr(p, last, ']'); + + if (p == NULL) { + p = name.data; + } + } + + p = ngx_strlchr(p, last, ':'); + + if (p != NULL) { + name.len = p - name.data; + } + + if (!u->conf->ssl_server_name) { + goto done; + } + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */ + + if (name.len == 0 || *name.data == '[') { + goto done; + } + + if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) { + goto done; + } + + /* + * SSL_set_tlsext_host_name() needs a null-terminated string, + * hence we explicitly null-terminate name here + */ + + p = ngx_pnalloc(r->pool, name.len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + (void) ngx_cpystrn(p, name.data, name.len + 1); + + name.data = p; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "upstream SSL server name: \"%s\"", name.data); + + if (SSL_set_tlsext_host_name(c->ssl->connection, name.data) == 0) { + ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0, + "SSL_set_tlsext_host_name(\"%s\") failed", name.data); + return NGX_ERROR; + } + +#endif + +done: + + u->ssl_name = name; + + return NGX_OK; +} + +#endif + + +static ngx_int_t +ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + off_t file_pos; + ngx_chain_t *cl; + + if (u->reinit_request(r) != NGX_OK) { + return NGX_ERROR; + } + + u->keepalive = 0; + u->upgrade = 0; + + ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); + u->headers_in.content_length_n = -1; + u->headers_in.last_modified_time = -1; + + if (ngx_list_init(&u->headers_in.headers, r->pool, 8, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + /* reinit the request chain */ + + file_pos = 0; + + for (cl = u->request_bufs; cl; cl = cl->next) { + cl->buf->pos = cl->buf->start; + + /* there is at most one file */ + + if (cl->buf->in_file) { + cl->buf->file_pos = file_pos; + file_pos = cl->buf->file_last; + } + } + + /* reinit the subrequest's ngx_output_chain() context */ + + if (r->request_body && r->request_body->temp_file + && r != r->main && u->output.buf) + { + u->output.free = ngx_alloc_chain_link(r->pool); + if (u->output.free == NULL) { + return NGX_ERROR; + } + + u->output.free->buf = u->output.buf; + u->output.free->next = NULL; + + u->output.buf->pos = u->output.buf->start; + u->output.buf->last = u->output.buf->start; + } + + u->output.buf = NULL; + u->output.in = NULL; + u->output.busy = NULL; + + /* reinit u->buffer */ + + u->buffer.pos = u->buffer.start; + +#if (NGX_HTTP_CACHE) + + if (r->cache) { + u->buffer.pos += r->cache->header_start; + } + +#endif + + u->buffer.last = u->buffer.pos; + + return NGX_OK; +} + + +static void +ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u, + ngx_uint_t do_write) +{ + ngx_int_t rc; + ngx_connection_t *c; + + c = u->peer.connection; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream send request"); + + if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + return; + } + + c->log->action = "sending request to upstream"; + + rc = ngx_http_upstream_send_request_body(r, u, do_write); + + if (rc == NGX_ERROR) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + return; + } + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + ngx_http_upstream_finalize_request(r, u, rc); + return; + } + + if (rc == NGX_AGAIN) { + if (!c->write->ready) { + ngx_add_timer(c->write, u->conf->send_timeout); + + } else if (c->write->timer_set) { + ngx_del_timer(c->write); + } + + if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + return; + } + + /* rc == NGX_OK */ + + if (c->write->timer_set) { + ngx_del_timer(c->write); + } + + if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { + if (ngx_tcp_push(c->fd) == NGX_ERROR) { + ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, + ngx_tcp_push_n " failed"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + } + + u->write_event_handler = ngx_http_upstream_dummy_handler; + + if (ngx_handle_write_event(c->write, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_add_timer(c->read, u->conf->read_timeout); + + if (c->read->ready) { + ngx_http_upstream_process_header(r, u); + return; + } +} + + +static ngx_int_t +ngx_http_upstream_send_request_body(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_uint_t do_write) +{ + int tcp_nodelay; + ngx_int_t rc; + ngx_chain_t *out, *cl, *ln; + ngx_connection_t *c; + ngx_http_core_loc_conf_t *clcf; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream send request body"); + + if (!r->request_body_no_buffering) { + + /* buffered request body */ + + if (!u->request_sent) { + u->request_sent = 1; + out = u->request_bufs; + + } else { + out = NULL; + } + + return ngx_output_chain(&u->output, out); + } + + if (!u->request_sent) { + u->request_sent = 1; + out = u->request_bufs; + + if (r->request_body->bufs) { + for (cl = out; cl->next; cl = out->next) { /* void */ } + cl->next = r->request_body->bufs; + r->request_body->bufs = NULL; + } + + c = u->peer.connection; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + return NGX_ERROR; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + r->read_event_handler = ngx_http_upstream_read_request_handler; + + } else { + out = NULL; + } + + for ( ;; ) { + + if (do_write) { + rc = ngx_output_chain(&u->output, out); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + while (out) { + ln = out; + out = out->next; + ngx_free_chain(r->pool, ln); + } + + if (rc == NGX_OK && !r->reading_body) { + break; + } + } + + if (r->reading_body) { + /* read client request body */ + + rc = ngx_http_read_unbuffered_request_body(r); + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + return rc; + } + + out = r->request_body->bufs; + r->request_body->bufs = NULL; + } + + /* stop if there is nothing to send */ + + if (out == NULL) { + rc = NGX_AGAIN; + break; + } + + do_write = 1; + } + + if (!r->reading_body) { + if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { + r->read_event_handler = + ngx_http_upstream_rd_check_broken_connection; + } + } + + return rc; +} + + +static void +ngx_http_upstream_send_request_handler(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_connection_t *c; + + c = u->peer.connection; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream send request handler"); + + if (c->write->timedout) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT); + return; + } + +#if (NGX_HTTP_SSL) + + if (u->ssl && c->ssl == NULL) { + ngx_http_upstream_ssl_init_connection(r, u, c); + return; + } + +#endif + + if (u->header_sent) { + u->write_event_handler = ngx_http_upstream_dummy_handler; + + (void) ngx_handle_write_event(c->write, 0); + + return; + } + + ngx_http_upstream_send_request(r, u, 1); +} + + +static void +ngx_http_upstream_read_request_handler(ngx_http_request_t *r) +{ + ngx_connection_t *c; + ngx_http_upstream_t *u; + + c = r->connection; + u = r->upstream; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream read request handler"); + + if (c->read->timedout) { + c->timedout = 1; + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + + ngx_http_upstream_send_request(r, u, 0); +} + + +static void +ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ssize_t n; + ngx_int_t rc; + ngx_time_t *tp; + ngx_connection_t *c; + + c = u->peer.connection; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process header"); + + c->log->action = "reading response header from upstream"; + + if (c->read->timedout) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT); + return; + } + + if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + return; + } + + if (u->buffer.start == NULL) { + u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size); + if (u->buffer.start == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + u->buffer.pos = u->buffer.start; + u->buffer.last = u->buffer.start; + u->buffer.end = u->buffer.start + u->conf->buffer_size; + u->buffer.temporary = 1; + + u->buffer.tag = u->output.tag; + + if (ngx_list_init(&u->headers_in.headers, r->pool, 8, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + +#if (NGX_HTTP_CACHE) + + if (r->cache) { + u->buffer.pos += r->cache->header_start; + u->buffer.last = u->buffer.pos; + } +#endif + } + + for ( ;; ) { + + n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last); + + if (n == NGX_AGAIN) { +#if 0 + ngx_add_timer(rev, u->read_timeout); +#endif + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + return; + } + + if (n == 0) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream prematurely closed connection"); + } + + if (n == NGX_ERROR || n == 0) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + return; + } + + u->buffer.last += n; + +#if 0 + u->valid_header_in = 0; + + u->peer.cached = 0; +#endif + + rc = u->process_header(r); + + if (rc == NGX_AGAIN) { + + if (u->buffer.last == u->buffer.end) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream sent too big header"); + + ngx_http_upstream_next(r, u, + NGX_HTTP_UPSTREAM_FT_INVALID_HEADER); + return; + } + + continue; + } + + break; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER); + return; + } + + if (rc == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + /* rc == NGX_OK */ + + tp = ngx_timeofday(); + u->state->header_sec = tp->sec - u->state->response_sec; + u->state->header_msec = tp->msec - u->state->response_msec; + + if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) { + + if (ngx_http_upstream_test_next(r, u) == NGX_OK) { + return; + } + + if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) { + return; + } + } + + if (ngx_http_upstream_process_headers(r, u) != NGX_OK) { + return; + } + + if (!r->subrequest_in_memory) { + ngx_http_upstream_send_response(r, u); + return; + } + + /* subrequest content in memory */ + + if (u->input_filter == NULL) { + u->input_filter_init = ngx_http_upstream_non_buffered_filter_init; + u->input_filter = ngx_http_upstream_non_buffered_filter; + u->input_filter_ctx = r; + } + + if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + n = u->buffer.last - u->buffer.pos; + + if (n) { + u->buffer.last = u->buffer.pos; + + u->state->response_length += n; + + if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + + if (u->length == 0) { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + u->read_event_handler = ngx_http_upstream_process_body_in_memory; + + ngx_http_upstream_process_body_in_memory(r, u); +} + + +static ngx_int_t +ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ngx_uint_t status; + ngx_http_upstream_next_t *un; + + status = u->headers_in.status_n; + + for (un = ngx_http_upstream_next_errors; un->status; un++) { + + if (status != un->status) { + continue; + } + + if (u->peer.tries > 1 && (u->conf->next_upstream & un->mask)) { + ngx_http_upstream_next(r, u, un->mask); + return NGX_OK; + } + +#if (NGX_HTTP_CACHE) + + if (u->cache_status == NGX_HTTP_CACHE_EXPIRED + && (u->conf->cache_use_stale & un->mask)) + { + ngx_int_t rc; + + rc = u->reinit_request(r); + + if (rc == NGX_OK) { + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); + } + + ngx_http_upstream_finalize_request(r, u, rc); + return NGX_OK; + } + +#endif + } + +#if (NGX_HTTP_CACHE) + + if (status == NGX_HTTP_NOT_MODIFIED + && u->cache_status == NGX_HTTP_CACHE_EXPIRED + && u->conf->cache_revalidate) + { + time_t now, valid; + ngx_int_t rc; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream not modified"); + + now = ngx_time(); + valid = r->cache->valid_sec; + + rc = u->reinit_request(r); + + if (rc != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, rc); + return NGX_OK; + } + + u->cache_status = NGX_HTTP_CACHE_REVALIDATED; + rc = ngx_http_upstream_cache_send(r, u); + + if (valid == 0) { + valid = r->cache->valid_sec; + } + + if (valid == 0) { + valid = ngx_http_file_cache_valid(u->conf->cache_valid, + u->headers_in.status_n); + if (valid) { + valid = now + valid; + } + } + + if (valid) { + r->cache->valid_sec = valid; + r->cache->date = now; + + ngx_http_file_cache_update_header(r); + } + + ngx_http_upstream_finalize_request(r, u, rc); + return NGX_OK; + } + +#endif + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_http_upstream_intercept_errors(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_int_t status; + ngx_uint_t i; + ngx_table_elt_t *h; + ngx_http_err_page_t *err_page; + ngx_http_core_loc_conf_t *clcf; + + status = u->headers_in.status_n; + + if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) { + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND); + return NGX_OK; + } + + if (!u->conf->intercept_errors) { + return NGX_DECLINED; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->error_pages == NULL) { + return NGX_DECLINED; + } + + err_page = clcf->error_pages->elts; + for (i = 0; i < clcf->error_pages->nelts; i++) { + + if (err_page[i].status == status) { + + if (status == NGX_HTTP_UNAUTHORIZED + && u->headers_in.www_authenticate) + { + h = ngx_list_push(&r->headers_out.headers); + + if (h == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_OK; + } + + *h = *u->headers_in.www_authenticate; + + r->headers_out.www_authenticate = h; + } + +#if (NGX_HTTP_CACHE) + + if (r->cache) { + time_t valid; + + valid = ngx_http_file_cache_valid(u->conf->cache_valid, status); + + if (valid) { + r->cache->valid_sec = ngx_time() + valid; + r->cache->error = status; + } + + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); + } +#endif + ngx_http_upstream_finalize_request(r, u, status); + + return NGX_OK; + } + } + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_http_upstream_test_connect(ngx_connection_t *c) +{ + int err; + socklen_t len; + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + if (c->write->pending_eof || c->read->pending_eof) { + if (c->write->pending_eof) { + err = c->write->kq_errno; + + } else { + err = c->read->kq_errno; + } + + c->log->action = "connecting to upstream"; + (void) ngx_connection_error(c, err, + "kevent() reported that connect() failed"); + return NGX_ERROR; + } + + } else +#endif + { + err = 0; + len = sizeof(int); + + /* + * BSDs and Linux return 0 and set a pending error in err + * Solaris returns -1 and sets errno + */ + + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) + == -1) + { + err = ngx_socket_errno; + } + + if (err) { + c->log->action = "connecting to upstream"; + (void) ngx_connection_error(c, err, "connect() failed"); + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ngx_str_t uri, args; + ngx_uint_t i, flags; + ngx_list_part_t *part; + ngx_table_elt_t *h; + ngx_http_upstream_header_t *hh; + ngx_http_upstream_main_conf_t *umcf; + + umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); + + if (u->headers_in.x_accel_redirect + && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT)) + { + ngx_http_upstream_finalize_request(r, u, NGX_DECLINED); + + part = &u->headers_in.headers.part; + h = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + h = part->elts; + i = 0; + } + + hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash, + h[i].lowcase_key, h[i].key.len); + + if (hh && hh->redirect) { + if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) { + ngx_http_finalize_request(r, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_DONE; + } + } + } + + uri = u->headers_in.x_accel_redirect->value; + + if (uri.data[0] == '@') { + ngx_http_named_location(r, &uri); + + } else { + ngx_str_null(&args); + flags = NGX_HTTP_LOG_UNSAFE; + + if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) { + ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); + return NGX_DONE; + } + + if (r->method != NGX_HTTP_HEAD) { + r->method = NGX_HTTP_GET; + } + + ngx_http_internal_redirect(r, &uri, &args); + } + + ngx_http_finalize_request(r, NGX_DONE); + return NGX_DONE; + } + + part = &u->headers_in.headers.part; + h = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + h = part->elts; + i = 0; + } + + if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash, + h[i].lowcase_key, h[i].key.len)) + { + continue; + } + + hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash, + h[i].lowcase_key, h[i].key.len); + + if (hh) { + if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_DONE; + } + + continue; + } + + if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_DONE; + } + } + + if (r->headers_out.server && r->headers_out.server->value.data == NULL) { + r->headers_out.server->hash = 0; + } + + if (r->headers_out.date && r->headers_out.date->value.data == NULL) { + r->headers_out.date->hash = 0; + } + + r->headers_out.status = u->headers_in.status_n; + r->headers_out.status_line = u->headers_in.status_line; + + r->headers_out.content_length_n = u->headers_in.content_length_n; + + r->disable_not_modified = !u->cacheable; + + if (u->conf->force_ranges) { + r->allow_ranges = 1; + r->single_range = 1; + +#if (NGX_HTTP_CACHE) + if (r->cached) { + r->single_range = 0; + } +#endif + } + + u->length = -1; + + return NGX_OK; +} + + +static void +ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_event_t *rev; + ngx_connection_t *c; + + c = u->peer.connection; + rev = c->read; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process body on memory"); + + if (rev->timedout) { + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT); + return; + } + + b = &u->buffer; + + for ( ;; ) { + + size = b->end - b->last; + + if (size == 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "upstream buffer is too small to read response"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + n = c->recv(c, b->last, size); + + if (n == NGX_AGAIN) { + break; + } + + if (n == 0 || n == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, n); + return; + } + + u->state->response_length += n; + + if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (!rev->ready) { + break; + } + } + + if (u->length == 0) { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (rev->active) { + ngx_add_timer(rev, u->conf->read_timeout); + + } else if (rev->timer_set) { + ngx_del_timer(rev); + } +} + + +static void +ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + int tcp_nodelay; + ssize_t n; + ngx_int_t rc; + ngx_event_pipe_t *p; + ngx_connection_t *c; + ngx_http_core_loc_conf_t *clcf; + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) { + ngx_http_upstream_finalize_request(r, u, rc); + return; + } + + u->header_sent = 1; + + if (u->upgrade) { + ngx_http_upstream_upgrade(r, u); + return; + } + + c = r->connection; + + if (r->header_only) { + + if (!u->buffering) { + ngx_http_upstream_finalize_request(r, u, rc); + return; + } + + if (!u->cacheable && !u->store) { + ngx_http_upstream_finalize_request(r, u, rc); + return; + } + + u->pipe->downstream_error = 1; + } + + if (r->request_body && r->request_body->temp_file) { + ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd); + r->request_body->temp_file->file.fd = NGX_INVALID_FILE; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (!u->buffering) { + + if (u->input_filter == NULL) { + u->input_filter_init = ngx_http_upstream_non_buffered_filter_init; + u->input_filter = ngx_http_upstream_non_buffered_filter; + u->input_filter_ctx = r; + } + + u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream; + r->write_event_handler = + ngx_http_upstream_process_non_buffered_downstream; + + r->limit_rate = 0; + + if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + n = u->buffer.last - u->buffer.pos; + + if (n) { + u->buffer.last = u->buffer.pos; + + u->state->response_length += n; + + if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + ngx_http_upstream_process_non_buffered_downstream(r); + + } else { + u->buffer.pos = u->buffer.start; + u->buffer.last = u->buffer.start; + + if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (u->peer.connection->read->ready || u->length == 0) { + ngx_http_upstream_process_non_buffered_upstream(r, u); + } + } + + return; + } + + /* TODO: preallocate event_pipe bufs, look "Content-Length" */ + +#if (NGX_HTTP_CACHE) + + if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) { + ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd); + r->cache->file.fd = NGX_INVALID_FILE; + } + + switch (ngx_http_test_predicates(r, u->conf->no_cache)) { + + case NGX_ERROR: + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + + case NGX_DECLINED: + u->cacheable = 0; + break; + + default: /* NGX_OK */ + + if (u->cache_status == NGX_HTTP_CACHE_BYPASS) { + + /* create cache if previously bypassed */ + + if (ngx_http_file_cache_create(r) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + + break; + } + + if (u->cacheable) { + time_t now, valid; + + now = ngx_time(); + + valid = r->cache->valid_sec; + + if (valid == 0) { + valid = ngx_http_file_cache_valid(u->conf->cache_valid, + u->headers_in.status_n); + if (valid) { + r->cache->valid_sec = now + valid; + } + } + + if (valid) { + r->cache->date = now; + r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start); + + if (u->headers_in.status_n == NGX_HTTP_OK + || u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT) + { + r->cache->last_modified = u->headers_in.last_modified_time; + + if (u->headers_in.etag) { + r->cache->etag = u->headers_in.etag->value; + + } else { + ngx_str_null(&r->cache->etag); + } + + } else { + r->cache->last_modified = -1; + ngx_str_null(&r->cache->etag); + } + + if (ngx_http_file_cache_set_header(r, u->buffer.start) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + } else { + u->cacheable = 0; + } + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http cacheable: %d", u->cacheable); + + if (u->cacheable == 0 && r->cache) { + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); + } + +#endif + + p = u->pipe; + + p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter; + p->output_ctx = r; + p->tag = u->output.tag; + p->bufs = u->conf->bufs; + p->busy_size = u->conf->busy_buffers_size; + p->upstream = u->peer.connection; + p->downstream = c; + p->pool = r->pool; + p->log = c->log; + p->limit_rate = u->conf->limit_rate; + p->start_sec = ngx_time(); + + p->cacheable = u->cacheable || u->store; + + p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); + if (p->temp_file == NULL) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + p->temp_file->file.fd = NGX_INVALID_FILE; + p->temp_file->file.log = c->log; + p->temp_file->path = u->conf->temp_path; + p->temp_file->pool = r->pool; + + if (p->cacheable) { + p->temp_file->persistent = 1; + +#if (NGX_HTTP_CACHE) + if (r->cache && r->cache->file_cache->temp_path) { + p->temp_file->path = r->cache->file_cache->temp_path; + } +#endif + + } else { + p->temp_file->log_level = NGX_LOG_WARN; + p->temp_file->warn = "an upstream response is buffered " + "to a temporary file"; + } + + p->max_temp_file_size = u->conf->max_temp_file_size; + p->temp_file_write_size = u->conf->temp_file_write_size; + + p->preread_bufs = ngx_alloc_chain_link(r->pool); + if (p->preread_bufs == NULL) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + p->preread_bufs->buf = &u->buffer; + p->preread_bufs->next = NULL; + u->buffer.recycled = 1; + + p->preread_size = u->buffer.last - u->buffer.pos; + + if (u->cacheable) { + + p->buf_to_file = ngx_calloc_buf(r->pool); + if (p->buf_to_file == NULL) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + p->buf_to_file->start = u->buffer.start; + p->buf_to_file->pos = u->buffer.start; + p->buf_to_file->last = u->buffer.pos; + p->buf_to_file->temporary = 1; + } + + if (ngx_event_flags & NGX_USE_AIO_EVENT) { + /* the posted aio operation may corrupt a shadow buffer */ + p->single_buf = 1; + } + + /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */ + p->free_bufs = 1; + + /* + * event_pipe would do u->buffer.last += p->preread_size + * as though these bytes were read + */ + u->buffer.last = u->buffer.pos; + + if (u->conf->cyclic_temp_file) { + + /* + * we need to disable the use of sendfile() if we use cyclic temp file + * because the writing a new data may interfere with sendfile() + * that uses the same kernel file pages (at least on FreeBSD) + */ + + p->cyclic_temp_file = 1; + c->sendfile = 0; + + } else { + p->cyclic_temp_file = 0; + } + + p->read_timeout = u->conf->read_timeout; + p->send_timeout = clcf->send_timeout; + p->send_lowat = clcf->send_lowat; + + p->length = -1; + + if (u->input_filter_init + && u->input_filter_init(p->input_ctx) != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + u->read_event_handler = ngx_http_upstream_process_upstream; + r->write_event_handler = ngx_http_upstream_process_downstream; + + ngx_http_upstream_process_upstream(r, u); +} + + +static void +ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + int tcp_nodelay; + ngx_connection_t *c; + ngx_http_core_loc_conf_t *clcf; + + c = r->connection; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + /* TODO: prevent upgrade if not requested or not possible */ + + r->keepalive = 0; + c->log->action = "proxying upgraded connection"; + + u->read_event_handler = ngx_http_upstream_upgraded_read_upstream; + u->write_event_handler = ngx_http_upstream_upgraded_write_upstream; + r->read_event_handler = ngx_http_upstream_upgraded_read_downstream; + r->write_event_handler = ngx_http_upstream_upgraded_write_downstream; + + if (clcf->tcp_nodelay) { + tcp_nodelay = 1; + + if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + if (u->peer.connection->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, u->peer.connection->log, 0, + "tcp_nodelay"); + + if (setsockopt(u->peer.connection->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(u->peer.connection, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + u->peer.connection->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + } + + if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (u->peer.connection->read->ready + || u->buffer.pos != u->buffer.last) + { + ngx_post_event(c->read, &ngx_posted_events); + ngx_http_upstream_process_upgraded(r, 1, 1); + return; + } + + ngx_http_upstream_process_upgraded(r, 0, 1); +} + + +static void +ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r) +{ + ngx_http_upstream_process_upgraded(r, 0, 0); +} + + +static void +ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r) +{ + ngx_http_upstream_process_upgraded(r, 1, 1); +} + + +static void +ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_http_upstream_process_upgraded(r, 1, 0); +} + + +static void +ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_http_upstream_process_upgraded(r, 0, 1); +} + + +static void +ngx_http_upstream_process_upgraded(ngx_http_request_t *r, + ngx_uint_t from_upstream, ngx_uint_t do_write) +{ + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_connection_t *c, *downstream, *upstream, *dst, *src; + ngx_http_upstream_t *u; + ngx_http_core_loc_conf_t *clcf; + + c = r->connection; + u = r->upstream; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process upgraded, fu:%ui", from_upstream); + + downstream = c; + upstream = u->peer.connection; + + if (downstream->write->timedout) { + c->timedout = 1; + ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + + if (upstream->read->timedout || upstream->write->timedout) { + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT); + return; + } + + if (from_upstream) { + src = upstream; + dst = downstream; + b = &u->buffer; + + } else { + src = downstream; + dst = upstream; + b = &u->from_client; + + if (r->header_in->last > r->header_in->pos) { + b = r->header_in; + b->end = b->last; + do_write = 1; + } + + if (b->start == NULL) { + b->start = ngx_palloc(r->pool, u->conf->buffer_size); + if (b->start == NULL) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + b->pos = b->start; + b->last = b->start; + b->end = b->start + u->conf->buffer_size; + b->temporary = 1; + b->tag = u->output.tag; + } + } + + for ( ;; ) { + + if (do_write) { + + size = b->last - b->pos; + + if (size && dst->write->ready) { + + n = dst->send(dst, b->pos, size); + + if (n == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (n > 0) { + b->pos += n; + + if (b->pos == b->last) { + b->pos = b->start; + b->last = b->start; + } + } + } + } + + size = b->end - b->last; + + if (size && src->read->ready) { + + n = src->recv(src, b->last, size); + + if (n == NGX_AGAIN || n == 0) { + break; + } + + if (n > 0) { + do_write = 1; + b->last += n; + + continue; + } + + if (n == NGX_ERROR) { + src->read->eof = 1; + } + } + + break; + } + + if ((upstream->read->eof && u->buffer.pos == u->buffer.last) + || (downstream->read->eof && u->from_client.pos == u->from_client.last) + || (downstream->read->eof && upstream->read->eof)) + { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream upgraded done"); + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (ngx_handle_write_event(upstream->write, u->conf->send_lowat) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (upstream->write->active && !upstream->write->ready) { + ngx_add_timer(upstream->write, u->conf->send_timeout); + + } else if (upstream->write->timer_set) { + ngx_del_timer(upstream->write); + } + + if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (upstream->read->active && !upstream->read->ready) { + ngx_add_timer(upstream->read, u->conf->read_timeout); + + } else if (upstream->read->timer_set) { + ngx_del_timer(upstream->read); + } + + if (ngx_handle_write_event(downstream->write, clcf->send_lowat) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (downstream->write->active && !downstream->write->ready) { + ngx_add_timer(downstream->write, clcf->send_timeout); + + } else if (downstream->write->timer_set) { + ngx_del_timer(downstream->write); + } +} + + +static void +ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r) +{ + ngx_event_t *wev; + ngx_connection_t *c; + ngx_http_upstream_t *u; + + c = r->connection; + u = r->upstream; + wev = c->write; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process non buffered downstream"); + + c->log->action = "sending to client"; + + if (wev->timedout) { + c->timedout = 1; + ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + + ngx_http_upstream_process_non_buffered_request(r, 1); +} + + +static void +ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_connection_t *c; + + c = u->peer.connection; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process non buffered upstream"); + + c->log->action = "reading upstream"; + + if (c->read->timedout) { + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT); + return; + } + + ngx_http_upstream_process_non_buffered_request(r, 0); +} + + +static void +ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r, + ngx_uint_t do_write) +{ + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_int_t rc; + ngx_connection_t *downstream, *upstream; + ngx_http_upstream_t *u; + ngx_http_core_loc_conf_t *clcf; + + u = r->upstream; + downstream = r->connection; + upstream = u->peer.connection; + + b = &u->buffer; + + do_write = do_write || u->length == 0; + + for ( ;; ) { + + if (do_write) { + + if (u->out_bufs || u->busy_bufs) { + rc = ngx_http_output_filter(r, u->out_bufs); + + if (rc == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs, + &u->out_bufs, u->output.tag); + } + + if (u->busy_bufs == NULL) { + + if (u->length == 0 + || (upstream->read->eof && u->length == -1)) + { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + if (upstream->read->eof) { + ngx_log_error(NGX_LOG_ERR, upstream->log, 0, + "upstream prematurely closed connection"); + + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_BAD_GATEWAY); + return; + } + + if (upstream->read->error) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_BAD_GATEWAY); + return; + } + + b->pos = b->start; + b->last = b->start; + } + } + + size = b->end - b->last; + + if (size && upstream->read->ready) { + + n = upstream->recv(upstream, b->last, size); + + if (n == NGX_AGAIN) { + break; + } + + if (n > 0) { + u->state->response_length += n; + + if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + + do_write = 1; + + continue; + } + + break; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (downstream->data == r) { + if (ngx_handle_write_event(downstream->write, clcf->send_lowat) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + + if (downstream->write->active && !downstream->write->ready) { + ngx_add_timer(downstream->write, clcf->send_timeout); + + } else if (downstream->write->timer_set) { + ngx_del_timer(downstream->write); + } + + if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (upstream->read->active && !upstream->read->ready) { + ngx_add_timer(upstream->read, u->conf->read_timeout); + + } else if (upstream->read->timer_set) { + ngx_del_timer(upstream->read); + } +} + + +static ngx_int_t +ngx_http_upstream_non_buffered_filter_init(void *data) +{ + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes) +{ + ngx_http_request_t *r = data; + + ngx_buf_t *b; + ngx_chain_t *cl, **ll; + ngx_http_upstream_t *u; + + u = r->upstream; + + for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) { + ll = &cl->next; + } + + cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs); + if (cl == NULL) { + return NGX_ERROR; + } + + *ll = cl; + + cl->buf->flush = 1; + cl->buf->memory = 1; + + b = &u->buffer; + + cl->buf->pos = b->last; + b->last += bytes; + cl->buf->last = b->last; + cl->buf->tag = u->output.tag; + + if (u->length == -1) { + return NGX_OK; + } + + u->length -= bytes; + + return NGX_OK; +} + + +static void +ngx_http_upstream_process_downstream(ngx_http_request_t *r) +{ + ngx_event_t *wev; + ngx_connection_t *c; + ngx_event_pipe_t *p; + ngx_http_upstream_t *u; + + c = r->connection; + u = r->upstream; + p = u->pipe; + wev = c->write; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process downstream"); + + c->log->action = "sending to client"; + + if (wev->timedout) { + + if (wev->delayed) { + + wev->timedout = 0; + wev->delayed = 0; + + if (!wev->ready) { + ngx_add_timer(wev, p->send_timeout); + + if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + } + + return; + } + + if (ngx_event_pipe(p, wev->write) == NGX_ABORT) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + } else { + p->downstream_error = 1; + c->timedout = 1; + ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); + } + + } else { + + if (wev->delayed) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http downstream delayed"); + + if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + } + + return; + } + + if (ngx_event_pipe(p, 1) == NGX_ABORT) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + + ngx_http_upstream_process_request(r, u); +} + + +static void +ngx_http_upstream_process_upstream(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_event_t *rev; + ngx_event_pipe_t *p; + ngx_connection_t *c; + + c = u->peer.connection; + p = u->pipe; + rev = c->read; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process upstream"); + + c->log->action = "reading upstream"; + + if (rev->timedout) { + + if (rev->delayed) { + + rev->timedout = 0; + rev->delayed = 0; + + if (!rev->ready) { + ngx_add_timer(rev, p->read_timeout); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + } + + return; + } + + if (ngx_event_pipe(p, 0) == NGX_ABORT) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + } else { + p->upstream_error = 1; + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); + } + + } else { + + if (rev->delayed) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream delayed"); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + } + + return; + } + + if (ngx_event_pipe(p, 0) == NGX_ABORT) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + + ngx_http_upstream_process_request(r, u); +} + + +static void +ngx_http_upstream_process_request(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_temp_file_t *tf; + ngx_event_pipe_t *p; + + p = u->pipe; + + if (u->peer.connection) { + + if (u->store) { + + if (p->upstream_eof || p->upstream_done) { + + tf = p->temp_file; + + if (u->headers_in.status_n == NGX_HTTP_OK + && (p->upstream_done || p->length == -1) + && (u->headers_in.content_length_n == -1 + || u->headers_in.content_length_n == tf->offset)) + { + ngx_http_upstream_store(r, u); + } + } + } + +#if (NGX_HTTP_CACHE) + + if (u->cacheable) { + + if (p->upstream_done) { + ngx_http_file_cache_update(r, p->temp_file); + + } else if (p->upstream_eof) { + + tf = p->temp_file; + + if (p->length == -1 + && (u->headers_in.content_length_n == -1 + || u->headers_in.content_length_n + == tf->offset - (off_t) r->cache->body_start)) + { + ngx_http_file_cache_update(r, tf); + + } else { + ngx_http_file_cache_free(r->cache, tf); + } + + } else if (p->upstream_error) { + ngx_http_file_cache_free(r->cache, p->temp_file); + } + } + +#endif + + if (p->upstream_done || p->upstream_eof || p->upstream_error) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream exit: %p", p->out); + + if (p->upstream_done + || (p->upstream_eof && p->length == -1)) + { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + if (p->upstream_eof) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "upstream prematurely closed connection"); + } + + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); + return; + } + } + + if (p->downstream_error) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream downstream error"); + + if (!u->cacheable && !u->store && u->peer.connection) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + } + } +} + + +static void +ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + size_t root; + time_t lm; + ngx_str_t path; + ngx_temp_file_t *tf; + ngx_ext_rename_file_t ext; + + tf = u->pipe->temp_file; + + if (tf->file.fd == NGX_INVALID_FILE) { + + /* create file for empty 200 response */ + + tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); + if (tf == NULL) { + return; + } + + tf->file.fd = NGX_INVALID_FILE; + tf->file.log = r->connection->log; + tf->path = u->conf->temp_path; + tf->pool = r->pool; + tf->persistent = 1; + + if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, + tf->persistent, tf->clean, tf->access) + != NGX_OK) + { + return; + } + + u->pipe->temp_file = tf; + } + + ext.access = u->conf->store_access; + ext.path_access = u->conf->store_access; + ext.time = -1; + ext.create_path = 1; + ext.delete_file = 1; + ext.log = r->connection->log; + + if (u->headers_in.last_modified) { + + lm = ngx_http_parse_time(u->headers_in.last_modified->value.data, + u->headers_in.last_modified->value.len); + + if (lm != NGX_ERROR) { + ext.time = lm; + ext.fd = tf->file.fd; + } + } + + if (u->conf->store_lengths == NULL) { + + if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { + return; + } + + } else { + if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0, + u->conf->store_values->elts) + == NULL) + { + return; + } + } + + path.len--; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "upstream stores \"%s\" to \"%s\"", + tf->file.name.data, path.data); + + (void) ngx_ext_rename_file(&tf->file.name, &path, &ext); + + u->store = 0; +} + + +static void +ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u) +{ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream dummy handler"); +} + + +static void +ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, + ngx_uint_t ft_type) +{ + ngx_msec_t timeout; + ngx_uint_t status, state; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http next upstream, %xi", ft_type); + + if (u->peer.sockaddr) { + + if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403 + || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) + { + state = NGX_PEER_NEXT; + + } else { + state = NGX_PEER_FAILED; + } + + u->peer.free(&u->peer, u->peer.data, state); + u->peer.sockaddr = NULL; + } + + if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, + "upstream timed out"); + } + + if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR + && (!u->request_sent || !r->request_body_no_buffering)) + { + status = 0; + + /* TODO: inform balancer instead */ + + u->peer.tries++; + + } else { + switch (ft_type) { + + case NGX_HTTP_UPSTREAM_FT_TIMEOUT: + status = NGX_HTTP_GATEWAY_TIME_OUT; + break; + + case NGX_HTTP_UPSTREAM_FT_HTTP_500: + status = NGX_HTTP_INTERNAL_SERVER_ERROR; + break; + + case NGX_HTTP_UPSTREAM_FT_HTTP_403: + status = NGX_HTTP_FORBIDDEN; + break; + + case NGX_HTTP_UPSTREAM_FT_HTTP_404: + status = NGX_HTTP_NOT_FOUND; + break; + + /* + * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING + * never reach here + */ + + default: + status = NGX_HTTP_BAD_GATEWAY; + } + } + + if (r->connection->error) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + + if (status) { + u->state->status = status; + timeout = u->conf->next_upstream_timeout; + + if (u->peer.tries == 0 + || !(u->conf->next_upstream & ft_type) + || (u->request_sent && r->request_body_no_buffering) + || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) + { +#if (NGX_HTTP_CACHE) + + if (u->cache_status == NGX_HTTP_CACHE_EXPIRED + && (u->conf->cache_use_stale & ft_type)) + { + ngx_int_t rc; + + rc = u->reinit_request(r); + + if (rc == NGX_OK) { + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); + } + + ngx_http_upstream_finalize_request(r, u, rc); + return; + } +#endif + + ngx_http_upstream_finalize_request(r, u, status); + return; + } + } + + if (u->peer.connection) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "close http upstream connection: %d", + u->peer.connection->fd); +#if (NGX_HTTP_SSL) + + if (u->peer.connection->ssl) { + u->peer.connection->ssl->no_wait_shutdown = 1; + u->peer.connection->ssl->no_send_shutdown = 1; + + (void) ngx_ssl_shutdown(u->peer.connection); + } +#endif + + if (u->peer.connection->pool) { + ngx_destroy_pool(u->peer.connection->pool); + } + + ngx_close_connection(u->peer.connection); + u->peer.connection = NULL; + } + + ngx_http_upstream_connect(r, u); +} + + +static void +ngx_http_upstream_cleanup(void *data) +{ + ngx_http_request_t *r = data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "cleanup http upstream request: \"%V\"", &r->uri); + + ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE); +} + + +static void +ngx_http_upstream_finalize_request(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_int_t rc) +{ + ngx_uint_t flush; + ngx_time_t *tp; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "finalize http upstream request: %i", rc); + + if (u->cleanup == NULL) { + /* the request was already finalized */ + ngx_http_finalize_request(r, NGX_DONE); + return; + } + + *u->cleanup = NULL; + u->cleanup = NULL; + + if (u->resolved && u->resolved->ctx) { + ngx_resolve_name_done(u->resolved->ctx); + u->resolved->ctx = NULL; + } + + if (u->state && u->state->response_sec) { + tp = ngx_timeofday(); + u->state->response_sec = tp->sec - u->state->response_sec; + u->state->response_msec = tp->msec - u->state->response_msec; + + if (u->pipe && u->pipe->read_length) { + u->state->response_length = u->pipe->read_length; + } + } + + u->finalize_request(r, rc); + + if (u->peer.free && u->peer.sockaddr) { + u->peer.free(&u->peer, u->peer.data, 0); + u->peer.sockaddr = NULL; + } + + if (u->peer.connection) { + +#if (NGX_HTTP_SSL) + + /* TODO: do not shutdown persistent connection */ + + if (u->peer.connection->ssl) { + + /* + * We send the "close notify" shutdown alert to the upstream only + * and do not wait its "close notify" shutdown alert. + * It is acceptable according to the TLS standard. + */ + + u->peer.connection->ssl->no_wait_shutdown = 1; + + (void) ngx_ssl_shutdown(u->peer.connection); + } +#endif + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "close http upstream connection: %d", + u->peer.connection->fd); + + if (u->peer.connection->pool) { + ngx_destroy_pool(u->peer.connection->pool); + } + + ngx_close_connection(u->peer.connection); + } + + u->peer.connection = NULL; + + if (u->pipe && u->pipe->temp_file) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream temp fd: %d", + u->pipe->temp_file->file.fd); + } + + if (u->store && u->pipe && u->pipe->temp_file + && u->pipe->temp_file->file.fd != NGX_INVALID_FILE) + { + if (ngx_delete_file(u->pipe->temp_file->file.name.data) + == NGX_FILE_ERROR) + { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_delete_file_n " \"%s\" failed", + u->pipe->temp_file->file.name.data); + } + } + +#if (NGX_HTTP_CACHE) + + if (r->cache) { + + if (u->cacheable) { + + if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) { + time_t valid; + + valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc); + + if (valid) { + r->cache->valid_sec = ngx_time() + valid; + r->cache->error = rc; + } + } + } + + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); + } + +#endif + + if (r->subrequest_in_memory + && u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) + { + u->buffer.last = u->buffer.pos; + } + + if (rc == NGX_DECLINED) { + return; + } + + r->connection->log->action = "sending to client"; + + if (!u->header_sent + || rc == NGX_HTTP_REQUEST_TIME_OUT + || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST) + { + ngx_http_finalize_request(r, rc); + return; + } + + flush = 0; + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + rc = NGX_ERROR; + flush = 1; + } + + if (r->header_only) { + ngx_http_finalize_request(r, rc); + return; + } + + if (rc == 0) { + rc = ngx_http_send_special(r, NGX_HTTP_LAST); + + } else if (flush) { + r->keepalive = 0; + rc = ngx_http_send_special(r, NGX_HTTP_FLUSH); + } + + ngx_http_finalize_request(r, rc); +} + + +static ngx_int_t +ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_table_elt_t **ph; + + ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset); + + if (*ph == NULL) { + *ph = h; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_content_length(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + + u->headers_in.content_length = h; + u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_last_modified(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + + u->headers_in.last_modified = h; + +#if (NGX_HTTP_CACHE) + + if (u->cacheable) { + u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data, + h->value.len); + } + +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_array_t *pa; + ngx_table_elt_t **ph; + ngx_http_upstream_t *u; + + u = r->upstream; + pa = &u->headers_in.cookies; + + if (pa->elts == NULL) { + if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK) + { + return NGX_ERROR; + } + } + + ph = ngx_array_push(pa); + if (ph == NULL) { + return NGX_ERROR; + } + + *ph = h; + +#if (NGX_HTTP_CACHE) + if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) { + u->cacheable = 0; + } +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_cache_control(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_array_t *pa; + ngx_table_elt_t **ph; + ngx_http_upstream_t *u; + + u = r->upstream; + pa = &u->headers_in.cache_control; + + if (pa->elts == NULL) { + if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) + { + return NGX_ERROR; + } + } + + ph = ngx_array_push(pa); + if (ph == NULL) { + return NGX_ERROR; + } + + *ph = h; + +#if (NGX_HTTP_CACHE) + { + u_char *p, *start, *last; + ngx_int_t n; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) { + return NGX_OK; + } + + if (r->cache == NULL) { + return NGX_OK; + } + + if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) { + return NGX_OK; + } + + start = h->value.data; + last = start + h->value.len; + + if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL + || ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL + || ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL) + { + u->cacheable = 0; + return NGX_OK; + } + + p = ngx_strlcasestrn(start, last, (u_char *) "s-maxage=", 9 - 1); + offset = 9; + + if (p == NULL) { + p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1); + offset = 8; + } + + if (p == NULL) { + return NGX_OK; + } + + n = 0; + + for (p += offset; p < last; p++) { + if (*p == ',' || *p == ';' || *p == ' ') { + break; + } + + if (*p >= '0' && *p <= '9') { + n = n * 10 + *p - '0'; + continue; + } + + u->cacheable = 0; + return NGX_OK; + } + + if (n == 0) { + u->cacheable = 0; + return NGX_OK; + } + + r->cache->valid_sec = ngx_time() + n; + } +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + u->headers_in.expires = h; + +#if (NGX_HTTP_CACHE) + { + time_t expires; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES) { + return NGX_OK; + } + + if (r->cache == NULL) { + return NGX_OK; + } + + if (r->cache->valid_sec != 0) { + return NGX_OK; + } + + expires = ngx_http_parse_time(h->value.data, h->value.len); + + if (expires == NGX_ERROR || expires < ngx_time()) { + u->cacheable = 0; + return NGX_OK; + } + + r->cache->valid_sec = expires; + } +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_accel_expires(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + u->headers_in.x_accel_expires = h; + +#if (NGX_HTTP_CACHE) + { + u_char *p; + size_t len; + ngx_int_t n; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES) { + return NGX_OK; + } + + if (r->cache == NULL) { + return NGX_OK; + } + + len = h->value.len; + p = h->value.data; + + if (p[0] != '@') { + n = ngx_atoi(p, len); + + switch (n) { + case 0: + u->cacheable = 0; + /* fall through */ + + case NGX_ERROR: + return NGX_OK; + + default: + r->cache->valid_sec = ngx_time() + n; + return NGX_OK; + } + } + + p++; + len--; + + n = ngx_atoi(p, len); + + if (n != NGX_ERROR) { + r->cache->valid_sec = n; + } + } +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_int_t n; + ngx_http_upstream_t *u; + + u = r->upstream; + u->headers_in.x_accel_limit_rate = h; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) { + return NGX_OK; + } + + n = ngx_atoi(h->value.data, h->value.len); + + if (n != NGX_ERROR) { + r->limit_rate = (size_t) n; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + u_char c0, c1, c2; + ngx_http_upstream_t *u; + + u = r->upstream; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING) { + return NGX_OK; + } + + if (u->conf->change_buffering) { + + if (h->value.len == 2) { + c0 = ngx_tolower(h->value.data[0]); + c1 = ngx_tolower(h->value.data[1]); + + if (c0 == 'n' && c1 == 'o') { + u->buffering = 0; + } + + } else if (h->value.len == 3) { + c0 = ngx_tolower(h->value.data[0]); + c1 = ngx_tolower(h->value.data[1]); + c2 = ngx_tolower(h->value.data[2]); + + if (c0 == 'y' && c1 == 'e' && c2 == 's') { + u->buffering = 1; + } + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) { + return NGX_OK; + } + + r->headers_out.override_charset = &h->value; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + r->upstream->headers_in.connection = h; + + if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len, + (u_char *) "close", 5 - 1) + != NULL) + { + r->upstream->headers_in.connection_close = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + r->upstream->headers_in.transfer_encoding = h; + + if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len, + (u_char *) "chunked", 7 - 1) + != NULL) + { + r->upstream->headers_in.chunked = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_vary(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + u->headers_in.vary = h; + +#if (NGX_HTTP_CACHE) + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_VARY) { + return NGX_OK; + } + + if (r->cache == NULL) { + return NGX_OK; + } + + if (h->value.len > NGX_HTTP_CACHE_VARY_LEN + || (h->value.len == 1 && h->value.data[0] == '*')) + { + u->cacheable = 0; + } + + r->cache->vary = h->value; + +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_table_elt_t *ho, **ph; + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + if (offset) { + ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset); + *ph = ho; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_array_t *pa; + ngx_table_elt_t *ho, **ph; + + pa = (ngx_array_t *) ((char *) &r->headers_out + offset); + + if (pa->elts == NULL) { + if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) + { + return NGX_ERROR; + } + } + + ph = ngx_array_push(pa); + if (ph == NULL) { + return NGX_ERROR; + } + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + *ph = ho; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + u_char *p, *last; + + r->headers_out.content_type_len = h->value.len; + r->headers_out.content_type = h->value; + r->headers_out.content_type_lowcase = NULL; + + for (p = h->value.data; *p; p++) { + + if (*p != ';') { + continue; + } + + last = p; + + while (*++p == ' ') { /* void */ } + + if (*p == '\0') { + return NGX_OK; + } + + if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) { + continue; + } + + p += 8; + + r->headers_out.content_type_len = last - h->value.data; + + if (*p == '"') { + p++; + } + + last = h->value.data + h->value.len; + + if (*(last - 1) == '"') { + last--; + } + + r->headers_out.charset.len = last - p; + r->headers_out.charset.data = p; + + return NGX_OK; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_table_elt_t *ho; + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + r->headers_out.last_modified = ho; + +#if (NGX_HTTP_CACHE) + + if (r->upstream->cacheable) { + r->headers_out.last_modified_time = + r->upstream->headers_in.last_modified_time; + } + +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_int_t rc; + ngx_table_elt_t *ho; + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + if (r->upstream->rewrite_redirect) { + rc = r->upstream->rewrite_redirect(r, ho, 0); + + if (rc == NGX_DECLINED) { + return NGX_OK; + } + + if (rc == NGX_OK) { + r->headers_out.location = ho; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "rewritten location: \"%V\"", &ho->value); + } + + return rc; + } + + if (ho->value.data[0] != '/') { + r->headers_out.location = ho; + } + + /* + * we do not set r->headers_out.location here to avoid the handling + * the local redirects without a host name by ngx_http_header_filter() + */ + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + u_char *p; + ngx_int_t rc; + ngx_table_elt_t *ho; + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + if (r->upstream->rewrite_redirect) { + + p = ngx_strcasestrn(ho->value.data, "url=", 4 - 1); + + if (p) { + rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data); + + } else { + return NGX_OK; + } + + if (rc == NGX_DECLINED) { + return NGX_OK; + } + + if (rc == NGX_OK) { + r->headers_out.refresh = ho; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "rewritten refresh: \"%V\"", &ho->value); + } + + return rc; + } + + r->headers_out.refresh = ho; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_int_t rc; + ngx_table_elt_t *ho; + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + if (r->upstream->rewrite_cookie) { + rc = r->upstream->rewrite_cookie(r, ho); + + if (rc == NGX_DECLINED) { + return NGX_OK; + } + +#if (NGX_DEBUG) + if (rc == NGX_OK) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "rewritten cookie: \"%V\"", &ho->value); + } +#endif + + return rc; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_table_elt_t *ho; + + if (r->upstream->conf->force_ranges) { + return NGX_OK; + } + +#if (NGX_HTTP_CACHE) + + if (r->cached) { + r->allow_ranges = 1; + return NGX_OK; + } + + if (r->upstream->cacheable) { + r->allow_ranges = 1; + r->single_range = 1; + return NGX_OK; + } + +#endif + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + r->headers_out.accept_ranges = ho; + + return NGX_OK; +} + + +#if (NGX_HTTP_GZIP) + +static ngx_int_t +ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_table_elt_t *ho; + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + r->headers_out.content_encoding = ho; + + return NGX_OK; +} + +#endif + + +static ngx_int_t +ngx_http_upstream_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_upstream_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_http_upstream_state_t *state; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { + v->not_found = 1; + return NGX_OK; + } + + len = 0; + state = r->upstream_states->elts; + + for (i = 0; i < r->upstream_states->nelts; i++) { + if (state[i].peer) { + len += state[i].peer->len + 2; + + } else { + len += 3; + } + } + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + i = 0; + + for ( ;; ) { + if (state[i].peer) { + p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len); + } + + if (++i == r->upstream_states->nelts) { + break; + } + + if (state[i].peer) { + *p++ = ','; + *p++ = ' '; + + } else { + *p++ = ' '; + *p++ = ':'; + *p++ = ' '; + + if (++i == r->upstream_states->nelts) { + break; + } + + continue; + } + } + + v->len = p - v->data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_status_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_http_upstream_state_t *state; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { + v->not_found = 1; + return NGX_OK; + } + + len = r->upstream_states->nelts * (3 + 2); + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + i = 0; + state = r->upstream_states->elts; + + for ( ;; ) { + if (state[i].status) { + p = ngx_sprintf(p, "%ui", state[i].status); + + } else { + *p++ = '-'; + } + + if (++i == r->upstream_states->nelts) { + break; + } + + if (state[i].peer) { + *p++ = ','; + *p++ = ' '; + + } else { + *p++ = ' '; + *p++ = ':'; + *p++ = ' '; + + if (++i == r->upstream_states->nelts) { + break; + } + + continue; + } + } + + v->len = p - v->data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_response_time_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_msec_int_t ms; + ngx_http_upstream_state_t *state; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { + v->not_found = 1; + return NGX_OK; + } + + len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2); + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + i = 0; + state = r->upstream_states->elts; + + for ( ;; ) { + if (state[i].status) { + + if (data + && state[i].header_sec != (time_t) NGX_ERROR) + { + ms = (ngx_msec_int_t) + (state[i].header_sec * 1000 + state[i].header_msec); + + } else { + ms = (ngx_msec_int_t) + (state[i].response_sec * 1000 + state[i].response_msec); + } + + ms = ngx_max(ms, 0); + p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); + + } else { + *p++ = '-'; + } + + if (++i == r->upstream_states->nelts) { + break; + } + + if (state[i].peer) { + *p++ = ','; + *p++ = ' '; + + } else { + *p++ = ' '; + *p++ = ':'; + *p++ = ' '; + + if (++i == r->upstream_states->nelts) { + break; + } + + continue; + } + } + + v->len = p - v->data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_response_length_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_http_upstream_state_t *state; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { + v->not_found = 1; + return NGX_OK; + } + + len = r->upstream_states->nelts * (NGX_OFF_T_LEN + 2); + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + i = 0; + state = r->upstream_states->elts; + + for ( ;; ) { + p = ngx_sprintf(p, "%O", state[i].response_length); + + if (++i == r->upstream_states->nelts) { + break; + } + + if (state[i].peer) { + *p++ = ','; + *p++ = ' '; + + } else { + *p++ = ' '; + *p++ = ':'; + *p++ = ' '; + + if (++i == r->upstream_states->nelts) { + break; + } + + continue; + } + } + + v->len = p - v->data; + + return NGX_OK; +} + + +ngx_int_t +ngx_http_upstream_header_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->upstream == NULL) { + v->not_found = 1; + return NGX_OK; + } + + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->upstream->headers_in.headers.part, + sizeof("upstream_http_") - 1); +} + + +ngx_int_t +ngx_http_upstream_cookie_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_str_t cookie, s; + + if (r->upstream == NULL) { + v->not_found = 1; + return NGX_OK; + } + + s.len = name->len - (sizeof("upstream_cookie_") - 1); + s.data = name->data + sizeof("upstream_cookie_") - 1; + + if (ngx_http_parse_set_cookie_lines(&r->upstream->headers_in.cookies, + &s, &cookie) + == NGX_DECLINED) + { + v->not_found = 1; + return NGX_OK; + } + + v->len = cookie.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = cookie.data; + + return NGX_OK; +} + + +#if (NGX_HTTP_CACHE) + +ngx_int_t +ngx_http_upstream_cache_status(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t n; + + if (r->upstream == NULL || r->upstream->cache_status == 0) { + v->not_found = 1; + return NGX_OK; + } + + n = r->upstream->cache_status - 1; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = ngx_http_cache_status[n].len; + v->data = ngx_http_cache_status[n].data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_cache_last_modified(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + if (r->upstream == NULL + || !r->upstream->conf->cache_revalidate + || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED + || r->cache->last_modified == -1) + { + v->not_found = 1; + return NGX_OK; + } + + p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_http_time(p, r->cache->last_modified) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_cache_etag(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->upstream == NULL + || !r->upstream->conf->cache_revalidate + || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED + || r->cache->etag.len == 0) + { + v->not_found = 1; + return NGX_OK; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = r->cache->etag.len; + v->data = r->cache->etag.data; + + return NGX_OK; +} + +#endif + + +static char * +ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) +{ + char *rv; + void *mconf; + ngx_str_t *value; + ngx_url_t u; + ngx_uint_t m; + ngx_conf_t pcf; + ngx_http_module_t *module; + ngx_http_conf_ctx_t *ctx, *http_ctx; + ngx_http_upstream_srv_conf_t *uscf; + + ngx_memzero(&u, sizeof(ngx_url_t)); + + value = cf->args->elts; + u.host = value[1]; + u.no_resolve = 1; + u.no_port = 1; + + uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE + |NGX_HTTP_UPSTREAM_WEIGHT + |NGX_HTTP_UPSTREAM_MAX_FAILS + |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT + |NGX_HTTP_UPSTREAM_DOWN + |NGX_HTTP_UPSTREAM_BACKUP); + if (uscf == NULL) { + return NGX_CONF_ERROR; + } + + + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); + if (ctx == NULL) { + return NGX_CONF_ERROR; + } + + http_ctx = cf->ctx; + ctx->main_conf = http_ctx->main_conf; + + /* the upstream{}'s srv_conf */ + + ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); + if (ctx->srv_conf == NULL) { + return NGX_CONF_ERROR; + } + + ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf; + + uscf->srv_conf = ctx->srv_conf; + + + /* the upstream{}'s loc_conf */ + + ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); + if (ctx->loc_conf == NULL) { + return NGX_CONF_ERROR; + } + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_HTTP_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->create_srv_conf) { + mconf = module->create_srv_conf(cf); + if (mconf == NULL) { + return NGX_CONF_ERROR; + } + + ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; + } + + if (module->create_loc_conf) { + mconf = module->create_loc_conf(cf); + if (mconf == NULL) { + return NGX_CONF_ERROR; + } + + ctx->loc_conf[ngx_modules[m]->ctx_index] = mconf; + } + } + + uscf->servers = ngx_array_create(cf->pool, 4, + sizeof(ngx_http_upstream_server_t)); + if (uscf->servers == NULL) { + return NGX_CONF_ERROR; + } + + + /* parse inside upstream{} */ + + pcf = *cf; + cf->ctx = ctx; + cf->cmd_type = NGX_HTTP_UPS_CONF; + + rv = ngx_conf_parse(cf, NULL); + + *cf = pcf; + + if (rv != NGX_CONF_OK) { + return rv; + } + + if (uscf->servers->nelts == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "no servers are inside upstream"); + return NGX_CONF_ERROR; + } + + return rv; +} + + +static char * +ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_upstream_srv_conf_t *uscf = conf; + + time_t fail_timeout; + ngx_str_t *value, s; + ngx_url_t u; + ngx_int_t weight, max_fails; + ngx_uint_t i; + ngx_http_upstream_server_t *us; + + us = ngx_array_push(uscf->servers); + if (us == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); + + value = cf->args->elts; + + weight = 1; + max_fails = 1; + fail_timeout = 10; + + for (i = 2; i < cf->args->nelts; i++) { + + if (ngx_strncmp(value[i].data, "weight=", 7) == 0) { + + if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) { + goto not_supported; + } + + weight = ngx_atoi(&value[i].data[7], value[i].len - 7); + + if (weight == NGX_ERROR || weight == 0) { + goto invalid; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) { + + if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) { + goto not_supported; + } + + max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10); + + if (max_fails == NGX_ERROR) { + goto invalid; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) { + + if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) { + goto not_supported; + } + + s.len = value[i].len - 13; + s.data = &value[i].data[13]; + + fail_timeout = ngx_parse_time(&s, 1); + + if (fail_timeout == (time_t) NGX_ERROR) { + goto invalid; + } + + continue; + } + + if (ngx_strcmp(value[i].data, "backup") == 0) { + + if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) { + goto not_supported; + } + + us->backup = 1; + + continue; + } + + if (ngx_strcmp(value[i].data, "down") == 0) { + + if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) { + goto not_supported; + } + + us->down = 1; + + continue; + } + + goto invalid; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + + u.url = value[1]; + u.default_port = 80; + + if (ngx_parse_url(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in upstream \"%V\"", u.err, &u.url); + } + + return NGX_CONF_ERROR; + } + + us->name = u.url; + us->addrs = u.addrs; + us->naddrs = u.naddrs; + us->weight = weight; + us->max_fails = max_fails; + us->fail_timeout = fail_timeout; + + return NGX_CONF_OK; + +invalid: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[i]); + + return NGX_CONF_ERROR; + +not_supported: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "balancing method does not support parameter \"%V\"", + &value[i]); + + return NGX_CONF_ERROR; +} + + +ngx_http_upstream_srv_conf_t * +ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) +{ + ngx_uint_t i; + ngx_http_upstream_server_t *us; + ngx_http_upstream_srv_conf_t *uscf, **uscfp; + ngx_http_upstream_main_conf_t *umcf; + + if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) { + + if (ngx_parse_url(cf->pool, u) != NGX_OK) { + if (u->err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in upstream \"%V\"", u->err, &u->url); + } + + return NULL; + } + } + + umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module); + + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + + if (uscfp[i]->host.len != u->host.len + || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) + != 0) + { + continue; + } + + if ((flags & NGX_HTTP_UPSTREAM_CREATE) + && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE)) + { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate upstream \"%V\"", &u->host); + return NULL; + } + + if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "upstream \"%V\" may not have port %d", + &u->host, u->port); + return NULL; + } + + if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port) { + ngx_log_error(NGX_LOG_WARN, cf->log, 0, + "upstream \"%V\" may not have port %d in %s:%ui", + &u->host, uscfp[i]->port, + uscfp[i]->file_name, uscfp[i]->line); + return NULL; + } + + if (uscfp[i]->port && u->port + && uscfp[i]->port != u->port) + { + continue; + } + + if (uscfp[i]->default_port && u->default_port + && uscfp[i]->default_port != u->default_port) + { + continue; + } + + if (flags & NGX_HTTP_UPSTREAM_CREATE) { + uscfp[i]->flags = flags; + } + + return uscfp[i]; + } + + uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t)); + if (uscf == NULL) { + return NULL; + } + + uscf->flags = flags; + uscf->host = u->host; + uscf->file_name = cf->conf_file->file.name.data; + uscf->line = cf->conf_file->line; + uscf->port = u->port; + uscf->default_port = u->default_port; + uscf->no_port = u->no_port; + + if (u->naddrs == 1 && (u->port || u->family == AF_UNIX)) { + uscf->servers = ngx_array_create(cf->pool, 1, + sizeof(ngx_http_upstream_server_t)); + if (uscf->servers == NULL) { + return NULL; + } + + us = ngx_array_push(uscf->servers); + if (us == NULL) { + return NULL; + } + + ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); + + us->addrs = u->addrs; + us->naddrs = 1; + } + + uscfp = ngx_array_push(&umcf->upstreams); + if (uscfp == NULL) { + return NULL; + } + + *uscfp = uscf; + + return uscf; +} + + +char * +ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_int_t rc; + ngx_str_t *value; + ngx_http_complex_value_t cv; + ngx_http_upstream_local_t **plocal, *local; + ngx_http_compile_complex_value_t ccv; + + plocal = (ngx_http_upstream_local_t **) (p + cmd->offset); + + if (*plocal != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + *plocal = NULL; + return NGX_CONF_OK; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t)); + if (local == NULL) { + return NGX_CONF_ERROR; + } + + *plocal = local; + + if (cv.lengths) { + local->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (local->value == NULL) { + return NGX_CONF_ERROR; + } + + *local->value = cv; + + return NGX_CONF_OK; + } + + local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); + if (local->addr == NULL) { + return NGX_CONF_ERROR; + } + + rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len); + + switch (rc) { + case NGX_OK: + local->addr->name = value[1]; + return NGX_CONF_OK; + + case NGX_DECLINED: + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid address \"%V\"", &value[1]); + /* fall through */ + + default: + return NGX_CONF_ERROR; + } +} + + +static ngx_addr_t * +ngx_http_upstream_get_local(ngx_http_request_t *r, + ngx_http_upstream_local_t *local) +{ + ngx_int_t rc; + ngx_str_t val; + ngx_addr_t *addr; + + if (local == NULL) { + return NULL; + } + + if (local->value == NULL) { + return local->addr; + } + + if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) { + return NULL; + } + + if (val.len == 0) { + return NULL; + } + + addr = ngx_palloc(r->pool, sizeof(ngx_addr_t)); + if (addr == NULL) { + return NULL; + } + + rc = ngx_parse_addr(r->pool, addr, val.data, val.len); + + switch (rc) { + case NGX_OK: + addr->name = val; + return addr; + + case NGX_DECLINED: + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "invalid local address \"%V\"", &val); + /* fall through */ + + default: + return NULL; + } +} + + +char * +ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_array_t **a; + ngx_http_upstream_param_t *param; + + a = (ngx_array_t **) (p + cmd->offset); + + if (*a == NULL) { + *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t)); + if (*a == NULL) { + return NGX_CONF_ERROR; + } + } + + param = ngx_array_push(*a); + if (param == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + param->key = value[1]; + param->value = value[2]; + param->skip_empty = 0; + + if (cf->args->nelts == 4) { + if (ngx_strcmp(value[3].data, "if_not_empty") != 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[3]); + return NGX_CONF_ERROR; + } + + param->skip_empty = 1; + } + + return NGX_CONF_OK; +} + + +ngx_int_t +ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev, + ngx_str_t *default_hide_headers, ngx_hash_init_t *hash) +{ + ngx_str_t *h; + ngx_uint_t i, j; + ngx_array_t hide_headers; + ngx_hash_key_t *hk; + + if (conf->hide_headers == NGX_CONF_UNSET_PTR + && conf->pass_headers == NGX_CONF_UNSET_PTR) + { + conf->hide_headers = prev->hide_headers; + conf->pass_headers = prev->pass_headers; + + conf->hide_headers_hash = prev->hide_headers_hash; + + if (conf->hide_headers_hash.buckets +#if (NGX_HTTP_CACHE) + && ((conf->cache == 0) == (prev->cache == 0)) +#endif + ) + { + return NGX_OK; + } + + } else { + if (conf->hide_headers == NGX_CONF_UNSET_PTR) { + conf->hide_headers = prev->hide_headers; + } + + if (conf->pass_headers == NGX_CONF_UNSET_PTR) { + conf->pass_headers = prev->pass_headers; + } + } + + if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + for (h = default_hide_headers; h->len; h++) { + hk = ngx_array_push(&hide_headers); + if (hk == NULL) { + return NGX_ERROR; + } + + hk->key = *h; + hk->key_hash = ngx_hash_key_lc(h->data, h->len); + hk->value = (void *) 1; + } + + if (conf->hide_headers != NGX_CONF_UNSET_PTR) { + + h = conf->hide_headers->elts; + + for (i = 0; i < conf->hide_headers->nelts; i++) { + + hk = hide_headers.elts; + + for (j = 0; j < hide_headers.nelts; j++) { + if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) { + goto exist; + } + } + + hk = ngx_array_push(&hide_headers); + if (hk == NULL) { + return NGX_ERROR; + } + + hk->key = h[i]; + hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len); + hk->value = (void *) 1; + + exist: + + continue; + } + } + + if (conf->pass_headers != NGX_CONF_UNSET_PTR) { + + h = conf->pass_headers->elts; + hk = hide_headers.elts; + + for (i = 0; i < conf->pass_headers->nelts; i++) { + for (j = 0; j < hide_headers.nelts; j++) { + + if (hk[j].key.data == NULL) { + continue; + } + + if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) { + hk[j].key.data = NULL; + break; + } + } + } + } + + hash->hash = &conf->hide_headers_hash; + hash->key = ngx_hash_key_lc; + hash->pool = cf->pool; + hash->temp_pool = NULL; + + return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts); +} + + +static void * +ngx_http_upstream_create_main_conf(ngx_conf_t *cf) +{ + ngx_http_upstream_main_conf_t *umcf; + + umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t)); + if (umcf == NULL) { + return NULL; + } + + if (ngx_array_init(&umcf->upstreams, cf->pool, 4, + sizeof(ngx_http_upstream_srv_conf_t *)) + != NGX_OK) + { + return NULL; + } + + return umcf; +} + + +static char * +ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf) +{ + ngx_http_upstream_main_conf_t *umcf = conf; + + ngx_uint_t i; + ngx_array_t headers_in; + ngx_hash_key_t *hk; + ngx_hash_init_t hash; + ngx_http_upstream_init_pt init; + ngx_http_upstream_header_t *header; + ngx_http_upstream_srv_conf_t **uscfp; + + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + + init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream: + ngx_http_upstream_init_round_robin; + + if (init(cf, uscfp[i]) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + + /* upstream_headers_in_hash */ + + if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + for (header = ngx_http_upstream_headers_in; header->name.len; header++) { + hk = ngx_array_push(&headers_in); + if (hk == NULL) { + return NGX_CONF_ERROR; + } + + hk->key = header->name; + hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); + hk->value = header; + } + + hash.hash = &umcf->headers_in_hash; + hash.key = ngx_hash_key_lc; + hash.max_size = 512; + hash.bucket_size = ngx_align(64, ngx_cacheline_size); + hash.name = "upstream_headers_in_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/http/ngx_http_upstream.h b/hm_nginx/src/http/ngx_http_upstream.h new file mode 100644 index 0000000..895a559 --- /dev/null +++ b/hm_nginx/src/http/ngx_http_upstream.h @@ -0,0 +1,413 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_HTTP_UPSTREAM_H_INCLUDED_ +#define _NGX_HTTP_UPSTREAM_H_INCLUDED_ + + +#include +#include +#include +#include +#include +#include + + +#define NGX_HTTP_UPSTREAM_FT_ERROR 0x00000002 +#define NGX_HTTP_UPSTREAM_FT_TIMEOUT 0x00000004 +#define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER 0x00000008 +#define NGX_HTTP_UPSTREAM_FT_HTTP_500 0x00000010 +#define NGX_HTTP_UPSTREAM_FT_HTTP_502 0x00000020 +#define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000040 +#define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080 +#define NGX_HTTP_UPSTREAM_FT_HTTP_403 0x00000100 +#define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000200 +#define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000400 +#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000800 +#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00001000 +#define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 +#define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000 + +#define NGX_HTTP_UPSTREAM_FT_STATUS (NGX_HTTP_UPSTREAM_FT_HTTP_500 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_502 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_503 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_504 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_403 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_404) + +#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40 + + +#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002 +#define NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES 0x00000004 +#define NGX_HTTP_UPSTREAM_IGN_EXPIRES 0x00000008 +#define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL 0x00000010 +#define NGX_HTTP_UPSTREAM_IGN_SET_COOKIE 0x00000020 +#define NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE 0x00000040 +#define NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING 0x00000080 +#define NGX_HTTP_UPSTREAM_IGN_XA_CHARSET 0x00000100 +#define NGX_HTTP_UPSTREAM_IGN_VARY 0x00000200 + + +typedef struct { + ngx_msec_t bl_time; + ngx_uint_t bl_state; + + ngx_uint_t status; + time_t response_sec; + ngx_uint_t response_msec; + time_t header_sec; + ngx_uint_t header_msec; + off_t response_length; + + ngx_str_t *peer; +} ngx_http_upstream_state_t; + + +typedef struct { + ngx_hash_t headers_in_hash; + ngx_array_t upstreams; + /* ngx_http_upstream_srv_conf_t */ +} ngx_http_upstream_main_conf_t; + +typedef struct ngx_http_upstream_srv_conf_s ngx_http_upstream_srv_conf_t; + +typedef ngx_int_t (*ngx_http_upstream_init_pt)(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us); +typedef ngx_int_t (*ngx_http_upstream_init_peer_pt)(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us); + + +typedef struct { + ngx_http_upstream_init_pt init_upstream; + ngx_http_upstream_init_peer_pt init; + void *data; +} ngx_http_upstream_peer_t; + + +typedef struct { + ngx_str_t name; + ngx_addr_t *addrs; + ngx_uint_t naddrs; + ngx_uint_t weight; + ngx_uint_t max_fails; + time_t fail_timeout; + + unsigned down:1; + unsigned backup:1; +} ngx_http_upstream_server_t; + + +#define NGX_HTTP_UPSTREAM_CREATE 0x0001 +#define NGX_HTTP_UPSTREAM_WEIGHT 0x0002 +#define NGX_HTTP_UPSTREAM_MAX_FAILS 0x0004 +#define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT 0x0008 +#define NGX_HTTP_UPSTREAM_DOWN 0x0010 +#define NGX_HTTP_UPSTREAM_BACKUP 0x0020 + + +struct ngx_http_upstream_srv_conf_s { + ngx_http_upstream_peer_t peer; + void **srv_conf; + + ngx_array_t *servers; /* ngx_http_upstream_server_t */ + + ngx_uint_t flags; + ngx_str_t host; + u_char *file_name; + ngx_uint_t line; + in_port_t port; + in_port_t default_port; + ngx_uint_t no_port; /* unsigned no_port:1 */ +}; + + +typedef struct { + ngx_addr_t *addr; + ngx_http_complex_value_t *value; +} ngx_http_upstream_local_t; + + +typedef struct { + ngx_http_upstream_srv_conf_t *upstream; + + ngx_msec_t connect_timeout; + ngx_msec_t send_timeout; + ngx_msec_t read_timeout; + ngx_msec_t timeout; + ngx_msec_t next_upstream_timeout; + + size_t send_lowat; + size_t buffer_size; + size_t limit_rate; + + size_t busy_buffers_size; + size_t max_temp_file_size; + size_t temp_file_write_size; + + size_t busy_buffers_size_conf; + size_t max_temp_file_size_conf; + size_t temp_file_write_size_conf; + + ngx_bufs_t bufs; + + ngx_uint_t ignore_headers; + ngx_uint_t next_upstream; + ngx_uint_t store_access; + ngx_uint_t next_upstream_tries; + ngx_flag_t buffering; + ngx_flag_t request_buffering; + ngx_flag_t pass_request_headers; + ngx_flag_t pass_request_body; + + ngx_flag_t ignore_client_abort; + ngx_flag_t intercept_errors; + ngx_flag_t cyclic_temp_file; + ngx_flag_t force_ranges; + + ngx_path_t *temp_path; + + ngx_hash_t hide_headers_hash; + ngx_array_t *hide_headers; + ngx_array_t *pass_headers; + + ngx_http_upstream_local_t *local; + +#if (NGX_HTTP_CACHE) + ngx_shm_zone_t *cache_zone; + ngx_http_complex_value_t *cache_value; + + ngx_uint_t cache_min_uses; + ngx_uint_t cache_use_stale; + ngx_uint_t cache_methods; + + ngx_flag_t cache_lock; + ngx_msec_t cache_lock_timeout; + ngx_msec_t cache_lock_age; + + ngx_flag_t cache_revalidate; + + ngx_array_t *cache_valid; + ngx_array_t *cache_bypass; + ngx_array_t *no_cache; +#endif + + ngx_array_t *store_lengths; + ngx_array_t *store_values; + +#if (NGX_HTTP_CACHE) + signed cache:2; +#endif + signed store:2; + unsigned intercept_404:1; + unsigned change_buffering:1; + +#if (NGX_HTTP_SSL) + ngx_ssl_t *ssl; + ngx_flag_t ssl_session_reuse; + + ngx_http_complex_value_t *ssl_name; + ngx_flag_t ssl_server_name; + ngx_flag_t ssl_verify; +#endif + + ngx_str_t module; +} ngx_http_upstream_conf_t; + + +typedef struct { + ngx_str_t name; + ngx_http_header_handler_pt handler; + ngx_uint_t offset; + ngx_http_header_handler_pt copy_handler; + ngx_uint_t conf; + ngx_uint_t redirect; /* unsigned redirect:1; */ +} ngx_http_upstream_header_t; + + +typedef struct { + ngx_list_t headers; + + ngx_uint_t status_n; + ngx_str_t status_line; + + ngx_table_elt_t *status; + ngx_table_elt_t *date; + ngx_table_elt_t *server; + ngx_table_elt_t *connection; + + ngx_table_elt_t *expires; + ngx_table_elt_t *etag; + ngx_table_elt_t *x_accel_expires; + ngx_table_elt_t *x_accel_redirect; + ngx_table_elt_t *x_accel_limit_rate; + + ngx_table_elt_t *content_type; + ngx_table_elt_t *content_length; + + ngx_table_elt_t *last_modified; + ngx_table_elt_t *location; + ngx_table_elt_t *accept_ranges; + ngx_table_elt_t *www_authenticate; + ngx_table_elt_t *transfer_encoding; + ngx_table_elt_t *vary; + +#if (NGX_HTTP_GZIP) + ngx_table_elt_t *content_encoding; +#endif + + ngx_array_t cache_control; + ngx_array_t cookies; + + off_t content_length_n; + time_t last_modified_time; + + unsigned connection_close:1; + unsigned chunked:1; +} ngx_http_upstream_headers_in_t; + + +typedef struct { + ngx_str_t host; + in_port_t port; + ngx_uint_t no_port; /* unsigned no_port:1 */ + + ngx_uint_t naddrs; + ngx_addr_t *addrs; + + struct sockaddr *sockaddr; + socklen_t socklen; + + ngx_resolver_ctx_t *ctx; +} ngx_http_upstream_resolved_t; + + +typedef void (*ngx_http_upstream_handler_pt)(ngx_http_request_t *r, + ngx_http_upstream_t *u); + + +struct ngx_http_upstream_s { + ngx_http_upstream_handler_pt read_event_handler; + ngx_http_upstream_handler_pt write_event_handler; + + ngx_peer_connection_t peer; + + ngx_event_pipe_t *pipe; + + ngx_chain_t *request_bufs; + + ngx_output_chain_ctx_t output; + ngx_chain_writer_ctx_t writer; + + ngx_http_upstream_conf_t *conf; +#if (NGX_HTTP_CACHE) + ngx_array_t *caches; +#endif + + ngx_http_upstream_headers_in_t headers_in; + + ngx_http_upstream_resolved_t *resolved; + + ngx_buf_t from_client; + + ngx_buf_t buffer; + off_t length; + + ngx_chain_t *out_bufs; + ngx_chain_t *busy_bufs; + ngx_chain_t *free_bufs; + + ngx_int_t (*input_filter_init)(void *data); + ngx_int_t (*input_filter)(void *data, ssize_t bytes); + void *input_filter_ctx; + +#if (NGX_HTTP_CACHE) + ngx_int_t (*create_key)(ngx_http_request_t *r); +#endif + ngx_int_t (*create_request)(ngx_http_request_t *r); + ngx_int_t (*reinit_request)(ngx_http_request_t *r); + ngx_int_t (*process_header)(ngx_http_request_t *r); + void (*abort_request)(ngx_http_request_t *r); + void (*finalize_request)(ngx_http_request_t *r, + ngx_int_t rc); + ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r, + ngx_table_elt_t *h, size_t prefix); + ngx_int_t (*rewrite_cookie)(ngx_http_request_t *r, + ngx_table_elt_t *h); + + ngx_msec_t timeout; + + ngx_http_upstream_state_t *state; + + ngx_str_t method; + ngx_str_t schema; + ngx_str_t uri; + +#if (NGX_HTTP_SSL) + ngx_str_t ssl_name; +#endif + + ngx_http_cleanup_pt *cleanup; + + unsigned store:1; + unsigned cacheable:1; + unsigned accel:1; + unsigned ssl:1; +#if (NGX_HTTP_CACHE) + unsigned cache_status:3; +#endif + + unsigned buffering:1; + unsigned keepalive:1; + unsigned upgrade:1; + + unsigned request_sent:1; + unsigned header_sent:1; +}; + + +typedef struct { + ngx_uint_t status; + ngx_uint_t mask; +} ngx_http_upstream_next_t; + + +typedef struct { + ngx_str_t key; + ngx_str_t value; + ngx_uint_t skip_empty; +} ngx_http_upstream_param_t; + + +ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r); +void ngx_http_upstream_init(ngx_http_request_t *r); +ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf, + ngx_url_t *u, ngx_uint_t flags); +char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +char *ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev, + ngx_str_t *default_hide_headers, ngx_hash_init_t *hash); + + +#define ngx_http_conf_upstream_srv_conf(uscf, module) \ + uscf->srv_conf[module.ctx_index] + + +extern ngx_module_t ngx_http_upstream_module; +extern ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask[]; +extern ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[]; + + +#endif /* _NGX_HTTP_UPSTREAM_H_INCLUDED_ */ diff --git a/hm_nginx/src/http/ngx_http_upstream_round_robin.c b/hm_nginx/src/http/ngx_http_upstream_round_robin.c new file mode 100644 index 0000000..2d0649b --- /dev/null +++ b/hm_nginx/src/http/ngx_http_upstream_round_robin.c @@ -0,0 +1,696 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#define ngx_http_upstream_tries(p) ((p)->number \ + + ((p)->next ? (p)->next->number : 0)) + + +static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer( + ngx_http_upstream_rr_peer_data_t *rrp); + +#if (NGX_HTTP_SSL) + +static ngx_int_t ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc, + void *data); +static void ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc, + void *data); + +#endif + + +ngx_int_t +ngx_http_upstream_init_round_robin(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us) +{ + ngx_url_t u; + ngx_uint_t i, j, n, w; + ngx_http_upstream_server_t *server; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_rr_peers_t *peers, *backup; + + us->peer.init = ngx_http_upstream_init_round_robin_peer; + + if (us->servers) { + server = us->servers->elts; + + n = 0; + w = 0; + + for (i = 0; i < us->servers->nelts; i++) { + if (server[i].backup) { + continue; + } + + n += server[i].naddrs; + w += server[i].naddrs * server[i].weight; + } + + if (n == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no servers in upstream \"%V\" in %s:%ui", + &us->host, us->file_name, us->line); + return NGX_ERROR; + } + + peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); + if (peers == NULL) { + return NGX_ERROR; + } + + peers->single = (n == 1); + peers->number = n; + peers->weighted = (w != n); + peers->total_weight = w; + peers->name = &us->host; + + n = 0; + peer = peers->peer; + + for (i = 0; i < us->servers->nelts; i++) { + if (server[i].backup) { + continue; + } + + for (j = 0; j < server[i].naddrs; j++) { + peer[n].sockaddr = server[i].addrs[j].sockaddr; + peer[n].socklen = server[i].addrs[j].socklen; + peer[n].name = server[i].addrs[j].name; + peer[n].weight = server[i].weight; + peer[n].effective_weight = server[i].weight; + peer[n].current_weight = 0; + peer[n].max_fails = server[i].max_fails; + peer[n].fail_timeout = server[i].fail_timeout; + peer[n].down = server[i].down; + peer[n].server = server[i].name; + n++; + } + } + + us->peer.data = peers; + + /* backup servers */ + + n = 0; + w = 0; + + for (i = 0; i < us->servers->nelts; i++) { + if (!server[i].backup) { + continue; + } + + n += server[i].naddrs; + w += server[i].naddrs * server[i].weight; + } + + if (n == 0) { + return NGX_OK; + } + + backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); + if (backup == NULL) { + return NGX_ERROR; + } + + peers->single = 0; + backup->single = 0; + backup->number = n; + backup->weighted = (w != n); + backup->total_weight = w; + backup->name = &us->host; + + n = 0; + peer = backup->peer; + + for (i = 0; i < us->servers->nelts; i++) { + if (!server[i].backup) { + continue; + } + + for (j = 0; j < server[i].naddrs; j++) { + peer[n].sockaddr = server[i].addrs[j].sockaddr; + peer[n].socklen = server[i].addrs[j].socklen; + peer[n].name = server[i].addrs[j].name; + peer[n].weight = server[i].weight; + peer[n].effective_weight = server[i].weight; + peer[n].current_weight = 0; + peer[n].max_fails = server[i].max_fails; + peer[n].fail_timeout = server[i].fail_timeout; + peer[n].down = server[i].down; + peer[n].server = server[i].name; + n++; + } + } + + peers->next = backup; + + return NGX_OK; + } + + + /* an upstream implicitly defined by proxy_pass, etc. */ + + if (us->port == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no port in upstream \"%V\" in %s:%ui", + &us->host, us->file_name, us->line); + return NGX_ERROR; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + + u.host = us->host; + u.port = us->port; + + if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "%s in upstream \"%V\" in %s:%ui", + u.err, &us->host, us->file_name, us->line); + } + + return NGX_ERROR; + } + + n = u.naddrs; + + peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); + if (peers == NULL) { + return NGX_ERROR; + } + + peers->single = (n == 1); + peers->number = n; + peers->weighted = 0; + peers->total_weight = n; + peers->name = &us->host; + + peer = peers->peer; + + for (i = 0; i < u.naddrs; i++) { + peer[i].sockaddr = u.addrs[i].sockaddr; + peer[i].socklen = u.addrs[i].socklen; + peer[i].name = u.addrs[i].name; + peer[i].weight = 1; + peer[i].effective_weight = 1; + peer[i].current_weight = 0; + peer[i].max_fails = 1; + peer[i].fail_timeout = 10; + } + + us->peer.data = peers; + + /* implicitly defined upstream has no backup servers */ + + return NGX_OK; +} + + +ngx_int_t +ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us) +{ + ngx_uint_t n; + ngx_http_upstream_rr_peer_data_t *rrp; + + rrp = r->upstream->peer.data; + + if (rrp == NULL) { + rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t)); + if (rrp == NULL) { + return NGX_ERROR; + } + + r->upstream->peer.data = rrp; + } + + rrp->peers = us->peer.data; + rrp->current = 0; + + n = rrp->peers->number; + + if (rrp->peers->next && rrp->peers->next->number > n) { + n = rrp->peers->next->number; + } + + if (n <= 8 * sizeof(uintptr_t)) { + rrp->tried = &rrp->data; + rrp->data = 0; + + } else { + n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); + + rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t)); + if (rrp->tried == NULL) { + return NGX_ERROR; + } + } + + r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; + r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; + r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers); +#if (NGX_HTTP_SSL) + r->upstream->peer.set_session = + ngx_http_upstream_set_round_robin_peer_session; + r->upstream->peer.save_session = + ngx_http_upstream_save_round_robin_peer_session; +#endif + + return NGX_OK; +} + + +ngx_int_t +ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, + ngx_http_upstream_resolved_t *ur) +{ + u_char *p; + size_t len; + socklen_t socklen; + ngx_uint_t i, n; + struct sockaddr *sockaddr; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_rr_peers_t *peers; + ngx_http_upstream_rr_peer_data_t *rrp; + + rrp = r->upstream->peer.data; + + if (rrp == NULL) { + rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t)); + if (rrp == NULL) { + return NGX_ERROR; + } + + r->upstream->peer.data = rrp; + } + + peers = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peers_t) + + sizeof(ngx_http_upstream_rr_peer_t) * (ur->naddrs - 1)); + if (peers == NULL) { + return NGX_ERROR; + } + + peers->single = (ur->naddrs == 1); + peers->number = ur->naddrs; + peers->name = &ur->host; + + peer = peers->peer; + + if (ur->sockaddr) { + peer[0].sockaddr = ur->sockaddr; + peer[0].socklen = ur->socklen; + peer[0].name = ur->host; + peer[0].weight = 1; + peer[0].effective_weight = 1; + peer[0].current_weight = 0; + peer[0].max_fails = 1; + peer[0].fail_timeout = 10; + + } else { + + for (i = 0; i < ur->naddrs; i++) { + + socklen = ur->addrs[i].socklen; + + sockaddr = ngx_palloc(r->pool, socklen); + if (sockaddr == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen); + + switch (sockaddr->sa_family) { +#if (NGX_HAVE_INET6) + case AF_INET6: + ((struct sockaddr_in6 *) sockaddr)->sin6_port = htons(ur->port); + break; +#endif + default: /* AF_INET */ + ((struct sockaddr_in *) sockaddr)->sin_port = htons(ur->port); + } + + p = ngx_pnalloc(r->pool, NGX_SOCKADDR_STRLEN); + if (p == NULL) { + return NGX_ERROR; + } + + len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1); + + peer[i].sockaddr = sockaddr; + peer[i].socklen = socklen; + peer[i].name.len = len; + peer[i].name.data = p; + peer[i].weight = 1; + peer[i].effective_weight = 1; + peer[i].current_weight = 0; + peer[i].max_fails = 1; + peer[i].fail_timeout = 10; + } + } + + rrp->peers = peers; + rrp->current = 0; + + if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { + rrp->tried = &rrp->data; + rrp->data = 0; + + } else { + n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) + / (8 * sizeof(uintptr_t)); + + rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t)); + if (rrp->tried == NULL) { + return NGX_ERROR; + } + } + + r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; + r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; + r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers); +#if (NGX_HTTP_SSL) + r->upstream->peer.set_session = ngx_http_upstream_empty_set_session; + r->upstream->peer.save_session = ngx_http_upstream_empty_save_session; +#endif + + return NGX_OK; +} + + +ngx_int_t +ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) +{ + ngx_http_upstream_rr_peer_data_t *rrp = data; + + ngx_int_t rc; + ngx_uint_t i, n; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_rr_peers_t *peers; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "get rr peer, try: %ui", pc->tries); + + pc->cached = 0; + pc->connection = NULL; + + peers = rrp->peers; + + /* ngx_lock_mutex(peers->mutex); */ + + if (peers->single) { + peer = &peers->peer[0]; + + if (peer->down) { + goto failed; + } + + } else { + + /* there are several peers */ + + peer = ngx_http_upstream_get_peer(rrp); + + if (peer == NULL) { + goto failed; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "get rr peer, current: %ui %i", + rrp->current, peer->current_weight); + } + + pc->sockaddr = peer->sockaddr; + pc->socklen = peer->socklen; + pc->name = &peer->name; + + /* ngx_unlock_mutex(peers->mutex); */ + + return NGX_OK; + +failed: + + if (peers->next) { + + /* ngx_unlock_mutex(peers->mutex); */ + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); + + rrp->peers = peers->next; + + n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) + / (8 * sizeof(uintptr_t)); + + for (i = 0; i < n; i++) { + rrp->tried[i] = 0; + } + + rc = ngx_http_upstream_get_round_robin_peer(pc, rrp); + + if (rc != NGX_BUSY) { + return rc; + } + + /* ngx_lock_mutex(peers->mutex); */ + } + + /* all peers failed, mark them as live for quick recovery */ + + for (i = 0; i < peers->number; i++) { + peers->peer[i].fails = 0; + } + + /* ngx_unlock_mutex(peers->mutex); */ + + pc->name = peers->name; + + return NGX_BUSY; +} + + +static ngx_http_upstream_rr_peer_t * +ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp) +{ + time_t now; + uintptr_t m; + ngx_int_t total; + ngx_uint_t i, n; + ngx_http_upstream_rr_peer_t *peer, *best; + + now = ngx_time(); + + best = NULL; + total = 0; + + for (i = 0; i < rrp->peers->number; i++) { + + n = i / (8 * sizeof(uintptr_t)); + m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); + + if (rrp->tried[n] & m) { + continue; + } + + peer = &rrp->peers->peer[i]; + + if (peer->down) { + continue; + } + + if (peer->max_fails + && peer->fails >= peer->max_fails + && now - peer->checked <= peer->fail_timeout) + { + continue; + } + + peer->current_weight += peer->effective_weight; + total += peer->effective_weight; + + if (peer->effective_weight < peer->weight) { + peer->effective_weight++; + } + + if (best == NULL || peer->current_weight > best->current_weight) { + best = peer; + } + } + + if (best == NULL) { + return NULL; + } + + i = best - &rrp->peers->peer[0]; + + rrp->current = i; + + n = i / (8 * sizeof(uintptr_t)); + m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); + + rrp->tried[n] |= m; + + best->current_weight -= total; + + if (now - best->checked > best->fail_timeout) { + best->checked = now; + } + + return best; +} + + +void +ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, + ngx_uint_t state) +{ + ngx_http_upstream_rr_peer_data_t *rrp = data; + + time_t now; + ngx_http_upstream_rr_peer_t *peer; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "free rr peer %ui %ui", pc->tries, state); + + /* TODO: NGX_PEER_KEEPALIVE */ + + if (rrp->peers->single) { + pc->tries = 0; + return; + } + + peer = &rrp->peers->peer[rrp->current]; + + if (state & NGX_PEER_FAILED) { + now = ngx_time(); + + /* ngx_lock_mutex(rrp->peers->mutex); */ + + peer->fails++; + peer->accessed = now; + peer->checked = now; + + if (peer->max_fails) { + peer->effective_weight -= peer->weight / peer->max_fails; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "free rr peer failed: %ui %i", + rrp->current, peer->effective_weight); + + if (peer->effective_weight < 0) { + peer->effective_weight = 0; + } + + /* ngx_unlock_mutex(rrp->peers->mutex); */ + + } else { + + /* mark peer live if check passed */ + + if (peer->accessed < peer->checked) { + peer->fails = 0; + } + } + + if (pc->tries) { + pc->tries--; + } + + /* ngx_unlock_mutex(rrp->peers->mutex); */ +} + + +#if (NGX_HTTP_SSL) + +ngx_int_t +ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data) +{ + ngx_http_upstream_rr_peer_data_t *rrp = data; + + ngx_int_t rc; + ngx_ssl_session_t *ssl_session; + ngx_http_upstream_rr_peer_t *peer; + + peer = &rrp->peers->peer[rrp->current]; + + /* TODO: threads only mutex */ + /* ngx_lock_mutex(rrp->peers->mutex); */ + + ssl_session = peer->ssl_session; + + rc = ngx_ssl_set_session(pc->connection, ssl_session); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "set session: %p", ssl_session); + + /* ngx_unlock_mutex(rrp->peers->mutex); */ + + return rc; +} + + +void +ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data) +{ + ngx_http_upstream_rr_peer_data_t *rrp = data; + + ngx_ssl_session_t *old_ssl_session, *ssl_session; + ngx_http_upstream_rr_peer_t *peer; + + ssl_session = ngx_ssl_get_session(pc->connection); + + if (ssl_session == NULL) { + return; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "save session: %p", ssl_session); + + peer = &rrp->peers->peer[rrp->current]; + + /* TODO: threads only mutex */ + /* ngx_lock_mutex(rrp->peers->mutex); */ + + old_ssl_session = peer->ssl_session; + peer->ssl_session = ssl_session; + + /* ngx_unlock_mutex(rrp->peers->mutex); */ + + if (old_ssl_session) { + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "old session: %p", old_ssl_session); + + /* TODO: may block */ + + ngx_ssl_free_session(old_ssl_session); + } +} + + +static ngx_int_t +ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc, void *data) +{ + return NGX_OK; +} + + +static void +ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc, void *data) +{ + return; +} + +#endif diff --git a/hm_nginx/src/http/ngx_http_upstream_round_robin.h b/hm_nginx/src/http/ngx_http_upstream_round_robin.h new file mode 100644 index 0000000..3bbba0b --- /dev/null +++ b/hm_nginx/src/http/ngx_http_upstream_round_robin.h @@ -0,0 +1,88 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_ +#define _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_str_t name; + ngx_str_t server; + + ngx_int_t current_weight; + ngx_int_t effective_weight; + ngx_int_t weight; + + ngx_uint_t fails; + time_t accessed; + time_t checked; + + ngx_uint_t max_fails; + time_t fail_timeout; + + ngx_uint_t down; /* unsigned down:1; */ + +#if (NGX_HTTP_SSL) + ngx_ssl_session_t *ssl_session; /* local to a process */ +#endif +} ngx_http_upstream_rr_peer_t; + + +typedef struct ngx_http_upstream_rr_peers_s ngx_http_upstream_rr_peers_t; + +struct ngx_http_upstream_rr_peers_s { + ngx_uint_t number; + + ngx_uint_t total_weight; + + unsigned single:1; + unsigned weighted:1; + + ngx_str_t *name; + + ngx_http_upstream_rr_peers_t *next; + + ngx_http_upstream_rr_peer_t peer[1]; +}; + + +typedef struct { + ngx_http_upstream_rr_peers_t *peers; + ngx_uint_t current; + uintptr_t *tried; + uintptr_t data; +} ngx_http_upstream_rr_peer_data_t; + + +ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us); +ngx_int_t ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us); +ngx_int_t ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, + ngx_http_upstream_resolved_t *ur); +ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, + void *data); +void ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, + void *data, ngx_uint_t state); + +#if (NGX_HTTP_SSL) +ngx_int_t + ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data); +void ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, + void *data); +#endif + + +#endif /* _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_ */ diff --git a/hm_nginx/src/http/ngx_http_variables.c b/hm_nginx/src/http/ngx_http_variables.c new file mode 100644 index 0000000..c65de35 --- /dev/null +++ b/hm_nginx/src/http/ngx_http_variables.c @@ -0,0 +1,2620 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#if 0 +static void ngx_http_variable_request_set(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#endif +static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static void ngx_http_variable_request_set_size(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_http_variable_cookies(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data, u_char sep); + +static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#if (NGX_HAVE_TCP_INFO) +static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#endif + +static ngx_int_t ngx_http_variable_content_length(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static void ngx_http_variable_set_args(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_bytes_sent(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_pipe(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_msec(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +/* + * TODO: + * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED + * REMOTE_HOST (null), REMOTE_IDENT (null), + * SERVER_SOFTWARE + * + * Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner) + */ + +/* + * the $http_host, $http_user_agent, $http_referer, and $http_via + * variables may be handled by generic + * ngx_http_variable_unknown_header_in(), but for performance reasons + * they are handled using dedicated entries + */ + +static ngx_http_variable_t ngx_http_core_variables[] = { + + { ngx_string("http_host"), NULL, ngx_http_variable_header, + offsetof(ngx_http_request_t, headers_in.host), 0, 0 }, + + { ngx_string("http_user_agent"), NULL, ngx_http_variable_header, + offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 }, + + { ngx_string("http_referer"), NULL, ngx_http_variable_header, + offsetof(ngx_http_request_t, headers_in.referer), 0, 0 }, + +#if (NGX_HTTP_GZIP) + { ngx_string("http_via"), NULL, ngx_http_variable_header, + offsetof(ngx_http_request_t, headers_in.via), 0, 0 }, +#endif + +#if (NGX_HTTP_X_FORWARDED_FOR) + { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers, + offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 }, +#endif + + { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies, + offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 }, + + { ngx_string("content_length"), NULL, ngx_http_variable_content_length, + 0, 0, 0 }, + + { ngx_string("content_type"), NULL, ngx_http_variable_header, + offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 }, + + { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 }, + + { ngx_string("binary_remote_addr"), NULL, + ngx_http_variable_binary_remote_addr, 0, 0, 0 }, + + { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 }, + + { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 }, + + { ngx_string("proxy_protocol_addr"), NULL, + ngx_http_variable_proxy_protocol_addr, 0, 0, 0 }, + + { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, + + { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 }, + + { ngx_string("server_protocol"), NULL, ngx_http_variable_request, + offsetof(ngx_http_request_t, http_protocol), 0, 0 }, + + { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 }, + + { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 }, + + { ngx_string("request_uri"), NULL, ngx_http_variable_request, + offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, + + { ngx_string("uri"), NULL, ngx_http_variable_request, + offsetof(ngx_http_request_t, uri), + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("document_uri"), NULL, ngx_http_variable_request, + offsetof(ngx_http_request_t, uri), + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 }, + + { ngx_string("document_root"), NULL, + ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("realpath_root"), NULL, + ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("query_string"), NULL, ngx_http_variable_request, + offsetof(ngx_http_request_t, args), + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("args"), + ngx_http_variable_set_args, + ngx_http_variable_request, + offsetof(ngx_http_request_t, args), + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("is_args"), NULL, ngx_http_variable_is_args, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("request_filename"), NULL, + ngx_http_variable_request_filename, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 }, + + { ngx_string("request_method"), NULL, + ngx_http_variable_request_method, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 }, + + { ngx_string("bytes_sent"), NULL, ngx_http_variable_bytes_sent, + 0, 0, 0 }, + + { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent, + 0, 0, 0 }, + + { ngx_string("pipe"), NULL, ngx_http_variable_pipe, + 0, 0, 0 }, + + { ngx_string("request_completion"), NULL, + ngx_http_variable_request_completion, + 0, 0, 0 }, + + { ngx_string("request_body"), NULL, + ngx_http_variable_request_body, + 0, 0, 0 }, + + { ngx_string("request_body_file"), NULL, + ngx_http_variable_request_body_file, + 0, 0, 0 }, + + { ngx_string("request_length"), NULL, ngx_http_variable_request_length, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("request_time"), NULL, ngx_http_variable_request_time, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("status"), NULL, + ngx_http_variable_status, 0, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("sent_http_content_type"), NULL, + ngx_http_variable_sent_content_type, 0, 0, 0 }, + + { ngx_string("sent_http_content_length"), NULL, + ngx_http_variable_sent_content_length, 0, 0, 0 }, + + { ngx_string("sent_http_location"), NULL, + ngx_http_variable_sent_location, 0, 0, 0 }, + + { ngx_string("sent_http_last_modified"), NULL, + ngx_http_variable_sent_last_modified, 0, 0, 0 }, + + { ngx_string("sent_http_connection"), NULL, + ngx_http_variable_sent_connection, 0, 0, 0 }, + + { ngx_string("sent_http_keep_alive"), NULL, + ngx_http_variable_sent_keep_alive, 0, 0, 0 }, + + { ngx_string("sent_http_transfer_encoding"), NULL, + ngx_http_variable_sent_transfer_encoding, 0, 0, 0 }, + + { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers, + offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 }, + + { ngx_string("limit_rate"), ngx_http_variable_request_set_size, + ngx_http_variable_request_get_size, + offsetof(ngx_http_request_t, limit_rate), + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("connection"), NULL, + ngx_http_variable_connection, 0, 0, 0 }, + + { ngx_string("connection_requests"), NULL, + ngx_http_variable_connection_requests, 0, 0, 0 }, + + { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, + 0, 0, 0 }, + + { ngx_string("hostname"), NULL, ngx_http_variable_hostname, + 0, 0, 0 }, + + { ngx_string("pid"), NULL, ngx_http_variable_pid, + 0, 0, 0 }, + + { ngx_string("msec"), NULL, ngx_http_variable_msec, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("time_local"), NULL, ngx_http_variable_time_local, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + +#if (NGX_HAVE_TCP_INFO) + { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo, + 1, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo, + 2, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo, + 3, NGX_HTTP_VAR_NOCACHEABLE, 0 }, +#endif + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +ngx_http_variable_value_t ngx_http_variable_null_value = + ngx_http_variable(""); +ngx_http_variable_value_t ngx_http_variable_true_value = + ngx_http_variable("1"); + + +ngx_http_variable_t * +ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) +{ + ngx_int_t rc; + ngx_uint_t i; + ngx_hash_key_t *key; + ngx_http_variable_t *v; + ngx_http_core_main_conf_t *cmcf; + + if (name->len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid variable name \"$\""); + return NULL; + } + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + key = cmcf->variables_keys->keys.elts; + for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { + if (name->len != key[i].key.len + || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) + { + continue; + } + + v = key[i].value; + + if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the duplicate \"%V\" variable", name); + return NULL; + } + + return v; + } + + v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t)); + if (v == NULL) { + return NULL; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NULL; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = flags; + v->index = 0; + + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); + + if (rc == NGX_ERROR) { + return NULL; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", name); + return NULL; + } + + return v; +} + + +ngx_int_t +ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) +{ + ngx_uint_t i; + ngx_http_variable_t *v; + ngx_http_core_main_conf_t *cmcf; + + if (name->len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid variable name \"$\""); + return NGX_ERROR; + } + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + v = cmcf->variables.elts; + + if (v == NULL) { + if (ngx_array_init(&cmcf->variables, cf->pool, 4, + sizeof(ngx_http_variable_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + } else { + for (i = 0; i < cmcf->variables.nelts; i++) { + if (name->len != v[i].name.len + || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + { + continue; + } + + return i; + } + } + + v = ngx_array_push(&cmcf->variables); + if (v == NULL) { + return NGX_ERROR; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NGX_ERROR; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = 0; + v->index = cmcf->variables.nelts - 1; + + return v->index; +} + + +ngx_http_variable_value_t * +ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) +{ + ngx_http_variable_t *v; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + if (cmcf->variables.nelts <= index) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "unknown variable index: %ui", index); + return NULL; + } + + if (r->variables[index].not_found || r->variables[index].valid) { + return &r->variables[index]; + } + + v = cmcf->variables.elts; + + if (v[index].get_handler(r, &r->variables[index], v[index].data) + == NGX_OK) + { + if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) { + r->variables[index].no_cacheable = 1; + } + + return &r->variables[index]; + } + + r->variables[index].valid = 0; + r->variables[index].not_found = 1; + + return NULL; +} + + +ngx_http_variable_value_t * +ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index) +{ + ngx_http_variable_value_t *v; + + v = &r->variables[index]; + + if (v->valid || v->not_found) { + if (!v->no_cacheable) { + return v; + } + + v->valid = 0; + v->not_found = 0; + } + + return ngx_http_get_indexed_variable(r, index); +} + + +ngx_http_variable_value_t * +ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) +{ + ngx_http_variable_t *v; + ngx_http_variable_value_t *vv; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); + + if (v) { + if (v->flags & NGX_HTTP_VAR_INDEXED) { + return ngx_http_get_flushed_variable(r, v->index); + + } else { + + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); + + if (vv && v->get_handler(r, vv, v->data) == NGX_OK) { + return vv; + } + + return NULL; + } + } + + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); + if (vv == NULL) { + return NULL; + } + + if (ngx_strncmp(name->data, "http_", 5) == 0) { + + if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "sent_http_", 10) == 0) { + + if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) { + + if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "cookie_", 7) == 0) { + + if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) { + + if (ngx_http_upstream_cookie_variable(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "arg_", 4) == 0) { + + if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + + vv->not_found = 1; + + return vv; +} + + +static ngx_int_t +ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *s; + + s = (ngx_str_t *) ((char *) r + data); + + if (s->data) { + v->len = s->len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s->data; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + +#if 0 + +static void +ngx_http_variable_request_set(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *s; + + s = (ngx_str_t *) ((char *) r + data); + + s->len = v->len; + s->data = v->data; +} + +#endif + + +static ngx_int_t +ngx_http_variable_request_get_size(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + size_t *sp; + + sp = (size_t *) ((char *) r + data); + + v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN); + if (v->data == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static void +ngx_http_variable_request_set_size(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ssize_t s, *sp; + ngx_str_t val; + + val.len = v->len; + val.data = v->data; + + s = ngx_parse_size(&val); + + if (s == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "invalid size \"%V\"", &val); + return; + } + + sp = (ssize_t *) ((char *) r + data); + + *sp = s; + + return; +} + + +static ngx_int_t +ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_table_elt_t *h; + + h = *(ngx_table_elt_t **) ((char *) r + data); + + if (h) { + v->len = h->value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = h->value.data; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_cookies(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + return ngx_http_variable_headers_internal(r, v, data, ';'); +} + + +static ngx_int_t +ngx_http_variable_headers(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + return ngx_http_variable_headers_internal(r, v, data, ','); +} + + +static ngx_int_t +ngx_http_variable_headers_internal(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data, u_char sep) +{ + size_t len; + u_char *p, *end; + ngx_uint_t i, n; + ngx_array_t *a; + ngx_table_elt_t **h; + + a = (ngx_array_t *) ((char *) r + data); + + n = a->nelts; + h = a->elts; + + len = 0; + + for (i = 0; i < n; i++) { + + if (h[i]->hash == 0) { + continue; + } + + len += h[i]->value.len + 2; + } + + if (len == 0) { + v->not_found = 1; + return NGX_OK; + } + + len -= 2; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (n == 1) { + v->len = (*h)->value.len; + v->data = (*h)->value.data; + + return NGX_OK; + } + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = len; + v->data = p; + + end = p + len; + + for (i = 0; /* void */ ; i++) { + + if (h[i]->hash == 0) { + continue; + } + + p = ngx_copy(p, h[i]->value.data, h[i]->value.len); + + if (p == end) { + break; + } + + *p++ = sep; *p++ = ' '; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_unknown_header_in(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->headers_in.headers.part, + sizeof("http_") - 1); +} + + +static ngx_int_t +ngx_http_variable_unknown_header_out(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->headers_out.headers.part, + sizeof("sent_http_") - 1); +} + + +ngx_int_t +ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var, + ngx_list_part_t *part, size_t prefix) +{ + u_char ch; + ngx_uint_t i, n; + ngx_table_elt_t *header; + + header = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) { + ch = header[i].key.data[n]; + + if (ch >= 'A' && ch <= 'Z') { + ch |= 0x20; + + } else if (ch == '-') { + ch = '_'; + } + + if (var->data[n + prefix] != ch) { + break; + } + } + + if (n + prefix == var->len && n == header[i].key.len) { + v->len = header[i].value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = header[i].value.data; + + return NGX_OK; + } + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_line(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p, *s; + + s = r->request_line.data; + + if (s == NULL) { + s = r->request_start; + + if (s == NULL) { + v->not_found = 1; + return NGX_OK; + } + + for (p = s; p < r->header_in->last; p++) { + if (*p == CR || *p == LF) { + break; + } + } + + r->request_line.len = p - s; + r->request_line.data = s; + } + + v->len = r->request_line.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_str_t cookie, s; + + s.len = name->len - (sizeof("cookie_") - 1); + s.data = name->data + sizeof("cookie_") - 1; + + if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie) + == NGX_DECLINED) + { + v->not_found = 1; + return NGX_OK; + } + + v->len = cookie.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = cookie.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + u_char *arg; + size_t len; + ngx_str_t value; + + len = name->len - (sizeof("arg_") - 1); + arg = name->data + sizeof("arg_") - 1; + + if (ngx_http_arg(r, arg, len, &value) != NGX_OK) { + v->not_found = 1; + return NGX_OK; + } + + v->data = value.data; + v->len = value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +#if (NGX_HAVE_TCP_INFO) + +static ngx_int_t +ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + struct tcp_info ti; + socklen_t len; + uint32_t value; + + len = sizeof(struct tcp_info); + if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) { + v->not_found = 1; + return NGX_OK; + } + + v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (data) { + case 0: + value = ti.tcpi_rtt; + break; + + case 1: + value = ti.tcpi_rttvar; + break; + + case 2: + value = ti.tcpi_snd_cwnd; + break; + + case 3: + value = ti.tcpi_rcv_space; + break; + + /* suppress warning */ + default: + value = 0; + break; + } + + v->len = ngx_sprintf(v->data, "%uD", value) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + +#endif + + +static ngx_int_t +ngx_http_variable_content_length(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + if (r->headers_in.content_length) { + v->len = r->headers_in.content_length->value.len; + v->data = r->headers_in.content_length->value.data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + } else if (r->reading_body) { + v->not_found = 1; + v->no_cacheable = 1; + + } else if (r->headers_in.content_length_n >= 0) { + p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p; + v->data = p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_http_core_srv_conf_t *cscf; + + if (r->headers_in.server.len) { + v->len = r->headers_in.server.len; + v->data = r->headers_in.server.data; + + } else { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + v->len = cscf->server_name.len; + v->data = cscf->server_name.data; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_binary_remote_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (r->connection->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) r->connection->sockaddr; + + v->len = sizeof(struct in6_addr); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = sin6->sin6_addr.s6_addr; + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) r->connection->sockaddr; + + v->len = sizeof(in_addr_t); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) &sin->sin_addr; + + break; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_remote_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->len = r->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->connection->addr_text.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_remote_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (r->connection->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) r->connection->sockaddr; + port = ntohs(sin6->sin6_port); + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + port = 0; + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) r->connection->sockaddr; + port = ntohs(sin->sin_port); + break; + } + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->len = r->connection->proxy_protocol_addr.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->connection->proxy_protocol_addr.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_server_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t s; + u_char addr[NGX_SOCKADDR_STRLEN]; + + s.len = NGX_SOCKADDR_STRLEN; + s.data = addr; + + if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) { + return NGX_ERROR; + } + + s.data = ngx_pnalloc(r->pool, s.len); + if (s.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s.data, addr, s.len); + + v->len = s.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_server_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) { + return NGX_ERROR; + } + + v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (r->connection->local_sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr; + port = ntohs(sin6->sin6_port); + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + port = 0; + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) r->connection->local_sockaddr; + port = ntohs(sin->sin_port); + break; + } + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_scheme(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ +#if (NGX_HTTP_SSL) + + if (r->connection->ssl) { + v->len = sizeof("https") - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "https"; + + return NGX_OK; + } + +#endif + + v->len = sizeof("http") - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "http"; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_https(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ +#if (NGX_HTTP_SSL) + + if (r->connection->ssl) { + v->len = sizeof("on") - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "on"; + + return NGX_OK; + } + +#endif + + *v = ngx_http_variable_null_value; + + return NGX_OK; +} + + +static void +ngx_http_variable_set_args(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + r->args.len = v->len; + r->args.data = v->data; + r->valid_unparsed_uri = 0; +} + + +static ngx_int_t +ngx_http_variable_is_args(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (r->args.len == 0) { + v->len = 0; + v->data = NULL; + return NGX_OK; + } + + v->len = 1; + v->data = (u_char *) "?"; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_document_root(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t path; + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->root_lengths == NULL) { + v->len = clcf->root.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = clcf->root.data; + + } else { + if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0, + clcf->root_values->elts) + == NULL) + { + return NGX_ERROR; + } + + if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path) + != NGX_OK) + { + return NGX_ERROR; + } + + v->len = path.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = path.data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_realpath_root(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *real; + size_t len; + ngx_str_t path; + ngx_http_core_loc_conf_t *clcf; +#if (NGX_HAVE_MAX_PATH) + u_char buffer[NGX_MAX_PATH]; +#endif + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->root_lengths == NULL) { + path = clcf->root; + + } else { + if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1, + clcf->root_values->elts) + == NULL) + { + return NGX_ERROR; + } + + path.data[path.len - 1] = '\0'; + + if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path) + != NGX_OK) + { + return NGX_ERROR; + } + } + +#if (NGX_HAVE_MAX_PATH) + real = buffer; +#else + real = NULL; +#endif + + real = ngx_realpath(path.data, real); + + if (real == NULL) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_realpath_n " \"%s\" failed", path.data); + return NGX_ERROR; + } + + len = ngx_strlen(real); + + v->data = ngx_pnalloc(r->pool, len); + if (v->data == NULL) { +#if !(NGX_HAVE_MAX_PATH) + ngx_free(real); +#endif + return NGX_ERROR; + } + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + ngx_memcpy(v->data, real, len); + +#if !(NGX_HAVE_MAX_PATH) + ngx_free(real); +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_filename(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + size_t root; + ngx_str_t path; + + if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { + return NGX_ERROR; + } + + /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */ + + v->len = path.len - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = path.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_server_name(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_core_srv_conf_t *cscf; + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + v->len = cscf->server_name.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = cscf->server_name.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_method(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->main->method_name.data) { + v->len = r->main->method_name.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->main->method_name.data; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_remote_user(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_int_t rc; + + rc = ngx_http_auth_basic_user(r); + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + v->len = r->headers_in.user.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->headers_in.user.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_bytes_sent(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", r->connection->sent) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + off_t sent; + u_char *p; + + sent = r->connection->sent - r->header_size; + + if (sent < 0) { + sent = 0; + } + + p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", sent) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_pipe(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->data = (u_char *) (r->pipeline ? "p" : "."); + v->len = 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_status(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t status; + + v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN); + if (v->data == NULL) { + return NGX_ERROR; + } + + if (r->err_status) { + status = r->err_status; + + } else if (r->headers_out.status) { + status = r->headers_out.status; + + } else if (r->http_version == NGX_HTTP_VERSION_9) { + status = 9; + + } else { + status = 0; + } + + v->len = ngx_sprintf(v->data, "%03ui", status) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_sent_content_type(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->headers_out.content_type.len) { + v->len = r->headers_out.content_type.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->headers_out.content_type.data; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_sent_content_length(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + if (r->headers_out.content_length) { + v->len = r->headers_out.content_length->value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->headers_out.content_length->value.data; + + return NGX_OK; + } + + if (r->headers_out.content_length_n >= 0) { + p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_sent_location(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t name; + + if (r->headers_out.location) { + v->len = r->headers_out.location->value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->headers_out.location->value.data; + + return NGX_OK; + } + + ngx_str_set(&name, "sent_http_location"); + + return ngx_http_variable_unknown_header(v, &name, + &r->headers_out.headers.part, + sizeof("sent_http_") - 1); +} + + +static ngx_int_t +ngx_http_variable_sent_last_modified(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + if (r->headers_out.last_modified) { + v->len = r->headers_out.last_modified->value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->headers_out.last_modified->value.data; + + return NGX_OK; + } + + if (r->headers_out.last_modified_time >= 0) { + p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_sent_connection(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + size_t len; + char *p; + + if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) { + len = sizeof("upgrade") - 1; + p = "upgrade"; + + } else if (r->keepalive) { + len = sizeof("keep-alive") - 1; + p = "keep-alive"; + + } else { + len = sizeof("close") - 1; + p = "close"; + } + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_sent_keep_alive(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + ngx_http_core_loc_conf_t *clcf; + + if (r->keepalive) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->keepalive_header) { + + p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; + } + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->chunked) { + v->len = sizeof("chunked") - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "chunked"; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_completion(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->request_complete) { + v->len = 2; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "OK"; + + return NGX_OK; + } + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) ""; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_body(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_buf_t *buf; + ngx_chain_t *cl; + + if (r->request_body == NULL + || r->request_body->bufs == NULL + || r->request_body->temp_file) + { + v->not_found = 1; + + return NGX_OK; + } + + cl = r->request_body->bufs; + buf = cl->buf; + + if (cl->next == NULL) { + v->len = buf->last - buf->pos; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = buf->pos; + + return NGX_OK; + } + + len = buf->last - buf->pos; + cl = cl->next; + + for ( /* void */ ; cl; cl = cl->next) { + buf = cl->buf; + len += buf->last - buf->pos; + } + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + cl = r->request_body->bufs; + + for ( /* void */ ; cl; cl = cl->next) { + buf = cl->buf; + p = ngx_cpymem(p, buf->pos, buf->last - buf->pos); + } + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_body_file(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->request_body == NULL || r->request_body->temp_file == NULL) { + v->not_found = 1; + + return NGX_OK; + } + + v->len = r->request_body->temp_file->file.name.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->request_body->temp_file->file.name.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_length(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", r->request_length) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_request_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + ngx_time_t *tp; + ngx_msec_int_t ms; + + p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4); + if (p == NULL) { + return NGX_ERROR; + } + + tp = ngx_timeofday(); + + ms = (ngx_msec_int_t) + ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); + ms = ngx_max(ms, 0); + + v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_connection(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%uA", r->connection->number) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_connection_requests(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_INT_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%ui", r->connection->requests) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_nginx_version(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->len = sizeof(NGINX_VERSION) - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) NGINX_VERSION; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_hostname(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->len = ngx_cycle->hostname.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = ngx_cycle->hostname.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_pid(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_INT64_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%P", ngx_pid) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_msec(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + ngx_time_t *tp; + + p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4); + if (p == NULL) { + return NGX_ERROR; + } + + tp = ngx_timeofday(); + + v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_time_iso8601(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, ngx_cached_http_log_iso8601.len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, ngx_cached_http_log_iso8601.data, + ngx_cached_http_log_iso8601.len); + + v->len = ngx_cached_http_log_iso8601.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_time_local(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, ngx_cached_http_log_time.len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len); + + v->len = ngx_cached_http_log_time.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +void * +ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_str_t *match) +{ + void *value; + u_char *low; + size_t len; + ngx_uint_t key; + + len = match->len; + + if (len) { + low = ngx_pnalloc(r->pool, len); + if (low == NULL) { + return NULL; + } + + } else { + low = NULL; + } + + key = ngx_hash_strlow(low, match->data, len); + + value = ngx_hash_find_combined(&map->hash, key, low, len); + if (value) { + return value; + } + +#if (NGX_PCRE) + + if (len && map->nregex) { + ngx_int_t n; + ngx_uint_t i; + ngx_http_map_regex_t *reg; + + reg = map->regex; + + for (i = 0; i < map->nregex; i++) { + + n = ngx_http_regex_exec(r, reg[i].regex, match); + + if (n == NGX_OK) { + return reg[i].value; + } + + if (n == NGX_DECLINED) { + continue; + } + + /* NGX_ERROR */ + + return NULL; + } + } + +#endif + + return NULL; +} + + +#if (NGX_PCRE) + +static ngx_int_t +ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + v->not_found = 1; + return NGX_OK; +} + + +ngx_http_regex_t * +ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) +{ + u_char *p; + size_t size; + ngx_str_t name; + ngx_uint_t i, n; + ngx_http_variable_t *v; + ngx_http_regex_t *re; + ngx_http_regex_variable_t *rv; + ngx_http_core_main_conf_t *cmcf; + + rc->pool = cf->pool; + + if (ngx_regex_compile(rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err); + return NULL; + } + + re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t)); + if (re == NULL) { + return NULL; + } + + re->regex = rc->regex; + re->ncaptures = rc->captures; + re->name = rc->pattern; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures); + + n = (ngx_uint_t) rc->named_captures; + + if (n == 0) { + return re; + } + + rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t)); + if (rv == NULL) { + return NULL; + } + + re->variables = rv; + re->nvariables = n; + + size = rc->name_size; + p = rc->names; + + for (i = 0; i < n; i++) { + rv[i].capture = 2 * ((p[0] << 8) + p[1]); + + name.data = &p[2]; + name.len = ngx_strlen(name.data); + + v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); + if (v == NULL) { + return NULL; + } + + rv[i].index = ngx_http_get_variable_index(cf, &name); + if (rv[i].index == NGX_ERROR) { + return NULL; + } + + v->get_handler = ngx_http_variable_not_found; + + p += size; + } + + return re; +} + + +ngx_int_t +ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s) +{ + ngx_int_t rc, index; + ngx_uint_t i, n, len; + ngx_http_variable_value_t *vv; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + if (re->ncaptures) { + len = cmcf->ncaptures; + + if (r->captures == NULL) { + r->captures = ngx_palloc(r->pool, len * sizeof(int)); + if (r->captures == NULL) { + return NGX_ERROR; + } + } + + } else { + len = 0; + } + + rc = ngx_regex_exec(re->regex, s, r->captures, len); + + if (rc == NGX_REGEX_NO_MATCHED) { + return NGX_DECLINED; + } + + if (rc < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", + rc, s, &re->name); + return NGX_ERROR; + } + + for (i = 0; i < re->nvariables; i++) { + + n = re->variables[i].capture; + index = re->variables[i].index; + vv = &r->variables[index]; + + vv->len = r->captures[n + 1] - r->captures[n]; + vv->valid = 1; + vv->no_cacheable = 0; + vv->not_found = 0; + vv->data = &s->data[r->captures[n]]; + +#if (NGX_DEBUG) + { + ngx_http_variable_t *v; + + v = cmcf->variables.elts; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http regex set $%V to \"%*s\"", + &v[index].name, vv->len, vv->data); + } +#endif + } + + r->ncaptures = rc * 2; + r->captures_data = s->data; + + return NGX_OK; +} + +#endif + + +ngx_int_t +ngx_http_variables_add_core_vars(ngx_conf_t *cf) +{ + ngx_int_t rc; + ngx_http_variable_t *cv, *v; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, + sizeof(ngx_hash_keys_arrays_t)); + if (cmcf->variables_keys == NULL) { + return NGX_ERROR; + } + + cmcf->variables_keys->pool = cf->pool; + cmcf->variables_keys->temp_pool = cf->pool; + + if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) + != NGX_OK) + { + return NGX_ERROR; + } + + for (cv = ngx_http_core_variables; cv->name.len; cv++) { + v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t)); + if (v == NULL) { + return NGX_ERROR; + } + + *v = *cv; + + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, + NGX_HASH_READONLY_KEY); + + if (rc == NGX_OK) { + continue; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", &v->name); + } + + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_int_t +ngx_http_variables_init_vars(ngx_conf_t *cf) +{ + ngx_uint_t i, n; + ngx_hash_key_t *key; + ngx_hash_init_t hash; + ngx_http_variable_t *v, *av; + ngx_http_core_main_conf_t *cmcf; + + /* set the handlers for the indexed http variables */ + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + v = cmcf->variables.elts; + key = cmcf->variables_keys->keys.elts; + + for (i = 0; i < cmcf->variables.nelts; i++) { + + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + + av = key[n].value; + + if (v[i].name.len == key[n].key.len + && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len) + == 0) + { + v[i].get_handler = av->get_handler; + v[i].data = av->data; + + av->flags |= NGX_HTTP_VAR_INDEXED; + v[i].flags = av->flags; + + av->index = i; + + if (av->get_handler == NULL) { + break; + } + + goto next; + } + } + + if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { + v[i].get_handler = ngx_http_variable_unknown_header_in; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) { + v[i].get_handler = ngx_http_variable_unknown_header_out; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) { + v[i].get_handler = ngx_http_upstream_header_variable; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) { + v[i].get_handler = ngx_http_variable_cookie; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) { + v[i].get_handler = ngx_http_upstream_cookie_variable; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { + v[i].get_handler = ngx_http_variable_argument; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; + + continue; + } + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown \"%V\" variable", &v[i].name); + + return NGX_ERROR; + + next: + continue; + } + + + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + av = key[n].value; + + if (av->flags & NGX_HTTP_VAR_NOHASH) { + key[n].key.data = NULL; + } + } + + + hash.hash = &cmcf->variables_hash; + hash.key = ngx_hash_key; + hash.max_size = cmcf->variables_hash_max_size; + hash.bucket_size = cmcf->variables_hash_bucket_size; + hash.name = "variables_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts, + cmcf->variables_keys->keys.nelts) + != NGX_OK) + { + return NGX_ERROR; + } + + cmcf->variables_keys = NULL; + + return NGX_OK; +} diff --git a/hm_nginx/src/http/ngx_http_variables.h b/hm_nginx/src/http/ngx_http_variables.h new file mode 100644 index 0000000..829fab3 --- /dev/null +++ b/hm_nginx/src/http/ngx_http_variables.h @@ -0,0 +1,112 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_HTTP_VARIABLES_H_INCLUDED_ +#define _NGX_HTTP_VARIABLES_H_INCLUDED_ + + +#include +#include +#include + + +typedef ngx_variable_value_t ngx_http_variable_value_t; + +#define ngx_http_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } + +typedef struct ngx_http_variable_s ngx_http_variable_t; + +typedef void (*ngx_http_set_variable_pt) (ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +typedef ngx_int_t (*ngx_http_get_variable_pt) (ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + + +#define NGX_HTTP_VAR_CHANGEABLE 1 +#define NGX_HTTP_VAR_NOCACHEABLE 2 +#define NGX_HTTP_VAR_INDEXED 4 +#define NGX_HTTP_VAR_NOHASH 8 + + +struct ngx_http_variable_s { + ngx_str_t name; /* must be first to build the hash */ + ngx_http_set_variable_pt set_handler; + ngx_http_get_variable_pt get_handler; + uintptr_t data; + ngx_uint_t flags; + ngx_uint_t index; +}; + + +ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, + ngx_uint_t flags); +ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); +ngx_http_variable_value_t *ngx_http_get_indexed_variable(ngx_http_request_t *r, + ngx_uint_t index); +ngx_http_variable_value_t *ngx_http_get_flushed_variable(ngx_http_request_t *r, + ngx_uint_t index); + +ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, + ngx_str_t *name, ngx_uint_t key); + +ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, + ngx_str_t *var, ngx_list_part_t *part, size_t prefix); + + +#if (NGX_PCRE) + +typedef struct { + ngx_uint_t capture; + ngx_int_t index; +} ngx_http_regex_variable_t; + + +typedef struct { + ngx_regex_t *regex; + ngx_uint_t ncaptures; + ngx_http_regex_variable_t *variables; + ngx_uint_t nvariables; + ngx_str_t name; +} ngx_http_regex_t; + + +typedef struct { + ngx_http_regex_t *regex; + void *value; +} ngx_http_map_regex_t; + + +ngx_http_regex_t *ngx_http_regex_compile(ngx_conf_t *cf, + ngx_regex_compile_t *rc); +ngx_int_t ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, + ngx_str_t *s); + +#endif + + +typedef struct { + ngx_hash_combined_t hash; +#if (NGX_PCRE) + ngx_http_map_regex_t *regex; + ngx_uint_t nregex; +#endif +} ngx_http_map_t; + + +void *ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, + ngx_str_t *match); + + +ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf); +ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf); + + +extern ngx_http_variable_value_t ngx_http_variable_null_value; +extern ngx_http_variable_value_t ngx_http_variable_true_value; + + +#endif /* _NGX_HTTP_VARIABLES_H_INCLUDED_ */ diff --git a/hm_nginx/src/http/ngx_http_write_filter_module.c b/hm_nginx/src/http/ngx_http_write_filter_module.c new file mode 100644 index 0000000..c164440 --- /dev/null +++ b/hm_nginx/src/http/ngx_http_write_filter_module.c @@ -0,0 +1,327 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +static ngx_int_t ngx_http_write_filter_init(ngx_conf_t *cf); + + +static ngx_http_module_t ngx_http_write_filter_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_write_filter_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL, /* merge location configuration */ +}; + + +ngx_module_t ngx_http_write_filter_module = { + NGX_MODULE_V1, + &ngx_http_write_filter_module_ctx, /* module context */ + NULL, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +ngx_int_t +ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + off_t size, sent, nsent, limit; + ngx_uint_t last, flush, sync; + ngx_msec_t delay; + ngx_chain_t *cl, *ln, **ll, *chain; + ngx_connection_t *c; + ngx_http_core_loc_conf_t *clcf; + + c = r->connection; + + if (c->error) { + return NGX_ERROR; + } + + size = 0; + flush = 0; + sync = 0; + last = 0; + ll = &r->out; + + /* find the size, the flush point and the last link of the saved chain */ + + for (cl = r->out; cl; cl = cl->next) { + ll = &cl->next; + + ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, + "write old buf t:%d f:%d %p, pos %p, size: %z " + "file: %O, size: %O", + cl->buf->temporary, cl->buf->in_file, + cl->buf->start, cl->buf->pos, + cl->buf->last - cl->buf->pos, + cl->buf->file_pos, + cl->buf->file_last - cl->buf->file_pos); + +#if 1 + if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "zero size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } +#endif + + size += ngx_buf_size(cl->buf); + + if (cl->buf->flush || cl->buf->recycled) { + flush = 1; + } + + if (cl->buf->sync) { + sync = 1; + } + + if (cl->buf->last_buf) { + last = 1; + } + } + + /* add the new chain to the existent one */ + + for (ln = in; ln; ln = ln->next) { + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = ln->buf; + *ll = cl; + ll = &cl->next; + + ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, + "write new buf t:%d f:%d %p, pos %p, size: %z " + "file: %O, size: %O", + cl->buf->temporary, cl->buf->in_file, + cl->buf->start, cl->buf->pos, + cl->buf->last - cl->buf->pos, + cl->buf->file_pos, + cl->buf->file_last - cl->buf->file_pos); + +#if 1 + if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "zero size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } +#endif + + size += ngx_buf_size(cl->buf); + + if (cl->buf->flush || cl->buf->recycled) { + flush = 1; + } + + if (cl->buf->sync) { + sync = 1; + } + + if (cl->buf->last_buf) { + last = 1; + } + } + + *ll = NULL; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http write filter: l:%d f:%d s:%O", last, flush, size); + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + /* + * avoid the output if there are no last buf, no flush point, + * there are the incoming bufs and the size of all bufs + * is smaller than "postpone_output" directive + */ + + if (!last && !flush && in && size < (off_t) clcf->postpone_output) { + return NGX_OK; + } + + if (c->write->delayed) { + c->buffered |= NGX_HTTP_WRITE_BUFFERED; + return NGX_AGAIN; + } + + if (size == 0 + && !(c->buffered & NGX_LOWLEVEL_BUFFERED) + && !(last && c->need_last_buf)) + { + if (last || flush || sync) { + for (cl = r->out; cl; /* void */) { + ln = cl; + cl = cl->next; + ngx_free_chain(r->pool, ln); + } + + r->out = NULL; + c->buffered &= ~NGX_HTTP_WRITE_BUFFERED; + + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "the http output chain is empty"); + + ngx_debug_point(); + + return NGX_ERROR; + } + + if (r->limit_rate) { + if (r->limit_rate_after == 0) { + r->limit_rate_after = clcf->limit_rate_after; + } + + limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1) + - (c->sent - r->limit_rate_after); + + if (limit <= 0) { + c->write->delayed = 1; + delay = (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1); + ngx_add_timer(c->write, delay); + + c->buffered |= NGX_HTTP_WRITE_BUFFERED; + + return NGX_AGAIN; + } + + if (clcf->sendfile_max_chunk + && (off_t) clcf->sendfile_max_chunk < limit) + { + limit = clcf->sendfile_max_chunk; + } + + } else { + limit = clcf->sendfile_max_chunk; + } + + sent = c->sent; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http write filter limit %O", limit); + + chain = c->send_chain(c, r->out, limit); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http write filter %p", chain); + + if (chain == NGX_CHAIN_ERROR) { + c->error = 1; + return NGX_ERROR; + } + + if (r->limit_rate) { + + nsent = c->sent; + + if (r->limit_rate_after) { + + sent -= r->limit_rate_after; + if (sent < 0) { + sent = 0; + } + + nsent -= r->limit_rate_after; + if (nsent < 0) { + nsent = 0; + } + } + + delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate); + + if (delay > 0) { + limit = 0; + c->write->delayed = 1; + ngx_add_timer(c->write, delay); + } + } + + if (limit + && c->write->ready + && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize)) + { + c->write->delayed = 1; + ngx_add_timer(c->write, 1); + } + + for (cl = r->out; cl && cl != chain; /* void */) { + ln = cl; + cl = cl->next; + ngx_free_chain(r->pool, ln); + } + + r->out = chain; + + if (chain) { + c->buffered |= NGX_HTTP_WRITE_BUFFERED; + return NGX_AGAIN; + } + + c->buffered &= ~NGX_HTTP_WRITE_BUFFERED; + + if ((c->buffered & NGX_LOWLEVEL_BUFFERED) && r->postponed == NULL) { + return NGX_AGAIN; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_write_filter_init(ngx_conf_t *cf) +{ + ngx_http_top_body_filter = ngx_http_write_filter; + + return NGX_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail.c b/hm_nginx/src/mail/ngx_mail.c new file mode 100644 index 0000000..bf1b858 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail.c @@ -0,0 +1,567 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, + ngx_mail_listen_t *listen); +static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports); +static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr); +#if (NGX_HAVE_INET6) +static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr); +#endif +static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two); + + +ngx_uint_t ngx_mail_max_module; + + +static ngx_command_t ngx_mail_commands[] = { + + { ngx_string("mail"), + NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_mail_block, + 0, + 0, + NULL }, + + { ngx_string("imap"), + NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_mail_block, + 0, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_core_module_t ngx_mail_module_ctx = { + ngx_string("mail"), + NULL, + NULL +}; + + +ngx_module_t ngx_mail_module = { + NGX_MODULE_V1, + &ngx_mail_module_ctx, /* module context */ + ngx_mail_commands, /* module directives */ + NGX_CORE_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static char * +ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *rv; + ngx_uint_t i, m, mi, s; + ngx_conf_t pcf; + ngx_array_t ports; + ngx_mail_listen_t *listen; + ngx_mail_module_t *module; + ngx_mail_conf_ctx_t *ctx; + ngx_mail_core_srv_conf_t **cscfp; + ngx_mail_core_main_conf_t *cmcf; + + if (cmd->name.data[0] == 'i') { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the \"imap\" directive is deprecated, " + "use the \"mail\" directive instead"); + } + + /* the main mail context */ + + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); + if (ctx == NULL) { + return NGX_CONF_ERROR; + } + + *(ngx_mail_conf_ctx_t **) conf = ctx; + + /* count the number of the mail modules and set up their indices */ + + ngx_mail_max_module = 0; + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + ngx_modules[m]->ctx_index = ngx_mail_max_module++; + } + + + /* the mail main_conf context, it is the same in the all mail contexts */ + + ctx->main_conf = ngx_pcalloc(cf->pool, + sizeof(void *) * ngx_mail_max_module); + if (ctx->main_conf == NULL) { + return NGX_CONF_ERROR; + } + + + /* + * the mail null srv_conf context, it is used to merge + * the server{}s' srv_conf's + */ + + ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module); + if (ctx->srv_conf == NULL) { + return NGX_CONF_ERROR; + } + + + /* + * create the main_conf's and the null srv_conf's of the all mail modules + */ + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + mi = ngx_modules[m]->ctx_index; + + if (module->create_main_conf) { + ctx->main_conf[mi] = module->create_main_conf(cf); + if (ctx->main_conf[mi] == NULL) { + return NGX_CONF_ERROR; + } + } + + if (module->create_srv_conf) { + ctx->srv_conf[mi] = module->create_srv_conf(cf); + if (ctx->srv_conf[mi] == NULL) { + return NGX_CONF_ERROR; + } + } + } + + + /* parse inside the mail{} block */ + + pcf = *cf; + cf->ctx = ctx; + + cf->module_type = NGX_MAIL_MODULE; + cf->cmd_type = NGX_MAIL_MAIN_CONF; + rv = ngx_conf_parse(cf, NULL); + + if (rv != NGX_CONF_OK) { + *cf = pcf; + return rv; + } + + + /* init mail{} main_conf's, merge the server{}s' srv_conf's */ + + cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; + cscfp = cmcf->servers.elts; + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + mi = ngx_modules[m]->ctx_index; + + /* init mail{} main_conf's */ + + cf->ctx = ctx; + + if (module->init_main_conf) { + rv = module->init_main_conf(cf, ctx->main_conf[mi]); + if (rv != NGX_CONF_OK) { + *cf = pcf; + return rv; + } + } + + for (s = 0; s < cmcf->servers.nelts; s++) { + + /* merge the server{}s' srv_conf's */ + + cf->ctx = cscfp[s]->ctx; + + if (module->merge_srv_conf) { + rv = module->merge_srv_conf(cf, + ctx->srv_conf[mi], + cscfp[s]->ctx->srv_conf[mi]); + if (rv != NGX_CONF_OK) { + *cf = pcf; + return rv; + } + } + } + } + + *cf = pcf; + + + if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + listen = cmcf->listen.elts; + + for (i = 0; i < cmcf->listen.nelts; i++) { + if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + return ngx_mail_optimize_servers(cf, &ports); +} + + +static ngx_int_t +ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, + ngx_mail_listen_t *listen) +{ + in_port_t p; + ngx_uint_t i; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_mail_conf_port_t *port; + ngx_mail_conf_addr_t *addr; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + sa = (struct sockaddr *) &listen->sockaddr; + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + p = sin6->sin6_port; + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + p = 0; + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + p = sin->sin_port; + break; + } + + port = ports->elts; + for (i = 0; i < ports->nelts; i++) { + if (p == port[i].port && sa->sa_family == port[i].family) { + + /* a port is already in the port list */ + + port = &port[i]; + goto found; + } + } + + /* add a port to the port list */ + + port = ngx_array_push(ports); + if (port == NULL) { + return NGX_ERROR; + } + + port->family = sa->sa_family; + port->port = p; + + if (ngx_array_init(&port->addrs, cf->temp_pool, 2, + sizeof(ngx_mail_conf_addr_t)) + != NGX_OK) + { + return NGX_ERROR; + } + +found: + + addr = ngx_array_push(&port->addrs); + if (addr == NULL) { + return NGX_ERROR; + } + + addr->sockaddr = (struct sockaddr *) &listen->sockaddr; + addr->socklen = listen->socklen; + addr->ctx = listen->ctx; + addr->bind = listen->bind; + addr->wildcard = listen->wildcard; + addr->so_keepalive = listen->so_keepalive; +#if (NGX_HAVE_KEEPALIVE_TUNABLE) + addr->tcp_keepidle = listen->tcp_keepidle; + addr->tcp_keepintvl = listen->tcp_keepintvl; + addr->tcp_keepcnt = listen->tcp_keepcnt; +#endif +#if (NGX_MAIL_SSL) + addr->ssl = listen->ssl; +#endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + addr->ipv6only = listen->ipv6only; +#endif + + return NGX_OK; +} + + +static char * +ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) +{ + ngx_uint_t i, p, last, bind_wildcard; + ngx_listening_t *ls; + ngx_mail_port_t *mport; + ngx_mail_conf_port_t *port; + ngx_mail_conf_addr_t *addr; + + port = ports->elts; + for (p = 0; p < ports->nelts; p++) { + + ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, + sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs); + + addr = port[p].addrs.elts; + last = port[p].addrs.nelts; + + /* + * if there is the binding to the "*:port" then we need to bind() + * to the "*:port" only and ignore the other bindings + */ + + if (addr[last - 1].wildcard) { + addr[last - 1].bind = 1; + bind_wildcard = 1; + + } else { + bind_wildcard = 0; + } + + i = 0; + + while (i < last) { + + if (bind_wildcard && !addr[i].bind) { + i++; + continue; + } + + ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen); + if (ls == NULL) { + return NGX_CONF_ERROR; + } + + ls->addr_ntop = 1; + ls->handler = ngx_mail_init_connection; + ls->pool_size = 256; + + /* TODO: error_log directive */ + ls->logp = &cf->cycle->new_log; + ls->log.data = &ls->addr_text; + ls->log.handler = ngx_accept_log_error; + + ls->keepalive = addr[i].so_keepalive; +#if (NGX_HAVE_KEEPALIVE_TUNABLE) + ls->keepidle = addr[i].tcp_keepidle; + ls->keepintvl = addr[i].tcp_keepintvl; + ls->keepcnt = addr[i].tcp_keepcnt; +#endif + +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + ls->ipv6only = addr[i].ipv6only; +#endif + + mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t)); + if (mport == NULL) { + return NGX_CONF_ERROR; + } + + ls->servers = mport; + + if (i == last - 1) { + mport->naddrs = last; + + } else { + mport->naddrs = 1; + i = 0; + } + + switch (ls->sockaddr->sa_family) { +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) { + return NGX_CONF_ERROR; + } + break; +#endif + default: /* AF_INET */ + if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) { + return NGX_CONF_ERROR; + } + break; + } + + addr++; + last--; + } + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_mail_in_addr_t *addrs; + struct sockaddr_in *sin; + u_char buf[NGX_SOCKADDR_STRLEN]; + + mport->addrs = ngx_pcalloc(cf->pool, + mport->naddrs * sizeof(ngx_mail_in_addr_t)); + if (mport->addrs == NULL) { + return NGX_ERROR; + } + + addrs = mport->addrs; + + for (i = 0; i < mport->naddrs; i++) { + + sin = (struct sockaddr_in *) addr[i].sockaddr; + addrs[i].addr = sin->sin_addr.s_addr; + + addrs[i].conf.ctx = addr[i].ctx; +#if (NGX_MAIL_SSL) + addrs[i].conf.ssl = addr[i].ssl; +#endif + + len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf, + NGX_SOCKADDR_STRLEN, 1); + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, buf, len); + + addrs[i].conf.addr_text.len = len; + addrs[i].conf.addr_text.data = p; + } + + return NGX_OK; +} + + +#if (NGX_HAVE_INET6) + +static ngx_int_t +ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_mail_in6_addr_t *addrs6; + struct sockaddr_in6 *sin6; + u_char buf[NGX_SOCKADDR_STRLEN]; + + mport->addrs = ngx_pcalloc(cf->pool, + mport->naddrs * sizeof(ngx_mail_in6_addr_t)); + if (mport->addrs == NULL) { + return NGX_ERROR; + } + + addrs6 = mport->addrs; + + for (i = 0; i < mport->naddrs; i++) { + + sin6 = (struct sockaddr_in6 *) addr[i].sockaddr; + addrs6[i].addr6 = sin6->sin6_addr; + + addrs6[i].conf.ctx = addr[i].ctx; +#if (NGX_MAIL_SSL) + addrs6[i].conf.ssl = addr[i].ssl; +#endif + + len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf, + NGX_SOCKADDR_STRLEN, 1); + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, buf, len); + + addrs6[i].conf.addr_text.len = len; + addrs6[i].conf.addr_text.data = p; + } + + return NGX_OK; +} + +#endif + + +static ngx_int_t +ngx_mail_cmp_conf_addrs(const void *one, const void *two) +{ + ngx_mail_conf_addr_t *first, *second; + + first = (ngx_mail_conf_addr_t *) one; + second = (ngx_mail_conf_addr_t *) two; + + if (first->wildcard) { + /* a wildcard must be the last resort, shift it to the end */ + return 1; + } + + if (second->wildcard) { + /* a wildcard must be the last resort, shift it to the end */ + return -1; + } + + if (first->bind && !second->bind) { + /* shift explicit bind()ed addresses to the start */ + return -1; + } + + if (!first->bind && second->bind) { + /* shift explicit bind()ed addresses to the start */ + return 1; + } + + /* do not sort by default */ + + return 0; +} diff --git a/hm_nginx/src/mail/ngx_mail.h b/hm_nginx/src/mail/ngx_mail.h new file mode 100644 index 0000000..0226139 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail.h @@ -0,0 +1,423 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_MAIL_H_INCLUDED_ +#define _NGX_MAIL_H_INCLUDED_ + + +#include +#include +#include +#include + +#if (NGX_MAIL_SSL) +#include +#endif + + + +typedef struct { + void **main_conf; + void **srv_conf; +} ngx_mail_conf_ctx_t; + + +typedef struct { + u_char sockaddr[NGX_SOCKADDRLEN]; + socklen_t socklen; + + /* server ctx */ + ngx_mail_conf_ctx_t *ctx; + + unsigned bind:1; + unsigned wildcard:1; +#if (NGX_MAIL_SSL) + unsigned ssl:1; +#endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + unsigned ipv6only:1; +#endif + unsigned so_keepalive:2; +#if (NGX_HAVE_KEEPALIVE_TUNABLE) + int tcp_keepidle; + int tcp_keepintvl; + int tcp_keepcnt; +#endif +} ngx_mail_listen_t; + + +typedef struct { + ngx_mail_conf_ctx_t *ctx; + ngx_str_t addr_text; +#if (NGX_MAIL_SSL) + ngx_uint_t ssl; /* unsigned ssl:1; */ +#endif +} ngx_mail_addr_conf_t; + +typedef struct { + in_addr_t addr; + ngx_mail_addr_conf_t conf; +} ngx_mail_in_addr_t; + + +#if (NGX_HAVE_INET6) + +typedef struct { + struct in6_addr addr6; + ngx_mail_addr_conf_t conf; +} ngx_mail_in6_addr_t; + +#endif + + +typedef struct { + /* ngx_mail_in_addr_t or ngx_mail_in6_addr_t */ + void *addrs; + ngx_uint_t naddrs; +} ngx_mail_port_t; + + +typedef struct { + int family; + in_port_t port; + ngx_array_t addrs; /* array of ngx_mail_conf_addr_t */ +} ngx_mail_conf_port_t; + + +typedef struct { + struct sockaddr *sockaddr; + socklen_t socklen; + + ngx_mail_conf_ctx_t *ctx; + + unsigned bind:1; + unsigned wildcard:1; +#if (NGX_MAIL_SSL) + unsigned ssl:1; +#endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + unsigned ipv6only:1; +#endif + unsigned so_keepalive:2; +#if (NGX_HAVE_KEEPALIVE_TUNABLE) + int tcp_keepidle; + int tcp_keepintvl; + int tcp_keepcnt; +#endif +} ngx_mail_conf_addr_t; + + +typedef struct { + ngx_array_t servers; /* ngx_mail_core_srv_conf_t */ + ngx_array_t listen; /* ngx_mail_listen_t */ +} ngx_mail_core_main_conf_t; + + +#define NGX_MAIL_POP3_PROTOCOL 0 +#define NGX_MAIL_IMAP_PROTOCOL 1 +#define NGX_MAIL_SMTP_PROTOCOL 2 + + +typedef struct ngx_mail_protocol_s ngx_mail_protocol_t; + + +typedef struct { + ngx_mail_protocol_t *protocol; + + ngx_msec_t timeout; + ngx_msec_t resolver_timeout; + + ngx_flag_t so_keepalive; + + ngx_str_t server_name; + + u_char *file_name; + ngx_int_t line; + + ngx_resolver_t *resolver; + + /* server ctx */ + ngx_mail_conf_ctx_t *ctx; +} ngx_mail_core_srv_conf_t; + + +typedef enum { + ngx_pop3_start = 0, + ngx_pop3_user, + ngx_pop3_passwd, + ngx_pop3_auth_login_username, + ngx_pop3_auth_login_password, + ngx_pop3_auth_plain, + ngx_pop3_auth_cram_md5 +} ngx_pop3_state_e; + + +typedef enum { + ngx_imap_start = 0, + ngx_imap_auth_login_username, + ngx_imap_auth_login_password, + ngx_imap_auth_plain, + ngx_imap_auth_cram_md5, + ngx_imap_login, + ngx_imap_user, + ngx_imap_passwd +} ngx_imap_state_e; + + +typedef enum { + ngx_smtp_start = 0, + ngx_smtp_auth_login_username, + ngx_smtp_auth_login_password, + ngx_smtp_auth_plain, + ngx_smtp_auth_cram_md5, + ngx_smtp_helo, + ngx_smtp_helo_xclient, + ngx_smtp_helo_from, + ngx_smtp_xclient, + ngx_smtp_xclient_from, + ngx_smtp_xclient_helo, + ngx_smtp_from, + ngx_smtp_to +} ngx_smtp_state_e; + + +typedef struct { + ngx_peer_connection_t upstream; + ngx_buf_t *buffer; +} ngx_mail_proxy_ctx_t; + + +typedef struct { + uint32_t signature; /* "MAIL" */ + + ngx_connection_t *connection; + + ngx_str_t out; + ngx_buf_t *buffer; + + void **ctx; + void **main_conf; + void **srv_conf; + + ngx_resolver_ctx_t *resolver_ctx; + + ngx_mail_proxy_ctx_t *proxy; + + ngx_uint_t mail_state; + + unsigned protocol:3; + unsigned blocked:1; + unsigned quit:1; + unsigned quoted:1; + unsigned backslash:1; + unsigned no_sync_literal:1; + unsigned starttls:1; + unsigned esmtp:1; + unsigned auth_method:3; + unsigned auth_wait:1; + + ngx_str_t login; + ngx_str_t passwd; + + ngx_str_t salt; + ngx_str_t tag; + ngx_str_t tagged_line; + ngx_str_t text; + + ngx_str_t *addr_text; + ngx_str_t host; + ngx_str_t smtp_helo; + ngx_str_t smtp_from; + ngx_str_t smtp_to; + + ngx_str_t cmd; + + ngx_uint_t command; + ngx_array_t args; + + ngx_uint_t login_attempt; + + /* used to parse POP3/IMAP/SMTP command */ + + ngx_uint_t state; + u_char *cmd_start; + u_char *arg_start; + u_char *arg_end; + ngx_uint_t literal_len; +} ngx_mail_session_t; + + +typedef struct { + ngx_str_t *client; + ngx_mail_session_t *session; +} ngx_mail_log_ctx_t; + + +#define NGX_POP3_USER 1 +#define NGX_POP3_PASS 2 +#define NGX_POP3_CAPA 3 +#define NGX_POP3_QUIT 4 +#define NGX_POP3_NOOP 5 +#define NGX_POP3_STLS 6 +#define NGX_POP3_APOP 7 +#define NGX_POP3_AUTH 8 +#define NGX_POP3_STAT 9 +#define NGX_POP3_LIST 10 +#define NGX_POP3_RETR 11 +#define NGX_POP3_DELE 12 +#define NGX_POP3_RSET 13 +#define NGX_POP3_TOP 14 +#define NGX_POP3_UIDL 15 + + +#define NGX_IMAP_LOGIN 1 +#define NGX_IMAP_LOGOUT 2 +#define NGX_IMAP_CAPABILITY 3 +#define NGX_IMAP_NOOP 4 +#define NGX_IMAP_STARTTLS 5 + +#define NGX_IMAP_NEXT 6 + +#define NGX_IMAP_AUTHENTICATE 7 + + +#define NGX_SMTP_HELO 1 +#define NGX_SMTP_EHLO 2 +#define NGX_SMTP_AUTH 3 +#define NGX_SMTP_QUIT 4 +#define NGX_SMTP_NOOP 5 +#define NGX_SMTP_MAIL 6 +#define NGX_SMTP_RSET 7 +#define NGX_SMTP_RCPT 8 +#define NGX_SMTP_DATA 9 +#define NGX_SMTP_VRFY 10 +#define NGX_SMTP_EXPN 11 +#define NGX_SMTP_HELP 12 +#define NGX_SMTP_STARTTLS 13 + + +#define NGX_MAIL_AUTH_PLAIN 0 +#define NGX_MAIL_AUTH_LOGIN 1 +#define NGX_MAIL_AUTH_LOGIN_USERNAME 2 +#define NGX_MAIL_AUTH_APOP 3 +#define NGX_MAIL_AUTH_CRAM_MD5 4 +#define NGX_MAIL_AUTH_NONE 5 + + +#define NGX_MAIL_AUTH_PLAIN_ENABLED 0x0002 +#define NGX_MAIL_AUTH_LOGIN_ENABLED 0x0004 +#define NGX_MAIL_AUTH_APOP_ENABLED 0x0008 +#define NGX_MAIL_AUTH_CRAM_MD5_ENABLED 0x0010 +#define NGX_MAIL_AUTH_NONE_ENABLED 0x0020 + + +#define NGX_MAIL_PARSE_INVALID_COMMAND 20 + + +typedef void (*ngx_mail_init_session_pt)(ngx_mail_session_t *s, + ngx_connection_t *c); +typedef void (*ngx_mail_init_protocol_pt)(ngx_event_t *rev); +typedef void (*ngx_mail_auth_state_pt)(ngx_event_t *rev); +typedef ngx_int_t (*ngx_mail_parse_command_pt)(ngx_mail_session_t *s); + + +struct ngx_mail_protocol_s { + ngx_str_t name; + in_port_t port[4]; + ngx_uint_t type; + + ngx_mail_init_session_pt init_session; + ngx_mail_init_protocol_pt init_protocol; + ngx_mail_parse_command_pt parse_command; + ngx_mail_auth_state_pt auth_state; + + ngx_str_t internal_server_error; + ngx_str_t cert_error; + ngx_str_t no_cert; +}; + + +typedef struct { + ngx_mail_protocol_t *protocol; + + void *(*create_main_conf)(ngx_conf_t *cf); + char *(*init_main_conf)(ngx_conf_t *cf, void *conf); + + void *(*create_srv_conf)(ngx_conf_t *cf); + char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, + void *conf); +} ngx_mail_module_t; + + +#define NGX_MAIL_MODULE 0x4C49414D /* "MAIL" */ + +#define NGX_MAIL_MAIN_CONF 0x02000000 +#define NGX_MAIL_SRV_CONF 0x04000000 + + +#define NGX_MAIL_MAIN_CONF_OFFSET offsetof(ngx_mail_conf_ctx_t, main_conf) +#define NGX_MAIL_SRV_CONF_OFFSET offsetof(ngx_mail_conf_ctx_t, srv_conf) + + +#define ngx_mail_get_module_ctx(s, module) (s)->ctx[module.ctx_index] +#define ngx_mail_set_ctx(s, c, module) s->ctx[module.ctx_index] = c; +#define ngx_mail_delete_ctx(s, module) s->ctx[module.ctx_index] = NULL; + + +#define ngx_mail_get_module_main_conf(s, module) \ + (s)->main_conf[module.ctx_index] +#define ngx_mail_get_module_srv_conf(s, module) (s)->srv_conf[module.ctx_index] + +#define ngx_mail_conf_get_module_main_conf(cf, module) \ + ((ngx_mail_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index] +#define ngx_mail_conf_get_module_srv_conf(cf, module) \ + ((ngx_mail_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index] + + +#if (NGX_MAIL_SSL) +void ngx_mail_starttls_handler(ngx_event_t *rev); +ngx_int_t ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c); +#endif + + +void ngx_mail_init_connection(ngx_connection_t *c); + +ngx_int_t ngx_mail_salt(ngx_mail_session_t *s, ngx_connection_t *c, + ngx_mail_core_srv_conf_t *cscf); +ngx_int_t ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, + ngx_uint_t n); +ngx_int_t ngx_mail_auth_login_username(ngx_mail_session_t *s, + ngx_connection_t *c, ngx_uint_t n); +ngx_int_t ngx_mail_auth_login_password(ngx_mail_session_t *s, + ngx_connection_t *c); +ngx_int_t ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, + ngx_connection_t *c, char *prefix, size_t len); +ngx_int_t ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c); +ngx_int_t ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c); + +void ngx_mail_send(ngx_event_t *wev); +ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_close_connection(ngx_connection_t *c); +void ngx_mail_session_internal_server_error(ngx_mail_session_t *s); +u_char *ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len); + + +char *ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + + +/* STUB */ +void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer); +void ngx_mail_auth_http_init(ngx_mail_session_t *s); +/**/ + + +extern ngx_uint_t ngx_mail_max_module; +extern ngx_module_t ngx_mail_core_module; + + +#endif /* _NGX_MAIL_H_INCLUDED_ */ diff --git a/hm_nginx/src/mail/ngx_mail_auth_http_module.c b/hm_nginx/src/mail/ngx_mail_auth_http_module.c new file mode 100644 index 0000000..d93e946 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_auth_http_module.c @@ -0,0 +1,1590 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +typedef struct { + ngx_addr_t *peer; + + ngx_msec_t timeout; + ngx_flag_t pass_client_cert; + + ngx_str_t host_header; + ngx_str_t uri; + ngx_str_t header; + + ngx_array_t *headers; + + u_char *file; + ngx_uint_t line; +} ngx_mail_auth_http_conf_t; + + +typedef struct ngx_mail_auth_http_ctx_s ngx_mail_auth_http_ctx_t; + +typedef void (*ngx_mail_auth_http_handler_pt)(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx); + +struct ngx_mail_auth_http_ctx_s { + ngx_buf_t *request; + ngx_buf_t *response; + ngx_peer_connection_t peer; + + ngx_mail_auth_http_handler_pt handler; + + ngx_uint_t state; + + u_char *header_name_start; + u_char *header_name_end; + u_char *header_start; + u_char *header_end; + + ngx_str_t addr; + ngx_str_t port; + ngx_str_t err; + ngx_str_t errmsg; + ngx_str_t errcode; + + time_t sleep; + + ngx_pool_t *pool; +}; + + +static void ngx_mail_auth_http_write_handler(ngx_event_t *wev); +static void ngx_mail_auth_http_read_handler(ngx_event_t *rev); +static void ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx); +static void ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx); +static void ngx_mail_auth_sleep_handler(ngx_event_t *rev); +static ngx_int_t ngx_mail_auth_http_parse_header_line(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx); +static void ngx_mail_auth_http_block_read(ngx_event_t *rev); +static void ngx_mail_auth_http_dummy_handler(ngx_event_t *ev); +static ngx_buf_t *ngx_mail_auth_http_create_request(ngx_mail_session_t *s, + ngx_pool_t *pool, ngx_mail_auth_http_conf_t *ahcf); +static ngx_int_t ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, + ngx_str_t *escaped); + +static void *ngx_mail_auth_http_create_conf(ngx_conf_t *cf); +static char *ngx_mail_auth_http_merge_conf(ngx_conf_t *cf, void *parent, + void *child); +static char *ngx_mail_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_mail_auth_http_header(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_command_t ngx_mail_auth_http_commands[] = { + + { ngx_string("auth_http"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_mail_auth_http, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("auth_http_timeout"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_auth_http_conf_t, timeout), + NULL }, + + { ngx_string("auth_http_header"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2, + ngx_mail_auth_http_header, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("auth_http_pass_client_cert"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_auth_http_conf_t, pass_client_cert), + NULL }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_auth_http_module_ctx = { + NULL, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_auth_http_create_conf, /* create server configuration */ + ngx_mail_auth_http_merge_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_auth_http_module = { + NGX_MODULE_V1, + &ngx_mail_auth_http_module_ctx, /* module context */ + ngx_mail_auth_http_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_str_t ngx_mail_auth_http_method[] = { + ngx_string("plain"), + ngx_string("plain"), + ngx_string("plain"), + ngx_string("apop"), + ngx_string("cram-md5"), + ngx_string("none") +}; + +static ngx_str_t ngx_mail_smtp_errcode = ngx_string("535 5.7.0"); + + +void +ngx_mail_auth_http_init(ngx_mail_session_t *s) +{ + ngx_int_t rc; + ngx_pool_t *pool; + ngx_mail_auth_http_ctx_t *ctx; + ngx_mail_auth_http_conf_t *ahcf; + + s->connection->log->action = "in http auth state"; + + pool = ngx_create_pool(2048, s->connection->log); + if (pool == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + + ctx = ngx_pcalloc(pool, sizeof(ngx_mail_auth_http_ctx_t)); + if (ctx == NULL) { + ngx_destroy_pool(pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ctx->pool = pool; + + ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module); + + ctx->request = ngx_mail_auth_http_create_request(s, pool, ahcf); + if (ctx->request == NULL) { + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ngx_mail_set_ctx(s, ctx, ngx_mail_auth_http_module); + + ctx->peer.sockaddr = ahcf->peer->sockaddr; + ctx->peer.socklen = ahcf->peer->socklen; + ctx->peer.name = &ahcf->peer->name; + ctx->peer.get = ngx_event_get_peer; + ctx->peer.log = s->connection->log; + ctx->peer.log_error = NGX_ERROR_ERR; + + rc = ngx_event_connect_peer(&ctx->peer); + + if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { + if (ctx->peer.connection) { + ngx_close_connection(ctx->peer.connection); + } + + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ctx->peer.connection->data = s; + ctx->peer.connection->pool = s->connection->pool; + + s->connection->read->handler = ngx_mail_auth_http_block_read; + ctx->peer.connection->read->handler = ngx_mail_auth_http_read_handler; + ctx->peer.connection->write->handler = ngx_mail_auth_http_write_handler; + + ctx->handler = ngx_mail_auth_http_ignore_status_line; + + ngx_add_timer(ctx->peer.connection->read, ahcf->timeout); + ngx_add_timer(ctx->peer.connection->write, ahcf->timeout); + + if (rc == NGX_OK) { + ngx_mail_auth_http_write_handler(ctx->peer.connection->write); + return; + } +} + + +static void +ngx_mail_auth_http_write_handler(ngx_event_t *wev) +{ + ssize_t n, size; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_auth_http_ctx_t *ctx; + ngx_mail_auth_http_conf_t *ahcf; + + c = wev->data; + s = c->data; + + ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module); + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, + "mail auth http write handler"); + + if (wev->timedout) { + ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, + "auth http server %V timed out", ctx->peer.name); + ngx_close_connection(c); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + size = ctx->request->last - ctx->request->pos; + + n = ngx_send(c, ctx->request->pos, size); + + if (n == NGX_ERROR) { + ngx_close_connection(c); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + if (n > 0) { + ctx->request->pos += n; + + if (n == size) { + wev->handler = ngx_mail_auth_http_dummy_handler; + + if (wev->timer_set) { + ngx_del_timer(wev); + } + + if (ngx_handle_write_event(wev, 0) != NGX_OK) { + ngx_close_connection(c); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + } + + return; + } + } + + if (!wev->timer_set) { + ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module); + ngx_add_timer(wev, ahcf->timeout); + } +} + + +static void +ngx_mail_auth_http_read_handler(ngx_event_t *rev) +{ + ssize_t n, size; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_auth_http_ctx_t *ctx; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail auth http read handler"); + + ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, + "auth http server %V timed out", ctx->peer.name); + ngx_close_connection(c); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + if (ctx->response == NULL) { + ctx->response = ngx_create_temp_buf(ctx->pool, 1024); + if (ctx->response == NULL) { + ngx_close_connection(c); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + } + + size = ctx->response->end - ctx->response->last; + + n = ngx_recv(c, ctx->response->pos, size); + + if (n > 0) { + ctx->response->last += n; + + ctx->handler(s, ctx); + return; + } + + if (n == NGX_AGAIN) { + return; + } + + ngx_close_connection(c); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); +} + + +static void +ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx) +{ + u_char *p, ch; + enum { + sw_start = 0, + sw_H, + sw_HT, + sw_HTT, + sw_HTTP, + sw_skip, + sw_almost_done + } state; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail auth http process status line"); + + state = ctx->state; + + for (p = ctx->response->pos; p < ctx->response->last; p++) { + ch = *p; + + switch (state) { + + /* "HTTP/" */ + case sw_start: + if (ch == 'H') { + state = sw_H; + break; + } + goto next; + + case sw_H: + if (ch == 'T') { + state = sw_HT; + break; + } + goto next; + + case sw_HT: + if (ch == 'T') { + state = sw_HTT; + break; + } + goto next; + + case sw_HTT: + if (ch == 'P') { + state = sw_HTTP; + break; + } + goto next; + + case sw_HTTP: + if (ch == '/') { + state = sw_skip; + break; + } + goto next; + + /* any text until end of line */ + case sw_skip: + switch (ch) { + case CR: + state = sw_almost_done; + + break; + case LF: + goto done; + } + break; + + /* end of status line */ + case sw_almost_done: + if (ch == LF) { + goto done; + } + + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "auth http server &V sent invalid response", + ctx->peer.name); + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + } + + ctx->response->pos = p; + ctx->state = state; + + return; + +next: + + p = ctx->response->start - 1; + +done: + + ctx->response->pos = p + 1; + ctx->state = 0; + ctx->handler = ngx_mail_auth_http_process_headers; + ctx->handler(s, ctx); +} + + +static void +ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx) +{ + u_char *p; + time_t timer; + size_t len, size; + ngx_int_t rc, port, n; + ngx_addr_t *peer; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail auth http process headers"); + + for ( ;; ) { + rc = ngx_mail_auth_http_parse_header_line(s, ctx); + + if (rc == NGX_OK) { + +#if (NGX_DEBUG) + { + ngx_str_t key, value; + + key.len = ctx->header_name_end - ctx->header_name_start; + key.data = ctx->header_name_start; + value.len = ctx->header_end - ctx->header_start; + value.data = ctx->header_start; + + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail auth http header: \"%V: %V\"", + &key, &value); + } +#endif + + len = ctx->header_name_end - ctx->header_name_start; + + if (len == sizeof("Auth-Status") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Status", + sizeof("Auth-Status") - 1) + == 0) + { + len = ctx->header_end - ctx->header_start; + + if (len == 2 + && ctx->header_start[0] == 'O' + && ctx->header_start[1] == 'K') + { + continue; + } + + if (len == 4 + && ctx->header_start[0] == 'W' + && ctx->header_start[1] == 'A' + && ctx->header_start[2] == 'I' + && ctx->header_start[3] == 'T') + { + s->auth_wait = 1; + continue; + } + + ctx->errmsg.len = len; + ctx->errmsg.data = ctx->header_start; + + switch (s->protocol) { + + case NGX_MAIL_POP3_PROTOCOL: + size = sizeof("-ERR ") - 1 + len + sizeof(CRLF) - 1; + break; + + case NGX_MAIL_IMAP_PROTOCOL: + size = s->tag.len + sizeof("NO ") - 1 + len + + sizeof(CRLF) - 1; + break; + + default: /* NGX_MAIL_SMTP_PROTOCOL */ + ctx->err = ctx->errmsg; + continue; + } + + p = ngx_pnalloc(s->connection->pool, size); + if (p == NULL) { + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ctx->err.data = p; + + switch (s->protocol) { + + case NGX_MAIL_POP3_PROTOCOL: + *p++ = '-'; *p++ = 'E'; *p++ = 'R'; *p++ = 'R'; *p++ = ' '; + break; + + case NGX_MAIL_IMAP_PROTOCOL: + p = ngx_cpymem(p, s->tag.data, s->tag.len); + *p++ = 'N'; *p++ = 'O'; *p++ = ' '; + break; + + default: /* NGX_MAIL_SMTP_PROTOCOL */ + break; + } + + p = ngx_cpymem(p, ctx->header_start, len); + *p++ = CR; *p++ = LF; + + ctx->err.len = p - ctx->err.data; + + continue; + } + + if (len == sizeof("Auth-Server") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Server", + sizeof("Auth-Server") - 1) + == 0) + { + ctx->addr.len = ctx->header_end - ctx->header_start; + ctx->addr.data = ctx->header_start; + + continue; + } + + if (len == sizeof("Auth-Port") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Port", + sizeof("Auth-Port") - 1) + == 0) + { + ctx->port.len = ctx->header_end - ctx->header_start; + ctx->port.data = ctx->header_start; + + continue; + } + + if (len == sizeof("Auth-User") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-User", + sizeof("Auth-User") - 1) + == 0) + { + s->login.len = ctx->header_end - ctx->header_start; + + s->login.data = ngx_pnalloc(s->connection->pool, s->login.len); + if (s->login.data == NULL) { + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ngx_memcpy(s->login.data, ctx->header_start, s->login.len); + + continue; + } + + if (len == sizeof("Auth-Pass") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Pass", + sizeof("Auth-Pass") - 1) + == 0) + { + s->passwd.len = ctx->header_end - ctx->header_start; + + s->passwd.data = ngx_pnalloc(s->connection->pool, + s->passwd.len); + if (s->passwd.data == NULL) { + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ngx_memcpy(s->passwd.data, ctx->header_start, s->passwd.len); + + continue; + } + + if (len == sizeof("Auth-Wait") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Wait", + sizeof("Auth-Wait") - 1) + == 0) + { + n = ngx_atoi(ctx->header_start, + ctx->header_end - ctx->header_start); + + if (n != NGX_ERROR) { + ctx->sleep = n; + } + + continue; + } + + if (len == sizeof("Auth-Error-Code") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Error-Code", + sizeof("Auth-Error-Code") - 1) + == 0) + { + ctx->errcode.len = ctx->header_end - ctx->header_start; + + ctx->errcode.data = ngx_pnalloc(s->connection->pool, + ctx->errcode.len); + if (ctx->errcode.data == NULL) { + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ngx_memcpy(ctx->errcode.data, ctx->header_start, + ctx->errcode.len); + + continue; + } + + /* ignore other headers */ + + continue; + } + + if (rc == NGX_DONE) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail auth http header done"); + + ngx_close_connection(ctx->peer.connection); + + if (ctx->err.len) { + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client login failed: \"%V\"", &ctx->errmsg); + + if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { + + if (ctx->errcode.len == 0) { + ctx->errcode = ngx_mail_smtp_errcode; + } + + ctx->err.len = ctx->errcode.len + ctx->errmsg.len + + sizeof(" " CRLF) - 1; + + p = ngx_pnalloc(s->connection->pool, ctx->err.len); + if (p == NULL) { + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + ctx->err.data = p; + + p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len); + *p++ = ' '; + p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len); + *p++ = CR; *p = LF; + } + + s->out = ctx->err; + timer = ctx->sleep; + + ngx_destroy_pool(ctx->pool); + + if (timer == 0) { + s->quit = 1; + ngx_mail_send(s->connection->write); + return; + } + + ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000)); + + s->connection->read->handler = ngx_mail_auth_sleep_handler; + + return; + } + + if (s->auth_wait) { + timer = ctx->sleep; + + ngx_destroy_pool(ctx->pool); + + if (timer == 0) { + ngx_mail_auth_http_init(s); + return; + } + + ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000)); + + s->connection->read->handler = ngx_mail_auth_sleep_handler; + + return; + } + + if (ctx->addr.len == 0 || ctx->port.len == 0) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "auth http server %V did not send server or port", + ctx->peer.name); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + if (s->passwd.data == NULL + && s->protocol != NGX_MAIL_SMTP_PROTOCOL) + { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "auth http server %V did not send password", + ctx->peer.name); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t)); + if (peer == NULL) { + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + rc = ngx_parse_addr(s->connection->pool, peer, + ctx->addr.data, ctx->addr.len); + + switch (rc) { + case NGX_OK: + break; + + case NGX_DECLINED: + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "auth http server %V sent invalid server " + "address:\"%V\"", + ctx->peer.name, &ctx->addr); + /* fall through */ + + default: + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + port = ngx_atoi(ctx->port.data, ctx->port.len); + if (port == NGX_ERROR || port < 1 || port > 65535) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "auth http server %V sent invalid server " + "port:\"%V\"", + ctx->peer.name, &ctx->port); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + switch (peer->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) peer->sockaddr; + sin6->sin6_port = htons((in_port_t) port); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) peer->sockaddr; + sin->sin_port = htons((in_port_t) port); + break; + } + + len = ctx->addr.len + 1 + ctx->port.len; + + peer->name.len = len; + + peer->name.data = ngx_pnalloc(s->connection->pool, len); + if (peer->name.data == NULL) { + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } + + len = ctx->addr.len; + + ngx_memcpy(peer->name.data, ctx->addr.data, len); + + peer->name.data[len++] = ':'; + + ngx_memcpy(peer->name.data + len, ctx->port.data, ctx->port.len); + + ngx_destroy_pool(ctx->pool); + ngx_mail_proxy_init(s, peer); + + return; + } + + if (rc == NGX_AGAIN ) { + return; + } + + /* rc == NGX_ERROR */ + + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "auth http server %V sent invalid header in response", + ctx->peer.name); + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + + return; + } +} + + +static void +ngx_mail_auth_sleep_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail auth sleep handler"); + + c = rev->data; + s = c->data; + + if (rev->timedout) { + + rev->timedout = 0; + + if (s->auth_wait) { + s->auth_wait = 0; + ngx_mail_auth_http_init(s); + return; + } + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + rev->handler = cscf->protocol->auth_state; + + s->mail_state = 0; + s->auth_method = NGX_MAIL_AUTH_PLAIN; + + c->log->action = "in auth state"; + + ngx_mail_send(c->write); + + if (c->destroyed) { + return; + } + + ngx_add_timer(rev, cscf->timeout); + + if (rev->ready) { + rev->handler(rev); + return; + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + return; + } + + if (rev->active) { + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + } +} + + +static ngx_int_t +ngx_mail_auth_http_parse_header_line(ngx_mail_session_t *s, + ngx_mail_auth_http_ctx_t *ctx) +{ + u_char c, ch, *p; + enum { + sw_start = 0, + sw_name, + sw_space_before_value, + sw_value, + sw_space_after_value, + sw_almost_done, + sw_header_almost_done + } state; + + state = ctx->state; + + for (p = ctx->response->pos; p < ctx->response->last; p++) { + ch = *p; + + switch (state) { + + /* first char */ + case sw_start: + + switch (ch) { + case CR: + ctx->header_end = p; + state = sw_header_almost_done; + break; + case LF: + ctx->header_end = p; + goto header_done; + default: + state = sw_name; + ctx->header_name_start = p; + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'z') { + break; + } + + if (ch >= '0' && ch <= '9') { + break; + } + + return NGX_ERROR; + } + break; + + /* header name */ + case sw_name: + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'z') { + break; + } + + if (ch == ':') { + ctx->header_name_end = p; + state = sw_space_before_value; + break; + } + + if (ch == '-') { + break; + } + + if (ch >= '0' && ch <= '9') { + break; + } + + if (ch == CR) { + ctx->header_name_end = p; + ctx->header_start = p; + ctx->header_end = p; + state = sw_almost_done; + break; + } + + if (ch == LF) { + ctx->header_name_end = p; + ctx->header_start = p; + ctx->header_end = p; + goto done; + } + + return NGX_ERROR; + + /* space* before header value */ + case sw_space_before_value: + switch (ch) { + case ' ': + break; + case CR: + ctx->header_start = p; + ctx->header_end = p; + state = sw_almost_done; + break; + case LF: + ctx->header_start = p; + ctx->header_end = p; + goto done; + default: + ctx->header_start = p; + state = sw_value; + break; + } + break; + + /* header value */ + case sw_value: + switch (ch) { + case ' ': + ctx->header_end = p; + state = sw_space_after_value; + break; + case CR: + ctx->header_end = p; + state = sw_almost_done; + break; + case LF: + ctx->header_end = p; + goto done; + } + break; + + /* space* before end of header line */ + case sw_space_after_value: + switch (ch) { + case ' ': + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + default: + state = sw_value; + break; + } + break; + + /* end of header line */ + case sw_almost_done: + switch (ch) { + case LF: + goto done; + default: + return NGX_ERROR; + } + + /* end of header */ + case sw_header_almost_done: + switch (ch) { + case LF: + goto header_done; + default: + return NGX_ERROR; + } + } + } + + ctx->response->pos = p; + ctx->state = state; + + return NGX_AGAIN; + +done: + + ctx->response->pos = p + 1; + ctx->state = sw_start; + + return NGX_OK; + +header_done: + + ctx->response->pos = p + 1; + ctx->state = sw_start; + + return NGX_DONE; +} + + +static void +ngx_mail_auth_http_block_read(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_auth_http_ctx_t *ctx; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail auth http block read"); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + c = rev->data; + s = c->data; + + ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module); + + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + } +} + + +static void +ngx_mail_auth_http_dummy_handler(ngx_event_t *ev) +{ + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, ev->log, 0, + "mail auth http dummy handler"); +} + + +static ngx_buf_t * +ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, + ngx_mail_auth_http_conf_t *ahcf) +{ + size_t len; + ngx_buf_t *b; + ngx_str_t login, passwd; +#if (NGX_MAIL_SSL) + ngx_str_t verify, subject, issuer, serial, fingerprint, + raw_cert, cert; + ngx_connection_t *c; + ngx_mail_ssl_conf_t *sslcf; +#endif + ngx_mail_core_srv_conf_t *cscf; + + if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { + return NULL; + } + + if (ngx_mail_auth_http_escape(pool, &s->passwd, &passwd) != NGX_OK) { + return NULL; + } + +#if (NGX_MAIL_SSL) + + c = s->connection; + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (c->ssl && sslcf->verify) { + + /* certificate details */ + + if (ngx_ssl_get_client_verify(c, pool, &verify) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_subject_dn(c, pool, &subject) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_issuer_dn(c, pool, &issuer) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_serial_number(c, pool, &serial) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_fingerprint(c, pool, &fingerprint) != NGX_OK) { + return NULL; + } + + if (ahcf->pass_client_cert) { + + /* certificate itself, if configured */ + + if (ngx_ssl_get_raw_certificate(c, pool, &raw_cert) != NGX_OK) { + return NULL; + } + + if (ngx_mail_auth_http_escape(pool, &raw_cert, &cert) != NGX_OK) { + return NULL; + } + + } else { + ngx_str_null(&cert); + } + + } else { + ngx_str_null(&verify); + ngx_str_null(&subject); + ngx_str_null(&issuer); + ngx_str_null(&serial); + ngx_str_null(&fingerprint); + ngx_str_null(&cert); + } + +#endif + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 + + sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 + + sizeof("Auth-Method: ") - 1 + + ngx_mail_auth_http_method[s->auth_method].len + + sizeof(CRLF) - 1 + + sizeof("Auth-User: ") - 1 + login.len + sizeof(CRLF) - 1 + + sizeof("Auth-Pass: ") - 1 + passwd.len + sizeof(CRLF) - 1 + + sizeof("Auth-Salt: ") - 1 + s->salt.len + + sizeof("Auth-Protocol: ") - 1 + cscf->protocol->name.len + + sizeof(CRLF) - 1 + + sizeof("Auth-Login-Attempt: ") - 1 + NGX_INT_T_LEN + + sizeof(CRLF) - 1 + + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len + + sizeof(CRLF) - 1 + + sizeof("Client-Host: ") - 1 + s->host.len + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + sizeof(CRLF) - 1 +#if (NGX_MAIL_SSL) + + sizeof("Auth-SSL: on" CRLF) - 1 + + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Subject: ") - 1 + subject.len + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Serial: ") - 1 + serial.len + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Cert: ") - 1 + cert.len + sizeof(CRLF) - 1 +#endif + + ahcf->header.len + + sizeof(CRLF) - 1; + + b = ngx_create_temp_buf(pool, len); + if (b == NULL) { + return NULL; + } + + b->last = ngx_cpymem(b->last, "GET ", sizeof("GET ") - 1); + b->last = ngx_copy(b->last, ahcf->uri.data, ahcf->uri.len); + b->last = ngx_cpymem(b->last, " HTTP/1.0" CRLF, + sizeof(" HTTP/1.0" CRLF) - 1); + + b->last = ngx_cpymem(b->last, "Host: ", sizeof("Host: ") - 1); + b->last = ngx_copy(b->last, ahcf->host_header.data, + ahcf->host_header.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-Method: ", + sizeof("Auth-Method: ") - 1); + b->last = ngx_cpymem(b->last, + ngx_mail_auth_http_method[s->auth_method].data, + ngx_mail_auth_http_method[s->auth_method].len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-User: ", sizeof("Auth-User: ") - 1); + b->last = ngx_copy(b->last, login.data, login.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-Pass: ", sizeof("Auth-Pass: ") - 1); + b->last = ngx_copy(b->last, passwd.data, passwd.len); + *b->last++ = CR; *b->last++ = LF; + + if (s->auth_method != NGX_MAIL_AUTH_PLAIN && s->salt.len) { + b->last = ngx_cpymem(b->last, "Auth-Salt: ", sizeof("Auth-Salt: ") - 1); + b->last = ngx_copy(b->last, s->salt.data, s->salt.len); + + s->passwd.data = NULL; + } + + b->last = ngx_cpymem(b->last, "Auth-Protocol: ", + sizeof("Auth-Protocol: ") - 1); + b->last = ngx_cpymem(b->last, cscf->protocol->name.data, + cscf->protocol->name.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_sprintf(b->last, "Auth-Login-Attempt: %ui" CRLF, + s->login_attempt); + + b->last = ngx_cpymem(b->last, "Client-IP: ", sizeof("Client-IP: ") - 1); + b->last = ngx_copy(b->last, s->connection->addr_text.data, + s->connection->addr_text.len); + *b->last++ = CR; *b->last++ = LF; + + if (s->host.len) { + b->last = ngx_cpymem(b->last, "Client-Host: ", + sizeof("Client-Host: ") - 1); + b->last = ngx_copy(b->last, s->host.data, s->host.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + + /* HELO, MAIL FROM, and RCPT TO can't contain CRLF, no need to escape */ + + b->last = ngx_cpymem(b->last, "Auth-SMTP-Helo: ", + sizeof("Auth-SMTP-Helo: ") - 1); + b->last = ngx_copy(b->last, s->smtp_helo.data, s->smtp_helo.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-SMTP-From: ", + sizeof("Auth-SMTP-From: ") - 1); + b->last = ngx_copy(b->last, s->smtp_from.data, s->smtp_from.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-SMTP-To: ", + sizeof("Auth-SMTP-To: ") - 1); + b->last = ngx_copy(b->last, s->smtp_to.data, s->smtp_to.len); + *b->last++ = CR; *b->last++ = LF; + + } + +#if (NGX_MAIL_SSL) + + if (c->ssl) { + b->last = ngx_cpymem(b->last, "Auth-SSL: on" CRLF, + sizeof("Auth-SSL: on" CRLF) - 1); + + if (verify.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Verify: ", + sizeof("Auth-SSL-Verify: ") - 1); + b->last = ngx_copy(b->last, verify.data, verify.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (subject.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Subject: ", + sizeof("Auth-SSL-Subject: ") - 1); + b->last = ngx_copy(b->last, subject.data, subject.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (issuer.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Issuer: ", + sizeof("Auth-SSL-Issuer: ") - 1); + b->last = ngx_copy(b->last, issuer.data, issuer.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (serial.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Serial: ", + sizeof("Auth-SSL-Serial: ") - 1); + b->last = ngx_copy(b->last, serial.data, serial.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (fingerprint.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Fingerprint: ", + sizeof("Auth-SSL-Fingerprint: ") - 1); + b->last = ngx_copy(b->last, fingerprint.data, fingerprint.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (cert.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Cert: ", + sizeof("Auth-SSL-Cert: ") - 1); + b->last = ngx_copy(b->last, cert.data, cert.len); + *b->last++ = CR; *b->last++ = LF; + } + } + +#endif + + if (ahcf->header.len) { + b->last = ngx_copy(b->last, ahcf->header.data, ahcf->header.len); + } + + /* add "\r\n" at the header end */ + *b->last++ = CR; *b->last++ = LF; + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail auth http header:%N\"%*s\"", + (size_t) (b->last - b->pos), b->pos); +#endif + + return b; +} + + +static ngx_int_t +ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, ngx_str_t *escaped) +{ + u_char *p; + uintptr_t n; + + n = ngx_escape_uri(NULL, text->data, text->len, NGX_ESCAPE_MAIL_AUTH); + + if (n == 0) { + *escaped = *text; + return NGX_OK; + } + + escaped->len = text->len + n * 2; + + p = ngx_pnalloc(pool, escaped->len); + if (p == NULL) { + return NGX_ERROR; + } + + (void) ngx_escape_uri(p, text->data, text->len, NGX_ESCAPE_MAIL_AUTH); + + escaped->data = p; + + return NGX_OK; +} + + +static void * +ngx_mail_auth_http_create_conf(ngx_conf_t *cf) +{ + ngx_mail_auth_http_conf_t *ahcf; + + ahcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_auth_http_conf_t)); + if (ahcf == NULL) { + return NULL; + } + + ahcf->timeout = NGX_CONF_UNSET_MSEC; + ahcf->pass_client_cert = NGX_CONF_UNSET; + + ahcf->file = cf->conf_file->file.name.data; + ahcf->line = cf->conf_file->line; + + return ahcf; +} + + +static char * +ngx_mail_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_auth_http_conf_t *prev = parent; + ngx_mail_auth_http_conf_t *conf = child; + + u_char *p; + size_t len; + ngx_uint_t i; + ngx_table_elt_t *header; + + if (conf->peer == NULL) { + conf->peer = prev->peer; + conf->host_header = prev->host_header; + conf->uri = prev->uri; + + if (conf->peer == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"auth_http\" is defined for server in %s:%ui", + conf->file, conf->line); + + return NGX_CONF_ERROR; + } + } + + ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); + + ngx_conf_merge_value(conf->pass_client_cert, prev->pass_client_cert, 0); + + if (conf->headers == NULL) { + conf->headers = prev->headers; + conf->header = prev->header; + } + + if (conf->headers && conf->header.len == 0) { + len = 0; + header = conf->headers->elts; + for (i = 0; i < conf->headers->nelts; i++) { + len += header[i].key.len + 2 + header[i].value.len + 2; + } + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->header.len = len; + conf->header.data = p; + + for (i = 0; i < conf->headers->nelts; i++) { + p = ngx_cpymem(p, header[i].key.data, header[i].key.len); + *p++ = ':'; *p++ = ' '; + p = ngx_cpymem(p, header[i].value.data, header[i].value.len); + *p++ = CR; *p++ = LF; + } + } + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_auth_http_conf_t *ahcf = conf; + + ngx_str_t *value; + ngx_url_t u; + + value = cf->args->elts; + + ngx_memzero(&u, sizeof(ngx_url_t)); + + u.url = value[1]; + u.default_port = 80; + u.uri_part = 1; + + if (ngx_strncmp(u.url.data, "http://", 7) == 0) { + u.url.len -= 7; + u.url.data += 7; + } + + if (ngx_parse_url(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in auth_http \"%V\"", u.err, &u.url); + } + + return NGX_CONF_ERROR; + } + + ahcf->peer = u.addrs; + + if (u.family != AF_UNIX) { + ahcf->host_header = u.host; + + } else { + ngx_str_set(&ahcf->host_header, "localhost"); + } + + ahcf->uri = u.uri; + + if (ahcf->uri.len == 0) { + ngx_str_set(&ahcf->uri, "/"); + } + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_auth_http_header(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_auth_http_conf_t *ahcf = conf; + + ngx_str_t *value; + ngx_table_elt_t *header; + + if (ahcf->headers == NULL) { + ahcf->headers = ngx_array_create(cf->pool, 1, sizeof(ngx_table_elt_t)); + if (ahcf->headers == NULL) { + return NGX_CONF_ERROR; + } + } + + header = ngx_array_push(ahcf->headers); + if (header == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + header->key = value[1]; + header->value = value[2]; + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail_core_module.c b/hm_nginx/src/mail/ngx_mail_core_module.c new file mode 100644 index 0000000..05a47f5 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_core_module.c @@ -0,0 +1,653 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static void *ngx_mail_core_create_main_conf(ngx_conf_t *cf); +static void *ngx_mail_core_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); +static char *ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_conf_deprecated_t ngx_conf_deprecated_so_keepalive = { + ngx_conf_deprecated, "so_keepalive", + "so_keepalive\" parameter of the \"listen" +}; + + +static ngx_command_t ngx_mail_core_commands[] = { + + { ngx_string("server"), + NGX_MAIL_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_mail_core_server, + 0, + 0, + NULL }, + + { ngx_string("listen"), + NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_core_listen, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("protocol"), + NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_mail_core_protocol, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("so_keepalive"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_core_srv_conf_t, so_keepalive), + &ngx_conf_deprecated_so_keepalive }, + + { ngx_string("timeout"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_core_srv_conf_t, timeout), + NULL }, + + { ngx_string("server_name"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_core_srv_conf_t, server_name), + NULL }, + + { ngx_string("resolver"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_core_resolver, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("resolver_timeout"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_core_srv_conf_t, resolver_timeout), + NULL }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_core_module_ctx = { + NULL, /* protocol */ + + ngx_mail_core_create_main_conf, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_core_create_srv_conf, /* create server configuration */ + ngx_mail_core_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_core_module = { + NGX_MODULE_V1, + &ngx_mail_core_module_ctx, /* module context */ + ngx_mail_core_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_core_create_main_conf(ngx_conf_t *cf) +{ + ngx_mail_core_main_conf_t *cmcf; + + cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_main_conf_t)); + if (cmcf == NULL) { + return NULL; + } + + if (ngx_array_init(&cmcf->servers, cf->pool, 4, + sizeof(ngx_mail_core_srv_conf_t *)) + != NGX_OK) + { + return NULL; + } + + if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_mail_listen_t)) + != NGX_OK) + { + return NULL; + } + + return cmcf; +} + + +static void * +ngx_mail_core_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_core_srv_conf_t *cscf; + + cscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_srv_conf_t)); + if (cscf == NULL) { + return NULL; + } + + /* + * set by ngx_pcalloc(): + * + * cscf->protocol = NULL; + */ + + cscf->timeout = NGX_CONF_UNSET_MSEC; + cscf->resolver_timeout = NGX_CONF_UNSET_MSEC; + cscf->so_keepalive = NGX_CONF_UNSET; + + cscf->resolver = NGX_CONF_UNSET_PTR; + + cscf->file_name = cf->conf_file->file.name.data; + cscf->line = cf->conf_file->line; + + return cscf; +} + + +static char * +ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_core_srv_conf_t *prev = parent; + ngx_mail_core_srv_conf_t *conf = child; + + ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); + ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout, + 30000); + + ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0); + + + ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); + + if (conf->server_name.len == 0) { + conf->server_name = cf->cycle->hostname; + } + + if (conf->protocol == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown mail protocol for server in %s:%ui", + conf->file_name, conf->line); + return NGX_CONF_ERROR; + } + + ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL); + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *rv; + void *mconf; + ngx_uint_t m; + ngx_conf_t pcf; + ngx_mail_module_t *module; + ngx_mail_conf_ctx_t *ctx, *mail_ctx; + ngx_mail_core_srv_conf_t *cscf, **cscfp; + ngx_mail_core_main_conf_t *cmcf; + + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); + if (ctx == NULL) { + return NGX_CONF_ERROR; + } + + mail_ctx = cf->ctx; + ctx->main_conf = mail_ctx->main_conf; + + /* the server{}'s srv_conf */ + + ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module); + if (ctx->srv_conf == NULL) { + return NGX_CONF_ERROR; + } + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->create_srv_conf) { + mconf = module->create_srv_conf(cf); + if (mconf == NULL) { + return NGX_CONF_ERROR; + } + + ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; + } + } + + /* the server configuration context */ + + cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index]; + cscf->ctx = ctx; + + cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; + + cscfp = ngx_array_push(&cmcf->servers); + if (cscfp == NULL) { + return NGX_CONF_ERROR; + } + + *cscfp = cscf; + + + /* parse inside server{} */ + + pcf = *cf; + cf->ctx = ctx; + cf->cmd_type = NGX_MAIL_SRV_CONF; + + rv = ngx_conf_parse(cf, NULL); + + *cf = pcf; + + return rv; +} + + +static char * +ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_core_srv_conf_t *cscf = conf; + + size_t len, off; + in_port_t port; + ngx_str_t *value; + ngx_url_t u; + ngx_uint_t i, m; + struct sockaddr *sa; + ngx_mail_listen_t *ls; + ngx_mail_module_t *module; + struct sockaddr_in *sin; + ngx_mail_core_main_conf_t *cmcf; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + value = cf->args->elts; + + ngx_memzero(&u, sizeof(ngx_url_t)); + + u.url = value[1]; + u.listen = 1; + + if (ngx_parse_url(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in \"%V\" of the \"listen\" directive", + u.err, &u.url); + } + + return NGX_CONF_ERROR; + } + + cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); + + ls = cmcf->listen.elts; + + for (i = 0; i < cmcf->listen.nelts; i++) { + + sa = (struct sockaddr *) ls[i].sockaddr; + + if (sa->sa_family != u.family) { + continue; + } + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + off = offsetof(struct sockaddr_in6, sin6_addr); + len = 16; + sin6 = (struct sockaddr_in6 *) sa; + port = ntohs(sin6->sin6_port); + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + off = offsetof(struct sockaddr_un, sun_path); + len = sizeof(((struct sockaddr_un *) sa)->sun_path); + port = 0; + break; +#endif + + default: /* AF_INET */ + off = offsetof(struct sockaddr_in, sin_addr); + len = 4; + sin = (struct sockaddr_in *) sa; + port = ntohs(sin->sin_port); + break; + } + + if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { + continue; + } + + if (port != u.port) { + continue; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate \"%V\" address and port pair", &u.url); + return NGX_CONF_ERROR; + } + + ls = ngx_array_push(&cmcf->listen); + if (ls == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(ls, sizeof(ngx_mail_listen_t)); + + ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); + + ls->socklen = u.socklen; + ls->wildcard = u.wildcard; + ls->ctx = cf->ctx; + +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + ls->ipv6only = 1; +#endif + + if (cscf->protocol == NULL) { + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->protocol == NULL) { + continue; + } + + for (i = 0; module->protocol->port[i]; i++) { + if (module->protocol->port[i] == u.port) { + cscf->protocol = module->protocol; + break; + } + } + } + } + + for (i = 2; i < cf->args->nelts; i++) { + + if (ngx_strcmp(value[i].data, "bind") == 0) { + ls->bind = 1; + continue; + } + + if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + struct sockaddr *sa; + u_char buf[NGX_SOCKADDR_STRLEN]; + + sa = (struct sockaddr *) ls->sockaddr; + + if (sa->sa_family == AF_INET6) { + + if (ngx_strcmp(&value[i].data[10], "n") == 0) { + ls->ipv6only = 1; + + } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { + ls->ipv6only = 0; + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid ipv6only flags \"%s\"", + &value[i].data[9]); + return NGX_CONF_ERROR; + } + + ls->bind = 1; + + } else { + len = ngx_sock_ntop(sa, ls->socklen, buf, + NGX_SOCKADDR_STRLEN, 1); + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "ipv6only is not supported " + "on addr \"%*s\", ignored", len, buf); + } + + continue; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "bind ipv6only is not supported " + "on this platform"); + return NGX_CONF_ERROR; +#endif + } + + if (ngx_strcmp(value[i].data, "ssl") == 0) { +#if (NGX_MAIL_SSL) + ls->ssl = 1; + continue; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the \"ssl\" parameter requires " + "ngx_mail_ssl_module"); + return NGX_CONF_ERROR; +#endif + } + + if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { + + if (ngx_strcmp(&value[i].data[13], "on") == 0) { + ls->so_keepalive = 1; + + } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { + ls->so_keepalive = 2; + + } else { + +#if (NGX_HAVE_KEEPALIVE_TUNABLE) + u_char *p, *end; + ngx_str_t s; + + end = value[i].data + value[i].len; + s.data = value[i].data + 13; + + p = ngx_strlchr(s.data, end, ':'); + if (p == NULL) { + p = end; + } + + if (p > s.data) { + s.len = p - s.data; + + ls->tcp_keepidle = ngx_parse_time(&s, 1); + if (ls->tcp_keepidle == (time_t) NGX_ERROR) { + goto invalid_so_keepalive; + } + } + + s.data = (p < end) ? (p + 1) : end; + + p = ngx_strlchr(s.data, end, ':'); + if (p == NULL) { + p = end; + } + + if (p > s.data) { + s.len = p - s.data; + + ls->tcp_keepintvl = ngx_parse_time(&s, 1); + if (ls->tcp_keepintvl == (time_t) NGX_ERROR) { + goto invalid_so_keepalive; + } + } + + s.data = (p < end) ? (p + 1) : end; + + if (s.data < end) { + s.len = end - s.data; + + ls->tcp_keepcnt = ngx_atoi(s.data, s.len); + if (ls->tcp_keepcnt == NGX_ERROR) { + goto invalid_so_keepalive; + } + } + + if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0 + && ls->tcp_keepcnt == 0) + { + goto invalid_so_keepalive; + } + + ls->so_keepalive = 1; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the \"so_keepalive\" parameter accepts " + "only \"on\" or \"off\" on this platform"); + return NGX_CONF_ERROR; + +#endif + } + + ls->bind = 1; + + continue; + +#if (NGX_HAVE_KEEPALIVE_TUNABLE) + invalid_so_keepalive: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid so_keepalive value: \"%s\"", + &value[i].data[13]); + return NGX_CONF_ERROR; +#endif + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the invalid \"%V\" parameter", &value[i]); + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_core_srv_conf_t *cscf = conf; + + ngx_str_t *value; + ngx_uint_t m; + ngx_mail_module_t *module; + + value = cf->args->elts; + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->protocol + && ngx_strcmp(module->protocol->name.data, value[1].data) == 0) + { + cscf->protocol = module->protocol; + + return NGX_CONF_OK; + } + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown protocol \"%V\"", &value[1]); + return NGX_CONF_ERROR; +} + + +static char * +ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_core_srv_conf_t *cscf = conf; + + ngx_str_t *value; + + value = cf->args->elts; + + if (cscf->resolver != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + if (ngx_strcmp(value[1].data, "off") == 0) { + cscf->resolver = NULL; + return NGX_CONF_OK; + } + + cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1); + if (cscf->resolver == NULL) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +char * +ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_str_t *c, *value; + ngx_uint_t i; + ngx_array_t *a; + + a = (ngx_array_t *) (p + cmd->offset); + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + c = ngx_array_push(a); + if (c == NULL) { + return NGX_CONF_ERROR; + } + + *c = value[i]; + } + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail_handler.c b/hm_nginx/src/mail/ngx_mail_handler.c new file mode 100644 index 0000000..870b5ee --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_handler.c @@ -0,0 +1,861 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static void ngx_mail_init_session(ngx_connection_t *c); + +#if (NGX_MAIL_SSL) +static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); +static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c); +static ngx_int_t ngx_mail_verify_cert(ngx_mail_session_t *s, + ngx_connection_t *c); +#endif + + +void +ngx_mail_init_connection(ngx_connection_t *c) +{ + size_t len; + ngx_uint_t i; + ngx_mail_port_t *port; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_mail_log_ctx_t *ctx; + ngx_mail_in_addr_t *addr; + ngx_mail_session_t *s; + ngx_mail_addr_conf_t *addr_conf; + u_char text[NGX_SOCKADDR_STRLEN]; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; + ngx_mail_in6_addr_t *addr6; +#endif + + + /* find the server configuration for the address:port */ + + port = c->listening->servers; + + if (port->naddrs > 1) { + + /* + * There are several addresses on this port and one of them + * is the "*:port" wildcard so getsockname() is needed to determine + * the server address. + * + * AcceptEx() already gave this address. + */ + + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + + sa = c->local_sockaddr; + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + + addr6 = port->addrs; + + /* the last address is "*" */ + + for (i = 0; i < port->naddrs - 1; i++) { + if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { + break; + } + } + + addr_conf = &addr6[i].conf; + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + + addr = port->addrs; + + /* the last address is "*" */ + + for (i = 0; i < port->naddrs - 1; i++) { + if (addr[i].addr == sin->sin_addr.s_addr) { + break; + } + } + + addr_conf = &addr[i].conf; + + break; + } + + } else { + switch (c->local_sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + addr6 = port->addrs; + addr_conf = &addr6[0].conf; + break; +#endif + + default: /* AF_INET */ + addr = port->addrs; + addr_conf = &addr[0].conf; + break; + } + } + + s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); + if (s == NULL) { + ngx_mail_close_connection(c); + return; + } + + s->signature = NGX_MAIL_MODULE; + + s->main_conf = addr_conf->ctx->main_conf; + s->srv_conf = addr_conf->ctx->srv_conf; + + s->addr_text = &addr_conf->addr_text; + + c->data = s; + s->connection = c; + + len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); + + ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", + c->number, len, text, s->addr_text); + + ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); + if (ctx == NULL) { + ngx_mail_close_connection(c); + return; + } + + ctx->client = &c->addr_text; + ctx->session = s; + + c->log->connection = c->number; + c->log->handler = ngx_mail_log_error; + c->log->data = ctx; + c->log->action = "sending client greeting line"; + + c->log_error = NGX_ERROR_INFO; + +#if (NGX_MAIL_SSL) + { + ngx_mail_ssl_conf_t *sslcf; + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->enable) { + c->log->action = "SSL handshaking"; + + ngx_mail_ssl_init_connection(&sslcf->ssl, c); + return; + } + + if (addr_conf->ssl) { + + c->log->action = "SSL handshaking"; + + if (sslcf->ssl.ctx == NULL) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "no \"ssl_certificate\" is defined " + "in server listening on SSL port"); + ngx_mail_close_connection(c); + return; + } + + ngx_mail_ssl_init_connection(&sslcf->ssl, c); + return; + } + + } +#endif + + ngx_mail_init_session(c); +} + + +#if (NGX_MAIL_SSL) + +void +ngx_mail_starttls_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_ssl_conf_t *sslcf; + + c = rev->data; + s = c->data; + s->starttls = 1; + + c->log->action = "in starttls state"; + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + ngx_mail_ssl_init_connection(&sslcf->ssl, c); +} + + +static void +ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) +{ + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { + ngx_mail_close_connection(c); + return; + } + + if (ngx_ssl_handshake(c) == NGX_AGAIN) { + + s = c->data; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + ngx_add_timer(c->read, cscf->timeout); + + c->ssl->handler = ngx_mail_ssl_handshake_handler; + + return; + } + + ngx_mail_ssl_handshake_handler(c); +} + + +static void +ngx_mail_ssl_handshake_handler(ngx_connection_t *c) +{ + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + if (c->ssl->handshaked) { + + s = c->data; + + if (ngx_mail_verify_cert(s, c) != NGX_OK) { + return; + } + + if (s->starttls) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + c->read->handler = cscf->protocol->init_protocol; + c->write->handler = ngx_mail_send; + + cscf->protocol->init_protocol(c->read); + + return; + } + + c->read->ready = 0; + + ngx_mail_init_session(c); + return; + } + + ngx_mail_close_connection(c); +} + + +static ngx_int_t +ngx_mail_verify_cert(ngx_mail_session_t *s, ngx_connection_t *c) +{ + long rc; + X509 *cert; + ngx_mail_ssl_conf_t *sslcf; + ngx_mail_core_srv_conf_t *cscf; + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (!sslcf->verify) { + return NGX_OK; + } + + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK + && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc))) + { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + + ngx_ssl_remove_cached_session(sslcf->ssl.ctx, + (SSL_get0_session(c->ssl->connection))); + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + s->out = cscf->protocol->cert_error; + s->quit = 1; + + c->write->handler = ngx_mail_send; + + ngx_mail_send(s->connection->write); + return NGX_ERROR; + } + + if (sslcf->verify == 1) { + cert = SSL_get_peer_certificate(c->ssl->connection); + + if (cert == NULL) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent no required SSL certificate"); + + ngx_ssl_remove_cached_session(sslcf->ssl.ctx, + (SSL_get0_session(c->ssl->connection))); + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + s->out = cscf->protocol->no_cert; + s->quit = 1; + + c->write->handler = ngx_mail_send; + + ngx_mail_send(s->connection->write); + return NGX_ERROR; + } + + X509_free(cert); + } + + return NGX_OK; +} + +#endif + + +static void +ngx_mail_init_session(ngx_connection_t *c) +{ + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + s = c->data; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + s->protocol = cscf->protocol->type; + + s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_mail_max_module); + if (s->ctx == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + + c->write->handler = ngx_mail_send; + + cscf->protocol->init_session(s, c); +} + + +ngx_int_t +ngx_mail_salt(ngx_mail_session_t *s, ngx_connection_t *c, + ngx_mail_core_srv_conf_t *cscf) +{ + s->salt.data = ngx_pnalloc(c->pool, + sizeof(" <18446744073709551616.@>" CRLF) - 1 + + NGX_TIME_T_LEN + + cscf->server_name.len); + if (s->salt.data == NULL) { + return NGX_ERROR; + } + + s->salt.len = ngx_sprintf(s->salt.data, "<%ul.%T@%V>" CRLF, + ngx_random(), ngx_time(), &cscf->server_name) + - s->salt.data; + + return NGX_OK; +} + + +#if (NGX_MAIL_SSL) + +ngx_int_t +ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_mail_ssl_conf_t *sslcf; + + if (c->ssl) { + return 0; + } + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + return 1; + } + + return 0; +} + +#endif + + +ngx_int_t +ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n) +{ + u_char *p, *last; + ngx_str_t *arg, plain; + + arg = s->args.elts; + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth plain: \"%V\"", &arg[n]); +#endif + + plain.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len)); + if (plain.data == NULL) { + return NGX_ERROR; + } + + if (ngx_decode_base64(&plain, &arg[n]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding in AUTH PLAIN command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + p = plain.data; + last = p + plain.len; + + while (p < last && *p++) { /* void */ } + + if (p == last) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid login in AUTH PLAIN command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + s->login.data = p; + + while (p < last && *p) { p++; } + + if (p == last) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid password in AUTH PLAIN command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + s->login.len = p++ - s->login.data; + + s->passwd.len = last - p; + s->passwd.data = p; + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth plain: \"%V\" \"%V\"", &s->login, &s->passwd); +#endif + + return NGX_DONE; +} + + +ngx_int_t +ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c, + ngx_uint_t n) +{ + ngx_str_t *arg; + + arg = s->args.elts; + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth login username: \"%V\"", &arg[n]); + + s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len)); + if (s->login.data == NULL) { + return NGX_ERROR; + } + + if (ngx_decode_base64(&s->login, &arg[n]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding in AUTH LOGIN command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth login username: \"%V\"", &s->login); + + return NGX_OK; +} + + +ngx_int_t +ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + + arg = s->args.elts; + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth login password: \"%V\"", &arg[0]); +#endif + + s->passwd.data = ngx_pnalloc(c->pool, + ngx_base64_decoded_length(arg[0].len)); + if (s->passwd.data == NULL) { + return NGX_ERROR; + } + + if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding in AUTH LOGIN command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth login password: \"%V\"", &s->passwd); +#endif + + return NGX_DONE; +} + + +ngx_int_t +ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c, + char *prefix, size_t len) +{ + u_char *p; + ngx_str_t salt; + ngx_uint_t n; + + p = ngx_pnalloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) + 2); + if (p == NULL) { + return NGX_ERROR; + } + + salt.data = ngx_cpymem(p, prefix, len); + s->salt.len -= 2; + + ngx_encode_base64(&salt, &s->salt); + + s->salt.len += 2; + n = len + salt.len; + p[n++] = CR; p[n++] = LF; + + s->out.len = n; + s->out.data = p; + + return NGX_OK; +} + + +ngx_int_t +ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c) +{ + u_char *p, *last; + ngx_str_t *arg; + + arg = s->args.elts; + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth cram-md5: \"%V\"", &arg[0]); + + s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len)); + if (s->login.data == NULL) { + return NGX_ERROR; + } + + if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding in AUTH CRAM-MD5 command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + p = s->login.data; + last = p + s->login.len; + + while (p < last) { + if (*p++ == ' ') { + s->login.len = p - s->login.data - 1; + s->passwd.len = last - p; + s->passwd.data = p; + break; + } + } + + if (s->passwd.len != 32) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid CRAM-MD5 hash in AUTH CRAM-MD5 command"); + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail auth cram-md5: \"%V\" \"%V\"", &s->login, &s->passwd); + + s->auth_method = NGX_MAIL_AUTH_CRAM_MD5; + + return NGX_DONE; +} + + +void +ngx_mail_send(ngx_event_t *wev) +{ + ngx_int_t n; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + c = wev->data; + s = c->data; + + if (wev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + if (s->out.len == 0) { + if (ngx_handle_write_event(c->write, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + return; + } + + n = c->send(c, s->out.data, s->out.len); + + if (n > 0) { + s->out.data += n; + s->out.len -= n; + + if (s->out.len != 0) { + goto again; + } + + if (wev->timer_set) { + ngx_del_timer(wev); + } + + if (s->quit) { + ngx_mail_close_connection(c); + return; + } + + if (s->blocked) { + c->read->handler(c->read); + } + + return; + } + + if (n == NGX_ERROR) { + ngx_mail_close_connection(c); + return; + } + + /* n == NGX_AGAIN */ + +again: + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + ngx_add_timer(c->write, cscf->timeout); + + if (ngx_handle_write_event(c->write, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } +} + + +ngx_int_t +ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ssize_t n; + ngx_int_t rc; + ngx_str_t l; + ngx_mail_core_srv_conf_t *cscf; + + n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last); + + if (n == NGX_ERROR || n == 0) { + ngx_mail_close_connection(c); + return NGX_ERROR; + } + + if (n > 0) { + s->buffer->last += n; + } + + if (n == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return NGX_ERROR; + } + + if (s->buffer->pos == s->buffer->last) { + return NGX_AGAIN; + } + } + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + rc = cscf->protocol->parse_command(s); + + if (rc == NGX_AGAIN) { + + if (s->buffer->last < s->buffer->end) { + return rc; + } + + l.len = s->buffer->last - s->buffer->start; + l.data = s->buffer->start; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent too long command \"%V\"", &l); + + s->quit = 1; + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) { + return rc; + } + + if (rc == NGX_ERROR) { + ngx_mail_close_connection(c); + return NGX_ERROR; + } + + return NGX_OK; +} + + +void +ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c) +{ + s->args.nelts = 0; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } + + s->state = 0; + + if (c->read->timer_set) { + ngx_del_timer(c->read); + } + + s->login_attempt++; + + ngx_mail_auth_http_init(s); +} + + +void +ngx_mail_session_internal_server_error(ngx_mail_session_t *s) +{ + ngx_mail_core_srv_conf_t *cscf; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + s->out = cscf->protocol->internal_server_error; + s->quit = 1; + + ngx_mail_send(s->connection->write); +} + + +void +ngx_mail_close_connection(ngx_connection_t *c) +{ + ngx_pool_t *pool; + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "close mail connection: %d", c->fd); + +#if (NGX_MAIL_SSL) + + if (c->ssl) { + if (ngx_ssl_shutdown(c) == NGX_AGAIN) { + c->ssl->handler = ngx_mail_close_connection; + return; + } + } + +#endif + +#if (NGX_STAT_STUB) + (void) ngx_atomic_fetch_add(ngx_stat_active, -1); +#endif + + c->destroyed = 1; + + pool = c->pool; + + ngx_close_connection(c); + + ngx_destroy_pool(pool); +} + + +u_char * +ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len) +{ + u_char *p; + ngx_mail_session_t *s; + ngx_mail_log_ctx_t *ctx; + + if (log->action) { + p = ngx_snprintf(buf, len, " while %s", log->action); + len -= p - buf; + buf = p; + } + + ctx = log->data; + + p = ngx_snprintf(buf, len, ", client: %V", ctx->client); + len -= p - buf; + buf = p; + + s = ctx->session; + + if (s == NULL) { + return p; + } + + p = ngx_snprintf(buf, len, "%s, server: %V", + s->starttls ? " using starttls" : "", + s->addr_text); + len -= p - buf; + buf = p; + + if (s->login.len == 0) { + return p; + } + + p = ngx_snprintf(buf, len, ", login: \"%V\"", &s->login); + len -= p - buf; + buf = p; + + if (s->proxy == NULL) { + return p; + } + + p = ngx_snprintf(buf, len, ", upstream: %V", s->proxy->upstream.name); + + return p; +} diff --git a/hm_nginx/src/mail/ngx_mail_imap_handler.c b/hm_nginx/src/mail/ngx_mail_imap_handler.c new file mode 100644 index 0000000..57e2fb7 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_imap_handler.c @@ -0,0 +1,457 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +static ngx_int_t ngx_mail_imap_login(ngx_mail_session_t *s, + ngx_connection_t *c); +static ngx_int_t ngx_mail_imap_authenticate(ngx_mail_session_t *s, + ngx_connection_t *c); +static ngx_int_t ngx_mail_imap_capability(ngx_mail_session_t *s, + ngx_connection_t *c); +static ngx_int_t ngx_mail_imap_starttls(ngx_mail_session_t *s, + ngx_connection_t *c); + + +static u_char imap_greeting[] = "* OK IMAP4 ready" CRLF; +static u_char imap_star[] = "* "; +static u_char imap_ok[] = "OK completed" CRLF; +static u_char imap_next[] = "+ OK" CRLF; +static u_char imap_plain_next[] = "+ " CRLF; +static u_char imap_username[] = "+ VXNlcm5hbWU6" CRLF; +static u_char imap_password[] = "+ UGFzc3dvcmQ6" CRLF; +static u_char imap_bye[] = "* BYE" CRLF; +static u_char imap_invalid_command[] = "BAD invalid command" CRLF; + + +void +ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_mail_core_srv_conf_t *cscf; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + ngx_str_set(&s->out, imap_greeting); + + c->read->handler = ngx_mail_imap_init_protocol; + + ngx_add_timer(c->read, cscf->timeout); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + ngx_mail_send(c->write); +} + + +void +ngx_mail_imap_init_protocol(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_imap_srv_conf_t *iscf; + + c = rev->data; + + c->log->action = "in auth state"; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + s = c->data; + + if (s->buffer == NULL) { + if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) + == NGX_ERROR) + { + ngx_mail_session_internal_server_error(s); + return; + } + + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); + + s->buffer = ngx_create_temp_buf(c->pool, iscf->client_buffer_size); + if (s->buffer == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + } + + s->mail_state = ngx_imap_start; + c->read->handler = ngx_mail_imap_auth_state; + + ngx_mail_imap_auth_state(rev); +} + + +void +ngx_mail_imap_auth_state(ngx_event_t *rev) +{ + u_char *p, *dst, *src, *end; + ngx_str_t *arg; + ngx_int_t rc; + ngx_uint_t tag, i; + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth state"); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + if (s->out.len) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy"); + s->blocked = 1; + return; + } + + s->blocked = 0; + + rc = ngx_mail_read_command(s, c); + + if (rc == NGX_AGAIN || rc == NGX_ERROR) { + return; + } + + tag = 1; + s->text.len = 0; + ngx_str_set(&s->out, imap_ok); + + if (rc == NGX_OK) { + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i", + s->command); + + if (s->backslash) { + + arg = s->args.elts; + + for (i = 0; i < s->args.nelts; i++) { + dst = arg[i].data; + end = dst + arg[i].len; + + for (src = dst; src < end; dst++) { + *dst = *src; + if (*src++ == '\\') { + *dst = *src++; + } + } + + arg[i].len = dst - arg[i].data; + } + + s->backslash = 0; + } + + switch (s->mail_state) { + + case ngx_imap_start: + + switch (s->command) { + + case NGX_IMAP_LOGIN: + rc = ngx_mail_imap_login(s, c); + break; + + case NGX_IMAP_AUTHENTICATE: + rc = ngx_mail_imap_authenticate(s, c); + tag = (rc != NGX_OK); + break; + + case NGX_IMAP_CAPABILITY: + rc = ngx_mail_imap_capability(s, c); + break; + + case NGX_IMAP_LOGOUT: + s->quit = 1; + ngx_str_set(&s->text, imap_bye); + break; + + case NGX_IMAP_NOOP: + break; + + case NGX_IMAP_STARTTLS: + rc = ngx_mail_imap_starttls(s, c); + break; + + default: + rc = NGX_MAIL_PARSE_INVALID_COMMAND; + break; + } + + break; + + case ngx_imap_auth_login_username: + rc = ngx_mail_auth_login_username(s, c, 0); + + tag = 0; + ngx_str_set(&s->out, imap_password); + s->mail_state = ngx_imap_auth_login_password; + + break; + + case ngx_imap_auth_login_password: + rc = ngx_mail_auth_login_password(s, c); + break; + + case ngx_imap_auth_plain: + rc = ngx_mail_auth_plain(s, c, 0); + break; + + case ngx_imap_auth_cram_md5: + rc = ngx_mail_auth_cram_md5(s, c); + break; + } + + } else if (rc == NGX_IMAP_NEXT) { + tag = 0; + ngx_str_set(&s->out, imap_next); + } + + switch (rc) { + + case NGX_DONE: + ngx_mail_auth(s, c); + return; + + case NGX_ERROR: + ngx_mail_session_internal_server_error(s); + return; + + case NGX_MAIL_PARSE_INVALID_COMMAND: + s->state = 0; + ngx_str_set(&s->out, imap_invalid_command); + s->mail_state = ngx_imap_start; + break; + } + + if (tag) { + if (s->tag.len == 0) { + ngx_str_set(&s->tag, imap_star); + } + + if (s->tagged_line.len < s->tag.len + s->text.len + s->out.len) { + s->tagged_line.len = s->tag.len + s->text.len + s->out.len; + s->tagged_line.data = ngx_pnalloc(c->pool, s->tagged_line.len); + if (s->tagged_line.data == NULL) { + ngx_mail_close_connection(c); + return; + } + } + + p = s->tagged_line.data; + + if (s->text.len) { + p = ngx_cpymem(p, s->text.data, s->text.len); + } + + p = ngx_cpymem(p, s->tag.data, s->tag.len); + ngx_memcpy(p, s->out.data, s->out.len); + + s->out.len = s->text.len + s->tag.len + s->out.len; + s->out.data = s->tagged_line.data; + } + + if (rc != NGX_IMAP_NEXT) { + s->args.nelts = 0; + + if (s->state) { + /* preserve tag */ + s->arg_start = s->buffer->start + s->tag.len; + s->buffer->pos = s->arg_start; + s->buffer->last = s->arg_start; + + } else { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + s->tag.len = 0; + } + } + + ngx_mail_send(c->write); +} + + +static ngx_int_t +ngx_mail_imap_login(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + arg = s->args.elts; + + if (s->args.nelts != 2 || arg[0].len == 0) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + s->login.len = arg[0].len; + s->login.data = ngx_pnalloc(c->pool, s->login.len); + if (s->login.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->login.data, arg[0].data, s->login.len); + + s->passwd.len = arg[1].len; + s->passwd.data = ngx_pnalloc(c->pool, s->passwd.len); + if (s->passwd.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len); + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "imap login:\"%V\" passwd:\"%V\"", + &s->login, &s->passwd); +#else + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "imap login:\"%V\"", &s->login); +#endif + + return NGX_DONE; +} + + +static ngx_int_t +ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_int_t rc; + ngx_mail_core_srv_conf_t *cscf; + ngx_mail_imap_srv_conf_t *iscf; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + rc = ngx_mail_auth_parse(s, c); + + switch (rc) { + + case NGX_MAIL_AUTH_LOGIN: + + ngx_str_set(&s->out, imap_username); + s->mail_state = ngx_imap_auth_login_username; + + return NGX_OK; + + case NGX_MAIL_AUTH_LOGIN_USERNAME: + + ngx_str_set(&s->out, imap_password); + s->mail_state = ngx_imap_auth_login_password; + + return ngx_mail_auth_login_username(s, c, 1); + + case NGX_MAIL_AUTH_PLAIN: + + ngx_str_set(&s->out, imap_plain_next); + s->mail_state = ngx_imap_auth_plain; + + return NGX_OK; + + case NGX_MAIL_AUTH_CRAM_MD5: + + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); + + if (!(iscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (s->salt.data == NULL) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (ngx_mail_salt(s, c, cscf) != NGX_OK) { + return NGX_ERROR; + } + } + + if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) { + s->mail_state = ngx_imap_auth_cram_md5; + return NGX_OK; + } + + return NGX_ERROR; + } + + return rc; +} + + +static ngx_int_t +ngx_mail_imap_capability(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_mail_imap_srv_conf_t *iscf; + + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); + +#if (NGX_MAIL_SSL) + + if (c->ssl == NULL) { + ngx_mail_ssl_conf_t *sslcf; + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { + s->text = iscf->starttls_capability; + return NGX_OK; + } + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + s->text = iscf->starttls_only_capability; + return NGX_OK; + } + } +#endif + + s->text = iscf->capability; + + return NGX_OK; +} + + +static ngx_int_t +ngx_mail_imap_starttls(ngx_mail_session_t *s, ngx_connection_t *c) +{ +#if (NGX_MAIL_SSL) + ngx_mail_ssl_conf_t *sslcf; + + if (c->ssl == NULL) { + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + if (sslcf->starttls) { + c->read->handler = ngx_mail_starttls_handler; + return NGX_OK; + } + } + +#endif + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} diff --git a/hm_nginx/src/mail/ngx_mail_imap_module.c b/hm_nginx/src/mail/ngx_mail_imap_module.c new file mode 100644 index 0000000..d281070 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_imap_module.c @@ -0,0 +1,255 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +static void *ngx_mail_imap_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_imap_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_str_t ngx_mail_imap_default_capabilities[] = { + ngx_string("IMAP4"), + ngx_string("IMAP4rev1"), + ngx_string("UIDPLUS"), + ngx_null_string +}; + + +static ngx_conf_bitmask_t ngx_mail_imap_auth_methods[] = { + { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, + { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, + { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, + { ngx_null_string, 0 } +}; + + +static ngx_str_t ngx_mail_imap_auth_methods_names[] = { + ngx_string("AUTH=PLAIN"), + ngx_string("AUTH=LOGIN"), + ngx_null_string, /* APOP */ + ngx_string("AUTH=CRAM-MD5"), + ngx_null_string /* NONE */ +}; + + +static ngx_mail_protocol_t ngx_mail_imap_protocol = { + ngx_string("imap"), + { 143, 993, 0, 0 }, + NGX_MAIL_IMAP_PROTOCOL, + + ngx_mail_imap_init_session, + ngx_mail_imap_init_protocol, + ngx_mail_imap_parse_command, + ngx_mail_imap_auth_state, + + ngx_string("* BAD internal server error" CRLF), + ngx_string("* BYE SSL certificate error" CRLF), + ngx_string("* BYE No required SSL certificate" CRLF) +}; + + +static ngx_command_t ngx_mail_imap_commands[] = { + + { ngx_string("imap_client_buffer"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_imap_srv_conf_t, client_buffer_size), + NULL }, + + { ngx_string("imap_capabilities"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_capabilities, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_imap_srv_conf_t, capabilities), + NULL }, + + { ngx_string("imap_auth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_imap_srv_conf_t, auth_methods), + &ngx_mail_imap_auth_methods }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_imap_module_ctx = { + &ngx_mail_imap_protocol, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_imap_create_srv_conf, /* create server configuration */ + ngx_mail_imap_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_imap_module = { + NGX_MODULE_V1, + &ngx_mail_imap_module_ctx, /* module context */ + ngx_mail_imap_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_imap_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_imap_srv_conf_t *iscf; + + iscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_imap_srv_conf_t)); + if (iscf == NULL) { + return NULL; + } + + iscf->client_buffer_size = NGX_CONF_UNSET_SIZE; + + if (ngx_array_init(&iscf->capabilities, cf->pool, 4, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + + return iscf; +} + + +static char * +ngx_mail_imap_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_imap_srv_conf_t *prev = parent; + ngx_mail_imap_srv_conf_t *conf = child; + + u_char *p, *auth; + size_t size; + ngx_str_t *c, *d; + ngx_uint_t i, m; + + ngx_conf_merge_size_value(conf->client_buffer_size, + prev->client_buffer_size, + (size_t) ngx_pagesize); + + ngx_conf_merge_bitmask_value(conf->auth_methods, + prev->auth_methods, + (NGX_CONF_BITMASK_SET + |NGX_MAIL_AUTH_PLAIN_ENABLED)); + + + if (conf->capabilities.nelts == 0) { + conf->capabilities = prev->capabilities; + } + + if (conf->capabilities.nelts == 0) { + + for (d = ngx_mail_imap_default_capabilities; d->len; d++) { + c = ngx_array_push(&conf->capabilities); + if (c == NULL) { + return NGX_CONF_ERROR; + } + + *c = *d; + } + } + + size = sizeof("* CAPABILITY" CRLF) - 1; + + c = conf->capabilities.elts; + for (i = 0; i < conf->capabilities.nelts; i++) { + size += 1 + c[i].len; + } + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + size += 1 + ngx_mail_imap_auth_methods_names[i].len; + } + } + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->capability.len = size; + conf->capability.data = p; + + p = ngx_cpymem(p, "* CAPABILITY", sizeof("* CAPABILITY") - 1); + + for (i = 0; i < conf->capabilities.nelts; i++) { + *p++ = ' '; + p = ngx_cpymem(p, c[i].data, c[i].len); + } + + auth = p; + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_mail_imap_auth_methods_names[i].data, + ngx_mail_imap_auth_methods_names[i].len); + } + } + + *p++ = CR; *p = LF; + + + size += sizeof(" STARTTLS") - 1; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_capability.len = size; + conf->starttls_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + conf->capability.len - (sizeof(CRLF) - 1)); + p = ngx_cpymem(p, " STARTTLS", sizeof(" STARTTLS") - 1); + *p++ = CR; *p = LF; + + + size = (auth - conf->capability.data) + sizeof(CRLF) - 1 + + sizeof(" STARTTLS LOGINDISABLED") - 1; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_only_capability.len = size; + conf->starttls_only_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + auth - conf->capability.data); + p = ngx_cpymem(p, " STARTTLS LOGINDISABLED", + sizeof(" STARTTLS LOGINDISABLED") - 1); + *p++ = CR; *p = LF; + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail_imap_module.h b/hm_nginx/src/mail/ngx_mail_imap_module.h new file mode 100644 index 0000000..131b445 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_imap_module.h @@ -0,0 +1,39 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_MAIL_IMAP_MODULE_H_INCLUDED_ +#define _NGX_MAIL_IMAP_MODULE_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + size_t client_buffer_size; + + ngx_str_t capability; + ngx_str_t starttls_capability; + ngx_str_t starttls_only_capability; + + ngx_uint_t auth_methods; + + ngx_array_t capabilities; +} ngx_mail_imap_srv_conf_t; + + +void ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_imap_init_protocol(ngx_event_t *rev); +void ngx_mail_imap_auth_state(ngx_event_t *rev); +ngx_int_t ngx_mail_imap_parse_command(ngx_mail_session_t *s); + + +extern ngx_module_t ngx_mail_imap_module; + + +#endif /* _NGX_MAIL_IMAP_MODULE_H_INCLUDED_ */ diff --git a/hm_nginx/src/mail/ngx_mail_parse.c b/hm_nginx/src/mail/ngx_mail_parse.c new file mode 100644 index 0000000..b158f5a --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_parse.c @@ -0,0 +1,918 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include +#include +#include + + +ngx_int_t +ngx_mail_pop3_parse_command(ngx_mail_session_t *s) +{ + u_char ch, *p, *c, c0, c1, c2, c3; + ngx_str_t *arg; + enum { + sw_start = 0, + sw_spaces_before_argument, + sw_argument, + sw_almost_done + } state; + + state = s->state; + + for (p = s->buffer->pos; p < s->buffer->last; p++) { + ch = *p; + + switch (state) { + + /* POP3 command */ + case sw_start: + if (ch == ' ' || ch == CR || ch == LF) { + c = s->buffer->start; + + if (p - c == 4) { + + c0 = ngx_toupper(c[0]); + c1 = ngx_toupper(c[1]); + c2 = ngx_toupper(c[2]); + c3 = ngx_toupper(c[3]); + + if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R') + { + s->command = NGX_POP3_USER; + + } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S') + { + s->command = NGX_POP3_PASS; + + } else if (c0 == 'A' && c1 == 'P' && c2 == 'O' && c3 == 'P') + { + s->command = NGX_POP3_APOP; + + } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') + { + s->command = NGX_POP3_QUIT; + + } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A') + { + s->command = NGX_POP3_CAPA; + + } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H') + { + s->command = NGX_POP3_AUTH; + + } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') + { + s->command = NGX_POP3_NOOP; +#if (NGX_MAIL_SSL) + } else if (c0 == 'S' && c1 == 'T' && c2 == 'L' && c3 == 'S') + { + s->command = NGX_POP3_STLS; +#endif + } else { + goto invalid; + } + + } else { + goto invalid; + } + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + } + + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + goto invalid; + } + + break; + + case sw_spaces_before_argument: + switch (ch) { + case ' ': + break; + case CR: + state = sw_almost_done; + s->arg_end = p; + break; + case LF: + s->arg_end = p; + goto done; + default: + if (s->args.nelts <= 2) { + state = sw_argument; + s->arg_start = p; + break; + } + goto invalid; + } + break; + + case sw_argument: + switch (ch) { + + case ' ': + + /* + * the space should be considered as part of the at username + * or password, but not of argument in other commands + */ + + if (s->command == NGX_POP3_USER + || s->command == NGX_POP3_PASS) + { + break; + } + + /* fall through */ + + case CR: + case LF: + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + + default: + break; + } + break; + + case sw_almost_done: + switch (ch) { + case LF: + goto done; + default: + goto invalid; + } + } + } + + s->buffer->pos = p; + s->state = state; + + return NGX_AGAIN; + +done: + + s->buffer->pos = p + 1; + + if (s->arg_start) { + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = s->arg_end - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + } + + s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; + + return NGX_OK; + +invalid: + + s->state = sw_start; + s->arg_start = NULL; + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} + + +ngx_int_t +ngx_mail_imap_parse_command(ngx_mail_session_t *s) +{ + u_char ch, *p, *c; + ngx_str_t *arg; + enum { + sw_start = 0, + sw_spaces_before_command, + sw_command, + sw_spaces_before_argument, + sw_argument, + sw_backslash, + sw_literal, + sw_no_sync_literal_argument, + sw_start_literal_argument, + sw_literal_argument, + sw_end_literal_argument, + sw_almost_done + } state; + + state = s->state; + + for (p = s->buffer->pos; p < s->buffer->last; p++) { + ch = *p; + + switch (state) { + + /* IMAP tag */ + case sw_start: + switch (ch) { + case ' ': + s->tag.len = p - s->buffer->start + 1; + s->tag.data = s->buffer->start; + state = sw_spaces_before_command; + break; + case CR: + s->state = sw_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; + case LF: + s->state = sw_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + break; + + case sw_spaces_before_command: + switch (ch) { + case ' ': + break; + case CR: + s->state = sw_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; + case LF: + s->state = sw_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; + default: + s->cmd_start = p; + state = sw_command; + break; + } + break; + + case sw_command: + if (ch == ' ' || ch == CR || ch == LF) { + + c = s->cmd_start; + + switch (p - c) { + + case 4: + if ((c[0] == 'N' || c[0] == 'n') + && (c[1] == 'O'|| c[1] == 'o') + && (c[2] == 'O'|| c[2] == 'o') + && (c[3] == 'P'|| c[3] == 'p')) + { + s->command = NGX_IMAP_NOOP; + + } else { + goto invalid; + } + break; + + case 5: + if ((c[0] == 'L'|| c[0] == 'l') + && (c[1] == 'O'|| c[1] == 'o') + && (c[2] == 'G'|| c[2] == 'g') + && (c[3] == 'I'|| c[3] == 'i') + && (c[4] == 'N'|| c[4] == 'n')) + { + s->command = NGX_IMAP_LOGIN; + + } else { + goto invalid; + } + break; + + case 6: + if ((c[0] == 'L'|| c[0] == 'l') + && (c[1] == 'O'|| c[1] == 'o') + && (c[2] == 'G'|| c[2] == 'g') + && (c[3] == 'O'|| c[3] == 'o') + && (c[4] == 'U'|| c[4] == 'u') + && (c[5] == 'T'|| c[5] == 't')) + { + s->command = NGX_IMAP_LOGOUT; + + } else { + goto invalid; + } + break; + +#if (NGX_MAIL_SSL) + case 8: + if ((c[0] == 'S'|| c[0] == 's') + && (c[1] == 'T'|| c[1] == 't') + && (c[2] == 'A'|| c[2] == 'a') + && (c[3] == 'R'|| c[3] == 'r') + && (c[4] == 'T'|| c[4] == 't') + && (c[5] == 'T'|| c[5] == 't') + && (c[6] == 'L'|| c[6] == 'l') + && (c[7] == 'S'|| c[7] == 's')) + { + s->command = NGX_IMAP_STARTTLS; + + } else { + goto invalid; + } + break; +#endif + + case 10: + if ((c[0] == 'C'|| c[0] == 'c') + && (c[1] == 'A'|| c[1] == 'a') + && (c[2] == 'P'|| c[2] == 'p') + && (c[3] == 'A'|| c[3] == 'a') + && (c[4] == 'B'|| c[4] == 'b') + && (c[5] == 'I'|| c[5] == 'i') + && (c[6] == 'L'|| c[6] == 'l') + && (c[7] == 'I'|| c[7] == 'i') + && (c[8] == 'T'|| c[8] == 't') + && (c[9] == 'Y'|| c[9] == 'y')) + { + s->command = NGX_IMAP_CAPABILITY; + + } else { + goto invalid; + } + break; + + case 12: + if ((c[0] == 'A'|| c[0] == 'a') + && (c[1] == 'U'|| c[1] == 'u') + && (c[2] == 'T'|| c[2] == 't') + && (c[3] == 'H'|| c[3] == 'h') + && (c[4] == 'E'|| c[4] == 'e') + && (c[5] == 'N'|| c[5] == 'n') + && (c[6] == 'T'|| c[6] == 't') + && (c[7] == 'I'|| c[7] == 'i') + && (c[8] == 'C'|| c[8] == 'c') + && (c[9] == 'A'|| c[9] == 'a') + && (c[10] == 'T'|| c[10] == 't') + && (c[11] == 'E'|| c[11] == 'e')) + { + s->command = NGX_IMAP_AUTHENTICATE; + + } else { + goto invalid; + } + break; + + default: + goto invalid; + } + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + } + + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + goto invalid; + } + + break; + + case sw_spaces_before_argument: + switch (ch) { + case ' ': + break; + case CR: + state = sw_almost_done; + s->arg_end = p; + break; + case LF: + s->arg_end = p; + goto done; + case '"': + if (s->args.nelts <= 2) { + s->quoted = 1; + s->arg_start = p + 1; + state = sw_argument; + break; + } + goto invalid; + case '{': + if (s->args.nelts <= 2) { + state = sw_literal; + break; + } + goto invalid; + default: + if (s->args.nelts <= 2) { + s->arg_start = p; + state = sw_argument; + break; + } + goto invalid; + } + break; + + case sw_argument: + if (ch == ' ' && s->quoted) { + break; + } + + switch (ch) { + case '"': + if (!s->quoted) { + break; + } + s->quoted = 0; + /* fall through */ + case ' ': + case CR: + case LF: + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + + switch (ch) { + case '"': + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + case '\\': + if (s->quoted) { + s->backslash = 1; + state = sw_backslash; + } + break; + } + break; + + case sw_backslash: + switch (ch) { + case CR: + case LF: + goto invalid; + default: + state = sw_argument; + } + break; + + case sw_literal: + if (ch >= '0' && ch <= '9') { + s->literal_len = s->literal_len * 10 + (ch - '0'); + break; + } + if (ch == '}') { + state = sw_start_literal_argument; + break; + } + if (ch == '+') { + state = sw_no_sync_literal_argument; + break; + } + goto invalid; + + case sw_no_sync_literal_argument: + if (ch == '}') { + s->no_sync_literal = 1; + state = sw_start_literal_argument; + break; + } + goto invalid; + + case sw_start_literal_argument: + switch (ch) { + case CR: + break; + case LF: + s->buffer->pos = p + 1; + s->arg_start = p + 1; + if (s->no_sync_literal == 0) { + s->state = sw_literal_argument; + return NGX_IMAP_NEXT; + } + state = sw_literal_argument; + s->no_sync_literal = 0; + break; + default: + goto invalid; + } + break; + + case sw_literal_argument: + if (s->literal_len && --s->literal_len) { + break; + } + + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p + 1 - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + state = sw_end_literal_argument; + + break; + + case sw_end_literal_argument: + switch (ch) { + case '{': + if (s->args.nelts <= 2) { + state = sw_literal; + break; + } + goto invalid; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + default: + state = sw_spaces_before_argument; + break; + } + break; + + case sw_almost_done: + switch (ch) { + case LF: + goto done; + default: + goto invalid; + } + } + } + + s->buffer->pos = p; + s->state = state; + + return NGX_AGAIN; + +done: + + s->buffer->pos = p + 1; + + if (s->arg_start) { + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = s->arg_end - s->arg_start; + arg->data = s->arg_start; + + s->arg_start = NULL; + s->cmd_start = NULL; + s->quoted = 0; + s->no_sync_literal = 0; + s->literal_len = 0; + } + + s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; + + return NGX_OK; + +invalid: + + s->state = sw_start; + s->quoted = 0; + s->no_sync_literal = 0; + s->literal_len = 0; + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} + + +ngx_int_t +ngx_mail_smtp_parse_command(ngx_mail_session_t *s) +{ + u_char ch, *p, *c, c0, c1, c2, c3; + ngx_str_t *arg; + enum { + sw_start = 0, + sw_command, + sw_invalid, + sw_spaces_before_argument, + sw_argument, + sw_almost_done + } state; + + state = s->state; + + for (p = s->buffer->pos; p < s->buffer->last; p++) { + ch = *p; + + switch (state) { + + /* SMTP command */ + case sw_start: + s->cmd_start = p; + state = sw_command; + + /* fall through */ + + case sw_command: + if (ch == ' ' || ch == CR || ch == LF) { + c = s->cmd_start; + + if (p - c == 4) { + + c0 = ngx_toupper(c[0]); + c1 = ngx_toupper(c[1]); + c2 = ngx_toupper(c[2]); + c3 = ngx_toupper(c[3]); + + if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'O') + { + s->command = NGX_SMTP_HELO; + + } else if (c0 == 'E' && c1 == 'H' && c2 == 'L' && c3 == 'O') + { + s->command = NGX_SMTP_EHLO; + + } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') + { + s->command = NGX_SMTP_QUIT; + + } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H') + { + s->command = NGX_SMTP_AUTH; + + } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') + { + s->command = NGX_SMTP_NOOP; + + } else if (c0 == 'M' && c1 == 'A' && c2 == 'I' && c3 == 'L') + { + s->command = NGX_SMTP_MAIL; + + } else if (c0 == 'R' && c1 == 'S' && c2 == 'E' && c3 == 'T') + { + s->command = NGX_SMTP_RSET; + + } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T') + { + s->command = NGX_SMTP_RCPT; + + } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y') + { + s->command = NGX_SMTP_VRFY; + + } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N') + { + s->command = NGX_SMTP_EXPN; + + } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P') + { + s->command = NGX_SMTP_HELP; + + } else { + goto invalid; + } +#if (NGX_MAIL_SSL) + } else if (p - c == 8) { + + if ((c[0] == 'S'|| c[0] == 's') + && (c[1] == 'T'|| c[1] == 't') + && (c[2] == 'A'|| c[2] == 'a') + && (c[3] == 'R'|| c[3] == 'r') + && (c[4] == 'T'|| c[4] == 't') + && (c[5] == 'T'|| c[5] == 't') + && (c[6] == 'L'|| c[6] == 'l') + && (c[7] == 'S'|| c[7] == 's')) + { + s->command = NGX_SMTP_STARTTLS; + + } else { + goto invalid; + } +#endif + } else { + goto invalid; + } + + s->cmd.data = s->cmd_start; + s->cmd.len = p - s->cmd_start; + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + } + + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + goto invalid; + } + + break; + + case sw_invalid: + goto invalid; + + case sw_spaces_before_argument: + switch (ch) { + case ' ': + break; + case CR: + state = sw_almost_done; + s->arg_end = p; + break; + case LF: + s->arg_end = p; + goto done; + default: + if (s->args.nelts <= 10) { + state = sw_argument; + s->arg_start = p; + break; + } + goto invalid; + } + break; + + case sw_argument: + switch (ch) { + case ' ': + case CR: + case LF: + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + + default: + break; + } + break; + + case sw_almost_done: + switch (ch) { + case LF: + goto done; + default: + goto invalid; + } + } + } + + s->buffer->pos = p; + s->state = state; + + return NGX_AGAIN; + +done: + + s->buffer->pos = p + 1; + + if (s->arg_start) { + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = s->arg_end - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + } + + s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; + + return NGX_OK; + +invalid: + + s->state = sw_invalid; + s->arg_start = NULL; + + /* skip invalid command till LF */ + + for (p = s->buffer->pos; p < s->buffer->last; p++) { + if (*p == LF) { + s->state = sw_start; + p++; + break; + } + } + + s->buffer->pos = p; + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} + + +ngx_int_t +ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + if (s->args.nelts == 0) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + arg = s->args.elts; + + if (arg[0].len == 5) { + + if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { + + if (s->args.nelts == 1) { + return NGX_MAIL_AUTH_LOGIN; + } + + if (s->args.nelts == 2) { + return NGX_MAIL_AUTH_LOGIN_USERNAME; + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { + + if (s->args.nelts == 1) { + return NGX_MAIL_AUTH_PLAIN; + } + + if (s->args.nelts == 2) { + return ngx_mail_auth_plain(s, c, 1); + } + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (arg[0].len == 8) { + + if (s->args.nelts != 1) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) { + return NGX_MAIL_AUTH_CRAM_MD5; + } + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} diff --git a/hm_nginx/src/mail/ngx_mail_pop3_handler.c b/hm_nginx/src/mail/ngx_mail_pop3_handler.c new file mode 100644 index 0000000..51bc257 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_pop3_handler.c @@ -0,0 +1,500 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +static ngx_int_t ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_pop3_pass(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c, + ngx_int_t stls); +static ngx_int_t ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c); + + +static u_char pop3_greeting[] = "+OK POP3 ready" CRLF; +static u_char pop3_ok[] = "+OK" CRLF; +static u_char pop3_next[] = "+ " CRLF; +static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; +static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; +static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; + + +void +ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c) +{ + u_char *p; + ngx_mail_core_srv_conf_t *cscf; + ngx_mail_pop3_srv_conf_t *pscf; + + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (pscf->auth_methods + & (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) + { + if (ngx_mail_salt(s, c, cscf) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + s->out.data = ngx_pnalloc(c->pool, sizeof(pop3_greeting) + s->salt.len); + if (s->out.data == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + + p = ngx_cpymem(s->out.data, pop3_greeting, sizeof(pop3_greeting) - 3); + *p++ = ' '; + p = ngx_cpymem(p, s->salt.data, s->salt.len); + + s->out.len = p - s->out.data; + + } else { + ngx_str_set(&s->out, pop3_greeting); + } + + c->read->handler = ngx_mail_pop3_init_protocol; + + ngx_add_timer(c->read, cscf->timeout); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + ngx_mail_send(c->write); +} + + +void +ngx_mail_pop3_init_protocol(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + + c->log->action = "in auth state"; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + s = c->data; + + if (s->buffer == NULL) { + if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) + == NGX_ERROR) + { + ngx_mail_session_internal_server_error(s); + return; + } + + s->buffer = ngx_create_temp_buf(c->pool, 128); + if (s->buffer == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + } + + s->mail_state = ngx_pop3_start; + c->read->handler = ngx_mail_pop3_auth_state; + + ngx_mail_pop3_auth_state(rev); +} + + +void +ngx_mail_pop3_auth_state(ngx_event_t *rev) +{ + ngx_int_t rc; + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 auth state"); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + if (s->out.len) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy"); + s->blocked = 1; + return; + } + + s->blocked = 0; + + rc = ngx_mail_read_command(s, c); + + if (rc == NGX_AGAIN || rc == NGX_ERROR) { + return; + } + + ngx_str_set(&s->out, pop3_ok); + + if (rc == NGX_OK) { + switch (s->mail_state) { + + case ngx_pop3_start: + + switch (s->command) { + + case NGX_POP3_USER: + rc = ngx_mail_pop3_user(s, c); + break; + + case NGX_POP3_CAPA: + rc = ngx_mail_pop3_capa(s, c, 1); + break; + + case NGX_POP3_APOP: + rc = ngx_mail_pop3_apop(s, c); + break; + + case NGX_POP3_AUTH: + rc = ngx_mail_pop3_auth(s, c); + break; + + case NGX_POP3_QUIT: + s->quit = 1; + break; + + case NGX_POP3_NOOP: + break; + + case NGX_POP3_STLS: + rc = ngx_mail_pop3_stls(s, c); + break; + + default: + rc = NGX_MAIL_PARSE_INVALID_COMMAND; + break; + } + + break; + + case ngx_pop3_user: + + switch (s->command) { + + case NGX_POP3_PASS: + rc = ngx_mail_pop3_pass(s, c); + break; + + case NGX_POP3_CAPA: + rc = ngx_mail_pop3_capa(s, c, 0); + break; + + case NGX_POP3_QUIT: + s->quit = 1; + break; + + case NGX_POP3_NOOP: + break; + + default: + rc = NGX_MAIL_PARSE_INVALID_COMMAND; + break; + } + + break; + + /* suppress warnings */ + case ngx_pop3_passwd: + break; + + case ngx_pop3_auth_login_username: + rc = ngx_mail_auth_login_username(s, c, 0); + + ngx_str_set(&s->out, pop3_password); + s->mail_state = ngx_pop3_auth_login_password; + break; + + case ngx_pop3_auth_login_password: + rc = ngx_mail_auth_login_password(s, c); + break; + + case ngx_pop3_auth_plain: + rc = ngx_mail_auth_plain(s, c, 0); + break; + + case ngx_pop3_auth_cram_md5: + rc = ngx_mail_auth_cram_md5(s, c); + break; + } + } + + switch (rc) { + + case NGX_DONE: + ngx_mail_auth(s, c); + return; + + case NGX_ERROR: + ngx_mail_session_internal_server_error(s); + return; + + case NGX_MAIL_PARSE_INVALID_COMMAND: + s->mail_state = ngx_pop3_start; + s->state = 0; + + ngx_str_set(&s->out, pop3_invalid_command); + + /* fall through */ + + case NGX_OK: + + s->args.nelts = 0; + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + + if (s->state) { + s->arg_start = s->buffer->start; + } + + ngx_mail_send(c->write); + } +} + +static ngx_int_t +ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + if (s->args.nelts != 1) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + arg = s->args.elts; + s->login.len = arg[0].len; + s->login.data = ngx_pnalloc(c->pool, s->login.len); + if (s->login.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->login.data, arg[0].data, s->login.len); + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "pop3 login: \"%V\"", &s->login); + + s->mail_state = ngx_pop3_user; + + return NGX_OK; +} + + +static ngx_int_t +ngx_mail_pop3_pass(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + + if (s->args.nelts != 1) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + arg = s->args.elts; + s->passwd.len = arg[0].len; + s->passwd.data = ngx_pnalloc(c->pool, s->passwd.len); + if (s->passwd.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->passwd.data, arg[0].data, s->passwd.len); + +#if (NGX_DEBUG_MAIL_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "pop3 passwd: \"%V\"", &s->passwd); +#endif + + return NGX_DONE; +} + + +static ngx_int_t +ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c, ngx_int_t stls) +{ + ngx_mail_pop3_srv_conf_t *pscf; + + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); + +#if (NGX_MAIL_SSL) + + if (stls && c->ssl == NULL) { + ngx_mail_ssl_conf_t *sslcf; + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { + s->out = pscf->starttls_capability; + return NGX_OK; + } + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + s->out = pscf->starttls_only_capability; + return NGX_OK; + } + } + +#endif + + s->out = pscf->capability; + return NGX_OK; +} + + +static ngx_int_t +ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c) +{ +#if (NGX_MAIL_SSL) + ngx_mail_ssl_conf_t *sslcf; + + if (c->ssl == NULL) { + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + if (sslcf->starttls) { + c->read->handler = ngx_mail_starttls_handler; + return NGX_OK; + } + } + +#endif + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} + + +static ngx_int_t +ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + ngx_mail_pop3_srv_conf_t *pscf; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + if (s->args.nelts != 2) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); + + if (!(pscf->auth_methods & NGX_MAIL_AUTH_APOP_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + arg = s->args.elts; + + s->login.len = arg[0].len; + s->login.data = ngx_pnalloc(c->pool, s->login.len); + if (s->login.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->login.data, arg[0].data, s->login.len); + + s->passwd.len = arg[1].len; + s->passwd.data = ngx_pnalloc(c->pool, s->passwd.len); + if (s->passwd.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len); + + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "pop3 apop: \"%V\" \"%V\"", &s->login, &s->passwd); + + s->auth_method = NGX_MAIL_AUTH_APOP; + + return NGX_DONE; +} + + +static ngx_int_t +ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_int_t rc; + ngx_mail_pop3_srv_conf_t *pscf; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); + + if (s->args.nelts == 0) { + s->out = pscf->auth_capability; + s->state = 0; + + return NGX_OK; + } + + rc = ngx_mail_auth_parse(s, c); + + switch (rc) { + + case NGX_MAIL_AUTH_LOGIN: + + ngx_str_set(&s->out, pop3_username); + s->mail_state = ngx_pop3_auth_login_username; + + return NGX_OK; + + case NGX_MAIL_AUTH_LOGIN_USERNAME: + + ngx_str_set(&s->out, pop3_password); + s->mail_state = ngx_pop3_auth_login_password; + + return ngx_mail_auth_login_username(s, c, 1); + + case NGX_MAIL_AUTH_PLAIN: + + ngx_str_set(&s->out, pop3_next); + s->mail_state = ngx_pop3_auth_plain; + + return NGX_OK; + + case NGX_MAIL_AUTH_CRAM_MD5: + + if (!(pscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) { + s->mail_state = ngx_pop3_auth_cram_md5; + return NGX_OK; + } + + return NGX_ERROR; + } + + return rc; +} diff --git a/hm_nginx/src/mail/ngx_mail_pop3_module.c b/hm_nginx/src/mail/ngx_mail_pop3_module.c new file mode 100644 index 0000000..73f8531 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_pop3_module.c @@ -0,0 +1,266 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +static void *ngx_mail_pop3_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_str_t ngx_mail_pop3_default_capabilities[] = { + ngx_string("TOP"), + ngx_string("USER"), + ngx_string("UIDL"), + ngx_null_string +}; + + +static ngx_conf_bitmask_t ngx_mail_pop3_auth_methods[] = { + { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, + { ngx_string("apop"), NGX_MAIL_AUTH_APOP_ENABLED }, + { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, + { ngx_null_string, 0 } +}; + + +static ngx_str_t ngx_mail_pop3_auth_plain_capability = + ngx_string("+OK methods supported:" CRLF + "LOGIN" CRLF + "PLAIN" CRLF + "." CRLF); + + +static ngx_str_t ngx_mail_pop3_auth_cram_md5_capability = + ngx_string("+OK methods supported:" CRLF + "LOGIN" CRLF + "PLAIN" CRLF + "CRAM-MD5" CRLF + "." CRLF); + + +static ngx_mail_protocol_t ngx_mail_pop3_protocol = { + ngx_string("pop3"), + { 110, 995, 0, 0 }, + NGX_MAIL_POP3_PROTOCOL, + + ngx_mail_pop3_init_session, + ngx_mail_pop3_init_protocol, + ngx_mail_pop3_parse_command, + ngx_mail_pop3_auth_state, + + ngx_string("-ERR internal server error" CRLF), + ngx_string("-ERR SSL certificate error" CRLF), + ngx_string("-ERR No required SSL certificate" CRLF) +}; + + +static ngx_command_t ngx_mail_pop3_commands[] = { + + { ngx_string("pop3_capabilities"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_capabilities, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_pop3_srv_conf_t, capabilities), + NULL }, + + { ngx_string("pop3_auth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_pop3_srv_conf_t, auth_methods), + &ngx_mail_pop3_auth_methods }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_pop3_module_ctx = { + &ngx_mail_pop3_protocol, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_pop3_create_srv_conf, /* create server configuration */ + ngx_mail_pop3_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_pop3_module = { + NGX_MODULE_V1, + &ngx_mail_pop3_module_ctx, /* module context */ + ngx_mail_pop3_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_pop3_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_pop3_srv_conf_t *pscf; + + pscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_pop3_srv_conf_t)); + if (pscf == NULL) { + return NULL; + } + + if (ngx_array_init(&pscf->capabilities, cf->pool, 4, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + + return pscf; +} + + +static char * +ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_pop3_srv_conf_t *prev = parent; + ngx_mail_pop3_srv_conf_t *conf = child; + + u_char *p; + size_t size, stls_only_size; + ngx_str_t *c, *d; + ngx_uint_t i; + + ngx_conf_merge_bitmask_value(conf->auth_methods, + prev->auth_methods, + (NGX_CONF_BITMASK_SET + |NGX_MAIL_AUTH_PLAIN_ENABLED)); + + if (conf->capabilities.nelts == 0) { + conf->capabilities = prev->capabilities; + } + + if (conf->capabilities.nelts == 0) { + + for (d = ngx_mail_pop3_default_capabilities; d->len; d++) { + c = ngx_array_push(&conf->capabilities); + if (c == NULL) { + return NGX_CONF_ERROR; + } + + *c = *d; + } + } + + size = sizeof("+OK Capability list follows" CRLF) - 1 + + sizeof("." CRLF) - 1; + + stls_only_size = size + sizeof("STLS" CRLF) - 1; + + c = conf->capabilities.elts; + for (i = 0; i < conf->capabilities.nelts; i++) { + size += c[i].len + sizeof(CRLF) - 1; + + if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { + continue; + } + + stls_only_size += c[i].len + sizeof(CRLF) - 1; + } + + if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { + size += sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1; + + } else { + size += sizeof("SASL LOGIN PLAIN" CRLF) - 1; + } + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->capability.len = size; + conf->capability.data = p; + + p = ngx_cpymem(p, "+OK Capability list follows" CRLF, + sizeof("+OK Capability list follows" CRLF) - 1); + + for (i = 0; i < conf->capabilities.nelts; i++) { + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { + p = ngx_cpymem(p, "SASL LOGIN PLAIN CRAM-MD5" CRLF, + sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1); + + } else { + p = ngx_cpymem(p, "SASL LOGIN PLAIN" CRLF, + sizeof("SASL LOGIN PLAIN" CRLF) - 1); + } + + *p++ = '.'; *p++ = CR; *p = LF; + + + size += sizeof("STLS" CRLF) - 1; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_capability.len = size; + conf->starttls_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + conf->capability.len - (sizeof("." CRLF) - 1)); + + p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); + *p++ = '.'; *p++ = CR; *p = LF; + + + if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { + conf->auth_capability = ngx_mail_pop3_auth_cram_md5_capability; + + } else { + conf->auth_capability = ngx_mail_pop3_auth_plain_capability; + } + + + p = ngx_pnalloc(cf->pool, stls_only_size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_only_capability.len = stls_only_size; + conf->starttls_only_capability.data = p; + + p = ngx_cpymem(p, "+OK Capability list follows" CRLF, + sizeof("+OK Capability list follows" CRLF) - 1); + + for (i = 0; i < conf->capabilities.nelts; i++) { + if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { + continue; + } + + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); + *p++ = '.'; *p++ = CR; *p = LF; + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail_pop3_module.h b/hm_nginx/src/mail/ngx_mail_pop3_module.h new file mode 100644 index 0000000..86947a7 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_pop3_module.h @@ -0,0 +1,38 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_MAIL_POP3_MODULE_H_INCLUDED_ +#define _NGX_MAIL_POP3_MODULE_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + ngx_str_t capability; + ngx_str_t starttls_capability; + ngx_str_t starttls_only_capability; + ngx_str_t auth_capability; + + ngx_uint_t auth_methods; + + ngx_array_t capabilities; +} ngx_mail_pop3_srv_conf_t; + + +void ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_pop3_init_protocol(ngx_event_t *rev); +void ngx_mail_pop3_auth_state(ngx_event_t *rev); +ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s); + + +extern ngx_module_t ngx_mail_pop3_module; + + +#endif /* _NGX_MAIL_POP3_MODULE_H_INCLUDED_ */ diff --git a/hm_nginx/src/mail/ngx_mail_proxy_module.c b/hm_nginx/src/mail/ngx_mail_proxy_module.c new file mode 100644 index 0000000..41cbcf6 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_proxy_module.c @@ -0,0 +1,1136 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +typedef struct { + ngx_flag_t enable; + ngx_flag_t pass_error_message; + ngx_flag_t xclient; + size_t buffer_size; + ngx_msec_t timeout; +} ngx_mail_proxy_conf_t; + + +static void ngx_mail_proxy_block_read(ngx_event_t *rev); +static void ngx_mail_proxy_pop3_handler(ngx_event_t *rev); +static void ngx_mail_proxy_imap_handler(ngx_event_t *rev); +static void ngx_mail_proxy_smtp_handler(ngx_event_t *rev); +static void ngx_mail_proxy_dummy_handler(ngx_event_t *ev); +static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s, + ngx_uint_t state); +static void ngx_mail_proxy_handler(ngx_event_t *ev); +static void ngx_mail_proxy_upstream_error(ngx_mail_session_t *s); +static void ngx_mail_proxy_internal_server_error(ngx_mail_session_t *s); +static void ngx_mail_proxy_close_session(ngx_mail_session_t *s); +static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf); +static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_command_t ngx_mail_proxy_commands[] = { + + { ngx_string("proxy"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, enable), + NULL }, + + { ngx_string("proxy_buffer"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, buffer_size), + NULL }, + + { ngx_string("proxy_timeout"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, timeout), + NULL }, + + { ngx_string("proxy_pass_error_message"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, pass_error_message), + NULL }, + + { ngx_string("xclient"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, xclient), + NULL }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_proxy_module_ctx = { + NULL, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_proxy_create_conf, /* create server configuration */ + ngx_mail_proxy_merge_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_proxy_module = { + NGX_MODULE_V1, + &ngx_mail_proxy_module_ctx, /* module context */ + ngx_mail_proxy_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static u_char smtp_auth_ok[] = "235 2.0.0 OK" CRLF; + + +void +ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer) +{ + int keepalive; + ngx_int_t rc; + ngx_mail_proxy_ctx_t *p; + ngx_mail_proxy_conf_t *pcf; + ngx_mail_core_srv_conf_t *cscf; + + s->connection->log->action = "connecting to upstream"; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (cscf->so_keepalive) { + keepalive = 1; + + if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE, + (const void *) &keepalive, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno, + "setsockopt(SO_KEEPALIVE) failed"); + } + } + + p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t)); + if (p == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + + s->proxy = p; + + p->upstream.sockaddr = peer->sockaddr; + p->upstream.socklen = peer->socklen; + p->upstream.name = &peer->name; + p->upstream.get = ngx_event_get_peer; + p->upstream.log = s->connection->log; + p->upstream.log_error = NGX_ERROR_ERR; + + rc = ngx_event_connect_peer(&p->upstream); + + if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + ngx_add_timer(p->upstream.connection->read, cscf->timeout); + + p->upstream.connection->data = s; + p->upstream.connection->pool = s->connection->pool; + + s->connection->read->handler = ngx_mail_proxy_block_read; + p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler; + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + s->proxy->buffer = ngx_create_temp_buf(s->connection->pool, + pcf->buffer_size); + if (s->proxy->buffer == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + s->out.len = 0; + + switch (s->protocol) { + + case NGX_MAIL_POP3_PROTOCOL: + p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler; + s->mail_state = ngx_pop3_start; + break; + + case NGX_MAIL_IMAP_PROTOCOL: + p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler; + s->mail_state = ngx_imap_start; + break; + + default: /* NGX_MAIL_SMTP_PROTOCOL */ + p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler; + s->mail_state = ngx_smtp_start; + break; + } +} + + +static void +ngx_mail_proxy_block_read(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy block read"); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + c = rev->data; + s = c->data; + + ngx_mail_proxy_close_session(s); + } +} + + +static void +ngx_mail_proxy_pop3_handler(ngx_event_t *rev) +{ + u_char *p; + ngx_int_t rc; + ngx_str_t line; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_proxy_conf_t *pcf; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy pop3 auth handler"); + + c = rev->data; + s = c->data; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "upstream timed out"); + c->timedout = 1; + ngx_mail_proxy_internal_server_error(s); + return; + } + + rc = ngx_mail_proxy_read_response(s, 0); + + if (rc == NGX_AGAIN) { + return; + } + + if (rc == NGX_ERROR) { + ngx_mail_proxy_upstream_error(s); + return; + } + + switch (s->mail_state) { + + case ngx_pop3_start: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send user"); + + s->connection->log->action = "sending user name to upstream"; + + line.len = sizeof("USER ") - 1 + s->login.len + 2; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, "USER ", sizeof("USER ") - 1); + p = ngx_cpymem(p, s->login.data, s->login.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_pop3_user; + break; + + case ngx_pop3_user: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send pass"); + + s->connection->log->action = "sending password to upstream"; + + line.len = sizeof("PASS ") - 1 + s->passwd.len + 2; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, "PASS ", sizeof("PASS ") - 1); + p = ngx_cpymem(p, s->passwd.data, s->passwd.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_pop3_passwd; + break; + + case ngx_pop3_passwd: + s->connection->read->handler = ngx_mail_proxy_handler; + s->connection->write->handler = ngx_mail_proxy_handler; + rev->handler = ngx_mail_proxy_handler; + c->write->handler = ngx_mail_proxy_handler; + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); + ngx_del_timer(c->read); + + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + + ngx_mail_proxy_handler(s->connection->write); + + return; + + default: +#if (NGX_SUPPRESS_WARN) + ngx_str_null(&line); +#endif + break; + } + + if (c->send(c, line.data, line.len) < (ssize_t) line.len) { + /* + * we treat the incomplete sending as NGX_ERROR + * because it is very strange here + */ + ngx_mail_proxy_internal_server_error(s); + return; + } + + s->proxy->buffer->pos = s->proxy->buffer->start; + s->proxy->buffer->last = s->proxy->buffer->start; +} + + +static void +ngx_mail_proxy_imap_handler(ngx_event_t *rev) +{ + u_char *p; + ngx_int_t rc; + ngx_str_t line; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_proxy_conf_t *pcf; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy imap auth handler"); + + c = rev->data; + s = c->data; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "upstream timed out"); + c->timedout = 1; + ngx_mail_proxy_internal_server_error(s); + return; + } + + rc = ngx_mail_proxy_read_response(s, s->mail_state); + + if (rc == NGX_AGAIN) { + return; + } + + if (rc == NGX_ERROR) { + ngx_mail_proxy_upstream_error(s); + return; + } + + switch (s->mail_state) { + + case ngx_imap_start: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send login"); + + s->connection->log->action = "sending LOGIN command to upstream"; + + line.len = s->tag.len + sizeof("LOGIN ") - 1 + + 1 + NGX_SIZE_T_LEN + 1 + 2; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + line.len = ngx_sprintf(line.data, "%VLOGIN {%uz}" CRLF, + &s->tag, s->login.len) + - line.data; + + s->mail_state = ngx_imap_login; + break; + + case ngx_imap_login: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send user"); + + s->connection->log->action = "sending user name to upstream"; + + line.len = s->login.len + 1 + 1 + NGX_SIZE_T_LEN + 1 + 2; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + line.len = ngx_sprintf(line.data, "%V {%uz}" CRLF, + &s->login, s->passwd.len) + - line.data; + + s->mail_state = ngx_imap_user; + break; + + case ngx_imap_user: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send passwd"); + + s->connection->log->action = "sending password to upstream"; + + line.len = s->passwd.len + 2; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, s->passwd.data, s->passwd.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_imap_passwd; + break; + + case ngx_imap_passwd: + s->connection->read->handler = ngx_mail_proxy_handler; + s->connection->write->handler = ngx_mail_proxy_handler; + rev->handler = ngx_mail_proxy_handler; + c->write->handler = ngx_mail_proxy_handler; + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); + ngx_del_timer(c->read); + + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + + ngx_mail_proxy_handler(s->connection->write); + + return; + + default: +#if (NGX_SUPPRESS_WARN) + ngx_str_null(&line); +#endif + break; + } + + if (c->send(c, line.data, line.len) < (ssize_t) line.len) { + /* + * we treat the incomplete sending as NGX_ERROR + * because it is very strange here + */ + ngx_mail_proxy_internal_server_error(s); + return; + } + + s->proxy->buffer->pos = s->proxy->buffer->start; + s->proxy->buffer->last = s->proxy->buffer->start; +} + + +static void +ngx_mail_proxy_smtp_handler(ngx_event_t *rev) +{ + u_char *p; + ngx_int_t rc; + ngx_str_t line; + ngx_buf_t *b; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_proxy_conf_t *pcf; + ngx_mail_core_srv_conf_t *cscf; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy smtp auth handler"); + + c = rev->data; + s = c->data; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "upstream timed out"); + c->timedout = 1; + ngx_mail_proxy_internal_server_error(s); + return; + } + + rc = ngx_mail_proxy_read_response(s, s->mail_state); + + if (rc == NGX_AGAIN) { + return; + } + + if (rc == NGX_ERROR) { + ngx_mail_proxy_upstream_error(s); + return; + } + + switch (s->mail_state) { + + case ngx_smtp_start: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send ehlo"); + + s->connection->log->action = "sending HELO/EHLO to upstream"; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + line.len = sizeof("HELO ") - 1 + cscf->server_name.len + 2; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + p = ngx_cpymem(line.data, + ((s->esmtp || pcf->xclient) ? "EHLO " : "HELO "), + sizeof("HELO ") - 1); + + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + *p++ = CR; *p = LF; + + if (pcf->xclient) { + s->mail_state = ngx_smtp_helo_xclient; + + } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { + s->mail_state = ngx_smtp_helo_from; + + } else { + s->mail_state = ngx_smtp_helo; + } + + break; + + case ngx_smtp_helo_xclient: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send xclient"); + + s->connection->log->action = "sending XCLIENT to upstream"; + + line.len = sizeof("XCLIENT ADDR= LOGIN= NAME=" + CRLF) - 1 + + s->connection->addr_text.len + s->login.len + s->host.len; + +#if (NGX_HAVE_INET6) + if (s->connection->sockaddr->sa_family == AF_INET6) { + line.len += sizeof("IPV6:") - 1; + } +#endif + + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, "XCLIENT ADDR=", sizeof("XCLIENT ADDR=") - 1); + +#if (NGX_HAVE_INET6) + if (s->connection->sockaddr->sa_family == AF_INET6) { + p = ngx_cpymem(p, "IPV6:", sizeof("IPV6:") - 1); + } +#endif + + p = ngx_copy(p, s->connection->addr_text.data, + s->connection->addr_text.len); + + if (s->login.len) { + p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1); + p = ngx_copy(p, s->login.data, s->login.len); + } + + p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1); + p = ngx_copy(p, s->host.data, s->host.len); + + *p++ = CR; *p++ = LF; + + line.len = p - line.data; + + if (s->smtp_helo.len) { + s->mail_state = ngx_smtp_xclient_helo; + + } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { + s->mail_state = ngx_smtp_xclient_from; + + } else { + s->mail_state = ngx_smtp_xclient; + } + + break; + + case ngx_smtp_xclient_helo: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send client ehlo"); + + s->connection->log->action = "sending client HELO/EHLO to upstream"; + + line.len = sizeof("HELO " CRLF) - 1 + s->smtp_helo.len; + + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + line.len = ngx_sprintf(line.data, + ((s->esmtp) ? "EHLO %V" CRLF : "HELO %V" CRLF), + &s->smtp_helo) + - line.data; + + s->mail_state = (s->auth_method == NGX_MAIL_AUTH_NONE) ? + ngx_smtp_helo_from : ngx_smtp_helo; + + break; + + case ngx_smtp_helo_from: + case ngx_smtp_xclient_from: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send mail from"); + + s->connection->log->action = "sending MAIL FROM to upstream"; + + line.len = s->smtp_from.len + sizeof(CRLF) - 1; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, s->smtp_from.data, s->smtp_from.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_smtp_from; + + break; + + case ngx_smtp_from: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send rcpt to"); + + s->connection->log->action = "sending RCPT TO to upstream"; + + line.len = s->smtp_to.len + sizeof(CRLF) - 1; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, s->smtp_to.data, s->smtp_to.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_smtp_to; + + break; + + case ngx_smtp_helo: + case ngx_smtp_xclient: + case ngx_smtp_to: + + b = s->proxy->buffer; + + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + b->pos = b->start; + + } else { + ngx_memcpy(b->start, smtp_auth_ok, sizeof(smtp_auth_ok) - 1); + b->last = b->start + sizeof(smtp_auth_ok) - 1; + } + + s->connection->read->handler = ngx_mail_proxy_handler; + s->connection->write->handler = ngx_mail_proxy_handler; + rev->handler = ngx_mail_proxy_handler; + c->write->handler = ngx_mail_proxy_handler; + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); + ngx_del_timer(c->read); + + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + + if (s->buffer->pos == s->buffer->last) { + ngx_mail_proxy_handler(s->connection->write); + + } else { + ngx_mail_proxy_handler(c->write); + } + + return; + + default: +#if (NGX_SUPPRESS_WARN) + ngx_str_null(&line); +#endif + break; + } + + if (c->send(c, line.data, line.len) < (ssize_t) line.len) { + /* + * we treat the incomplete sending as NGX_ERROR + * because it is very strange here + */ + ngx_mail_proxy_internal_server_error(s); + return; + } + + s->proxy->buffer->pos = s->proxy->buffer->start; + s->proxy->buffer->last = s->proxy->buffer->start; +} + + +static void +ngx_mail_proxy_dummy_handler(ngx_event_t *wev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler"); + + if (ngx_handle_write_event(wev, 0) != NGX_OK) { + c = wev->data; + s = c->data; + + ngx_mail_proxy_close_session(s); + } +} + + +static ngx_int_t +ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state) +{ + u_char *p, *m; + ssize_t n; + ngx_buf_t *b; + ngx_mail_proxy_conf_t *pcf; + + s->connection->log->action = "reading response from upstream"; + + b = s->proxy->buffer; + + n = s->proxy->upstream.connection->recv(s->proxy->upstream.connection, + b->last, b->end - b->last); + + if (n == NGX_ERROR || n == 0) { + return NGX_ERROR; + } + + if (n == NGX_AGAIN) { + return NGX_AGAIN; + } + + b->last += n; + + if (b->last - b->pos < 4) { + return NGX_AGAIN; + } + + if (*(b->last - 2) != CR || *(b->last - 1) != LF) { + if (b->last == b->end) { + *(b->last - 1) = '\0'; + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "upstream sent too long response line: \"%s\"", + b->pos); + return NGX_ERROR; + } + + return NGX_AGAIN; + } + + p = b->pos; + + switch (s->protocol) { + + case NGX_MAIL_POP3_PROTOCOL: + if (p[0] == '+' && p[1] == 'O' && p[2] == 'K') { + return NGX_OK; + } + break; + + case NGX_MAIL_IMAP_PROTOCOL: + switch (state) { + + case ngx_imap_start: + if (p[0] == '*' && p[1] == ' ' && p[2] == 'O' && p[3] == 'K') { + return NGX_OK; + } + break; + + case ngx_imap_login: + case ngx_imap_user: + if (p[0] == '+') { + return NGX_OK; + } + break; + + case ngx_imap_passwd: + if (ngx_strncmp(p, s->tag.data, s->tag.len) == 0) { + p += s->tag.len; + if (p[0] == 'O' && p[1] == 'K') { + return NGX_OK; + } + } + break; + } + + break; + + default: /* NGX_MAIL_SMTP_PROTOCOL */ + + if (p[3] == '-') { + /* multiline reply, check if we got last line */ + + m = b->last - (sizeof(CRLF "200" CRLF) - 1); + + while (m > p) { + if (m[0] == CR && m[1] == LF) { + break; + } + + m--; + } + + if (m <= p || m[5] == '-') { + return NGX_AGAIN; + } + } + + switch (state) { + + case ngx_smtp_start: + if (p[0] == '2' && p[1] == '2' && p[2] == '0') { + return NGX_OK; + } + break; + + case ngx_smtp_helo: + case ngx_smtp_helo_xclient: + case ngx_smtp_helo_from: + case ngx_smtp_from: + if (p[0] == '2' && p[1] == '5' && p[2] == '0') { + return NGX_OK; + } + break; + + case ngx_smtp_xclient: + case ngx_smtp_xclient_from: + case ngx_smtp_xclient_helo: + if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') { + return NGX_OK; + } + break; + + case ngx_smtp_to: + return NGX_OK; + } + + break; + } + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + if (pcf->pass_error_message == 0) { + *(b->last - 2) = '\0'; + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "upstream sent invalid response: \"%s\"", p); + return NGX_ERROR; + } + + s->out.len = b->last - p - 2; + s->out.data = p; + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "upstream sent invalid response: \"%V\"", &s->out); + + s->out.len = b->last - b->pos; + s->out.data = b->pos; + + return NGX_ERROR; +} + + +static void +ngx_mail_proxy_handler(ngx_event_t *ev) +{ + char *action, *recv_action, *send_action; + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_uint_t do_write; + ngx_connection_t *c, *src, *dst; + ngx_mail_session_t *s; + ngx_mail_proxy_conf_t *pcf; + + c = ev->data; + s = c->data; + + if (ev->timedout) { + c->log->action = "proxying"; + + if (c == s->connection) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "client timed out"); + c->timedout = 1; + + } else { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "upstream timed out"); + } + + ngx_mail_proxy_close_session(s); + return; + } + + if (c == s->connection) { + if (ev->write) { + recv_action = "proxying and reading from upstream"; + send_action = "proxying and sending to client"; + src = s->proxy->upstream.connection; + dst = c; + b = s->proxy->buffer; + + } else { + recv_action = "proxying and reading from client"; + send_action = "proxying and sending to upstream"; + src = c; + dst = s->proxy->upstream.connection; + b = s->buffer; + } + + } else { + if (ev->write) { + recv_action = "proxying and reading from client"; + send_action = "proxying and sending to upstream"; + src = s->connection; + dst = c; + b = s->buffer; + + } else { + recv_action = "proxying and reading from upstream"; + send_action = "proxying and sending to client"; + src = c; + dst = s->connection; + b = s->proxy->buffer; + } + } + + do_write = ev->write ? 1 : 0; + + ngx_log_debug3(NGX_LOG_DEBUG_MAIL, ev->log, 0, + "mail proxy handler: %d, #%d > #%d", + do_write, src->fd, dst->fd); + + for ( ;; ) { + + if (do_write) { + + size = b->last - b->pos; + + if (size && dst->write->ready) { + c->log->action = send_action; + + n = dst->send(dst, b->pos, size); + + if (n == NGX_ERROR) { + ngx_mail_proxy_close_session(s); + return; + } + + if (n > 0) { + b->pos += n; + + if (b->pos == b->last) { + b->pos = b->start; + b->last = b->start; + } + } + } + } + + size = b->end - b->last; + + if (size && src->read->ready) { + c->log->action = recv_action; + + n = src->recv(src, b->last, size); + + if (n == NGX_AGAIN || n == 0) { + break; + } + + if (n > 0) { + do_write = 1; + b->last += n; + + continue; + } + + if (n == NGX_ERROR) { + src->read->eof = 1; + } + } + + break; + } + + c->log->action = "proxying"; + + if ((s->connection->read->eof && s->buffer->pos == s->buffer->last) + || (s->proxy->upstream.connection->read->eof + && s->proxy->buffer->pos == s->proxy->buffer->last) + || (s->connection->read->eof + && s->proxy->upstream.connection->read->eof)) + { + action = c->log->action; + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxied session done"); + c->log->action = action; + + ngx_mail_proxy_close_session(s); + return; + } + + if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { + ngx_mail_proxy_close_session(s); + return; + } + + if (ngx_handle_read_event(dst->read, 0) != NGX_OK) { + ngx_mail_proxy_close_session(s); + return; + } + + if (ngx_handle_write_event(src->write, 0) != NGX_OK) { + ngx_mail_proxy_close_session(s); + return; + } + + if (ngx_handle_read_event(src->read, 0) != NGX_OK) { + ngx_mail_proxy_close_session(s); + return; + } + + if (c == s->connection) { + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + ngx_add_timer(c->read, pcf->timeout); + } +} + + +static void +ngx_mail_proxy_upstream_error(ngx_mail_session_t *s) +{ + if (s->proxy->upstream.connection) { + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "close mail proxy connection: %d", + s->proxy->upstream.connection->fd); + + ngx_close_connection(s->proxy->upstream.connection); + } + + if (s->out.len == 0) { + ngx_mail_session_internal_server_error(s); + return; + } + + s->quit = 1; + ngx_mail_send(s->connection->write); +} + + +static void +ngx_mail_proxy_internal_server_error(ngx_mail_session_t *s) +{ + if (s->proxy->upstream.connection) { + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "close mail proxy connection: %d", + s->proxy->upstream.connection->fd); + + ngx_close_connection(s->proxy->upstream.connection); + } + + ngx_mail_session_internal_server_error(s); +} + + +static void +ngx_mail_proxy_close_session(ngx_mail_session_t *s) +{ + if (s->proxy->upstream.connection) { + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "close mail proxy connection: %d", + s->proxy->upstream.connection->fd); + + ngx_close_connection(s->proxy->upstream.connection); + } + + ngx_mail_close_connection(s->connection); +} + + +static void * +ngx_mail_proxy_create_conf(ngx_conf_t *cf) +{ + ngx_mail_proxy_conf_t *pcf; + + pcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_proxy_conf_t)); + if (pcf == NULL) { + return NULL; + } + + pcf->enable = NGX_CONF_UNSET; + pcf->pass_error_message = NGX_CONF_UNSET; + pcf->xclient = NGX_CONF_UNSET; + pcf->buffer_size = NGX_CONF_UNSET_SIZE; + pcf->timeout = NGX_CONF_UNSET_MSEC; + + return pcf; +} + + +static char * +ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_proxy_conf_t *prev = parent; + ngx_mail_proxy_conf_t *conf = child; + + ngx_conf_merge_value(conf->enable, prev->enable, 0); + ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0); + ngx_conf_merge_value(conf->xclient, prev->xclient, 1); + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, + (size_t) ngx_pagesize); + ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail_smtp_handler.c b/hm_nginx/src/mail/ngx_mail_smtp_handler.c new file mode 100644 index 0000000..46d703e --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_smtp_handler.c @@ -0,0 +1,857 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx); +static void ngx_mail_smtp_resolve_name(ngx_event_t *rev); +static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx); +static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c); +static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev); +static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, + ngx_connection_t *c); + +static ngx_int_t ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_starttls(ngx_mail_session_t *s, + ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c); + +static ngx_int_t ngx_mail_smtp_discard_command(ngx_mail_session_t *s, + ngx_connection_t *c, char *err); +static void ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s, + ngx_connection_t *c, char *err); + + +static u_char smtp_ok[] = "250 2.0.0 OK" CRLF; +static u_char smtp_bye[] = "221 2.0.0 Bye" CRLF; +static u_char smtp_starttls[] = "220 2.0.0 Start TLS" CRLF; +static u_char smtp_next[] = "334 " CRLF; +static u_char smtp_username[] = "334 VXNlcm5hbWU6" CRLF; +static u_char smtp_password[] = "334 UGFzc3dvcmQ6" CRLF; +static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF; +static u_char smtp_invalid_pipelining[] = + "503 5.5.0 Improper use of SMTP command pipelining" CRLF; +static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF; +static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF; +static u_char smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF; + + +static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]"); +static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]"); + + +void +ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_resolver_ctx_t *ctx; + ngx_mail_core_srv_conf_t *cscf; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (cscf->resolver == NULL) { + s->host = smtp_unavailable; + ngx_mail_smtp_greeting(s, c); + return; + } + +#if (NGX_HAVE_UNIX_DOMAIN) + if (c->sockaddr->sa_family == AF_UNIX) { + s->host = smtp_tempunavail; + ngx_mail_smtp_greeting(s, c); + return; + } +#endif + + c->log->action = "in resolving client address"; + + ctx = ngx_resolve_start(cscf->resolver, NULL); + if (ctx == NULL) { + ngx_mail_close_connection(c); + return; + } + + ctx->addr.sockaddr = c->sockaddr; + ctx->addr.socklen = c->socklen; + ctx->handler = ngx_mail_smtp_resolve_addr_handler; + ctx->data = s; + ctx->timeout = cscf->resolver_timeout; + + if (ngx_resolve_addr(ctx) != NGX_OK) { + ngx_mail_close_connection(c); + } +} + + +static void +ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + s = ctx->data; + c = s->connection; + + if (ctx->state) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "%V could not be resolved (%i: %s)", + &c->addr_text, ctx->state, + ngx_resolver_strerror(ctx->state)); + + if (ctx->state == NGX_RESOLVE_NXDOMAIN) { + s->host = smtp_unavailable; + + } else { + s->host = smtp_tempunavail; + } + + ngx_resolve_addr_done(ctx); + + ngx_mail_smtp_greeting(s, s->connection); + + return; + } + + c->log->action = "in resolving client hostname"; + + s->host.data = ngx_pstrdup(c->pool, &ctx->name); + if (s->host.data == NULL) { + ngx_resolve_addr_done(ctx); + ngx_mail_close_connection(c); + return; + } + + s->host.len = ctx->name.len; + + ngx_resolve_addr_done(ctx); + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "address resolved: %V", &s->host); + + c->read->handler = ngx_mail_smtp_resolve_name; + + ngx_post_event(c->read, &ngx_posted_events); +} + + +static void +ngx_mail_smtp_resolve_name(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_resolver_ctx_t *ctx; + ngx_mail_core_srv_conf_t *cscf; + + c = rev->data; + s = c->data; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + ctx = ngx_resolve_start(cscf->resolver, NULL); + if (ctx == NULL) { + ngx_mail_close_connection(c); + return; + } + + ctx->name = s->host; + ctx->handler = ngx_mail_smtp_resolve_name_handler; + ctx->data = s; + ctx->timeout = cscf->resolver_timeout; + + if (ngx_resolve_name(ctx) != NGX_OK) { + ngx_mail_close_connection(c); + } +} + + +static void +ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx) +{ + ngx_uint_t i; + ngx_connection_t *c; + ngx_mail_session_t *s; + + s = ctx->data; + c = s->connection; + + if (ctx->state) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "\"%V\" could not be resolved (%i: %s)", + &ctx->name, ctx->state, + ngx_resolver_strerror(ctx->state)); + + if (ctx->state == NGX_RESOLVE_NXDOMAIN) { + s->host = smtp_unavailable; + + } else { + s->host = smtp_tempunavail; + } + + } else { + +#if (NGX_DEBUG) + { + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_str_t addr; + + addr.data = text; + + for (i = 0; i < ctx->naddrs; i++) { + addr.len = ngx_sock_ntop(ctx->addrs[i].sockaddr, + ctx->addrs[i].socklen, + text, NGX_SOCKADDR_STRLEN, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "name was resolved to %V", &addr); + } + } +#endif + + for (i = 0; i < ctx->naddrs; i++) { + if (ngx_cmp_sockaddr(ctx->addrs[i].sockaddr, ctx->addrs[i].socklen, + c->sockaddr, c->socklen, 0) + == NGX_OK) + { + goto found; + } + } + + s->host = smtp_unavailable; + } + +found: + + ngx_resolve_name_done(ctx); + + ngx_mail_smtp_greeting(s, c); +} + + +static void +ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_msec_t timeout; + ngx_mail_core_srv_conf_t *cscf; + ngx_mail_smtp_srv_conf_t *sscf; + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "smtp greeting for \"%V\"", &s->host); + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout; + ngx_add_timer(c->read, timeout); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + if (sscf->greeting_delay) { + c->read->handler = ngx_mail_smtp_invalid_pipelining; + return; + } + + c->read->handler = ngx_mail_smtp_init_protocol; + + s->out = sscf->greeting; + + ngx_mail_send(c->write); +} + + +static void +ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + ngx_mail_smtp_srv_conf_t *sscf; + + c = rev->data; + s = c->data; + + c->log->action = "in delay pipelining state"; + + if (rev->timedout) { + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "delay greeting"); + + rev->timedout = 0; + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + c->read->handler = ngx_mail_smtp_init_protocol; + + ngx_add_timer(c->read, cscf->timeout); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + s->out = sscf->greeting; + + } else { + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "invalid pipelining"); + + if (s->buffer == NULL) { + if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) { + return; + } + } + + if (ngx_mail_smtp_discard_command(s, c, + "client was rejected before greeting: \"%V\"") + != NGX_OK) + { + return; + } + + ngx_str_set(&s->out, smtp_invalid_pipelining); + s->quit = 1; + } + + ngx_mail_send(c->write); +} + + +void +ngx_mail_smtp_init_protocol(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + + c->log->action = "in auth state"; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + s = c->data; + + if (s->buffer == NULL) { + if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) { + return; + } + } + + s->mail_state = ngx_smtp_start; + c->read->handler = ngx_mail_smtp_auth_state; + + ngx_mail_smtp_auth_state(rev); +} + + +static ngx_int_t +ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_mail_smtp_srv_conf_t *sscf; + + if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) { + ngx_mail_session_internal_server_error(s); + return NGX_ERROR; + } + + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + s->buffer = ngx_create_temp_buf(c->pool, sscf->client_buffer_size); + if (s->buffer == NULL) { + ngx_mail_session_internal_server_error(s); + return NGX_ERROR; + } + + return NGX_OK; +} + + +void +ngx_mail_smtp_auth_state(ngx_event_t *rev) +{ + ngx_int_t rc; + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp auth state"); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + if (s->out.len) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy"); + s->blocked = 1; + return; + } + + s->blocked = 0; + + rc = ngx_mail_read_command(s, c); + + if (rc == NGX_AGAIN || rc == NGX_ERROR) { + return; + } + + ngx_str_set(&s->out, smtp_ok); + + if (rc == NGX_OK) { + switch (s->mail_state) { + + case ngx_smtp_start: + + switch (s->command) { + + case NGX_SMTP_HELO: + case NGX_SMTP_EHLO: + rc = ngx_mail_smtp_helo(s, c); + break; + + case NGX_SMTP_AUTH: + rc = ngx_mail_smtp_auth(s, c); + break; + + case NGX_SMTP_QUIT: + s->quit = 1; + ngx_str_set(&s->out, smtp_bye); + break; + + case NGX_SMTP_MAIL: + rc = ngx_mail_smtp_mail(s, c); + break; + + case NGX_SMTP_RCPT: + rc = ngx_mail_smtp_rcpt(s, c); + break; + + case NGX_SMTP_RSET: + rc = ngx_mail_smtp_rset(s, c); + break; + + case NGX_SMTP_NOOP: + break; + + case NGX_SMTP_STARTTLS: + rc = ngx_mail_smtp_starttls(s, c); + ngx_str_set(&s->out, smtp_starttls); + break; + + default: + rc = NGX_MAIL_PARSE_INVALID_COMMAND; + break; + } + + break; + + case ngx_smtp_auth_login_username: + rc = ngx_mail_auth_login_username(s, c, 0); + + ngx_str_set(&s->out, smtp_password); + s->mail_state = ngx_smtp_auth_login_password; + break; + + case ngx_smtp_auth_login_password: + rc = ngx_mail_auth_login_password(s, c); + break; + + case ngx_smtp_auth_plain: + rc = ngx_mail_auth_plain(s, c, 0); + break; + + case ngx_smtp_auth_cram_md5: + rc = ngx_mail_auth_cram_md5(s, c); + break; + } + } + + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + + switch (rc) { + + case NGX_DONE: + ngx_mail_auth(s, c); + return; + + case NGX_ERROR: + ngx_mail_session_internal_server_error(s); + return; + + case NGX_MAIL_PARSE_INVALID_COMMAND: + s->mail_state = ngx_smtp_start; + s->state = 0; + ngx_str_set(&s->out, smtp_invalid_command); + + /* fall through */ + + case NGX_OK: + s->args.nelts = 0; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } + + if (s->state) { + s->arg_start = s->buffer->pos; + } + + ngx_mail_send(c->write); + } +} + + +static ngx_int_t +ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + ngx_mail_smtp_srv_conf_t *sscf; + + if (s->args.nelts != 1) { + ngx_str_set(&s->out, smtp_invalid_argument); + s->state = 0; + return NGX_OK; + } + + arg = s->args.elts; + + s->smtp_helo.len = arg[0].len; + + s->smtp_helo.data = ngx_pnalloc(c->pool, arg[0].len); + if (s->smtp_helo.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); + + ngx_str_null(&s->smtp_from); + ngx_str_null(&s->smtp_to); + + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + if (s->command == NGX_SMTP_HELO) { + s->out = sscf->server_name; + + } else { + s->esmtp = 1; + +#if (NGX_MAIL_SSL) + + if (c->ssl == NULL) { + ngx_mail_ssl_conf_t *sslcf; + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { + s->out = sscf->starttls_capability; + return NGX_OK; + } + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + s->out = sscf->starttls_only_capability; + return NGX_OK; + } + } +#endif + + s->out = sscf->capability; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_int_t rc; + ngx_mail_core_srv_conf_t *cscf; + ngx_mail_smtp_srv_conf_t *sscf; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + if (s->args.nelts == 0) { + ngx_str_set(&s->out, smtp_invalid_argument); + s->state = 0; + return NGX_OK; + } + + rc = ngx_mail_auth_parse(s, c); + + switch (rc) { + + case NGX_MAIL_AUTH_LOGIN: + + ngx_str_set(&s->out, smtp_username); + s->mail_state = ngx_smtp_auth_login_username; + + return NGX_OK; + + case NGX_MAIL_AUTH_LOGIN_USERNAME: + + ngx_str_set(&s->out, smtp_password); + s->mail_state = ngx_smtp_auth_login_password; + + return ngx_mail_auth_login_username(s, c, 1); + + case NGX_MAIL_AUTH_PLAIN: + + ngx_str_set(&s->out, smtp_next); + s->mail_state = ngx_smtp_auth_plain; + + return NGX_OK; + + case NGX_MAIL_AUTH_CRAM_MD5: + + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + if (!(sscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (s->salt.data == NULL) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (ngx_mail_salt(s, c, cscf) != NGX_OK) { + return NGX_ERROR; + } + } + + if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4) == NGX_OK) { + s->mail_state = ngx_smtp_auth_cram_md5; + return NGX_OK; + } + + return NGX_ERROR; + } + + return rc; +} + + +static ngx_int_t +ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg, cmd; + ngx_mail_smtp_srv_conf_t *sscf; + + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + if (!(sscf->auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) { + ngx_mail_smtp_log_rejected_command(s, c, "client was rejected: \"%V\""); + ngx_str_set(&s->out, smtp_auth_required); + return NGX_OK; + } + + /* auth none */ + + if (s->smtp_from.len) { + ngx_str_set(&s->out, smtp_bad_sequence); + return NGX_OK; + } + + if (s->args.nelts == 0) { + ngx_str_set(&s->out, smtp_invalid_argument); + return NGX_OK; + } + + arg = s->args.elts; + arg += s->args.nelts - 1; + + cmd.len = arg->data + arg->len - s->cmd.data; + cmd.data = s->cmd.data; + + s->smtp_from.len = cmd.len; + + s->smtp_from.data = ngx_pnalloc(c->pool, cmd.len); + if (s->smtp_from.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len); + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "smtp mail from:\"%V\"", &s->smtp_from); + + ngx_str_set(&s->out, smtp_ok); + + return NGX_OK; +} + + +static ngx_int_t +ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg, cmd; + + if (s->smtp_from.len == 0) { + ngx_str_set(&s->out, smtp_bad_sequence); + return NGX_OK; + } + + if (s->args.nelts == 0) { + ngx_str_set(&s->out, smtp_invalid_argument); + return NGX_OK; + } + + arg = s->args.elts; + arg += s->args.nelts - 1; + + cmd.len = arg->data + arg->len - s->cmd.data; + cmd.data = s->cmd.data; + + s->smtp_to.len = cmd.len; + + s->smtp_to.data = ngx_pnalloc(c->pool, cmd.len); + if (s->smtp_to.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len); + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "smtp rcpt to:\"%V\"", &s->smtp_to); + + s->auth_method = NGX_MAIL_AUTH_NONE; + + return NGX_DONE; +} + + +static ngx_int_t +ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_null(&s->smtp_from); + ngx_str_null(&s->smtp_to); + ngx_str_set(&s->out, smtp_ok); + + return NGX_OK; +} + + +static ngx_int_t +ngx_mail_smtp_starttls(ngx_mail_session_t *s, ngx_connection_t *c) +{ +#if (NGX_MAIL_SSL) + ngx_mail_ssl_conf_t *sslcf; + + if (c->ssl == NULL) { + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + if (sslcf->starttls) { + + /* + * RFC3207 requires us to discard any knowledge + * obtained from client before STARTTLS. + */ + + ngx_str_null(&s->smtp_helo); + ngx_str_null(&s->smtp_from); + ngx_str_null(&s->smtp_to); + + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + + c->read->handler = ngx_mail_starttls_handler; + return NGX_OK; + } + } + +#endif + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} + + +static ngx_int_t +ngx_mail_smtp_discard_command(ngx_mail_session_t *s, ngx_connection_t *c, + char *err) +{ + ssize_t n; + + n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last); + + if (n == NGX_ERROR || n == 0) { + ngx_mail_close_connection(c); + return NGX_ERROR; + } + + if (n > 0) { + s->buffer->last += n; + } + + if (n == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return NGX_ERROR; + } + + return NGX_AGAIN; + } + + ngx_mail_smtp_log_rejected_command(s, c, err); + + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + + return NGX_OK; +} + + +static void +ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s, ngx_connection_t *c, + char *err) +{ + u_char ch; + ngx_str_t cmd; + ngx_uint_t i; + + if (c->log->log_level < NGX_LOG_INFO) { + return; + } + + cmd.len = s->buffer->last - s->buffer->start; + cmd.data = s->buffer->start; + + for (i = 0; i < cmd.len; i++) { + ch = cmd.data[i]; + + if (ch != CR && ch != LF) { + continue; + } + + cmd.data[i] = '_'; + } + + cmd.len = i; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, err, &cmd); +} diff --git a/hm_nginx/src/mail/ngx_mail_smtp_module.c b/hm_nginx/src/mail/ngx_mail_smtp_module.c new file mode 100644 index 0000000..d5bb51c --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_smtp_module.c @@ -0,0 +1,309 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include +#include + + +static void *ngx_mail_smtp_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_conf_bitmask_t ngx_mail_smtp_auth_methods[] = { + { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, + { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, + { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, + { ngx_string("none"), NGX_MAIL_AUTH_NONE_ENABLED }, + { ngx_null_string, 0 } +}; + + +static ngx_str_t ngx_mail_smtp_auth_methods_names[] = { + ngx_string("PLAIN"), + ngx_string("LOGIN"), + ngx_null_string, /* APOP */ + ngx_string("CRAM-MD5"), + ngx_null_string /* NONE */ +}; + + +static ngx_mail_protocol_t ngx_mail_smtp_protocol = { + ngx_string("smtp"), + { 25, 465, 587, 0 }, + NGX_MAIL_SMTP_PROTOCOL, + + ngx_mail_smtp_init_session, + ngx_mail_smtp_init_protocol, + ngx_mail_smtp_parse_command, + ngx_mail_smtp_auth_state, + + ngx_string("451 4.3.2 Internal server error" CRLF), + ngx_string("421 4.7.1 SSL certificate error" CRLF), + ngx_string("421 4.7.1 No required SSL certificate" CRLF) +}; + + +static ngx_command_t ngx_mail_smtp_commands[] = { + + { ngx_string("smtp_client_buffer"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, client_buffer_size), + NULL }, + + { ngx_string("smtp_greeting_delay"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, greeting_delay), + NULL }, + + { ngx_string("smtp_capabilities"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_capabilities, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, capabilities), + NULL }, + + { ngx_string("smtp_auth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, auth_methods), + &ngx_mail_smtp_auth_methods }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_smtp_module_ctx = { + &ngx_mail_smtp_protocol, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_smtp_create_srv_conf, /* create server configuration */ + ngx_mail_smtp_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_smtp_module = { + NGX_MODULE_V1, + &ngx_mail_smtp_module_ctx, /* module context */ + ngx_mail_smtp_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_smtp_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_smtp_srv_conf_t *sscf; + + sscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_smtp_srv_conf_t)); + if (sscf == NULL) { + return NULL; + } + + sscf->client_buffer_size = NGX_CONF_UNSET_SIZE; + sscf->greeting_delay = NGX_CONF_UNSET_MSEC; + + if (ngx_array_init(&sscf->capabilities, cf->pool, 4, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + + return sscf; +} + + +static char * +ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_smtp_srv_conf_t *prev = parent; + ngx_mail_smtp_srv_conf_t *conf = child; + + u_char *p, *auth, *last; + size_t size; + ngx_str_t *c; + ngx_uint_t i, m, auth_enabled; + ngx_mail_core_srv_conf_t *cscf; + + ngx_conf_merge_size_value(conf->client_buffer_size, + prev->client_buffer_size, + (size_t) ngx_pagesize); + + ngx_conf_merge_msec_value(conf->greeting_delay, + prev->greeting_delay, 0); + + ngx_conf_merge_bitmask_value(conf->auth_methods, + prev->auth_methods, + (NGX_CONF_BITMASK_SET + |NGX_MAIL_AUTH_PLAIN_ENABLED + |NGX_MAIL_AUTH_LOGIN_ENABLED)); + + + cscf = ngx_mail_conf_get_module_srv_conf(cf, ngx_mail_core_module); + + size = sizeof("220 ESMTP ready" CRLF) - 1 + cscf->server_name.len; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->greeting.len = size; + conf->greeting.data = p; + + *p++ = '2'; *p++ = '2'; *p++ = '0'; *p++ = ' '; + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + ngx_memcpy(p, " ESMTP ready" CRLF, sizeof(" ESMTP ready" CRLF) - 1); + + + size = sizeof("250 " CRLF) - 1 + cscf->server_name.len; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->server_name.len = size; + conf->server_name.data = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + *p++ = CR; *p = LF; + + + if (conf->capabilities.nelts == 0) { + conf->capabilities = prev->capabilities; + } + + size = sizeof("250-") - 1 + cscf->server_name.len + sizeof(CRLF) - 1; + + c = conf->capabilities.elts; + for (i = 0; i < conf->capabilities.nelts; i++) { + size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; + } + + auth_enabled = 0; + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + size += 1 + ngx_mail_smtp_auth_methods_names[i].len; + auth_enabled = 1; + } + } + + if (auth_enabled) { + size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + } + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->capability.len = size; + conf->capability.data = p; + + last = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + *p++ = CR; *p++ = LF; + + for (i = 0; i < conf->capabilities.nelts; i++) { + last = p; + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + auth = p; + + if (auth_enabled) { + last = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; + *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_mail_smtp_auth_methods_names[i].data, + ngx_mail_smtp_auth_methods_names[i].len); + } + } + + *p++ = CR; *p = LF; + + } else { + last[3] = ' '; + } + + size += sizeof("250 STARTTLS" CRLF) - 1; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_capability.len = size; + conf->starttls_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, conf->capability.len); + + p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + + p = conf->starttls_capability.data + + (last - conf->capability.data) + 3; + *p = '-'; + + size = (auth - conf->capability.data) + + sizeof("250 STARTTLS" CRLF) - 1; + + p = ngx_pnalloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_only_capability.len = size; + conf->starttls_only_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, auth - conf->capability.data); + + ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + + if (last < auth) { + p = conf->starttls_only_capability.data + + (last - conf->capability.data) + 3; + *p = '-'; + } + + return NGX_CONF_OK; +} diff --git a/hm_nginx/src/mail/ngx_mail_smtp_module.h b/hm_nginx/src/mail/ngx_mail_smtp_module.h new file mode 100644 index 0000000..04ffab6 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_smtp_module.h @@ -0,0 +1,45 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_MAIL_SMTP_MODULE_H_INCLUDED_ +#define _NGX_MAIL_SMTP_MODULE_H_INCLUDED_ + + +#include +#include +#include +#include + + +typedef struct { + ngx_msec_t greeting_delay; + + size_t client_buffer_size; + + ngx_str_t capability; + ngx_str_t starttls_capability; + ngx_str_t starttls_only_capability; + + ngx_str_t server_name; + ngx_str_t greeting; + + ngx_uint_t auth_methods; + + ngx_array_t capabilities; +} ngx_mail_smtp_srv_conf_t; + + +void ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_smtp_init_protocol(ngx_event_t *rev); +void ngx_mail_smtp_auth_state(ngx_event_t *rev); +ngx_int_t ngx_mail_smtp_parse_command(ngx_mail_session_t *s); + + +extern ngx_module_t ngx_mail_smtp_module; + + +#endif /* _NGX_MAIL_SMTP_MODULE_H_INCLUDED_ */ diff --git a/hm_nginx/src/mail/ngx_mail_ssl_module.c b/hm_nginx/src/mail/ngx_mail_ssl_module.c new file mode 100644 index 0000000..e1efb61 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_ssl_module.c @@ -0,0 +1,657 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" +#define NGX_DEFAULT_ECDH_CURVE "prime256v1" + + +static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); +static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); + +static char *ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_conf_enum_t ngx_mail_starttls_state[] = { + { ngx_string("off"), NGX_MAIL_STARTTLS_OFF }, + { ngx_string("on"), NGX_MAIL_STARTTLS_ON }, + { ngx_string("only"), NGX_MAIL_STARTTLS_ONLY }, + { ngx_null_string, 0 } +}; + + + +static ngx_conf_bitmask_t ngx_mail_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, + { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_null_string, 0 } +}; + + +static ngx_conf_enum_t ngx_mail_ssl_verify[] = { + { ngx_string("off"), 0 }, + { ngx_string("on"), 1 }, + { ngx_string("optional"), 2 }, + { ngx_string("optional_no_ca"), 3 }, + { ngx_null_string, 0 } +}; + + +static ngx_command_t ngx_mail_ssl_commands[] = { + + { ngx_string("ssl"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_mail_ssl_enable, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, enable), + NULL }, + + { ngx_string("starttls"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_mail_ssl_starttls, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, starttls), + ngx_mail_starttls_state }, + + { ngx_string("ssl_certificate"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, certificate), + NULL }, + + { ngx_string("ssl_certificate_key"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, certificate_key), + NULL }, + + { ngx_string("ssl_password_file"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_mail_ssl_password_file, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("ssl_dhparam"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, dhparam), + NULL }, + + { ngx_string("ssl_ecdh_curve"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, ecdh_curve), + NULL }, + + { ngx_string("ssl_protocols"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, protocols), + &ngx_mail_ssl_protocols }, + + { ngx_string("ssl_ciphers"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, ciphers), + NULL }, + + { ngx_string("ssl_prefer_server_ciphers"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, prefer_server_ciphers), + NULL }, + + { ngx_string("ssl_session_cache"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12, + ngx_mail_ssl_session_cache, + NGX_MAIL_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("ssl_session_tickets"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, session_tickets), + NULL }, + + { ngx_string("ssl_session_ticket_key"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, session_ticket_keys), + NULL }, + + { ngx_string("ssl_session_timeout"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_sec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, session_timeout), + NULL }, + + { ngx_string("ssl_verify_client"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, verify), + &ngx_mail_ssl_verify }, + + { ngx_string("ssl_verify_depth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, verify_depth), + NULL }, + + { ngx_string("ssl_client_certificate"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, client_certificate), + NULL }, + + { ngx_string("ssl_trusted_certificate"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, trusted_certificate), + NULL }, + + { ngx_string("ssl_crl"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, crl), + NULL }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_ssl_module_ctx = { + NULL, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_ssl_create_conf, /* create server configuration */ + ngx_mail_ssl_merge_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_ssl_module = { + NGX_MODULE_V1, + &ngx_mail_ssl_module_ctx, /* module context */ + ngx_mail_ssl_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL"); + + +static void * +ngx_mail_ssl_create_conf(ngx_conf_t *cf) +{ + ngx_mail_ssl_conf_t *scf; + + scf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_ssl_conf_t)); + if (scf == NULL) { + return NULL; + } + + /* + * set by ngx_pcalloc(): + * + * scf->protocols = 0; + * scf->certificate = { 0, NULL }; + * scf->certificate_key = { 0, NULL }; + * scf->dhparam = { 0, NULL }; + * scf->ecdh_curve = { 0, NULL }; + * scf->client_certificate = { 0, NULL }; + * scf->trusted_certificate = { 0, NULL }; + * scf->crl = { 0, NULL }; + * scf->ciphers = { 0, NULL }; + * scf->shm_zone = NULL; + */ + + scf->enable = NGX_CONF_UNSET; + scf->starttls = NGX_CONF_UNSET_UINT; + scf->passwords = NGX_CONF_UNSET_PTR; + scf->prefer_server_ciphers = NGX_CONF_UNSET; + scf->verify = NGX_CONF_UNSET_UINT; + scf->verify_depth = NGX_CONF_UNSET_UINT; + scf->builtin_session_cache = NGX_CONF_UNSET; + scf->session_timeout = NGX_CONF_UNSET; + scf->session_tickets = NGX_CONF_UNSET; + scf->session_ticket_keys = NGX_CONF_UNSET_PTR; + + return scf; +} + + +static char * +ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_ssl_conf_t *prev = parent; + ngx_mail_ssl_conf_t *conf = child; + + char *mode; + ngx_pool_cleanup_t *cln; + + ngx_conf_merge_value(conf->enable, prev->enable, 0); + ngx_conf_merge_uint_value(conf->starttls, prev->starttls, + NGX_MAIL_STARTTLS_OFF); + + ngx_conf_merge_value(conf->session_timeout, + prev->session_timeout, 300); + + ngx_conf_merge_value(conf->prefer_server_ciphers, + prev->prefer_server_ciphers, 0); + + ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, + (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 + |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); + + ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); + ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); + + ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); + ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + + ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); + + ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); + + ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, + NGX_DEFAULT_ECDH_CURVE); + + ngx_conf_merge_str_value(conf->client_certificate, + prev->client_certificate, ""); + ngx_conf_merge_str_value(conf->trusted_certificate, + prev->trusted_certificate, ""); + ngx_conf_merge_str_value(conf->crl, prev->crl, ""); + + ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); + + + conf->ssl.log = cf->log; + + if (conf->enable) { + mode = "ssl"; + + } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { + mode = "starttls"; + + } else { + mode = ""; + } + + if (conf->file == NULL) { + conf->file = prev->file; + conf->line = prev->line; + } + + if (*mode) { + + if (conf->certificate.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate\" is defined for " + "the \"%s\" directive in %s:%ui", + mode, conf->file, conf->line); + return NGX_CONF_ERROR; + } + + if (conf->certificate_key.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined for " + "the \"%s\" directive in %s:%ui", + mode, conf->file, conf->line); + return NGX_CONF_ERROR; + } + + } else { + + if (conf->certificate.len == 0) { + return NGX_CONF_OK; + } + + if (conf->certificate_key.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\"", + &conf->certificate); + return NGX_CONF_ERROR; + } + } + + if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { + return NGX_CONF_ERROR; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NGX_CONF_ERROR; + } + + cln->handler = ngx_ssl_cleanup_ctx; + cln->data = &conf->ssl; + + if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, + &conf->certificate_key, conf->passwords) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (conf->verify) { + + if (conf->client_certificate.len == 0 && conf->verify != 3) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no ssl_client_certificate for ssl_client_verify"); + return NGX_CONF_ERROR; + } + + if (ngx_ssl_client_certificate(cf, &conf->ssl, + &conf->client_certificate, + conf->verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, &conf->ssl, + &conf->trusted_certificate, + conf->verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + if (SSL_CTX_set_cipher_list(conf->ssl.ctx, + (const char *) conf->ciphers.data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + &conf->ciphers); + return NGX_CONF_ERROR; + } + + if (conf->prefer_server_ciphers) { + SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } + +#ifndef LIBRESSL_VERSION_NUMBER + SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); +#endif + + if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { + return NGX_CONF_ERROR; + } + + ngx_conf_merge_value(conf->builtin_session_cache, + prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); + + if (conf->shm_zone == NULL) { + conf->shm_zone = prev->shm_zone; + } + + if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, + conf->builtin_session_cache, + conf->shm_zone, conf->session_timeout) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + ngx_conf_merge_value(conf->session_tickets, + prev->session_tickets, 1); + +#ifdef SSL_OP_NO_TICKET + if (!conf->session_tickets) { + SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET); + } +#endif + + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_ssl_conf_t *scf = conf; + + char *rv; + + rv = ngx_conf_set_flag_slot(cf, cmd, conf); + + if (rv != NGX_CONF_OK) { + return rv; + } + + if (scf->enable && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "\"starttls\" directive conflicts with \"ssl on\""); + return NGX_CONF_ERROR; + } + + scf->file = cf->conf_file->file.name.data; + scf->line = cf->conf_file->line; + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_ssl_conf_t *scf = conf; + + char *rv; + + rv = ngx_conf_set_enum_slot(cf, cmd, conf); + + if (rv != NGX_CONF_OK) { + return rv; + } + + if (scf->enable == 1 && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "\"ssl\" directive conflicts with \"starttls\""); + return NGX_CONF_ERROR; + } + + scf->file = cf->conf_file->file.name.data; + scf->line = cf->conf_file->line; + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_ssl_conf_t *scf = conf; + + ngx_str_t *value; + + if (scf->passwords != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + value = cf->args->elts; + + scf->passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (scf->passwords == NULL) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_ssl_conf_t *scf = conf; + + size_t len; + ngx_str_t *value, name, size; + ngx_int_t n; + ngx_uint_t i, j; + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + + if (ngx_strcmp(value[i].data, "off") == 0) { + scf->builtin_session_cache = NGX_SSL_NO_SCACHE; + continue; + } + + if (ngx_strcmp(value[i].data, "none") == 0) { + scf->builtin_session_cache = NGX_SSL_NONE_SCACHE; + continue; + } + + if (ngx_strcmp(value[i].data, "builtin") == 0) { + scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE; + continue; + } + + if (value[i].len > sizeof("builtin:") - 1 + && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1) + == 0) + { + n = ngx_atoi(value[i].data + sizeof("builtin:") - 1, + value[i].len - (sizeof("builtin:") - 1)); + + if (n == NGX_ERROR) { + goto invalid; + } + + scf->builtin_session_cache = n; + + continue; + } + + if (value[i].len > sizeof("shared:") - 1 + && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1) + == 0) + { + len = 0; + + for (j = sizeof("shared:") - 1; j < value[i].len; j++) { + if (value[i].data[j] == ':') { + break; + } + + len++; + } + + if (len == 0) { + goto invalid; + } + + name.len = len; + name.data = value[i].data + sizeof("shared:") - 1; + + size.len = value[i].len - j - 1; + size.data = name.data + len + 1; + + n = ngx_parse_size(&size); + + if (n == NGX_ERROR) { + goto invalid; + } + + if (n < (ngx_int_t) (8 * ngx_pagesize)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "session cache \"%V\" is too small", + &value[i]); + + return NGX_CONF_ERROR; + } + + scf->shm_zone = ngx_shared_memory_add(cf, &name, n, + &ngx_mail_ssl_module); + if (scf->shm_zone == NULL) { + return NGX_CONF_ERROR; + } + + scf->shm_zone->init = ngx_ssl_session_cache_init; + + continue; + } + + goto invalid; + } + + if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) { + scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE; + } + + return NGX_CONF_OK; + +invalid: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid session cache \"%V\"", &value[i]); + + return NGX_CONF_ERROR; +} diff --git a/hm_nginx/src/mail/ngx_mail_ssl_module.h b/hm_nginx/src/mail/ngx_mail_ssl_module.h new file mode 100644 index 0000000..296a6a2 --- /dev/null +++ b/hm_nginx/src/mail/ngx_mail_ssl_module.h @@ -0,0 +1,63 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_MAIL_SSL_H_INCLUDED_ +#define _NGX_MAIL_SSL_H_INCLUDED_ + + +#include +#include +#include + + +#define NGX_MAIL_STARTTLS_OFF 0 +#define NGX_MAIL_STARTTLS_ON 1 +#define NGX_MAIL_STARTTLS_ONLY 2 + + +typedef struct { + ngx_flag_t enable; + ngx_flag_t prefer_server_ciphers; + + ngx_ssl_t ssl; + + ngx_uint_t starttls; + ngx_uint_t protocols; + + ngx_uint_t verify; + ngx_uint_t verify_depth; + + ssize_t builtin_session_cache; + + time_t session_timeout; + + ngx_str_t certificate; + ngx_str_t certificate_key; + ngx_str_t dhparam; + ngx_str_t ecdh_curve; + ngx_str_t client_certificate; + ngx_str_t trusted_certificate; + ngx_str_t crl; + + ngx_str_t ciphers; + + ngx_array_t *passwords; + + ngx_shm_zone_t *shm_zone; + + ngx_flag_t session_tickets; + ngx_array_t *session_ticket_keys; + + u_char *file; + ngx_uint_t line; +} ngx_mail_ssl_conf_t; + + +extern ngx_module_t ngx_mail_ssl_module; + + +#endif /* _NGX_MAIL_SSL_H_INCLUDED_ */ diff --git a/hm_nginx/src/misc/ngx_cpp_test_module.cpp b/hm_nginx/src/misc/ngx_cpp_test_module.cpp new file mode 100644 index 0000000..5d2f08d --- /dev/null +++ b/hm_nginx/src/misc/ngx_cpp_test_module.cpp @@ -0,0 +1,29 @@ + +// stub module to test header files' C++ compatibility + +extern "C" { + #include + #include + #include + #include + #include + + #include + + #include + #include + #include + #include +} + +// nginx header files should go before other, because they define 64-bit off_t +// #include + + +void ngx_cpp_test_handler(void *data); + +void +ngx_cpp_test_handler(void *data) +{ + return; +} diff --git a/hm_nginx/src/misc/ngx_google_perftools_module.c b/hm_nginx/src/misc/ngx_google_perftools_module.c new file mode 100644 index 0000000..f2f8221 --- /dev/null +++ b/hm_nginx/src/misc/ngx_google_perftools_module.c @@ -0,0 +1,126 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + +/* + * declare Profiler interface here because + * is C++ header file + */ + +int ProfilerStart(u_char* fname); +void ProfilerStop(void); +void ProfilerRegisterThread(void); + + +static void *ngx_google_perftools_create_conf(ngx_cycle_t *cycle); +static ngx_int_t ngx_google_perftools_worker(ngx_cycle_t *cycle); + + +typedef struct { + ngx_str_t profiles; +} ngx_google_perftools_conf_t; + + +static ngx_command_t ngx_google_perftools_commands[] = { + + { ngx_string("google_perftools_profiles"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + 0, + offsetof(ngx_google_perftools_conf_t, profiles), + NULL }, + + ngx_null_command +}; + + +static ngx_core_module_t ngx_google_perftools_module_ctx = { + ngx_string("google_perftools"), + ngx_google_perftools_create_conf, + NULL +}; + + +ngx_module_t ngx_google_perftools_module = { + NGX_MODULE_V1, + &ngx_google_perftools_module_ctx, /* module context */ + ngx_google_perftools_commands, /* module directives */ + NGX_CORE_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + ngx_google_perftools_worker, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_google_perftools_create_conf(ngx_cycle_t *cycle) +{ + ngx_google_perftools_conf_t *gptcf; + + gptcf = ngx_pcalloc(cycle->pool, sizeof(ngx_google_perftools_conf_t)); + if (gptcf == NULL) { + return NULL; + } + + /* + * set by ngx_pcalloc() + * + * gptcf->profiles = { 0, NULL }; + */ + + return gptcf; +} + + +static ngx_int_t +ngx_google_perftools_worker(ngx_cycle_t *cycle) +{ + u_char *profile; + ngx_google_perftools_conf_t *gptcf; + + gptcf = (ngx_google_perftools_conf_t *) + ngx_get_conf(cycle->conf_ctx, ngx_google_perftools_module); + + if (gptcf->profiles.len == 0) { + return NGX_OK; + } + + profile = ngx_alloc(gptcf->profiles.len + NGX_INT_T_LEN + 2, cycle->log); + if (profile == NULL) { + return NGX_OK; + } + + if (getenv("CPUPROFILE")) { + /* disable inherited Profiler enabled in master process */ + ProfilerStop(); + } + + ngx_sprintf(profile, "%V.%d%Z", &gptcf->profiles, ngx_pid); + + if (ProfilerStart(profile)) { + /* start ITIMER_PROF timer */ + ProfilerRegisterThread(); + + } else { + ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno, + "ProfilerStart(%s) failed", profile); + } + + ngx_free(profile); + + return NGX_OK; +} + + +/* ProfilerStop() is called on Profiler destruction */ diff --git a/hm_nginx/src/os/unix/ngx_aio_read.c b/hm_nginx/src/os/unix/ngx_aio_read.c new file mode 100644 index 0000000..7849881 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_aio_read.c @@ -0,0 +1,109 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +extern int ngx_kqueue; + + +ssize_t +ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size) +{ + int n; + ngx_event_t *rev; + + rev = c->read; + + if (!rev->ready) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, "second aio post"); + return NGX_AGAIN; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "rev->complete: %d", rev->complete); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "aio size: %d", size); + + if (!rev->complete) { + ngx_memzero(&rev->aiocb, sizeof(struct aiocb)); + + rev->aiocb.aio_fildes = c->fd; + rev->aiocb.aio_buf = buf; + rev->aiocb.aio_nbytes = size; + +#if (NGX_HAVE_KQUEUE) + rev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; + rev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; + rev->aiocb.aio_sigevent.sigev_value.sigval_ptr = rev; +#endif + + if (aio_read(&rev->aiocb) == -1) { + ngx_log_error(NGX_LOG_CRIT, rev->log, ngx_errno, + "aio_read() failed"); + rev->error = 1; + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "aio_read: #%d OK", c->fd); + + rev->active = 1; + rev->ready = 0; + } + + rev->complete = 0; + + n = aio_error(&rev->aiocb); + if (n == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "aio_error() failed"); + rev->error = 1; + return NGX_ERROR; + } + + if (n != 0) { + if (n == NGX_EINPROGRESS) { + if (rev->ready) { + ngx_log_error(NGX_LOG_ALERT, c->log, n, + "aio_read() still in progress"); + rev->ready = 0; + } + return NGX_AGAIN; + } + + ngx_log_error(NGX_LOG_CRIT, c->log, n, "aio_read() failed"); + rev->error = 1; + rev->ready = 0; + return NGX_ERROR; + } + + n = aio_return(&rev->aiocb); + if (n == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, + "aio_return() failed"); + + rev->error = 1; + rev->ready = 0; + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, rev->log, 0, + "aio_read: #%d %d", c->fd, n); + + if (n == 0) { + rev->eof = 1; + rev->ready = 0; + } else { + rev->ready = 1; + } + + rev->active = 0; + + return n; +} diff --git a/hm_nginx/src/os/unix/ngx_aio_read_chain.c b/hm_nginx/src/os/unix/ngx_aio_read_chain.c new file mode 100644 index 0000000..d8722b2 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_aio_read_chain.c @@ -0,0 +1,78 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ssize_t +ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit) +{ + int n; + u_char *buf, *prev; + size_t size; + ssize_t total; + + if (c->read->pending_eof) { + c->read->ready = 0; + return 0; + } + + total = 0; + + while (cl) { + + /* we can post the single aio operation only */ + + if (!c->read->ready) { + return total ? total : NGX_AGAIN; + } + + buf = cl->buf->last; + prev = cl->buf->last; + size = 0; + + /* coalesce the neighbouring bufs */ + + while (cl && prev == cl->buf->last) { + size += cl->buf->end - cl->buf->last; + prev = cl->buf->end; + cl = cl->next; + } + + n = ngx_aio_read(c, buf, size); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_read: %d", n); + + if (n == NGX_AGAIN) { + return total ? total : NGX_AGAIN; + } + + if (n == NGX_ERROR) { + return NGX_ERROR; + } + + if (n == 0) { + c->read->pending_eof = 1; + if (total) { + c->read->eof = 0; + c->read->ready = 1; + } + return total; + } + + if (n > 0) { + total += n; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "aio_read total: %d", total); + } + + return total ? total : NGX_AGAIN; +} diff --git a/hm_nginx/src/os/unix/ngx_aio_write.c b/hm_nginx/src/os/unix/ngx_aio_write.c new file mode 100644 index 0000000..f0d9391 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_aio_write.c @@ -0,0 +1,109 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +extern int ngx_kqueue; + + +ssize_t +ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size) +{ + int n; + ngx_event_t *wev; + + wev = c->write; + + if (!wev->ready) { + return NGX_AGAIN; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, wev->log, 0, + "aio: wev->complete: %d", wev->complete); + + if (!wev->complete) { + ngx_memzero(&wev->aiocb, sizeof(struct aiocb)); + + wev->aiocb.aio_fildes = c->fd; + wev->aiocb.aio_buf = buf; + wev->aiocb.aio_nbytes = size; + +#if (NGX_HAVE_KQUEUE) + wev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; + wev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; + wev->aiocb.aio_sigevent.sigev_value.sigval_ptr = wev; +#endif + + if (aio_write(&wev->aiocb) == -1) { + ngx_log_error(NGX_LOG_CRIT, wev->log, ngx_errno, + "aio_write() failed"); + return NGX_ERROR; + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0, "aio_write: OK"); + + wev->active = 1; + wev->ready = 0; + } + + wev->complete = 0; + + n = aio_error(&wev->aiocb); + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, wev->log, ngx_errno, "aio_error() failed"); + wev->error = 1; + return NGX_ERROR; + } + + if (n != 0) { + if (n == NGX_EINPROGRESS) { + if (wev->ready) { + ngx_log_error(NGX_LOG_ALERT, wev->log, n, + "aio_write() still in progress"); + wev->ready = 0; + } + return NGX_AGAIN; + } + + ngx_log_error(NGX_LOG_CRIT, wev->log, n, "aio_write() failed"); + wev->error = 1; + wev->ready = 0; + +#if 1 + n = aio_return(&wev->aiocb); + if (n == -1) { + ngx_log_error(NGX_LOG_ALERT, wev->log, ngx_errno, + "aio_return() failed"); + } + + ngx_log_error(NGX_LOG_CRIT, wev->log, n, "aio_return() %d", n); +#endif + + return NGX_ERROR; + } + + n = aio_return(&wev->aiocb); + if (n == -1) { + ngx_log_error(NGX_LOG_ALERT, wev->log, ngx_errno, + "aio_return() failed"); + + wev->error = 1; + wev->ready = 0; + return NGX_ERROR; + } + + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, wev->log, 0, "aio_write: %d", n); + + wev->active = 0; + wev->ready = 1; + + return n; +} diff --git a/hm_nginx/src/os/unix/ngx_aio_write_chain.c b/hm_nginx/src/os/unix/ngx_aio_write_chain.c new file mode 100644 index 0000000..b0c2508 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_aio_write_chain.c @@ -0,0 +1,100 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ngx_chain_t * +ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) +{ + u_char *buf, *prev; + off_t send, sent; + size_t len; + ssize_t n, size; + ngx_chain_t *cl; + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { + limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; + sent = 0; + cl = in; + + while (cl) { + + if (cl->buf->pos == cl->buf->last) { + cl = cl->next; + continue; + } + + /* we can post the single aio operation only */ + + if (!c->write->ready) { + return cl; + } + + buf = cl->buf->pos; + prev = buf; + len = 0; + + /* coalesce the neighbouring bufs */ + + while (cl && prev == cl->buf->pos && send < limit) { + if (ngx_buf_special(cl->buf)) { + continue; + } + + size = cl->buf->last - cl->buf->pos; + + if (send + size > limit) { + size = limit - send; + } + + len += size; + prev = cl->buf->pos + size; + send += size; + cl = cl->next; + } + + n = ngx_aio_write(c, buf, len); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_write: %z", n); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + if (n > 0) { + sent += n; + c->sent += n; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "aio_write sent: %O", c->sent); + + for (cl = in; cl; cl = cl->next) { + + if (sent >= cl->buf->last - cl->buf->pos) { + sent -= cl->buf->last - cl->buf->pos; + cl->buf->pos = cl->buf->last; + + continue; + } + + cl->buf->pos += sent; + + break; + } + } + + return cl; +} diff --git a/hm_nginx/src/os/unix/ngx_alloc.c b/hm_nginx/src/os/unix/ngx_alloc.c new file mode 100644 index 0000000..5c2f787 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_alloc.c @@ -0,0 +1,90 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +ngx_uint_t ngx_pagesize; +ngx_uint_t ngx_pagesize_shift; +ngx_uint_t ngx_cacheline_size; + + +void * +ngx_alloc(size_t size, ngx_log_t *log) +{ + void *p; + + p = malloc(size); + if (p == NULL) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "malloc(%uz) failed", size); + } + + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size); + + return p; +} + + +void * +ngx_calloc(size_t size, ngx_log_t *log) +{ + void *p; + + p = ngx_alloc(size, log); + + if (p) { + ngx_memzero(p, size); + } + + return p; +} + + +#if (NGX_HAVE_POSIX_MEMALIGN) + +void * +ngx_memalign(size_t alignment, size_t size, ngx_log_t *log) +{ + void *p; + int err; + + err = posix_memalign(&p, alignment, size); + + if (err) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "posix_memalign(%uz, %uz) failed", alignment, size); + p = NULL; + } + + ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0, + "posix_memalign: %p:%uz @%uz", p, size, alignment); + + return p; +} + +#elif (NGX_HAVE_MEMALIGN) + +void * +ngx_memalign(size_t alignment, size_t size, ngx_log_t *log) +{ + void *p; + + p = memalign(alignment, size); + if (p == NULL) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "memalign(%uz, %uz) failed", alignment, size); + } + + ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0, + "memalign: %p:%uz @%uz", p, size, alignment); + + return p; +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_alloc.h b/hm_nginx/src/os/unix/ngx_alloc.h new file mode 100644 index 0000000..655db25 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_alloc.h @@ -0,0 +1,45 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_ALLOC_H_INCLUDED_ +#define _NGX_ALLOC_H_INCLUDED_ + + +#include +#include + + +void *ngx_alloc(size_t size, ngx_log_t *log); +void *ngx_calloc(size_t size, ngx_log_t *log); + +#define ngx_free free + + +/* + * Linux has memalign() or posix_memalign() + * Solaris has memalign() + * FreeBSD 7.0 has posix_memalign(), besides, early version's malloc() + * aligns allocations bigger than page size at the page boundary + */ + +#if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN) + +void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log); + +#else + +#define ngx_memalign(alignment, size, log) ngx_alloc(size, log) + +#endif + + +extern ngx_uint_t ngx_pagesize; +extern ngx_uint_t ngx_pagesize_shift; +extern ngx_uint_t ngx_cacheline_size; + + +#endif /* _NGX_ALLOC_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_atomic.h b/hm_nginx/src/os/unix/ngx_atomic.h new file mode 100644 index 0000000..417cd86 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_atomic.h @@ -0,0 +1,313 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_ATOMIC_H_INCLUDED_ +#define _NGX_ATOMIC_H_INCLUDED_ + + +#include +#include + + +#if (NGX_HAVE_LIBATOMIC) + +#define AO_REQUIRE_CAS +#include + +#define NGX_HAVE_ATOMIC_OPS 1 + +typedef long ngx_atomic_int_t; +typedef AO_t ngx_atomic_uint_t; +typedef volatile ngx_atomic_uint_t ngx_atomic_t; + +#if (NGX_PTR_SIZE == 8) +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) +#else +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) +#endif + +#define ngx_atomic_cmp_set(lock, old, new) \ + AO_compare_and_swap(lock, old, new) +#define ngx_atomic_fetch_add(value, add) \ + AO_fetch_and_add(value, add) +#define ngx_memory_barrier() AO_nop() +#define ngx_cpu_pause() + + +#elif (NGX_DARWIN_ATOMIC) + +/* + * use Darwin 8 atomic(3) and barrier(3) operations + * optimized at run-time for UP and SMP + */ + +#include + +/* "bool" conflicts with perl's CORE/handy.h */ +#if 0 +#undef bool +#endif + + +#define NGX_HAVE_ATOMIC_OPS 1 + +#if (NGX_PTR_SIZE == 8) + +typedef int64_t ngx_atomic_int_t; +typedef uint64_t ngx_atomic_uint_t; +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) + +#define ngx_atomic_cmp_set(lock, old, new) \ + OSAtomicCompareAndSwap64Barrier(old, new, (int64_t *) lock) + +#define ngx_atomic_fetch_add(value, add) \ + (OSAtomicAdd64(add, (int64_t *) value) - add) + +#else + +typedef int32_t ngx_atomic_int_t; +typedef uint32_t ngx_atomic_uint_t; +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) + +#define ngx_atomic_cmp_set(lock, old, new) \ + OSAtomicCompareAndSwap32Barrier(old, new, (int32_t *) lock) + +#define ngx_atomic_fetch_add(value, add) \ + (OSAtomicAdd32(add, (int32_t *) value) - add) + +#endif + +#define ngx_memory_barrier() OSMemoryBarrier() + +#define ngx_cpu_pause() + +typedef volatile ngx_atomic_uint_t ngx_atomic_t; + + +#elif (NGX_HAVE_GCC_ATOMIC) + +/* GCC 4.1 builtin atomic operations */ + +#define NGX_HAVE_ATOMIC_OPS 1 + +typedef long ngx_atomic_int_t; +typedef unsigned long ngx_atomic_uint_t; + +#if (NGX_PTR_SIZE == 8) +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) +#else +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) +#endif + +typedef volatile ngx_atomic_uint_t ngx_atomic_t; + + +#define ngx_atomic_cmp_set(lock, old, set) \ + __sync_bool_compare_and_swap(lock, old, set) + +#define ngx_atomic_fetch_add(value, add) \ + __sync_fetch_and_add(value, add) + +#define ngx_memory_barrier() __sync_synchronize() + +#if ( __i386__ || __i386 || __amd64__ || __amd64 ) +#define ngx_cpu_pause() __asm__ ("pause") +#else +#define ngx_cpu_pause() +#endif + + +#elif ( __i386__ || __i386 ) + +typedef int32_t ngx_atomic_int_t; +typedef uint32_t ngx_atomic_uint_t; +typedef volatile ngx_atomic_uint_t ngx_atomic_t; +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) + + +#if ( __SUNPRO_C ) + +#define NGX_HAVE_ATOMIC_OPS 1 + +ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set); + +ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add); + +/* + * Sun Studio 12 exits with segmentation fault on '__asm ("pause")', + * so ngx_cpu_pause is declared in src/os/unix/ngx_sunpro_x86.il + */ + +void +ngx_cpu_pause(void); + +/* the code in src/os/unix/ngx_sunpro_x86.il */ + +#define ngx_memory_barrier() __asm (".volatile"); __asm (".nonvolatile") + + +#else /* ( __GNUC__ || __INTEL_COMPILER ) */ + +#define NGX_HAVE_ATOMIC_OPS 1 + +#include "ngx_gcc_atomic_x86.h" + +#endif + + +#elif ( __amd64__ || __amd64 ) + +typedef int64_t ngx_atomic_int_t; +typedef uint64_t ngx_atomic_uint_t; +typedef volatile ngx_atomic_uint_t ngx_atomic_t; +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) + + +#if ( __SUNPRO_C ) + +#define NGX_HAVE_ATOMIC_OPS 1 + +ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set); + +ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add); + +/* + * Sun Studio 12 exits with segmentation fault on '__asm ("pause")', + * so ngx_cpu_pause is declared in src/os/unix/ngx_sunpro_amd64.il + */ + +void +ngx_cpu_pause(void); + +/* the code in src/os/unix/ngx_sunpro_amd64.il */ + +#define ngx_memory_barrier() __asm (".volatile"); __asm (".nonvolatile") + + +#else /* ( __GNUC__ || __INTEL_COMPILER ) */ + +#define NGX_HAVE_ATOMIC_OPS 1 + +#include "ngx_gcc_atomic_amd64.h" + +#endif + + +#elif ( __sparc__ || __sparc || __sparcv9 ) + +#if (NGX_PTR_SIZE == 8) + +typedef int64_t ngx_atomic_int_t; +typedef uint64_t ngx_atomic_uint_t; +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) + +#else + +typedef int32_t ngx_atomic_int_t; +typedef uint32_t ngx_atomic_uint_t; +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) + +#endif + +typedef volatile ngx_atomic_uint_t ngx_atomic_t; + + +#if ( __SUNPRO_C ) + +#define NGX_HAVE_ATOMIC_OPS 1 + +#include "ngx_sunpro_atomic_sparc64.h" + + +#else /* ( __GNUC__ || __INTEL_COMPILER ) */ + +#define NGX_HAVE_ATOMIC_OPS 1 + +#include "ngx_gcc_atomic_sparc64.h" + +#endif + + +#elif ( __powerpc__ || __POWERPC__ ) + +#define NGX_HAVE_ATOMIC_OPS 1 + +#if (NGX_PTR_SIZE == 8) + +typedef int64_t ngx_atomic_int_t; +typedef uint64_t ngx_atomic_uint_t; +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) + +#else + +typedef int32_t ngx_atomic_int_t; +typedef uint32_t ngx_atomic_uint_t; +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) + +#endif + +typedef volatile ngx_atomic_uint_t ngx_atomic_t; + + +#include "ngx_gcc_atomic_ppc.h" + +#endif + + +#if !(NGX_HAVE_ATOMIC_OPS) + +#define NGX_HAVE_ATOMIC_OPS 0 + +typedef int32_t ngx_atomic_int_t; +typedef uint32_t ngx_atomic_uint_t; +typedef volatile ngx_atomic_uint_t ngx_atomic_t; +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) + + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + if (*lock == old) { + *lock = set; + return 1; + } + + return 0; +} + + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_int_t old; + + old = *value; + *value += add; + + return old; +} + +#define ngx_memory_barrier() +#define ngx_cpu_pause() + +#endif + + +void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin); + +#define ngx_trylock(lock) (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1)) +#define ngx_unlock(lock) *(lock) = 0 + + +#endif /* _NGX_ATOMIC_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_channel.c b/hm_nginx/src/os/unix/ngx_channel.c new file mode 100644 index 0000000..1efa066 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_channel.c @@ -0,0 +1,253 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ngx_int_t +ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, + ngx_log_t *log) +{ + ssize_t n; + ngx_err_t err; + struct iovec iov[1]; + struct msghdr msg; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + + union { + struct cmsghdr cm; + char space[CMSG_SPACE(sizeof(int))]; + } cmsg; + + if (ch->fd == -1) { + msg.msg_control = NULL; + msg.msg_controllen = 0; + + } else { + msg.msg_control = (caddr_t) &cmsg; + msg.msg_controllen = sizeof(cmsg); + + ngx_memzero(&cmsg, sizeof(cmsg)); + + cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int)); + cmsg.cm.cmsg_level = SOL_SOCKET; + cmsg.cm.cmsg_type = SCM_RIGHTS; + + /* + * We have to use ngx_memcpy() instead of simple + * *(int *) CMSG_DATA(&cmsg.cm) = ch->fd; + * because some gcc 4.4 with -O2/3/s optimization issues the warning: + * dereferencing type-punned pointer will break strict-aliasing rules + * + * Fortunately, gcc with -O1 compiles this ngx_memcpy() + * in the same simple assignment as in the code above + */ + + ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int)); + } + + msg.msg_flags = 0; + +#else + + if (ch->fd == -1) { + msg.msg_accrights = NULL; + msg.msg_accrightslen = 0; + + } else { + msg.msg_accrights = (caddr_t) &ch->fd; + msg.msg_accrightslen = sizeof(int); + } + +#endif + + iov[0].iov_base = (char *) ch; + iov[0].iov_len = size; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + n = sendmsg(s, &msg, 0); + + if (n == -1) { + err = ngx_errno; + if (err == NGX_EAGAIN) { + return NGX_AGAIN; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed"); + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_int_t +ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log) +{ + ssize_t n; + ngx_err_t err; + struct iovec iov[1]; + struct msghdr msg; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + union { + struct cmsghdr cm; + char space[CMSG_SPACE(sizeof(int))]; + } cmsg; +#else + int fd; +#endif + + iov[0].iov_base = (char *) ch; + iov[0].iov_len = size; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + msg.msg_control = (caddr_t) &cmsg; + msg.msg_controllen = sizeof(cmsg); +#else + msg.msg_accrights = (caddr_t) &fd; + msg.msg_accrightslen = sizeof(int); +#endif + + n = recvmsg(s, &msg, 0); + + if (n == -1) { + err = ngx_errno; + if (err == NGX_EAGAIN) { + return NGX_AGAIN; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, "recvmsg() failed"); + return NGX_ERROR; + } + + if (n == 0) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "recvmsg() returned zero"); + return NGX_ERROR; + } + + if ((size_t) n < sizeof(ngx_channel_t)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "recvmsg() returned not enough data: %z", n); + return NGX_ERROR; + } + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + + if (ch->command == NGX_CMD_OPEN_CHANNEL) { + + if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "recvmsg() returned too small ancillary data"); + return NGX_ERROR; + } + + if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS) + { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "recvmsg() returned invalid ancillary data " + "level %d or type %d", + cmsg.cm.cmsg_level, cmsg.cm.cmsg_type); + return NGX_ERROR; + } + + /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */ + + ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int)); + } + + if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "recvmsg() truncated data"); + } + +#else + + if (ch->command == NGX_CMD_OPEN_CHANNEL) { + if (msg.msg_accrightslen != sizeof(int)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "recvmsg() returned no ancillary data"); + return NGX_ERROR; + } + + ch->fd = fd; + } + +#endif + + return n; +} + + +ngx_int_t +ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event, + ngx_event_handler_pt handler) +{ + ngx_event_t *ev, *rev, *wev; + ngx_connection_t *c; + + c = ngx_get_connection(fd, cycle->log); + + if (c == NULL) { + return NGX_ERROR; + } + + c->pool = cycle->pool; + + rev = c->read; + wev = c->write; + + rev->log = cycle->log; + wev->log = cycle->log; + + rev->channel = 1; + wev->channel = 1; + + ev = (event == NGX_READ_EVENT) ? rev : wev; + + ev->handler = handler; + + if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) { + if (ngx_add_conn(c) == NGX_ERROR) { + ngx_free_connection(c); + return NGX_ERROR; + } + + } else { + if (ngx_add_event(ev, event, 0) == NGX_ERROR) { + ngx_free_connection(c); + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +void +ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log) +{ + if (close(fd[0]) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed"); + } + + if (close(fd[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed"); + } +} diff --git a/hm_nginx/src/os/unix/ngx_channel.h b/hm_nginx/src/os/unix/ngx_channel.h new file mode 100644 index 0000000..d7a9f6b --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_channel.h @@ -0,0 +1,34 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_CHANNEL_H_INCLUDED_ +#define _NGX_CHANNEL_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + ngx_uint_t command; + ngx_pid_t pid; + ngx_int_t slot; + ngx_fd_t fd; +} ngx_channel_t; + + +ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, + ngx_log_t *log); +ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, + ngx_log_t *log); +ngx_int_t ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, + ngx_int_t event, ngx_event_handler_pt handler); +void ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log); + + +#endif /* _NGX_CHANNEL_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_daemon.c b/hm_nginx/src/os/unix/ngx_daemon.c new file mode 100644 index 0000000..ab67211 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_daemon.c @@ -0,0 +1,70 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +ngx_int_t +ngx_daemon(ngx_log_t *log) +{ + int fd; + + switch (fork()) { + case -1: + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed"); + return NGX_ERROR; + + case 0: + break; + + default: + exit(0); + } + + ngx_pid = ngx_getpid(); + + if (setsid() == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed"); + return NGX_ERROR; + } + + umask(0); + + fd = open("/dev/null", O_RDWR); + if (fd == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "open(\"/dev/null\") failed"); + return NGX_ERROR; + } + + if (dup2(fd, STDIN_FILENO) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed"); + return NGX_ERROR; + } + + if (dup2(fd, STDOUT_FILENO) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed"); + return NGX_ERROR; + } + +#if 0 + if (dup2(fd, STDERR_FILENO) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); + return NGX_ERROR; + } +#endif + + if (fd > STDERR_FILENO) { + if (close(fd) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); + return NGX_ERROR; + } + } + + return NGX_OK; +} diff --git a/hm_nginx/src/os/unix/ngx_darwin.h b/hm_nginx/src/os/unix/ngx_darwin.h new file mode 100644 index 0000000..4d01b26 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_darwin.h @@ -0,0 +1,23 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_DARWIN_H_INCLUDED_ +#define _NGX_DARWIN_H_INCLUDED_ + + +void ngx_debug_init(void); +ngx_chain_t *ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + +extern int ngx_darwin_kern_osreldate; +extern int ngx_darwin_hw_ncpu; +extern u_long ngx_darwin_net_inet_tcp_sendspace; + +extern ngx_uint_t ngx_debug_malloc; + + +#endif /* _NGX_DARWIN_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_darwin_config.h b/hm_nginx/src/os/unix/ngx_darwin_config.h new file mode 100644 index 0000000..bbad977 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_darwin_config.h @@ -0,0 +1,95 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_DARWIN_CONFIG_H_INCLUDED_ +#define _NGX_DARWIN_CONFIG_H_INCLUDED_ + + +#include +#include +#include +#include +#include +#include /* offsetof() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* statfs() */ + +#include /* FIONBIO */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include /* TCP_NODELAY */ +#include +#include +#include + +#include +#include + + +#ifndef IOV_MAX +#define IOV_MAX 64 +#endif + + +#include + + +#if (NGX_HAVE_POSIX_SEM) +#include +#endif + + +#if (NGX_HAVE_POLL) +#include +#endif + + +#if (NGX_HAVE_KQUEUE) +#include +#endif + + +#define NGX_LISTEN_BACKLOG -1 + + +#ifndef NGX_HAVE_INHERITED_NONBLOCK +#define NGX_HAVE_INHERITED_NONBLOCK 1 +#endif + + +#ifndef NGX_HAVE_CASELESS_FILESYSTEM +#define NGX_HAVE_CASELESS_FILESYSTEM 1 +#endif + + +#define NGX_HAVE_OS_SPECIFIC_INIT 1 +#define NGX_HAVE_DEBUG_MALLOC 1 + + +extern char **environ; + + +#endif /* _NGX_DARWIN_CONFIG_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_darwin_init.c b/hm_nginx/src/os/unix/ngx_darwin_init.c new file mode 100644 index 0000000..1bc7520 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_darwin_init.c @@ -0,0 +1,196 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +char ngx_darwin_kern_ostype[16]; +char ngx_darwin_kern_osrelease[128]; +int ngx_darwin_hw_ncpu; +int ngx_darwin_kern_ipc_somaxconn; +u_long ngx_darwin_net_inet_tcp_sendspace; + +ngx_uint_t ngx_debug_malloc; + + +static ngx_os_io_t ngx_darwin_io = { + ngx_unix_recv, + ngx_readv_chain, + ngx_udp_unix_recv, + ngx_unix_send, +#if (NGX_HAVE_SENDFILE) + ngx_darwin_sendfile_chain, + NGX_IO_SENDFILE +#else + ngx_writev_chain, + 0 +#endif +}; + + +typedef struct { + char *name; + void *value; + size_t size; + ngx_uint_t exists; +} sysctl_t; + + +sysctl_t sysctls[] = { + { "hw.ncpu", + &ngx_darwin_hw_ncpu, + sizeof(ngx_darwin_hw_ncpu), 0 }, + + { "net.inet.tcp.sendspace", + &ngx_darwin_net_inet_tcp_sendspace, + sizeof(ngx_darwin_net_inet_tcp_sendspace), 0 }, + + { "kern.ipc.somaxconn", + &ngx_darwin_kern_ipc_somaxconn, + sizeof(ngx_darwin_kern_ipc_somaxconn), 0 }, + + { NULL, NULL, 0, 0 } +}; + + +void +ngx_debug_init(void) +{ +#if (NGX_DEBUG_MALLOC) + + /* + * MacOSX 10.6, 10.7: MallocScribble fills freed memory with 0x55 + * and fills allocated memory with 0xAA. + * MacOSX 10.4, 10.5: MallocScribble fills freed memory with 0x55, + * MallocPreScribble fills allocated memory with 0xAA. + * MacOSX 10.3: MallocScribble fills freed memory with 0x55, + * and no way to fill allocated memory. + */ + + setenv("MallocScribble", "1", 0); + + ngx_debug_malloc = 1; + +#else + + if (getenv("MallocScribble")) { + ngx_debug_malloc = 1; + } + +#endif +} + + +ngx_int_t +ngx_os_specific_init(ngx_log_t *log) +{ + size_t size; + ngx_err_t err; + ngx_uint_t i; + + size = sizeof(ngx_darwin_kern_ostype); + if (sysctlbyname("kern.ostype", ngx_darwin_kern_ostype, &size, NULL, 0) + == -1) + { + err = ngx_errno; + + if (err != NGX_ENOENT) { + + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(kern.ostype) failed"); + + if (err != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_darwin_kern_ostype[size - 1] = '\0'; + } + } + + size = sizeof(ngx_darwin_kern_osrelease); + if (sysctlbyname("kern.osrelease", ngx_darwin_kern_osrelease, &size, + NULL, 0) + == -1) + { + err = ngx_errno; + + if (err != NGX_ENOENT) { + + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(kern.osrelease) failed"); + + if (err != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_darwin_kern_osrelease[size - 1] = '\0'; + } + } + + for (i = 0; sysctls[i].name; i++) { + size = sysctls[i].size; + + if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0) + == 0) + { + sysctls[i].exists = 1; + continue; + } + + err = ngx_errno; + + if (err == NGX_ENOENT) { + continue; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(%s) failed", sysctls[i].name); + return NGX_ERROR; + } + + ngx_ncpu = ngx_darwin_hw_ncpu; + + if (ngx_darwin_kern_ipc_somaxconn > 32767) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "sysctl kern.ipc.somaxconn must be less than 32768"); + return NGX_ERROR; + } + + ngx_tcp_nodelay_and_tcp_nopush = 1; + + ngx_os_io = ngx_darwin_io; + + return NGX_OK; +} + + +void +ngx_os_specific_status(ngx_log_t *log) +{ + u_long value; + ngx_uint_t i; + + if (ngx_darwin_kern_ostype[0]) { + ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", + ngx_darwin_kern_ostype, ngx_darwin_kern_osrelease); + } + + for (i = 0; sysctls[i].name; i++) { + if (sysctls[i].exists) { + if (sysctls[i].size == sizeof(long)) { + value = *(long *) sysctls[i].value; + + } else { + value = *(int *) sysctls[i].value; + } + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l", + sysctls[i].name, value); + } + } +} diff --git a/hm_nginx/src/os/unix/ngx_darwin_sendfile_chain.c b/hm_nginx/src/os/unix/ngx_darwin_sendfile_chain.c new file mode 100644 index 0000000..c802e9f --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_darwin_sendfile_chain.c @@ -0,0 +1,206 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +/* + * It seems that Darwin 9.4 (Mac OS X 1.5) sendfile() has the same + * old bug as early FreeBSD sendfile() syscall: + * http://bugs.freebsd.org/33771 + * + * Besides sendfile() has another bug: if one calls sendfile() + * with both a header and a trailer, then sendfile() ignores a file part + * at all and sends only the header and the trailer together. + * For this reason we send a trailer only if there is no a header. + * + * Although sendfile() allows to pass a header or a trailer, + * it may send the header or the trailer and a part of the file + * in different packets. And FreeBSD workaround (TCP_NOPUSH option) + * does not help. + */ + + +ngx_chain_t * +ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) +{ + int rc; + off_t send, prev_send, sent; + off_t file_size; + ssize_t n; + ngx_uint_t eintr; + ngx_err_t err; + ngx_buf_t *file; + ngx_event_t *wev; + ngx_chain_t *cl; + ngx_iovec_t header, trailer; + struct sf_hdtr hdtr; + struct iovec headers[NGX_IOVS_PREALLOCATE]; + struct iovec trailers[NGX_IOVS_PREALLOCATE]; + + wev = c->write; + + if (!wev->ready) { + return in; + } + +#if (NGX_HAVE_KQUEUE) + + if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); + wev->error = 1; + return NGX_CHAIN_ERROR; + } + +#endif + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { + limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; + + header.iovs = headers; + header.nalloc = NGX_IOVS_PREALLOCATE; + + trailer.iovs = trailers; + trailer.nalloc = NGX_IOVS_PREALLOCATE; + + for ( ;; ) { + eintr = 0; + prev_send = send; + + /* create the header iovec and coalesce the neighbouring bufs */ + + cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log); + + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + send += header.size; + + if (cl && cl->buf->in_file && send < limit) { + file = cl->buf; + + /* coalesce the neighbouring file bufs */ + + file_size = ngx_chain_coalesce_file(&cl, limit - send); + + send += file_size; + + if (header.count == 0) { + + /* + * create the trailer iovec and coalesce the neighbouring bufs + */ + + cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, + c->log); + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + send += trailer.size; + + } else { + trailer.count = 0; + } + + /* + * sendfile() returns EINVAL if sf_hdtr's count is 0, + * but corresponding pointer is not NULL + */ + + hdtr.headers = header.count ? header.iovs : NULL; + hdtr.hdr_cnt = header.count; + hdtr.trailers = trailer.count ? trailer.iovs : NULL; + hdtr.trl_cnt = trailer.count; + + sent = header.size + file_size; + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendfile: @%O %O h:%uz", + file->file_pos, sent, header.size); + + rc = sendfile(file->file->fd, c->fd, file->file_pos, + &sent, &hdtr, 0); + + if (rc == -1) { + err = ngx_errno; + + switch (err) { + case NGX_EAGAIN: + break; + + case NGX_EINTR: + eintr = 1; + break; + + default: + wev->error = 1; + (void) ngx_connection_error(c, err, "sendfile() failed"); + return NGX_CHAIN_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, + "sendfile() sent only %O bytes", sent); + } + + if (rc == 0 && sent == 0) { + + /* + * if rc and sent equal to zero, then someone + * has truncated the file, so the offset became beyond + * the end of the file + */ + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfile() reported that \"%s\" was truncated", + file->file->name.data); + + return NGX_CHAIN_ERROR; + } + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendfile: %d, @%O %O:%O", + rc, file->file_pos, sent, file_size + header.size); + + } else { + n = ngx_writev(c, &header); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + sent = (n == NGX_AGAIN) ? 0 : n; + } + + c->sent += sent; + + in = ngx_chain_update_sent(in, sent); + + if (eintr) { + send = prev_send + sent; + continue; + } + + if (send - prev_send != sent) { + wev->ready = 0; + return in; + } + + if (send >= limit || in == NULL) { + return in; + } + } +} diff --git a/hm_nginx/src/os/unix/ngx_errno.c b/hm_nginx/src/os/unix/ngx_errno.c new file mode 100644 index 0000000..e787b23 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_errno.c @@ -0,0 +1,87 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +/* + * The strerror() messages are copied because: + * + * 1) strerror() and strerror_r() functions are not Async-Signal-Safe, + * therefore, they cannot be used in signal handlers; + * + * 2) a direct sys_errlist[] array may be used instead of these functions, + * but Linux linker warns about its usage: + * + * warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead + * warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead + * + * causing false bug reports. + */ + + +static ngx_str_t *ngx_sys_errlist; +static ngx_str_t ngx_unknown_error = ngx_string("Unknown error"); + + +u_char * +ngx_strerror(ngx_err_t err, u_char *errstr, size_t size) +{ + ngx_str_t *msg; + + msg = ((ngx_uint_t) err < NGX_SYS_NERR) ? &ngx_sys_errlist[err]: + &ngx_unknown_error; + size = ngx_min(size, msg->len); + + return ngx_cpymem(errstr, msg->data, size); +} + + +ngx_int_t +ngx_strerror_init(void) +{ + char *msg; + u_char *p; + size_t len; + ngx_err_t err; + + /* + * ngx_strerror() is not ready to work at this stage, therefore, + * malloc() is used and possible errors are logged using strerror(). + */ + + len = NGX_SYS_NERR * sizeof(ngx_str_t); + + ngx_sys_errlist = malloc(len); + if (ngx_sys_errlist == NULL) { + goto failed; + } + + for (err = 0; err < NGX_SYS_NERR; err++) { + msg = strerror(err); + len = ngx_strlen(msg); + + p = malloc(len); + if (p == NULL) { + goto failed; + } + + ngx_memcpy(p, msg, len); + ngx_sys_errlist[err].len = len; + ngx_sys_errlist[err].data = p; + } + + return NGX_OK; + +failed: + + err = errno; + ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err)); + + return NGX_ERROR; +} diff --git a/hm_nginx/src/os/unix/ngx_errno.h b/hm_nginx/src/os/unix/ngx_errno.h new file mode 100644 index 0000000..16cafda --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_errno.h @@ -0,0 +1,78 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_ERRNO_H_INCLUDED_ +#define _NGX_ERRNO_H_INCLUDED_ + + +#include +#include + + +typedef int ngx_err_t; + +#define NGX_EPERM EPERM +#define NGX_ENOENT ENOENT +#define NGX_ENOPATH ENOENT +#define NGX_ESRCH ESRCH +#define NGX_EINTR EINTR +#define NGX_ECHILD ECHILD +#define NGX_ENOMEM ENOMEM +#define NGX_EACCES EACCES +#define NGX_EBUSY EBUSY +#define NGX_EEXIST EEXIST +#define NGX_EXDEV EXDEV +#define NGX_ENOTDIR ENOTDIR +#define NGX_EISDIR EISDIR +#define NGX_EINVAL EINVAL +#define NGX_ENFILE ENFILE +#define NGX_EMFILE EMFILE +#define NGX_ENOSPC ENOSPC +#define NGX_EPIPE EPIPE +#define NGX_EINPROGRESS EINPROGRESS +#define NGX_ENOPROTOOPT ENOPROTOOPT +#define NGX_EOPNOTSUPP EOPNOTSUPP +#define NGX_EADDRINUSE EADDRINUSE +#define NGX_ECONNABORTED ECONNABORTED +#define NGX_ECONNRESET ECONNRESET +#define NGX_ENOTCONN ENOTCONN +#define NGX_ETIMEDOUT ETIMEDOUT +#define NGX_ECONNREFUSED ECONNREFUSED +#define NGX_ENAMETOOLONG ENAMETOOLONG +#define NGX_ENETDOWN ENETDOWN +#define NGX_ENETUNREACH ENETUNREACH +#define NGX_EHOSTDOWN EHOSTDOWN +#define NGX_EHOSTUNREACH EHOSTUNREACH +#define NGX_ENOSYS ENOSYS +#define NGX_ECANCELED ECANCELED +#define NGX_EILSEQ EILSEQ +#define NGX_ENOMOREFILES 0 +#define NGX_ELOOP ELOOP +#define NGX_EBADF EBADF + +#if (NGX_HAVE_OPENAT) +#define NGX_EMLINK EMLINK +#endif + +#if (__hpux__) +#define NGX_EAGAIN EWOULDBLOCK +#else +#define NGX_EAGAIN EAGAIN +#endif + + +#define ngx_errno errno +#define ngx_socket_errno errno +#define ngx_set_errno(err) errno = err +#define ngx_set_socket_errno(err) errno = err + + +u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size); +ngx_int_t ngx_strerror_init(void); + + +#endif /* _NGX_ERRNO_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_file_aio_read.c b/hm_nginx/src/os/unix/ngx_file_aio_read.c new file mode 100644 index 0000000..b11cf8a --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_file_aio_read.c @@ -0,0 +1,216 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +/* + * FreeBSD file AIO features and quirks: + * + * if an asked data are already in VM cache, then aio_error() returns 0, + * and the data are already copied in buffer; + * + * aio_read() preread in VM cache as minimum 16K (probably BKVASIZE); + * the first AIO preload may be up to 128K; + * + * aio_read/aio_error() may return EINPROGRESS for just written data; + * + * kqueue EVFILT_AIO filter is level triggered only: an event repeats + * until aio_return() will be called; + * + * aio_cancel() cannot cancel file AIO: it returns AIO_NOTCANCELED always. + */ + + +extern int ngx_kqueue; + + +static ssize_t ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, + ngx_event_t *ev); +static void ngx_file_aio_event_handler(ngx_event_t *ev); + + +ngx_int_t +ngx_file_aio_init(ngx_file_t *file, ngx_pool_t *pool) +{ + ngx_event_aio_t *aio; + + aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); + if (aio == NULL) { + return NGX_ERROR; + } + + aio->file = file; + aio->fd = file->fd; + aio->event.data = aio; + aio->event.ready = 1; + aio->event.log = file->log; + + file->aio = aio; + + return NGX_OK; +} + + +ssize_t +ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, + ngx_pool_t *pool) +{ + int n; + ngx_event_t *ev; + ngx_event_aio_t *aio; + + if (!ngx_file_aio) { + return ngx_read_file(file, buf, size, offset); + } + + if (file->aio == NULL && ngx_file_aio_init(file, pool) != NGX_OK) { + return NGX_ERROR; + } + + aio = file->aio; + ev = &aio->event; + + if (!ev->ready) { + ngx_log_error(NGX_LOG_ALERT, file->log, 0, + "second aio post for \"%V\"", &file->name); + return NGX_AGAIN; + } + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio complete:%d @%O:%z %V", + ev->complete, offset, size, &file->name); + + if (ev->complete) { + ev->complete = 0; + ngx_set_errno(aio->err); + + if (aio->err == 0) { + return aio->nbytes; + } + + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "aio read \"%s\" failed", file->name.data); + + return NGX_ERROR; + } + + ngx_memzero(&aio->aiocb, sizeof(struct aiocb)); + + aio->aiocb.aio_fildes = file->fd; + aio->aiocb.aio_offset = offset; + aio->aiocb.aio_buf = buf; + aio->aiocb.aio_nbytes = size; +#if (NGX_HAVE_KQUEUE) + aio->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; + aio->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; + aio->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev; +#endif + ev->handler = ngx_file_aio_event_handler; + + n = aio_read(&aio->aiocb); + + if (n == -1) { + n = ngx_errno; + + if (n == NGX_EAGAIN) { + return ngx_read_file(file, buf, size, offset); + } + + ngx_log_error(NGX_LOG_CRIT, file->log, n, + "aio_read(\"%V\") failed", &file->name); + + if (n == NGX_ENOSYS) { + ngx_file_aio = 0; + return ngx_read_file(file, buf, size, offset); + } + + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio_read: fd:%d %d", file->fd, n); + + ev->active = 1; + ev->ready = 0; + ev->complete = 0; + + return ngx_file_aio_result(aio->file, aio, ev); +} + + +static ssize_t +ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, ngx_event_t *ev) +{ + int n; + ngx_err_t err; + + n = aio_error(&aio->aiocb); + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio_error: fd:%d %d", file->fd, n); + + if (n == -1) { + err = ngx_errno; + aio->err = err; + + ngx_log_error(NGX_LOG_ALERT, file->log, err, + "aio_error(\"%V\") failed", &file->name); + return NGX_ERROR; + } + + if (n == NGX_EINPROGRESS) { + if (ev->ready) { + ev->ready = 0; + ngx_log_error(NGX_LOG_ALERT, file->log, n, + "aio_read(\"%V\") still in progress", + &file->name); + } + + return NGX_AGAIN; + } + + n = aio_return(&aio->aiocb); + + if (n == -1) { + err = ngx_errno; + aio->err = err; + ev->ready = 1; + + ngx_log_error(NGX_LOG_CRIT, file->log, err, + "aio_return(\"%V\") failed", &file->name); + return NGX_ERROR; + } + + aio->err = 0; + aio->nbytes = n; + ev->ready = 1; + ev->active = 0; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio_return: fd:%d %d", file->fd, n); + + return n; +} + + +static void +ngx_file_aio_event_handler(ngx_event_t *ev) +{ + ngx_event_aio_t *aio; + + aio = ev->data; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0, + "aio event handler fd:%d %V", aio->fd, &aio->file->name); + + if (ngx_file_aio_result(aio->file, aio, ev) != NGX_AGAIN) { + aio->handler(ev); + } +} diff --git a/hm_nginx/src/os/unix/ngx_files.c b/hm_nginx/src/os/unix/ngx_files.c new file mode 100644 index 0000000..2a3ed2f --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_files.c @@ -0,0 +1,673 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#if (NGX_THREADS) +#include +static void ngx_thread_read_handler(void *data, ngx_log_t *log); +#endif + + +#if (NGX_HAVE_FILE_AIO) + +ngx_uint_t ngx_file_aio = 1; + +#endif + + +ssize_t +ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) +{ + ssize_t n; + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "read: %d, %p, %uz, %O", file->fd, buf, size, offset); + +#if (NGX_HAVE_PREAD) + + n = pread(file->fd, buf, size, offset); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "pread() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + +#else + + if (file->sys_offset != offset) { + if (lseek(file->fd, offset, SEEK_SET) == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "lseek() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->sys_offset = offset; + } + + n = read(file->fd, buf, size); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "read() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->sys_offset += n; + +#endif + + file->offset += n; + + return n; +} + + +#if (NGX_THREADS) + +typedef struct { + ngx_fd_t fd; + u_char *buf; + size_t size; + off_t offset; + + size_t read; + ngx_err_t err; +} ngx_thread_read_ctx_t; + + +ssize_t +ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, u_char *buf, + size_t size, off_t offset, ngx_pool_t *pool) +{ + ngx_thread_task_t *task; + ngx_thread_read_ctx_t *ctx; + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "thread read: %d, %p, %uz, %O", + file->fd, buf, size, offset); + + task = *taskp; + + if (task == NULL) { + task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_read_ctx_t)); + if (task == NULL) { + return NGX_ERROR; + } + + task->handler = ngx_thread_read_handler; + + *taskp = task; + } + + ctx = task->ctx; + + if (task->event.complete) { + task->event.complete = 0; + + if (ctx->err) { + ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err, + "pread() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + return ctx->read; + } + + ctx->fd = file->fd; + ctx->buf = buf; + ctx->size = size; + ctx->offset = offset; + + if (file->thread_handler(task, file) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_AGAIN; +} + + +#if (NGX_HAVE_PREAD) + +static void +ngx_thread_read_handler(void *data, ngx_log_t *log) +{ + ngx_thread_read_ctx_t *ctx = data; + + ssize_t n; + + ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler"); + + n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset); + + if (n == -1) { + ctx->err = ngx_errno; + + } else { + ctx->read = n; + ctx->err = 0; + } + +#if 0 + ngx_time_update(); +#endif + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0, + "pread: %z (err: %i) of %uz @%O", + n, ctx->err, ctx->size, ctx->offset); +} + +#else + +#error pread() is required! + +#endif + +#endif /* NGX_THREADS */ + + +ssize_t +ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) +{ + ssize_t n, written; + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "write: %d, %p, %uz, %O", file->fd, buf, size, offset); + + written = 0; + +#if (NGX_HAVE_PWRITE) + + for ( ;; ) { + n = pwrite(file->fd, buf + written, size, offset); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "pwrite() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->offset += n; + written += n; + + if ((size_t) n == size) { + return written; + } + + offset += n; + size -= n; + } + +#else + + if (file->sys_offset != offset) { + if (lseek(file->fd, offset, SEEK_SET) == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "lseek() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->sys_offset = offset; + } + + for ( ;; ) { + n = write(file->fd, buf + written, size); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "write() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->offset += n; + written += n; + + if ((size_t) n == size) { + return written; + } + + size -= n; + } +#endif +} + + +ngx_fd_t +ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access) +{ + ngx_fd_t fd; + + fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR, + access ? access : 0600); + + if (fd != -1 && !persistent) { + (void) unlink((const char *) name); + } + + return fd; +} + + +#define NGX_IOVS 8 + +ssize_t +ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, + ngx_pool_t *pool) +{ + u_char *prev; + size_t size; + ssize_t total, n; + ngx_array_t vec; + struct iovec *iov, iovs[NGX_IOVS]; + + /* use pwrite() if there is the only buf in a chain */ + + if (cl->next == NULL) { + return ngx_write_file(file, cl->buf->pos, + (size_t) (cl->buf->last - cl->buf->pos), + offset); + } + + total = 0; + + vec.elts = iovs; + vec.size = sizeof(struct iovec); + vec.nalloc = NGX_IOVS; + vec.pool = pool; + + do { + prev = NULL; + iov = NULL; + size = 0; + + vec.nelts = 0; + + /* create the iovec and coalesce the neighbouring bufs */ + + while (cl && vec.nelts < IOV_MAX) { + if (prev == cl->buf->pos) { + iov->iov_len += cl->buf->last - cl->buf->pos; + + } else { + iov = ngx_array_push(&vec); + if (iov == NULL) { + return NGX_ERROR; + } + + iov->iov_base = (void *) cl->buf->pos; + iov->iov_len = cl->buf->last - cl->buf->pos; + } + + size += cl->buf->last - cl->buf->pos; + prev = cl->buf->last; + cl = cl->next; + } + + /* use pwrite() if there is the only iovec buffer */ + + if (vec.nelts == 1) { + iov = vec.elts; + + n = ngx_write_file(file, (u_char *) iov[0].iov_base, + iov[0].iov_len, offset); + + if (n == NGX_ERROR) { + return n; + } + + return total + n; + } + + if (file->sys_offset != offset) { + if (lseek(file->fd, offset, SEEK_SET) == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "lseek() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->sys_offset = offset; + } + + n = writev(file->fd, vec.elts, vec.nelts); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "writev() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + if ((size_t) n != size) { + ngx_log_error(NGX_LOG_CRIT, file->log, 0, + "writev() \"%s\" has written only %z of %uz", + file->name.data, n, size); + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "writev: %d, %z", file->fd, n); + + file->sys_offset += n; + file->offset += n; + offset += n; + total += n; + + } while (cl); + + return total; +} + + +ngx_int_t +ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s) +{ + struct timeval tv[2]; + + tv[0].tv_sec = ngx_time(); + tv[0].tv_usec = 0; + tv[1].tv_sec = s; + tv[1].tv_usec = 0; + + if (utimes((char *) name, tv) != -1) { + return NGX_OK; + } + + return NGX_ERROR; +} + + +ngx_int_t +ngx_create_file_mapping(ngx_file_mapping_t *fm) +{ + fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, + NGX_FILE_DEFAULT_ACCESS); + if (fm->fd == NGX_INVALID_FILE) { + ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, + ngx_open_file_n " \"%s\" failed", fm->name); + return NGX_ERROR; + } + + if (ftruncate(fm->fd, fm->size) == -1) { + ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, + "ftruncate() \"%s\" failed", fm->name); + goto failed; + } + + fm->addr = mmap(NULL, fm->size, PROT_READ|PROT_WRITE, MAP_SHARED, + fm->fd, 0); + if (fm->addr != MAP_FAILED) { + return NGX_OK; + } + + ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, + "mmap(%uz) \"%s\" failed", fm->size, fm->name); + +failed: + + if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", fm->name); + } + + return NGX_ERROR; +} + + +void +ngx_close_file_mapping(ngx_file_mapping_t *fm) +{ + if (munmap(fm->addr, fm->size) == -1) { + ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, + "munmap(%uz) \"%s\" failed", fm->size, fm->name); + } + + if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", fm->name); + } +} + + +ngx_int_t +ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir) +{ + dir->dir = opendir((const char *) name->data); + + if (dir->dir == NULL) { + return NGX_ERROR; + } + + dir->valid_info = 0; + + return NGX_OK; +} + + +ngx_int_t +ngx_read_dir(ngx_dir_t *dir) +{ + dir->de = readdir(dir->dir); + + if (dir->de) { +#if (NGX_HAVE_D_TYPE) + dir->type = dir->de->d_type; +#else + dir->type = 0; +#endif + return NGX_OK; + } + + return NGX_ERROR; +} + + +ngx_int_t +ngx_open_glob(ngx_glob_t *gl) +{ + int n; + + n = glob((char *) gl->pattern, 0, NULL, &gl->pglob); + + if (n == 0) { + return NGX_OK; + } + +#ifdef GLOB_NOMATCH + + if (n == GLOB_NOMATCH && gl->test) { + return NGX_OK; + } + +#endif + + return NGX_ERROR; +} + + +ngx_int_t +ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name) +{ + size_t count; + +#ifdef GLOB_NOMATCH + count = (size_t) gl->pglob.gl_pathc; +#else + count = (size_t) gl->pglob.gl_matchc; +#endif + + if (gl->n < count) { + + name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]); + name->data = (u_char *) gl->pglob.gl_pathv[gl->n]; + gl->n++; + + return NGX_OK; + } + + return NGX_DONE; +} + + +void +ngx_close_glob(ngx_glob_t *gl) +{ + globfree(&gl->pglob); +} + + +ngx_err_t +ngx_trylock_fd(ngx_fd_t fd) +{ + struct flock fl; + + ngx_memzero(&fl, sizeof(struct flock)); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + + if (fcntl(fd, F_SETLK, &fl) == -1) { + return ngx_errno; + } + + return 0; +} + + +ngx_err_t +ngx_lock_fd(ngx_fd_t fd) +{ + struct flock fl; + + ngx_memzero(&fl, sizeof(struct flock)); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + + if (fcntl(fd, F_SETLKW, &fl) == -1) { + return ngx_errno; + } + + return 0; +} + + +ngx_err_t +ngx_unlock_fd(ngx_fd_t fd) +{ + struct flock fl; + + ngx_memzero(&fl, sizeof(struct flock)); + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + + if (fcntl(fd, F_SETLK, &fl) == -1) { + return ngx_errno; + } + + return 0; +} + + +#if (NGX_HAVE_POSIX_FADVISE) && !(NGX_HAVE_F_READAHEAD) + +ngx_int_t +ngx_read_ahead(ngx_fd_t fd, size_t n) +{ + int err; + + err = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); + + if (err == 0) { + return 0; + } + + ngx_set_errno(err); + return NGX_FILE_ERROR; +} + +#endif + + +#if (NGX_HAVE_O_DIRECT) + +ngx_int_t +ngx_directio_on(ngx_fd_t fd) +{ + int flags; + + flags = fcntl(fd, F_GETFL); + + if (flags == -1) { + return NGX_FILE_ERROR; + } + + return fcntl(fd, F_SETFL, flags | O_DIRECT); +} + + +ngx_int_t +ngx_directio_off(ngx_fd_t fd) +{ + int flags; + + flags = fcntl(fd, F_GETFL); + + if (flags == -1) { + return NGX_FILE_ERROR; + } + + return fcntl(fd, F_SETFL, flags & ~O_DIRECT); +} + +#endif + + +#if (NGX_HAVE_STATFS) + +size_t +ngx_fs_bsize(u_char *name) +{ + struct statfs fs; + + if (statfs((char *) name, &fs) == -1) { + return 512; + } + + if ((fs.f_bsize % 512) != 0) { + return 512; + } + + return (size_t) fs.f_bsize; +} + +#elif (NGX_HAVE_STATVFS) + +size_t +ngx_fs_bsize(u_char *name) +{ + struct statvfs fs; + + if (statvfs((char *) name, &fs) == -1) { + return 512; + } + + if ((fs.f_frsize % 512) != 0) { + return 512; + } + + return (size_t) fs.f_frsize; +} + +#else + +size_t +ngx_fs_bsize(u_char *name) +{ + return 512; +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_files.h b/hm_nginx/src/os/unix/ngx_files.h new file mode 100644 index 0000000..b6990bc --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_files.h @@ -0,0 +1,392 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_FILES_H_INCLUDED_ +#define _NGX_FILES_H_INCLUDED_ + + +#include +#include + + +typedef int ngx_fd_t; +typedef struct stat ngx_file_info_t; +typedef ino_t ngx_file_uniq_t; + + +typedef struct { + u_char *name; + size_t size; + void *addr; + ngx_fd_t fd; + ngx_log_t *log; +} ngx_file_mapping_t; + + +typedef struct { + DIR *dir; + struct dirent *de; + struct stat info; + + unsigned type:8; + unsigned valid_info:1; +} ngx_dir_t; + + +typedef struct { + size_t n; + glob_t pglob; + u_char *pattern; + ngx_log_t *log; + ngx_uint_t test; +} ngx_glob_t; + + +#define NGX_INVALID_FILE -1 +#define NGX_FILE_ERROR -1 + + + +#ifdef __CYGWIN__ + +#ifndef NGX_HAVE_CASELESS_FILESYSTEM +#define NGX_HAVE_CASELESS_FILESYSTEM 1 +#endif + +#define ngx_open_file(name, mode, create, access) \ + open((const char *) name, mode|create|O_BINARY, access) + +#else + +#define ngx_open_file(name, mode, create, access) \ + open((const char *) name, mode|create, access) + +#endif + +#define ngx_open_file_n "open()" + +#define NGX_FILE_RDONLY O_RDONLY +#define NGX_FILE_WRONLY O_WRONLY +#define NGX_FILE_RDWR O_RDWR +#define NGX_FILE_CREATE_OR_OPEN O_CREAT +#define NGX_FILE_OPEN 0 +#define NGX_FILE_TRUNCATE (O_CREAT|O_TRUNC) +#define NGX_FILE_APPEND (O_WRONLY|O_APPEND) +#define NGX_FILE_NONBLOCK O_NONBLOCK + +#if (NGX_HAVE_OPENAT) +#define NGX_FILE_NOFOLLOW O_NOFOLLOW + +#if defined(O_DIRECTORY) +#define NGX_FILE_DIRECTORY O_DIRECTORY +#else +#define NGX_FILE_DIRECTORY 0 +#endif + +#if defined(O_SEARCH) +#define NGX_FILE_SEARCH (O_SEARCH|NGX_FILE_DIRECTORY) + +#elif defined(O_EXEC) +#define NGX_FILE_SEARCH (O_EXEC|NGX_FILE_DIRECTORY) + +#elif (NGX_HAVE_O_PATH) +#define NGX_FILE_SEARCH (O_PATH|O_RDONLY|NGX_FILE_DIRECTORY) + +#else +#define NGX_FILE_SEARCH (O_RDONLY|NGX_FILE_DIRECTORY) +#endif + +#endif /* NGX_HAVE_OPENAT */ + +#define NGX_FILE_DEFAULT_ACCESS 0644 +#define NGX_FILE_OWNER_ACCESS 0600 + + +#define ngx_close_file close +#define ngx_close_file_n "close()" + + +#define ngx_delete_file(name) unlink((const char *) name) +#define ngx_delete_file_n "unlink()" + + +ngx_fd_t ngx_open_tempfile(u_char *name, ngx_uint_t persistent, + ngx_uint_t access); +#define ngx_open_tempfile_n "open()" + + +ssize_t ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset); +#if (NGX_HAVE_PREAD) +#define ngx_read_file_n "pread()" +#else +#define ngx_read_file_n "read()" +#endif + +ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, + off_t offset); + +ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce, + off_t offset, ngx_pool_t *pool); + + +#define ngx_read_fd read +#define ngx_read_fd_n "read()" + +/* + * we use inlined function instead of simple #define + * because glibc 2.3 sets warn_unused_result attribute for write() + * and in this case gcc 4.3 ignores (void) cast + */ +static ngx_inline ssize_t +ngx_write_fd(ngx_fd_t fd, void *buf, size_t n) +{ + return write(fd, buf, n); +} + +#define ngx_write_fd_n "write()" + + +#define ngx_write_console ngx_write_fd + + +#define ngx_linefeed(p) *p++ = LF; +#define NGX_LINEFEED_SIZE 1 +#define NGX_LINEFEED "\x0a" + + +#define ngx_rename_file(o, n) rename((const char *) o, (const char *) n) +#define ngx_rename_file_n "rename()" + + +#define ngx_change_file_access(n, a) chmod((const char *) n, a) +#define ngx_change_file_access_n "chmod()" + + +ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s); +#define ngx_set_file_time_n "utimes()" + + +#define ngx_file_info(file, sb) stat((const char *) file, sb) +#define ngx_file_info_n "stat()" + +#define ngx_fd_info(fd, sb) fstat(fd, sb) +#define ngx_fd_info_n "fstat()" + +#define ngx_link_info(file, sb) lstat((const char *) file, sb) +#define ngx_link_info_n "lstat()" + +#define ngx_is_dir(sb) (S_ISDIR((sb)->st_mode)) +#define ngx_is_file(sb) (S_ISREG((sb)->st_mode)) +#define ngx_is_link(sb) (S_ISLNK((sb)->st_mode)) +#define ngx_is_exec(sb) (((sb)->st_mode & S_IXUSR) == S_IXUSR) +#define ngx_file_access(sb) ((sb)->st_mode & 0777) +#define ngx_file_size(sb) (sb)->st_size +#define ngx_file_fs_size(sb) ngx_max((sb)->st_size, (sb)->st_blocks * 512) +#define ngx_file_mtime(sb) (sb)->st_mtime +#define ngx_file_uniq(sb) (sb)->st_ino + + +ngx_int_t ngx_create_file_mapping(ngx_file_mapping_t *fm); +void ngx_close_file_mapping(ngx_file_mapping_t *fm); + + +#define ngx_realpath(p, r) (u_char *) realpath((char *) p, (char *) r) +#define ngx_realpath_n "realpath()" +#define ngx_getcwd(buf, size) (getcwd((char *) buf, size) != NULL) +#define ngx_getcwd_n "getcwd()" +#define ngx_path_separator(c) ((c) == '/') + + +#if defined(PATH_MAX) + +#define NGX_HAVE_MAX_PATH 1 +#define NGX_MAX_PATH PATH_MAX + +#else + +#define NGX_MAX_PATH 4096 + +#endif + + +#define NGX_DIR_MASK_LEN 0 + + +ngx_int_t ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir); +#define ngx_open_dir_n "opendir()" + + +#define ngx_close_dir(d) closedir((d)->dir) +#define ngx_close_dir_n "closedir()" + + +ngx_int_t ngx_read_dir(ngx_dir_t *dir); +#define ngx_read_dir_n "readdir()" + + +#define ngx_create_dir(name, access) mkdir((const char *) name, access) +#define ngx_create_dir_n "mkdir()" + + +#define ngx_delete_dir(name) rmdir((const char *) name) +#define ngx_delete_dir_n "rmdir()" + + +#define ngx_dir_access(a) (a | (a & 0444) >> 2) + + +#define ngx_de_name(dir) ((u_char *) (dir)->de->d_name) +#if (NGX_HAVE_D_NAMLEN) +#define ngx_de_namelen(dir) (dir)->de->d_namlen +#else +#define ngx_de_namelen(dir) ngx_strlen((dir)->de->d_name) +#endif + +static ngx_inline ngx_int_t +ngx_de_info(u_char *name, ngx_dir_t *dir) +{ + dir->type = 0; + return stat((const char *) name, &dir->info); +} + +#define ngx_de_info_n "stat()" +#define ngx_de_link_info(name, dir) lstat((const char *) name, &(dir)->info) +#define ngx_de_link_info_n "lstat()" + +#if (NGX_HAVE_D_TYPE) + +/* + * some file systems (e.g. XFS on Linux and CD9660 on FreeBSD) + * do not set dirent.d_type + */ + +#define ngx_de_is_dir(dir) \ + (((dir)->type) ? ((dir)->type == DT_DIR) : (S_ISDIR((dir)->info.st_mode))) +#define ngx_de_is_file(dir) \ + (((dir)->type) ? ((dir)->type == DT_REG) : (S_ISREG((dir)->info.st_mode))) +#define ngx_de_is_link(dir) \ + (((dir)->type) ? ((dir)->type == DT_LNK) : (S_ISLNK((dir)->info.st_mode))) + +#else + +#define ngx_de_is_dir(dir) (S_ISDIR((dir)->info.st_mode)) +#define ngx_de_is_file(dir) (S_ISREG((dir)->info.st_mode)) +#define ngx_de_is_link(dir) (S_ISLNK((dir)->info.st_mode)) + +#endif + +#define ngx_de_access(dir) (((dir)->info.st_mode) & 0777) +#define ngx_de_size(dir) (dir)->info.st_size +#define ngx_de_fs_size(dir) \ + ngx_max((dir)->info.st_size, (dir)->info.st_blocks * 512) +#define ngx_de_mtime(dir) (dir)->info.st_mtime + + +ngx_int_t ngx_open_glob(ngx_glob_t *gl); +#define ngx_open_glob_n "glob()" +ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name); +void ngx_close_glob(ngx_glob_t *gl); + + +ngx_err_t ngx_trylock_fd(ngx_fd_t fd); +ngx_err_t ngx_lock_fd(ngx_fd_t fd); +ngx_err_t ngx_unlock_fd(ngx_fd_t fd); + +#define ngx_trylock_fd_n "fcntl(F_SETLK, F_WRLCK)" +#define ngx_lock_fd_n "fcntl(F_SETLKW, F_WRLCK)" +#define ngx_unlock_fd_n "fcntl(F_SETLK, F_UNLCK)" + + +#if (NGX_HAVE_F_READAHEAD) + +#define NGX_HAVE_READ_AHEAD 1 + +#define ngx_read_ahead(fd, n) fcntl(fd, F_READAHEAD, (int) n) +#define ngx_read_ahead_n "fcntl(fd, F_READAHEAD)" + +#elif (NGX_HAVE_POSIX_FADVISE) + +#define NGX_HAVE_READ_AHEAD 1 + +ngx_int_t ngx_read_ahead(ngx_fd_t fd, size_t n); +#define ngx_read_ahead_n "posix_fadvise(POSIX_FADV_SEQUENTIAL)" + +#else + +#define ngx_read_ahead(fd, n) 0 +#define ngx_read_ahead_n "ngx_read_ahead_n" + +#endif + + +#if (NGX_HAVE_O_DIRECT) + +ngx_int_t ngx_directio_on(ngx_fd_t fd); +#define ngx_directio_on_n "fcntl(O_DIRECT)" + +ngx_int_t ngx_directio_off(ngx_fd_t fd); +#define ngx_directio_off_n "fcntl(!O_DIRECT)" + +#elif (NGX_HAVE_F_NOCACHE) + +#define ngx_directio_on(fd) fcntl(fd, F_NOCACHE, 1) +#define ngx_directio_on_n "fcntl(F_NOCACHE, 1)" + +#elif (NGX_HAVE_DIRECTIO) + +#define ngx_directio_on(fd) directio(fd, DIRECTIO_ON) +#define ngx_directio_on_n "directio(DIRECTIO_ON)" + +#else + +#define ngx_directio_on(fd) 0 +#define ngx_directio_on_n "ngx_directio_on_n" + +#endif + +size_t ngx_fs_bsize(u_char *name); + + +#if (NGX_HAVE_OPENAT) + +#define ngx_openat_file(fd, name, mode, create, access) \ + openat(fd, (const char *) name, mode|create, access) + +#define ngx_openat_file_n "openat()" + +#define ngx_file_at_info(fd, name, sb, flag) \ + fstatat(fd, (const char *) name, sb, flag) + +#define ngx_file_at_info_n "fstatat()" + +#define NGX_AT_FDCWD (ngx_fd_t) AT_FDCWD + +#endif + + +#define ngx_stderr STDERR_FILENO +#define ngx_set_stderr(fd) dup2(fd, STDERR_FILENO) +#define ngx_set_stderr_n "dup2(STDERR_FILENO)" + + +#if (NGX_HAVE_FILE_AIO) + +ngx_int_t ngx_file_aio_init(ngx_file_t *file, ngx_pool_t *pool); +ssize_t ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, + off_t offset, ngx_pool_t *pool); + +extern ngx_uint_t ngx_file_aio; + +#endif + +#if (NGX_THREADS) +ssize_t ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, + u_char *buf, size_t size, off_t offset, ngx_pool_t *pool); +#endif + + +#endif /* _NGX_FILES_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_freebsd.h b/hm_nginx/src/os/unix/ngx_freebsd.h new file mode 100644 index 0000000..4f93da5 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_freebsd.h @@ -0,0 +1,25 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_FREEBSD_H_INCLUDED_ +#define _NGX_FREEBSD_H_INCLUDED_ + + +void ngx_debug_init(void); +ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + +extern int ngx_freebsd_kern_osreldate; +extern int ngx_freebsd_hw_ncpu; +extern u_long ngx_freebsd_net_inet_tcp_sendspace; + +extern ngx_uint_t ngx_freebsd_sendfile_nbytes_bug; +extern ngx_uint_t ngx_freebsd_use_tcp_nopush; +extern ngx_uint_t ngx_debug_malloc; + + +#endif /* _NGX_FREEBSD_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_freebsd_config.h b/hm_nginx/src/os/unix/ngx_freebsd_config.h new file mode 100644 index 0000000..8f06051 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_freebsd_config.h @@ -0,0 +1,121 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_FREEBSD_CONFIG_H_INCLUDED_ +#define _NGX_FREEBSD_CONFIG_H_INCLUDED_ + + +#include +#include +#include +#include +#include /* offsetof() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* ALIGN() */ +#include /* statfs() */ + +#include /* FIONBIO */ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include /* TCP_NODELAY, TCP_NOPUSH */ +#include +#include +#include + +#include /* setproctitle() before 4.1 */ +#include +#include + + +#if __FreeBSD_version < 400017 + +/* + * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA() + */ + +#undef CMSG_SPACE +#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l)) + +#undef CMSG_LEN +#define CMSG_LEN(l) (ALIGN(sizeof(struct cmsghdr)) + (l)) + +#undef CMSG_DATA +#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr))) + +#endif + + +#include + + +#if (NGX_HAVE_POSIX_SEM) +#include +#endif + + +#if (NGX_HAVE_POLL) +#include +#endif + + +#if (NGX_HAVE_KQUEUE) +#include +#endif + + +#if (NGX_HAVE_FILE_AIO || NGX_HAVE_AIO) +#include +typedef struct aiocb ngx_aiocb_t; +#endif + + +#define NGX_LISTEN_BACKLOG -1 + + +#ifdef __DragonFly__ +#define NGX_KEEPALIVE_FACTOR 1000 +#endif + + +#ifndef IOV_MAX +#define IOV_MAX 1024 +#endif + + +#ifndef NGX_HAVE_INHERITED_NONBLOCK +#define NGX_HAVE_INHERITED_NONBLOCK 1 +#endif + + +#define NGX_HAVE_OS_SPECIFIC_INIT 1 +#define NGX_HAVE_DEBUG_MALLOC 1 + + +extern char **environ; +extern char *malloc_options; + + +#endif /* _NGX_FREEBSD_CONFIG_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_freebsd_init.c b/hm_nginx/src/os/unix/ngx_freebsd_init.c new file mode 100644 index 0000000..c4c12dd --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_freebsd_init.c @@ -0,0 +1,260 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +/* FreeBSD 3.0 at least */ +char ngx_freebsd_kern_ostype[16]; +char ngx_freebsd_kern_osrelease[128]; +int ngx_freebsd_kern_osreldate; +int ngx_freebsd_hw_ncpu; +int ngx_freebsd_kern_ipc_somaxconn; +u_long ngx_freebsd_net_inet_tcp_sendspace; + +/* FreeBSD 4.9 */ +int ngx_freebsd_machdep_hlt_logical_cpus; + + +ngx_uint_t ngx_freebsd_sendfile_nbytes_bug; +ngx_uint_t ngx_freebsd_use_tcp_nopush; + +ngx_uint_t ngx_debug_malloc; + + +static ngx_os_io_t ngx_freebsd_io = { + ngx_unix_recv, + ngx_readv_chain, + ngx_udp_unix_recv, + ngx_unix_send, +#if (NGX_HAVE_SENDFILE) + ngx_freebsd_sendfile_chain, + NGX_IO_SENDFILE +#else + ngx_writev_chain, + 0 +#endif +}; + + +typedef struct { + char *name; + void *value; + size_t size; + ngx_uint_t exists; +} sysctl_t; + + +sysctl_t sysctls[] = { + { "hw.ncpu", + &ngx_freebsd_hw_ncpu, + sizeof(ngx_freebsd_hw_ncpu), 0 }, + + { "machdep.hlt_logical_cpus", + &ngx_freebsd_machdep_hlt_logical_cpus, + sizeof(ngx_freebsd_machdep_hlt_logical_cpus), 0 }, + + { "net.inet.tcp.sendspace", + &ngx_freebsd_net_inet_tcp_sendspace, + sizeof(ngx_freebsd_net_inet_tcp_sendspace), 0 }, + + { "kern.ipc.somaxconn", + &ngx_freebsd_kern_ipc_somaxconn, + sizeof(ngx_freebsd_kern_ipc_somaxconn), 0 }, + + { NULL, NULL, 0, 0 } +}; + + +void +ngx_debug_init(void) +{ +#if (NGX_DEBUG_MALLOC) + +#if __FreeBSD_version >= 500014 && __FreeBSD_version < 1000011 + _malloc_options = "J"; +#elif __FreeBSD_version < 500014 + malloc_options = "J"; +#endif + + ngx_debug_malloc = 1; + +#else + char *mo; + + mo = getenv("MALLOC_OPTIONS"); + + if (mo && ngx_strchr(mo, 'J')) { + ngx_debug_malloc = 1; + } +#endif +} + + +ngx_int_t +ngx_os_specific_init(ngx_log_t *log) +{ + int version; + size_t size; + ngx_err_t err; + ngx_uint_t i; + + size = sizeof(ngx_freebsd_kern_ostype); + if (sysctlbyname("kern.ostype", + ngx_freebsd_kern_ostype, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysctlbyname(kern.ostype) failed"); + + if (ngx_errno != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_freebsd_kern_ostype[size - 1] = '\0'; + } + + size = sizeof(ngx_freebsd_kern_osrelease); + if (sysctlbyname("kern.osrelease", + ngx_freebsd_kern_osrelease, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysctlbyname(kern.osrelease) failed"); + + if (ngx_errno != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_freebsd_kern_osrelease[size - 1] = '\0'; + } + + + size = sizeof(int); + if (sysctlbyname("kern.osreldate", + &ngx_freebsd_kern_osreldate, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysctlbyname(kern.osreldate) failed"); + return NGX_ERROR; + } + + version = ngx_freebsd_kern_osreldate; + + +#if (NGX_HAVE_SENDFILE) + + /* + * The determination of the sendfile() "nbytes bug" is complex enough. + * There are two sendfile() syscalls: a new #393 has no bug while + * an old #336 has the bug in some versions and has not in others. + * Besides libc_r wrapper also emulates the bug in some versions. + * There is no way to say exactly if syscall #336 in FreeBSD circa 4.6 + * has the bug. We use the algorithm that is correct at least for + * RELEASEs and for syscalls only (not libc_r wrapper). + * + * 4.6.1-RELEASE and below have the bug + * 4.6.2-RELEASE and above have the new syscall + * + * We detect the new sendfile() syscall available at the compile time + * to allow an old binary to run correctly on an updated FreeBSD system. + */ + +#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \ + || __FreeBSD_version == 460002 || __FreeBSD_version >= 500039 + + /* a new syscall without the bug */ + + ngx_freebsd_sendfile_nbytes_bug = 0; + +#else + + /* an old syscall that may have the bug */ + + ngx_freebsd_sendfile_nbytes_bug = 1; + +#endif + +#endif /* NGX_HAVE_SENDFILE */ + + + if ((version < 500000 && version >= 440003) || version >= 500017) { + ngx_freebsd_use_tcp_nopush = 1; + } + + + for (i = 0; sysctls[i].name; i++) { + size = sysctls[i].size; + + if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0) + == 0) + { + sysctls[i].exists = 1; + continue; + } + + err = ngx_errno; + + if (err == NGX_ENOENT) { + continue; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(%s) failed", sysctls[i].name); + return NGX_ERROR; + } + + if (ngx_freebsd_machdep_hlt_logical_cpus) { + ngx_ncpu = ngx_freebsd_hw_ncpu / 2; + + } else { + ngx_ncpu = ngx_freebsd_hw_ncpu; + } + + if (version < 600008 && ngx_freebsd_kern_ipc_somaxconn > 32767) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "sysctl kern.ipc.somaxconn must be less than 32768"); + return NGX_ERROR; + } + + ngx_tcp_nodelay_and_tcp_nopush = 1; + + ngx_os_io = ngx_freebsd_io; + + return NGX_OK; +} + + +void +ngx_os_specific_status(ngx_log_t *log) +{ + u_long value; + ngx_uint_t i; + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", + ngx_freebsd_kern_ostype, ngx_freebsd_kern_osrelease); + +#ifdef __DragonFly_version + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "kern.osreldate: %d, built on %d", + ngx_freebsd_kern_osreldate, __DragonFly_version); +#else + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "kern.osreldate: %d, built on %d", + ngx_freebsd_kern_osreldate, __FreeBSD_version); +#endif + + for (i = 0; sysctls[i].name; i++) { + if (sysctls[i].exists) { + if (sysctls[i].size == sizeof(long)) { + value = *(long *) sysctls[i].value; + + } else { + value = *(int *) sysctls[i].value; + } + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l", + sysctls[i].name, value); + } + } +} diff --git a/hm_nginx/src/os/unix/ngx_freebsd_sendfile_chain.c b/hm_nginx/src/os/unix/ngx_freebsd_sendfile_chain.c new file mode 100644 index 0000000..3f17dc6 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -0,0 +1,312 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +/* + * Although FreeBSD sendfile() allows to pass a header and a trailer, + * it cannot send a header with a part of the file in one packet until + * FreeBSD 5.3. Besides, over the fast ethernet connection sendfile() + * may send the partially filled packets, i.e. the 8 file pages may be sent + * as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet, + * and then again the 11 full 1460-bytes packets. + * + * Therefore we use the TCP_NOPUSH option (similar to Linux's TCP_CORK) + * to postpone the sending - it not only sends a header and the first part of + * the file in one packet, but also sends the file pages in the full packets. + * + * But until FreeBSD 4.5 turning TCP_NOPUSH off does not flush a pending + * data that less than MSS, so that data may be sent with 5 second delay. + * So we do not use TCP_NOPUSH on FreeBSD prior to 4.5, although it can be used + * for non-keepalive HTTP connections. + */ + + +ngx_chain_t * +ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) +{ + int rc, flags; + off_t send, prev_send, sent; + size_t file_size; + ssize_t n; + ngx_uint_t eintr, eagain; + ngx_err_t err; + ngx_buf_t *file; + ngx_event_t *wev; + ngx_chain_t *cl; + ngx_iovec_t header, trailer; + struct sf_hdtr hdtr; + struct iovec headers[NGX_IOVS_PREALLOCATE]; + struct iovec trailers[NGX_IOVS_PREALLOCATE]; +#if (NGX_HAVE_AIO_SENDFILE) + ngx_uint_t ebusy; + ngx_event_aio_t *aio; +#endif + + wev = c->write; + + if (!wev->ready) { + return in; + } + +#if (NGX_HAVE_KQUEUE) + + if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); + wev->error = 1; + return NGX_CHAIN_ERROR; + } + +#endif + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { + limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; + eagain = 0; + flags = 0; + +#if (NGX_HAVE_AIO_SENDFILE && NGX_SUPPRESS_WARN) + aio = NULL; + file = NULL; +#endif + + header.iovs = headers; + header.nalloc = NGX_IOVS_PREALLOCATE; + + trailer.iovs = trailers; + trailer.nalloc = NGX_IOVS_PREALLOCATE; + + for ( ;; ) { + eintr = 0; +#if (NGX_HAVE_AIO_SENDFILE) + ebusy = 0; +#endif + prev_send = send; + + /* create the header iovec and coalesce the neighbouring bufs */ + + cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log); + + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + send += header.size; + + if (cl && cl->buf->in_file && send < limit) { + file = cl->buf; + + /* coalesce the neighbouring file bufs */ + + file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send); + + send += file_size; + + /* create the trailer iovec and coalesce the neighbouring bufs */ + + cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, c->log); + + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + send += trailer.size; + + if (ngx_freebsd_use_tcp_nopush + && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET) + { + if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { + err = ngx_socket_errno; + + /* + * there is a tiny chance to be interrupted, however, + * we continue a processing without the TCP_NOPUSH + */ + + if (err != NGX_EINTR) { + wev->error = 1; + (void) ngx_connection_error(c, err, + ngx_tcp_nopush_n " failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nopush = NGX_TCP_NOPUSH_SET; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "tcp_nopush"); + } + } + + /* + * sendfile() does unneeded work if sf_hdtr's count is 0, + * but corresponding pointer is not NULL + */ + + hdtr.headers = header.count ? header.iovs : NULL; + hdtr.hdr_cnt = header.count; + hdtr.trailers = trailer.count ? trailer.iovs : NULL; + hdtr.trl_cnt = trailer.count; + + /* + * the "nbytes bug" of the old sendfile() syscall: + * http://bugs.freebsd.org/33771 + */ + + if (!ngx_freebsd_sendfile_nbytes_bug) { + header.size = 0; + } + + sent = 0; + +#if (NGX_HAVE_AIO_SENDFILE) + aio = file->file->aio; + flags = (aio && aio->preload_handler) ? SF_NODISKIO : 0; +#endif + + rc = sendfile(file->file->fd, c->fd, file->file_pos, + file_size + header.size, &hdtr, &sent, flags); + + if (rc == -1) { + err = ngx_errno; + + switch (err) { + case NGX_EAGAIN: + eagain = 1; + break; + + case NGX_EINTR: + eintr = 1; + break; + +#if (NGX_HAVE_AIO_SENDFILE) + case NGX_EBUSY: + ebusy = 1; + break; +#endif + + default: + wev->error = 1; + (void) ngx_connection_error(c, err, "sendfile() failed"); + return NGX_CHAIN_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, + "sendfile() sent only %O bytes", sent); + + /* + * sendfile() in FreeBSD 3.x-4.x may return value >= 0 + * on success, although only 0 is documented + */ + + } else if (rc >= 0 && sent == 0) { + + /* + * if rc is OK and sent equal to zero, then someone + * has truncated the file, so the offset became beyond + * the end of the file + */ + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfile() reported that \"%s\" was truncated at %O", + file->file->name.data, file->file_pos); + + return NGX_CHAIN_ERROR; + } + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendfile: %d, @%O %O:%uz", + rc, file->file_pos, sent, file_size + header.size); + + } else { + n = ngx_writev(c, &header); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + sent = (n == NGX_AGAIN) ? 0 : n; + } + + c->sent += sent; + + in = ngx_chain_update_sent(in, sent); + +#if (NGX_HAVE_AIO_SENDFILE) + + if (ebusy) { + if (sent == 0) { + c->busy_count++; + + if (c->busy_count > 2) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfile(%V) returned busy again", + &file->file->name); + + c->busy_count = 0; + aio->preload_handler = NULL; + + send = prev_send; + continue; + } + + } else { + c->busy_count = 0; + } + + n = aio->preload_handler(file); + + if (n > 0) { + send = prev_send + sent; + continue; + } + + return in; + } + + if (flags == SF_NODISKIO) { + c->busy_count = 0; + } + +#endif + + if (eagain) { + + /* + * sendfile() may return EAGAIN, even if it has sent a whole file + * part, it indicates that the successive sendfile() call would + * return EAGAIN right away and would not send anything. + * We use it as a hint. + */ + + wev->ready = 0; + return in; + } + + if (eintr) { + send = prev_send + sent; + continue; + } + + if (send - prev_send != sent) { + wev->ready = 0; + return in; + } + + if (send >= limit || in == NULL) { + return in; + } + } +} diff --git a/hm_nginx/src/os/unix/ngx_gcc_atomic_amd64.h b/hm_nginx/src/os/unix/ngx_gcc_atomic_amd64.h new file mode 100644 index 0000000..159a297 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_gcc_atomic_amd64.h @@ -0,0 +1,82 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#if (NGX_SMP) +#define NGX_SMP_LOCK "lock;" +#else +#define NGX_SMP_LOCK +#endif + + +/* + * "cmpxchgq r, [m]": + * + * if (rax == [m]) { + * zf = 1; + * [m] = r; + * } else { + * zf = 0; + * rax = [m]; + * } + * + * + * The "r" is any register, %rax (%r0) - %r16. + * The "=a" and "a" are the %rax register. + * Although we can return result in any register, we use "a" because it is + * used in cmpxchgq anyway. The result is actually in %al but not in $rax, + * however as the code is inlined gcc can test %al as well as %rax. + * + * The "cc" means that flags were changed. + */ + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + u_char res; + + __asm__ volatile ( + + NGX_SMP_LOCK + " cmpxchgq %3, %1; " + " sete %0; " + + : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory"); + + return res; +} + + +/* + * "xaddq r, [m]": + * + * temp = [m]; + * [m] += r; + * r = temp; + * + * + * The "+r" is any register, %rax (%r0) - %r16. + * The "cc" means that flags were changed. + */ + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + __asm__ volatile ( + + NGX_SMP_LOCK + " xaddq %0, %1; " + + : "+r" (add) : "m" (*value) : "cc", "memory"); + + return add; +} + + +#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") + +#define ngx_cpu_pause() __asm__ ("pause") diff --git a/hm_nginx/src/os/unix/ngx_gcc_atomic_ppc.h b/hm_nginx/src/os/unix/ngx_gcc_atomic_ppc.h new file mode 100644 index 0000000..45afc4b --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_gcc_atomic_ppc.h @@ -0,0 +1,155 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +/* + * The ppc assembler treats ";" as comment, so we have to use "\n". + * The minus in "bne-" is a hint for the branch prediction unit that + * this branch is unlikely to be taken. + * The "1b" means the nearest backward label "1" and the "1f" means + * the nearest forward label "1". + * + * The "b" means that the base registers can be used only, i.e. + * any register except r0. The r0 register always has a zero value and + * could not be used in "addi r0, r0, 1". + * The "=&b" means that no input registers can be used. + * + * "sync" read and write barriers + * "isync" read barrier, is faster than "sync" + * "eieio" write barrier, is faster than "sync" + * "lwsync" write barrier, is faster than "eieio" on ppc64 + */ + +#if (NGX_PTR_SIZE == 8) + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + ngx_atomic_uint_t res, temp; + + __asm__ volatile ( + + " li %0, 0 \n" /* preset "0" to "res" */ + " lwsync \n" /* write barrier */ + "1: \n" + " ldarx %1, 0, %2 \n" /* load from [lock] into "temp" */ + /* and store reservation */ + " cmpd %1, %3 \n" /* compare "temp" and "old" */ + " bne- 2f \n" /* not equal */ + " stdcx. %4, 0, %2 \n" /* store "set" into [lock] if reservation */ + /* is not cleared */ + " bne- 1b \n" /* the reservation was cleared */ + " isync \n" /* read barrier */ + " li %0, 1 \n" /* set "1" to "res" */ + "2: \n" + + : "=&b" (res), "=&b" (temp) + : "b" (lock), "b" (old), "b" (set) + : "cc", "memory"); + + return res; +} + + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_uint_t res, temp; + + __asm__ volatile ( + + " lwsync \n" /* write barrier */ + "1: ldarx %0, 0, %2 \n" /* load from [value] into "res" */ + /* and store reservation */ + " add %1, %0, %3 \n" /* "res" + "add" store in "temp" */ + " stdcx. %1, 0, %2 \n" /* store "temp" into [value] if reservation */ + /* is not cleared */ + " bne- 1b \n" /* try again if reservation was cleared */ + " isync \n" /* read barrier */ + + : "=&b" (res), "=&b" (temp) + : "b" (value), "b" (add) + : "cc", "memory"); + + return res; +} + + +#if (NGX_SMP) +#define ngx_memory_barrier() \ + __asm__ volatile ("isync \n lwsync \n" ::: "memory") +#else +#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") +#endif + +#else + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + ngx_atomic_uint_t res, temp; + + __asm__ volatile ( + + " li %0, 0 \n" /* preset "0" to "res" */ + " eieio \n" /* write barrier */ + "1: \n" + " lwarx %1, 0, %2 \n" /* load from [lock] into "temp" */ + /* and store reservation */ + " cmpw %1, %3 \n" /* compare "temp" and "old" */ + " bne- 2f \n" /* not equal */ + " stwcx. %4, 0, %2 \n" /* store "set" into [lock] if reservation */ + /* is not cleared */ + " bne- 1b \n" /* the reservation was cleared */ + " isync \n" /* read barrier */ + " li %0, 1 \n" /* set "1" to "res" */ + "2: \n" + + : "=&b" (res), "=&b" (temp) + : "b" (lock), "b" (old), "b" (set) + : "cc", "memory"); + + return res; +} + + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_uint_t res, temp; + + __asm__ volatile ( + + " eieio \n" /* write barrier */ + "1: lwarx %0, 0, %2 \n" /* load from [value] into "res" */ + /* and store reservation */ + " add %1, %0, %3 \n" /* "res" + "add" store in "temp" */ + " stwcx. %1, 0, %2 \n" /* store "temp" into [value] if reservation */ + /* is not cleared */ + " bne- 1b \n" /* try again if reservation was cleared */ + " isync \n" /* read barrier */ + + : "=&b" (res), "=&b" (temp) + : "b" (value), "b" (add) + : "cc", "memory"); + + return res; +} + + +#if (NGX_SMP) +#define ngx_memory_barrier() \ + __asm__ volatile ("isync \n eieio \n" ::: "memory") +#else +#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") +#endif + +#endif + + +#define ngx_cpu_pause() diff --git a/hm_nginx/src/os/unix/ngx_gcc_atomic_sparc64.h b/hm_nginx/src/os/unix/ngx_gcc_atomic_sparc64.h new file mode 100644 index 0000000..a84db35 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_gcc_atomic_sparc64.h @@ -0,0 +1,82 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +/* + * "casa [r1] 0x80, r2, r0" and + * "casxa [r1] 0x80, r2, r0" do the following: + * + * if ([r1] == r2) { + * swap(r0, [r1]); + * } else { + * r0 = [r1]; + * } + * + * so "r0 == r2" means that the operation was successful. + * + * + * The "r" means the general register. + * The "+r" means the general register used for both input and output. + */ + + +#if (NGX_PTR_SIZE == 4) +#define NGX_CASA "casa" +#else +#define NGX_CASA "casxa" +#endif + + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + __asm__ volatile ( + + NGX_CASA " [%1] 0x80, %2, %0" + + : "+r" (set) : "r" (lock), "r" (old) : "memory"); + + return (set == old); +} + + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_uint_t old, res; + + old = *value; + + for ( ;; ) { + + res = old + add; + + __asm__ volatile ( + + NGX_CASA " [%1] 0x80, %2, %0" + + : "+r" (res) : "r" (value), "r" (old) : "memory"); + + if (res == old) { + return res; + } + + old = res; + } +} + + +#if (NGX_SMP) +#define ngx_memory_barrier() \ + __asm__ volatile ( \ + "membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad" \ + ::: "memory") +#else +#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") +#endif + +#define ngx_cpu_pause() diff --git a/hm_nginx/src/os/unix/ngx_gcc_atomic_x86.h b/hm_nginx/src/os/unix/ngx_gcc_atomic_x86.h new file mode 100644 index 0000000..54e01ae --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_gcc_atomic_x86.h @@ -0,0 +1,127 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#if (NGX_SMP) +#define NGX_SMP_LOCK "lock;" +#else +#define NGX_SMP_LOCK +#endif + + +/* + * "cmpxchgl r, [m]": + * + * if (eax == [m]) { + * zf = 1; + * [m] = r; + * } else { + * zf = 0; + * eax = [m]; + * } + * + * + * The "r" means the general register. + * The "=a" and "a" are the %eax register. + * Although we can return result in any register, we use "a" because it is + * used in cmpxchgl anyway. The result is actually in %al but not in %eax, + * however, as the code is inlined gcc can test %al as well as %eax, + * and icc adds "movzbl %al, %eax" by itself. + * + * The "cc" means that flags were changed. + */ + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + u_char res; + + __asm__ volatile ( + + NGX_SMP_LOCK + " cmpxchgl %3, %1; " + " sete %0; " + + : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory"); + + return res; +} + + +/* + * "xaddl r, [m]": + * + * temp = [m]; + * [m] += r; + * r = temp; + * + * + * The "+r" means the general register. + * The "cc" means that flags were changed. + */ + + +#if !(( __GNUC__ == 2 && __GNUC_MINOR__ <= 7 ) || ( __INTEL_COMPILER >= 800 )) + +/* + * icc 8.1 and 9.0 compile broken code with -march=pentium4 option: + * ngx_atomic_fetch_add() always return the input "add" value, + * so we use the gcc 2.7 version. + * + * icc 8.1 and 9.0 with -march=pentiumpro option or icc 7.1 compile + * correct code. + */ + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + __asm__ volatile ( + + NGX_SMP_LOCK + " xaddl %0, %1; " + + : "+r" (add) : "m" (*value) : "cc", "memory"); + + return add; +} + + +#else + +/* + * gcc 2.7 does not support "+r", so we have to use the fixed + * %eax ("=a" and "a") and this adds two superfluous instructions in the end + * of code, something like this: "mov %eax, %edx / mov %edx, %eax". + */ + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_uint_t old; + + __asm__ volatile ( + + NGX_SMP_LOCK + " xaddl %2, %1; " + + : "=a" (old) : "m" (*value), "a" (add) : "cc", "memory"); + + return old; +} + +#endif + + +/* + * on x86 the write operations go in a program order, so we need only + * to disable the gcc reorder optimizations + */ + +#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") + +/* old "as" does not support "pause" opcode */ +#define ngx_cpu_pause() __asm__ (".byte 0xf3, 0x90") diff --git a/hm_nginx/src/os/unix/ngx_linux.h b/hm_nginx/src/os/unix/ngx_linux.h new file mode 100644 index 0000000..1b8bdac --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_linux.h @@ -0,0 +1,18 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_LINUX_H_INCLUDED_ +#define _NGX_LINUX_H_INCLUDED_ + + +ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + +extern int ngx_linux_rtsig_max; + + +#endif /* _NGX_LINUX_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_linux_aio_read.c b/hm_nginx/src/os/unix/ngx_linux_aio_read.c new file mode 100644 index 0000000..b0a9236 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_linux_aio_read.c @@ -0,0 +1,148 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +extern int ngx_eventfd; +extern aio_context_t ngx_aio_ctx; + + +static void ngx_file_aio_event_handler(ngx_event_t *ev); + + +static int +io_submit(aio_context_t ctx, long n, struct iocb **paiocb) +{ + return syscall(SYS_io_submit, ctx, n, paiocb); +} + + +ngx_int_t +ngx_file_aio_init(ngx_file_t *file, ngx_pool_t *pool) +{ + ngx_event_aio_t *aio; + + aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); + if (aio == NULL) { + return NGX_ERROR; + } + + aio->file = file; + aio->fd = file->fd; + aio->event.data = aio; + aio->event.ready = 1; + aio->event.log = file->log; + + file->aio = aio; + + return NGX_OK; +} + + +ssize_t +ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, + ngx_pool_t *pool) +{ + ngx_err_t err; + struct iocb *piocb[1]; + ngx_event_t *ev; + ngx_event_aio_t *aio; + + if (!ngx_file_aio) { + return ngx_read_file(file, buf, size, offset); + } + + if (file->aio == NULL && ngx_file_aio_init(file, pool) != NGX_OK) { + return NGX_ERROR; + } + + aio = file->aio; + ev = &aio->event; + + if (!ev->ready) { + ngx_log_error(NGX_LOG_ALERT, file->log, 0, + "second aio post for \"%V\"", &file->name); + return NGX_AGAIN; + } + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio complete:%d @%O:%z %V", + ev->complete, offset, size, &file->name); + + if (ev->complete) { + ev->active = 0; + ev->complete = 0; + + if (aio->res >= 0) { + ngx_set_errno(0); + return aio->res; + } + + ngx_set_errno(-aio->res); + + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "aio read \"%s\" failed", file->name.data); + + return NGX_ERROR; + } + + ngx_memzero(&aio->aiocb, sizeof(struct iocb)); + + aio->aiocb.aio_data = (uint64_t) (uintptr_t) ev; + aio->aiocb.aio_lio_opcode = IOCB_CMD_PREAD; + aio->aiocb.aio_fildes = file->fd; + aio->aiocb.aio_buf = (uint64_t) (uintptr_t) buf; + aio->aiocb.aio_nbytes = size; + aio->aiocb.aio_offset = offset; + aio->aiocb.aio_flags = IOCB_FLAG_RESFD; + aio->aiocb.aio_resfd = ngx_eventfd; + + ev->handler = ngx_file_aio_event_handler; + + piocb[0] = &aio->aiocb; + + if (io_submit(ngx_aio_ctx, 1, piocb) == 1) { + ev->active = 1; + ev->ready = 0; + ev->complete = 0; + + return NGX_AGAIN; + } + + err = ngx_errno; + + if (err == NGX_EAGAIN) { + return ngx_read_file(file, buf, size, offset); + } + + ngx_log_error(NGX_LOG_CRIT, file->log, err, + "io_submit(\"%V\") failed", &file->name); + + if (err == NGX_ENOSYS) { + ngx_file_aio = 0; + return ngx_read_file(file, buf, size, offset); + } + + return NGX_ERROR; +} + + +static void +ngx_file_aio_event_handler(ngx_event_t *ev) +{ + ngx_event_aio_t *aio; + + aio = ev->data; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0, + "aio event handler fd:%d %V", aio->fd, &aio->file->name); + + aio->handler(ev); +} diff --git a/hm_nginx/src/os/unix/ngx_linux_config.h b/hm_nginx/src/os/unix/ngx_linux_config.h new file mode 100644 index 0000000..0c0b168 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_linux_config.h @@ -0,0 +1,127 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_LINUX_CONFIG_H_INCLUDED_ +#define _NGX_LINUX_CONFIG_H_INCLUDED_ + + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* pread(), pwrite(), gethostname() */ +#endif + +#define _FILE_OFFSET_BITS 64 + +#include +#include +#include +#include +#include /* offsetof() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* statfs() */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include /* TCP_NODELAY, TCP_CORK */ +#include +#include +#include + +#include /* tzset() */ +#include /* memalign() */ +#include /* IOV_MAX */ +#include +#include +#include /* uname() */ + + +#include + + +#if (NGX_HAVE_POSIX_SEM) +#include +#endif + + +#if (NGX_HAVE_SYS_PRCTL_H) +#include +#endif + + +#if (NGX_HAVE_SENDFILE64) +#include +#else +extern ssize_t sendfile(int s, int fd, int32_t *offset, size_t size); +#define NGX_SENDFILE_LIMIT 0x80000000 +#endif + + +#if (NGX_HAVE_POLL) +#include +#endif + + +#if (NGX_HAVE_RTSIG) +#include +#include +#endif + + +#if (NGX_HAVE_EPOLL) +#include +#endif + + +#if (NGX_HAVE_SYS_EVENTFD_H) +#include +#endif +#include +#if (NGX_HAVE_FILE_AIO) +#include +typedef struct iocb ngx_aiocb_t; +#endif + + +#define NGX_LISTEN_BACKLOG 511 + + +#ifndef NGX_HAVE_SO_SNDLOWAT +/* setsockopt(SO_SNDLOWAT) returns ENOPROTOOPT */ +#define NGX_HAVE_SO_SNDLOWAT 0 +#endif + + +#ifndef NGX_HAVE_INHERITED_NONBLOCK +#define NGX_HAVE_INHERITED_NONBLOCK 0 +#endif + + +#define NGX_HAVE_OS_SPECIFIC_INIT 1 +#define ngx_debug_init() + + +extern char **environ; + + +#endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_linux_init.c b/hm_nginx/src/os/unix/ngx_linux_init.c new file mode 100644 index 0000000..b910380 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_linux_init.c @@ -0,0 +1,91 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +u_char ngx_linux_kern_ostype[50]; +u_char ngx_linux_kern_osrelease[50]; + +int ngx_linux_rtsig_max; + + +static ngx_os_io_t ngx_linux_io = { + ngx_unix_recv, + ngx_readv_chain, + ngx_udp_unix_recv, + ngx_unix_send, +#if (NGX_HAVE_SENDFILE) + ngx_linux_sendfile_chain, + NGX_IO_SENDFILE +#else + ngx_writev_chain, + 0 +#endif +}; + + +ngx_int_t +ngx_os_specific_init(ngx_log_t *log) +{ + struct utsname u; + + if (uname(&u) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "uname() failed"); + return NGX_ERROR; + } + + (void) ngx_cpystrn(ngx_linux_kern_ostype, (u_char *) u.sysname, + sizeof(ngx_linux_kern_ostype)); + + (void) ngx_cpystrn(ngx_linux_kern_osrelease, (u_char *) u.release, + sizeof(ngx_linux_kern_osrelease)); + +#if (NGX_HAVE_RTSIG) + { + int name[2]; + size_t len; + ngx_err_t err; + + name[0] = CTL_KERN; + name[1] = KERN_RTSIGMAX; + len = sizeof(ngx_linux_rtsig_max); + + if (sysctl(name, 2, &ngx_linux_rtsig_max, &len, NULL, 0) == -1) { + err = ngx_errno; + + if (err != NGX_ENOTDIR && err != NGX_ENOSYS) { + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctl(KERN_RTSIGMAX) failed"); + + return NGX_ERROR; + } + + ngx_linux_rtsig_max = 0; + } + + } +#endif + + ngx_os_io = ngx_linux_io; + + return NGX_OK; +} + + +void +ngx_os_specific_status(ngx_log_t *log) +{ + ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", + ngx_linux_kern_ostype, ngx_linux_kern_osrelease); + +#if (NGX_HAVE_RTSIG) + ngx_log_error(NGX_LOG_NOTICE, log, 0, "sysctl(KERN_RTSIGMAX): %d", + ngx_linux_rtsig_max); +#endif +} diff --git a/hm_nginx/src/os/unix/ngx_linux_sendfile_chain.c b/hm_nginx/src/os/unix/ngx_linux_sendfile_chain.c new file mode 100644 index 0000000..97f741d --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_linux_sendfile_chain.c @@ -0,0 +1,419 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +static ssize_t ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file, + size_t size); + +#if (NGX_THREADS) +#include + +#if !(NGX_HAVE_SENDFILE64) +#error sendfile64() is required! +#endif + +static ngx_int_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, + size_t size, size_t *sent); +static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log); +#endif + + +/* + * On Linux up to 2.4.21 sendfile() (syscall #187) works with 32-bit + * offsets only, and the including breaks the compiling, + * if off_t is 64 bit wide. So we use own sendfile() definition, where offset + * parameter is int32_t, and use sendfile() for the file parts below 2G only, + * see src/os/unix/ngx_linux_config.h + * + * Linux 2.4.21 has the new sendfile64() syscall #239. + * + * On Linux up to 2.6.16 sendfile() does not allow to pass the count parameter + * more than 2G-1 bytes even on 64-bit platforms: it returns EINVAL, + * so we limit it to 2G-1 bytes. + */ + +#define NGX_SENDFILE_MAXSIZE 2147483647L + + +ngx_chain_t * +ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) +{ + int tcp_nodelay; + off_t send, prev_send; + size_t file_size, sent; + ssize_t n; + ngx_err_t err; + ngx_buf_t *file; + ngx_event_t *wev; + ngx_chain_t *cl; + ngx_iovec_t header; + struct iovec headers[NGX_IOVS_PREALLOCATE]; +#if (NGX_THREADS) + ngx_int_t rc; + ngx_uint_t thread_handled, thread_complete; +#endif + + wev = c->write; + + if (!wev->ready) { + return in; + } + + + /* the maximum limit size is 2G-1 - the page size */ + + if (limit == 0 || limit > (off_t) (NGX_SENDFILE_MAXSIZE - ngx_pagesize)) { + limit = NGX_SENDFILE_MAXSIZE - ngx_pagesize; + } + + + send = 0; + + header.iovs = headers; + header.nalloc = NGX_IOVS_PREALLOCATE; + + for ( ;; ) { + prev_send = send; +#if (NGX_THREADS) + thread_handled = 0; + thread_complete = 0; +#endif + + /* create the iovec and coalesce the neighbouring bufs */ + + cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log); + + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + send += header.size; + + /* set TCP_CORK if there is a header before a file */ + + if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET + && header.count != 0 + && cl + && cl->buf->in_file) + { + /* the TCP_CORK and TCP_NODELAY are mutually exclusive */ + + if (c->tcp_nodelay == NGX_TCP_NODELAY_SET) { + + tcp_nodelay = 0; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + err = ngx_socket_errno; + + /* + * there is a tiny chance to be interrupted, however, + * we continue a processing with the TCP_NODELAY + * and without the TCP_CORK + */ + + if (err != NGX_EINTR) { + wev->error = 1; + ngx_connection_error(c, err, + "setsockopt(TCP_NODELAY) failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nodelay = NGX_TCP_NODELAY_UNSET; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "no tcp_nodelay"); + } + } + + if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + + if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { + err = ngx_socket_errno; + + /* + * there is a tiny chance to be interrupted, however, + * we continue a processing without the TCP_CORK + */ + + if (err != NGX_EINTR) { + wev->error = 1; + ngx_connection_error(c, err, + ngx_tcp_nopush_n " failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nopush = NGX_TCP_NOPUSH_SET; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "tcp_nopush"); + } + } + } + + /* get the file buf */ + + if (header.count == 0 && cl && cl->buf->in_file && send < limit) { + file = cl->buf; + + /* coalesce the neighbouring file bufs */ + + file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send); + + send += file_size; +#if 1 + if (file_size == 0) { + ngx_debug_point(); + return NGX_CHAIN_ERROR; + } +#endif + +#if (NGX_THREADS) + if (file->file->thread_handler) { + rc = ngx_linux_sendfile_thread(c, file, file_size, &sent); + + switch (rc) { + case NGX_OK: + thread_handled = 1; + break; + + case NGX_DONE: + thread_complete = 1; + break; + + case NGX_AGAIN: + break; + + default: /* NGX_ERROR */ + return NGX_CHAIN_ERROR; + } + + } else +#endif + { + n = ngx_linux_sendfile(c, file, file_size); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + sent = (n == NGX_AGAIN) ? 0 : n; + } + + } else { + n = ngx_writev(c, &header); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + sent = (n == NGX_AGAIN) ? 0 : n; + } + + c->sent += sent; + + in = ngx_chain_update_sent(in, sent); + + if ((size_t) (send - prev_send) != sent) { +#if (NGX_THREADS) + if (thread_handled) { + return in; + } + + if (thread_complete) { + send = prev_send + sent; + continue; + } +#endif + wev->ready = 0; + return in; + } + + if (send >= limit || in == NULL) { + return in; + } + } +} + + +static ssize_t +ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size) +{ +#if (NGX_HAVE_SENDFILE64) + off_t offset; +#else + int32_t offset; +#endif + ssize_t n; + ngx_err_t err; + +#if (NGX_HAVE_SENDFILE64) + offset = file->file_pos; +#else + offset = (int32_t) file->file_pos; +#endif + +eintr: + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendfile: @%O %uz", file->file_pos, size); + + n = sendfile(c->fd, file->file->fd, &offset, size); + + if (n == -1) { + err = ngx_errno; + + switch (err) { + case NGX_EAGAIN: + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "sendfile() is not ready"); + return NGX_AGAIN; + + case NGX_EINTR: + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "sendfile() was interrupted"); + goto eintr; + + default: + c->write->error = 1; + ngx_connection_error(c, err, "sendfile() failed"); + return NGX_ERROR; + } + } + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %z of %uz @%O", + n, size, file->file_pos); + + return n; +} + + +#if (NGX_THREADS) + +typedef struct { + ngx_buf_t *file; + ngx_socket_t socket; + size_t size; + + size_t sent; + ngx_err_t err; +} ngx_linux_sendfile_ctx_t; + + +static ngx_int_t +ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, + size_t *sent) +{ + ngx_uint_t flags; + ngx_event_t *wev; + ngx_thread_task_t *task; + ngx_linux_sendfile_ctx_t *ctx; + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, c->log, 0, + "linux sendfile thread: %d, %uz, %O", + file->file->fd, size, file->file_pos); + + task = c->sendfile_task; + + if (task == NULL) { + task = ngx_thread_task_alloc(c->pool, sizeof(ngx_linux_sendfile_ctx_t)); + if (task == NULL) { + return NGX_ERROR; + } + + task->handler = ngx_linux_sendfile_thread_handler; + + c->sendfile_task = task; + } + + ctx = task->ctx; + wev = c->write; + + if (task->event.complete) { + task->event.complete = 0; + + if (ctx->err && ctx->err != NGX_EAGAIN) { + wev->error = 1; + ngx_connection_error(c, ctx->err, "sendfile() failed"); + return NGX_ERROR; + } + + *sent = ctx->sent; + + return (ctx->sent == ctx->size) ? NGX_DONE : NGX_AGAIN; + } + + ctx->file = file; + ctx->socket = c->fd; + ctx->size = size; + + if (wev->active) { + flags = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ? NGX_CLEAR_EVENT + : NGX_LEVEL_EVENT; + + if (ngx_del_event(wev, NGX_WRITE_EVENT, flags) == NGX_ERROR) { + return NGX_ERROR; + } + } + + if (file->file->thread_handler(task, file->file) != NGX_OK) { + return NGX_ERROR; + } + + *sent = 0; + + return NGX_OK; +} + + +static void +ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log) +{ + ngx_linux_sendfile_ctx_t *ctx = data; + + off_t offset; + ssize_t n; + ngx_buf_t *file; + + ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "linux sendfile thread handler"); + + file = ctx->file; + offset = file->file_pos; + +again: + + n = sendfile(ctx->socket, file->file->fd, &offset, ctx->size); + + if (n == -1) { + ctx->err = ngx_errno; + + } else { + ctx->sent = n; + ctx->err = 0; + } + +#if 0 + ngx_time_update(); +#endif + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, + "sendfile: %z (err: %i) of %uz @%O", + n, ctx->err, ctx->size, file->file_pos); + + if (ctx->err == NGX_EINTR) { + goto again; + } +} + +#endif /* NGX_THREADS */ diff --git a/hm_nginx/src/os/unix/ngx_os.h b/hm_nginx/src/os/unix/ngx_os.h new file mode 100644 index 0000000..09f7917 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_os.h @@ -0,0 +1,105 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_OS_H_INCLUDED_ +#define _NGX_OS_H_INCLUDED_ + + +#include +#include + + +#define NGX_IO_SENDFILE 1 + + +typedef ssize_t (*ngx_recv_pt)(ngx_connection_t *c, u_char *buf, size_t size); +typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); +typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size); +typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + +typedef struct { + ngx_recv_pt recv; + ngx_recv_chain_pt recv_chain; + ngx_recv_pt udp_recv; + ngx_send_pt send; + ngx_send_chain_pt send_chain; + ngx_uint_t flags; +} ngx_os_io_t; + + +ngx_int_t ngx_os_init(ngx_log_t *log); +void ngx_os_status(ngx_log_t *log); +ngx_int_t ngx_os_specific_init(ngx_log_t *log); +void ngx_os_specific_status(ngx_log_t *log); +ngx_int_t ngx_daemon(ngx_log_t *log); +ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_int_t pid); + + +ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); +ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry, off_t limit); +ssize_t ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); +ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size); +ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + +#if (NGX_HAVE_AIO) +ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size); +ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit); +ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size); +ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); +#endif + + +#if (IOV_MAX > 64) +#define NGX_IOVS_PREALLOCATE 64 +#else +#define NGX_IOVS_PREALLOCATE IOV_MAX +#endif + + +typedef struct { + struct iovec *iovs; + ngx_uint_t count; + size_t size; + ngx_uint_t nalloc; +} ngx_iovec_t; + +ngx_chain_t *ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, + size_t limit, ngx_log_t *log); + + +ssize_t ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec); + + +extern ngx_os_io_t ngx_os_io; +extern ngx_int_t ngx_ncpu; +extern ngx_int_t ngx_max_sockets; +extern ngx_uint_t ngx_inherited_nonblocking; +extern ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; + + +#if (NGX_FREEBSD) +#include + + +#elif (NGX_LINUX) +#include + + +#elif (NGX_SOLARIS) +#include + + +#elif (NGX_DARWIN) +#include +#endif + + +#endif /* _NGX_OS_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_posix_config.h b/hm_nginx/src/os/unix/ngx_posix_config.h new file mode 100644 index 0000000..d725659 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_posix_config.h @@ -0,0 +1,158 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_POSIX_CONFIG_H_INCLUDED_ +#define _NGX_POSIX_CONFIG_H_INCLUDED_ + + +#if (NGX_HPUX) +#define _XOPEN_SOURCE +#define _XOPEN_SOURCE_EXTENDED 1 +#define _HPUX_ALT_XOPEN_SOCKET_API +#endif + + +#if (NGX_TRU64) +#define _REENTRANT +#endif + + +#ifdef __CYGWIN__ +#define timezonevar /* timezone is variable */ +#define NGX_BROKEN_SCM_RIGHTS 1 +#endif + + +#include +#include +#if (NGX_HAVE_UNISTD_H) +#include +#endif +#if (NGX_HAVE_INTTYPES_H) +#include +#endif +#include +#include /* offsetof() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (NGX_HAVE_SYS_PARAM_H) +#include /* statfs() */ +#endif +#if (NGX_HAVE_SYS_MOUNT_H) +#include /* statfs() */ +#endif +#if (NGX_HAVE_SYS_STATVFS_H) +#include /* statvfs() */ +#endif + +#if (NGX_HAVE_SYS_FILIO_H) +#include /* FIONBIO */ +#endif +#include /* FIONBIO */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include /* TCP_NODELAY */ +#include +#include +#include + +#if (NGX_HAVE_LIMITS_H) +#include /* IOV_MAX */ +#endif + +#ifdef __CYGWIN__ +#include /* memalign() */ +#endif + +#if (NGX_HAVE_CRYPT_H) +#include +#endif + + +#ifndef IOV_MAX +#define IOV_MAX 16 +#endif + + +#include + + +#if (NGX_HAVE_POSIX_SEM) +#include +#endif + + +#if (NGX_HAVE_POLL) +#include +#endif + + +#if (NGX_HAVE_KQUEUE) +#include +#endif + + +#if (NGX_HAVE_DEVPOLL) +#include +#include +#endif + + +#if (NGX_HAVE_FILE_AIO) +#include +typedef struct aiocb ngx_aiocb_t; +#endif + + +#define NGX_LISTEN_BACKLOG 511 + +#define ngx_debug_init() + + +#if (__FreeBSD__) && (__FreeBSD_version < 400017) + +#include /* ALIGN() */ + +/* + * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA() + */ + +#undef CMSG_SPACE +#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l)) + +#undef CMSG_LEN +#define CMSG_LEN(l) (ALIGN(sizeof(struct cmsghdr)) + (l)) + +#undef CMSG_DATA +#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr))) + +#endif + + +extern char **environ; + + +#endif /* _NGX_POSIX_CONFIG_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_posix_init.c b/hm_nginx/src/os/unix/ngx_posix_init.c new file mode 100644 index 0000000..bf3a310 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_posix_init.c @@ -0,0 +1,130 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ngx_int_t ngx_ncpu; +ngx_int_t ngx_max_sockets; +ngx_uint_t ngx_inherited_nonblocking; +ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; + + +struct rlimit rlmt; + + +ngx_os_io_t ngx_os_io = { + ngx_unix_recv, + ngx_readv_chain, + ngx_udp_unix_recv, + ngx_unix_send, + ngx_writev_chain, + 0 +}; + + +ngx_int_t +ngx_os_init(ngx_log_t *log) +{ + ngx_uint_t n; + +#if (NGX_HAVE_OS_SPECIFIC_INIT) + if (ngx_os_specific_init(log) != NGX_OK) { + return NGX_ERROR; + } +#endif + + if (ngx_init_setproctitle(log) != NGX_OK) { + return NGX_ERROR; + } + + ngx_pagesize = getpagesize(); + ngx_cacheline_size = NGX_CPU_CACHE_LINE; + + for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ } + +#if (NGX_HAVE_SC_NPROCESSORS_ONLN) + if (ngx_ncpu == 0) { + ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN); + } +#endif + + if (ngx_ncpu < 1) { + ngx_ncpu = 1; + } + + ngx_cpuinfo(); + + if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, errno, + "getrlimit(RLIMIT_NOFILE) failed)"); + return NGX_ERROR; + } + + ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur; + +#if (NGX_HAVE_INHERITED_NONBLOCK || NGX_HAVE_ACCEPT4) + ngx_inherited_nonblocking = 1; +#else + ngx_inherited_nonblocking = 0; +#endif + + srandom(ngx_time()); + + return NGX_OK; +} + + +void +ngx_os_status(ngx_log_t *log) +{ + ngx_log_error(NGX_LOG_NOTICE, log, 0, NGINX_VER_BUILD); + +#ifdef NGX_COMPILER + ngx_log_error(NGX_LOG_NOTICE, log, 0, "built by " NGX_COMPILER); +#endif + +#if (NGX_HAVE_OS_SPECIFIC_INIT) + ngx_os_specific_status(log); +#endif + + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "getrlimit(RLIMIT_NOFILE): %r:%r", + rlmt.rlim_cur, rlmt.rlim_max); +} + + +#if 0 + +ngx_int_t +ngx_posix_post_conf_init(ngx_log_t *log) +{ + ngx_fd_t pp[2]; + + if (pipe(pp) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "pipe() failed"); + return NGX_ERROR; + } + + if (dup2(pp[1], STDERR_FILENO) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDERR) failed"); + return NGX_ERROR; + } + + if (pp[1] > STDERR_FILENO) { + if (close(pp[1]) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, errno, "close() failed"); + return NGX_ERROR; + } + } + + return NGX_OK; +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_process.c b/hm_nginx/src/os/unix/ngx_process.c new file mode 100644 index 0000000..6f3f385 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_process.c @@ -0,0 +1,630 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +typedef struct { + int signo; + char *signame; + char *name; + void (*handler)(int signo); +} ngx_signal_t; + + + +static void ngx_execute_proc(ngx_cycle_t *cycle, void *data); +static void ngx_signal_handler(int signo); +static void ngx_process_get_status(void); +static void ngx_unlock_mutexes(ngx_pid_t pid); + + +int ngx_argc; +char **ngx_argv; +char **ngx_os_argv; + +ngx_int_t ngx_process_slot; +ngx_socket_t ngx_channel; +ngx_int_t ngx_last_process; +ngx_process_t ngx_processes[NGX_MAX_PROCESSES]; + + +ngx_signal_t signals[] = { + { ngx_signal_value(NGX_RECONFIGURE_SIGNAL), + "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL), + "reload", + ngx_signal_handler }, + + { ngx_signal_value(NGX_REOPEN_SIGNAL), + "SIG" ngx_value(NGX_REOPEN_SIGNAL), + "reopen", + ngx_signal_handler }, + + { ngx_signal_value(NGX_NOACCEPT_SIGNAL), + "SIG" ngx_value(NGX_NOACCEPT_SIGNAL), + "", + ngx_signal_handler }, + + { ngx_signal_value(NGX_TERMINATE_SIGNAL), + "SIG" ngx_value(NGX_TERMINATE_SIGNAL), + "stop", + ngx_signal_handler }, + + { ngx_signal_value(NGX_SHUTDOWN_SIGNAL), + "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL), + "quit", + ngx_signal_handler }, + + { ngx_signal_value(NGX_CHANGEBIN_SIGNAL), + "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL), + "", + ngx_signal_handler }, + + { SIGALRM, "SIGALRM", "", ngx_signal_handler }, + + { SIGINT, "SIGINT", "", ngx_signal_handler }, + + { SIGIO, "SIGIO", "", ngx_signal_handler }, + + { SIGCHLD, "SIGCHLD", "", ngx_signal_handler }, + + { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN }, + + { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN }, + + { 0, NULL, "", NULL } +}; + + +ngx_pid_t +ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, + char *name, ngx_int_t respawn) +{ + u_long on; + ngx_pid_t pid; + ngx_int_t s; + + if (respawn >= 0) { + s = respawn; + + } else { + for (s = 0; s < ngx_last_process; s++) { + if (ngx_processes[s].pid == -1) { + break; + } + } + + if (s == NGX_MAX_PROCESSES) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "no more than %d processes can be spawned", + NGX_MAX_PROCESSES); + return NGX_INVALID_PID; + } + } + + + if (respawn != NGX_PROCESS_DETACHED) { + + /* Solaris 9 still has no AF_LOCAL */ + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "socketpair() failed while spawning \"%s\"", name); + return NGX_INVALID_PID; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "channel %d:%d", + ngx_processes[s].channel[0], + ngx_processes[s].channel[1]); + + if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_nonblocking_n " failed while spawning \"%s\"", + name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + } + + if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_nonblocking_n " failed while spawning \"%s\"", + name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + } + + on = 1; + if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "ioctl(FIOASYNC) failed while spawning \"%s\"", name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + } + + if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "fcntl(F_SETOWN) failed while spawning \"%s\"", name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + } + + if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", + name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + } + + if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", + name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + } + + ngx_channel = ngx_processes[s].channel[1]; + + } else { + ngx_processes[s].channel[0] = -1; + ngx_processes[s].channel[1] = -1; + } + + ngx_process_slot = s; + + + pid = fork(); + + switch (pid) { + + case -1: + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "fork() failed while spawning \"%s\"", name); + ngx_close_channel(ngx_processes[s].channel, cycle->log); + return NGX_INVALID_PID; + + case 0: + ngx_pid = ngx_getpid(); + proc(cycle, data); + break; + + default: + break; + } + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid); + + ngx_processes[s].pid = pid; + ngx_processes[s].exited = 0; + + if (respawn >= 0) { + return pid; + } + + ngx_processes[s].proc = proc; + ngx_processes[s].data = data; + ngx_processes[s].name = name; + ngx_processes[s].exiting = 0; + + switch (respawn) { + + case NGX_PROCESS_NORESPAWN: + ngx_processes[s].respawn = 0; + ngx_processes[s].just_spawn = 0; + ngx_processes[s].detached = 0; + break; + + case NGX_PROCESS_JUST_SPAWN: + ngx_processes[s].respawn = 0; + ngx_processes[s].just_spawn = 1; + ngx_processes[s].detached = 0; + break; + + case NGX_PROCESS_RESPAWN: + ngx_processes[s].respawn = 1; + ngx_processes[s].just_spawn = 0; + ngx_processes[s].detached = 0; + break; + + case NGX_PROCESS_JUST_RESPAWN: + ngx_processes[s].respawn = 1; + ngx_processes[s].just_spawn = 1; + ngx_processes[s].detached = 0; + break; + + case NGX_PROCESS_DETACHED: + ngx_processes[s].respawn = 0; + ngx_processes[s].just_spawn = 0; + ngx_processes[s].detached = 1; + break; + } + + if (s == ngx_last_process) { + ngx_last_process++; + } + + return pid; +} + + +ngx_pid_t +ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx) +{ + return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name, + NGX_PROCESS_DETACHED); +} + + +static void +ngx_execute_proc(ngx_cycle_t *cycle, void *data) +{ + ngx_exec_ctx_t *ctx = data; + + if (execve(ctx->path, ctx->argv, ctx->envp) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "execve() failed while executing %s \"%s\"", + ctx->name, ctx->path); + } + + exit(1); +} + + +ngx_int_t +ngx_init_signals(ngx_log_t *log) +{ + ngx_signal_t *sig; + struct sigaction sa; + + for (sig = signals; sig->signo != 0; sig++) { + ngx_memzero(&sa, sizeof(struct sigaction)); + sa.sa_handler = sig->handler; + sigemptyset(&sa.sa_mask); + if (sigaction(sig->signo, &sa, NULL) == -1) { +#if (NGX_VALGRIND) + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sigaction(%s) failed, ignored", sig->signame); +#else + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "sigaction(%s) failed", sig->signame); + return NGX_ERROR; +#endif + } + } + + return NGX_OK; +} + + +void +ngx_signal_handler(int signo) +{ + char *action; + ngx_int_t ignore; + ngx_err_t err; + ngx_signal_t *sig; + + ignore = 0; + + err = ngx_errno; + + for (sig = signals; sig->signo != 0; sig++) { + if (sig->signo == signo) { + break; + } + } + + ngx_time_sigsafe_update(); + + action = ""; + + switch (ngx_process) { + + case NGX_PROCESS_MASTER: + case NGX_PROCESS_SINGLE: + switch (signo) { + + case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): + ngx_quit = 1; + action = ", shutting down"; + break; + + case ngx_signal_value(NGX_TERMINATE_SIGNAL): + case SIGINT: + ngx_terminate = 1; + action = ", exiting"; + break; + + case ngx_signal_value(NGX_NOACCEPT_SIGNAL): + if (ngx_daemonized) { + ngx_noaccept = 1; + action = ", stop accepting connections"; + } + break; + + case ngx_signal_value(NGX_RECONFIGURE_SIGNAL): + ngx_reconfigure = 1; + action = ", reconfiguring"; + break; + + case ngx_signal_value(NGX_REOPEN_SIGNAL): + ngx_reopen = 1; + action = ", reopening logs"; + break; + + case ngx_signal_value(NGX_CHANGEBIN_SIGNAL): + if (getppid() > 1 || ngx_new_binary > 0) { + + /* + * Ignore the signal in the new binary if its parent is + * not the init process, i.e. the old binary's process + * is still running. Or ignore the signal in the old binary's + * process if the new binary's process is already running. + */ + + action = ", ignoring"; + ignore = 1; + break; + } + + ngx_change_binary = 1; + action = ", changing binary"; + break; + + case SIGALRM: + ngx_sigalrm = 1; + break; + + case SIGIO: + ngx_sigio = 1; + break; + + case SIGCHLD: + ngx_reap = 1; + break; + } + + break; + + case NGX_PROCESS_WORKER: + case NGX_PROCESS_HELPER: + switch (signo) { + + case ngx_signal_value(NGX_NOACCEPT_SIGNAL): + if (!ngx_daemonized) { + break; + } + ngx_debug_quit = 1; + case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): + ngx_quit = 1; + action = ", shutting down"; + break; + + case ngx_signal_value(NGX_TERMINATE_SIGNAL): + case SIGINT: + ngx_terminate = 1; + action = ", exiting"; + break; + + case ngx_signal_value(NGX_REOPEN_SIGNAL): + ngx_reopen = 1; + action = ", reopening logs"; + break; + + case ngx_signal_value(NGX_RECONFIGURE_SIGNAL): + case ngx_signal_value(NGX_CHANGEBIN_SIGNAL): + case SIGIO: + action = ", ignoring"; + break; + } + + break; + } + + ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, + "signal %d (%s) received%s", signo, sig->signame, action); + + if (ignore) { + ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0, + "the changing binary signal is ignored: " + "you should shutdown or terminate " + "before either old or new binary's process"); + } + + if (signo == SIGCHLD) { + ngx_process_get_status(); + } + + ngx_set_errno(err); +} + + +static void +ngx_process_get_status(void) +{ + int status; + char *process; + ngx_pid_t pid; + ngx_err_t err; + ngx_int_t i; + ngx_uint_t one; + + one = 0; + + for ( ;; ) { + pid = waitpid(-1, &status, WNOHANG); + + if (pid == 0) { + return; + } + + if (pid == -1) { + err = ngx_errno; + + if (err == NGX_EINTR) { + continue; + } + + if (err == NGX_ECHILD && one) { + return; + } + + /* + * Solaris always calls the signal handler for each exited process + * despite waitpid() may be already called for this process. + * + * When several processes exit at the same time FreeBSD may + * erroneously call the signal handler for exited process + * despite waitpid() may be already called for this process. + */ + + if (err == NGX_ECHILD) { + ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, err, + "waitpid() failed"); + return; + } + + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, + "waitpid() failed"); + return; + } + + + one = 1; + process = "unknown process"; + + for (i = 0; i < ngx_last_process; i++) { + if (ngx_processes[i].pid == pid) { + ngx_processes[i].status = status; + ngx_processes[i].exited = 1; + process = ngx_processes[i].name; + break; + } + } + + if (WTERMSIG(status)) { +#ifdef WCOREDUMP + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "%s %P exited on signal %d%s", + process, pid, WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); +#else + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "%s %P exited on signal %d", + process, pid, WTERMSIG(status)); +#endif + + } else { + ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, + "%s %P exited with code %d", + process, pid, WEXITSTATUS(status)); + } + + if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "%s %P exited with fatal code %d " + "and cannot be respawned", + process, pid, WEXITSTATUS(status)); + ngx_processes[i].respawn = 0; + } + + ngx_unlock_mutexes(pid); + } +} + + +static void +ngx_unlock_mutexes(ngx_pid_t pid) +{ + ngx_uint_t i; + ngx_shm_zone_t *shm_zone; + ngx_list_part_t *part; + ngx_slab_pool_t *sp; + + /* + * unlock the accept mutex if the abnormally exited process + * held it + */ + + if (ngx_accept_mutex_ptr) { + (void) ngx_shmtx_force_unlock(&ngx_accept_mutex, pid); + } + + /* + * unlock shared memory mutexes if held by the abnormally exited + * process + */ + + part = (ngx_list_part_t *) &ngx_cycle->shared_memory.part; + shm_zone = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + part = part->next; + shm_zone = part->elts; + i = 0; + } + + sp = (ngx_slab_pool_t *) shm_zone[i].shm.addr; + + if (ngx_shmtx_force_unlock(&sp->mutex, pid)) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "shared memory zone \"%V\" was locked by %P", + &shm_zone[i].shm.name, pid); + } + } +} + + +void +ngx_debug_point(void) +{ + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, + ngx_core_module); + + switch (ccf->debug_points) { + + case NGX_DEBUG_POINTS_STOP: + raise(SIGSTOP); + break; + + case NGX_DEBUG_POINTS_ABORT: + ngx_abort(); + } +} + + +ngx_int_t +ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_int_t pid) +{ + ngx_signal_t *sig; + + for (sig = signals; sig->signo != 0; sig++) { + if (ngx_strcmp(name, sig->name) == 0) { + if (kill(pid, sig->signo) != -1) { + return 0; + } + + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "kill(%P, %d) failed", pid, sig->signo); + } + } + + return 1; +} diff --git a/hm_nginx/src/os/unix/ngx_process.h b/hm_nginx/src/os/unix/ngx_process.h new file mode 100644 index 0000000..7b5e8c0 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_process.h @@ -0,0 +1,88 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_PROCESS_H_INCLUDED_ +#define _NGX_PROCESS_H_INCLUDED_ + + +#include +#include + + +typedef pid_t ngx_pid_t; + +#define NGX_INVALID_PID -1 + +typedef void (*ngx_spawn_proc_pt) (ngx_cycle_t *cycle, void *data); + +typedef struct { + ngx_pid_t pid; + int status; + ngx_socket_t channel[2]; + + ngx_spawn_proc_pt proc; + void *data; + char *name; + + unsigned respawn:1; + unsigned just_spawn:1; + unsigned detached:1; + unsigned exiting:1; + unsigned exited:1; +} ngx_process_t; + + +typedef struct { + char *path; + char *name; + char *const *argv; + char *const *envp; +} ngx_exec_ctx_t; + + +#define NGX_MAX_PROCESSES 1024 + +#define NGX_PROCESS_NORESPAWN -1 +#define NGX_PROCESS_JUST_SPAWN -2 +#define NGX_PROCESS_RESPAWN -3 +#define NGX_PROCESS_JUST_RESPAWN -4 +#define NGX_PROCESS_DETACHED -5 + + +#define ngx_getpid getpid + +#ifndef ngx_log_pid +#define ngx_log_pid ngx_pid +#endif + + +ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, + ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn); +ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx); +ngx_int_t ngx_init_signals(ngx_log_t *log); +void ngx_debug_point(void); + + +#if (NGX_HAVE_SCHED_YIELD) +#define ngx_sched_yield() sched_yield() +#else +#define ngx_sched_yield() usleep(1) +#endif + + +extern int ngx_argc; +extern char **ngx_argv; +extern char **ngx_os_argv; + +extern ngx_pid_t ngx_pid; +extern ngx_socket_t ngx_channel; +extern ngx_int_t ngx_process_slot; +extern ngx_int_t ngx_last_process; +extern ngx_process_t ngx_processes[NGX_MAX_PROCESSES]; + + +#endif /* _NGX_PROCESS_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_process_cycle.c b/hm_nginx/src/os/unix/ngx_process_cycle.c new file mode 100644 index 0000000..1d5e700 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_process_cycle.c @@ -0,0 +1,1224 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, + ngx_int_t type); +static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, + ngx_uint_t respawn); +static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch); +static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); +static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle); +static void ngx_master_process_exit(ngx_cycle_t *cycle); +static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); +static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker); +static void ngx_worker_process_exit(ngx_cycle_t *cycle); +static void ngx_channel_handler(ngx_event_t *ev); +static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data); +static void ngx_cache_manager_process_handler(ngx_event_t *ev); +static void ngx_cache_loader_process_handler(ngx_event_t *ev); + + +ngx_uint_t ngx_process; +ngx_pid_t ngx_pid; + +sig_atomic_t ngx_reap; +sig_atomic_t ngx_sigio; +sig_atomic_t ngx_sigalrm; +sig_atomic_t ngx_terminate; +sig_atomic_t ngx_quit; +sig_atomic_t ngx_debug_quit; +ngx_uint_t ngx_exiting; +sig_atomic_t ngx_reconfigure; +sig_atomic_t ngx_reopen; + +sig_atomic_t ngx_change_binary; +ngx_pid_t ngx_new_binary; +ngx_uint_t ngx_inherited; +ngx_uint_t ngx_daemonized; + +sig_atomic_t ngx_noaccept; +ngx_uint_t ngx_noaccepting; +ngx_uint_t ngx_restart; + + +static u_char master_process[] = "master process"; + + +static ngx_cache_manager_ctx_t ngx_cache_manager_ctx = { + ngx_cache_manager_process_handler, "cache manager process", 0 +}; + +static ngx_cache_manager_ctx_t ngx_cache_loader_ctx = { + ngx_cache_loader_process_handler, "cache loader process", 60000 +}; + + +static ngx_cycle_t ngx_exit_cycle; +static ngx_log_t ngx_exit_log; +static ngx_open_file_t ngx_exit_log_file; + + +void +ngx_master_process_cycle(ngx_cycle_t *cycle) +{ + char *title; + u_char *p; + size_t size; + ngx_int_t i; + ngx_uint_t n, sigio; + sigset_t set; + struct itimerval itv; + ngx_uint_t live; + ngx_msec_t delay; + ngx_listening_t *ls; + ngx_core_conf_t *ccf; + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigaddset(&set, SIGALRM); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGINT); + sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); + + if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed"); + } + + sigemptyset(&set); + + + size = sizeof(master_process); + + for (i = 0; i < ngx_argc; i++) { + size += ngx_strlen(ngx_argv[i]) + 1; + } + + title = ngx_pnalloc(cycle->pool, size); + if (title == NULL) { + /* fatal */ + exit(2); + } + + p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); + for (i = 0; i < ngx_argc; i++) { + *p++ = ' '; + p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); + } + + ngx_setproctitle(title); + + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + + ngx_start_worker_processes(cycle, ccf->worker_processes, + NGX_PROCESS_RESPAWN); + ngx_start_cache_manager_processes(cycle, 0); + + ngx_new_binary = 0; + delay = 0; + sigio = 0; + live = 1; + + for ( ;; ) { + if (delay) { + if (ngx_sigalrm) { + sigio = 0; + delay *= 2; + ngx_sigalrm = 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "termination cycle: %d", delay); + + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 0; + itv.it_value.tv_sec = delay / 1000; + itv.it_value.tv_usec = (delay % 1000 ) * 1000; + + if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setitimer() failed"); + } + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); + + sigsuspend(&set); + + ngx_time_update(); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "wake up, sigio %i", sigio); + + if (ngx_reap) { + ngx_reap = 0; + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); + + live = ngx_reap_children(cycle); + } + + if (!live && (ngx_terminate || ngx_quit)) { + ngx_master_process_exit(cycle); + } + + if (ngx_terminate) { + if (delay == 0) { + delay = 50; + } + + if (sigio) { + sigio--; + continue; + } + + sigio = ccf->worker_processes + 2 /* cache processes */; + + if (delay > 1000) { + ngx_signal_worker_processes(cycle, SIGKILL); + } else { + ngx_signal_worker_processes(cycle, + ngx_signal_value(NGX_TERMINATE_SIGNAL)); + } + + continue; + } + + if (ngx_quit) { + ngx_signal_worker_processes(cycle, + ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); + + ls = cycle->listening.elts; + for (n = 0; n < cycle->listening.nelts; n++) { + if (ngx_close_socket(ls[n].fd) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[n].addr_text); + } + } + cycle->listening.nelts = 0; + + continue; + } + + if (ngx_reconfigure) { + ngx_reconfigure = 0; + + if (ngx_new_binary) { + ngx_start_worker_processes(cycle, ccf->worker_processes, + NGX_PROCESS_RESPAWN); + ngx_start_cache_manager_processes(cycle, 0); + ngx_noaccepting = 0; + + continue; + } + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); + + cycle = ngx_init_cycle(cycle); + if (cycle == NULL) { + cycle = (ngx_cycle_t *) ngx_cycle; + continue; + } + + ngx_cycle = cycle; + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, + ngx_core_module); + ngx_start_worker_processes(cycle, ccf->worker_processes, + NGX_PROCESS_JUST_RESPAWN); + ngx_start_cache_manager_processes(cycle, 1); + + /* allow new processes to start */ + ngx_msleep(100); + + live = 1; + ngx_signal_worker_processes(cycle, + ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); + } + + if (ngx_restart) { + ngx_restart = 0; + ngx_start_worker_processes(cycle, ccf->worker_processes, + NGX_PROCESS_RESPAWN); + ngx_start_cache_manager_processes(cycle, 0); + live = 1; + } + + if (ngx_reopen) { + ngx_reopen = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); + ngx_reopen_files(cycle, ccf->user); + ngx_signal_worker_processes(cycle, + ngx_signal_value(NGX_REOPEN_SIGNAL)); + } + + if (ngx_change_binary) { + ngx_change_binary = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); + ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); + } + + if (ngx_noaccept) { + ngx_noaccept = 0; + ngx_noaccepting = 1; + ngx_signal_worker_processes(cycle, + ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); + } + } +} + + +void +ngx_single_process_cycle(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + + if (ngx_set_environment(cycle, NULL) == NULL) { + /* fatal */ + exit(2); + } + + for (i = 0; ngx_modules[i]; i++) { + if (ngx_modules[i]->init_process) { + if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { + /* fatal */ + exit(2); + } + } + } + + for ( ;; ) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); + + ngx_process_events_and_timers(cycle); + + if (ngx_terminate || ngx_quit) { + + for (i = 0; ngx_modules[i]; i++) { + if (ngx_modules[i]->exit_process) { + ngx_modules[i]->exit_process(cycle); + } + } + + ngx_master_process_exit(cycle); + } + + if (ngx_reconfigure) { + ngx_reconfigure = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); + + cycle = ngx_init_cycle(cycle); + if (cycle == NULL) { + cycle = (ngx_cycle_t *) ngx_cycle; + continue; + } + + ngx_cycle = cycle; + } + + if (ngx_reopen) { + ngx_reopen = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); + ngx_reopen_files(cycle, (ngx_uid_t) -1); + } + } +} + + +static void +ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) +{ + ngx_int_t i; + ngx_channel_t ch; + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); + + ngx_memzero(&ch, sizeof(ngx_channel_t)); + + ch.command = NGX_CMD_OPEN_CHANNEL; + + for (i = 0; i < n; i++) { + + ngx_spawn_process(cycle, ngx_worker_process_cycle, + (void *) (intptr_t) i, "worker process", type); + + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + ngx_pass_open_channel(cycle, &ch); + } +} + + +static void +ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) +{ + ngx_uint_t i, manager, loader; + ngx_path_t **path; + ngx_channel_t ch; + + manager = 0; + loader = 0; + + path = ngx_cycle->paths.elts; + for (i = 0; i < ngx_cycle->paths.nelts; i++) { + + if (path[i]->manager) { + manager = 1; + } + + if (path[i]->loader) { + loader = 1; + } + } + + if (manager == 0) { + return; + } + + ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, + &ngx_cache_manager_ctx, "cache manager process", + respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); + + ngx_memzero(&ch, sizeof(ngx_channel_t)); + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + ngx_pass_open_channel(cycle, &ch); + + if (loader == 0) { + return; + } + + ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, + &ngx_cache_loader_ctx, "cache loader process", + respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN); + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + ngx_pass_open_channel(cycle, &ch); +} + + +static void +ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) +{ + ngx_int_t i; + + for (i = 0; i < ngx_last_process; i++) { + + if (i == ngx_process_slot + || ngx_processes[i].pid == -1 + || ngx_processes[i].channel[0] == -1) + { + continue; + } + + ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", + ch->slot, ch->pid, ch->fd, + i, ngx_processes[i].pid, + ngx_processes[i].channel[0]); + + /* TODO: NGX_AGAIN */ + + ngx_write_channel(ngx_processes[i].channel[0], + ch, sizeof(ngx_channel_t), cycle->log); + } +} + + +static void +ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo) +{ + ngx_int_t i; + ngx_err_t err; + ngx_channel_t ch; + + ngx_memzero(&ch, sizeof(ngx_channel_t)); + +#if (NGX_BROKEN_SCM_RIGHTS) + + ch.command = 0; + +#else + + switch (signo) { + + case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): + ch.command = NGX_CMD_QUIT; + break; + + case ngx_signal_value(NGX_TERMINATE_SIGNAL): + ch.command = NGX_CMD_TERMINATE; + break; + + case ngx_signal_value(NGX_REOPEN_SIGNAL): + ch.command = NGX_CMD_REOPEN; + break; + + default: + ch.command = 0; + } + +#endif + + ch.fd = -1; + + + for (i = 0; i < ngx_last_process; i++) { + + ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "child: %d %P e:%d t:%d d:%d r:%d j:%d", + i, + ngx_processes[i].pid, + ngx_processes[i].exiting, + ngx_processes[i].exited, + ngx_processes[i].detached, + ngx_processes[i].respawn, + ngx_processes[i].just_spawn); + + if (ngx_processes[i].detached || ngx_processes[i].pid == -1) { + continue; + } + + if (ngx_processes[i].just_spawn) { + ngx_processes[i].just_spawn = 0; + continue; + } + + if (ngx_processes[i].exiting + && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL)) + { + continue; + } + + if (ch.command) { + if (ngx_write_channel(ngx_processes[i].channel[0], + &ch, sizeof(ngx_channel_t), cycle->log) + == NGX_OK) + { + if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) { + ngx_processes[i].exiting = 1; + } + + continue; + } + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "kill (%P, %d)", ngx_processes[i].pid, signo); + + if (kill(ngx_processes[i].pid, signo) == -1) { + err = ngx_errno; + ngx_log_error(NGX_LOG_ALERT, cycle->log, err, + "kill(%P, %d) failed", ngx_processes[i].pid, signo); + + if (err == NGX_ESRCH) { + ngx_processes[i].exited = 1; + ngx_processes[i].exiting = 0; + ngx_reap = 1; + } + + continue; + } + + if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) { + ngx_processes[i].exiting = 1; + } + } +} + + +static ngx_uint_t +ngx_reap_children(ngx_cycle_t *cycle) +{ + ngx_int_t i, n; + ngx_uint_t live; + ngx_channel_t ch; + ngx_core_conf_t *ccf; + + ngx_memzero(&ch, sizeof(ngx_channel_t)); + + ch.command = NGX_CMD_CLOSE_CHANNEL; + ch.fd = -1; + + live = 0; + for (i = 0; i < ngx_last_process; i++) { + + ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "child: %d %P e:%d t:%d d:%d r:%d j:%d", + i, + ngx_processes[i].pid, + ngx_processes[i].exiting, + ngx_processes[i].exited, + ngx_processes[i].detached, + ngx_processes[i].respawn, + ngx_processes[i].just_spawn); + + if (ngx_processes[i].pid == -1) { + continue; + } + + if (ngx_processes[i].exited) { + + if (!ngx_processes[i].detached) { + ngx_close_channel(ngx_processes[i].channel, cycle->log); + + ngx_processes[i].channel[0] = -1; + ngx_processes[i].channel[1] = -1; + + ch.pid = ngx_processes[i].pid; + ch.slot = i; + + for (n = 0; n < ngx_last_process; n++) { + if (ngx_processes[n].exited + || ngx_processes[n].pid == -1 + || ngx_processes[n].channel[0] == -1) + { + continue; + } + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "pass close channel s:%i pid:%P to:%P", + ch.slot, ch.pid, ngx_processes[n].pid); + + /* TODO: NGX_AGAIN */ + + ngx_write_channel(ngx_processes[n].channel[0], + &ch, sizeof(ngx_channel_t), cycle->log); + } + } + + if (ngx_processes[i].respawn + && !ngx_processes[i].exiting + && !ngx_terminate + && !ngx_quit) + { + if (ngx_spawn_process(cycle, ngx_processes[i].proc, + ngx_processes[i].data, + ngx_processes[i].name, i) + == NGX_INVALID_PID) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "could not respawn %s", + ngx_processes[i].name); + continue; + } + + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + ngx_pass_open_channel(cycle, &ch); + + live = 1; + + continue; + } + + if (ngx_processes[i].pid == ngx_new_binary) { + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, + ngx_core_module); + + if (ngx_rename_file((char *) ccf->oldpid.data, + (char *) ccf->pid.data) + == NGX_FILE_ERROR) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_rename_file_n " %s back to %s failed " + "after the new binary process \"%s\" exited", + ccf->oldpid.data, ccf->pid.data, ngx_argv[0]); + } + + ngx_new_binary = 0; + if (ngx_noaccepting) { + ngx_restart = 1; + ngx_noaccepting = 0; + } + } + + if (i == ngx_last_process - 1) { + ngx_last_process--; + + } else { + ngx_processes[i].pid = -1; + } + + } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) { + live = 1; + } + } + + return live; +} + + +static void +ngx_master_process_exit(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + + ngx_delete_pidfile(cycle); + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit"); + + for (i = 0; ngx_modules[i]; i++) { + if (ngx_modules[i]->exit_master) { + ngx_modules[i]->exit_master(cycle); + } + } + + ngx_close_listening_sockets(cycle); + + /* + * Copy ngx_cycle->log related data to the special static exit cycle, + * log, and log file structures enough to allow a signal handler to log. + * The handler may be called when standard ngx_cycle->log allocated from + * ngx_cycle->pool is already destroyed. + */ + + + ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log); + + ngx_exit_log_file.fd = ngx_exit_log.file->fd; + ngx_exit_log.file = &ngx_exit_log_file; + ngx_exit_log.next = NULL; + ngx_exit_log.writer = NULL; + + ngx_exit_cycle.log = &ngx_exit_log; + ngx_exit_cycle.files = ngx_cycle->files; + ngx_exit_cycle.files_n = ngx_cycle->files_n; + ngx_cycle = &ngx_exit_cycle; + + ngx_destroy_pool(cycle->pool); + + exit(0); +} + + +static void +ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) +{ + ngx_int_t worker = (intptr_t) data; + + ngx_uint_t i; + ngx_connection_t *c; + + ngx_process = NGX_PROCESS_WORKER; + + ngx_worker_process_init(cycle, worker); + + ngx_setproctitle("worker process"); + + for ( ;; ) { + + if (ngx_exiting) { + + c = cycle->connections; + + for (i = 0; i < cycle->connection_n; i++) { + + /* THREAD: lock */ + + if (c[i].fd != -1 && c[i].idle) { + c[i].close = 1; + c[i].read->handler(c[i].read); + } + } + + ngx_event_cancel_timers(); + + if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel) + { + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); + + ngx_worker_process_exit(cycle); + } + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); + + ngx_process_events_and_timers(cycle); + + if (ngx_terminate) { + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); + + ngx_worker_process_exit(cycle); + } + + if (ngx_quit) { + ngx_quit = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, + "gracefully shutting down"); + ngx_setproctitle("worker process is shutting down"); + + if (!ngx_exiting) { + ngx_close_listening_sockets(cycle); + ngx_exiting = 1; + } + } + + if (ngx_reopen) { + ngx_reopen = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); + ngx_reopen_files(cycle, -1); + } + } +} + + +static void +ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) +{ + sigset_t set; + uint64_t cpu_affinity; + ngx_int_t n; + ngx_uint_t i; + struct rlimit rlmt; + ngx_core_conf_t *ccf; + ngx_listening_t *ls; + + if (ngx_set_environment(cycle, NULL) == NULL) { + /* fatal */ + exit(2); + } + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + + if (worker >= 0 && ccf->priority != 0) { + if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setpriority(%d) failed", ccf->priority); + } + } + + if (ccf->rlimit_nofile != NGX_CONF_UNSET) { + rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile; + rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile; + + if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setrlimit(RLIMIT_NOFILE, %i) failed", + ccf->rlimit_nofile); + } + } + + if (ccf->rlimit_core != NGX_CONF_UNSET) { + rlmt.rlim_cur = (rlim_t) ccf->rlimit_core; + rlmt.rlim_max = (rlim_t) ccf->rlimit_core; + + if (setrlimit(RLIMIT_CORE, &rlmt) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setrlimit(RLIMIT_CORE, %O) failed", + ccf->rlimit_core); + } + } + +#ifdef RLIMIT_SIGPENDING + if (ccf->rlimit_sigpending != NGX_CONF_UNSET) { + rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending; + rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending; + + if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setrlimit(RLIMIT_SIGPENDING, %i) failed", + ccf->rlimit_sigpending); + } + } +#endif + + if (geteuid() == 0) { + if (setgid(ccf->group) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "setgid(%d) failed", ccf->group); + /* fatal */ + exit(2); + } + + if (initgroups(ccf->username, ccf->group) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "initgroups(%s, %d) failed", + ccf->username, ccf->group); + } + + if (setuid(ccf->user) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "setuid(%d) failed", ccf->user); + /* fatal */ + exit(2); + } + } + + if (worker >= 0) { + cpu_affinity = ngx_get_cpu_affinity(worker); + + if (cpu_affinity) { + ngx_setaffinity(cpu_affinity, cycle->log); + } + } + +#if (NGX_HAVE_PR_SET_DUMPABLE) + + /* allow coredump after setuid() in Linux 2.4.x */ + + if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "prctl(PR_SET_DUMPABLE) failed"); + } + +#endif + + if (ccf->working_directory.len) { + if (chdir((char *) ccf->working_directory.data) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "chdir(\"%s\") failed", ccf->working_directory.data); + /* fatal */ + exit(2); + } + } + + sigemptyset(&set); + + if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed"); + } + + srandom((ngx_pid << 16) ^ ngx_time()); + + /* + * disable deleting previous events for the listening sockets because + * in the worker processes there are no events at all at this point + */ + ls = cycle->listening.elts; + for (i = 0; i < cycle->listening.nelts; i++) { + ls[i].previous = NULL; + } + + for (i = 0; ngx_modules[i]; i++) { + if (ngx_modules[i]->init_process) { + if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { + /* fatal */ + exit(2); + } + } + } + + for (n = 0; n < ngx_last_process; n++) { + + if (ngx_processes[n].pid == -1) { + continue; + } + + if (n == ngx_process_slot) { + continue; + } + + if (ngx_processes[n].channel[1] == -1) { + continue; + } + + if (close(ngx_processes[n].channel[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() channel failed"); + } + } + + if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() channel failed"); + } + +#if 0 + ngx_last_process = 0; +#endif + + if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, + ngx_channel_handler) + == NGX_ERROR) + { + /* fatal */ + exit(2); + } +} + + +static void +ngx_worker_process_exit(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + ngx_connection_t *c; + + for (i = 0; ngx_modules[i]; i++) { + if (ngx_modules[i]->exit_process) { + ngx_modules[i]->exit_process(cycle); + } + } + + if (ngx_exiting) { + c = cycle->connections; + for (i = 0; i < cycle->connection_n; i++) { + if (c[i].fd != -1 + && c[i].read + && !c[i].read->accept + && !c[i].read->channel + && !c[i].read->resolver) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "*%uA open socket #%d left in connection %ui", + c[i].number, c[i].fd, i); + ngx_debug_quit = 1; + } + } + + if (ngx_debug_quit) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting"); + ngx_debug_point(); + } + } + + /* + * Copy ngx_cycle->log related data to the special static exit cycle, + * log, and log file structures enough to allow a signal handler to log. + * The handler may be called when standard ngx_cycle->log allocated from + * ngx_cycle->pool is already destroyed. + */ + + ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log); + + ngx_exit_log_file.fd = ngx_exit_log.file->fd; + ngx_exit_log.file = &ngx_exit_log_file; + ngx_exit_log.next = NULL; + ngx_exit_log.writer = NULL; + + ngx_exit_cycle.log = &ngx_exit_log; + ngx_exit_cycle.files = ngx_cycle->files; + ngx_exit_cycle.files_n = ngx_cycle->files_n; + ngx_cycle = &ngx_exit_cycle; + + ngx_destroy_pool(cycle->pool); + + ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit"); + + exit(0); +} + + +static void +ngx_channel_handler(ngx_event_t *ev) +{ + ngx_int_t n; + ngx_channel_t ch; + ngx_connection_t *c; + + if (ev->timedout) { + ev->timedout = 0; + return; + } + + c = ev->data; + + ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler"); + + for ( ;; ) { + + n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log); + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n); + + if (n == NGX_ERROR) { + + if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { + ngx_del_conn(c, 0); + } + + ngx_close_connection(c); + return; + } + + if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) { + if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) { + return; + } + } + + if (n == NGX_AGAIN) { + return; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, + "channel command: %d", ch.command); + + switch (ch.command) { + + case NGX_CMD_QUIT: + ngx_quit = 1; + break; + + case NGX_CMD_TERMINATE: + ngx_terminate = 1; + break; + + case NGX_CMD_REOPEN: + ngx_reopen = 1; + break; + + case NGX_CMD_OPEN_CHANNEL: + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0, + "get channel s:%i pid:%P fd:%d", + ch.slot, ch.pid, ch.fd); + + ngx_processes[ch.slot].pid = ch.pid; + ngx_processes[ch.slot].channel[0] = ch.fd; + break; + + case NGX_CMD_CLOSE_CHANNEL: + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0, + "close channel s:%i pid:%P our:%P fd:%d", + ch.slot, ch.pid, ngx_processes[ch.slot].pid, + ngx_processes[ch.slot].channel[0]); + + if (close(ngx_processes[ch.slot].channel[0]) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "close() channel failed"); + } + + ngx_processes[ch.slot].channel[0] = -1; + break; + } + } +} + + +static void +ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data) +{ + ngx_cache_manager_ctx_t *ctx = data; + + void *ident[4]; + ngx_event_t ev; + + /* + * Set correct process type since closing listening Unix domain socket + * in a master process also removes the Unix domain socket file. + */ + ngx_process = NGX_PROCESS_HELPER; + + ngx_close_listening_sockets(cycle); + + /* Set a moderate number of connections for a helper process. */ + cycle->connection_n = 512; + + ngx_worker_process_init(cycle, -1); + + ngx_memzero(&ev, sizeof(ngx_event_t)); + ev.handler = ctx->handler; + ev.data = ident; + ev.log = cycle->log; + ident[3] = (void *) -1; + + ngx_use_accept_mutex = 0; + + ngx_setproctitle(ctx->name); + + ngx_add_timer(&ev, ctx->delay); + + for ( ;; ) { + + if (ngx_terminate || ngx_quit) { + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); + exit(0); + } + + if (ngx_reopen) { + ngx_reopen = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); + ngx_reopen_files(cycle, -1); + } + + ngx_process_events_and_timers(cycle); + } +} + + +static void +ngx_cache_manager_process_handler(ngx_event_t *ev) +{ + time_t next, n; + ngx_uint_t i; + ngx_path_t **path; + + next = 60 * 60; + + path = ngx_cycle->paths.elts; + for (i = 0; i < ngx_cycle->paths.nelts; i++) { + + if (path[i]->manager) { + n = path[i]->manager(path[i]->data); + + next = (n <= next) ? n : next; + + ngx_time_update(); + } + } + + if (next == 0) { + next = 1; + } + + ngx_add_timer(ev, next * 1000); +} + + +static void +ngx_cache_loader_process_handler(ngx_event_t *ev) +{ + ngx_uint_t i; + ngx_path_t **path; + ngx_cycle_t *cycle; + + cycle = (ngx_cycle_t *) ngx_cycle; + + path = cycle->paths.elts; + for (i = 0; i < cycle->paths.nelts; i++) { + + if (ngx_terminate || ngx_quit) { + break; + } + + if (path[i]->loader) { + path[i]->loader(path[i]->data); + ngx_time_update(); + } + } + + exit(0); +} diff --git a/hm_nginx/src/os/unix/ngx_process_cycle.h b/hm_nginx/src/os/unix/ngx_process_cycle.h new file mode 100644 index 0000000..d44c377 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_process_cycle.h @@ -0,0 +1,60 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_PROCESS_CYCLE_H_INCLUDED_ +#define _NGX_PROCESS_CYCLE_H_INCLUDED_ + + +#include +#include + + +#define NGX_CMD_OPEN_CHANNEL 1 +#define NGX_CMD_CLOSE_CHANNEL 2 +#define NGX_CMD_QUIT 3 +#define NGX_CMD_TERMINATE 4 +#define NGX_CMD_REOPEN 5 + + +#define NGX_PROCESS_SINGLE 0 +#define NGX_PROCESS_MASTER 1 +#define NGX_PROCESS_SIGNALLER 2 +#define NGX_PROCESS_WORKER 3 +#define NGX_PROCESS_HELPER 4 + + +typedef struct { + ngx_event_handler_pt handler; + char *name; + ngx_msec_t delay; +} ngx_cache_manager_ctx_t; + + +void ngx_master_process_cycle(ngx_cycle_t *cycle); +void ngx_single_process_cycle(ngx_cycle_t *cycle); + + +extern ngx_uint_t ngx_process; +extern ngx_pid_t ngx_pid; +extern ngx_pid_t ngx_new_binary; +extern ngx_uint_t ngx_inherited; +extern ngx_uint_t ngx_daemonized; +extern ngx_uint_t ngx_exiting; + +extern sig_atomic_t ngx_reap; +extern sig_atomic_t ngx_sigio; +extern sig_atomic_t ngx_sigalrm; +extern sig_atomic_t ngx_quit; +extern sig_atomic_t ngx_debug_quit; +extern sig_atomic_t ngx_terminate; +extern sig_atomic_t ngx_noaccept; +extern sig_atomic_t ngx_reconfigure; +extern sig_atomic_t ngx_reopen; +extern sig_atomic_t ngx_change_binary; + + +#endif /* _NGX_PROCESS_CYCLE_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_readv_chain.c b/hm_nginx/src/os/unix/ngx_readv_chain.c new file mode 100644 index 0000000..3544b4b --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_readv_chain.c @@ -0,0 +1,186 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ssize_t +ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) +{ + u_char *prev; + ssize_t n, size; + ngx_err_t err; + ngx_array_t vec; + ngx_event_t *rev; + struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE]; + + rev = c->read; + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: eof:%d, avail:%d, err:%d", + rev->pending_eof, rev->available, rev->kq_errno); + + if (rev->available == 0) { + if (rev->pending_eof) { + rev->ready = 0; + rev->eof = 1; + + ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, + "kevent() reported about an closed connection"); + + if (rev->kq_errno) { + rev->error = 1; + ngx_set_socket_errno(rev->kq_errno); + return NGX_ERROR; + } + + return 0; + + } else { + return NGX_AGAIN; + } + } + } + +#endif + + prev = NULL; + iov = NULL; + size = 0; + + vec.elts = iovs; + vec.nelts = 0; + vec.size = sizeof(struct iovec); + vec.nalloc = NGX_IOVS_PREALLOCATE; + vec.pool = c->pool; + + /* coalesce the neighbouring bufs */ + + while (chain) { + n = chain->buf->end - chain->buf->last; + + if (limit) { + if (size >= limit) { + break; + } + + if (size + n > limit) { + n = (ssize_t) (limit - size); + } + } + + if (prev == chain->buf->last) { + iov->iov_len += n; + + } else { + if (vec.nelts >= IOV_MAX) { + break; + } + + iov = ngx_array_push(&vec); + if (iov == NULL) { + return NGX_ERROR; + } + + iov->iov_base = (void *) chain->buf->last; + iov->iov_len = n; + } + + size += n; + prev = chain->buf->end; + chain = chain->next; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: %d, last:%d", vec.nelts, iov->iov_len); + + do { + n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); + + if (n >= 0) { + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available -= n; + + /* + * rev->available may be negative here because some additional + * bytes may be received between kevent() and recv() + */ + + if (rev->available <= 0) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + if (rev->available < 0) { + rev->available = 0; + } + } + + if (n == 0) { + + /* + * on FreeBSD recv() may return 0 on closed socket + * even if kqueue reported about available data + */ + +#if 0 + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "readv() returned 0 while kevent() reported " + "%d available bytes", rev->available); +#endif + + rev->ready = 0; + rev->eof = 1; + rev->available = 0; + } + + return n; + } + +#endif /* NGX_HAVE_KQUEUE */ + + if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { + rev->ready = 0; + } + + if (n == 0) { + rev->eof = 1; + } + + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "readv() not ready"); + n = NGX_AGAIN; + + } else { + n = ngx_connection_error(c, err, "readv() failed"); + break; + } + + } while (err == NGX_EINTR); + + rev->ready = 0; + + if (n == NGX_ERROR) { + c->read->error = 1; + } + + return n; +} diff --git a/hm_nginx/src/os/unix/ngx_recv.c b/hm_nginx/src/os/unix/ngx_recv.c new file mode 100644 index 0000000..86675df --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_recv.c @@ -0,0 +1,183 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#if (NGX_HAVE_KQUEUE) + +ssize_t +ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) +{ + ssize_t n; + ngx_err_t err; + ngx_event_t *rev; + + rev = c->read; + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: eof:%d, avail:%d, err:%d", + rev->pending_eof, rev->available, rev->kq_errno); + + if (rev->available == 0) { + if (rev->pending_eof) { + rev->ready = 0; + rev->eof = 1; + + if (rev->kq_errno) { + rev->error = 1; + ngx_set_socket_errno(rev->kq_errno); + + return ngx_connection_error(c, rev->kq_errno, + "kevent() reported about an closed connection"); + } + + return 0; + + } else { + rev->ready = 0; + return NGX_AGAIN; + } + } + } + + do { + n = recv(c->fd, buf, size, 0); + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: fd:%d %d of %d", c->fd, n, size); + + if (n >= 0) { + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available -= n; + + /* + * rev->available may be negative here because some additional + * bytes may be received between kevent() and recv() + */ + + if (rev->available <= 0) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + if (rev->available < 0) { + rev->available = 0; + } + } + + if (n == 0) { + + /* + * on FreeBSD recv() may return 0 on closed socket + * even if kqueue reported about available data + */ + + rev->ready = 0; + rev->eof = 1; + rev->available = 0; + } + + return n; + } + + if ((size_t) n < size + && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) + { + rev->ready = 0; + } + + if (n == 0) { + rev->eof = 1; + } + + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "recv() not ready"); + n = NGX_AGAIN; + + } else { + n = ngx_connection_error(c, err, "recv() failed"); + break; + } + + } while (err == NGX_EINTR); + + rev->ready = 0; + + if (n == NGX_ERROR) { + rev->error = 1; + } + + return n; +} + +#else /* ! NGX_HAVE_KQUEUE */ + +ssize_t +ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) +{ + ssize_t n; + ngx_err_t err; + ngx_event_t *rev; + + rev = c->read; + + do { + n = recv(c->fd, buf, size, 0); + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: fd:%d %d of %d", c->fd, n, size); + + if (n == 0) { + rev->ready = 0; + rev->eof = 1; + return n; + + } else if (n > 0) { + + if ((size_t) n < size + && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) + { + rev->ready = 0; + } + + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "recv() not ready"); + n = NGX_AGAIN; + + } else { + n = ngx_connection_error(c, err, "recv() failed"); + break; + } + + } while (err == NGX_EINTR); + + rev->ready = 0; + + if (n == NGX_ERROR) { + rev->error = 1; + } + + return n; +} + +#endif /* NGX_HAVE_KQUEUE */ diff --git a/hm_nginx/src/os/unix/ngx_send.c b/hm_nginx/src/os/unix/ngx_send.c new file mode 100644 index 0000000..80995ab --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_send.c @@ -0,0 +1,73 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ssize_t +ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size) +{ + ssize_t n; + ngx_err_t err; + ngx_event_t *wev; + + wev = c->write; + +#if (NGX_HAVE_KQUEUE) + + if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); + wev->error = 1; + return NGX_ERROR; + } + +#endif + + for ( ;; ) { + n = send(c->fd, buf, size, 0); + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "send: fd:%d %d of %d", c->fd, n, size); + + if (n > 0) { + if (n < (ssize_t) size) { + wev->ready = 0; + } + + c->sent += n; + + return n; + } + + err = ngx_socket_errno; + + if (n == 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, err, "send() returned zero"); + wev->ready = 0; + return n; + } + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + wev->ready = 0; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "send() not ready"); + + if (err == NGX_EAGAIN) { + return NGX_AGAIN; + } + + } else { + wev->error = 1; + (void) ngx_connection_error(c, err, "send() failed"); + return NGX_ERROR; + } + } +} diff --git a/hm_nginx/src/os/unix/ngx_setaffinity.c b/hm_nginx/src/os/unix/ngx_setaffinity.c new file mode 100644 index 0000000..8f6cf35 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_setaffinity.c @@ -0,0 +1,69 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#if (NGX_HAVE_CPUSET_SETAFFINITY) + +#include + +void +ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +{ + cpuset_t mask; + ngx_uint_t i; + + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "cpuset_setaffinity(0x%08Xl)", cpu_affinity); + + CPU_ZERO(&mask); + i = 0; + do { + if (cpu_affinity & 1) { + CPU_SET(i, &mask); + } + i++; + cpu_affinity >>= 1; + } while (cpu_affinity); + + if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, + sizeof(cpuset_t), &mask) == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "cpuset_setaffinity() failed"); + } +} + +#elif (NGX_HAVE_SCHED_SETAFFINITY) + +void +ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +{ + cpu_set_t mask; + ngx_uint_t i; + + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "sched_setaffinity(0x%08Xl)", cpu_affinity); + + CPU_ZERO(&mask); + i = 0; + do { + if (cpu_affinity & 1) { + CPU_SET(i, &mask); + } + i++; + cpu_affinity >>= 1; + } while (cpu_affinity); + + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sched_setaffinity() failed"); + } +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_setaffinity.h b/hm_nginx/src/os/unix/ngx_setaffinity.h new file mode 100644 index 0000000..33f5835 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_setaffinity.h @@ -0,0 +1,23 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + +#ifndef _NGX_SETAFFINITY_H_INCLUDED_ +#define _NGX_SETAFFINITY_H_INCLUDED_ + + +#if (NGX_HAVE_SCHED_SETAFFINITY || NGX_HAVE_CPUSET_SETAFFINITY) + +#define NGX_HAVE_CPU_AFFINITY 1 + +void ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log); + +#else + +#define ngx_setaffinity(cpu_affinity, log) + +#endif + + +#endif /* _NGX_SETAFFINITY_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_setproctitle.c b/hm_nginx/src/os/unix/ngx_setproctitle.c new file mode 100644 index 0000000..91afa51 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_setproctitle.c @@ -0,0 +1,135 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#if (NGX_SETPROCTITLE_USES_ENV) + +/* + * To change the process title in Linux and Solaris we have to set argv[1] + * to NULL and to copy the title to the same place where the argv[0] points to. + * However, argv[0] may be too small to hold a new title. Fortunately, Linux + * and Solaris store argv[] and environ[] one after another. So we should + * ensure that is the continuous memory and then we allocate the new memory + * for environ[] and copy it. After this we could use the memory starting + * from argv[0] for our process title. + * + * The Solaris's standard /bin/ps does not show the changed process title. + * You have to use "/usr/ucb/ps -w" instead. Besides, the UCB ps does not + * show a new title if its length less than the origin command line length. + * To avoid it we append to a new title the origin command line in the + * parenthesis. + */ + +extern char **environ; + +static char *ngx_os_argv_last; + +ngx_int_t +ngx_init_setproctitle(ngx_log_t *log) +{ + u_char *p; + size_t size; + ngx_uint_t i; + + size = 0; + + for (i = 0; environ[i]; i++) { + size += ngx_strlen(environ[i]) + 1; + } + + p = ngx_alloc(size, log); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_os_argv_last = ngx_os_argv[0]; + + for (i = 0; ngx_os_argv[i]; i++) { + if (ngx_os_argv_last == ngx_os_argv[i]) { + ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1; + } + } + + for (i = 0; environ[i]; i++) { + if (ngx_os_argv_last == environ[i]) { + + size = ngx_strlen(environ[i]) + 1; + ngx_os_argv_last = environ[i] + size; + + ngx_cpystrn(p, (u_char *) environ[i], size); + environ[i] = (char *) p; + p += size; + } + } + + ngx_os_argv_last--; + + return NGX_OK; +} + + +void +ngx_setproctitle(char *title) +{ + u_char *p; + +#if (NGX_SOLARIS) + + ngx_int_t i; + size_t size; + +#endif + + ngx_os_argv[1] = NULL; + + p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ", + ngx_os_argv_last - ngx_os_argv[0]); + + p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p); + +#if (NGX_SOLARIS) + + size = 0; + + for (i = 0; i < ngx_argc; i++) { + size += ngx_strlen(ngx_argv[i]) + 1; + } + + if (size > (size_t) ((char *) p - ngx_os_argv[0])) { + + /* + * ngx_setproctitle() is too rare operation so we use + * the non-optimized copies + */ + + p = ngx_cpystrn(p, (u_char *) " (", ngx_os_argv_last - (char *) p); + + for (i = 0; i < ngx_argc; i++) { + p = ngx_cpystrn(p, (u_char *) ngx_argv[i], + ngx_os_argv_last - (char *) p); + p = ngx_cpystrn(p, (u_char *) " ", ngx_os_argv_last - (char *) p); + } + + if (*(p - 1) == ' ') { + *(p - 1) = ')'; + } + } + +#endif + + if (ngx_os_argv_last - (char *) p) { + ngx_memset(p, NGX_SETPROCTITLE_PAD, ngx_os_argv_last - (char *) p); + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, + "setproctitle: \"%s\"", ngx_os_argv[0]); +} + +#endif /* NGX_SETPROCTITLE_USES_ENV */ diff --git a/hm_nginx/src/os/unix/ngx_setproctitle.h b/hm_nginx/src/os/unix/ngx_setproctitle.h new file mode 100644 index 0000000..c363662 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_setproctitle.h @@ -0,0 +1,52 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_SETPROCTITLE_H_INCLUDED_ +#define _NGX_SETPROCTITLE_H_INCLUDED_ + + +#if (NGX_HAVE_SETPROCTITLE) + +/* FreeBSD, NetBSD, OpenBSD */ + +#define ngx_init_setproctitle(log) NGX_OK +#define ngx_setproctitle(title) setproctitle("%s", title) + + +#else /* !NGX_HAVE_SETPROCTITLE */ + +#if !defined NGX_SETPROCTITLE_USES_ENV + +#if (NGX_SOLARIS) + +#define NGX_SETPROCTITLE_USES_ENV 1 +#define NGX_SETPROCTITLE_PAD ' ' + +ngx_int_t ngx_init_setproctitle(ngx_log_t *log); +void ngx_setproctitle(char *title); + +#elif (NGX_LINUX) || (NGX_DARWIN) + +#define NGX_SETPROCTITLE_USES_ENV 1 +#define NGX_SETPROCTITLE_PAD '\0' + +ngx_int_t ngx_init_setproctitle(ngx_log_t *log); +void ngx_setproctitle(char *title); + +#else + +#define ngx_init_setproctitle(log) NGX_OK +#define ngx_setproctitle(title) + +#endif /* OSes */ + +#endif /* NGX_SETPROCTITLE_USES_ENV */ + +#endif /* NGX_HAVE_SETPROCTITLE */ + + +#endif /* _NGX_SETPROCTITLE_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_shmem.c b/hm_nginx/src/os/unix/ngx_shmem.c new file mode 100644 index 0000000..3ec7cbf --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_shmem.c @@ -0,0 +1,126 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#if (NGX_HAVE_MAP_ANON) + +ngx_int_t +ngx_shm_alloc(ngx_shm_t *shm) +{ + shm->addr = (u_char *) mmap(NULL, shm->size, + PROT_READ|PROT_WRITE, + MAP_ANON|MAP_SHARED, -1, 0); + + if (shm->addr == MAP_FAILED) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size); + return NGX_ERROR; + } + + return NGX_OK; +} + + +void +ngx_shm_free(ngx_shm_t *shm) +{ + if (munmap((void *) shm->addr, shm->size) == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "munmap(%p, %uz) failed", shm->addr, shm->size); + } +} + +#elif (NGX_HAVE_MAP_DEVZERO) + +ngx_int_t +ngx_shm_alloc(ngx_shm_t *shm) +{ + ngx_fd_t fd; + + fd = open("/dev/zero", O_RDWR); + + if (fd == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "open(\"/dev/zero\") failed"); + return NGX_ERROR; + } + + shm->addr = (u_char *) mmap(NULL, shm->size, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0); + + if (shm->addr == MAP_FAILED) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "mmap(/dev/zero, MAP_SHARED, %uz) failed", shm->size); + } + + if (close(fd) == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "close(\"/dev/zero\") failed"); + } + + return (shm->addr == MAP_FAILED) ? NGX_ERROR : NGX_OK; +} + + +void +ngx_shm_free(ngx_shm_t *shm) +{ + if (munmap((void *) shm->addr, shm->size) == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "munmap(%p, %uz) failed", shm->addr, shm->size); + } +} + +#elif (NGX_HAVE_SYSVSHM) + +#include +#include + + +ngx_int_t +ngx_shm_alloc(ngx_shm_t *shm) +{ + int id; + + id = shmget(IPC_PRIVATE, shm->size, (SHM_R|SHM_W|IPC_CREAT)); + + if (id == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "shmget(%uz) failed", shm->size); + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, shm->log, 0, "shmget id: %d", id); + + shm->addr = shmat(id, NULL, 0); + + if (shm->addr == (void *) -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmat() failed"); + } + + if (shmctl(id, IPC_RMID, NULL) == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "shmctl(IPC_RMID) failed"); + } + + return (shm->addr == (void *) -1) ? NGX_ERROR : NGX_OK; +} + + +void +ngx_shm_free(ngx_shm_t *shm) +{ + if (shmdt(shm->addr) == -1) { + ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, + "shmdt(%p) failed", shm->addr); + } +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_shmem.h b/hm_nginx/src/os/unix/ngx_shmem.h new file mode 100644 index 0000000..566a7d3 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_shmem.h @@ -0,0 +1,29 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_SHMEM_H_INCLUDED_ +#define _NGX_SHMEM_H_INCLUDED_ + + +#include +#include + + +typedef struct { + u_char *addr; + size_t size; + ngx_str_t name; + ngx_log_t *log; + ngx_uint_t exists; /* unsigned exists:1; */ +} ngx_shm_t; + + +ngx_int_t ngx_shm_alloc(ngx_shm_t *shm); +void ngx_shm_free(ngx_shm_t *shm); + + +#endif /* _NGX_SHMEM_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_socket.c b/hm_nginx/src/os/unix/ngx_socket.c new file mode 100644 index 0000000..3978f65 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_socket.c @@ -0,0 +1,116 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +/* + * ioctl(FIONBIO) sets a non-blocking mode with the single syscall + * while fcntl(F_SETFL, O_NONBLOCK) needs to learn the current state + * using fcntl(F_GETFL). + * + * ioctl() and fcntl() are syscalls at least in FreeBSD 2.x, Linux 2.2 + * and Solaris 7. + * + * ioctl() in Linux 2.4 and 2.6 uses BKL, however, fcntl(F_SETFL) uses it too. + */ + + +#if (NGX_HAVE_FIONBIO) + +int +ngx_nonblocking(ngx_socket_t s) +{ + int nb; + + nb = 1; + + return ioctl(s, FIONBIO, &nb); +} + + +int +ngx_blocking(ngx_socket_t s) +{ + int nb; + + nb = 0; + + return ioctl(s, FIONBIO, &nb); +} + +#endif + + +#if (NGX_FREEBSD) + +int +ngx_tcp_nopush(ngx_socket_t s) +{ + int tcp_nopush; + + tcp_nopush = 1; + + return setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, + (const void *) &tcp_nopush, sizeof(int)); +} + + +int +ngx_tcp_push(ngx_socket_t s) +{ + int tcp_nopush; + + tcp_nopush = 0; + + return setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, + (const void *) &tcp_nopush, sizeof(int)); +} + +#elif (NGX_LINUX) + + +int +ngx_tcp_nopush(ngx_socket_t s) +{ + int cork; + + cork = 1; + + return setsockopt(s, IPPROTO_TCP, TCP_CORK, + (const void *) &cork, sizeof(int)); +} + + +int +ngx_tcp_push(ngx_socket_t s) +{ + int cork; + + cork = 0; + + return setsockopt(s, IPPROTO_TCP, TCP_CORK, + (const void *) &cork, sizeof(int)); +} + +#else + +int +ngx_tcp_nopush(ngx_socket_t s) +{ + return 0; +} + + +int +ngx_tcp_push(ngx_socket_t s) +{ + return 0; +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_socket.h b/hm_nginx/src/os/unix/ngx_socket.h new file mode 100644 index 0000000..fcc5153 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_socket.h @@ -0,0 +1,64 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_SOCKET_H_INCLUDED_ +#define _NGX_SOCKET_H_INCLUDED_ + + +#include + + +#define NGX_WRITE_SHUTDOWN SHUT_WR + +typedef int ngx_socket_t; + +#define ngx_socket socket +#define ngx_socket_n "socket()" + + +#if (NGX_HAVE_FIONBIO) + +int ngx_nonblocking(ngx_socket_t s); +int ngx_blocking(ngx_socket_t s); + +#define ngx_nonblocking_n "ioctl(FIONBIO)" +#define ngx_blocking_n "ioctl(!FIONBIO)" + +#else + +#define ngx_nonblocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK) +#define ngx_nonblocking_n "fcntl(O_NONBLOCK)" + +#define ngx_blocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK) +#define ngx_blocking_n "fcntl(!O_NONBLOCK)" + +#endif + +int ngx_tcp_nopush(ngx_socket_t s); +int ngx_tcp_push(ngx_socket_t s); + +#if (NGX_LINUX) + +#define ngx_tcp_nopush_n "setsockopt(TCP_CORK)" +#define ngx_tcp_push_n "setsockopt(!TCP_CORK)" + +#else + +#define ngx_tcp_nopush_n "setsockopt(TCP_NOPUSH)" +#define ngx_tcp_push_n "setsockopt(!TCP_NOPUSH)" + +#endif + + +#define ngx_shutdown_socket shutdown +#define ngx_shutdown_socket_n "shutdown()" + +#define ngx_close_socket close +#define ngx_close_socket_n "close() socket" + + +#endif /* _NGX_SOCKET_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_solaris.h b/hm_nginx/src/os/unix/ngx_solaris.h new file mode 100644 index 0000000..7b167d8 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_solaris.h @@ -0,0 +1,16 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_SOLARIS_H_INCLUDED_ +#define _NGX_SOLARIS_H_INCLUDED_ + + +ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + + +#endif /* _NGX_SOLARIS_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_solaris_config.h b/hm_nginx/src/os/unix/ngx_solaris_config.h new file mode 100644 index 0000000..ddfd984 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_solaris_config.h @@ -0,0 +1,110 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_SOLARIS_CONFIG_H_INCLUDED_ +#define _NGX_SOLARIS_CONFIG_H_INCLUDED_ + + +#ifndef _REENTRANT +#define _REENTRANT +#endif + +#define _FILE_OFFSET_BITS 64 /* must be before */ + +#include +#include +#include +#include +#include /* offsetof() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* statvfs() */ + +#include /* FIONBIO */ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include /* TCP_NODELAY */ +#include +#include +#include + +#include +#include /* IOV_MAX */ +#include +#include + +#define NGX_ALIGNMENT _MAX_ALIGNMENT + +#include + + +#if (NGX_HAVE_POSIX_SEM) +#include +#endif + + +#if (NGX_HAVE_POLL) +#include +#endif + + +#if (NGX_HAVE_DEVPOLL) +#include +#include +#endif + + +#if (NGX_HAVE_EVENTPORT) +#include +#endif + + +#if (NGX_HAVE_SENDFILE) +#include +#endif + + +#define NGX_LISTEN_BACKLOG 511 + + +#ifndef NGX_HAVE_INHERITED_NONBLOCK +#define NGX_HAVE_INHERITED_NONBLOCK 1 +#endif + + +#ifndef NGX_HAVE_SO_SNDLOWAT +/* setsockopt(SO_SNDLOWAT) returns ENOPROTOOPT */ +#define NGX_HAVE_SO_SNDLOWAT 0 +#endif + + +#define NGX_HAVE_OS_SPECIFIC_INIT 1 +#define ngx_debug_init() + + +extern char **environ; + + +#endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_solaris_init.c b/hm_nginx/src/os/unix/ngx_solaris_init.c new file mode 100644 index 0000000..f2f3600 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_solaris_init.c @@ -0,0 +1,75 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +char ngx_solaris_sysname[20]; +char ngx_solaris_release[10]; +char ngx_solaris_version[50]; + + +static ngx_os_io_t ngx_solaris_io = { + ngx_unix_recv, + ngx_readv_chain, + ngx_udp_unix_recv, + ngx_unix_send, +#if (NGX_HAVE_SENDFILE) + ngx_solaris_sendfilev_chain, + NGX_IO_SENDFILE +#else + ngx_writev_chain, + 0 +#endif +}; + + +ngx_int_t +ngx_os_specific_init(ngx_log_t *log) +{ + if (sysinfo(SI_SYSNAME, ngx_solaris_sysname, sizeof(ngx_solaris_sysname)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysinfo(SI_SYSNAME) failed"); + return NGX_ERROR; + } + + if (sysinfo(SI_RELEASE, ngx_solaris_release, sizeof(ngx_solaris_release)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysinfo(SI_RELEASE) failed"); + return NGX_ERROR; + } + + if (sysinfo(SI_VERSION, ngx_solaris_version, sizeof(ngx_solaris_version)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysinfo(SI_SYSNAME) failed"); + return NGX_ERROR; + } + + + ngx_os_io = ngx_solaris_io; + + return NGX_OK; +} + + +void +ngx_os_specific_status(ngx_log_t *log) +{ + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", + ngx_solaris_sysname, ngx_solaris_release); + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "version: %s", + ngx_solaris_version); +} diff --git a/hm_nginx/src/os/unix/ngx_solaris_sendfilev_chain.c b/hm_nginx/src/os/unix/ngx_solaris_sendfilev_chain.c new file mode 100644 index 0000000..7504239 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_solaris_sendfilev_chain.c @@ -0,0 +1,205 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#if (NGX_TEST_BUILD_SOLARIS_SENDFILEV) + +/* Solaris declarations */ + +typedef struct sendfilevec { + int sfv_fd; + u_int sfv_flag; + off_t sfv_off; + size_t sfv_len; +} sendfilevec_t; + +#define SFV_FD_SELF -2 + +static ssize_t sendfilev(int fd, const struct sendfilevec *vec, + int sfvcnt, size_t *xferred) +{ + return -1; +} + +ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); + +#endif + + +#define NGX_SENDFILEVECS NGX_IOVS_PREALLOCATE + + +ngx_chain_t * +ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) +{ + int fd; + u_char *prev; + off_t size, send, prev_send, aligned, fprev; + size_t sent; + ssize_t n; + ngx_int_t eintr; + ngx_err_t err; + ngx_uint_t nsfv; + sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; + ngx_event_t *wev; + ngx_chain_t *cl; + + wev = c->write; + + if (!wev->ready) { + return in; + } + + if (!c->sendfile) { + return ngx_writev_chain(c, in, limit); + } + + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { + limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; + } + + + send = 0; + + for ( ;; ) { + fd = SFV_FD_SELF; + prev = NULL; + fprev = 0; + sfv = NULL; + eintr = 0; + sent = 0; + prev_send = send; + + nsfv = 0; + + /* create the sendfilevec and coalesce the neighbouring bufs */ + + for (cl = in; cl && send < limit; cl = cl->next) { + + if (ngx_buf_special(cl->buf)) { + continue; + } + + if (ngx_buf_in_memory_only(cl->buf)) { + fd = SFV_FD_SELF; + + size = cl->buf->last - cl->buf->pos; + + if (send + size > limit) { + size = limit - send; + } + + if (prev == cl->buf->pos) { + sfv->sfv_len += (size_t) size; + + } else { + if (nsfv == NGX_SENDFILEVECS) { + break; + } + + sfv = &sfvs[nsfv++]; + + sfv->sfv_fd = SFV_FD_SELF; + sfv->sfv_flag = 0; + sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos; + sfv->sfv_len = (size_t) size; + } + + prev = cl->buf->pos + (size_t) size; + send += size; + + } else { + prev = NULL; + + size = cl->buf->file_last - cl->buf->file_pos; + + if (send + size > limit) { + size = limit - send; + + aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) + & ~((off_t) ngx_pagesize - 1); + + if (aligned <= cl->buf->file_last) { + size = aligned - cl->buf->file_pos; + } + } + + if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) { + sfv->sfv_len += (size_t) size; + + } else { + if (nsfv == NGX_SENDFILEVECS) { + break; + } + + sfv = &sfvs[nsfv++]; + + fd = cl->buf->file->fd; + sfv->sfv_fd = fd; + sfv->sfv_flag = 0; + sfv->sfv_off = cl->buf->file_pos; + sfv->sfv_len = (size_t) size; + } + + fprev = cl->buf->file_pos + size; + send += size; + } + } + + n = sendfilev(c->fd, sfvs, nsfv, &sent); + + if (n == -1) { + err = ngx_errno; + + switch (err) { + case NGX_EAGAIN: + break; + + case NGX_EINTR: + eintr = 1; + break; + + default: + wev->error = 1; + ngx_connection_error(c, err, "sendfilev() failed"); + return NGX_CHAIN_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, + "sendfilev() sent only %uz bytes", sent); + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendfilev: %z %z", n, sent); + + c->sent += sent; + + in = ngx_chain_update_sent(in, sent); + + if (eintr) { + send = prev_send + sent; + continue; + } + + if (send - prev_send != (off_t) sent) { + wev->ready = 0; + return in; + } + + if (send >= limit || in == NULL) { + return in; + } + } +} diff --git a/hm_nginx/src/os/unix/ngx_sunpro_amd64.il b/hm_nginx/src/os/unix/ngx_sunpro_amd64.il new file mode 100644 index 0000000..dc454b2 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_sunpro_amd64.il @@ -0,0 +1,43 @@ +/ +/ Copyright (C) Igor Sysoev +/ Copyright (C) Nginx, Inc. +/ + +/ ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock, +/ ngx_atomic_uint_t old, ngx_atomic_uint_t set); +/ +/ the arguments are passed in %rdi, %rsi, %rdx +/ the result is returned in the %rax + + .inline ngx_atomic_cmp_set,0 + movq %rsi, %rax + lock + cmpxchgq %rdx, (%rdi) + setz %al + movzbq %al, %rax + .end + + +/ ngx_atomic_int_t ngx_atomic_fetch_add(ngx_atomic_t *value, +/ ngx_atomic_int_t add); +/ +/ the arguments are passed in %rdi, %rsi +/ the result is returned in the %rax + + .inline ngx_atomic_fetch_add,0 + movq %rsi, %rax + lock + xaddq %rax, (%rdi) + .end + + +/ ngx_cpu_pause() +/ +/ the "rep; nop" is used instead of "pause" to avoid the "[ PAUSE ]" hardware +/ capability added by linker because Solaris/amd64 does not know about it: +/ +/ ld.so.1: nginx: fatal: hardware capability unsupported: 0x2000 [ PAUSE ] + + .inline ngx_cpu_pause,0 + rep; nop + .end diff --git a/hm_nginx/src/os/unix/ngx_sunpro_atomic_sparc64.h b/hm_nginx/src/os/unix/ngx_sunpro_atomic_sparc64.h new file mode 100644 index 0000000..5f28055 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_sunpro_atomic_sparc64.h @@ -0,0 +1,61 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#if (NGX_PTR_SIZE == 4) +#define NGX_CASA ngx_casa +#else +#define NGX_CASA ngx_casxa +#endif + + +ngx_atomic_uint_t +ngx_casa(ngx_atomic_uint_t set, ngx_atomic_uint_t old, ngx_atomic_t *lock); + +ngx_atomic_uint_t +ngx_casxa(ngx_atomic_uint_t set, ngx_atomic_uint_t old, ngx_atomic_t *lock); + +/* the code in src/os/unix/ngx_sunpro_sparc64.il */ + + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + set = NGX_CASA(set, old, lock); + + return (set == old); +} + + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_uint_t old, res; + + old = *value; + + for ( ;; ) { + + res = old + add; + + res = NGX_CASA(res, old, value); + + if (res == old) { + return res; + } + + old = res; + } +} + + +#define ngx_memory_barrier() \ + __asm (".volatile"); \ + __asm ("membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad"); \ + __asm (".nonvolatile") + +#define ngx_cpu_pause() diff --git a/hm_nginx/src/os/unix/ngx_sunpro_sparc64.il b/hm_nginx/src/os/unix/ngx_sunpro_sparc64.il new file mode 100644 index 0000000..bdeef61 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_sunpro_sparc64.il @@ -0,0 +1,36 @@ +/ +/ Copyright (C) Igor Sysoev +/ Copyright (C) Nginx, Inc. +/ + + +/ "casa [%o2] 0x80, %o1, %o0" and +/ "casxa [%o2] 0x80, %o1, %o0" do the following: +/ +/ if ([%o2] == %o1) { +/ swap(%o0, [%o2]); +/ } else { +/ %o0 = [%o2]; +/ } + + +/ ngx_atomic_uint_t ngx_casa(ngx_atomic_uint_t set, ngx_atomic_uint_t old, +/ ngx_atomic_t *lock); +/ +/ the arguments are passed in the %o0, %o1, %o2 +/ the result is returned in the %o0 + + .inline ngx_casa,0 + casa [%o2] 0x80, %o1, %o0 + .end + + +/ ngx_atomic_uint_t ngx_casxa(ngx_atomic_uint_t set, ngx_atomic_uint_t old, +/ ngx_atomic_t *lock); +/ +/ the arguments are passed in the %o0, %o1, %o2 +/ the result is returned in the %o0 + + .inline ngx_casxa,0 + casxa [%o2] 0x80, %o1, %o0 + .end diff --git a/hm_nginx/src/os/unix/ngx_sunpro_x86.il b/hm_nginx/src/os/unix/ngx_sunpro_x86.il new file mode 100644 index 0000000..fd1cc00 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_sunpro_x86.il @@ -0,0 +1,44 @@ +/ +/ Copyright (C) Igor Sysoev +/ Copyright (C) Nginx, Inc. +/ + +/ ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock, +/ ngx_atomic_uint_t old, ngx_atomic_uint_t set); +/ +/ the arguments are passed on stack (%esp), 4(%esp), 8(%esp) + + .inline ngx_atomic_cmp_set,0 + movl (%esp), %ecx + movl 4(%esp), %eax + movl 8(%esp), %edx + lock + cmpxchgl %edx, (%ecx) + setz %al + movzbl %al, %eax + .end + + +/ ngx_atomic_int_t ngx_atomic_fetch_add(ngx_atomic_t *value, +/ ngx_atomic_int_t add); +/ +/ the arguments are passed on stack (%esp), 4(%esp) + + .inline ngx_atomic_fetch_add,0 + movl (%esp), %ecx + movl 4(%esp), %eax + lock + xaddl %eax, (%ecx) + .end + + +/ ngx_cpu_pause() +/ +/ the "rep; nop" is used instead of "pause" to avoid the "[ PAUSE ]" hardware +/ capability added by linker because Solaris/i386 does not know about it: +/ +/ ld.so.1: nginx: fatal: hardware capability unsupported: 0x2000 [ PAUSE ] + + .inline ngx_cpu_pause,0 + rep; nop + .end diff --git a/hm_nginx/src/os/unix/ngx_thread.h b/hm_nginx/src/os/unix/ngx_thread.h new file mode 100644 index 0000000..1b52dd7 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_thread.h @@ -0,0 +1,71 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_THREAD_H_INCLUDED_ +#define _NGX_THREAD_H_INCLUDED_ + + +#include +#include + +#if (NGX_THREADS) + +#include + + +typedef pthread_mutex_t ngx_thread_mutex_t; + +ngx_int_t ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log); +ngx_int_t ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log); +ngx_int_t ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log); +ngx_int_t ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log); + + +typedef pthread_cond_t ngx_thread_cond_t; + +ngx_int_t ngx_thread_cond_create(ngx_thread_cond_t *cond, ngx_log_t *log); +ngx_int_t ngx_thread_cond_destroy(ngx_thread_cond_t *cond, ngx_log_t *log); +ngx_int_t ngx_thread_cond_signal(ngx_thread_cond_t *cond, ngx_log_t *log); +ngx_int_t ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx, + ngx_log_t *log); + + +#if (NGX_LINUX) + +typedef pid_t ngx_tid_t; +#define NGX_TID_T_FMT "%P" + +#elif (NGX_FREEBSD) + +typedef uint32_t ngx_tid_t; +#define NGX_TID_T_FMT "%uD" + +#elif (NGX_DARWIN) + +typedef uint64_t ngx_tid_t; +#define NGX_TID_T_FMT "%uA" + +#else + +typedef uint64_t ngx_tid_t; +#define NGX_TID_T_FMT "%uA" + +#endif + +ngx_tid_t ngx_thread_tid(void); + +#define ngx_log_tid ngx_thread_tid() + +#else + +#define ngx_log_tid 0 +#define NGX_TID_T_FMT "%d" + +#endif + + +#endif /* _NGX_THREAD_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_thread_cond.c b/hm_nginx/src/os/unix/ngx_thread_cond.c new file mode 100644 index 0000000..f524696 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_thread_cond.c @@ -0,0 +1,87 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +ngx_int_t +ngx_thread_cond_create(ngx_thread_cond_t *cond, ngx_log_t *log) +{ + ngx_err_t err; + + err = pthread_cond_init(cond, NULL); + if (err == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_cond_init(%p)", cond); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_EMERG, log, err, "pthread_cond_init() failed"); + return NGX_ERROR; +} + + +ngx_int_t +ngx_thread_cond_destroy(ngx_thread_cond_t *cond, ngx_log_t *log) +{ + ngx_err_t err; + + err = pthread_cond_destroy(cond); + if (err == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_cond_destroy(%p)", cond); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_EMERG, log, err, "pthread_cond_destroy() failed"); + return NGX_ERROR; +} + + +ngx_int_t +ngx_thread_cond_signal(ngx_thread_cond_t *cond, ngx_log_t *log) +{ + ngx_err_t err; + + err = pthread_cond_signal(cond); + if (err == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_cond_signal(%p)", cond); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_EMERG, log, err, "pthread_cond_signal() failed"); + return NGX_ERROR; +} + + +ngx_int_t +ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx, + ngx_log_t *log) +{ + ngx_err_t err; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_cond_wait(%p) enter", cond); + + err = pthread_cond_wait(cond, mtx); + +#if 0 + ngx_time_update(); +#endif + + if (err == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_cond_wait(%p) exit", cond); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_cond_wait() failed"); + + return NGX_ERROR; +} diff --git a/hm_nginx/src/os/unix/ngx_thread_id.c b/hm_nginx/src/os/unix/ngx_thread_id.c new file mode 100644 index 0000000..5174f1a --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_thread_id.c @@ -0,0 +1,70 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#if (NGX_LINUX) + +/* + * Linux thread id is a pid of thread created by clone(2), + * glibc does not provide a wrapper for gettid(). + */ + +ngx_tid_t +ngx_thread_tid(void) +{ + return syscall(SYS_gettid); +} + +#elif (NGX_FREEBSD) && (__FreeBSD_version >= 900031) + +#include + +ngx_tid_t +ngx_thread_tid(void) +{ + return pthread_getthreadid_np(); +} + +#elif (NGX_DARWIN) + +/* + * MacOSX thread has two thread ids: + * + * 1) MacOSX 10.6 (Snow Leoprad) has pthread_threadid_np() returning + * an uint64_t value, which is obtained using the __thread_selfid() + * syscall. It is a number above 300,000. + */ + +ngx_tid_t +ngx_thread_tid(void) +{ + uint64_t tid; + + (void) pthread_threadid_np(NULL, &tid); + return tid; +} + +/* + * 2) Kernel thread mach_port_t returned by pthread_mach_thread_np(). + * It is a number in range 100-100,000. + * + * return pthread_mach_thread_np(pthread_self()); + */ + +#else + +ngx_tid_t +ngx_thread_tid(void) +{ + return (uint64_t) (uintptr_t) pthread_self(); +} + +#endif diff --git a/hm_nginx/src/os/unix/ngx_thread_mutex.c b/hm_nginx/src/os/unix/ngx_thread_mutex.c new file mode 100644 index 0000000..6e8385e --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_thread_mutex.c @@ -0,0 +1,174 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + +#include +#include + + +/* + * All modern pthread mutex implementations try to acquire a lock + * atomically in userland before going to sleep in kernel. Some + * spins before the sleeping. + * + * In Solaris since version 8 all mutex types spin before sleeping. + * The default spin count is 1000. It can be overridden using + * _THREAD_ADAPTIVE_SPIN=100 environment variable. + * + * In MacOSX all mutex types spin to acquire a lock protecting a mutex's + * internals. If the mutex is busy, thread calls Mach semaphore_wait(). + * + * + * PTHREAD_MUTEX_NORMAL lacks deadlock detection and is the fastest + * mutex type. + * + * Linux: No spinning. The internal name PTHREAD_MUTEX_TIMED_NP + * remains from the times when pthread_mutex_timedlock() was + * non-standard extension. Alias name: PTHREAD_MUTEX_FAST_NP. + * FreeBSD: No spinning. + * + * + * PTHREAD_MUTEX_ERRORCHECK is usually as fast as PTHREAD_MUTEX_NORMAL + * yet has lightweight deadlock detection. + * + * Linux: No spinning. The internal name: PTHREAD_MUTEX_ERRORCHECK_NP. + * FreeBSD: No spinning. + * + * + * PTHREAD_MUTEX_RECURSIVE allows recursive locking. + * + * Linux: No spinning. The internal name: PTHREAD_MUTEX_RECURSIVE_NP. + * FreeBSD: No spinning. + * + * + * PTHREAD_MUTEX_ADAPTIVE_NP spins on SMP systems before sleeping. + * + * Linux: No deadlock detection. Dynamically changes a spin count + * for each mutex from 10 to 100 based on spin count taken + * previously. + * FreeBSD: Deadlock detection. The default spin count is 2000. + * It can be overriden using LIBPTHREAD_SPINLOOPS environment + * variable or by pthread_mutex_setspinloops_np(). If a lock + * is still busy, sched_yield() can be called on both UP and + * SMP systems. The default yield loop count is zero, but + * it can be set by LIBPTHREAD_YIELDLOOPS environment + * variable or by pthread_mutex_setyieldloops_np(). + * Solaris: No PTHREAD_MUTEX_ADAPTIVE_NP. + * MacOSX: No PTHREAD_MUTEX_ADAPTIVE_NP. + * + * + * PTHREAD_MUTEX_ELISION_NP is a Linux extension to elide locks using + * Intel Restricted Transactional Memory. It is the most suitable for + * rwlock pattern access because it allows simultaneous reads without lock. + * Supported since glibc 2.18. + * + * + * PTHREAD_MUTEX_DEFAULT is default mutex type. + * + * Linux: PTHREAD_MUTEX_NORMAL. + * FreeBSD: PTHREAD_MUTEX_ERRORCHECK. + * Solaris: PTHREAD_MUTEX_NORMAL. + * MacOSX: PTHREAD_MUTEX_NORMAL. + */ + + +ngx_int_t +ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log) +{ + ngx_err_t err; + pthread_mutexattr_t attr; + + err = pthread_mutexattr_init(&attr); + if (err != 0) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "pthread_mutexattr_init() failed"); + return NGX_ERROR; + } + + err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + if (err != 0) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "pthread_mutexattr_settype" + "(PTHREAD_MUTEX_ERRORCHECK) failed"); + return NGX_ERROR; + } + + err = pthread_mutex_init(mtx, &attr); + if (err != 0) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "pthread_mutex_init() failed"); + return NGX_ERROR; + } + + err = pthread_mutexattr_destroy(&attr); + if (err != 0) { + ngx_log_error(NGX_LOG_ALERT, log, err, + "pthread_mutexattr_destroy() failed"); + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_mutex_init(%p)", mtx); + return NGX_OK; +} + + +ngx_int_t +ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log) +{ + ngx_err_t err; + + err = pthread_mutex_destroy(mtx); + if (err != 0) { + ngx_log_error(NGX_LOG_ALERT, log, err, + "pthread_mutex_destroy() failed"); + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_mutex_destroy(%p)", mtx); + return NGX_OK; +} + + +ngx_int_t +ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log) +{ + ngx_err_t err; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_mutex_lock(%p) enter", mtx); + + err = pthread_mutex_lock(mtx); + if (err == 0) { + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_mutex_lock() failed"); + + return NGX_ERROR; +} + + +ngx_int_t +ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log) +{ + ngx_err_t err; + + err = pthread_mutex_unlock(mtx); + +#if 0 + ngx_time_update(); +#endif + + if (err == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "pthread_mutex_unlock(%p) exit", mtx); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_mutex_unlock() failed"); + + return NGX_ERROR; +} diff --git a/hm_nginx/src/os/unix/ngx_time.c b/hm_nginx/src/os/unix/ngx_time.c new file mode 100644 index 0000000..cc760b2 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_time.c @@ -0,0 +1,104 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +/* + * FreeBSD does not test /etc/localtime change, however, we can workaround it + * by calling tzset() with TZ and then without TZ to update timezone. + * The trick should work since FreeBSD 2.1.0. + * + * Linux does not test /etc/localtime change in localtime(), + * but may stat("/etc/localtime") several times in every strftime(), + * therefore we use it to update timezone. + * + * Solaris does not test /etc/TIMEZONE change too and no workaround available. + */ + +void +ngx_timezone_update(void) +{ +#if (NGX_FREEBSD) + + if (getenv("TZ")) { + return; + } + + putenv("TZ=UTC"); + + tzset(); + + unsetenv("TZ"); + + tzset(); + +#elif (NGX_LINUX) + time_t s; + struct tm *t; + char buf[4]; + + s = time(0); + + t = localtime(&s); + + strftime(buf, 4, "%H", t); + +#endif +} + + +void +ngx_localtime(time_t s, ngx_tm_t *tm) +{ +#if (NGX_HAVE_LOCALTIME_R) + (void) localtime_r(&s, tm); + +#else + ngx_tm_t *t; + + t = localtime(&s); + *tm = *t; + +#endif + + tm->ngx_tm_mon++; + tm->ngx_tm_year += 1900; +} + + +void +ngx_libc_localtime(time_t s, struct tm *tm) +{ +#if (NGX_HAVE_LOCALTIME_R) + (void) localtime_r(&s, tm); + +#else + struct tm *t; + + t = localtime(&s); + *tm = *t; + +#endif +} + + +void +ngx_libc_gmtime(time_t s, struct tm *tm) +{ +#if (NGX_HAVE_LOCALTIME_R) + (void) gmtime_r(&s, tm); + +#else + struct tm *t; + + t = gmtime(&s); + *tm = *t; + +#endif +} diff --git a/hm_nginx/src/os/unix/ngx_time.h b/hm_nginx/src/os/unix/ngx_time.h new file mode 100644 index 0000000..c128c9a --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_time.h @@ -0,0 +1,66 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_TIME_H_INCLUDED_ +#define _NGX_TIME_H_INCLUDED_ + + +#include +#include + + +typedef ngx_rbtree_key_t ngx_msec_t; +typedef ngx_rbtree_key_int_t ngx_msec_int_t; + +typedef struct tm ngx_tm_t; + +#define ngx_tm_sec tm_sec +#define ngx_tm_min tm_min +#define ngx_tm_hour tm_hour +#define ngx_tm_mday tm_mday +#define ngx_tm_mon tm_mon +#define ngx_tm_year tm_year +#define ngx_tm_wday tm_wday +#define ngx_tm_isdst tm_isdst + +#define ngx_tm_sec_t int +#define ngx_tm_min_t int +#define ngx_tm_hour_t int +#define ngx_tm_mday_t int +#define ngx_tm_mon_t int +#define ngx_tm_year_t int +#define ngx_tm_wday_t int + + +#if (NGX_HAVE_GMTOFF) +#define ngx_tm_gmtoff tm_gmtoff +#define ngx_tm_zone tm_zone +#endif + + +#if (NGX_SOLARIS) + +#define ngx_timezone(isdst) (- (isdst ? altzone : timezone) / 60) + +#else + +#define ngx_timezone(isdst) (- (isdst ? timezone + 3600 : timezone) / 60) + +#endif + + +void ngx_timezone_update(void); +void ngx_localtime(time_t s, ngx_tm_t *tm); +void ngx_libc_localtime(time_t s, struct tm *tm); +void ngx_libc_gmtime(time_t s, struct tm *tm); + +#define ngx_gettimeofday(tp) (void) gettimeofday(tp, NULL); +#define ngx_msleep(ms) (void) usleep(ms * 1000) +#define ngx_sleep(s) (void) sleep(s) + + +#endif /* _NGX_TIME_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_udp_recv.c b/hm_nginx/src/os/unix/ngx_udp_recv.c new file mode 100644 index 0000000..1c807a0 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_udp_recv.c @@ -0,0 +1,115 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#if (NGX_HAVE_KQUEUE) + +ssize_t +ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) +{ + ssize_t n; + ngx_err_t err; + ngx_event_t *rev; + + rev = c->read; + + do { + n = recv(c->fd, buf, size, 0); + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: fd:%d %d of %d", c->fd, n, size); + + if (n >= 0) { + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available -= n; + + /* + * rev->available may be negative here because some additional + * bytes may be received between kevent() and recv() + */ + + if (rev->available <= 0) { + rev->ready = 0; + rev->available = 0; + } + } + + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "recv() not ready"); + n = NGX_AGAIN; + + } else { + n = ngx_connection_error(c, err, "recv() failed"); + break; + } + + } while (err == NGX_EINTR); + + rev->ready = 0; + + if (n == NGX_ERROR) { + rev->error = 1; + } + + return n; +} + +#else /* ! NGX_HAVE_KQUEUE */ + +ssize_t +ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) +{ + ssize_t n; + ngx_err_t err; + ngx_event_t *rev; + + rev = c->read; + + do { + n = recv(c->fd, buf, size, 0); + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: fd:%d %d of %d", c->fd, n, size); + + if (n >= 0) { + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "recv() not ready"); + n = NGX_AGAIN; + + } else { + n = ngx_connection_error(c, err, "recv() failed"); + break; + } + + } while (err == NGX_EINTR); + + rev->ready = 0; + + if (n == NGX_ERROR) { + rev->error = 1; + } + + return n; +} + +#endif /* NGX_HAVE_KQUEUE */ diff --git a/hm_nginx/src/os/unix/ngx_user.c b/hm_nginx/src/os/unix/ngx_user.c new file mode 100644 index 0000000..27c76ef --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_user.c @@ -0,0 +1,90 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +/* + * Solaris has thread-safe crypt() + * Linux has crypt_r(); "struct crypt_data" is more than 128K + * FreeBSD needs the mutex to protect crypt() + * + * TODO: + * ngx_crypt_init() to init mutex + */ + + +#if (NGX_CRYPT) + +#if (NGX_HAVE_GNU_CRYPT_R) + +ngx_int_t +ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) +{ + char *value; + size_t len; + struct crypt_data cd; + + cd.initialized = 0; +#ifdef __GLIBC__ + /* work around the glibc bug */ + cd.current_salt[0] = ~salt[0]; +#endif + + value = crypt_r((char *) key, (char *) salt, &cd); + + if (value) { + len = ngx_strlen(value) + 1; + + *encrypted = ngx_pnalloc(pool, len); + if (*encrypted == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(*encrypted, value, len); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_CRIT, pool->log, ngx_errno, "crypt_r() failed"); + + return NGX_ERROR; +} + +#else + +ngx_int_t +ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) +{ + char *value; + size_t len; + ngx_err_t err; + + value = crypt((char *) key, (char *) salt); + + if (value) { + len = ngx_strlen(value) + 1; + + *encrypted = ngx_pnalloc(pool, len); + if (*encrypted == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(*encrypted, value, len); + return NGX_OK; + } + + err = ngx_errno; + + ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt() failed"); + + return NGX_ERROR; +} + +#endif + +#endif /* NGX_CRYPT */ diff --git a/hm_nginx/src/os/unix/ngx_user.h b/hm_nginx/src/os/unix/ngx_user.h new file mode 100644 index 0000000..6e82204 --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_user.h @@ -0,0 +1,24 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_USER_H_INCLUDED_ +#define _NGX_USER_H_INCLUDED_ + + +#include +#include + + +typedef uid_t ngx_uid_t; +typedef gid_t ngx_gid_t; + + +ngx_int_t ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, + u_char **encrypted); + + +#endif /* _NGX_USER_H_INCLUDED_ */ diff --git a/hm_nginx/src/os/unix/ngx_writev_chain.c b/hm_nginx/src/os/unix/ngx_writev_chain.c new file mode 100644 index 0000000..e38a3aa --- /dev/null +++ b/hm_nginx/src/os/unix/ngx_writev_chain.c @@ -0,0 +1,216 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ngx_chain_t * +ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) +{ + ssize_t n, sent; + off_t send, prev_send; + ngx_chain_t *cl; + ngx_event_t *wev; + ngx_iovec_t vec; + struct iovec iovs[NGX_IOVS_PREALLOCATE]; + + wev = c->write; + + if (!wev->ready) { + return in; + } + +#if (NGX_HAVE_KQUEUE) + + if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); + wev->error = 1; + return NGX_CHAIN_ERROR; + } + +#endif + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { + limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; + + vec.iovs = iovs; + vec.nalloc = NGX_IOVS_PREALLOCATE; + + for ( ;; ) { + prev_send = send; + + /* create the iovec and coalesce the neighbouring bufs */ + + cl = ngx_output_chain_to_iovec(&vec, in, limit - send, c->log); + + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + if (cl && cl->buf->in_file) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "file buf in writev " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + + return NGX_CHAIN_ERROR; + } + + send += vec.size; + + n = ngx_writev(c, &vec); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + sent = (n == NGX_AGAIN) ? 0 : n; + + c->sent += sent; + + in = ngx_chain_update_sent(in, sent); + + if (send - prev_send != sent) { + wev->ready = 0; + return in; + } + + if (send >= limit || in == NULL) { + return in; + } + } +} + + +ngx_chain_t * +ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, size_t limit, + ngx_log_t *log) +{ + size_t total, size; + u_char *prev; + ngx_uint_t n; + struct iovec *iov; + + iov = NULL; + prev = NULL; + total = 0; + n = 0; + + for ( /* void */ ; in && total < limit; in = in->next) { + + if (ngx_buf_special(in->buf)) { + continue; + } + + if (in->buf->in_file) { + break; + } + + if (!ngx_buf_in_memory(in->buf)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "bad buf in output chain " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + in->buf->temporary, + in->buf->recycled, + in->buf->in_file, + in->buf->start, + in->buf->pos, + in->buf->last, + in->buf->file, + in->buf->file_pos, + in->buf->file_last); + + ngx_debug_point(); + + return NGX_CHAIN_ERROR; + } + + size = in->buf->last - in->buf->pos; + + if (size > limit - total) { + size = limit - total; + } + + if (prev == in->buf->pos) { + iov->iov_len += size; + + } else { + if (n == vec->nalloc) { + break; + } + + iov = &vec->iovs[n++]; + + iov->iov_base = (void *) in->buf->pos; + iov->iov_len = size; + } + + prev = in->buf->pos + size; + total += size; + } + + vec->count = n; + vec->size = total; + + return in; +} + + +ssize_t +ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec) +{ + ssize_t n; + ngx_err_t err; + +eintr: + + n = writev(c->fd, vec->iovs, vec->count); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "writev: %z of %uz", n, vec->size); + + if (n == -1) { + err = ngx_errno; + + switch (err) { + case NGX_EAGAIN: + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "writev() not ready"); + return NGX_AGAIN; + + case NGX_EINTR: + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "writev() was interrupted"); + goto eintr; + + default: + c->write->error = 1; + ngx_connection_error(c, err, "writev() failed"); + return NGX_ERROR; + } + } + + return n; +} diff --git a/hm_proto/LICENSE b/hm_proto/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/hm_proto/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/hm_proto/Makefile b/hm_proto/Makefile new file mode 100644 index 0000000..8c9c1a2 --- /dev/null +++ b/hm_proto/Makefile @@ -0,0 +1,45 @@ +INCS= -Isrc/include -I../hm_base/src/include +LIBS_PATH= -L../hm_base/lib/ +LIBS= -lhmbase +CFLAGS+= -g + +compile = $(CC) -c $(CFLAGS) $(INCS) $(LIBS_PATH) src/$(1).c -o src/$(1).o $(LIBS) + +static: hmproto + +hmproto: + rm -rf lib/ + $(call compile,alloptions) + $(call compile,bnet) + $(call compile,chooseentities) + $(call compile,chooseoption) + $(call compile,creategame) + $(call compile,packet) + $(call compile,entity) + $(call compile,entitychoices) + $(call compile,game_entity) + $(call compile,gamesetup) + $(call compile,handshake) + $(call compile,hide) + $(call compile,meta) + $(call compile,mouseinfo) + $(call compile,option) + $(call compile,platform) + $(call compile,player) + $(call compile,powerend) + $(call compile,powerhistory) + $(call compile,powerhistorydata) + $(call compile,powerstart) + $(call compile,proto) + $(call compile,suboption) + $(call compile,tag) + $(call compile,tagchange) + $(call compile,turntimer) + $(call compile,userui) + mkdir -p lib/ + ar cq lib/libhmproto.a src/*.o + +clean: + rm -rf src/*.o ./lib/ + +.PHONY: static hmproto diff --git a/hm_proto/README.md b/hm_proto/README.md new file mode 100644 index 0000000..2a773fa --- /dev/null +++ b/hm_proto/README.md @@ -0,0 +1,2 @@ +# hm_proto +hearthmod proto diff --git a/hm_proto/src/alloptions.c b/hm_proto/src/alloptions.c new file mode 100644 index 0000000..bef5485 --- /dev/null +++ b/hm_proto/src/alloptions.c @@ -0,0 +1,87 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void alloptions_free(struct alloptions_s *a) +{ + struct option_s *o, *del; + + for(o = a->options; o != NULL; del = o, o = o->next, option_free(del)); + + free(a); +} + +int alloptions_serialize(void *ao, char **dst, const char *maxdst) +{ + int n = 0; + struct option_s *m; + struct alloptions_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->id); + + for(m = s->options; m != NULL; m = m->next) { + write_byte(dst, maxdst, 18); + n = option_size(m); + write_uint(dst, maxdst, n); + option_serialize(m, dst, maxdst); + } + + return (*dst - start); +} + +int alloptions_size(struct alloptions_s *p) +{ + int num = 0, n; + struct option_s *s; + + num += 1; + num += sizeofu64(p->id); + + for(s = p->options; s != NULL; s = s->next) { + num += 1; + n = option_size(s); + num += sizeofu32(n) + n; + } + + return num; +} + +void alloptions_dump(struct alloptions_s *a) +{ + struct suboption_target_s *t; + struct suboption_s *m; + struct option_s *o; + + hm_log(LOG_DEBUG, lg, "Dumping alloptions:"); + hm_log(LOG_DEBUG, lg, "id: %lld", a->id); + for(o = a->options; o != NULL; o = o->next) { + hm_log(LOG_DEBUG, lg, "\tOption type: %lld", o->type); + for(m = o->mainoption; m != NULL; m = m->next) { + hm_log(LOG_DEBUG, lg, "\t\tMainoption id: %lld", m->id); + for(t = m->target; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\t\tTarget id: %lld", t->value); + } + } + assert(o->suboptions == NULL); + } +} diff --git a/hm_proto/src/bnet.c b/hm_proto/src/bnet.c new file mode 100644 index 0000000..21010d5 --- /dev/null +++ b/hm_proto/src/bnet.c @@ -0,0 +1,31 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int bnet_size(struct powerhistory_player_s *player) +{ + int size = 0; + + if(player) { + size += 2; + size += sizeofu64(player->bnet_hi); + size += sizeofu64(player->bnet_lo); + } + + return size; +} diff --git a/hm_proto/src/chooseentities.c b/hm_proto/src/chooseentities.c new file mode 100644 index 0000000..08a209e --- /dev/null +++ b/hm_proto/src/chooseentities.c @@ -0,0 +1,87 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void chooseentities_free(struct chooseentities_s *c) +{ + struct chooseentities_ent_s *e, *del; + + for(e = c->entity; e != NULL; del = e, e = e->next, free(del)); + + free(c); +} + +int chooseentities_serialize(void *ao, char **dst, const char *maxdst) +{ + struct chooseentities_s *s; + struct chooseentities_ent_s *e; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->id); + + write_byte(dst, maxdst, 18); + write_uint64(dst, maxdst, s->nentity); + + for(e = s->entity; e != NULL; e = e->next) { + write_uint(dst, maxdst, e->entity); + } + + return (*dst - start); +} + +void *chooseentities_deserialize(char **dst, const char *maxdst) +{ + int n, i; + struct chooseentities_s *c; + struct chooseentities_ent_s *e; + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + + c->id = read_uint64(dst, maxdst); + c->entity = NULL; + + n = read_byte(dst, maxdst); + if(n != 18) { + return c; + } + + c->nentity = read_uint(dst, maxdst); + if(c->nentity > 5 || c->nentity < 0) { + free(c); + return NULL; + } + + for(i = 0; i < c->nentity && *dst < maxdst; i++) { + e = malloc(sizeof(*e)); + e->entity = read_uint(dst, maxdst); + e->next = c->entity; + c->entity = e; + } + + return c; +} diff --git a/hm_proto/src/chooseoption.c b/hm_proto/src/chooseoption.c new file mode 100644 index 0000000..4c3c805 --- /dev/null +++ b/hm_proto/src/chooseoption.c @@ -0,0 +1,99 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void chooseoption_free(struct chooseoption_s *c) +{ + free(c); +} + +int chooseoption_serialize(void *ao, char **dst, const char *maxdst) +{ + struct chooseoption_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->id); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->index); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, s->target); + + if(s->suboption != 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, s->suboption); + } + + if(s->position != 0) { + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, s->position); + } + + return (*dst - start); +} + +void *chooseoption_deserialize(char **dst, const char *maxdst) +{ + int n; + struct chooseoption_s *o; + + o = malloc(sizeof(*o)); + memset(o, 0, sizeof(*o)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + o->id = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + o->index = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + o->target = read_uint64(dst, maxdst); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 32) { + o->suboption = read_uint64(dst, maxdst); + } else if(n == 40) { + o->position = read_uint64(dst, maxdst); + } else { + error(); + } + } + + return o; +} + +void chooseoption_dump(struct chooseoption_s *o, u64 local_held_card) +{ + hm_log(LOG_DEBUG, lg, "Choose options dump: option id: %lld index: %lld target: %lld suboption: %lld position: %lld local held card: %lld", o->id, o->index, o->target, o->suboption, o->position, local_held_card); + +} diff --git a/hm_proto/src/creategame.c b/hm_proto/src/creategame.c new file mode 100644 index 0000000..2abf48a --- /dev/null +++ b/hm_proto/src/creategame.c @@ -0,0 +1,109 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void creategame_free(struct powerhistory_creategame_s *c) +{ + struct powerhistory_player_s *player, *del; + + for(player = c->player; player != NULL; del = player, player = player->next, player_free(del)); + + free(c); +} + +struct powerhistory_creategame_s *creategame_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_creategame_s *t; + struct powerhistory_player_s *player; + + t = malloc(sizeof(*t)); + t->player = t->player_tail = NULL; + + n = read_byte(dst, maxdst); + + if(n != 10) { + error(); + } + len = read_uint(dst, maxdst); + + t->game_entity = game_entity_deserialize(dst, *dst + len); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + + len = read_uint(dst, maxdst); + + player = player_deserialize(dst, *dst + len); + player->next = NULL; + + if(t->player == NULL && t->player_tail == NULL) { + t->player = player; + t->player_tail = player; + } else { + t->player_tail->next = player; + t->player_tail = player; + } + } + + return t; +} + +int creategame_size(struct powerhistory_creategame_s *cg) +{ + struct powerhistory_player_s *p; + int num = 0; + int n; + + if(cg) { + num += 1; + n = game_entity_size(cg->game_entity); + num += sizeofu32(n) + n; + + for(p = cg->player; p != NULL; p = p->next) { + num += 1; + n = player_size(p); + num += sizeofu32(n) + n; + } + } + + return num; +} + +int creategame_serialize(struct powerhistory_creategame_s *cg, char **dst, const char *maxdst) +{ + int n; + struct powerhistory_player_s *p; + + write_byte(dst, maxdst, 10); + n = game_entity_size(cg->game_entity); + write_uint(dst, maxdst, n); + game_entity_serialize(cg->game_entity, dst, maxdst); + + for(p = cg->player; p != NULL; p = p->next) { + write_byte(dst, maxdst, 18); + n = player_size(p); + write_uint(dst, maxdst, n); + player_serialize(p, dst, maxdst); + } + + return 0; +} diff --git a/hm_proto/src/entity.c b/hm_proto/src/entity.c new file mode 100644 index 0000000..4ae9d3d --- /dev/null +++ b/hm_proto/src/entity.c @@ -0,0 +1,119 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void entity_free(struct powerhistory_entity_s *e) +{ + struct powerhistory_tag_s *tag, *del; + + for(tag = e->tag; tag != NULL; del = tag, tag = tag->next, tag_free(del)); + + //free(e->name); + + free(e); +} + +struct powerhistory_entity_s *entity_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_entity_s *p; + struct powerhistory_tag_s *t; + + p = malloc(sizeof(*p)); + + p->tag = p->tag_tail = NULL; + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + + p->entity = read_uint64(dst, maxdst); + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + + p->name = read_bytes(dst, maxdst, &p->nname); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + len = read_uint(dst, maxdst); + + if(n == 26) { + t = tag_deserialize(dst, *dst + len); + t->next = NULL; + + if(p->tag == NULL && p->tag_tail == NULL) { + p->tag = t; + p->tag_tail = t; + } else { + p->tag_tail->next = t; + p->tag_tail = t; + } + } else { + error(); + return NULL; + } + } + + return p; +} + + +int entity_size(struct powerhistory_entity_s *ent) +{ + int num = 0; + int ts; + struct powerhistory_tag_s *tag; + + num += 2; + num += sizeofu64(ent->entity); + num += sizeofu32(ent->nname) + ent->nname; + + for(tag = ent->tag; tag != NULL; tag = tag->next) { + num += 1; + ts = tag_size(tag); + num += sizeofu32(ts) + ts; + } + + return num; +} + +int entity_serialize(struct powerhistory_entity_s *ent, char **dst, const char *maxdst) +{ + int ts; + struct powerhistory_tag_s *t; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->entity); + + write_byte(dst, maxdst, 18); + write_bytes(dst, maxdst, ent->name, ent->nname); + + if(ent->tag) { + for(t = ent->tag; t != NULL; t = t->next) { + write_byte(dst, maxdst, 26); + ts = tag_size(t); + write_uint(dst, maxdst, ts); + tag_serialize(t, dst, maxdst); + } + } + + return 0; +} diff --git a/hm_proto/src/entitychoices.c b/hm_proto/src/entitychoices.c new file mode 100644 index 0000000..b200eec --- /dev/null +++ b/hm_proto/src/entitychoices.c @@ -0,0 +1,144 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void entitychoices_free(struct entitychoices_s *ec) +{ + struct entitychoices_entities_s *e, *del; + + for(e = ec->entities; e != NULL; del = e, e = e->next, free(del)); + + free(ec); +} + +void *entitychoices_deserialize(char **dst, const char *maxdst) +{ + int n, i; + struct entitychoices_s *o; + struct entitychoices_entities_s *e = e; + + o = malloc(sizeof(*o)); + memset(o, 0, sizeof(*o)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + o->id = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + o->type = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 32) { + error(); + } + o->countmin = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 40) { + error(); + } + o->countmax = read_uint64(dst, maxdst); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 50) { + int n = read_uint(dst, maxdst); + for(i = 0; i < n; i++) { + e = malloc(sizeof(*e)); + e->entity = read_uint64(dst, maxdst); + e->next = o->entities; + o->entities = e; + } + } else if(n == 56) { + o->source = read_uint64(dst, maxdst); + } else if(n == 64) { + o->player_id = read_uint64(dst, maxdst); + } else { + error(); + } + } + + return o; +} + +int entitychoices_serialize(void *ep, char **dst, const char *maxdst) +{ + int n = 0; + struct entitychoices_entities_s *es; + struct entitychoices_s *e = ep; + char *start; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, e->id); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, e->type); + + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, e->countmin); + + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, e->countmax); + + if(e->entities) { + write_byte(dst, maxdst, 50); + for(es = e->entities; es != NULL; es = es->next) { + n += sizeofu64(es->entity); + } + + write_uint(dst, maxdst, n); + + for(es = e->entities; es != NULL; es = es->next) { + write_uint64(dst, maxdst, es->entity); + } + } + + if(e->source > 0) { + write_byte(dst, maxdst, 56); + write_uint64(dst, maxdst, e->source); + } + + write_byte(dst, maxdst, 64); + write_uint64(dst, maxdst, e->player_id); + + return (*dst - start); +} + +void entitychoices_dump(struct entitychoices_s *es) +{ + struct entitychoices_entities_s *ent; + + hm_log(LOG_DEBUG, lg, "Entity Choices dump:"); + hm_log(LOG_DEBUG, lg, "\t\tID: %lld", es->id); + hm_log(LOG_DEBUG, lg, "\t\tType: %lld", es->type); + hm_log(LOG_DEBUG, lg, "\t\tCountMin: %lld", es->countmin); + hm_log(LOG_DEBUG, lg, "\t\tCountMax: %lld", es->countmax); + hm_log(LOG_DEBUG, lg, "\t\tSource: %lld", es->source); + hm_log(LOG_DEBUG, lg, "\t\tPlayer: %lld", es->player_id); + + for(ent = es->entities; ent != NULL; ent = ent->next) { + hm_log(LOG_DEBUG, lg, "\t\t\tChild entity: %lld", ent->entity); + } +} diff --git a/hm_proto/src/game_entity.c b/hm_proto/src/game_entity.c new file mode 100644 index 0000000..3b332d1 --- /dev/null +++ b/hm_proto/src/game_entity.c @@ -0,0 +1,105 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void game_entity_free(struct powerhistory_game_entity_s *g) +{ + struct powerhistory_tag_s *tag, *del; + + for(tag = g->tag; tag != NULL; del = tag, tag = tag->next, tag_free(del)); + + free(g); +} + +struct powerhistory_game_entity_s *game_entity_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_game_entity_s *t; + struct powerhistory_tag_s *tag; + + t = malloc(sizeof(*t)); + memset(t, 0, sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + + t->id = read_uint64(dst, maxdst); + + while(*dst < maxdst) { + + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + + len = read_uint(dst, maxdst); + + tag = tag_deserialize(dst, *dst + len); + tag->next = NULL; + + if(t->tag == NULL && t->tag_tail == NULL) { + t->tag = tag; + t->tag_tail = tag; + } else { + t->tag_tail->next = tag; + t->tag_tail = tag; + } + } + + return t; +} + +int game_entity_serialize(struct powerhistory_game_entity_s *ent, char **dst, const char *maxdst) +{ + int ts; + struct powerhistory_tag_s *t; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->id); + + if(ent->tag) { + for(t = ent->tag; t != NULL; t = t->next) { + write_byte(dst, maxdst, 18); + ts = tag_size(t); + write_uint(dst, maxdst, ts); + tag_serialize(t, dst, maxdst); + } + } + + return 0; +} + +int game_entity_size(struct powerhistory_game_entity_s *ent) +{ + int ts; + struct powerhistory_tag_s *tag; + int num = 0; + + num += 1; + num += sizeofu64(ent->id); + + for(tag = ent->tag; tag != NULL; tag = tag->next) { + num += 1; + ts = tag_size(tag); + num += sizeofu32(ts) + ts; + } + + return num; +} diff --git a/hm_proto/src/gamesetup.c b/hm_proto/src/gamesetup.c new file mode 100644 index 0000000..f93c155 --- /dev/null +++ b/hm_proto/src/gamesetup.c @@ -0,0 +1,114 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void gamesetup_free(struct gamesetup_s *g) +{ + free(g); +} + +int gamesetup_serialize(void *data, char **dst, const char *maxdst) +{ + char *start; + struct gamesetup_s *g = data; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, g->board); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, g->maxsecrets); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, g->maxfriendlyminions); + + if(g->keepalive > 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, g->keepalive); + } + + if(g->stuckdisconnect > 0) { + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, g->stuckdisconnect); + } + + return (*dst - start); +} + +void *gamesetup_deserialize(char **dst, const char *maxdst) +{ + int n; + struct gamesetup_s *o; + + o = malloc(sizeof(*o)); + memset(o, 0, sizeof(*o)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + o->board = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + o->maxsecrets = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + o->maxfriendlyminions = read_uint64(dst, maxdst); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 32) { + o->keepalive = read_uint64(dst, maxdst); + } else if(n == 40) { + o->stuckdisconnect = read_uint64(dst, maxdst); + } else { + error(); + } + } + + return o; +} + +int gamesetup_size(struct gamesetup_s *g) +{ + int num = 0; + + num += 3; + num += sizeofu64(g->board); + num += sizeofu64(g->maxsecrets); + num += sizeofu64(g->maxfriendlyminions); + + if(g->keepalive > 0) { + num += 1; + num += sizeofu64(g->keepalive); + } + + if(g->stuckdisconnect > 0) { + num += 1; + num += sizeofu64(g->stuckdisconnect); + } + + return num; +} diff --git a/hm_proto/src/handshake.c b/hm_proto/src/handshake.c new file mode 100644 index 0000000..dceec7a --- /dev/null +++ b/hm_proto/src/handshake.c @@ -0,0 +1,115 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void handshake_free(struct handshake_s *h) +{ + platform_free(h->platform); + + free(h->version); + free(h->password); + + free(h); +} + +int handshake_serialize(void *ao, char **dst, const char *maxdst) +{ + struct handshake_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->gamehandle); + + write_byte(dst, maxdst, 18); + write_bytes(dst, maxdst, s->password, s->npassword); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, s->clienthandle); + + if(s->mission != 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, s->mission); + } + + write_byte(dst, maxdst, 42); + write_bytes(dst, maxdst, s->version, s->nversion); + + write_byte(dst, maxdst, 58); + write_uint(dst, maxdst, platform_size(s->platform)); + + platform_serialize(s->platform, dst, maxdst); + return (*dst - start); +} + +void *handshake_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct handshake_s *h; + + h = malloc(sizeof(*h)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + h->gamehandle = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + h->password = read_bytes(dst, maxdst, &h->npassword); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + h->clienthandle = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n == 32) { + h->mission = read_uint64(dst, maxdst); + n = read_byte(dst, maxdst); + } + + if(n != 42) { + error(); + } + h->version = read_bytes(dst, maxdst, &h->nversion); + + n = read_byte(dst, maxdst); + if(n != 58) { + error(); + } + len = read_uint(dst, maxdst); + h->platform = platform_deserialize(dst, *dst + len); + + return h; +} + +void handshake_dump(struct handshake_s *h) +{ + hm_log(LOG_DEBUG, lg, "Gamehandle: %lld password: [%.*s] clienthandle: %lld mission: %lld verion: [%.*s] ", h->gamehandle, h->npassword, h->password, h->clienthandle, h->mission, h->nversion, h->version); + if(h->platform) { + hm_log(LOG_DEBUG, lg, "Os: %lld screen: %lld name: [%.*s] store: %lld", h->platform->os, h->platform->screen, h->platform->nname, h->platform->name, h->platform->store); + + } +} diff --git a/hm_proto/src/hide.c b/hm_proto/src/hide.c new file mode 100644 index 0000000..d1bc19f --- /dev/null +++ b/hm_proto/src/hide.c @@ -0,0 +1,69 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void hide_free(struct powerhistory_hide_s *t) +{ + free(t); +} + +struct powerhistory_hide_s *hide_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_hide_s *t; + + t = malloc(sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + t->entity = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + t->zone = read_uint64(dst, maxdst); + + return t; +} + +int hide_serialize(struct powerhistory_hide_s *ent, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->entity); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, ent->zone); + + return 0; +} + +int hide_size(struct powerhistory_hide_s *hide) +{ + int size = 0; + + if(hide) { + size += 2; + size += sizeofu64(hide->entity); + size += sizeofu64(hide->zone); + } + + return size; +} diff --git a/hm_proto/src/include/chooseentities.h b/hm_proto/src/include/chooseentities.h new file mode 100644 index 0000000..588a9f3 --- /dev/null +++ b/hm_proto/src/include/chooseentities.h @@ -0,0 +1,36 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef CHOOSEENTITIES_H_ +#define CHOOSEENTITIES_H_ + +struct chooseentities_ent_s { + u64 entity; + struct chooseentities_ent_s *next; +}; + +struct chooseentities_s { + u64 id; + int nentity; + struct chooseentities_ent_s *entity; +}; + +void chooseentities_free(struct chooseentities_s *c); +void *chooseentities_deserialize(char **dst, const char *maxdst); +int chooseentities_serialize(void *ao, char **dst, const char *maxdst); + +#endif diff --git a/hm_proto/src/include/entitychoices.h b/hm_proto/src/include/entitychoices.h new file mode 100644 index 0000000..cf5cd51 --- /dev/null +++ b/hm_proto/src/include/entitychoices.h @@ -0,0 +1,43 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ENTITYCHOICES_H_ +#define ENTITYCHOICES_H_ + +struct entitychoices_entities_s { + u64 entity; + struct entitychoices_entities_s *next; +}; + +struct entitychoices_s { + u64 id; + u64 type; + u64 countmin; + u64 countmax; + + u64 source; + u64 player_id; + + struct entitychoices_entities_s *entities; +}; + +void entitychoices_free(struct entitychoices_s *ec); +int entitychoices_serialize(void *ep, char **dst, const char *maxdst); +void entitychoices_dump(struct entitychoices_s *es); +void *entitychoices_deserialize(char **dst, const char *maxdst); + +#endif diff --git a/hm_proto/src/include/gametag.h b/hm_proto/src/include/gametag.h new file mode 100644 index 0000000..03f47dc --- /dev/null +++ b/hm_proto/src/include/gametag.h @@ -0,0 +1,250 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef TAG_H_ +#define TAG_H_ + +enum gametag_e { + TAG_SCRIPT_DATA_NUM_1 = 2, + TAG_SCRIPT_DATA_NUM_2 = 3, + TAG_SCRIPT_DATA_ENT_1 = 4, + TAG_SCRIPT_DATA_ENT_2 = 5, + MISSION_EVENT = 6, + TIMEOUT = 7, + TURN_START = 8, + TURN_TIMER_SLUSH = 9, + PREMIUM = 12, + GOLD_REWARD_STATE = 13, + PLAYSTATE = 17, + LAST_AFFECTED_BY = 18, + STEP = 19, + TURN = 20, + FATIGUE = 22, + CURRENT_PLAYER = 23, + FIRST_PLAYER = 24, + RESOURCES_USED = 25, + RESOURCES = 26, + HERO_ENTITY = 27, + MAXHANDSIZE = 28, + STARTHANDSIZE = 29, + PLAYER_ID = 30, + TEAM_ID = 31, + TRIGGER_VISUAL = 32, + RECENTLY_ARRIVED = 33, + PROTECTING = 34, + PROTECTED = 35, + DEFENDING = 36, + PROPOSED_DEFENDER = 37, + ATTACKING = 38, + PROPOSED_ATTACKER = 39, + ATTACHED = 40, + EXHAUSTED = 43, + DAMAGE = 44, + HEALTH = 45, + ATK = 47, + COST = 48, + ZONE = 49, + CONTROLLER = 50, + OWNER = 51, + DEFINITION = 52, + ENTITY_ID = 53, + HISTORY_PROXY = 54, + COPY_DEATHRATTLE = 55, + ELITE = 114, + MAXRESOURCES = 176, + CARD_SET = 183, + CARDTEXT_INHAND = 184, + CARDNAME = 185, + CARD_ID = 186, + DURABILITY = 187, + SILENCED = 188, + WINDFURY = 189, + TAUNT = 190, + STEALTH = 191, + SPELLPOWER = 192, + DIVINE_SHIELD = 194, + CHARGE = 197, + NEXT_STEP = 198, + CLASS = 199, + CARDRACE = 200, + FACTION = 201, + CARDTYPE = 202, + RARITY = 203, + STATE = 204, + SUMMONED = 205, + FREEZE = 208, + ENRAGED = 212, + OVERLOAD = 215, + LOYALTY = 216, + DEATHRATTLE = 217, + BATTLECRY = 218, + SECRET = 219, + COMBO = 220, + CANT_HEAL = 221, + CANT_DAMAGE = 222, + CANT_SET_ASIDE = 223, + CANT_REMOVE_FROM_GAME = 224, + CANT_READY = 225, + CANT_EXHAUST = 226, + CANT_ATTACK = 227, + CANT_TARGET = 228, + CANT_DESTROY = 229, + CANT_DISCARD = 230, + CANT_PLAY = 231, + CANT_DRAW = 232, + INCOMING_HEALING_MULTIPLIER = 233, + INCOMING_HEALING_ADJUSTMENT = 234, + INCOMING_HEALING_CAP = 235, + INCOMING_DAMAGE_MULTIPLIER = 236, + INCOMING_DAMAGE_ADJUSTMENT = 237, + INCOMING_DAMAGE_CAP = 238, + CANT_BE_HEALED = 239, + CANT_BE_DAMAGED = 240, + CANT_BE_SET_ASIDE = 241, + CANT_BE_REMOVED_FROM_GAME = 242, + CANT_BE_READIED = 243, + CANT_BE_EXHAUSTED = 244, + CANT_BE_ATTACKED = 245, + CANT_BE_TARGETED = 246, + CANT_BE_DESTROYED = 247, + CANT_BE_SUMMONING_SICK = 253, + FROZEN = 260, + JUST_PLAYED = 261, + LINKEDCARD = 262, + ZONE_POSITION = 263, + CANT_BE_FROZEN = 264, + COMBO_ACTIVE = 266, + CARD_TARGET = 267, + NUM_CARDS_PLAYED_THIS_TURN = 269, + CANT_BE_TARGETED_BY_OPPONENTS = 270, + NUM_TURNS_IN_PLAY = 271, + NUM_TURNS_LEFT = 272, + OUTGOING_DAMAGE_CAP = 273, + OUTGOING_DAMAGE_ADJUSTMENT = 274, + OUTGOING_DAMAGE_MULTIPLIER = 275, + OUTGOING_HEALING_CAP = 276, + OUTGOING_HEALING_ADJUSTMENT = 277, + OUTGOING_HEALING_MULTIPLIER = 278, + INCOMING_ABILITY_DAMAGE_ADJUSTMENT = 279, + INCOMING_COMBAT_DAMAGE_ADJUSTMENT = 280, + OUTGOING_ABILITY_DAMAGE_ADJUSTMENT = 281, + OUTGOING_COMBAT_DAMAGE_ADJUSTMENT = 282, + OUTGOING_ABILITY_DAMAGE_MULTIPLIER = 283, + OUTGOING_ABILITY_DAMAGE_CAP = 284, + INCOMING_ABILITY_DAMAGE_MULTIPLIER = 285, + INCOMING_ABILITY_DAMAGE_CAP = 286, + OUTGOING_COMBAT_DAMAGE_MULTIPLIER = 287, + OUTGOING_COMBAT_DAMAGE_CAP = 288, + INCOMING_COMBAT_DAMAGE_MULTIPLIER = 289, + INCOMING_COMBAT_DAMAGE_CAP = 290, + CURRENT_SPELLPOWER = 291, + ARMOR = 292, + MORPH = 293, + IS_MORPHED = 294, + TEMP_RESOURCES = 295, + OVERLOAD_OWED = 296, + NUM_ATTACKS_THIS_TURN = 297, + NEXT_ALLY_BUFF = 302, + MAGNET = 303, + FIRST_CARD_PLAYED_THIS_TURN = 304, + MULLIGAN_STATE = 305, + TAUNT_READY = 306, + STEALTH_READY = 307, + CHARGE_READY = 308, + CANT_BE_TARGETED_BY_ABILITIES = 311, + SHOULDEXITCOMBAT = 312, + CREATOR = 313, + CANT_BE_DISPELLED = 314, + PARENT_CARD = 316, + NUM_MINIONS_PLAYED_THIS_TURN = 317, + PREDAMAGE = 318, + TARGETING_ARROW_TEXT = 325, + ENCHANTMENT_BIRTH_VISUAL = 330, + ENCHANTMENT_IDLE_VISUAL = 331, + CANT_BE_TARGETED_BY_HERO_POWERS = 332, + HEALTH_MINIMUM = 337, + TAG_ONE_TURN_EFFECT = 338, + SILENCE = 339, + COUNTER = 340, + ARTISTNAME = 342, + HAND_REVEALED = 348, + ADJACENT_BUFF = 350, + FLAVORTEXT = 351, + FORCED_PLAY = 352, + LOW_HEALTH_THRESHOLD = 353, + SPELLPOWER_DOUBLE = 356, + HEALING_DOUBLE = 357, + NUM_OPTIONS_PLAYED_THIS_TURN = 358, + TO_BE_DESTROYED = 360, + AURA = 362, + POISONOUS = 363, + HOW_TO_EARN = 364, + HOW_TO_EARN_GOLDEN = 365, + HERO_POWER_DOUBLE = 366, + AI_MUST_PLAY = 367, + NUM_MINIONS_PLAYER_KILLED_THIS_TURN = 368, + NUM_MINIONS_KILLED_THIS_TURN = 369, + AFFECTED_BY_SPELL_POWER = 370, + EXTRA_DEATHRATTLES = 371, + START_WITH_1_HEALTH = 372, + IMMUNE_WHILE_ATTACKING = 373, + MULTIPLY_HERO_DAMAGE = 374, + MULTIPLY_BUFF_VALUE = 375, + CUSTOM_KEYWORD_EFFECT = 376, + TOPDECK = 377, + CANT_BE_TARGETED_BY_BATTLECRIES = 379, + SHOWN_HERO_POWER = 380, + DEATHRATTLE_RETURN_ZONE = 382, + STEADY_SHOT_CAN_TARGET = 383, + DISPLAYED_CREATOR = 385, + POWERED_UP = 386, + SPARE_PART = 388, + FORGETFUL = 389, + CAN_SUMMON_MAXPLUSONE_MINION = 390, + OBFUSCATED = 391, + BURNING = 392, + OVERLOAD_LOCKED = 393, + NUM_TIMES_HERO_POWER_USED_THIS_GAME = 394, + CURRENT_HEROPOWER_DAMAGE_BONUS = 395, + HEROPOWER_DAMAGE = 396, + LAST_CARD_PLAYED = 397, + NUM_FRIENDLY_MINIONS_THAT_DIED_THIS_TURN = 398, + NUM_CARDS_DRAWN_THIS_TURN = 399, + AI_ONE_SHOT_KILL = 400, + EVIL_GLOW = 401, + HIDE_COST = 402, + INSPIRE = 403, + RECEIVES_DOUBLE_SPELLDAMAGE_BONUS = 404, + HEROPOWER_ADDITIONAL_ACTIVATIONS = 405, + HEROPOWER_ACTIVATIONS_THIS_TURN = 406, + REVEALED = 410, + NUM_FRIENDLY_MINIONS_THAT_DIED_THIS_GAME = 412, + CANNOT_ATTACK_HEROES = 413, + LOCK_AND_LOAD = 414, + TREASURE = 415, + SHADOWFORM = 416, + NUM_FRIENDLY_MINIONS_THAT_ATTACKED_THIS_TURN = 417, + NUM_RESOURCES_SPENT_THIS_GAME = 418, + CHOOSE_BOTH = 419, + ELECTRIC_CHARGE_LEVEL = 420, + HEAVILY_ARMORED = 421, + DONT_SHOW_IMMUNE = 422, + HISTORY_PROXY_NO_BIG_CARD = 432, + TRANSFORMED_FROM_CARD = 435, +}; + +#endif diff --git a/hm_proto/src/include/misc.h b/hm_proto/src/include/misc.h new file mode 100644 index 0000000..ccc5f0d --- /dev/null +++ b/hm_proto/src/include/misc.h @@ -0,0 +1,75 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef MISC_H_ +#define MISC_H_ + +struct gamesetup_s { + u64 board; + u64 maxsecrets; + u64 maxfriendlyminions; + u64 keepalive; + u64 stuckdisconnect; +}; + +struct handshake_s { + u64 gamehandle; + char *password; + int npassword; + u64 clienthandle; + u64 mission; + char *version; + int nversion; + + struct platform_s *platform; +}; + +struct platform_s { + u64 os; + u64 screen; + int nname; + char *name; + u64 store; +}; + +struct chooseoption_s { + u64 id; + u64 index; + u64 target; + u64 suboption; + u64 position; +}; + +void gamesetup_free(struct gamesetup_s *g); +int gamesetup_serialize(void *data, char **dst, const char *maxdst); +void *gamesetup_deserialize(char **dst, const char *maxdst); + +void handshake_free(struct handshake_s *h); +void *handshake_deserialize(char **dst, const char *maxdst); +int handshake_serialize(void *ao, char **dst, const char *maxdst); + +void platform_free(struct platform_s *p); +struct platform_s *platform_deserialize(char **dst, const char *maxdst); +int platform_serialize(void *ao, char **dst, const char *maxdst); +int platform_size(struct platform_s *p); + +int chooseoption_serialize(void *ao, char **dst, const char *maxdst); +void chooseoption_free(struct chooseoption_s *c); +void *chooseoption_deserialize(char **dst, const char *maxdst); +void chooseoption_dump(struct chooseoption_s *o, u64 local_held_card); + +#endif diff --git a/hm_proto/src/include/mouseinfo.h b/hm_proto/src/include/mouseinfo.h new file mode 100644 index 0000000..195c799 --- /dev/null +++ b/hm_proto/src/include/mouseinfo.h @@ -0,0 +1,34 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef MOUSEINFO_H_ +#define MOUSEINFO_H_ + +struct mouseinfo_s { + u64 arroworigin; + u64 heldcard; + u64 overcard; + u64 x; + u64 y; +}; + +void mouseinfo_free(struct mouseinfo_s *p); +void *mouseinfo_deserialize(char **dst, const char *maxdst); +int mouseinfo_serialize(void *ao, char **dst, const char *maxdst); +int mouseinfo_size(struct mouseinfo_s *p); + +#endif diff --git a/hm_proto/src/include/options.h b/hm_proto/src/include/options.h new file mode 100644 index 0000000..33881b2 --- /dev/null +++ b/hm_proto/src/include/options.h @@ -0,0 +1,60 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef OPTIONS_H_ +#define OPTIONS_H_ + +struct suboption_target_s { + u64 value; + struct suboption_target_s *next; +}; + +struct suboption_s { + u64 id; + struct suboption_target_s *target; + + struct suboption_s *next; +}; + +struct option_s { + u64 type; + struct suboption_s *mainoption; + struct suboption_s *suboptions; + + struct option_s *next; +}; + +struct alloptions_s { + u64 id; + struct option_s *options; +}; + +void alloptions_free(struct alloptions_s *a); +int alloptions_serialize(void *s, char **dst, const char *maxdst); +int alloptions_size(struct alloptions_s *p); + +void option_free(struct option_s *p); +int option_serialize(struct option_s *s, char **dst, const char *maxdst); +int option_size(struct option_s *p); + +void suboption_free(struct suboption_s *p); +int suboption_serialize(struct suboption_s *s, char **dst, const char *maxdst); +int suboption_size(struct suboption_s *p); + +void alloptions_dump(struct alloptions_s *a); + +#endif diff --git a/hm_proto/src/include/packet.h b/hm_proto/src/include/packet.h new file mode 100644 index 0000000..632adc1 --- /dev/null +++ b/hm_proto/src/include/packet.h @@ -0,0 +1,69 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef PACKET_H_ +#define PACKET_H_ + +enum packet_e { + P_GETGAMESTATE = 0x01, + P_CHOOSEOPTION = 0x02, + P_CHOOSEENTITIES = 0x03, + P_TURNTIMER = 0x09, + P_ENTITIESCHOSEN = 0x0D, + P_ALLOPTIONS = 0x0E, + P_USERUI = 0x0F, + P_GAMESETUP = 0x10, + P_ENTITYCHOICES = 0x11, + P_POWERHISTORY = 0x13, + P_SPECTATORNOTIFY = 0x18, + P_PING = 0x73, + P_PONG = 0x74, + P_HANDSHAKE = 0xA8, +}; + +struct packet_s { + int id; + int len; + void *data; +}; + +struct packet_meta_s { + int id; + void *(*deserialize)(char **dst, const char *end); + int (*serialize)(void *p, char **dst, const char *end); + int (*free)(void *p); +}; + +#define parse_packet(m_p, m_buf, m_nbuf)\ + char *ptrd##m_buf = m_buf;\ + m_p = deserialize(&ptrd##m_buf, ptrd##m_buf + m_nbuf); + +#define build_packet(m_p, m_src, m_type, m_buffer)\ + char m_buffer[8192];\ + char *ptr##m_buffer;\ + int n##m_buffer = 0;\ + ptr##m_buffer = m_buffer;\ + add_packet(&m_p, m_src, m_type);\ + n##m_buffer = serialize(m_p, &ptr##m_buffer, ptr##m_buffer + sizeof(m_buffer)); + +void packet_free(struct packet_s *p); +struct packet_s *deserialize(char **dst, const char *maxdst); +int serialize(struct packet_s *p, char **dst, const char *maxdst); +struct packet_s *packet_init(enum packet_e id, void *data); +void add_packet(struct packet_s **dst, void *ph, enum packet_e n); + +#endif diff --git a/hm_proto/src/include/powerhistory.h b/hm_proto/src/include/powerhistory.h new file mode 100644 index 0000000..20154fc --- /dev/null +++ b/hm_proto/src/include/powerhistory.h @@ -0,0 +1,174 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef DEF_H_ +#define DEF_H_ + +struct powerhistory_tag_s { + u64 name; + u64 value; + + struct powerhistory_tag_s *next; +}; + +struct powerhistory_hide_s { + u64 entity; + u64 zone; +}; + +struct powerhistory_tagchange_s { + u64 entity; + u64 tag; + u64 value; +}; + +struct powerhistory_entity_s { + u64 entity; + char *name; + int nname; + + struct powerhistory_tag_s *tag, *tag_tail; +}; + +struct powerhistory_powerstart_s { + u64 type; + u64 index; + u64 source; + u64 target; + + int ncard_id; + char *card_id; +}; + +struct powerhistory_powerend_s { + int i; +}; + +struct powerhistory_game_entity_s { + u64 id; + struct powerhistory_tag_s *tag, *tag_tail; +}; + +struct powerhistory_s { + struct powerhistory_data_s *data, *data_tail; +}; + +struct powerhistory_info_s { + u64 id; + struct powerhistory_info_s *next; +}; + +struct powerhistory_meta_s { + u64 type; + u64 data; + struct powerhistory_info_s *info, *info_tail; +}; + +struct powerhistory_player_s { + u64 id; + u64 bnet_hi; + u64 bnet_lo; + u64 cardback; + struct powerhistory_game_entity_s *entity; + + struct powerhistory_player_s *next; +}; + +struct powerhistory_creategame_s { + struct powerhistory_game_entity_s *game_entity; + struct powerhistory_player_s *player, *player_tail; +}; + +struct powerhistory_data_s { + struct powerhistory_entity_s *full; + struct powerhistory_entity_s *show; + struct powerhistory_hide_s *hide; + struct powerhistory_tagchange_s *tagchange; + struct powerhistory_creategame_s *creategame; + struct powerhistory_powerstart_s *powerstart; + struct powerhistory_powerend_s *powerend; + struct powerhistory_entity_s *change_entity; + struct powerhistory_meta_s *meta; + + struct powerhistory_data_s *next, *tail; +}; + +void powerhistory_free(struct powerhistory_s *p); +void *powerhistory_deserialize(char **dst, const char *maxdst); +int powerhistory_serialize(void *data, char **dst, const char *maxdst); +int powerhistory_size(struct powerhistory_s *ph); + +struct powerhistory_data_s *powerhistory_data_deserialize(char **dst, const char *maxdst); +int powerhistorydata_serialize(struct powerhistory_data_s *ph, char **dst, const char *maxdst); +int powerhistorydata_size(struct powerhistory_data_s *ph); +void powerhistory_data_free(struct powerhistory_data_s *d); + +struct powerhistory_meta_s *meta_deserialize(char **dst, const char *maxdst); +int meta_serialize(struct powerhistory_meta_s *ph, char **dst, const char *maxdst); +int meta_size(struct powerhistory_meta_s *ph); +void meta_free(struct powerhistory_meta_s *t); + +struct powerhistory_powerend_s *powerend_deserialize(char **dst, const char *maxdst); +int powerend_serialize(struct powerhistory_powerend_s *ph, char **dst, const char *maxdst); +int powerend_size(struct powerhistory_powerend_s *ph); +void powerend_free(struct powerhistory_powerend_s *p); + +struct powerhistory_powerstart_s *powerstart_deserialize(char **dst, const char *maxdst); +int powerstart_serialize(struct powerhistory_powerstart_s *ph, char **dst, const char *maxdst); +int powerstart_size(struct powerhistory_powerstart_s *ph); +void powerstart_free(struct powerhistory_powerstart_s *p); + +struct powerhistory_creategame_s *creategame_deserialize(char **dst, const char *maxdst); +int creategame_serialize(struct powerhistory_creategame_s *ph, char **dst, const char *maxdst); +int creategame_size(struct powerhistory_creategame_s *ph); +void creategame_free(struct powerhistory_creategame_s *c); + +struct powerhistory_tagchange_s *tagchange_deserialize(char **dst, const char *maxdst); +int tagchange_serialize(struct powerhistory_tagchange_s *ph, char **dst, const char *maxdst); +int tagchange_size(struct powerhistory_tagchange_s *ph); +void tagchange_free(struct powerhistory_tagchange_s *t); + +struct powerhistory_hide_s *hide_deserialize(char **dst, const char *maxdst); +int hide_serialize(struct powerhistory_hide_s *ph, char **dst, const char *maxdst); +int hide_size(struct powerhistory_hide_s *ph); +void hide_free(struct powerhistory_hide_s *t); + +struct powerhistory_game_entity_s *game_entity_deserialize(char **dst, const char *maxdst); +int game_entity_serialize(struct powerhistory_game_entity_s *ph, char **dst, const char *maxdst); +int game_entity_size(struct powerhistory_game_entity_s *ph); +void game_entity_free(struct powerhistory_game_entity_s *g); + +struct powerhistory_entity_s *entity_deserialize(char **dst, const char *maxdst); +int entity_serialize(struct powerhistory_entity_s *ph, char **dst, const char *maxdst); +int entity_size(struct powerhistory_entity_s *ph); +void entity_free(struct powerhistory_entity_s *e); + +struct powerhistory_tag_s *tag_deserialize(char **dst, const char *maxdst); +int tag_serialize(struct powerhistory_tag_s *ph, char **dst, const char *maxdst); +int tag_size(struct powerhistory_tag_s *ph); +void tag_free(struct powerhistory_tag_s *t); + +void player_free(struct powerhistory_player_s *p); +struct powerhistory_player_s *player_deserialize(char **dst, const char *maxdst); +int player_serialize(struct powerhistory_player_s *ph, char **dst, const char *maxdst); +int player_size(struct powerhistory_player_s *ph); + +int bnet_size(struct powerhistory_player_s *ph); + +void powerhistory_dump(struct powerhistory_s *p); + +#endif diff --git a/hm_proto/src/include/proto.h b/hm_proto/src/include/proto.h new file mode 100644 index 0000000..cdfc824 --- /dev/null +++ b/hm_proto/src/include/proto.h @@ -0,0 +1,68 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef PROTO_H_ +#define PROTO_H_ + +#define error()\ + hm_log(LOG_EMERG, lg, "dst: %p end: %p n: %d", *dst, maxdst, n);\ + abort(); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +typedef unsigned long long u64; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int sizeofu64(u64 v); +int sizeofu32(int v); +int write_byte(char **dst, const char *end, const char src); +int write_bytes(char **dst, const char *end, const char *src, const int nsrc); +void write_uint(char **dst, const char *end, int src); +void write_uint64(char **dst, const char *end, u64 src); +int write_mem_int(char **dst, const char *end, const int src); +char read_byte(char **dst, const char *end); +int read_uint(char **dst, const char *end); +u64 read_uint64(char **dst, const char *end); +int read_mem_int(char **dst, const char *end); +char *read_bytes(char **dst, const char *end, int *ndst); +int skip(char **dst, const char *end, const int jump); + +extern struct hm_log_s *lg; + +#endif diff --git a/hm_proto/src/include/turntimer.h b/hm_proto/src/include/turntimer.h new file mode 100644 index 0000000..1aeebea --- /dev/null +++ b/hm_proto/src/include/turntimer.h @@ -0,0 +1,32 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef TURNTIMER_H_ +#define TURNTIMER_H_ + +struct turntimer_s { + u64 seconds; + u64 turn; + char show; +}; + +void turntimer_free(struct turntimer_s *t); +int turntimer_serialize(void *ao, char **dst, const char *maxdst); +void turntimer_dump(struct turntimer_s *t); +void *turntimer_deserialize(char **dst, const char *maxdst); + +#endif diff --git a/hm_proto/src/include/userui.h b/hm_proto/src/include/userui.h new file mode 100644 index 0000000..ec03734 --- /dev/null +++ b/hm_proto/src/include/userui.h @@ -0,0 +1,33 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef USERUI_H_ +#define USERUI_H_ + +struct userui_s { + struct mouseinfo_s *mouseinfo; + u64 emote; + u64 player_id; +}; + +void userui_free(struct userui_s *u); +int userui_serialize(void *ao, char **dst, const char *maxdst); +void *userui_deserialize(char **dst, const char *maxdst); +int userui_size(struct userui_s *p); +void userui_dump(struct userui_s *u); + +#endif diff --git a/hm_proto/src/include/zone.h b/hm_proto/src/include/zone.h new file mode 100644 index 0000000..e1d6134 --- /dev/null +++ b/hm_proto/src/include/zone.h @@ -0,0 +1,33 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ZONE_H_ +#define ZONE_H_ + +enum zone_e { + ZONE_INVALID = 0, + ZONE_PLAY = 1, + ZONE_DECK = 2, + ZONE_HAND = 3, + ZONE_GRAVEYARD = 4, + ZONE_REMOVEDFROMGAME = 5, + ZONE_SETASIDE = 6, + ZONE_SECRET = 7, + ZONE_DISCARD = -2, +}; + +#endif diff --git a/hm_proto/src/meta.c b/hm_proto/src/meta.c new file mode 100644 index 0000000..fb47069 --- /dev/null +++ b/hm_proto/src/meta.c @@ -0,0 +1,126 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void meta_free(struct powerhistory_meta_s *t) +{ + struct powerhistory_info_s *info, *del; + + for(info = t->info; info != NULL; del = info, info = info->next, free(del)); + + free(t); +} + +struct powerhistory_meta_s *meta_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_meta_s *t; + struct powerhistory_info_s *info; + int i; + + t = malloc(sizeof(*t)); + memset(t, 0, sizeof(*t)); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 18) { + len = read_uint(dst, maxdst); + + for(i = 0; i < len; i++) { + info = malloc(sizeof(*info)); + info->id = read_uint64(dst, maxdst); + info->next = NULL; + + if(t->info == NULL && t->info_tail == NULL) { + t->info = info; + t->info_tail = info; + } else { + t->info_tail->next = info; + t->info_tail = info; + } + } + } else if(n == 24) { + t->type = read_uint64(dst, maxdst); + } else if(n == 32) { + t->data = read_uint64(dst, maxdst); + } else { + error(); + } + } + + return t; +} + + +int meta_size(struct powerhistory_meta_s *p) +{ + int num = 0, num2; + struct powerhistory_info_s *m; + + if(p->info) { + num += 1; + num2 = num; + for(m = p->info; m != NULL; m = m->next) { + num += sizeofu64(m->id); + } + num += sizeofu32(num - num2); + } + + if(p->type != 0) { + num += 1; + num += sizeofu64(p->type); + } + + if(p->data != 0) { + num += 1; + num += sizeofu64(p->data); + } + + return num; +} + +int meta_serialize(struct powerhistory_meta_s *p, char **dst, const char *maxdst) +{ + int num = 0; + struct powerhistory_info_s *m; + + if(p->info) { + write_byte(dst, maxdst, 18); + for(m = p->info; m != NULL; m = m->next) { + num += sizeofu64(m->id); + } + + write_uint(dst, maxdst, num); + + for(m = p->info; m != NULL; m = m->next) { + write_uint64(dst, maxdst, m->id); + } + } + + if(p->type != 0) { + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, p->type); + } + + if(p->data != 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, p->data); + } + + return 0; +} diff --git a/hm_proto/src/mouseinfo.c b/hm_proto/src/mouseinfo.c new file mode 100644 index 0000000..2ab3dcf --- /dev/null +++ b/hm_proto/src/mouseinfo.c @@ -0,0 +1,104 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void mouseinfo_free(struct mouseinfo_s *m) +{ + free(m); +} + +void *mouseinfo_deserialize(char **dst, const char *maxdst) +{ + int n; + struct mouseinfo_s *c; + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + c->arroworigin = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + c->heldcard = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + c->overcard = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 32) { + error(); + } + c->x = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 40) { + error(); + } + c->y = read_uint64(dst, maxdst); + + return c; +} + +int mouseinfo_serialize(void *ao, char **dst, const char *maxdst) +{ + struct mouseinfo_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->arroworigin); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->heldcard); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, s->overcard); + + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, s->x); + + write_byte(dst, maxdst, 40); + write_uint64(dst, maxdst, s->y); + + return (*dst - start); +} + +int mouseinfo_size(struct mouseinfo_s *p) +{ + int num = 0; + + num += 5; + num += sizeofu64(p->arroworigin); + num += sizeofu64(p->heldcard); + num += sizeofu64(p->overcard); + num += sizeofu64(p->x); + num += sizeofu64(p->y); + + return num; +} diff --git a/hm_proto/src/option.c b/hm_proto/src/option.c new file mode 100644 index 0000000..0c974d9 --- /dev/null +++ b/hm_proto/src/option.c @@ -0,0 +1,84 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void option_free(struct option_s *o) +{ + struct suboption_s *s, *del; + + for(s = o->mainoption; s != NULL; del = s, s = s->next, suboption_free(del)); + + for(s = o->suboptions; s != NULL; del = s, s = s->next, suboption_free(del)); + + free(o); +} + +int option_serialize(struct option_s *s, char **dst, const char *maxdst) +{ + int n = 0; + struct suboption_s *m; + char *start; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->type); + + if(s->mainoption) { + write_byte(dst, maxdst, 18); + n = suboption_size(s->mainoption); + write_uint(dst, maxdst, n); + suboption_serialize(s->mainoption, dst, maxdst); + } + + if(s->suboptions) { + for(m = s->suboptions; m != NULL; m = m->next) { + write_byte(dst, maxdst, 26); + n = suboption_size(m); + write_uint(dst, maxdst, n); + suboption_serialize(m, dst, maxdst); + } + } + + return (*dst - start); +} + +int option_size(struct option_s *p) +{ + int num = 0, n; + struct suboption_s *s; + + num += 1; + num += sizeofu64(p->type); + + if(p->mainoption) { + num += 1; + n = suboption_size(p->mainoption); + num += sizeofu32(n) + n; + } + + if(p->suboptions) { + for(s = p->suboptions; s != NULL; s = s->next) { + num += 1; + n = suboption_size(s); + num += sizeofu32(n) + n; + } + } + + return num; +} diff --git a/hm_proto/src/packet.c b/hm_proto/src/packet.c new file mode 100644 index 0000000..47e2fb2 --- /dev/null +++ b/hm_proto/src/packet.c @@ -0,0 +1,129 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +#define MAP_PACKET_MAX 12 + +typedef int (*f)(void *c); + +static struct packet_meta_s map_packet[MAP_PACKET_MAX] = { + {P_GETGAMESTATE, NULL, NULL, NULL}, + {P_CHOOSEOPTION, chooseoption_deserialize, chooseoption_serialize, (f)chooseoption_free}, + {P_TURNTIMER, turntimer_deserialize, turntimer_serialize, (f)turntimer_free}, + {P_CHOOSEENTITIES, chooseentities_deserialize, chooseentities_serialize, (f)chooseentities_free}, + {P_ALLOPTIONS, NULL, alloptions_serialize, (f)alloptions_free}, + {P_ENTITYCHOICES, entitychoices_deserialize, entitychoices_serialize, (f)entitychoices_free}, + {P_GAMESETUP, gamesetup_deserialize, gamesetup_serialize, (f)gamesetup_free}, + {P_USERUI, userui_deserialize, userui_serialize, (f)userui_free}, + {P_POWERHISTORY, powerhistory_deserialize, powerhistory_serialize, (f)powerhistory_free}, + {P_HANDSHAKE, handshake_deserialize, handshake_serialize, (f)handshake_free}, + {P_PING, NULL, NULL, NULL}, + {P_PONG, NULL, NULL, NULL}, +}; + +struct packet_s *deserialize(char **dst, const char *maxdst) +{ + struct packet_s *p; + int i; + + if(!(dst != NULL && *dst != NULL && *dst < maxdst)) { + return NULL; + } + + p = malloc(sizeof(*p)); + + p->id = read_mem_int(dst, maxdst); + p->len = read_mem_int(dst, maxdst); + + for(i = 0; i < MAP_PACKET_MAX; i++) { + if(map_packet[i].id == p->id) { + if(map_packet[i].deserialize) { + p->data = map_packet[i].deserialize(dst, maxdst); + assert(p->data); + } + return p; + } + } + + free(p); + + return NULL; +} + +void packet_free(struct packet_s *p) +{ + int i; + + for(i = 0; i < MAP_PACKET_MAX; i++) { + if(map_packet[i].id == p->id) { + if(map_packet[i].free) { + map_packet[i].free(p->data); + } + + free(p); + break; + } + } +} + +int serialize(struct packet_s *p, char **dst, const char *maxdst) +{ + int i, n = 0; + char *off_len; + + write_mem_int(dst, maxdst, p->id); + off_len = *dst; + write_mem_int(dst, maxdst, 0); // make space for length + + n += 2 * sizeof(int); + + for(i = 0; i < MAP_PACKET_MAX; i++) { + if(map_packet[i].id == p->id) { + if(map_packet[i].serialize) { + n += map_packet[i].serialize(p->data, dst, maxdst); + } + + write_mem_int(&off_len, maxdst, n - (2 * sizeof(int))); + + return n; + } + } + + return -1; +} + +struct packet_s *packet_init(enum packet_e id, void *data) +{ + struct packet_s *p; + + p = malloc(sizeof(*p)); + + p->id = id; + p->data = data; + + return p; +} + +void add_packet(struct packet_s **dst, void *ph, enum packet_e n) +{ + *dst = malloc(sizeof(**dst)); + memset(*dst, 0, sizeof(**dst)); + + (*dst)->data = ph; + (*dst)->id = n; +} diff --git a/hm_proto/src/platform.c b/hm_proto/src/platform.c new file mode 100644 index 0000000..81826bd --- /dev/null +++ b/hm_proto/src/platform.c @@ -0,0 +1,105 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void platform_free(struct platform_s *p) +{ + free(p->name); + + free(p); +} + +int platform_size(struct platform_s *p) +{ + int num = 0; + + num += 2; + num += sizeofu64(p->os); + num += sizeofu64(p->screen); + + num += 1; + num += sizeofu32(p->nname) + p->nname; + + if(p->store != 0) { + num += 1; + num += sizeofu64(p->store); + } + + return num; +} + +int platform_serialize(void *ao, char **dst, const char *maxdst) +{ + struct platform_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->os); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->screen); + + write_byte(dst, maxdst, 26); + write_bytes(dst, maxdst, s->name, s->nname); + + if(s->store != 0) { + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, s->store); + } + + return (*dst - start); +} + +struct platform_s *platform_deserialize(char **dst, const char *maxdst) +{ + int n; + struct platform_s *h; + + h = malloc(sizeof(*h)); + h->store = 0; + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + h->os = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + h->screen = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 26) { + error(); + } + h->name = read_bytes(dst, maxdst, &h->nname); + + if(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 32) { + h->store = read_uint64(dst, maxdst); + } + } + + return h; +} diff --git a/hm_proto/src/player.c b/hm_proto/src/player.c new file mode 100644 index 0000000..cf5a167 --- /dev/null +++ b/hm_proto/src/player.c @@ -0,0 +1,116 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void player_free(struct powerhistory_player_s *p) +{ + game_entity_free(p->entity); + + free(p); +} + +struct powerhistory_player_s *player_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct powerhistory_player_s *player; + + player = malloc(sizeof(*player)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + player->id = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 18) { + error(); + } + len = read_uint(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + player->bnet_hi = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + player->bnet_lo = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + player->cardback = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 34) { + error(); + } + len = read_uint(dst, maxdst); + player->entity = game_entity_deserialize(dst, *dst + len); + + return player; +} + +int player_serialize(struct powerhistory_player_s *player, char **dst, const char *maxdst) +{ + int n; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, player->id); + + // bnet + write_byte(dst, maxdst, 18); + n = bnet_size(player); + write_uint(dst, maxdst, n); + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, player->bnet_hi); + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, player->bnet_lo); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, player->cardback); + + write_byte(dst, maxdst, 34); + n = game_entity_size(player->entity); + write_uint(dst, maxdst, n); + game_entity_serialize(player->entity, dst, maxdst); + + return 0; +} + +int player_size(struct powerhistory_player_s *p) +{ + int size = 0, ts; + + if(p) { + size += 4; + size += sizeofu64(p->id); + ts = bnet_size(p); + size += sizeofu32(ts) + ts; + size += sizeofu64(p->cardback); + ts = game_entity_size(p->entity); + size += sizeofu32(ts) + ts; + } + + return size; +} diff --git a/hm_proto/src/powerend.c b/hm_proto/src/powerend.c new file mode 100644 index 0000000..3aa161f --- /dev/null +++ b/hm_proto/src/powerend.c @@ -0,0 +1,42 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerend_free(struct powerhistory_powerend_s *p) +{ + free(p); +} + +struct powerhistory_powerend_s *powerend_deserialize(char **dst, const char *maxdst) +{ + struct powerhistory_powerend_s *t; + + t = malloc(sizeof(*t)); + + return t; +} + +int powerend_serialize(struct powerhistory_powerend_s *t, char **dst, const char *maxdst) +{ + return 0; +} + +int powerend_size(struct powerhistory_powerend_s *p) +{ + return 0; +} diff --git a/hm_proto/src/powerhistory.c b/hm_proto/src/powerhistory.c new file mode 100644 index 0000000..ec28c9c --- /dev/null +++ b/hm_proto/src/powerhistory.c @@ -0,0 +1,183 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerhistory_free(struct powerhistory_s *p) +{ + struct powerhistory_data_s *d, *del; + + for(d = p->data; d != NULL; del = d, d = d->next, powerhistory_data_free(del)); + + free(p); +} + +void *powerhistory_deserialize(char **dst, const char *maxdst) +{ + struct powerhistory_s *p; + struct powerhistory_data_s *d; + int n, len; + + p = malloc(sizeof(*p)); + p->data = NULL; + p->data_tail = NULL; + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + len = read_uint(dst, maxdst); + + if(n == 10) { + d = powerhistory_data_deserialize(dst, *dst + len); + d->next = NULL; + + if(p->data == NULL && p->data_tail == NULL) { + p->data = d; + p->data_tail = d; + } else { + p->data_tail->next = d; + p->data_tail = d; + } + + } else { + error(); + return NULL; + } + } + + return p; +} + +int powerhistory_serialize(void *data, char **dst, const char *maxdst) +{ + int n, o = 0; + struct powerhistory_data_s *d; + struct powerhistory_s *ph = data; + + if(ph->data) { + for(d = ph->data; d != NULL; d = d->next) { + write_byte(dst, maxdst, 10); + o += 1; + n = powerhistorydata_size(d); + write_uint(dst, maxdst, n); + o += sizeofu32(n) + n; + powerhistorydata_serialize(d, dst, maxdst); + } + } + + return o; +} + +int powerhistory_size(struct powerhistory_s *ph) +{ + struct powerhistory_data_s *d; + int n, num = 0; + + if(ph->data) { + for(d = ph->data; d != NULL; d = d->next) { + num += 1; + n = powerhistorydata_size(d); + num += n + sizeofu32(n); + } + } + + return num; +} + +void powerhistory_dump(struct powerhistory_s *p) +{ + struct powerhistory_tag_s *t; + struct powerhistory_data_s *d; + struct powerhistory_game_entity_s *ge; + struct powerhistory_player_s *player; + struct powerhistory_info_s *i; + int it = 0; + + assert(p); + + for(d = p->data; d != NULL; d = d->next) { + hm_log(LOG_DEBUG, lg, "Data %d", it++); + + if(d->full) { + hm_log(LOG_DEBUG, lg, "data->full:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->full->entity, d->full->nname, d->full->name); + for(t = d->full->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + + if(d->show) { + hm_log(LOG_DEBUG, lg, "data->show:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->show->entity, d->show->nname, d->show->name); + for(t = d->show->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + + if(d->hide) { + hm_log(LOG_DEBUG, lg, "data->hide:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld zone: %lld", d->hide->entity, d->hide->zone); + } + + if(d->tagchange) { + hm_log(LOG_DEBUG, lg, "data->tagchange:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld tag: %lld value: %lld", d->tagchange->entity, d->tagchange->tag, d->tagchange->value); + } + + if(d->creategame) { + ge = d->creategame->game_entity; + hm_log(LOG_DEBUG, lg, "game entity id: %lld", ge->id); + for(t = ge->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\ttag name: %lld value: %lld", t->name, t->value); + } + + for(player = d->creategame->player; player != NULL; player = player->next) { + hm_log(LOG_DEBUG, lg, "\t\tdata->creategame->player:"); + hm_log(LOG_DEBUG, lg, "\t\t\tid: %lld bhi: %lld blo: %lld cardback: %lld", player->id, player->bnet_hi, player->bnet_lo, player->cardback); + ge = player->entity; + hm_log(LOG_DEBUG, lg, "\t\t\tplayer->entity: %lld", ge->id); + for(t = ge->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\t\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + } + + if(d->powerstart) { + hm_log(LOG_DEBUG, lg, "data->powerstart"); + hm_log(LOG_DEBUG, lg, "\ttype: %lld index: %lld source: %lld target: %lld card: [%.*s]", d->powerstart->type, d->powerstart->index, d->powerstart->source, d->powerstart->target, d->powerstart->ncard_id, d->powerstart->card_id); + } + + if(d->powerend) { + hm_log(LOG_DEBUG, lg, "data->powerend"); + } + + if(d->change_entity) { + hm_log(LOG_DEBUG, lg, "data->change_entity:"); + hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->change_entity->entity, d->change_entity->nname, d->change_entity->name); + for(t = d->change_entity->tag; t != NULL; t = t->next) { + hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value); + } + } + + if(d->meta) { + hm_log(LOG_DEBUG, lg, "data->meta:"); + hm_log(LOG_DEBUG, lg, "\ttype: %lld data: %lld", d->meta->type, d->meta->data); + for(i = d->meta->info; i != NULL; i = i->next) { + hm_log(LOG_DEBUG, lg, "\t\t\tinfo id: %lld", i->id); + } + } + } +} diff --git a/hm_proto/src/powerhistorydata.c b/hm_proto/src/powerhistorydata.c new file mode 100644 index 0000000..1554643 --- /dev/null +++ b/hm_proto/src/powerhistorydata.c @@ -0,0 +1,200 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerhistory_data_free(struct powerhistory_data_s *d) +{ + if(d->full) entity_free(d->full); + if(d->show) entity_free(d->show); + if(d->hide) hide_free(d->hide); + if(d->tagchange) tagchange_free(d->tagchange); + if(d->creategame) creategame_free(d->creategame); + if(d->powerstart) powerstart_free(d->powerstart); + if(d->powerend) powerend_free(d->powerend); + if(d->change_entity) entity_free(d->change_entity); + if(d->meta) meta_free(d->meta); + + free(d); +} + +struct powerhistory_data_s *powerhistory_data_deserialize(char **dst, const char *maxdst) +{ + struct powerhistory_data_s *p; + int n, len; + + p = malloc(sizeof(*p)); + memset(p, 0, sizeof(*p)); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + len = read_uint(dst, maxdst); + + if(n == 10) { + p->full = entity_deserialize(dst, *dst + len); + } else if(n == 18) { + p->show = entity_deserialize(dst, *dst + len); + } else if(n == 26) { + p->hide = hide_deserialize(dst, *dst + len); + } else if(n == 34) { + p->tagchange = tagchange_deserialize(dst, *dst + len); + } else if(n == 42) { + p->creategame = creategame_deserialize(dst, *dst + len); + } else if(n == 50) { + p->powerstart = powerstart_deserialize(dst, *dst + len); + } else if(n == 58) { + p->powerend = powerend_deserialize(dst, *dst + len); + } else if(n == 66) { + p->meta = meta_deserialize(dst, *dst + len); + } else { + return NULL; + } + } + + return p; +} + +int powerhistorydata_serialize(struct powerhistory_data_s *phd, char **dst, const char *maxdst) +{ + int n; + + if(phd->full) { + write_byte(dst, maxdst, 10); + n = entity_size(phd->full); + write_uint(dst, maxdst, n); + entity_serialize(phd->full, dst, maxdst); + } + + if(phd->show) { + write_byte(dst, maxdst, 18); + n = entity_size(phd->show); + write_uint(dst, maxdst, n); + entity_serialize(phd->show, dst, maxdst); + } + + if(phd->hide) { + write_byte(dst, maxdst, 26); + n = hide_size(phd->hide); + write_uint(dst, maxdst, n); + hide_serialize(phd->hide, dst, maxdst); + } + + if(phd->tagchange) { + write_byte(dst, maxdst, 34); + n = tagchange_size(phd->tagchange); + write_uint(dst, maxdst, n); + tagchange_serialize(phd->tagchange, dst, maxdst); + } + + if(phd->creategame) { + write_byte(dst, maxdst, 42); + n = creategame_size(phd->creategame); + write_uint(dst, maxdst, n); + creategame_serialize(phd->creategame, dst, maxdst); + } + + if(phd->powerstart) { + write_byte(dst, maxdst, 50); + n = powerstart_size(phd->powerstart); + write_uint(dst, maxdst, n); + powerstart_serialize(phd->powerstart, dst, maxdst); + } + + if(phd->powerend) { + write_byte(dst, maxdst, 58); + n = powerend_size(phd->powerend); + write_uint(dst, maxdst, n); + powerend_serialize(phd->powerend, dst, maxdst); + } + + if(phd->meta) { + write_byte(dst, maxdst, 66); + n = meta_size(phd->meta); + write_uint(dst, maxdst, n); + meta_serialize(phd->meta, dst, maxdst); + } + + if(phd->change_entity) { + write_byte(dst, maxdst, 74); + n = entity_size(phd->change_entity); + write_uint(dst, maxdst, n); + entity_serialize(phd->change_entity, dst, maxdst); + } + + return 0; +} + +int powerhistorydata_size(struct powerhistory_data_s *phd) +{ + int num = 0, n; + + if(phd->full) { + num += 1; + n = entity_size(phd->full); + num += n + sizeofu32(n); + } + + if(phd->show) { + num += 1; + n = entity_size(phd->show); + num += n + sizeofu32(n); + } + + if(phd->hide) { + num += 1; + n = hide_size(phd->hide); + num += n + sizeofu32(n); + } + + if(phd->tagchange) { + num += 1; + n = tagchange_size(phd->tagchange); + num += n + sizeofu32(n); + } + + if(phd->creategame) { + num += 1; + n = creategame_size(phd->creategame); + num += n + sizeofu32(n); + } + + if(phd->powerstart) { + num += 1; + n = powerstart_size(phd->powerstart); + num += n + sizeofu32(n); + } + + if(phd->powerend) { + num += 1; + n = powerend_size(phd->powerend); + num += n + sizeofu32(n); + } + + if(phd->meta) { + num += 1; + n = meta_size(phd->meta); + num += n + sizeofu32(n); + } + + if(phd->change_entity) { + num += 1; + n = entity_size(phd->change_entity); + num += n + sizeofu32(n); + } + + return num; +} diff --git a/hm_proto/src/powerstart.c b/hm_proto/src/powerstart.c new file mode 100644 index 0000000..883637e --- /dev/null +++ b/hm_proto/src/powerstart.c @@ -0,0 +1,112 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void powerstart_free(struct powerhistory_powerstart_s *p) +{ + free(p->card_id); + + free(p); +} + +struct powerhistory_powerstart_s *powerstart_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_powerstart_s *t; + + t = malloc(sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + t->type = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + t->index = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + t->source = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 32) { + error(); + } + t->target = read_uint64(dst, maxdst); + + t->ncard_id = 0; + t->card_id = NULL; + // optional + n = read_byte(dst, maxdst); + if(n != 42) { + return t; + } + + t->card_id = read_bytes(dst, maxdst, &t->ncard_id); + + return t; +} + +int powerstart_serialize(struct powerhistory_powerstart_s *p, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, p->type); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, p->index); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, p->source); + + write_byte(dst, maxdst, 32); + write_uint64(dst, maxdst, p->target); + + if(p->ncard_id > 0) { + write_byte(dst, maxdst, 42); + write_bytes(dst, maxdst, p->card_id, p->ncard_id); + } + + return 0; +} + +int powerstart_size(struct powerhistory_powerstart_s *p) +{ + int size = 0; + int n; + + if(p) { + size += 4; + size += sizeofu64(p->type); + size += sizeofu64(p->index); + size += sizeofu64(p->source); + size += sizeofu64(p->target); + if(p->ncard_id > 0) { + size += 1; + n = sizeofu64(p->ncard_id); + size += sizeofu32(n) + n; + } + } + + return size; +} diff --git a/hm_proto/src/proto.c b/hm_proto/src/proto.c new file mode 100644 index 0000000..5033032 --- /dev/null +++ b/hm_proto/src/proto.c @@ -0,0 +1,231 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +int sizeofu64(u64 val) +{ + unsigned int num = 1u; + + while(1 == 1) { + val >>= 7; + if(val == 0) { + break; + } + num++; + } + + return num; +} + +int sizeofu32(int val) +{ + unsigned int num = 1u; + + while(1 == 1) { + val >>= 7; + if(val == 0) { + break; + } + num++; + } + + return num; +} + +int read_mem_int(char **dst, const char *end) +{ + int n; + + if(*dst + sizeof(int) > end) { + return -1; + } + + n = *(int *)(*dst); + (*dst) += sizeof(int); + return n; +} + +int write_mem_int(char **dst, const char *end, const int src) +{ + if(*dst + sizeof(src) > end) { + hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", src, *dst, end); + abort(); + } + + memcpy(*dst, &src, sizeof(src)); + (*dst) += sizeof(src); + return 0; +} + + +int write_byte(char **dst, const char *end, char src) +{ + if(*dst + sizeof(src) > end) { + hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", src, *dst, end); + abort(); + } + + memcpy(*dst, &src, sizeof(src)); + (*dst)++; + return 0; +} + +char read_byte(char **dst, const char *end) +{ + char out; + + if(*dst + sizeof(char) > end) { + return -1; + } + + out = *((char *)(*dst)); + + (*dst)++; + return out; +} + +int skip(char **dst, const char *end, const int jump) +{ + if((*dst + jump) > end) { + hm_log(LOG_ALERT, lg, "Invalid skip %p %p %d", *dst, end, jump); + return -1; + } + + *dst += jump; + + return 0; +} + +int read_uint(char **dst, const char *end) +{ + int num = 0, num2; + int i; + + for(i = 0; (i < 5 && *dst < end); i++) { + num2 = read_byte(dst, end); + + if(i == 4 && (num2 & 240) != 0) { + hm_log(LOG_EMERG, lg, "Incorrect num size"); + abort(); + } + + if((num2 & 128) == 0) { + return num | (unsigned int)((unsigned int)num2 << 7 * i); + } + + num |= (unsigned int)((unsigned int)(num2 & 127) << 7 * i); + } + + return num; +} + +u64 read_uint64(char **dst, const char *end) +{ + u64 num = 0; + int num2; + int i; + + for(i = 0; (i < 10 && *dst < end); i++) { + num2 = read_byte(dst, end); + + if(i == 9 && (num2 & 254) != 0) { + hm_log(LOG_EMERG, lg, "Incorrect num size"); + abort(); + } + + if((num2 & 128) == 0) { + return num | (unsigned long long)((unsigned long long)num2 << 7 * i); + } + + num |= (unsigned long long)((unsigned long long)(num2 & 127) << 7 * i); + } + + return num; +} + +void write_uint(char **dst, const char *end, int src) +{ + char b; + + while(1 == 1) { + b = (char)(src & 127); + src >>= 7; + + if(src == 0) { + break; + } + + b |= 128; + + write_byte(dst, end, b); + } + + write_byte(dst, end, b); +} + +char *read_bytes(char **dst, const char *end, int *ndst) +{ + char *out; + + *ndst = read_uint(dst, end); + + if(*dst + *ndst > end) { + hm_log(LOG_EMERG, lg, "Dst read bytes %p %p %d", end, *dst + *ndst, *ndst); + abort(); + } + + out = malloc(*ndst); + memcpy(out, *dst, *ndst); + *dst += *ndst; + + return out; +} + +int write_bytes(char **dst, const char *end, const char *src, const int nsrc) +{ + if(*dst + nsrc > end) { + hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", nsrc, *dst, end); + abort(); + } + + write_uint(dst, end, nsrc); + + memcpy(*dst, src, nsrc); + (*dst) += nsrc; + return 0; +} + +void write_uint64(char **dst, const char *end, u64 src) +{ + char b; + + while(1 == 1) { + b = (char)(src & 127); + src >>= 7; + + if(src == 0) { + break; + } + + b |= 128; + + write_byte(dst, end, b); + } + + write_byte(dst, end, b); +} diff --git a/hm_proto/src/suboption.c b/hm_proto/src/suboption.c new file mode 100644 index 0000000..4e6e751 --- /dev/null +++ b/hm_proto/src/suboption.c @@ -0,0 +1,75 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void suboption_free(struct suboption_s *s) +{ + struct suboption_target_s *t, *del; + + for(t = s->target; t != NULL; del = t, t = t->next, free(del)); + + free(s); +} + +int suboption_size(struct suboption_s *p) +{ + int num = 0, num2; + struct suboption_target_s *m; + + num += sizeofu64(p->id); + + if(p->target) { + num += 1; + num2 = num; + for(m = p->target; m != NULL; m = m->next) { + num += sizeofu64(m->value); + } + num += sizeofu32(num - num2); + } + + num += 1; + + return num; +} + +int suboption_serialize(struct suboption_s *s, char **dst, const char *maxdst) +{ + int num = 0; + struct suboption_target_s *m; + char *start; + + start = *dst; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->id); + + if(s->target) { + write_byte(dst, maxdst, 26); + for(m = s->target; m != NULL; m = m->next) { + num += sizeofu64(m->value); + } + + write_uint(dst, maxdst, num); + + for(m = s->target; m != NULL; m = m->next) { + write_uint64(dst, maxdst, m->value); + } + } + + return (*dst - start); +} diff --git a/hm_proto/src/tag.c b/hm_proto/src/tag.c new file mode 100644 index 0000000..6ed24ec --- /dev/null +++ b/hm_proto/src/tag.c @@ -0,0 +1,73 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void tag_free(struct powerhistory_tag_s *t) +{ + free(t); +} + +struct powerhistory_tag_s *tag_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_tag_s *t; + + t = malloc(sizeof(*t)); + + + n = read_byte(dst, maxdst); + + if(n != 8) { + error(); + } + t->name = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + + if(n != 16) { + error(); + } + t->value = read_uint64(dst, maxdst); + + return t; +} + + +int tag_size(struct powerhistory_tag_s *tag) +{ + int size = 0; + + if(tag) { + size += 2; + size += sizeofu64(tag->name); + size += sizeofu64(tag->value); + } + + return size; +} + +int tag_serialize(struct powerhistory_tag_s *t, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, t->name); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, t->value); + + return 0; +} diff --git a/hm_proto/src/tagchange.c b/hm_proto/src/tagchange.c new file mode 100644 index 0000000..719dbbd --- /dev/null +++ b/hm_proto/src/tagchange.c @@ -0,0 +1,79 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void tagchange_free(struct powerhistory_tagchange_s *t) +{ + free(t); +} + +struct powerhistory_tagchange_s *tagchange_deserialize(char **dst, const char *maxdst) +{ + int n; + struct powerhistory_tagchange_s *t; + + t = malloc(sizeof(*t)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + t->entity = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + t->tag = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + t->value = read_uint64(dst, maxdst); + + return t; +} + +int tagchange_serialize(struct powerhistory_tagchange_s *ent, char **dst, const char *maxdst) +{ + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, ent->entity); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, ent->tag); + + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, ent->value); + + return 0; +} + +int tagchange_size(struct powerhistory_tagchange_s *t) +{ + int size = 0; + + if(t) { + size += 3; + size += sizeofu64(t->entity); + size += sizeofu64(t->tag); + size += sizeofu64(t->value); + } + + return size; +} diff --git a/hm_proto/src/turntimer.c b/hm_proto/src/turntimer.c new file mode 100644 index 0000000..d6bcaf7 --- /dev/null +++ b/hm_proto/src/turntimer.c @@ -0,0 +1,80 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void turntimer_free(struct turntimer_s *t) +{ + free(t); +} + +void *turntimer_deserialize(char **dst, const char *maxdst) +{ + int n; + struct turntimer_s *o; + + o = malloc(sizeof(*o)); + memset(o, 0, sizeof(*o)); + + n = read_byte(dst, maxdst); + if(n != 8) { + error(); + } + o->seconds = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 16) { + error(); + } + o->turn = read_uint64(dst, maxdst); + + n = read_byte(dst, maxdst); + if(n != 24) { + error(); + } + o->show = read_byte(dst, maxdst); + + return o; +} + +int turntimer_serialize(void *ao, char **dst, const char *maxdst) +{ + struct turntimer_s *s; + char *start; + + start = *dst; + s = ao; + + write_byte(dst, maxdst, 8); + write_uint64(dst, maxdst, s->seconds); + + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->turn); + + write_byte(dst, maxdst, 24); + write_byte(dst, maxdst, s->show); + + return (*dst - start); +} + +void turntimer_dump(struct turntimer_s *t) +{ + hm_log(LOG_DEBUG, lg, "Turn timer dump:"); + hm_log(LOG_DEBUG, lg, "\t\tseconds: %lld", t->seconds); + hm_log(LOG_DEBUG, lg, "\t\tturn: %lld", t->turn); + hm_log(LOG_DEBUG, lg, "\t\tshow: %d", t->show); +} diff --git a/hm_proto/src/userui.c b/hm_proto/src/userui.c new file mode 100644 index 0000000..25710be --- /dev/null +++ b/hm_proto/src/userui.c @@ -0,0 +1,124 @@ +/* + hm_gameserver - hearthmod gameserver + Copyright (C) 2016 Filip Pancik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +void userui_free(struct userui_s *u) +{ + mouseinfo_free(u->mouseinfo); + + free(u); +} + +void *userui_deserialize(char **dst, const char *maxdst) +{ + int n, len; + struct userui_s *c; + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + while(*dst < maxdst) { + n = read_byte(dst, maxdst); + if(n == 10) { + len = read_uint(dst, maxdst); + c->mouseinfo = mouseinfo_deserialize(dst, *dst + len); + } + else if(n == 16) { + c->emote = read_uint64(dst, maxdst); + } + else if(n == 24) { + c->player_id = read_uint64(dst, maxdst); + } + } + + return c; +} + +int userui_serialize(void *ao, char **dst, const char *maxdst) +{ + struct userui_s *s; + char *start; + int n; + + start = *dst; + s = ao; + + if(s->mouseinfo) { + write_byte(dst, maxdst, 10); + n = mouseinfo_size(s->mouseinfo); + write_uint(dst, maxdst, n); + mouseinfo_serialize(s->mouseinfo, dst, maxdst); + } + + if(s->emote != -1) { + write_byte(dst, maxdst, 16); + write_uint64(dst, maxdst, s->emote); + } + + if(s->player_id != -1) { + write_byte(dst, maxdst, 24); + write_uint64(dst, maxdst, s->player_id); + } + + return (*dst - start); +} + +int userui_size(struct userui_s *p) +{ + int num = 0, n; + + if(p->mouseinfo) { + num += 1; + n = mouseinfo_size(p->mouseinfo); + num += n + sizeofu32(n); + } + + if(p->emote != 0) { + num += 1; + num += sizeofu64(p->emote); + } + + if(p->player_id != 0) { + num += 1; + num += sizeofu64(p->player_id); + } + + return num; +} + +void userui_dump(struct userui_s *u) +{ + if(u) { + if(u->mouseinfo) { + hm_log(LOG_DEBUG, lg, "arrow origin: %lld", u->mouseinfo->arroworigin); + hm_log(LOG_DEBUG, lg, "heldcard: %lld", u->mouseinfo->heldcard); + hm_log(LOG_DEBUG, lg, "overcard: %lld", u->mouseinfo->overcard); + hm_log(LOG_DEBUG, lg, "x: %lld", u->mouseinfo->x); + hm_log(LOG_DEBUG, lg, "y: %lld", u->mouseinfo->y); + } + + if(u->emote != 0) { + hm_log(LOG_DEBUG, lg, "emote: %lld", u->emote); + } + + if(u->player_id != 0) { + hm_log(LOG_DEBUG, lg, "player_id: %lld", u->player_id); + } + + } +} diff --git a/hm_proto/test/all/Makefile b/hm_proto/test/all/Makefile new file mode 100644 index 0000000..5f18e02 --- /dev/null +++ b/hm_proto/test/all/Makefile @@ -0,0 +1,8 @@ +all: + $(CC) -Wall -g -I../../src/include -I../../../hm_base/src/include \ + -L../../lib -L../../../hm_base/lib \ + main.c \ + -lhmproto -lhmbase -lm\ + -o ./a.out + +.PHONY: all diff --git a/hm_proto/test/all/main.c b/hm_proto/test/all/main.c new file mode 100644 index 0000000..0f14e56 --- /dev/null +++ b/hm_proto/test/all/main.c @@ -0,0 +1,171 @@ +#include +#include + +struct hm_log_s *lg; + +#define DUMP(m_dst, m_i, m_s)\ + int i##m_i = 0;\ + printf("dumping [%s]\n", m_s);\ + for(i##m_i = 0; i##m_i < m_i; i##m_i++) {\ + printf("%x", m_dst[i##m_i]);\ + }\ + printf("\n"); + +#define REPEAT\ + packet_free(p);\ + {\ + for(i = 0; i < 10; i++) {\ + parse_packet(p, buf, nbuf);\ + build_packet_test(p, buf);\ + packet_free(p);\ + }\ + } + +#define build_packet_test(m_p, m_buffer)\ + char *ptrtest##m_buffer;\ + ptrtest##m_buffer = m_buffer;\ + n##m_buffer = serialize(m_p, &ptrtest##m_buffer, ptrtest##m_buffer + sizeof(m_buffer)); + +#define string(m_dst, m_ndst, m_s)\ + m_ndst = strlen(m_s);\ + m_dst = malloc(m_ndst);\ + memcpy(m_dst, m_s, m_ndst); + +int main() +{ + struct packet_s *p; + struct hm_log_s l; + int i; + + hm_log_open(&l, NULL, LOG_DEBUG); + lg = &l; + + // chooseoption + { + struct chooseoption_s *c; + c = malloc(sizeof(*c)); + c->id = 0xffff; + c->index = 0xffff; + c->target = 0xffff; + c->suboption = 0xffff; + c->position = 0xffff; + + build_packet(p, c, P_CHOOSEOPTION, buf); + REPEAT; + } + + // turn timer + { + struct turntimer_s *c; + c = malloc(sizeof(*c)); + c->seconds = 0xffff; + c->turn = 0xffff; + c->show = 0xff; + + build_packet(p, c, P_TURNTIMER, buf); + REPEAT; + } + + // gamesetup + { + struct gamesetup_s *c; + c = malloc(sizeof(*c)); + c->board = 0xffff; + c->maxsecrets = 0xffff; + c->maxfriendlyminions = 0xffff; + c->stuckdisconnect = 0xffff; + c->keepalive = 0xffff; + + build_packet(p, c, P_TURNTIMER, buf); + REPEAT; + } + + // handshake + { + struct handshake_s *c; + c = malloc(sizeof(*c)); + c->gamehandle = 0xffff; + string(c->password, c->npassword, "password"); + c->clienthandle = 0xffff; + c->mission = 0xffff; + string(c->version, c->nversion, "version"); + + struct platform_s *pl; + pl = malloc(sizeof(*pl)); + pl->os = 0xffff; + pl->screen = 0xffff; + string(pl->name, pl->nname, "name"); + pl->store = 0xffff; + + c->platform = pl; + + build_packet(p, c, P_HANDSHAKE, buf); + REPEAT; + } + + // chooseentities + { + struct chooseentities_s *c; + struct chooseentities_ent_s *e; + c = malloc(sizeof(*c)); + c->id = 0xffff; + c->nentity = 4; + c->entity = NULL; + for(i = 0; i < c->nentity; i++) { + e = malloc(sizeof(*e)); + e->entity = i; + e->next = c->entity; + c->entity = e; + } + + build_packet(p, c, P_CHOOSEENTITIES, buf); + REPEAT; + } + + // entitychoices + { + struct entitychoices_s *c; + struct entitychoices_entities_s *e; + c = malloc(sizeof(*c)); + c->id = 0xffff; + c->type = 0xffff; + c->countmin = 0xffff; + c->countmax = 0xffff; + c->source = 0xffff; + c->player_id = 0xffff; + c->entities = NULL; + + for(i = 0; i < 10; i++) { + e = malloc(sizeof(*e)); + e->entity = i; + e->next = c->entities; + c->entities = e; + } + + build_packet(p, c, P_ENTITYCHOICES, buf); + REPEAT; + } + + // userui + { + struct userui_s *c; + struct mouseinfo_s *e; + c = malloc(sizeof(*c)); + + e = malloc(sizeof(*e)); + e->arroworigin = 0xffff; + e->heldcard = 0xffff; + e->overcard = 0xffff; + e->x = 0xffff; + e->y = 0xffff; + + c->mouseinfo = e; + c->emote = 0xffff; + c->player_id = 0xffff; + + build_packet(p, c, P_USERUI, buf); + REPEAT; + } + + return 0; +} diff --git a/hm_stud/LICENSE b/hm_stud/LICENSE new file mode 100644 index 0000000..df4d414 --- /dev/null +++ b/hm_stud/LICENSE @@ -0,0 +1,25 @@ +Copyright 2012 Bump Technologies, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP TECHNOLOGIES, INC. OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Bump Technologies, Inc. diff --git a/hm_stud/Makefile b/hm_stud/Makefile new file mode 100644 index 0000000..eba3e9c --- /dev/null +++ b/hm_stud/Makefile @@ -0,0 +1,52 @@ +# [g]make USE_xxxx=1 +# +# USE_SHARED_CACHE : enable/disable a shared session cache (disabled by default) + +DESTDIR = +PREFIX = /usr/local +BINDIR = $(PREFIX)/bin +MANDIR = $(PREFIX)/share/man + +CFLAGS = -O2 -g -std=c99 -fno-strict-aliasing -Wall -W -D_GNU_SOURCE -I/usr/local/include +LDFLAGS = -lssl -lcrypto -lev -L/usr/local/lib +OBJS = stud.o ringbuffer.o configuration.o + +all: realall + +# Shared cache feature +ifneq ($(USE_SHARED_CACHE),) +CFLAGS += -DUSE_SHARED_CACHE -DUSE_SYSCALL_FUTEX +OBJS += shctx.o ebtree/libebtree.a +ALL += ebtree + +ebtree/libebtree.a: $(wildcard ebtree/*.c) + make -C ebtree +ebtree: + @[ -d ebtree ] || ( \ + echo "*** Download libebtree at http://1wt.eu/tools/ebtree/" ; \ + echo "*** Untar it and make a link named 'ebtree' to point on it"; \ + exit 1 ) +endif + +# No config file support? +ifneq ($(NO_CONFIG_FILE),) +CFLAGS += -DNO_CONFIG_FILE +endif + +ALL += stud +realall: $(ALL) + +stud: $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) + +install: $(ALL) + install -d $(DESTDIR)$(BINDIR) + install stud $(DESTDIR)$(BINDIR) + install -d $(DESTDIR)$(MANDIR)/man8 + install -m 644 stud.8 $(DESTDIR)$(MANDIR)/man8 + +clean: + rm -f stud $(OBJS) + + +.PHONY: all realall diff --git a/hm_stud/README.md b/hm_stud/README.md new file mode 100644 index 0000000..3ac455a --- /dev/null +++ b/hm_stud/README.md @@ -0,0 +1,191 @@ +STATUS +====== + +Stud is now officially abandonware, thanks for playing. + +Recommended alternative: https://github.com/varnish/hitch + +More info: https://blog.jamwt.com/2016/03/21/stud-no-more/ + +stud - The Scalable TLS Unwrapping Daemon +========================================= + +`stud` is a network proxy that terminates TLS/SSL connections and forwards the +unencrypted traffic to some backend. It's designed to handle 10s of thousands of +connections efficiently on multicore machines. + +It follows a process-per-core model; a parent process spawns N children who +each `accept()` on a common socket to distribute connected clients among them. +Within each child, asynchronous socket I/O is conducted across the local +connections using `libev` and `OpenSSL`'s nonblocking API. By default, +`stud` has an overhead of ~200KB per connection--it preallocates +some buffer space for data in flight between frontend and backend. + +`stud` has very few features--it's designed to be paired with an intelligent +backend like haproxy or nginx. It maintains a strict 1:1 connection pattern +with this backend handler so that the backend can dictate throttling behavior, +maxmium connection behavior, availability of service, etc. + +`stud` will optionally write the client IP address as the first few octets +(depending on IPv4 or IPv6) to the backend--or provide that information +using HAProxy's PROXY protocol. When used with the PROXY protocol, `stud` can +also transparently pass an existing PROXY header to the cleartext stream. This +is especially useful if a TCP proxy is used in front of `stud`. Using either of +these techniques, backends who care about the client IP can still access it even +though `stud` itself appears to be the connected client. + +Thanks to a contribution from Emeric at Exceliance (the folks behind HAProxy), +a special build of `stud` can be made that utilitizes shared memory to +use a common session cache between all child processes. This can speed up +large `stud` deployments by avoiding client renegotiation. + +Releases +--------- + +Please be aware of the policy regarding releases, code stability, and security: + + * In git, the tip of the master branch should always build on Linux and + FreeBSD, and is likely to be as stable as any other changeset. A + careful review of patches is conducted before being pushed to github. + * Periodically, a version tag will be pushed to github for an old(er) + changeset--0.1, 0.2, etc. These tags mark a particular release of + `stud` that has seen heavy testing and several weeks of production + stability. Conservative users are advised to use a tag. + * `stud` has an optional build that utilizes shared memory-based SSL contexts + and UDP peer communication to keep a session cache between many child processes + running on many machines. The use of this build can dramatically speed + up SSL handshakes on many-core and/or clustered deployments. + However, it's important to acknowledge the inevitable theoretical + security tradeoffs associated with the use of this (substantially more + complex) binary. Therefore, the deeply paranoid are advised to use + only the standard `stud` binary at the cost of some performance. + +Requirements and Limitations +---------------------------- + +`stud` requires: + + libev >= 4 + openssl (recent, >=1.0.0 recommended) + +Stud currently works on Linux, OpenBSD, FreeBSD, and MacOSX. +It has been tested the most heavily on Linux/x86_64. + +While porting it to other POSIX platforms is likely trivial, it hasn't be done +yet. Patches welcome! + +If you're handling a large number of connections, you'll +probably want to raise `ulimit -n` before running `stud`. +It's very strongly recommended to not run `stud` as root; ideally, it would +be run as a user ("stud", perhaps) that does nothing but run `stud`. Stud +will setuid (using -u) after binding if you need to bind to a low port (< 1024). + +Installing +---------- + +To install `stud`: + + $ make + $ sudo make install + +Usage +----- + +The only required argument is a path to a PEM file that contains the certificate +(or a chain of certificates) and private key. If multiple certificates are +given, `stud` will attempt to perform SNI (Server Name Indication) on new +connections, by comparing the indicated name with the names on each of the +certificates, in order. The first certificate that matches will be used. If none +of the certificates matches, the last certificate will be used as the default. + +Detail about the entire set of options can be found by invoking `stud -h`: + + CONFIGURATION: + + --config=FILE Load configuration from specified file. + --default-config Prints default configuration to stdout. + + ENCRYPTION METHODS: + + --tls TLSv1 (default) + --ssl SSLv3 (implies no TLSv1) + -c --ciphers=SUITE Sets allowed ciphers (Default: "") + -e --ssl-engine=NAME Sets OpenSSL engine (Default: "") + -O --prefer-server-ciphers Prefer server list order + + SOCKET: + + -b --backend=HOST,PORT Backend [connect] (default is "[127.0.0.1]:8000") + -f --frontend=HOST,PORT Frontend [bind] (default is "[*]:8443") + + PERFORMANCE: + + -n --workers=NUM Number of worker processes (Default: 1) + -B --backlog=NUM Set listen backlog size (Default: 100) + -k --keepalive=SECS TCP keepalive on client socket (Default: 3600) + + SECURITY: + + -r --chroot=DIR Sets chroot directory (Default: "") + -u --user=USER Set uid/gid after binding the socket (Default: "") + -g --group=GROUP Set gid after binding the socket (Default: "") + + LOGGING: + -q --quiet Be quiet; emit only error messages + -s --syslog Send log message to syslog in addition to stderr/stdout + --syslog-facility=FACILITY Syslog facility to use (Default: "daemon") + + OTHER OPTIONS: + --daemon Fork into background and become a daemon (Default: off) + --write-ip Write 1 octet with the IP family followed by the IP + address in 4 (IPv4) or 16 (IPv6) octets little-endian + to backend before the actual data + (Default: off) + --write-proxy Write HaProxy's PROXY (IPv4 or IPv6) protocol line + before actual data + (Default: off) + --proxy-proxy Proxy HaProxy's PROXY (IPv4 or IPv6) protocol line + before actual data + (Default: off) + + -t --test Test configuration and exit + -V --version Print program version and exit + -h --help This help message + +Configuration File +------------------ + +Stud can also use a configuration file that supports all the same options as the +command-line arguments. You can use `stud --default-config` to +generate the default configuration on stdout; then, customize your configuration and +pass it to `stud --config=FILE`. + +Serving HTTPS +------------- + +If you're using `stud` for HTTPS, please make sure to use the `--ssl` option! + + +Diffie–Hellman +-------------- + +To use DH with stud, you will need to add some bytes to your pem file: + +% openssl dhparam -rand - 1024 >> PEMFILE + +Be sure to set your cipher suite appropriately: -c DHE-RSA-AES256-SHA + +Authors +------- + +`stud` was originally written by Jamie Turner (@jamwt) and is maintained +by the Bump (http://bu.mp) server team. It currently (12/11) provides +server-side TLS termination for over 85 million Bump users. + +Special thanks to Colin Percival (@cperciva) for an early security +audit and code review. + +Finally, thank you to all the stud contributors, who have taken the +program from a good start to a solid project: + +https://github.com/bumptech/stud/contributors diff --git a/hm_stud/cert/gen_cert.sh b/hm_stud/cert/gen_cert.sh new file mode 100644 index 0000000..3a76174 --- /dev/null +++ b/hm_stud/cert/gen_cert.sh @@ -0,0 +1,8 @@ +#!/bin/sh +openssl genrsa -out test.com.key 1024 +openssl req -new -key test.com.key -out test.com.csr +openssl x509 -req -days 365 -in test.com.csr -signkey test.com.key -out test.com.crt +cat test.com.key test.com.crt > openssl genrsa -out test.com.key 1024 +openssl req -new -key test.com.key -out test.com.csr +openssl x509 -req -days 365 -in test.com.csr -signkey test.com.key -out test.com.crt +cat test.com.key test.com.crt > test.com.pem diff --git a/hm_stud/configuration.c b/hm_stud/configuration.c new file mode 100644 index 0000000..d8c9908 --- /dev/null +++ b/hm_stud/configuration.c @@ -0,0 +1,1324 @@ +/** + * configuration.c + * + * Author: Brane F. Gracnar + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "configuration.h" +#include "version.h" + +#define ADDR_LEN 150 +#define PORT_LEN 6 +#define CFG_BOOL_ON "on" + +// BEGIN: configuration parameters +#define CFG_CIPHERS "ciphers" +#define CFG_SSL_ENGINE "ssl-engine" +#define CFG_PREFER_SERVER_CIPHERS "prefer-server-ciphers" +#define CFG_BACKEND "backend" +#define CFG_FRONTEND "frontend" +#define CFG_WORKERS "workers" +#define CFG_BACKLOG "backlog" +#define CFG_KEEPALIVE "keepalive" +#define CFG_CHROOT "chroot" +#define CFG_USER "user" +#define CFG_GROUP "group" +#define CFG_QUIET "quiet" +#define CFG_SYSLOG "syslog" +#define CFG_SYSLOG_FACILITY "syslog-facility" +#define CFG_PARAM_SYSLOG_FACILITY 11015 +#define CFG_DAEMON "daemon" +#define CFG_WRITE_IP "write-ip" +#define CFG_WRITE_PROXY "write-proxy" +#define CFG_PEM_FILE "pem-file" +#define CFG_PROXY_PROXY "proxy-proxy" + +#ifdef USE_SHARED_CACHE + #define CFG_SHARED_CACHE "shared-cache" + #define CFG_SHARED_CACHE_LISTEN "shared-cache-listen" + #define CFG_SHARED_CACHE_PEER "shared-cache-peer" + #define CFG_SHARED_CACHE_MCASTIF "shared-cache-if" +#endif + +#ifndef NO_CONFIG_FILE + #define FMT_STR "%s = %s\n" + #define FMT_QSTR "%s = \"%s\"\n" + #define FMT_ISTR "%s = %d\n" + + #define CONFIG_MAX_LINES 10000 + #define CONFIG_BUF_SIZE 1024 + #define CFG_PARAM_CFGFILE 10000 + #define CFG_PARAM_DEFCFG 10001 + + #define CFG_CONFIG "config" + #define CFG_CONFIG_DEFAULT "default-config" +#endif +// END: configuration parameters + +static char var_buf[CONFIG_BUF_SIZE]; +static char val_buf[CONFIG_BUF_SIZE]; +static char error_buf[CONFIG_BUF_SIZE]; +static char tmp_buf[150]; + +// for testing configuration only +#include +SSL_CTX * init_openssl(); + +static void config_error_set (char *fmt, ...) { + memset(error_buf, '\0', sizeof(error_buf)); + va_list args; + va_start(args, fmt); + vsnprintf(error_buf, (sizeof(error_buf) - 1), fmt, args); + va_end(args); +} + +char * config_error_get (void) { + return error_buf; +} + +void config_die (char *fmt, ...) { + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + + exit(1); +} + +stud_config * config_new (void) { + stud_config *r = NULL; + r = malloc(sizeof(stud_config)); + if (r == NULL) { + config_error_set("Unable to allocate memory for configuration structure: %s", strerror(errno)); + return NULL; + } + + // set default values + + r->ETYPE = ENC_TLS; + r->PMODE = SSL_SERVER; + r->WRITE_IP_OCTET = 0; + r->WRITE_PROXY_LINE = 0; + r->PROXY_PROXY_LINE = 0; + r->CHROOT = NULL; + r->UID = 0; + r->GID = 0; + r->FRONT_IP = NULL; + r->FRONT_PORT = strdup("1119"); + r->BACK_IP = strdup("127.0.0.1"); + r->BACK_PORT = strdup("45678"); + r->NCORES = 1; + r->CERT_FILES = NULL; + r->CIPHER_SUITE = NULL; + r->ENGINE = NULL; + r->BACKLOG = 100; + +#ifdef USE_SHARED_CACHE + r->SHARED_CACHE = 0; + r->SHCUPD_IP = NULL; + r->SHCUPD_PORT = NULL; + + for (int i = 0 ; i < MAX_SHCUPD_PEERS; i++) + memset(&r->SHCUPD_PEERS[i], 0, sizeof(shcupd_peer_opt)); + + r->SHCUPD_MCASTIF = NULL; + r->SHCUPD_MCASTTTL = NULL; +#endif + + r->QUIET = 0; + r->SYSLOG = 0; + r->SYSLOG_FACILITY = LOG_DAEMON; + r->TCP_KEEPALIVE_TIME = 3600; + r->DAEMONIZE = 1; + r->PREFER_SERVER_CIPHERS = 0; + + return r; +} + +void config_destroy (stud_config *cfg) { + // printf("config_destroy() in pid %d: %p\n", getpid(), cfg); + if (cfg == NULL) return; + + // free all members! + if (cfg->CHROOT != NULL) free(cfg->CHROOT); + if (cfg->FRONT_IP != NULL) free(cfg->FRONT_IP); + if (cfg->FRONT_PORT != NULL) free(cfg->FRONT_PORT); + if (cfg->BACK_IP != NULL) free(cfg->BACK_IP); + if (cfg->BACK_PORT != NULL) free(cfg->BACK_PORT); + if (cfg->CERT_FILES != NULL) { + struct cert_files *curr = cfg->CERT_FILES, *next; + while (cfg->CERT_FILES != NULL) { + next = curr->NEXT; + free(curr); + curr = next; + } + } + if (cfg->CIPHER_SUITE != NULL) free(cfg->CIPHER_SUITE); + if (cfg->ENGINE != NULL) free(cfg->ENGINE); + +#ifdef USE_SHARED_CACHE + if (cfg->SHCUPD_IP != NULL) free(cfg->SHCUPD_IP); + if (cfg->SHCUPD_PORT != NULL) free(cfg->SHCUPD_PORT); + + for (int i = 0; i < MAX_SHCUPD_PEERS; i++) { + if (cfg->SHCUPD_PEERS[i].ip != NULL) + free(cfg->SHCUPD_PEERS[i].ip); + if (cfg->SHCUPD_PEERS[i].port != NULL) + free(cfg->SHCUPD_PEERS[i].port); + } + + if (cfg->SHCUPD_MCASTIF != NULL) free(cfg->SHCUPD_MCASTIF); + if (cfg->SHCUPD_MCASTTTL != NULL) free(cfg->SHCUPD_MCASTTTL); +#endif + + free(cfg); +} + +char * config_get_param (char *str) { + char *ptr; + int i; + + if (str == NULL) return NULL; + /** empty string? */ + if (strlen(str) < 1 || str[0] == '\n' || strcmp(str, "\r\n") == 0) return NULL; + + ptr = str; + + /** comments? */ + if (str[0] == '#') return NULL; + /** first alpha character */ + while (ptr != NULL && ! isalpha(*ptr)) + ptr++; + + /** overwrite alpha chars */ + memset(var_buf, '\0', sizeof(var_buf)); + i = 0; + while(ptr != NULL && (isalnum(*ptr) || *ptr == '-')) { + var_buf[i] = *ptr; + i++; + ptr++; + } + + if (strlen(var_buf) < 1) return NULL; + return var_buf; +} + +char * config_get_value (char *str) { + char *ptr; + int i = 0; + + if (str == NULL) return NULL; + if (strlen(str) < 1) return NULL; + + /** find '=' char */ + ptr = str; + while (ptr != NULL && (*ptr) != '=') + ptr++; + ptr++; + + /** skip whitespaces **/ + while (ptr != NULL && ! isgraph(*ptr)) + ptr++; + + /** no value found? */ + if (ptr == NULL) return NULL; + + /** overwrite alpha chars */ + memset(val_buf, '\0', sizeof(val_buf)); + while(ptr != NULL && isgraph(*ptr)) { + val_buf[i++] = *ptr; + ptr++; + } + + if (strlen(val_buf) < 1) return NULL; + return val_buf; +} + +char * str_rtrim(char *str) { + char *ptr; + int len; + + len = strlen(str); + ptr = str + len - 1; + while (ptr >= str && (isspace((int)*ptr ) || (char) *ptr == '"' || (char) *ptr == '\'')) --ptr; + + ptr[1] = '\0'; + + return str; +} + +char * str_ltrim(char *str) { + char *ptr; + int len; + + for (ptr = str; (*ptr && (isspace((int)*ptr) || (char) *ptr == '"' || (char) *ptr == '\'')); ++ptr); + + len = strlen(ptr); + memmove(str, ptr, len + 1); + + return str; +} + +char * str_trim(char *str) { + char *ptr; + ptr = str_rtrim(str); + str = str_ltrim(ptr); + return str; +} + +char * config_assign_str (char **dst, char *v) { + if (*dst == NULL) { + if (v != NULL && strlen(v) > 0) + *dst = strdup(v); + } else { + if (v != NULL && strlen(v) > 0) { + // we assume that there is enough room for v in *dst + memset(*dst, '\0', strlen(v) + 1); + memcpy(*dst, v, strlen(v)); + } + else + free(*dst); + } + return *dst; +} + +int config_param_val_bool (char *val, int *res) { + if (val == NULL) return 0; + if ( + strcasecmp(val, CFG_BOOL_ON) == 0 || + strcasecmp(val, "yes") == 0 || + strcasecmp(val, "y") == 0 || + strcasecmp(val, "true") == 0 || + strcasecmp(val, "t") == 0 || + strcasecmp(val, "1") == 0) { + *res = 1; + } + + return 1; +} + +char * config_param_val_str (char *val) { + return strdup(val); +} + +int config_param_host_port_wildcard (char *str, char **addr, char **port, int wildcard_okay) { + int len = (str != NULL) ? strlen(str) : 0; + if (str == NULL || ! len) { + config_error_set("Invalid/unset host/port string."); + return 0; + } + + // address/port buffers + char port_buf[PORT_LEN]; + char addr_buf[ADDR_LEN]; + + memset(port_buf, '\0', sizeof(port_buf)); + memset(addr_buf, '\0', sizeof(addr_buf)); + + // NEW FORMAT: [address]:port + if (*str == '[') { + char *ptr = str + 1; + char *x = strrchr(ptr, ']'); + if (x == NULL) { + config_error_set("Invalid address '%s'.", str); + return 0; + } + + // address + memcpy(addr_buf, ptr, (x - ptr)); + + // port + x += 2; + memcpy(port_buf, x, sizeof(port_buf) - 1); + } + // OLD FORMAT: address,port + else { + char *x = strrchr(str, ','); + if (x == NULL) { + config_error_set("Invalid address string '%s'", str); + return 0; + } + // addr + int addr_len = x - str; + memcpy(addr_buf, str, addr_len); + // port + memcpy(port_buf, (++x), sizeof(port_buf)); + } + + // printf("PARSED ADDR '%s', PORT '%s'\n", addr_buf, port_buf); + + // check port + int p = atoi(port_buf); + if (p < 1 || p > 65536) { + config_error_set("Invalid port number '%s'", port_buf); + return 0; + } + + // write + if (strcmp(addr_buf, "*") == 0) { + if (wildcard_okay) + free(*addr); + else { + config_error_set("Invalid address: wildcards are not allowed."); + return 0; + } + } else { + //if (*addr != NULL) free(*addr); + *addr = strdup(addr_buf); + } + // if (**port != NULL) free(*port); + *port = strdup(port_buf); + + // printf("ADDR FINAL: '%s', '%s'\n", *addr, *port); + + return 1; +} + +int config_param_host_port (char *str, char **addr, char **port) { + return config_param_host_port_wildcard(str, addr, port, 0); +} + +int config_param_val_int (char *str, int *dst) { + *dst = (str != NULL) ? atoi(str) : 0; + return 1; +} + +int config_param_val_int_pos (char *str, int *dst) { + int num = 0; + if (str != NULL) + num = atoi(str); + + if (num < 1) { + config_error_set("Not a positive number."); + return 0; + } + + *dst = num; + return 1; +} + +int config_param_val_intl (char *str, long int *dst) { + *dst = (str != NULL) ? atol(str) : 0; + return 1; +} + +int config_param_val_intl_pos (char *str, long int *dst) { + long int num = 0; + if (str != NULL) + num = atol(str); + + if (num < 1) { + config_error_set("Not a positive number."); + return 0; + } + + *dst = num; + return 1; +} + +#ifdef USE_SHARED_CACHE +/* Parse mcast and ttl options */ +int config_param_shcupd_mcastif (char *str, char **iface, char **ttl) { + char buf[150]; + char *sp; + + if (strlen(str) >= sizeof buf) { + config_error_set("Invalid option for IFACE[,TTL]"); + return 0; + } + + sp = strchr(str, ','); + if (!sp) { + if (!strcmp(str, "*")) + *iface = NULL; + else + *iface = str; + *ttl = NULL; + return 1; + } + else if (!strncmp(str, "*", sp - str)) { + *iface = NULL; + } + else { + *sp = 0; + *iface = str; + } + *ttl = sp + 1; + + return 1; +} + +int config_param_shcupd_peer (char *str, stud_config *cfg) { + if (cfg == NULL) { + config_error_set("Configuration pointer is NULL."); + return 0; + } + + // parse result + int r = 1; + + // find place for new peer + int offset = 0; + int i = 0; + for (i = 0; i < MAX_SHCUPD_PEERS; i++) { + if (cfg->SHCUPD_PEERS[i].ip == NULL && cfg->SHCUPD_PEERS[i].port == NULL) { + offset = i; + break; + } + } + if (i >= MAX_SHCUPD_PEERS) { + config_error_set( + "Reached maximum number of shared cache update peers (%d).", + MAX_SHCUPD_PEERS + ); + return 0; + } + + // create place for new peer + char *addr = malloc(ADDR_LEN); + if (addr == NULL) { + config_error_set( + "Unable to allocate memory for new shared cache update peer address: %s", + strerror(errno) + ); + r = 0; + goto outta_parse_peer; + } + memset(addr, '\0', ADDR_LEN); + char *port = malloc(PORT_LEN); + if (port == NULL) { + config_error_set( + "Unable to allocate memory for new shared cache update peer port: %s", + strerror(errno) + ); + r = 0; + goto outta_parse_peer; + } + memset(port, '\0', PORT_LEN); + + // try to parse address + if (! config_param_host_port(str, &addr, &port)) { + r = 0; + goto outta_parse_peer; + } + + outta_parse_peer: + + if (! r) { + if (addr != NULL) free(addr); + if (port != NULL) free(port); + } else { + cfg->SHCUPD_PEERS[offset].ip = addr; + cfg->SHCUPD_PEERS[offset].port = port; + } + + return r; +} + +#endif /* USE_SHARED_CACHE */ + +void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int line) { + int r = 1; + struct stat st; + + if (strcmp(k, "tls") == 0) { + cfg->ETYPE = ENC_TLS; + } + else if (strcmp(k, "ssl") == 0) { + cfg->ETYPE = ENC_SSL; + } + else if (strcmp(k, CFG_CIPHERS) == 0) { + if (v != NULL && strlen(v) > 0) { + config_assign_str(&cfg->CIPHER_SUITE, v); + } + } + else if (strcmp(k, CFG_SSL_ENGINE) == 0) { + if (v != NULL && strlen(v) > 0) { + config_assign_str(&cfg->ENGINE, v); + } + } + else if (strcmp(k, CFG_PREFER_SERVER_CIPHERS) == 0) { + r = config_param_val_bool(v, &cfg->PREFER_SERVER_CIPHERS); + } + else if (strcmp(k, CFG_FRONTEND) == 0) { + r = config_param_host_port_wildcard(v, &cfg->FRONT_IP, &cfg->FRONT_PORT, 1); + } + else if (strcmp(k, CFG_BACKEND) == 0) { + r = config_param_host_port(v, &cfg->BACK_IP, &cfg->BACK_PORT); + } + else if (strcmp(k, CFG_WORKERS) == 0) { + r = config_param_val_intl_pos(v, &cfg->NCORES); + } + else if (strcmp(k, CFG_BACKLOG) == 0) { + r = config_param_val_int(v, &cfg->BACKLOG); + if (r && cfg->BACKLOG < -1) cfg->BACKLOG = -1; + } + else if (strcmp(k, CFG_KEEPALIVE) == 0) { + r = config_param_val_int_pos(v, &cfg->TCP_KEEPALIVE_TIME); + } +#ifdef USE_SHARED_CACHE + else if (strcmp(k, CFG_SHARED_CACHE) == 0) { + r = config_param_val_int(v, &cfg->SHARED_CACHE); + } + else if (strcmp(k, CFG_SHARED_CACHE_LISTEN) == 0) { + if (v != NULL && strlen(v) > 0) + r = config_param_host_port_wildcard(v, &cfg->SHCUPD_IP, &cfg->SHCUPD_PORT, 1); + } + else if (strcmp(k, CFG_SHARED_CACHE_PEER) == 0) { + r = config_param_shcupd_peer(v, cfg); + } + else if (strcmp(k, CFG_SHARED_CACHE_MCASTIF) == 0) { + r = config_param_shcupd_mcastif(v, &cfg->SHCUPD_MCASTIF, &cfg->SHCUPD_MCASTTTL); + } +#endif + else if (strcmp(k, CFG_CHROOT) == 0) { + if (v != NULL && strlen(v) > 0) { + // check directory + if (stat(v, &st) != 0) { + config_error_set("Unable to stat directory '%s': %s'.", v, strerror(errno)); + r = 0; + } else { + if (! S_ISDIR(st.st_mode)) { + config_error_set("Bad chroot directory '%s': Not a directory.", v, strerror(errno)); + r = 0; + } else { + config_assign_str(&cfg->CHROOT, v); + } + } + } + } + else if (strcmp(k, CFG_USER) == 0) { + if (v != NULL && strlen(v) > 0) { + struct passwd *passwd; + passwd = getpwnam(v); + if (!passwd) { + config_error_set("Invalid user '%s'.", v); + r = 0; + } else { + cfg->UID = passwd->pw_uid; + cfg->GID = passwd->pw_gid; + } + } + } + else if (strcmp(k, CFG_GROUP) == 0) { + if (v != NULL && strlen(v) > 0) { + struct group *grp; + grp = getgrnam(v); + if (!grp) { + config_error_set("Invalid group '%s'.", v); + r = 0; + } else { + cfg->GID = grp->gr_gid; + } + } + } + else if (strcmp(k, CFG_QUIET) == 0) { + r = config_param_val_bool(v, &cfg->QUIET); + } + else if (strcmp(k, CFG_SYSLOG) == 0) { + r = config_param_val_bool(v, &cfg->SYSLOG); + } + else if (strcmp(k, CFG_SYSLOG_FACILITY) == 0) { + r = 1; + if (!strcmp(v, "auth") || !strcmp(v, "authpriv")) + cfg->SYSLOG_FACILITY = LOG_AUTHPRIV; + else if (!strcmp(v, "cron")) + cfg->SYSLOG_FACILITY = LOG_CRON; + else if (!strcmp(v, "daemon")) + cfg->SYSLOG_FACILITY = LOG_DAEMON; + else if (!strcmp(v, "ftp")) + cfg->SYSLOG_FACILITY = LOG_FTP; + else if (!strcmp(v, "local0")) + cfg->SYSLOG_FACILITY = LOG_LOCAL0; + else if (!strcmp(v, "local1")) + cfg->SYSLOG_FACILITY = LOG_LOCAL1; + else if (!strcmp(v, "local2")) + cfg->SYSLOG_FACILITY = LOG_LOCAL2; + else if (!strcmp(v, "local3")) + cfg->SYSLOG_FACILITY = LOG_LOCAL3; + else if (!strcmp(v, "local4")) + cfg->SYSLOG_FACILITY = LOG_LOCAL4; + else if (!strcmp(v, "local5")) + cfg->SYSLOG_FACILITY = LOG_LOCAL5; + else if (!strcmp(v, "local6")) + cfg->SYSLOG_FACILITY = LOG_LOCAL6; + else if (!strcmp(v, "local7")) + cfg->SYSLOG_FACILITY = LOG_LOCAL7; + else if (!strcmp(v, "lpr")) + cfg->SYSLOG_FACILITY = LOG_LPR; + else if (!strcmp(v, "mail")) + cfg->SYSLOG_FACILITY = LOG_MAIL; + else if (!strcmp(v, "news")) + cfg->SYSLOG_FACILITY = LOG_NEWS; + else if (!strcmp(v, "user")) + cfg->SYSLOG_FACILITY = LOG_USER; + else if (!strcmp(v, "uucp")) + cfg->SYSLOG_FACILITY = LOG_UUCP; + else { + config_error_set("Invalid facility '%s'.", v); + r = 0; + } + } + else if (strcmp(k, CFG_DAEMON) == 0) { + r = config_param_val_bool(v, &cfg->DAEMONIZE); + } + else if (strcmp(k, CFG_WRITE_IP) == 0) { + r = config_param_val_bool(v, &cfg->WRITE_IP_OCTET); + } + else if (strcmp(k, CFG_WRITE_PROXY) == 0) { + r = config_param_val_bool(v, &cfg->WRITE_PROXY_LINE); + } + else if (strcmp(k, CFG_PROXY_PROXY) == 0) { + r = config_param_val_bool(v, &cfg->PROXY_PROXY_LINE); + } + else if (strcmp(k, CFG_PEM_FILE) == 0) { + if (v != NULL && strlen(v) > 0) { + if (stat(v, &st) != 0) { + config_error_set("Unable to stat x509 certificate PEM file '%s': ", v, strerror(errno)); + r = 0; + } + else if (! S_ISREG(st.st_mode)) { + config_error_set("Invalid x509 certificate PEM file '%s': Not a file.", v); + r = 0; + } else { + struct cert_files *cert = calloc(1, sizeof(*cert)); + config_assign_str(&cert->CERT_FILE, v); + cert->NEXT = cfg->CERT_FILES; + cfg->CERT_FILES = cert; + } + } + } + else { + fprintf( + stderr, + "Ignoring unknown configuration key '%s' in configuration file '%s', line %d\n", + k, file, line + ); + } + + if (! r) { + if (file != NULL) + config_die("Error in configuration file '%s', line %d: %s\n", file, line, config_error_get()); + else + config_die("Invalid parameter '%s': %s", k, config_error_get()); + } +} + +#ifndef NO_CONFIG_FILE +int config_file_parse (char *file, stud_config *cfg) { + if (cfg == NULL) + config_die("Undefined stud options; THIS IS A BUG!\n"); + + char line[CONFIG_BUF_SIZE]; + FILE *fd = NULL; + + // should we read stdin? + if (file == NULL || strlen(file) < 1 || strcmp(file, "-") == 0) { + fd = stdin; + } else { + fd = fopen(file, "r"); + } + if (fd == NULL) + config_die("Unable to open configuration file '%s': %s\n", file, strerror(errno)); + + // read config + int i = 0; + while (i < CONFIG_MAX_LINES) { + memset(line, '\0', sizeof(line)); + if (fgets(line, (sizeof(line) - 1), fd) == NULL) break; + i++; + + // get configuration key + char *key, *val; + key = config_get_param(line); + if (key == NULL) continue; + + // get configuration key value... + val = config_get_value(line); + if (val == NULL) continue; + str_trim(val); + + // printf("File '%s', line %d, key: '%s', value: '%s'\n", file, i, key, val); + + // validate configuration key => value + config_param_validate(key, val, cfg, file, i); + } + + fclose(fd); + + return 1; +} +#endif /* NO_CONFIG_FILE */ + +char * config_disp_str (char *str) { + return (str == NULL) ? "" : str; +} + +char * config_disp_bool (int v) { + return (v > 0) ? CFG_BOOL_ON : "off"; +} + +char * config_disp_uid (uid_t uid) { + memset(tmp_buf, '\0', sizeof(tmp_buf)); + if (uid == 0 && geteuid() != 0) return tmp_buf; + struct passwd *pw = getpwuid(uid); + if (pw) { + memcpy(tmp_buf, pw->pw_name, strlen(pw->pw_name)); + } + return tmp_buf; +} + +char * config_disp_gid (gid_t gid) { + memset(tmp_buf, '\0', sizeof(tmp_buf)); + if (gid == 0 && geteuid() != 0) return tmp_buf; + struct group *gr = getgrgid(gid); + if (gr) { + memcpy(tmp_buf, gr->gr_name, strlen(gr->gr_name)); + } + return tmp_buf; +} + +char * config_disp_hostport (char *host, char *port) { + memset(tmp_buf, '\0', sizeof(tmp_buf)); + if (host == NULL && port == NULL) + return ""; + + strcat(tmp_buf, "["); + if (host == NULL) + strcat(tmp_buf, "*"); + else { + strncat(tmp_buf, host, 40); + } + strcat(tmp_buf, "]:"); + strncat(tmp_buf, port, 5); + return tmp_buf; +} + +const char * config_disp_log_facility (int facility) { + switch (facility) + { + case LOG_AUTHPRIV: + return "authpriv"; + case LOG_CRON: + return "cron"; + case LOG_DAEMON: + return "daemon"; + case LOG_FTP: + return "ftp"; + case LOG_LOCAL0: + return "local0"; + case LOG_LOCAL1: + return "local1"; + case LOG_LOCAL2: + return "local2"; + case LOG_LOCAL3: + return "local3"; + case LOG_LOCAL4: + return "local4"; + case LOG_LOCAL5: + return "local5"; + case LOG_LOCAL6: + return "local6"; + case LOG_LOCAL7: + return "local7"; + case LOG_LPR: + return "lpr"; + case LOG_MAIL: + return "mail"; + case LOG_NEWS: + return "news"; + case LOG_USER: + return "user"; + case LOG_UUCP: + return "uucp"; + default: + return "UNKNOWN"; + } +} + +void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) { + if (out == NULL) out = stderr; + fprintf(out, "Usage: %s [OPTIONS] PEM\n\n", basename(prog)); + fprintf(out, "This is stud, The Scalable TLS Unwrapping Daemon.\n\n"); +#ifndef NO_CONFIG_FILE + fprintf(out, "CONFIGURATION:\n"); + fprintf(out, "\n"); + fprintf(out, " --config=FILE Load configuration from specified file.\n"); + fprintf(out, " --default-config Prints default configuration to stdout.\n"); + fprintf(out, "\n"); +#endif + fprintf(out, "ENCRYPTION METHODS:\n"); + fprintf(out, "\n"); + fprintf(out, " --tls TLSv1 (default)\n"); + fprintf(out, " --ssl SSLv3 (implies no TLSv1)\n"); + fprintf(out, " -c --ciphers=SUITE Sets allowed ciphers (Default: \"%s\")\n", config_disp_str(cfg->CIPHER_SUITE)); + fprintf(out, " -e --ssl-engine=NAME Sets OpenSSL engine (Default: \"%s\")\n", config_disp_str(cfg->ENGINE)); + fprintf(out, " -O --prefer-server-ciphers Prefer server list order\n"); + fprintf(out, "\n"); + fprintf(out, "SOCKET:\n"); + fprintf(out, "\n"); + fprintf(out, " --client Enable client proxy mode\n"); + fprintf(out, " -b --backend=HOST,PORT Backend [connect] (default is \"%s\")\n", config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT)); + fprintf(out, " -f --frontend=HOST,PORT Frontend [bind] (default is \"%s\")\n", config_disp_hostport(cfg->FRONT_IP, cfg->FRONT_PORT)); + +#ifdef USE_SHARED_CACHE + fprintf(out, "\n"); + fprintf(out, " -U --shared-cache-listen=HOST,PORT\n"); + fprintf(out, " Accept cache updates on UDP (Default: \"%s\")\n", config_disp_hostport(cfg->SHCUPD_IP, cfg->SHCUPD_PORT)); + fprintf(out, " NOTE: This option requires enabled SSL session cache.\n"); + fprintf(out, " -P --shared-cache-peer=HOST,PORT\n"); + fprintf(out, " Send cache updates to specified peer\n"); + fprintf(out, " NOTE: This option can be specified multiple times.\n"); + fprintf(out, " -M --shared-cache-if=IFACE[,TTL]\n"); + fprintf(out, " Force iface and ttl to receive and send multicast updates\n"); +#endif + + fprintf(out, "\n"); + fprintf(out, "PERFORMANCE:\n"); + fprintf(out, "\n"); + fprintf(out, " -n --workers=NUM Number of worker processes (Default: %ld)\n", cfg->NCORES); + fprintf(out, " -B --backlog=NUM Set listen backlog size (Default: %d)\n", cfg->BACKLOG); + fprintf(out, " -k --keepalive=SECS TCP keepalive on client socket (Default: %d)\n", cfg->TCP_KEEPALIVE_TIME); + +#ifdef USE_SHARED_CACHE + fprintf(out, " -C --session-cache=NUM Enable and set SSL session cache to specified number\n"); + fprintf(out, " of sessions (Default: %d)\n", cfg->SHARED_CACHE); +#endif + + fprintf(out, "\n"); + fprintf(out, "SECURITY:\n"); + fprintf(out, "\n"); + fprintf(out, " -r --chroot=DIR Sets chroot directory (Default: \"%s\")\n", config_disp_str(cfg->CHROOT)); + fprintf(out, " -u --user=USER Set uid/gid after binding the socket (Default: \"%s\")\n", config_disp_uid(cfg->UID)); + fprintf(out, " -g --group=GROUP Set gid after binding the socket (Default: \"%s\")\n", config_disp_gid(cfg->GID)); + fprintf(out, "\n"); + fprintf(out, "LOGGING:\n"); + fprintf(out, " -q --quiet Be quiet; emit only error messages\n"); + fprintf(out, " -s --syslog Send log message to syslog in addition to stderr/stdout\n"); + fprintf(out, " --syslog-facility=FACILITY Syslog facility to use (Default: \"%s\")\n", config_disp_log_facility(cfg->SYSLOG_FACILITY)); + fprintf(out, "\n"); + fprintf(out, "OTHER OPTIONS:\n"); + fprintf(out, " --daemon Fork into background and become a daemon (Default: %s)\n", config_disp_bool(cfg->DAEMONIZE)); + fprintf(out, " --write-ip Write 1 octet with the IP family followed by the IP\n"); + fprintf(out, " address in 4 (IPv4) or 16 (IPv6) octets little-endian\n"); + fprintf(out, " to backend before the actual data\n"); + fprintf(out, " (Default: %s)\n", config_disp_bool(cfg->WRITE_IP_OCTET)); + fprintf(out, " --write-proxy Write HaProxy's PROXY (IPv4 or IPv6) protocol line\n" ); + fprintf(out, " before actual data\n"); + fprintf(out, " (Default: %s)\n", config_disp_bool(cfg->WRITE_PROXY_LINE)); + fprintf(out, " --proxy-proxy Proxy HaProxy's PROXY (IPv4 or IPv6) protocol line\n" ); + fprintf(out, " before actual data\n"); + fprintf(out, " (Default: %s)\n", config_disp_bool(cfg->PROXY_PROXY_LINE)); + fprintf(out, "\n"); + fprintf(out, " -t --test Test configuration and exit\n"); + fprintf(out, " -V --version Print program version and exit\n"); + fprintf(out, " -h --help This help message\n"); +} + +#ifndef NO_CONFIG_FILE +void config_print_default (FILE *fd, stud_config *cfg) { + if (fd == NULL) return; + fprintf(fd, "#\n"); + fprintf(fd, "# stud(8), The Scalable TLS Unwrapping Daemon's configuration\n"); + fprintf(fd, "#\n"); + fprintf(fd, "\n"); + fprintf(fd, "# NOTE: all config file parameters can be overriden\n"); + fprintf(fd, "# from command line!\n"); + fprintf(fd, "\n"); + + fprintf(fd, "# Listening address. REQUIRED.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, "# syntax: [HOST]:PORT\n"); + fprintf(fd, FMT_QSTR, CFG_FRONTEND, config_disp_hostport(cfg->FRONT_IP, cfg->FRONT_PORT)); + fprintf(fd, "\n"); + + fprintf(fd, "# Upstream server address. REQUIRED.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, "# syntax: [HOST]:PORT.\n"); + fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT)); + fprintf(fd, "\n"); + + fprintf(fd, "# SSL x509 certificate file. REQUIRED.\n"); + fprintf(fd, "# List multiple certs to use SNI. Certs are used in the order they\n"); + fprintf(fd, "# are listed; the last cert listed will be used if none of the others match\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_PEM_FILE, ""); + fprintf(fd, "\n"); + + fprintf(fd, "# SSL protocol.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# tls = on\n"); + fprintf(fd, "# ssl = off\n"); + fprintf(fd, "\n"); + + fprintf(fd, "# List of allowed SSL ciphers.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# Run openssl ciphers for list of available ciphers.\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_CIPHERS, config_disp_str(cfg->CIPHER_SUITE)); + fprintf(fd, "\n"); + + fprintf(fd, "# Enforce server cipher list order\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_PREFER_SERVER_CIPHERS, config_disp_bool(cfg->PREFER_SERVER_CIPHERS)); + fprintf(fd, "\n"); + + fprintf(fd, "# Use specified SSL engine\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_SSL_ENGINE, config_disp_str(cfg->ENGINE)); + fprintf(fd, "\n"); + + fprintf(fd, "# Number of worker processes\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: integer\n"); + fprintf(fd, FMT_ISTR, CFG_WORKERS, (int) cfg->NCORES); + fprintf(fd, "\n"); + + fprintf(fd, "# Listen backlog size\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: integer\n"); + fprintf(fd, FMT_ISTR, CFG_BACKLOG, cfg->BACKLOG); + fprintf(fd, "\n"); + + fprintf(fd, "# TCP socket keepalive interval in seconds\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: integer\n"); + fprintf(fd, FMT_ISTR, CFG_KEEPALIVE, cfg->TCP_KEEPALIVE_TIME); + fprintf(fd, "\n"); + +#ifdef USE_SHARED_CACHE + fprintf(fd, "# SSL session cache size\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: integer\n"); + fprintf(fd, FMT_ISTR, CFG_SHARED_CACHE, cfg->SHARED_CACHE); + fprintf(fd, "\n"); + + fprintf(fd, "# Accept shared SSL cache updates on specified listener.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, "# syntax: [HOST]:PORT\n"); + fprintf(fd, FMT_QSTR, CFG_SHARED_CACHE_LISTEN, config_disp_hostport(cfg->SHCUPD_IP, cfg->SHCUPD_PORT)); + fprintf(fd, "\n"); + + fprintf(fd, "# Shared cache peer address.\n"); + fprintf(fd, "# Multiple stud processes on multiple hosts (host limit: %d)\n", MAX_SHCUPD_PEERS); + fprintf(fd, "# can share SSL session cache by sending updates to peers.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# NOTE: This parameter can be specified multiple times in order\n"); + fprintf(fd, "# to specify multiple peers.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, "# syntax: [HOST]:PORT\n"); + fprintf(fd, "# " FMT_QSTR, CFG_SHARED_CACHE_PEER, config_disp_hostport(NULL, NULL)); + for (int i = 0; i < MAX_SHCUPD_PEERS; i++) { + if (cfg->SHCUPD_PEERS[i].ip == NULL && cfg->SHCUPD_PEERS[i].port == NULL) break; + fprintf(fd, FMT_QSTR, CFG_SHARED_CACHE_PEER, config_disp_hostport(cfg->SHCUPD_PEERS[i].ip, cfg->SHCUPD_PEERS[i].port)); + } + fprintf(fd, "\n"); + + fprintf(fd, "# Shared cache interface name and optional TTL\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, "# syntax: iface[,TTL]\n"); + fprintf(fd, "# %s = \"%s", CFG_SHARED_CACHE_MCASTIF, config_disp_str(cfg->SHCUPD_MCASTIF)); + if (cfg->SHCUPD_MCASTTTL != NULL && strlen(cfg->SHCUPD_MCASTTTL) > 0) { + fprintf(fd, ",%s", cfg->SHCUPD_MCASTTTL); + } + fprintf(fd, "\"\n"); + fprintf(fd, "\n"); +#endif + + fprintf(fd, "# Chroot directory\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_CHROOT, config_disp_str(cfg->CHROOT)); + fprintf(fd, "\n"); + + fprintf(fd, "# Set uid after binding a socket\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_USER, config_disp_uid(cfg->UID)); + fprintf(fd, "\n"); + + fprintf(fd, "# Set gid after binding a socket\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_GROUP, config_disp_gid(cfg->GID)); + fprintf(fd, "\n"); + + fprintf(fd, "# Quiet execution, report only error messages\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_QUIET, config_disp_bool(cfg->QUIET)); + fprintf(fd, "\n"); + + fprintf(fd, "# Use syslog for logging\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_SYSLOG, config_disp_bool(cfg->SYSLOG)); + fprintf(fd, "\n"); + + fprintf(fd, "# Syslog facility to use\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: string\n"); + fprintf(fd, FMT_QSTR, CFG_SYSLOG_FACILITY, config_disp_log_facility(cfg->SYSLOG_FACILITY)); + fprintf(fd, "\n"); + + fprintf(fd, "# Run as daemon\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_DAEMON, config_disp_bool(cfg->DAEMONIZE)); + fprintf(fd, "\n"); + + fprintf(fd, "# Report client address by writing IP before sending data\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# NOTE: This option is mutually exclusive with option %s and %s.\n", CFG_WRITE_PROXY, CFG_PROXY_PROXY); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_WRITE_IP, config_disp_bool(cfg->WRITE_IP_OCTET)); + fprintf(fd, "\n"); + + fprintf(fd, "# Report client address using SENDPROXY protocol, see\n"); + fprintf(fd, "# http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt\n"); + fprintf(fd, "# for details.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# NOTE: This option is mutually exclusive with option %s and %s.\n", CFG_WRITE_IP, CFG_PROXY_PROXY); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_WRITE_PROXY, config_disp_bool(cfg->WRITE_PROXY_LINE)); + fprintf(fd, "\n"); + + fprintf(fd, "# Proxy an existing SENDPROXY protocol header through this request.\n"); + fprintf(fd, "#\n"); + fprintf(fd, "# NOTE: This option is mutually exclusive with option %s and %s.\n", CFG_WRITE_IP, CFG_WRITE_PROXY); + fprintf(fd, "#\n"); + fprintf(fd, "# type: boolean\n"); + fprintf(fd, FMT_STR, CFG_PROXY_PROXY, config_disp_bool(cfg->PROXY_PROXY_LINE)); + fprintf(fd, "\n"); + + fprintf(fd, "# EOF\n"); +} +#endif /* NO_CONFIG_FILE */ + +void config_print_usage (char *prog, stud_config *cfg) { + config_print_usage_fd(prog, cfg, stdout); +} + +void config_parse_cli(int argc, char **argv, stud_config *cfg) { + static int tls = 0, ssl = 0; + static int client = 0; + int c, i; + int test_only = 0; + char *prog; + + struct option long_options[] = { +#ifndef NO_CONFIG_FILE + { CFG_CONFIG, 1, NULL, CFG_PARAM_CFGFILE }, + { CFG_CONFIG_DEFAULT, 0, NULL, CFG_PARAM_DEFCFG }, +#endif + + { "tls", 0, &tls, 1}, + { "ssl", 0, &ssl, 1}, + { "client", 0, &client, 1}, + { CFG_CIPHERS, 1, NULL, 'c' }, + { CFG_PREFER_SERVER_CIPHERS, 0, NULL, 'O' }, + { CFG_BACKEND, 1, NULL, 'b' }, + { CFG_FRONTEND, 1, NULL, 'f' }, + { CFG_WORKERS, 1, NULL, 'n' }, + { CFG_BACKLOG, 1, NULL, 'B' }, +#ifdef USE_SHARED_CACHE + { CFG_SHARED_CACHE, 1, NULL, 'C' }, + { CFG_SHARED_CACHE_LISTEN, 1, NULL, 'U' }, + { CFG_SHARED_CACHE_PEER, 1, NULL, 'P' }, + { CFG_SHARED_CACHE_MCASTIF, 1, NULL, 'M' }, +#endif + { CFG_KEEPALIVE, 1, NULL, 'k' }, + { CFG_CHROOT, 1, NULL, 'r' }, + { CFG_USER, 1, NULL, 'u' }, + { CFG_GROUP, 1, NULL, 'g' }, + { CFG_QUIET, 0, NULL, 'q' }, + { CFG_SYSLOG, 0, NULL, 's' }, + { CFG_SYSLOG_FACILITY, 1, NULL, CFG_PARAM_SYSLOG_FACILITY }, + { CFG_DAEMON, 0, &cfg->DAEMONIZE, 1 }, + { CFG_WRITE_IP, 0, &cfg->WRITE_IP_OCTET, 1 }, + { CFG_WRITE_PROXY, 0, &cfg->WRITE_PROXY_LINE, 1 }, + { CFG_PROXY_PROXY, 0, &cfg->PROXY_PROXY_LINE, 1 }, + + { "test", 0, NULL, 't' }, + { "version", 0, NULL, 'V' }, + { "help", 0, NULL, 'h' }, + { 0, 0, 0, 0 } + }; + + while (1) { + int option_index = 0; + c = getopt_long( + argc, argv, + "c:e:Ob:f:n:B:C:U:P:M:k:r:u:g:qstVh", + long_options, &option_index + ); + + if (c == -1) + break; + + switch (c) { + case 0: + break; +#ifndef NO_CONFIG_FILE + case CFG_PARAM_CFGFILE: + if (!config_file_parse(optarg, cfg)) + config_die("%s", config_error_get()); + break; + case CFG_PARAM_DEFCFG: + config_print_default(stdout, cfg); + exit(0); + break; +#endif + case CFG_PARAM_SYSLOG_FACILITY: + config_param_validate(CFG_SYSLOG_FACILITY, optarg, cfg, NULL, 0); + break; + case 'c': + config_param_validate(CFG_CIPHERS, optarg, cfg, NULL, 0); + break; + case 'e': + config_param_validate(CFG_SSL_ENGINE, optarg, cfg, NULL, 0); + break; + case 'O': + config_param_validate(CFG_PREFER_SERVER_CIPHERS, CFG_BOOL_ON, cfg, NULL, 0); + break; + case 'b': + config_param_validate(CFG_BACKEND, optarg, cfg, NULL, 0); + break; + case 'f': + config_param_validate(CFG_FRONTEND, optarg, cfg, NULL, 0); + break; + case 'n': + config_param_validate(CFG_WORKERS, optarg, cfg, NULL, 0); + break; + case 'B': + config_param_validate(CFG_BACKLOG, optarg, cfg, NULL, 0); + break; +#ifdef USE_SHARED_CACHE + case 'C': + config_param_validate(CFG_SHARED_CACHE, optarg, cfg, NULL, 0); + break; + case 'U': + config_param_validate(CFG_SHARED_CACHE_LISTEN, optarg, cfg, NULL, 0); + break; + case 'P': + config_param_validate(CFG_SHARED_CACHE_PEER, optarg, cfg, NULL, 0); + break; + case 'M': + config_param_validate(CFG_SHARED_CACHE_MCASTIF, optarg, cfg, NULL, 0); + break; +#endif + case 'k': + config_param_validate(CFG_KEEPALIVE, optarg, cfg, NULL, 0); + break; + case 'r': + config_param_validate(CFG_CHROOT, optarg, cfg, NULL, 0); + break; + case 'u': + config_param_validate(CFG_USER, optarg, cfg, NULL, 0); + break; + case 'g': + config_param_validate(CFG_GROUP, optarg, cfg, NULL, 0); + break; + case 'q': + config_param_validate(CFG_QUIET, CFG_BOOL_ON, cfg, NULL, 0); + break; + case 's': + config_param_validate(CFG_SYSLOG, CFG_BOOL_ON, cfg, NULL, 0); + break; + case 't': + test_only = 1; + break; + case 'V': + printf("%s %s\n", basename(argv[0]), STUD_VERSION); + exit(0); + break; + case 'h': + config_print_usage(argv[0], cfg); + exit(0); + break; + + default: + config_die("Invalid command line parameters. Run %s --help for instructions.", basename(argv[0])); + } + } + + prog = argv[0]; + + if (tls && ssl) + config_die("Options --tls and --ssl are mutually exclusive."); + else { + if (ssl) + cfg->ETYPE = ENC_SSL; + else if (tls) + cfg->ETYPE = ENC_TLS; + } + + if (client) { + cfg->PMODE = SSL_CLIENT; + } + + if (cfg->WRITE_IP_OCTET && cfg->WRITE_PROXY_LINE) + config_die("Options --write-ip and --write-proxy are mutually exclusive."); + + if (cfg->WRITE_PROXY_LINE && cfg->PROXY_PROXY_LINE) + config_die("Options --write-proxy and --proxy-proxy are mutually exclusive."); + + if (cfg->WRITE_IP_OCTET && cfg->PROXY_PROXY_LINE) + config_die("Options --write-ip and --proxy-proxy are mutually exclusive."); + + if (cfg->DAEMONIZE) { + cfg->SYSLOG = 1; + cfg->QUIET = 1; + } + +#ifdef USE_SHARED_CACHE + if (cfg->SHCUPD_IP != NULL && ! cfg->SHARED_CACHE) + config_die("Shared cache update listener is defined, but shared cache is disabled."); +#endif + + // Any arguments left are presumed to be PEM files + argc -= optind; + argv += optind; + for (i = 0; i < argc; i++) { + config_param_validate(CFG_PEM_FILE, argv[i], cfg, NULL, 0); + } + if (cfg->PMODE == SSL_SERVER && cfg->CERT_FILES == NULL) { + config_die("No x509 certificate PEM file specified!"); + } + + // was this only a test? + if (test_only) { + fprintf(stderr, "Trying to initialize SSL contexts with your certificates"); + if (!init_openssl()) { + config_die("Error initializing OpenSSL."); + } + printf("%s configuration looks ok.\n", basename(prog)); + exit(0); + } +} diff --git a/hm_stud/configuration.h b/hm_stud/configuration.h new file mode 100644 index 0000000..3ea68b0 --- /dev/null +++ b/hm_stud/configuration.h @@ -0,0 +1,80 @@ +/** + * configuration.h + * + * Author: Brane F. Gracnar + * + */ + +#include + +#ifdef USE_SHARED_CACHE + #include "shctx.h" + + #ifndef MAX_SHCUPD_PEERS + #define MAX_SHCUPD_PEERS 15 + #endif + +typedef struct shcupd_peer_opt { + char *ip; + char *port; +} shcupd_peer_opt; + +#endif + +typedef enum { + ENC_TLS, + ENC_SSL +} ENC_TYPE; + +typedef enum { + SSL_SERVER, + SSL_CLIENT +} PROXY_MODE; + +struct cert_files { + char *CERT_FILE; + struct cert_files *NEXT; +}; + +/* configuration structure */ +struct __stud_config { + ENC_TYPE ETYPE; + PROXY_MODE PMODE; + int WRITE_IP_OCTET; + int WRITE_PROXY_LINE; + int PROXY_PROXY_LINE; + char *CHROOT; + uid_t UID; + gid_t GID; + char *FRONT_IP; + char *FRONT_PORT; + char *BACK_IP; + char *BACK_PORT; + long NCORES; + struct cert_files *CERT_FILES; + char *CIPHER_SUITE; + char *ENGINE; + int BACKLOG; +#ifdef USE_SHARED_CACHE + int SHARED_CACHE; + char *SHCUPD_IP; + char *SHCUPD_PORT; + shcupd_peer_opt SHCUPD_PEERS[MAX_SHCUPD_PEERS+1]; + char *SHCUPD_MCASTIF; + char *SHCUPD_MCASTTTL; +#endif + int QUIET; + int SYSLOG; + int SYSLOG_FACILITY; + int TCP_KEEPALIVE_TIME; + int DAEMONIZE; + int PREFER_SERVER_CIPHERS; +}; + +typedef struct __stud_config stud_config; + +char * config_error_get (void); +stud_config * config_new (void); +void config_destroy (stud_config *cfg); +int config_file_parse (char *file, stud_config *cfg); +void config_parse_cli(int argc, char **argv, stud_config *cfg); diff --git a/hm_stud/debian/changelog b/hm_stud/debian/changelog new file mode 100644 index 0000000..c4d45a5 --- /dev/null +++ b/hm_stud/debian/changelog @@ -0,0 +1,6 @@ +stud (0.3~0.20111212) unstable; urgency=low + + * Initial release. + + -- Charlie Root Mon, 12 Dec 2011 13:24:18 +0100 + diff --git a/hm_stud/debian/compat b/hm_stud/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/hm_stud/debian/compat @@ -0,0 +1 @@ +7 diff --git a/hm_stud/debian/control b/hm_stud/debian/control new file mode 100644 index 0000000..9d83024 --- /dev/null +++ b/hm_stud/debian/control @@ -0,0 +1,26 @@ +Source: stud +Section: universe/net +Priority: optional +Maintainer: Charlie Root +Build-Depends: debhelper (>= 7.0.50~) +Standards-Version: 3.9.2 +Homepage: https://github.com/bumptech/stud + +Package: stud +Section: universe/net +Priority: optional +Architecture: any +Depends: libc6 (>= 2.4), libev4 (>= 1:4.04), libssl0.9.8 (>= 0.9.8k-1) | libssl1.0.0 (>= 1.0.0e-1) +# Depends: ${shlibs:Depends}, ${misc:Depends} +Description: The Scalable TLS Unwrapping Daemon + stud is a network proxy that terminates TLS/SSL connections and forwards + the unencrypted traffic to some backend. It's designed to handle 10s of + thousands of connections efficiently on multicore machines. + . + It follows a process-per-core model; a parent process spawns N children who + each accept() on a common socket to distribute connected clients among them. + Within each child, asynchronous socket I/O is conducted across the local + connections using libev and OpenSSL's nonblocking API. By default, stud + has an overhead of ~200KB per connection--it preallocates some buffer space + for data in flight between frontend and backend. + diff --git a/hm_stud/debian/copyright b/hm_stud/debian/copyright new file mode 100644 index 0000000..b7266d0 --- /dev/null +++ b/hm_stud/debian/copyright @@ -0,0 +1,25 @@ +Copyright 2011 Bump Technologies, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP TECHNOLOGIES, INC. OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Bump Technologies, Inc. diff --git a/hm_stud/debian/postinst b/hm_stud/debian/postinst new file mode 100644 index 0000000..e673c86 --- /dev/null +++ b/hm_stud/debian/postinst @@ -0,0 +1,43 @@ +#!/bin/sh + +case $1 in + # Configure this package. If the package must prompt the user for + # information, do it here. + configure) + mkdir -p /var/run/stud + ;; + + # Back out of an attempt to upgrade this package FROM THIS VERSION + # to version $2. Undo the effects of "prerm upgrade $2". + abort-upgrade) + ;; + + # Back out of an attempt to remove this package, which was due to + # a conflict with package $3 (version $4). Undo the effects of + # "prerm remove in-favour $3 $4". + abort-remove) + ;; + + # Back out of an attempt to deconfigure this package, which was + # due to package $6 (version $7) which we depend on being removed + # to make way for package $3 (version $4). Undo the effects of + # "prerm deconfigure in-favour $3 $4 removing $6 $7". + abort-deconfigure) + ;; + + *) + echo "$0: didn't understand being called with \`$1'" 1>&2 + exit 1; + ;; + +esac + +if service stud status >/dev/null 2>&1; then + echo + echo " !!!! WARNING !!!!" + echo + echo "stud is running, you should restart it." + echo +fi + +# EOF diff --git a/hm_stud/debian/postrm b/hm_stud/debian/postrm new file mode 100644 index 0000000..e2b78fe --- /dev/null +++ b/hm_stud/debian/postrm @@ -0,0 +1,34 @@ +#!/bin/sh + +case "$1" in + remove|purge|abort-install|abort-upgrade) + # This package is being removed, but its configuration has not yet + # been purged. + + # stud shouldn't start at system startup + # update-rc.d -f stud remove + + # remove rundir + rm -rf /var/run/stud >/dev/null 2>&1 + + # remove config dir + rm -rf /etc/stud >/dev/null 2>&1 + + ;; + + disappear) + ;; + + upgrade) + ;; + + failed-upgrade) + ;; + + *) echo "$0: didn't understand being called with \`$1'" 1>&2 + exit 1;; +esac + +exit 0 + +# EOF diff --git a/hm_stud/debian/prerm b/hm_stud/debian/prerm new file mode 100644 index 0000000..d4671d1 --- /dev/null +++ b/hm_stud/debian/prerm @@ -0,0 +1,28 @@ +#!/bin/sh + +case "$1" in + remove|purge|abort-install|abort-upgrade) + # This package is being removed, but its configuration has not yet + # been purged. + + # shutdown service + service stud stop + + ;; + + disappear) + ;; + + upgrade) + ;; + + failed-upgrade) + ;; + + *) echo "$0: didn't understand being called with \`$1'" 1>&2 + exit 1;; +esac + +exit 0 + +# EOF diff --git a/hm_stud/debian/rules b/hm_stud/debian/rules new file mode 100644 index 0000000..aa6b51e --- /dev/null +++ b/hm_stud/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +override_dh_auto_clean: + rm -rf ebtree + make clean + +override_dh_auto_configure: + if [ ! -f ebtree-6.0.6.tar.gz ]; then wget http://1wt.eu/tools/ebtree/ebtree-6.0.6.tar.gz; fi + if [ ! -d ebtree ]; then tar zxpf ebtree-6.0.6.tar.gz; mv ebtree-6.0.6 ebtree; fi + +override_dh_auto_build: + make USE_SHARED_CACHE=1 PREFIX=/usr + +override_dh_auto_install: + dh_testdir + dh_testroot + dh_prep + dh_installdirs + make install DESTDIR=$(CURDIR)/debian/stud PREFIX=/usr + + # create stud instance configuration directory + mkdir -p $(CURDIR)/debian/stud/etc/stud + chown -R root:root $(CURDIR)/debian/stud/etc/stud + chmod 700 $(CURDIR)/debian/stud/etc/stud + echo "Run /etc/init.d/stud --sample-config > /etc/stud/something.conf for default instance configuration" >> "$(CURDIR)/debian/stud/etc/stud/README.TXT" + +%: + dh $@ + +# EOF diff --git a/hm_stud/gen_cert.sh b/hm_stud/gen_cert.sh new file mode 100644 index 0000000..91b25c0 --- /dev/null +++ b/hm_stud/gen_cert.sh @@ -0,0 +1,7 @@ +openssl genrsa -out test.com.key 1024 +penssl req -new -key test.com.key -out test.com.csr +openssl x509 -req -days 365 -in test.com.csr -signkey test.com.key -out test.com.crt +cat test.com.key test.com.crt > openssl genrsa -out test.com.key 1024 +openssl req -new -key test.com.key -out test.com.csr +openssl x509 -req -days 365 -in test.com.csr -signkey test.com.key -out test.com.crt +cat test.com.key test.com.crt > test.com.pem diff --git a/hm_stud/init.stud b/hm_stud/init.stud new file mode 100644 index 0000000..0dba4c5 --- /dev/null +++ b/hm_stud/init.stud @@ -0,0 +1,837 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: stud +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# Should-Start: $syslog +# Should-Stop: $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start or stop stud (SSL offloader) +### END INIT INFO + +####################################################### +# GLOBALS # +####################################################### + +# instance configuration directory +CONFIG_DIR="/etc/stud" + +# Runtime directory data +RUNTIME_DIR="/var/run/stud" + +####################################################### + +####################################################### + +stud_single_instance_config_reset() { +####################################################### +# stud instance configuration # +####################################################### + +# stud listening address +FRONTEND_ADDRESS="*,8443" + +# upstream service address +BACKEND_ADDRESS="127.0.0.1,80" + +# x509 certificate file +CERT_FILE="" + +# TLS only service? Don't set this to 1 if you're +# offloading HTTPS. +TLS_ONLY="0" + +# cipher suite (run openssl ciphers for full list) +CIPHER_SUITE="HIGH" + +# OpenSSL engine +ENGINE="" + +# Number of worker processes +WORKERS="1" + +# Listen backlog +BACKLOG="" + +# Chroot directory +CHROOT_DIR="" + +# drop privileges and run as specified +# user if set +SETUID_USER="" + +# use shared cache with specified number of sessions +# WARNING: stud must be compiled with USE_SHARED_CACHE=1 +SHARED_CACHE_SESSIONS="0" + +# Accept cache updates on specified address +# +# syntax: HOST,PORT +# +# WARNING: stud must be compiled with USE_SHARED_CACHE=1 +# SHARED_CACHE_SESSIONS must be >= 1 +CACHE_UPDATE_ACCEPT="" + +# Send cache updates to specified list space separated peers +# +# syntax: HOST1,PORT HOST2,PORT +# +# WARNING: stud must be compiled with USE_SHARED_CACHE=1 +# and CACHE_UPDATE_ACCEPT must be defined +CACHE_UPDATE_SEND="" + +# Force network interface and ttl to receive and send multicast +# cache updates +# +# syntax: IFACE[,TTL] +# +# WARNING: stud must be compiled with USE_SHARED_CACHE=1 +# and CACHE_UPDATE_ACCEPT must be defined +CACHE_UPDATE_IFACE="" + +# default tcp keepalive on client socket in seconds +CLIENT_TCP_KEEPALIVE_SEC="" + +# log to syslog? +SYSLOG="1" + +# Enable write-ip? +WRITE_IP="0" + +# Enable SENDPROXY protocol; see +# http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt +# for additional info +WRITE_PROXY="0" + +# Alternative OpenSSL library dir +# Use this if you'd like to run stud with different +# version of OpenSSL library +OPENSSL_LIB_DIR="" + +# Semicolon separated list of process affinities; requires +# taskset(8) utility. +# +# SYNTAX: +# ":;:;..." +# +# : stud worker process number, starting with 1 +# : process affinity, see taskset(8) for details +# +# EXAMPLES: +# +# "1:0" => bind first process to CPU0 +# +# "1:0;2:3-4;3:5;4:7" => bind first worker process to CPU0, +# second worker process to CPU3 and CPU4, +# third worker process to CPU5 and fourth +# worker process to CPU7 +PROCESS_AFFINITY="" + +# Process priority (integer between -19 to 19) +# lower value means higher priority +# +PROCESS_PRIORITY="" + +# ulimit -n value before starting single stud instance +# +# Comment out or set to 0 to disable ulimit -n +# setup. +# +ULIMIT_N="" + +# Additional stud command line options +# +# NOTE: set this only if you really know what your're +# doing +# +# ADDITIONAL_STUD_OPT="" + +# EOF +} + +PATH="${PATH}:." +INSTANCE_NAME="" +STUD=`which stud 2>/dev/null` + +die() { + msg_log "FATAL: $@" + echo "FATAL: $@" 1>&2 + exit 1 +} + +msg_log() { + ident="stud" + test ! -z "${INSTANCE_NAME}" && ident="${ident}/${INSTANCE_NAME}" + logger -i -t "${ident}" "$@" >/dev/null 2>&1 +} + +msg_err() { + msg_log "ERROR: $@" +} + + +_real_single_instance_start() { + # check stud binary + if [ -z "${STUD}" ] || [ ! -f "${STUD}" ] || [ ! -x "${STUD}" ]; then + die "Invalid stud binary: '${STUD}'" + fi + + # generate stud command line options + opts="-f ${FRONTEND_ADDRESS}" + opts="${opts} -b ${BACKEND_ADDRESS}" + + if [ "${TLS_ONLY}" = "1" ]; then + opts="${opts} --tls" + else + opts="${opts} --ssl" + fi + + test ! -z "${CIPHER_SUITE}" && opts="${opts} -c ${CIPHER_SUITE}" + test ! -z "${ENGINE}" && opts="${opts} -e ${ENGINE}" + + if [ ! -z "${WORKERS}" ] && [ ${WORKERS} -gt 0 ]; then + opts="${opts} -n ${WORKERS}" + fi + + if [ ! -z "${BACKLOG}" ] && [ ${BACKLOG} -gt 0 ]; then + opts="${opts} -B ${BACKLOG}" + fi + + if [ ! -z "${CLIENT_TCP_KEEPALIVE_SEC}" ] && [ ${CLIENT_TCP_KEEPALIVE_SEC} -gt 0 ]; then + opts="${opts} -k ${CLIENT_TCP_KEEPALIVE_SEC}" + fi + + # shared cache sessions... + if [ ! -z "${SHARED_CACHE_SESSIONS}" ] && [ ${SHARED_CACHE_SESSIONS} -gt 0 ]; then + opts="${opts} -C ${SHARED_CACHE_SESSIONS}" + + # shared cache stuff + if [ ! -z "${CACHE_UPDATE_ACCEPT}" ]; then + opts="${opts} -U ${CACHE_UPDATE_ACCEPT}" + + c_u=0 + for h in ${CACHE_UPDATE_SEND}; do + test ! -z "${h}" || continue + opts="${opts} -P ${h}" + c_u=$((c_u + 1)) + done + if [ ${c_u} -lt 1 ]; then + die "Cache updates are enabled but CACHE_UPDATE_SEND option seems to be empty." + fi + + if [ ! -z "${CACHE_UPDATE_IFACE}" ]; then + opts="${opts} -M ${CACHE_UPDATE_IFACE}" + fi + fi + + fi + + # chroot? + test ! -z "${CHROOT_DIR}" && opts="${opts} -r ${CHROOT_DIR}" + test ! -z "${SETUID_USER}" && opts="${opts} -u ${SETUID_USER}" + + opts="${opts} -q" + test "${SYSLOG}" = "1" && opts="${opts} -s" + + test "${WRITE_IP}" = "1" && opts="${opts} --write-ip" + test "${WRITE_PROXY}" = "1" && opts="${opts} --write-proxy" + + if [ ! -z "${CERT_FILE}" ] && [ -f "${CERT_FILE}" ] && [ -r "${CERT_FILE}" ]; then + opts="${opts} ${CERT_FILE}" + else + die "Invalid or unreadable certificate file '${CERT_FILE}'." + fi + + # additional command line options?! + if [ ! -z "${ADDITIONAL_STUD_OPT}" ]; then + opts="${opts} ${ADDITIONAL_STUD_OPT}" + fi + + # priority?! + prefix="" + if [ ! -z "${PROCESS_PRIORITY}" ]; then + prefix="nice -n ${PROCESS_PRIORITY}" + fi + + # we want to start stud in a daemon mode... + opts="${opts} --daemon" + + # set ulimits! + ulimit_set || die "Unable to set stud runtime limits." + + # disable linker stuff + unset LD_LIBRARY_PATH + + # set new lib path if requested + if [ ! -z "${OPENSSL_LIB_DIR}" -a -d "${OPENSSL_LIB_DIR}" ]; then + LD_LIBRARY_PATH="${OPENSSL_LIB_DIR}" + export LD_LIBRARY_PATH + fi + + # start stud! + msg_log "Starting instance '${INSTANCE_NAME}': ${STUD} ${opts}" + out=`${prefix} ${STUD} ${opts} 2>&1` + + # remove lib path + unset LD_LIBRARY_PATH + + # check invocation + stud_pid=`echo "${out}" | tail -n 1 | cut -d " " -f5 | tr -d '.'` + if [ -z "${stud_pid}" ]; then + die "Empty stud pid. This is extremely weird." + fi + + # wait a little bit, check if pid is still alive + sleep 0.2 >/dev/null 2>&1 + if ! kill -0 "${stud_pid}" >/dev/null 2>&1; then + die "Stud started successfully as pid ${stud_pid} but died shortly after startup."; + fi + + # write pid file! + pid_file_write "${INSTANCE_NAME}" "${stud_pid}" || msg_warn "${Error}" + + # set affinity! + stud_affinity_set "${stud_pid}" || die "${Error}" +} + +stud_single_instance_start() { + name="${1}" + if [ -z "${name}" ]; then + Error="Unable to stop undefined stud instance." + return 1 + fi + + # check if it is running + if stud_single_instance_status "${name}"; then + Error="Instance ${name} is already running as pid ${Error}." + return 1 + fi + + # do the real stuff... + Error="" + out=`_real_single_instance_start 2>&1` + rv=$? + if [ "${rv}" != "0" ]; then + Error="${out}" + rv=1 + fi + + # this is it! :) + return $rv +} + +stud_single_instance_stop() { + name="${1}" + if [ -z "${name}" ]; then + Error="Unable to stop undefined stud instance." + return 1 + fi + + # check if it is running + stud_single_instance_status "${name}" || return 1 + + # time to stop instance + pid="${Error}" + msg_log "Stopping stud instance '${name}', pid ${pid}." + + ok=0 + if ! kill "${pid}" >/dev/null 2>&1; then + Error="Unable to stop instance: unable to kill pid ${pid}." + return 1 + fi + + # wait for termination + i=0 + while [ ${i} -lt 9 ]; do + i=$((i + 1)) + # are you dead yet? + if ! kill -0 "${pid}" >/dev/null 2>&1; then + ok=1 + break + fi + sleep 0.1 >/dev/null 2>&1 + done + + # not ok?! try to with headshot... + if [ "${ok}" != "1" ]; then + msg_log "Gentle stop of instance ${name} failed, trying to stop it with SIGKILL." + if ! kill -9 "${pid}"; then + Error="Unable to stop instance ${name}: kill(1) failed." + return 1 + fi + fi + + return 0 +} + +stud_single_instance_restart() { + name="${1}" + if [ -z "${name}" ]; then + Error="Unable to stop undefined stud instance." + return 1 + fi + + # maybe we need to stop it first... + if stud_single_instance_status "${name}"; then + stud_single_instance_stop "${name}" || return 1 + fi + + # start it back... + Error="" + stud_single_instance_start "${name}" +} + +stud_single_instance_status() { + Error="" + if [ -z "${1}" ]; then + Error="Invalid instance name." + return 1 + fi + + # get pid file... + pid=`pid_file_read "${1}"` + + # check it... + if [ -z "${pid}" ] || ! kill -0 "${pid}" >/dev/null 2>&1; then + Error="Instance '${1}' is stopped." + return 1 + fi + + # set pid to Error + Error="${pid}" + return 0 +} + +# reads pid file of specific instance +pid_file_read() { + test -z "${1}" && return 1 + file="${RUNTIME_DIR}/${1}.pid" + test -f "${file}" -a -r "${file}" || return 1 + head -n 1 "${file}" +} + +# writes pid file for specific instance +pid_file_write() { + test -z "${1}" && return 1 + test -z "${2}" && return 1 + + # check runtime directory + if [ ! -e "${RUNTIME_DIR}" ] || [ ! -d "${RUNTIME_DIR}" ] || [ ! -w "${RUNTIME_DIR}" ]; then + # try to create directory + mkdir -p "${RUNTIME_DIR}" || die "Unable to create missing runtime directory '${RUNTIME_DIR}'" + fi + + file="${RUNTIME_DIR}/${1}.pid" + echo "${2}" > "${file}" +} + +# lists running instances +running_instance_list() { + list="" + for file in ${RUNTIME_DIR}/*.pid; do + test -f "${file}" || continue + + fileb=`basename "${file}"` + name=`echo "${fileb}" | cut -d. -f1` + if [ -z "${name}" ]; then + msg_log "Removing bogus pid file '${file}'." + rm -f "${file}" >/dev/null 2>&1 + continue + fi + pid=`pid_file_read "${name}"` + if [ -z "${pid}" ]; then + msg_log "Removing bogus pid file '${file}': instance '${name}' doesn't contain pid." + rm -f "${file}" >/dev/null 2>&1 + continue + fi + + # is this pid alive? + if ! kill -0 "${pid}" >/dev/null 2>&1 ; then + msg_log "Removing bogus pid file '${file}': instance '${name}' [pid ${pid}] is stopped." + rm -f "${file}" >/dev/null 2>&1 + continue + fi + + list="${list} ${name}" + done + echo ${list} +} + +stud_instances_start() { + list="$@" + if [ -z "${list}" ]; then + list=`stud_config_instances_list` + fi + if [ -z "${list}" ]; then + die "No stud instances configured in directory '${CONFIG_DIR}'." + fi + + echo "Starting stud instances:" + num_ok=0 + num_failed=0 + for instance in ${list}; do + echo -n " ${instance}: " + # load configuration + if ! stud_single_instance_config_load "${instance}"; then + echo "failed: ${Error}" + return 1 + # start instance + elif stud_single_instance_start "${instance}"; then + echo "done." + msg_log "Instance ${name} successfully started." + num_ok=$((num_ok + 1)) + else + echo "failed: ${Error}" + msg_err "Error starting instance ${name}: ${Error}" + num_failed=$((num_failed + 1)) + fi + done + + if [ "${num_failed}" != "0" ]; then + return 1 + else + return 0 + fi +} + +stud_instances_stop() { + list="$@" + if [ -z "${list}" ]; then + list=`running_instance_list` + fi + if [ -z "${list}" ]; then + die "No stud instances are running." + fi + + echo "Stopping stud instances:" + num_ok=0 + num_failed=0 + for instance in ${list}; do + echo -n " ${instance}: " + if stud_single_instance_stop "${instance}"; then + echo "done." + num_ok=$((num_ok + 1)) + msg_log "Instance ${instance} successfully stopped." + else + echo "failed: ${Error}" + msg_err "Error stopping instance ${instance}: ${Error}" + num_failed=$((num_failed + 1)) + fi + done + + if [ "${num_failed}" != "0" ]; then + return 1 + else + return 0 + fi +} + +stud_instances_restart() { + list="$@" + if [ -z "${list}" ]; then + list=`(running_instance_list ; stud_config_instances_list) | tr ' ' '\n' | sort -u | xargs echo` + fi + + echo "Restarting stud instances: " + num_ok=0 + num_failed=0 + for instance in ${list}; do + echo -n " ${instance}: "; + + # load configuration + if ! stud_single_instance_config_load "${instance}"; then + echo "failed: ${Error}" + return 1 + # restart instance + elif stud_single_instance_restart "${instance}"; then + echo "done." + num_ok=$((num_ok + 1)) + msg_log "Instance ${instance} successfully restarted." + else + echo "failed: ${Error}" + msg_err "Error restarting instance ${instance}: ${Error}" + num_failed=$((num_failed + 1)) + fi + done + + if [ "${num_failed}" != "0" ]; then + return 1 + else + return 0 + fi +} + +stud_instances_status() { + list_config=`stud_config_instances_list` + list_running=`running_instance_list` + + list_all=`echo ${list_config} ${list_running} | tr ' ' '\n' | sort -u | xargs echo` + + i=0; + + echo "Stud instance status: " + + if [ -z "${list_all}" ]; then + die "No instances are configured and/or running." + fi + + for instance in ${list_all}; do + echo -n " ${instance}: " + if stud_single_instance_status "${instance}"; then + echo "running as pid $Error" + i=$((i + 1)) + else + echo "stopped" + fi + done + + if [ ${i} -gt 0 ]; then + return 0 + else + return 1 + fi +} + +stud_config_instances_list() { + list="" + for file in ${CONFIG_DIR}/*.conf; do + test -f "${file}" -a -r "${file}" || continue + fileb=`basename "${file}"` + name=`echo "${fileb}" | cut -d. -f1` + test ! -z "${name}" || continue + list="${list} ${name}" + done + + echo ${list} +} + +stud_single_instance_config_print() { + head -n 151 "$0" | tail -n 123 +} + +stud_single_instance_config_load() { + file="${CONFIG_DIR}/${1}.conf" + INSTANCE_NAME="" + + # reset configuration + stud_single_instance_config_reset + Error='' + + if [ -f "${file}" -a -r "${file}" ]; then + . "${file}" >/dev/null || Error="Unable to load instance configuration file '${file}'." + else + Error="Invalid or unreadable instance configuration file '${file}'." + return 1 + fi + + # set instance name... + INSTANCE_NAME="${1}" + + return 0 +} + +stud_instance_worker_pids() { + test -z "${1}" && return 1 + ps -ef | grep " ${1} " | grep -v ' 1 ' | grep -v ' grep ' | awk '{print $2}' | xargs echo +} + +# prints worker pid for n-th worker +# arguments: +# $1: list of worker pids (string) +# $2: worker number +stud_instance_worker_pid_by_num() { + i=0 + local IFS=" " + for e in ${1}; do + i=$((i + 1)) + if [ "${i}" = "${2}" ]; then + echo "$e" + return 0 + fi + done + return 1 +} + +stud_affinity_set() { + # nothing to set? + test -z "$PROCESS_AFFINITY" && return 0 + + Error="" + +# "1:0;2:3-4;3:5;4:7" => bind first haproxy process to CPU0, +# second haproxy process to CPU3 and CPU4, +# third haproxy process to CPU5 and fourth +# process to CPU7 + + + worker_pids=`stud_instance_worker_pids "${1}"` + + local IFS=";" + item="" + for item in $PROCESS_AFFINITY; do + num=`echo "${item}" | cut -f1 -d:` + affinity=`echo "${item}" | cut -f2 -d:` + + # validate process number + test -z "$num" && continue + test ${num} -ge 1 2>&1 || continue + + # validate affinity + test -z "${affinity}" && continue + # WORKS: OpenSUSE + # DOESNT WORK: Debian/Ubuntu!!! + #echo "${affinity}" | grep -qPi '[^a-f0-9\-\,x]' && continue + + # is this raw affinity mask? + raw_affinity=0 + echo "${affinity}" | grep -qE '^0x' && raw_affinity=1 + + # get pid for process id $num + pid=`stud_instance_worker_pid_by_num "${worker_pids}" "$num"` + test -z "$pid" && continue + + #echo "item: $item; process num: $num; pid: $pid; affinity: $affinity; raw: $raw_affinity" + + opt="-p" + test "${raw_affinity}" = "0" && opt="${opt} -c" + opt="${opt} ${affinity}" + opt="${opt} ${pid}" + # echo "WILL RUN: 'taskset $opt'" + msg_log "Setting stud worker number ${num} (pid ${pid}) affinity using command: taskset ${opt}" + eval taskset ${opt} >/dev/null 2>&1 || msg_log "Error setting process affinity." + done +} + +ulimit_n_set() { + if [ -z "$ULIMIT_N" ] || [ "$ULIMIT_N" = "0" ]; then + return 0 + fi + + # try to set maximum possible limit... + i="$ULIMIT_N" + num=0 + while [ $i -gt 0 ]; do + num=$((num + 1)) + if ulimit -n "$i" > /dev/null 2>&1; then + percentage=$((i*100 / ${ULIMIT_N})) + if [ $percentage -lt 75 ]; then + Error="Filedescriptor limit set to only $i (${percentage}% of desired value of $ULIMIT_N); check your system settings." + return 1 + fi + msg_log "Filedescriptor limit successfully set to $i (${percentage}% of desired value of $ULIMIT_N) after ${num} iteration(s)." + return 0 + break + else + i=$((i - 100)) + fi + done + + Error="Filedescriptor limit of $ULIMIT_N could not be set." + msg_log "$Error" + return 1 +} + +ulimit_set() { + # set fd limit + ulimit_n_set || return 1 + + # set core file limit + ulimit -c unlimited >/dev/null 2>&1 + + return 0 +} + +printhelp() { + cat < + +/* Initialize a ringbuffer structure to empty */ + +void ringbuffer_init(ringbuffer *rb) { + rb->head = &rb->slots[0]; + rb->tail = &rb->slots[0]; + rb->used = 0; + int x; + for (x=0; xslots[x].next = &(rb->slots[(x + 1) % RING_SLOTS]); +} + +/** READ FUNCTIONS **/ + +/* Return a char * that represents the current unconsumed buffer */ +char * ringbuffer_read_next(ringbuffer *rb, int * length) { + assert(rb->used); + *length = rb->head->left; + return rb->head->ptr; +} + +/* Mark consumption of only part of the read head buffer */ +void ringbuffer_read_skip(ringbuffer *rb, int length) { + assert(rb->used); + rb->head->ptr += length; + rb->head->left -= length; +} + +/* Pop a consumed (fully read) head from the buffer */ +void ringbuffer_read_pop(ringbuffer *rb) { + assert(rb->used); + rb->head = rb->head->next; + rb->used--; +} + + +/** WRITE FUNCTIONS **/ + +/* Return the tail ptr (current target of new writes) */ +char * ringbuffer_write_ptr(ringbuffer *rb) { + assert(rb->used < RING_SLOTS); + return rb->tail->data; +} + +/* Mark the tail appended for `length` bytes, and move the cursor + * to the next slot */ +void ringbuffer_write_append(ringbuffer *rb, int length) { + assert(rb->used < RING_SLOTS); + + rb->used++; + + rb->tail->ptr = rb->tail->data; + rb->tail->left = length; + rb->tail = rb->tail->next; +} + +/** RING STATE FUNCTIONS **/ + +/* Used size of the ringbuffer */ +int ringbuffer_size(ringbuffer *rb) { + return rb->used; +} + +/* Used size of the ringbuffer */ +int ringbuffer_capacity(ringbuffer *rb) { + (void) rb; + return RING_SLOTS; +} + +/* Is the ringbuffer completely empty (implies: no data to be written) */ +int ringbuffer_is_empty(ringbuffer *rb) { + return rb->used == 0; +} + +/* Is the ringbuffer completely full (implies: no more data should be read) */ +int ringbuffer_is_full(ringbuffer *rb) { + return rb->used == RING_SLOTS; +} + diff --git a/hm_stud/ringbuffer.h b/hm_stud/ringbuffer.h new file mode 100644 index 0000000..cb8af13 --- /dev/null +++ b/hm_stud/ringbuffer.h @@ -0,0 +1,67 @@ +/** + * Copyright 2011 Bump Technologies, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP TECHNOLOGIES, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of Bump Technologies, Inc. + * + **/ + +#ifndef RINGBUFFER_H +#define RINGBUFFER_H + +#include + +/* Tweak these for potential memory/throughput tradeoffs */ +#define RING_SLOTS 3 +#define RING_DATA_LEN 1024 * 32 + +typedef struct bufent { + char data[RING_DATA_LEN]; + char *ptr; + size_t left; + struct bufent *next; +} bufent; + +typedef struct ringbuffer { + bufent slots[RING_SLOTS]; + bufent *head; // reads from the head + bufent *tail; // writes to the tail + size_t used; +} ringbuffer; + +void ringbuffer_init(ringbuffer *rb); + +char * ringbuffer_read_next(ringbuffer *rb, int * length); +void ringbuffer_read_skip(ringbuffer *rb, int length); +void ringbuffer_read_pop(ringbuffer *rb); + +char * ringbuffer_write_ptr(ringbuffer *rb); +void ringbuffer_write_append(ringbuffer *rb, int length); + +int ringbuffer_size(ringbuffer *rb); +int ringbuffer_capacity(ringbuffer *rb); +int ringbuffer_is_empty(ringbuffer *rb); +int ringbuffer_is_full(ringbuffer *rb); + +#endif /* RINGBUFFER_H */ diff --git a/hm_stud/shctx.c b/hm_stud/shctx.c new file mode 100644 index 0000000..3a82560 --- /dev/null +++ b/hm_stud/shctx.c @@ -0,0 +1,395 @@ +/* + * shctx.c + * + * Copyright (C) 2011 EXCELIANCE + * + * Author: Emeric Brun - emeric@exceliance.fr + * + */ +#include +#ifdef USE_SYSCALL_FUTEX +#include +#include +#include +#else /* USE_SYSCALL_FUTEX */ +#include +#endif /* USE_SYSCALL_FUTEX */ + +#include "ebtree/ebmbtree.h" +#include "shctx.h" + +struct shared_session { + struct ebmb_node key; + unsigned char key_data[SSL_MAX_SSL_SESSION_ID_LENGTH]; + long c_date; + int data_len; + unsigned char data[SHSESS_MAX_DATA_LEN]; + struct shared_session *p; + struct shared_session *n; +}; + + +struct shared_context { +#ifdef USE_SYSCALL_FUTEX + unsigned int waiters; +#else /* USE_SYSCALL_FUTEX */ + pthread_mutex_t mutex; +#endif + struct shared_session active; + struct shared_session free; +}; + +/* Static shared context */ +static struct shared_context *shctx = NULL; + +/* Callbacks */ +static void (*shared_session_new_cbk)(unsigned char *session, unsigned int session_len, long cdate); + + +/* Lock functions */ +#ifdef USE_SYSCALL_FUTEX +static inline unsigned int xchg(unsigned int *ptr, unsigned int x) +{ + __asm volatile("lock xchgl %0,%1" + : "=r" (x), "+m" (*ptr) + : "0" (x) + : "memory"); + return x; +} + +static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new) +{ + unsigned int ret; + + __asm volatile("lock cmpxchgl %2,%1" + : "=a" (ret), "+m" (*ptr) + : "r" (new), "0" (old) + : "memory"); + return ret; +} + +static inline unsigned char atomic_inc(unsigned int *ptr) +{ + unsigned char ret; + __asm volatile("lock incl %0\n" + "setne %1\n" + : "+m" (*ptr), "=qm" (ret) + : + : "memory"); + return ret; +} + +static inline unsigned char atomic_dec(unsigned int *ptr) +{ + unsigned char ret; + __asm volatile("lock decl %0\n" + "setne %1\n" + : "+m" (*ptr), "=qm" (ret) + : + : "memory"); + return ret; +} + +static inline void shared_context_lock(void) +{ + unsigned int x; + + x = cmpxchg(&shctx->waiters, 0, 1); + if (x) { + if (x != 2) + x = xchg(&shctx->waiters, 2); + + while (x) { + syscall(SYS_futex, &shctx->waiters, FUTEX_WAIT, 2, NULL, 0, 0); + x = xchg(&shctx->waiters, 2); + } + } +} + +static inline void shared_context_unlock(void) +{ + if (atomic_dec(&shctx->waiters)) { + shctx->waiters = 0; + syscall(SYS_futex, &shctx->waiters, FUTEX_WAKE, 1, NULL, 0, 0); + } +} + +#else /* USE_SYSCALL_FUTEX */ + +#define shared_context_lock(v) pthread_mutex_lock(&shctx->mutex) +#define shared_context_unlock(v) pthread_mutex_unlock(&shctx->mutex) + +#endif + +/* List Macros */ + +#define shsess_unset(s) (s)->n->p = (s)->p; \ + (s)->p->n = (s)->n; + +#define shsess_set_free(s) shsess_unset(s) \ + (s)->p = &shctx->free; \ + (s)->n = shctx->free.n; \ + shctx->free.n->p = s; \ + shctx->free.n = s; + + +#define shsess_set_active(s) shsess_unset(s) \ + (s)->p = &shctx->active; \ + (s)->n = shctx->active.n; \ + shctx->active.n->p = s; \ + shctx->active.n = s; + + +#define shsess_get_next() (shctx->free.p == shctx->free.n) ? \ + shctx->active.p : shctx->free.p; + +/* Tree Macros */ + +#define shsess_tree_delete(s) ebmb_delete(&(s)->key); + +#define shsess_tree_insert(s) (struct shared_session *)ebmb_insert(&shctx->active.key.node.branches, \ + &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH); + +#define shsess_tree_lookup(k) (struct shared_session *)ebmb_lookup(&shctx->active.key.node.branches, \ + (k), SSL_MAX_SSL_SESSION_ID_LENGTH); + +/* Other Macros */ + +#define shsess_set_key(s,k,l) { memcpy((s)->key_data, (k), (l)); \ + if ((l) < SSL_MAX_SSL_SESSION_ID_LENGTH) \ + memset((s)->key_data+(l), 0, SSL_MAX_SSL_SESSION_ID_LENGTH-(l)); }; + + +/* SSL context callbacks */ + +/* SSL callback used on new session creation */ +int shctx_new_cb(SSL *ssl, SSL_SESSION *sess) { + (void)ssl; + struct shared_session *shsess; + unsigned char *data,*p; + unsigned int data_len; + unsigned char encsess[SHSESS_MAX_ENCODED_LEN]; + + /* check if session reserved size in aligned buffer is large enougth for the ASN1 encode session */ + data_len=i2d_SSL_SESSION(sess, NULL); + if(data_len > SHSESS_MAX_DATA_LEN) + return 1; + + /* process ASN1 session encoding before the lock: lower cost */ + p = data = encsess+SSL_MAX_SSL_SESSION_ID_LENGTH; + i2d_SSL_SESSION(sess, &p); + + shared_context_lock(); + + shsess = shsess_get_next(); + + shsess_tree_delete(shsess); + + shsess_set_key(shsess, sess->session_id, sess->session_id_length); + + /* it returns the already existing node or current node if none, never returns null */ + shsess = shsess_tree_insert(shsess); + + /* store ASN1 encoded session into cache */ + shsess->data_len = data_len; + memcpy(shsess->data, data, data_len); + + /* store creation date */ + shsess->c_date = SSL_SESSION_get_time(sess); + + shsess_set_active(shsess); + + shared_context_unlock(); + + if (shared_session_new_cbk) { /* if user level callback is set */ + + /* copy sessionid padded with 0 into the sessionid + data aligned buffer */ + memcpy(encsess, sess->session_id, sess->session_id_length); + if (sess->session_id_length < SSL_MAX_SSL_SESSION_ID_LENGTH) + memset(encsess+sess->session_id_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sess->session_id_length); + + shared_session_new_cbk(encsess, SSL_MAX_SSL_SESSION_ID_LENGTH+data_len, SSL_SESSION_get_time(sess)); + } + + return 0; /* do not increment session reference count */ +} + +/* SSL callback used on lookup an existing session cause none found in internal cache */ +SSL_SESSION *shctx_get_cb(SSL *ssl, unsigned char *key, int key_len, int *do_copy) { + (void)ssl; + struct shared_session *shsess; + unsigned char data[SHSESS_MAX_DATA_LEN], *p; + unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH]; + unsigned int data_len; + long cdate; + SSL_SESSION *sess; + + /* allow the session to be freed automatically by openssl */ + *do_copy = 0; + + /* tree key is zeros padded sessionid */ + if ( key_len < SSL_MAX_SSL_SESSION_ID_LENGTH ) { + memcpy(tmpkey, key, key_len); + memset(tmpkey+key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-key_len); + key = tmpkey; + } + + /* lock cache */ + shared_context_lock(); + + /* lookup for session */ + shsess = shsess_tree_lookup(key); + if(!shsess) { + /* no session found: unlock cache and exit */ + shared_context_unlock(); + return NULL; + } + + /* backup creation date to reset in session after ASN1 decode */ + cdate = shsess->c_date; + + /* copy ASN1 session data to decode outside the lock */ + data_len = shsess->data_len; + memcpy(data, shsess->data, shsess->data_len); + + shsess_set_active(shsess); + + shared_context_unlock(); + + /* decode ASN1 session */ + p = data; + sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len); + + /* reset creation date */ + if (sess) + SSL_SESSION_set_time(sess, cdate); + + return sess; +} + +/* SSL callback used to signal session is no more used in internal cache */ +void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) { + (void)ctx; + struct shared_session *shsess; + unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH]; + unsigned char *key = sess->session_id; + + /* tree key is zeros padded sessionid */ + if ( sess->session_id_length < SSL_MAX_SSL_SESSION_ID_LENGTH ) { + memcpy(tmpkey, sess->session_id, sess->session_id_length); + memset(tmpkey+sess->session_id_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sess->session_id_length); + key = tmpkey; + } + + shared_context_lock(); + + /* lookup for session */ + shsess = shsess_tree_lookup(key); + if ( shsess ) { + shsess_set_free(shsess); + } + + /* unlock cache */ + shared_context_unlock(); +} + +/* User level function called to add a session to the cache (remote updates) */ +void shctx_sess_add(const unsigned char *encsess, unsigned int len, long cdate) { + struct shared_session *shsess; + + /* check buffer is at least padded key long + 1 byte + and data_len not too long */ + if ( (len <= SSL_MAX_SSL_SESSION_ID_LENGTH) + || (len > SHSESS_MAX_DATA_LEN+SSL_MAX_SSL_SESSION_ID_LENGTH) ) + return; + + + shared_context_lock(); + + shsess = shsess_get_next(); + + shsess_tree_delete(shsess); + + shsess_set_key(shsess, encsess, SSL_MAX_SSL_SESSION_ID_LENGTH); + + /* it returns the already existing node or current node if none, never returns null */ + shsess = shsess_tree_insert(shsess); + + /* store into cache and update earlier on session get events */ + if (cdate) + shsess->c_date = (long)cdate; + + /* copy ASN1 session data into cache */ + shsess->data_len = len-SSL_MAX_SSL_SESSION_ID_LENGTH; + memcpy(shsess->data, encsess+SSL_MAX_SSL_SESSION_ID_LENGTH, shsess->data_len); + + shsess_set_active(shsess); + + shared_context_unlock(); +} + +/* Function used to set a callback on new session creation */ +void shsess_set_new_cbk(void (*func)(unsigned char *, unsigned int, long)) { + shared_session_new_cbk = func; +} + +/* Init shared memory context if not allocated and set SSL context callbacks + * size is the max number of stored session + * Returns: -1 on alloc failure, size if performs context alloc, and 0 if just perform + * callbacks registration */ +int shared_context_init(SSL_CTX *ctx, int size) +{ + int ret = 0; + + if (!shctx) { + int i; + +#ifndef USE_SYSCALL_FUTEX + pthread_mutexattr_t attr; +#endif /* USE_SYSCALL_FUTEX */ + struct shared_session *prev,*cur; + + shctx = (struct shared_context *)mmap(NULL, sizeof(struct shared_context)+(size*sizeof(struct shared_session)), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (!shctx || shctx == MAP_FAILED) + return -1; + +#ifdef USE_SYSCALL_FUTEX + shctx->waiters = 0; +#else + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&shctx->mutex, &attr); +#endif + memset(&shctx->active.key, 0, sizeof(struct ebmb_node)); + memset(&shctx->free.key, 0, sizeof(struct ebmb_node)); + + /* No duplicate authorized in tree: */ + shctx->active.key.node.branches.b[1] = (void *)1; + + cur = &shctx->active; + cur->n = cur->p = cur; + + cur = &shctx->free; + for ( i = 0 ; i < size ; i++) { + prev = cur; + cur = (struct shared_session *)((char *)prev + sizeof(struct shared_session)); + prev->n = cur; + cur->p = prev; + } + cur->n = &shctx->free; + shctx->free.p = cur; + + ret = size; + } + + /* set SSL internal cache size to external cache / 8 + 123 */ + SSL_CTX_sess_set_cache_size(ctx, size >> 3 | 0x3ff); + + /* Set callbacks */ + SSL_CTX_sess_set_new_cb(ctx, shctx_new_cb); + SSL_CTX_sess_set_get_cb(ctx, shctx_get_cb); + SSL_CTX_sess_set_remove_cb(ctx, shctx_remove_cb); + + return ret; +} diff --git a/hm_stud/shctx.h b/hm_stud/shctx.h new file mode 100644 index 0000000..42a600c --- /dev/null +++ b/hm_stud/shctx.h @@ -0,0 +1,53 @@ +/* + * shctx.h + * + * Copyright (C) 2011 EXCELIANCE + * + * Author: Emeric Brun - emeric@exceliance.fr + * + */ + +#ifndef SHCTX_H +#define SHCTX_H +#include +#include + +#ifndef SHSESS_MAX_FOOTER_LEN +#define SHSESS_MAX_FOOTER_LEN sizeof(uint32_t) \ + + EVP_MAX_MD_SIZE +#endif + +#ifndef SHSESS_MAX_DATA_LEN +#define SHSESS_MAX_DATA_LEN 512 +#endif + +#define SHSESS_MAX_ENCODED_LEN SSL_MAX_SSL_SESSION_ID_LENGTH \ + + SHSESS_MAX_DATA_LEN \ + + SHSESS_MAX_FOOTER_LEN + + +/* Callback called on a new session event: + * session contains the sessionid zeros padded to SSL_MAX_SSL_SESSION_ID_LENGTH + * followed by ASN1 session encoding. + * len is set to SSL_MAX_SSL_SESSION_ID_LENGTH + ASN1 session length + * len is always less than SSL_MAX_SSL_SESSION_ID_LENGTH + SHSESS_MAX_DATA_LEN. + * Remaining Bytes from len to SHSESS_MAX_ENCODED_LEN can be used to add a footer. + * cdate is the creation date timestamp. + */ +void shsess_set_new_cbk(void (*func)(unsigned char *session, unsigned int len, long cdate)); + +/* Add a session into the cache, + * session contains the sessionid zeros padded to SSL_MAX_SSL_SESSION_ID_LENGTH + * followed by ASN1 session encoding. + * len is set to SSL_MAX_SSL_SESSION_ID_LENGTH + ASN1 data length. + * if len greater than SHSESS_MAX_ENCODED_LEN, session is not added. + * if cdate not 0, on get events session creation date will be reset to cdate */ +void shctx_sess_add(const unsigned char *session, unsigned int session_len, long cdate); + +/* Init shared memory context if not allocated and set SSL context callbacks + * size is the max number of stored session + * Returns: -1 on alloc failure, size if performs context alloc, and 0 if just + * perform callbacks registration */ +int shared_context_init(SSL_CTX *ctx, int size); + +#endif /* SHCTX_H */ diff --git a/hm_stud/stud.8 b/hm_stud/stud.8 new file mode 100644 index 0000000..bca288a --- /dev/null +++ b/hm_stud/stud.8 @@ -0,0 +1,129 @@ +.\" Copyright (c) 2011 Vincent Bernat +.\" +.\" Redistribution and use in source and binary forms, with or without modification, are +.\" permitted provided that the following conditions are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright notice, this list of +.\" conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright notice, this list +.\" of conditions and the following disclaimer in the documentation and/or other materials +.\" provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED +.\" WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +.\" FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP TECHNOLOGIES, INC. OR +.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +.\" ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" The views and conclusions contained in the software and documentation are those of the +.\" authors and should not be interpreted as representing official policies, either expressed +.\" or implied, of Bump Technologies, Inc. +.\" +.Dd $Mdocdate: September 23 2011 $ +.Dt STUD 8 +.Os +.Sh NAME +.Nm stud +.Nd The Scalable TLS Unwrapping Daemon +.Sh SYNOPSIS +.Nm +.Op Fl -tls +.Op Fl -ssl +.Op Fl c Ar ciphers +.Op Fl e Ar engine +.Op Fl b Ar host,port +.Op Fl f Ar host,port +.Op Fl n Ar cores +.Op Fl B Ar backlog +.Op Fl C Ar cache +.Op Fl r Ar path +.Op Fl u Ar username +.Op Fl qs +.Op Fl -write-ip +.Op Fl -write-proxy +.Ar certificate.pem +.Sh DESCRIPTION +.Nm +is a network proxy that terminates TLS/SSL connections and forwards the +unencrypted traffic to some backend. It's designed to handle 10s of thousands of +connections efficiently on multicore machines. +.Pp +.Nm +has very few features -- it's designed to be paired with an intelligent +backend like haproxy or nginx. It maintains a strict 1:1 connection pattern +with this backend handler so that the backend can dictate throttling behavior, +maxmium connection behavior, availability of service, etc. +.Pp +The only required argument is a path to a PEM file that contains the certificate +(or a chain of certificates) and private key. It should also contain +DH parameter if you wish to use Diffie-Hellman cipher suites. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl -tls +Use TLSv1 (default). +.It Fl -ssl +Use only SSLv3 and no TLSv1. +.It Fl c Ar ciphers +Set allowed ciphers using the same format as +.Ic openssl ciphers . +For example, you can use +.Ar RSA:!COMPLEMENTOFALL . +.It Fl e Ar engine +Specify an OpenSSL engine by its unique ID. The engine will be used by +default for all algorithms. The keyword +.Ar auto +can be used to load all available engines. +.It Fl b Ar host,port +Define backend. Default is +.Ar 127.0.0.1,8000 . +Incoming connections will be unwrapped and sent to this IP and port. +.It Fl f Ar host,port +Define frontend. Default is +.Ar *,8443 . +Incoming connections will be accepted to this IP and port and will be +sent to the backend defined above. +.It Fl n Ar cores +Use +.Ar cores +worker processes. Default is 1. +.It Fl B Ar backlog +Set listen backlog size. Default is 100. +.It Fl C Ar cache +Set shared cache size in sessions. By default, no shared cache is used. +.It Fl r Ar path +Chroot to the given path. By default, no chroot is done. +.It Fl u Ar username +Set GID/UID after binding the socket. By default, no privilege is dropped. +.It Fl q +Be quiet. Only emit error messages. +.It Fl s +Send messages to syslog in addition to +.Em stderr +and +.Em stdout . +.It Fl -syslog-facility Ar facility +Syslog facility to use. Default is +.Ar daemon . +.It Fl -write-ip +Write 1 octet with the IP family followed by the IP address in 4 +(IPv4) or 16 (IPv6) octets little-endian to backend before the actual +data. +.It Fl -write-proxy +Write HaProxy's PROXY (IPv4 or IPv6) protocol line +before actual data. +.El +.Sh SEE ALSO +.Xr ciphers 1SSL , +.Xr dhparam 1SSL , +.Xr haproxy 1 +.Sh AUTHORS +.Nm +was originally written by Jamie Turner (@jamwt) and is maintained by +the Bump server team. It currently provides server-side TLS +termination for over 40 million Bump users. diff --git a/hm_stud/stud.c b/hm_stud/stud.c new file mode 100644 index 0000000..51da68f --- /dev/null +++ b/hm_stud/stud.c @@ -0,0 +1,1878 @@ +/** + * Copyright 2011 Bump Technologies, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP TECHNOLOGIES, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of Bump Technologies, Inc. + * + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ringbuffer.h" +#include "shctx.h" +#include "configuration.h" + +#ifndef MSG_NOSIGNAL +# define MSG_NOSIGNAL 0 +#endif +#ifndef AI_ADDRCONFIG +# define AI_ADDRCONFIG 0 +#endif + +/* For Mac OS X */ +#ifndef TCP_KEEPIDLE +# ifdef TCP_KEEPALIVE +# define TCP_KEEPIDLE TCP_KEEPALIVE +# endif +#endif +#ifndef SOL_TCP +# define SOL_TCP IPPROTO_TCP +#endif + +/* Do we have SNI support? */ +#ifndef OPENSSL_NO_TLSEXT +#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME +#define OPENSSL_NO_TLSEXT +#endif +#endif + +/* Globals */ +static struct ev_loop *loop; +static struct addrinfo *backaddr; +static pid_t master_pid; +static ev_io listener; +static int listener_socket; +static int child_num; +static pid_t *child_pids; +static SSL_CTX *default_ctx; +static SSL_SESSION *client_session; + +#ifdef USE_SHARED_CACHE +static ev_io shcupd_listener; +static int shcupd_socket; +struct addrinfo *shcupd_peers[MAX_SHCUPD_PEERS+1]; +static unsigned char shared_secret[SHA_DIGEST_LENGTH]; +#endif /*USE_SHARED_CACHE*/ + +long openssl_version; +int create_workers; +stud_config *CONFIG; + +static char tcp_proxy_line[128] = ""; + +/* What agent/state requests the shutdown--for proper half-closed + * handling */ +typedef enum _SHUTDOWN_REQUESTOR { + SHUTDOWN_HARD, + SHUTDOWN_CLEAR, + SHUTDOWN_SSL +} SHUTDOWN_REQUESTOR; + +#ifndef OPENSSL_NO_TLSEXT +/* + * SSL context linked list. Someday it might be nice to have a more clever data + * structure here, but assuming the number of SNI certs is small it probably + * doesn't matter. + */ +typedef struct ctx_list { + char *servername; + SSL_CTX *ctx; + struct ctx_list *next; +} ctx_list; + +static ctx_list *sni_ctxs; + +#endif /* OPENSSL_NO_TLSEXT */ + +/* + * Proxied State + * + * All state associated with one proxied connection + */ +typedef struct proxystate { + ringbuffer ring_ssl2clear; /* Pushing bytes from secure to clear stream */ + ringbuffer ring_clear2ssl; /* Pushing bytes from clear to secure stream */ + + ev_io ev_r_ssl; /* Secure stream write event */ + ev_io ev_w_ssl; /* Secure stream read event */ + + ev_io ev_r_handshake; /* Secure stream handshake write event */ + ev_io ev_w_handshake; /* Secure stream handshake read event */ + + ev_io ev_w_connect; /* Backend connect event */ + + ev_io ev_r_clear; /* Clear stream write event */ + ev_io ev_w_clear; /* Clear stream read event */ + + ev_io ev_proxy; /* proxy read event */ + + int fd_up; /* Upstream (client) socket */ + int fd_down; /* Downstream (backend) socket */ + + int want_shutdown:1; /* Connection is half-shutdown */ + int handshaked:1; /* Initial handshake happened */ + int clear_connected:1; /* Clear stream is connected */ + int renegotiation:1; /* Renegotation is occuring */ + + SSL *ssl; /* OpenSSL SSL state */ + + struct sockaddr_storage remote_ip; /* Remote ip returned from `accept` */ +} proxystate; + +#define LOG(...) \ + do { \ + if (!CONFIG->QUIET) fprintf(stdout, __VA_ARGS__); \ + if (CONFIG->SYSLOG) syslog(LOG_INFO, __VA_ARGS__); \ + } while(0) + +#define ERR(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + if (CONFIG->SYSLOG) syslog(LOG_ERR, __VA_ARGS__); \ + } while(0) + +#define NULL_DEV "/dev/null" + +/* Set a file descriptor (socket) to non-blocking mode */ +static void setnonblocking(int fd) { + int flag = 1; + + assert(ioctl(fd, FIONBIO, &flag) == 0); +} + +/* set a tcp socket to use TCP Keepalive */ +static void settcpkeepalive(int fd) { + int optval = 1; + socklen_t optlen = sizeof(optval); + + if(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { + ERR("Error activating SO_KEEPALIVE on client socket: %s", strerror(errno)); + } + + optval = CONFIG->TCP_KEEPALIVE_TIME; + optlen = sizeof(optval); +#ifdef TCP_KEEPIDLE + if(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { + ERR("Error setting TCP_KEEPIDLE on client socket: %s", strerror(errno)); + } +#endif +} + +static void fail(const char* s) { + perror(s); + exit(1); +} + +void die (char *fmt, ...) { + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + exit(1); +} + +#ifndef OPENSSL_NO_DH +static int init_dh(SSL_CTX *ctx, const char *cert) { + DH *dh; + BIO *bio; + + assert(cert); + + bio = BIO_new_file(cert, "r"); + if (!bio) { + ERR_print_errors_fp(stderr); + return -1; + } + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (!dh) { + ERR("{core} Note: no DH parameters found in %s\n", cert); + return -1; + } + + LOG("{core} Using DH parameters from %s\n", cert); + SSL_CTX_set_tmp_dh(ctx, dh); + LOG("{core} DH initialized with %d bit key\n", 8*DH_size(dh)); + DH_free(dh); + +#ifndef OPENSSL_NO_EC +#ifdef NID_X9_62_prime256v1 + EC_KEY *ecdh = NULL; + ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + LOG("{core} ECDH Initialized with NIST P-256\n"); +#endif /* NID_X9_62_prime256v1 */ +#endif /* OPENSSL_NO_EC */ + + return 0; +} +#endif /* OPENSSL_NO_DH */ + +/* This callback function is executed while OpenSSL processes the SSL + * handshake and does SSL record layer stuff. It's used to trap + * client-initiated renegotiations. + */ +static void info_callback(const SSL *ssl, int where, int ret) { + (void)ret; + if (where & SSL_CB_HANDSHAKE_START) { + proxystate *ps = (proxystate *)SSL_get_app_data(ssl); + if (ps->handshaked) { + ps->renegotiation = 1; + LOG("{core} SSL renegotiation asked by client\n"); + } + } +} + +#ifdef USE_SHARED_CACHE + +/* Handle incoming message updates */ +static void handle_shcupd(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + unsigned char msg[SHSESS_MAX_ENCODED_LEN], hash[EVP_MAX_MD_SIZE]; + ssize_t r; + unsigned int hash_len; + uint32_t encdate; + long now = (time_t)ev_now(loop); + + while ( ( r = recv(w->fd, msg, sizeof(msg), 0) ) > 0 ) { + + /* msg len must be greater than 1 Byte of data + sig length */ + if (r < (int)(1+sizeof(shared_secret))) + continue; + + /* compute sig */ + r -= sizeof(shared_secret); + HMAC(EVP_sha1(), shared_secret, sizeof(shared_secret), msg, r, hash, &hash_len); + + if (hash_len != sizeof(shared_secret)) /* should never append */ + continue; + + /* check sign */ + if(memcmp(msg+r, hash, hash_len)) + continue; + + /* msg len must be greater than 1 Byte of data + encdate length */ + if (r < (int)(1+sizeof(uint32_t))) + continue; + + /* drop too unsync updates */ + r -= sizeof(uint32_t); + encdate = *((uint32_t *)&msg[r]); + if (!(abs((int)(int32_t)now-ntohl(encdate)) < SSL_CTX_get_timeout(default_ctx))) + continue; + + shctx_sess_add(msg, r, now); + } +} + +/* Send remote updates messages callback */ +void shcupd_session_new(unsigned char *msg, unsigned int len, long cdate) { + unsigned int hash_len; + struct addrinfo **pai = shcupd_peers; + uint32_t ncdate; + + /* add session creation encoded date to footer */ + ncdate = htonl((uint32_t)cdate); + memcpy(msg+len, &ncdate, sizeof(ncdate)); + len += sizeof(ncdate); + + /* add msg sign */ + HMAC(EVP_sha1(), shared_secret, sizeof(shared_secret), + msg, len, msg+len, &hash_len); + len += hash_len; + + /* send msg to peers */ + while (*pai) { + sendto(shcupd_socket, msg, len, 0, (*pai)->ai_addr, (*pai)->ai_addrlen); + pai++; + } +} + +/* Compute a sha1 secret from an ASN1 rsa private key */ +static int compute_secret(RSA *rsa, unsigned char *secret) { + unsigned char *buf,*p; + unsigned int length; + + length = i2d_RSAPrivateKey(rsa, NULL); + if (length <= 0) + return -1; + + p = buf = (unsigned char *)malloc(length*sizeof(unsigned char)); + if (!buf) + return -1; + + i2d_RSAPrivateKey(rsa,&p); + + SHA1(buf, length, secret); + + free(buf); + + return 0; +} + +/* Create udp socket to receive and send updates */ +static int create_shcupd_socket() { + struct addrinfo *ai, hints; + struct addrinfo **pai = shcupd_peers; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + const int gai_err = getaddrinfo(CONFIG->SHCUPD_IP, CONFIG->SHCUPD_PORT, + &hints, &ai); + if (gai_err != 0) { + ERR("{getaddrinfo}: [%s]\n", gai_strerror(gai_err)); + exit(1); + } + + /* check if peers inet family addresses match */ + while (*pai) { + if ((*pai)->ai_family != ai->ai_family) { + ERR("Share host and peers inet family differs\n"); + exit(1); + } + pai++; + } + + int s = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP); + + if (s == -1) + fail("{socket: shared cache updates}"); + + int t = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)); +#ifdef SO_REUSEPORT + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &t, sizeof(int)); +#endif + + setnonblocking(s); + + if (ai->ai_addr->sa_family == AF_INET) { + struct ip_mreqn mreqn; + + memset(&mreqn, 0, sizeof(mreqn)); + mreqn.imr_multiaddr.s_addr = ((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr; + + if (CONFIG->SHCUPD_MCASTIF) { + if (isalpha(*CONFIG->SHCUPD_MCASTIF)) { /* appears to be an iface name */ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + if (strlen(CONFIG->SHCUPD_MCASTIF) > IFNAMSIZ) { + ERR("Error iface name is too long [%s]\n",CONFIG->SHCUPD_MCASTIF); + exit(1); + } + + memcpy(ifr.ifr_name, CONFIG->SHCUPD_MCASTIF, strlen(CONFIG->SHCUPD_MCASTIF)); + if (ioctl(s, SIOCGIFINDEX, &ifr)) { + fail("{ioctl: SIOCGIFINDEX}"); + } + + mreqn.imr_ifindex = ifr.ifr_ifindex; + } + else if (strchr(CONFIG->SHCUPD_MCASTIF,'.')) { /* appears to be an ipv4 address */ + mreqn.imr_address.s_addr = inet_addr(CONFIG->SHCUPD_MCASTIF); + } + else { /* appears to be an iface index */ + mreqn.imr_ifindex = atoi(CONFIG->SHCUPD_MCASTIF); + } + } + + if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0) { + if (errno != EINVAL) { /* EINVAL if it is not a multicast address, + not an error we consider unicast */ + fail("{setsockopt: IP_ADD_MEMBERSIP}"); + } + } + else { /* this is a multicast address */ + unsigned char loop = 0; + + if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { + fail("{setsockopt: IP_MULTICAST_LOOP}"); + } + } + + /* optional set sockopts for sending to multicast msg */ + if (CONFIG->SHCUPD_MCASTIF && + setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)) < 0) { + fail("{setsockopt: IP_MULTICAST_IF}"); + } + + if (CONFIG->SHCUPD_MCASTTTL) { + unsigned char ttl; + + ttl = (unsigned char)atoi(CONFIG->SHCUPD_MCASTTTL); + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { + fail("{setsockopt: IP_MULTICAST_TTL}"); + } + } + + } +#ifdef IPV6_ADD_MEMBERSHIP + else if (ai->ai_addr->sa_family == AF_INET6) { + struct ipv6_mreq mreq; + + memset(&mreq, 0, sizeof(mreq)); + memcpy(&mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, + sizeof(mreq.ipv6mr_multiaddr)); + + if (CONFIG->SHCUPD_MCASTIF) { + if (isalpha(*CONFIG->SHCUPD_MCASTIF)) { /* appears to be an iface name */ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + if (strlen(CONFIG->SHCUPD_MCASTIF) > IFNAMSIZ) { + ERR("Error iface name is too long [%s]\n",CONFIG->SHCUPD_MCASTIF); + exit(1); + } + + memcpy(ifr.ifr_name, CONFIG->SHCUPD_MCASTIF, strlen(CONFIG->SHCUPD_MCASTIF)); + if (ioctl(s, SIOCGIFINDEX, &ifr)) { + fail("{ioctl: SIOCGIFINDEX}"); + } + + mreq.ipv6mr_interface = ifr.ifr_ifindex; + } + else { /* option appears to be an iface index */ + mreq.ipv6mr_interface = atoi(CONFIG->SHCUPD_MCASTIF); + } + } + + if (setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + if (errno != EINVAL) { /* EINVAL if it is not a multicast address, + not an error we consider unicast */ + fail("{setsockopt: IPV6_ADD_MEMBERSIP}"); + } + } + else { /* this is a multicast address */ + unsigned int loop = 0; + + if(setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { + fail("{setsockopt: IPV6_MULTICAST_LOOP}"); + } + } + + /* optional set sockopts for sending to multicast msg */ + if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, + &mreq.ipv6mr_interface, sizeof(mreq.ipv6mr_interface)) < 0) { + fail("{setsockopt: IPV6_MULTICAST_IF}"); + } + + if (CONFIG->SHCUPD_MCASTTTL) { + int hops; + + hops = atoi(CONFIG->SHCUPD_MCASTTTL); + if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { + fail("{setsockopt: IPV6_MULTICAST_HOPS}"); + } + } + } +#endif /* IPV6_ADD_MEMBERSHIP */ + + if (bind(s, ai->ai_addr, ai->ai_addrlen)) { + fail("{bind-socket}"); + } + + freeaddrinfo(ai); + + return s; +} + +#endif /*USE_SHARED_CACHE */ + +RSA *load_rsa_privatekey(SSL_CTX *ctx, const char *file) { + BIO *bio; + RSA *rsa; + + bio = BIO_new_file(file, "r"); + if (!bio) { + ERR_print_errors_fp(stderr); + return NULL; + } + + rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, + ctx->default_passwd_callback, ctx->default_passwd_callback_userdata); + BIO_free(bio); + + return rsa; +} + +#ifndef OPENSSL_NO_TLSEXT +/* + * Switch the context of the current SSL object to the most appropriate one + * based on the SNI header + */ +int sni_switch_ctx(SSL *ssl, int *al, void *data) { + (void)data; + (void)al; + const char *servername; + const ctx_list *cl; + + servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (!servername) return SSL_TLSEXT_ERR_NOACK; + + // For now, just compare servernames as case insensitive strings. Someday, + // it might be nice to Do The Right Thing around star certs. + for (cl = sni_ctxs; cl != NULL; cl = cl->next) { + if (strcasecmp(servername, cl->servername) == 0) { + SSL_set_SSL_CTX(ssl, cl->ctx); + return SSL_TLSEXT_ERR_NOACK; + } + } + + return SSL_TLSEXT_ERR_NOACK; +} +#endif /* OPENSSL_NO_TLSEXT */ + + +/* + * Initialize an SSL context + */ + +SSL_CTX *make_ctx(const char *pemfile) { + SSL_CTX *ctx; + RSA *rsa; + + long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; + +#ifdef SSL_OP_NO_COMPRESSION + ssloptions |= SSL_OP_NO_COMPRESSION; +#endif + + if (CONFIG->ETYPE == ENC_TLS) { + ctx = SSL_CTX_new((CONFIG->PMODE == SSL_CLIENT) ? + TLSv1_client_method() : TLSv1_server_method()); + } else if (CONFIG->ETYPE == ENC_SSL) { + ctx = SSL_CTX_new((CONFIG->PMODE == SSL_CLIENT) ? + SSLv23_client_method() : SSLv23_server_method()); + } else { + assert(CONFIG->ETYPE == ENC_TLS || CONFIG->ETYPE == ENC_SSL); + return NULL; // Won't happen, but gcc was complaining + } + + SSL_CTX_set_options(ctx, ssloptions); + SSL_CTX_set_info_callback(ctx, info_callback); + + if (CONFIG->CIPHER_SUITE) { + if (SSL_CTX_set_cipher_list(ctx, CONFIG->CIPHER_SUITE) != 1) { + ERR_print_errors_fp(stderr); + } + } + + if (CONFIG->PREFER_SERVER_CIPHERS) { + SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } + + if (CONFIG->PMODE == SSL_CLIENT) { + return ctx; + } + + /* SSL_SERVER Mode stuff */ + if (SSL_CTX_use_certificate_chain_file(ctx, pemfile) <= 0) { + ERR_print_errors_fp(stderr); + exit(1); + } + + rsa = load_rsa_privatekey(ctx, pemfile); + if (!rsa) { + ERR("Error loading rsa private key\n"); + exit(1); + } + + if (SSL_CTX_use_RSAPrivateKey(ctx, rsa) <= 0) { + ERR_print_errors_fp(stderr); + exit(1); + } + +#ifndef OPENSSL_NO_DH + init_dh(ctx, pemfile); +#endif /* OPENSSL_NO_DH */ + +#ifndef OPENSSL_NO_TLSEXT + if (!SSL_CTX_set_tlsext_servername_callback(ctx, sni_switch_ctx)) { + ERR("Error setting up SNI support\n"); + } +#endif /* OPENSSL_NO_TLSEXT */ + +#ifdef USE_SHARED_CACHE + if (CONFIG->SHARED_CACHE) { + if (shared_context_init(ctx, CONFIG->SHARED_CACHE) < 0) { + ERR("Unable to alloc memory for shared cache.\n"); + exit(1); + } + if (CONFIG->SHCUPD_PORT) { + if (compute_secret(rsa, shared_secret) < 0) { + ERR("Unable to compute shared secret.\n"); + exit(1); + } + + /* Force tls tickets cause keys differs */ + SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); + + if (*shcupd_peers) { + shsess_set_new_cbk(shcupd_session_new); + } + } + } +#endif + + RSA_free(rsa); + return ctx; +} + +/* Init library and load specified certificate. + * Establishes a SSL_ctx, to act as a template for + * each connection */ +void init_openssl() { + SSL_library_init(); + SSL_load_error_strings(); + + assert(CONFIG->CERT_FILES != NULL); + + // The first file (i.e., the last file listed in config) is always the + // "default" cert + default_ctx = make_ctx(CONFIG->CERT_FILES->CERT_FILE); + +#ifndef OPENSSL_NO_TLSEXT + { + struct cert_files *cf; + int i; + SSL_CTX *ctx; + X509 *x509; + BIO *f; + + STACK_OF(GENERAL_NAME) *names = NULL; + GENERAL_NAME *name; + +#define PUSH_CTX(asn1_str, ctx) \ + do { \ + struct ctx_list *cl; \ + cl = calloc(1, sizeof(*cl)); \ + ASN1_STRING_to_UTF8((unsigned char **)&cl->servername, asn1_str); \ + cl->ctx = ctx; \ + cl->next = sni_ctxs; \ + sni_ctxs = cl; \ + } while (0) + + // Go through the list of PEMs and make some SSL contexts for them. We also + // keep track of the names associated with each cert so we can do SNI on + // them later + for (cf = CONFIG->CERT_FILES->NEXT; cf != NULL; cf = cf->NEXT) { + ctx = make_ctx(cf->CERT_FILE); + f = BIO_new(BIO_s_file()); + // TODO: error checking + if (!BIO_read_filename(f, cf->CERT_FILE)) { + ERR("Could not read cert '%s'\n", cf->CERT_FILE); + } + x509 = PEM_read_bio_X509_AUX(f, NULL, NULL, NULL); + BIO_free(f); + + // First, look for Subject Alternative Names + names = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL); + for (i = 0; i < sk_GENERAL_NAME_num(names); i++) { + name = sk_GENERAL_NAME_value(names, i); + if (name->type == GEN_DNS) { + PUSH_CTX(name->d.dNSName, ctx); + } + } + if (sk_GENERAL_NAME_num(names) > 0) { + sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); + // If we actally found some, don't bother looking any further + continue; + } else if (names != NULL) { + sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); + } + + // Now we're left looking at the CN on the cert + X509_NAME *x509_name = X509_get_subject_name(x509); + i = X509_NAME_get_index_by_NID(x509_name, NID_commonName, -1); + if (i < 0) { + ERR("Could not find Subject Alternative Names or a CN on cert %s\n", + cf->CERT_FILE); + } + X509_NAME_ENTRY *x509_entry = X509_NAME_get_entry(x509_name, i); + PUSH_CTX(x509_entry->value, ctx); + } + } +#undef APPEND_CTX +#endif /* OPENSSL_NO_TLSEXT */ + + if (CONFIG->ENGINE) { + ENGINE *e = NULL; + ENGINE_load_builtin_engines(); + if (!strcmp(CONFIG->ENGINE, "auto")) + ENGINE_register_all_complete(); + else { + if ((e = ENGINE_by_id(CONFIG->ENGINE)) == NULL || + !ENGINE_init(e) || + !ENGINE_set_default(e, ENGINE_METHOD_ALL)) { + ERR_print_errors_fp(stderr); + exit(1); + } + LOG("{core} will use OpenSSL engine %s.\n", ENGINE_get_id(e)); + ENGINE_finish(e); + ENGINE_free(e); + } + } +} + +static void prepare_proxy_line(struct sockaddr* ai_addr) { + tcp_proxy_line[0] = 0; + char tcp6_address_string[INET6_ADDRSTRLEN]; + + if (ai_addr->sa_family == AF_INET) { + struct sockaddr_in* addr = (struct sockaddr_in*)ai_addr; + size_t res = snprintf(tcp_proxy_line, + sizeof(tcp_proxy_line), + "PROXY %%s %%s %s %%hu %hu\r\n", + inet_ntoa(addr->sin_addr), + ntohs(addr->sin_port)); + assert(res < sizeof(tcp_proxy_line)); + } + else if (ai_addr->sa_family == AF_INET6 ) { + struct sockaddr_in6* addr = (struct sockaddr_in6*)ai_addr; + inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN); + size_t res = snprintf(tcp_proxy_line, + sizeof(tcp_proxy_line), + "PROXY %%s %%s %s %%hu %hu\r\n", + tcp6_address_string, + ntohs(addr->sin6_port)); + assert(res < sizeof(tcp_proxy_line)); + } + else { + ERR("The --write-proxy mode is not implemented for this address family.\n"); + exit(1); + } +} + +/* Create the bound socket in the parent process */ +static int create_main_socket() { + struct addrinfo *ai, hints; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + const int gai_err = getaddrinfo(CONFIG->FRONT_IP, CONFIG->FRONT_PORT, + &hints, &ai); + if (gai_err != 0) { + ERR("{getaddrinfo}: [%s]\n", gai_strerror(gai_err)); + exit(1); + } + + int s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); + + if (s == -1) + fail("{socket: main}"); + + int t = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)); +#ifdef SO_REUSEPORT + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &t, sizeof(int)); +#endif + setnonblocking(s); + + if (bind(s, ai->ai_addr, ai->ai_addrlen)) { + fail("{bind-socket}"); + } + +#ifndef NO_DEFER_ACCEPT +#if TCP_DEFER_ACCEPT + int timeout = 1; + setsockopt(s, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int) ); +#endif /* TCP_DEFER_ACCEPT */ +#endif + + prepare_proxy_line(ai->ai_addr); + + freeaddrinfo(ai); + listen(s, CONFIG->BACKLOG); + + return s; +} + +/* Initiate a clear-text nonblocking connect() to the backend IP on behalf + * of a newly connected upstream (encrypted) client*/ +static int create_back_socket() { + int s = socket(backaddr->ai_family, SOCK_STREAM, IPPROTO_TCP); + + if (s == -1) + return -1; + + int flag = 1; + int ret = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); + if (ret == -1) { + perror("Couldn't setsockopt to backend (TCP_NODELAY)\n"); + } + setnonblocking(s); + + return s; +} + +/* Only enable a libev ev_io event if the proxied connection still + * has both up and down connected */ +static void safe_enable_io(proxystate *ps, ev_io *w) { + if (!ps->want_shutdown) + ev_io_start(loop, w); +} + +/* Only enable a libev ev_io event if the proxied connection still + * has both up and down connected */ +static void shutdown_proxy(proxystate *ps, SHUTDOWN_REQUESTOR req) { + if (ps->want_shutdown || req == SHUTDOWN_HARD) { + ev_io_stop(loop, &ps->ev_w_ssl); + ev_io_stop(loop, &ps->ev_r_ssl); + ev_io_stop(loop, &ps->ev_w_handshake); + ev_io_stop(loop, &ps->ev_r_handshake); + ev_io_stop(loop, &ps->ev_w_connect); + ev_io_stop(loop, &ps->ev_w_clear); + ev_io_stop(loop, &ps->ev_r_clear); + ev_io_stop(loop, &ps->ev_proxy); + + close(ps->fd_up); + close(ps->fd_down); + + SSL_set_shutdown(ps->ssl, SSL_SENT_SHUTDOWN); + SSL_free(ps->ssl); + + free(ps); + } + else { + ps->want_shutdown = 1; + if (req == SHUTDOWN_CLEAR && ringbuffer_is_empty(&ps->ring_clear2ssl)) + shutdown_proxy(ps, SHUTDOWN_HARD); + else if (req == SHUTDOWN_SSL && ringbuffer_is_empty(&ps->ring_ssl2clear)) + shutdown_proxy(ps, SHUTDOWN_HARD); + } +} + +/* Handle various socket errors */ +static void handle_socket_errno(proxystate *ps, int backend) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return; + + if (errno == ECONNRESET) + ERR("{%s} Connection reset by peer\n", backend ? "backend" : "client"); + else if (errno == ETIMEDOUT) + ERR("{%s} Connection to backend timed out\n", backend ? "backend" : "client"); + else if (errno == EPIPE) + ERR("{%s} Broken pipe to backend (EPIPE)\n", backend ? "backend" : "client"); + else + perror("{backend} [errno]"); + shutdown_proxy(ps, SHUTDOWN_CLEAR); +} +/* Start connect to backend */ +static void start_connect(proxystate *ps) { + int t = 1; + t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen); + if (t == 0 || errno == EINPROGRESS || errno == EINTR) { + ev_io_start(loop, &ps->ev_w_connect); + return ; + } + perror("{backend-connect}"); + shutdown_proxy(ps, SHUTDOWN_HARD); +} + +/* Read some data from the backend when libev says data is available-- + * write it into the upstream buffer and make sure the write event is + * enabled for the upstream socket */ +static void clear_read(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + proxystate *ps = (proxystate *)w->data; + if (ps->want_shutdown) { + ev_io_stop(loop, &ps->ev_r_clear); + return; + } + int fd = w->fd; + char * buf = ringbuffer_write_ptr(&ps->ring_clear2ssl); + t = recv(fd, buf, RING_DATA_LEN, 0); + + if (t > 0) { + ringbuffer_write_append(&ps->ring_clear2ssl, t); + if (ringbuffer_is_full(&ps->ring_clear2ssl)) + ev_io_stop(loop, &ps->ev_r_clear); + if (ps->handshaked) + safe_enable_io(ps, &ps->ev_w_ssl); + } + else if (t == 0) { + LOG("{%s} Connection closed\n", fd == ps->fd_down ? "backend" : "client"); + shutdown_proxy(ps, SHUTDOWN_CLEAR); + } + else { + assert(t == -1); + handle_socket_errno(ps, fd == ps->fd_down ? 1 : 0); + } +} +/* Write some data, previously received on the secure upstream socket, + * out of the downstream buffer and onto the backend socket */ +static void clear_write(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + proxystate *ps = (proxystate *)w->data; + int fd = w->fd; + int sz; + + assert(!ringbuffer_is_empty(&ps->ring_ssl2clear)); + + char *next = ringbuffer_read_next(&ps->ring_ssl2clear, &sz); + t = send(fd, next, sz, MSG_NOSIGNAL); + + if (t > 0) { + if (t == sz) { + ringbuffer_read_pop(&ps->ring_ssl2clear); + if (ps->handshaked) + safe_enable_io(ps, &ps->ev_r_ssl); + if (ringbuffer_is_empty(&ps->ring_ssl2clear)) { + if (ps->want_shutdown) { + shutdown_proxy(ps, SHUTDOWN_HARD); + return; // dealloc'd + } + ev_io_stop(loop, &ps->ev_w_clear); + } + } + else { + ringbuffer_read_skip(&ps->ring_ssl2clear, t); + } + } + else { + assert(t == -1); + handle_socket_errno(ps, fd == ps->fd_down ? 1 : 0); + } +} + +static void start_handshake(proxystate *ps, int err); + +/* Continue/complete the asynchronous connect() before starting data transmission + * between front/backend */ +static void handle_connect(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + proxystate *ps = (proxystate *)w->data; + t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen); + if (!t || errno == EISCONN || !errno) { + ev_io_stop(loop, &ps->ev_w_connect); + + if (!ps->clear_connected) { + ps->clear_connected = 1; + + /* if incoming buffer is not full */ + if (!ringbuffer_is_full(&ps->ring_clear2ssl)) + safe_enable_io(ps, &ps->ev_r_clear); + + /* if outgoing buffer is not empty */ + if (!ringbuffer_is_empty(&ps->ring_ssl2clear)) + // not safe.. we want to resume stream even during half-closed + ev_io_start(loop, &ps->ev_w_clear); + } + else { + /* Clear side already connected so connect is on secure side: perform handshake */ + start_handshake(ps, SSL_ERROR_WANT_WRITE); + } + } + else if (errno == EINPROGRESS || errno == EINTR || errno == EALREADY) { + /* do nothing, we'll get phoned home again... */ + } + else { + perror("{backend-connect}"); + shutdown_proxy(ps, SHUTDOWN_HARD); + } +} + +/* Upon receiving a signal from OpenSSL that a handshake is required, re-wire + * the read/write events to hook up to the handshake handlers */ +static void start_handshake(proxystate *ps, int err) { + ev_io_stop(loop, &ps->ev_r_ssl); + ev_io_stop(loop, &ps->ev_w_ssl); + + ps->handshaked = 0; + + if (err == SSL_ERROR_WANT_READ) + ev_io_start(loop, &ps->ev_r_handshake); + else if (err == SSL_ERROR_WANT_WRITE) + ev_io_start(loop, &ps->ev_w_handshake); +} + +/* After OpenSSL is done with a handshake, re-wire standard read/write handlers + * for data transmission */ +static void end_handshake(proxystate *ps) { + char tcp6_address_string[INET6_ADDRSTRLEN]; + size_t written = 0; + ev_io_stop(loop, &ps->ev_r_handshake); + ev_io_stop(loop, &ps->ev_w_handshake); + + /* Disable renegotiation (CVE-2009-3555) */ + if (ps->ssl->s3) { + ps->ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; + } + ps->handshaked = 1; + + /* Check if clear side is connected */ + if (!ps->clear_connected) { + if (CONFIG->WRITE_PROXY_LINE) { + char *ring_pnt = ringbuffer_write_ptr(&ps->ring_ssl2clear); + assert(ps->remote_ip.ss_family == AF_INET || + ps->remote_ip.ss_family == AF_INET6); + if(ps->remote_ip.ss_family == AF_INET) { + struct sockaddr_in* addr = (struct sockaddr_in*)&ps->remote_ip; + written = snprintf(ring_pnt, + RING_DATA_LEN, + tcp_proxy_line, + "TCP4", + inet_ntoa(addr->sin_addr), + ntohs(addr->sin_port)); + } + else if (ps->remote_ip.ss_family == AF_INET6) { + struct sockaddr_in6* addr = (struct sockaddr_in6*)&ps->remote_ip; + inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN); + written = snprintf(ring_pnt, + RING_DATA_LEN, + tcp_proxy_line, + "TCP6", + tcp6_address_string, + ntohs(addr->sin6_port)); + } + ringbuffer_write_append(&ps->ring_ssl2clear, written); + } + else if (CONFIG->WRITE_IP_OCTET) { + char *ring_pnt = ringbuffer_write_ptr(&ps->ring_ssl2clear); + assert(ps->remote_ip.ss_family == AF_INET || + ps->remote_ip.ss_family == AF_INET6); + *ring_pnt++ = (unsigned char) ps->remote_ip.ss_family; + if (ps->remote_ip.ss_family == AF_INET6) { + memcpy(ring_pnt, &((struct sockaddr_in6 *) &ps->remote_ip) + ->sin6_addr.s6_addr, 16U); + ringbuffer_write_append(&ps->ring_ssl2clear, 1U + 16U); + } + else { + memcpy(ring_pnt, &((struct sockaddr_in *) &ps->remote_ip) + ->sin_addr.s_addr, 4U); + ringbuffer_write_append(&ps->ring_ssl2clear, 1U + 4U); + } + } + /* start connect now */ + start_connect(ps); + } + else { + /* stud used in client mode, keep client session ) */ + if (!SSL_session_reused(ps->ssl)) { + if (client_session) + SSL_SESSION_free(client_session); + client_session = SSL_get1_session(ps->ssl); + } + } + + /* if incoming buffer is not full */ + if (!ringbuffer_is_full(&ps->ring_ssl2clear)) + safe_enable_io(ps, &ps->ev_r_ssl); + + /* if outgoing buffer is not empty */ + if (!ringbuffer_is_empty(&ps->ring_clear2ssl)) + // not safe.. we want to resume stream even during half-closed + ev_io_start(loop, &ps->ev_w_ssl); +} + +static void client_proxy_proxy(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + char *proxy = tcp_proxy_line, *end = tcp_proxy_line + sizeof(tcp_proxy_line); + proxystate *ps = (proxystate *)w->data; + BIO *b = SSL_get_rbio(ps->ssl); + + // Copy characters one-by-one until we hit a \n or an error + while (proxy != end && (t = BIO_read(b, proxy, 1)) == 1) { + if (*proxy++ == '\n') break; + } + + if (proxy == end) { + LOG("{client} Unexpectedly long PROXY line. Perhaps a malformed request?"); + shutdown_proxy(ps, SHUTDOWN_SSL); + } + else if (t == 1) { + if (ringbuffer_is_full(&ps->ring_ssl2clear)) { + LOG("{client} Error writing PROXY line"); + shutdown_proxy(ps, SHUTDOWN_SSL); + return; + } + + char *ring = ringbuffer_write_ptr(&ps->ring_ssl2clear); + memcpy(ring, tcp_proxy_line, proxy - tcp_proxy_line); + ringbuffer_write_append(&ps->ring_ssl2clear, proxy - tcp_proxy_line); + + // Finished reading the PROXY header + if (*(proxy - 1) == '\n') { + ev_io_stop(loop, &ps->ev_proxy); + + // Start the real handshake + start_handshake(ps, SSL_ERROR_WANT_READ); + } + } + else if (!BIO_should_retry(b)) { + LOG("{client} Unexpected error reading PROXY line"); + shutdown_proxy(ps, SHUTDOWN_SSL); + } +} + +/* The libev I/O handler during the OpenSSL handshake phase. Basically, just + * let OpenSSL do what it likes with the socket and obey its requests for reads + * or writes */ +static void client_handshake(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + proxystate *ps = (proxystate *)w->data; + + t = SSL_do_handshake(ps->ssl); + if (t == 1) { + end_handshake(ps); + } + else { + int err = SSL_get_error(ps->ssl, t); + if (err == SSL_ERROR_WANT_READ) { + ev_io_stop(loop, &ps->ev_w_handshake); + ev_io_start(loop, &ps->ev_r_handshake); + } + else if (err == SSL_ERROR_WANT_WRITE) { + ev_io_stop(loop, &ps->ev_r_handshake); + ev_io_start(loop, &ps->ev_w_handshake); + } + else if (err == SSL_ERROR_ZERO_RETURN) { + LOG("{%s} Connection closed (in handshake)\n", w->fd == ps->fd_up ? "client" : "backend"); + shutdown_proxy(ps, SHUTDOWN_SSL); + } + else { + LOG("{%s} Unexpected SSL error (in handshake): %d\n", w->fd == ps->fd_up ? "client" : "backend", err); + shutdown_proxy(ps, SHUTDOWN_SSL); + } + } +} + +/* Handle a socket error condition passed to us from OpenSSL */ +static void handle_fatal_ssl_error(proxystate *ps, int err, int backend) { + if (err == SSL_ERROR_ZERO_RETURN) + ERR("{%s} Connection closed (in data)\n", backend ? "backend" : "client"); + else if (err == SSL_ERROR_SYSCALL) + if (errno == 0) + ERR("{%s} Connection closed (in data)\n", backend ? "backend" : "client"); + else + perror(backend ? "{backend} [errno] " : "{client} [errno] "); + else + ERR("{%s} Unexpected SSL_read error: %d\n", backend ? "backend" : "client" , err); + shutdown_proxy(ps, SHUTDOWN_SSL); +} + +/* Read some data from the upstream secure socket via OpenSSL, + * and buffer anything we get for writing to the backend */ +static void ssl_read(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + proxystate *ps = (proxystate *)w->data; + if (ps->want_shutdown) { + ev_io_stop(loop, &ps->ev_r_ssl); + return; + } + char * buf = ringbuffer_write_ptr(&ps->ring_ssl2clear); + t = SSL_read(ps->ssl, buf, RING_DATA_LEN); + + /* Fix CVE-2009-3555. Disable reneg if started by client. */ + if (ps->renegotiation) { + shutdown_proxy(ps, SHUTDOWN_SSL); + return; + } + + if (t > 0) { + ringbuffer_write_append(&ps->ring_ssl2clear, t); + if (ringbuffer_is_full(&ps->ring_ssl2clear)) + ev_io_stop(loop, &ps->ev_r_ssl); + if (ps->clear_connected) + safe_enable_io(ps, &ps->ev_w_clear); + } + else { + int err = SSL_get_error(ps->ssl, t); + if (err == SSL_ERROR_WANT_WRITE) { + start_handshake(ps, err); + } + else if (err == SSL_ERROR_WANT_READ) { } /* incomplete SSL data */ + else + handle_fatal_ssl_error(ps, err, w->fd == ps->fd_up ? 0 : 1); + } +} + +/* Write some previously-buffered backend data upstream on the + * secure socket using OpenSSL */ +static void ssl_write(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + int t; + int sz; + proxystate *ps = (proxystate *)w->data; + assert(!ringbuffer_is_empty(&ps->ring_clear2ssl)); + char * next = ringbuffer_read_next(&ps->ring_clear2ssl, &sz); + t = SSL_write(ps->ssl, next, sz); + if (t > 0) { + if (t == sz) { + ringbuffer_read_pop(&ps->ring_clear2ssl); + if (ps->clear_connected) + safe_enable_io(ps, &ps->ev_r_clear); // can be re-enabled b/c we've popped + if (ringbuffer_is_empty(&ps->ring_clear2ssl)) { + if (ps->want_shutdown) { + shutdown_proxy(ps, SHUTDOWN_HARD); + return; + } + ev_io_stop(loop, &ps->ev_w_ssl); + } + } + else { + ringbuffer_read_skip(&ps->ring_clear2ssl, t); + } + } + else { + int err = SSL_get_error(ps->ssl, t); + if (err == SSL_ERROR_WANT_READ) { + start_handshake(ps, err); + } + else if (err == SSL_ERROR_WANT_WRITE) {} /* incomplete SSL data */ + else + handle_fatal_ssl_error(ps, err, w->fd == ps->fd_up ? 0 : 1); + } +} + +/* libev read handler for the bound socket. Socket is accepted, + * the proxystate is allocated and initalized, and we're off the races + * connecting to the backend */ +static void handle_accept(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + (void) loop; + struct sockaddr_storage addr; + socklen_t sl = sizeof(addr); + int client = accept(w->fd, (struct sockaddr *) &addr, &sl); + printf("accepted %d\n", client); + if (client == -1) { + switch (errno) { + case EMFILE: + ERR("{client} accept() failed; too many open files for this process\n"); + break; + + case ENFILE: + ERR("{client} accept() failed; too many open files for this system\n"); + break; + + default: + assert(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN); + break; + } + return; + } + + int flag = 1; + int ret = setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) ); + if (ret == -1) { + perror("Couldn't setsockopt on client (TCP_NODELAY)\n"); + } +#ifdef TCP_CWND + int cwnd = 10; + ret = setsockopt(client, IPPROTO_TCP, TCP_CWND, &cwnd, sizeof(cwnd)); + if (ret == -1) { + perror("Couldn't setsockopt on client (TCP_CWND)\n"); + } +#endif + + setnonblocking(client); + settcpkeepalive(client); + + int back = create_back_socket(); + + if (back == -1) { + close(client); + perror("{backend-socket}"); + return; + } + + SSL_CTX * ctx = (SSL_CTX *)w->data; + SSL *ssl = SSL_new(ctx); + long mode = SSL_MODE_ENABLE_PARTIAL_WRITE; +#ifdef SSL_MODE_RELEASE_BUFFERS + mode |= SSL_MODE_RELEASE_BUFFERS; +#endif + SSL_set_mode(ssl, mode); + SSL_set_accept_state(ssl); + SSL_set_fd(ssl, client); + + proxystate *ps = (proxystate *)malloc(sizeof(proxystate)); + + ps->fd_up = client; + ps->fd_down = back; + ps->ssl = ssl; + ps->want_shutdown = 0; + ps->clear_connected = 0; + ps->handshaked = 0; + ps->renegotiation = 0; + ps->remote_ip = addr; + ringbuffer_init(&ps->ring_clear2ssl); + ringbuffer_init(&ps->ring_ssl2clear); + + /* set up events */ + ev_io_init(&ps->ev_r_ssl, ssl_read, client, EV_READ); + ev_io_init(&ps->ev_w_ssl, ssl_write, client, EV_WRITE); + + ev_io_init(&ps->ev_r_handshake, client_handshake, client, EV_READ); + ev_io_init(&ps->ev_w_handshake, client_handshake, client, EV_WRITE); + + ev_io_init(&ps->ev_proxy, client_proxy_proxy, client, EV_READ); + + ev_io_init(&ps->ev_w_connect, handle_connect, back, EV_WRITE); + + ev_io_init(&ps->ev_w_clear, clear_write, back, EV_WRITE); + ev_io_init(&ps->ev_r_clear, clear_read, back, EV_READ); + + ps->ev_r_ssl.data = ps; + ps->ev_w_ssl.data = ps; + ps->ev_r_clear.data = ps; + ps->ev_w_clear.data = ps; + ps->ev_proxy.data = ps; + ps->ev_w_connect.data = ps; + ps->ev_r_handshake.data = ps; + ps->ev_w_handshake.data = ps; + + /* Link back proxystate to SSL state */ + SSL_set_app_data(ssl, ps); + + if (CONFIG->PROXY_PROXY_LINE) { + ev_io_start(loop, &ps->ev_proxy); + } + else { + start_handshake(ps, SSL_ERROR_WANT_READ); /* for client-first handshake */ + } +} + + +static void check_ppid(struct ev_loop *loop, ev_timer *w, int revents) { + (void) revents; + pid_t ppid = getppid(); + if (ppid != master_pid) { + ERR("{core} Process %d detected parent death, closing listener socket.\n", child_num); + ev_timer_stop(loop, w); + ev_io_stop(loop, &listener); + close(listener_socket); + } + +} + +static void handle_clear_accept(struct ev_loop *loop, ev_io *w, int revents) { + (void) revents; + (void) loop; + struct sockaddr_storage addr; + socklen_t sl = sizeof(addr); + int client = accept(w->fd, (struct sockaddr *) &addr, &sl); + + printf("accepted clear %d\n", client); + if (client == -1) { + switch (errno) { + case EMFILE: + ERR("{client} accept() failed; too many open files for this process\n"); + break; + + case ENFILE: + ERR("{client} accept() failed; too many open files for this system\n"); + break; + + default: + assert(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN); + break; + } + return; + } + + int flag = 1; + int ret = setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) ); + if (ret == -1) { + perror("Couldn't setsockopt on client (TCP_NODELAY)\n"); + } +#ifdef TCP_CWND + int cwnd = 10; + ret = setsockopt(client, IPPROTO_TCP, TCP_CWND, &cwnd, sizeof(cwnd)); + if (ret == -1) { + perror("Couldn't setsockopt on client (TCP_CWND)\n"); + } +#endif + + setnonblocking(client); + settcpkeepalive(client); + + int back = create_back_socket(); + + if (back == -1) { + close(client); + perror("{backend-socket}"); + return; + } + + SSL_CTX * ctx = (SSL_CTX *)w->data; + SSL *ssl = SSL_new(ctx); + long mode = SSL_MODE_ENABLE_PARTIAL_WRITE; +#ifdef SSL_MODE_RELEASE_BUFFERS + mode |= SSL_MODE_RELEASE_BUFFERS; +#endif + SSL_set_mode(ssl, mode); + SSL_set_connect_state(ssl); + SSL_set_fd(ssl, back); + if (client_session) + SSL_set_session(ssl, client_session); + + proxystate *ps = (proxystate *)malloc(sizeof(proxystate)); + + ps->fd_up = client; + ps->fd_down = back; + ps->ssl = ssl; + ps->want_shutdown = 0; + ps->clear_connected = 1; + ps->handshaked = 0; + ps->renegotiation = 0; + ps->remote_ip = addr; + ringbuffer_init(&ps->ring_clear2ssl); + ringbuffer_init(&ps->ring_ssl2clear); + + /* set up events */ + ev_io_init(&ps->ev_r_clear, clear_read, client, EV_READ); + ev_io_init(&ps->ev_w_clear, clear_write, client, EV_WRITE); + + ev_io_init(&ps->ev_w_connect, handle_connect, back, EV_WRITE); + + ev_io_init(&ps->ev_r_handshake, client_handshake, back, EV_READ); + ev_io_init(&ps->ev_w_handshake, client_handshake, back, EV_WRITE); + + + ev_io_init(&ps->ev_w_ssl, ssl_write, back, EV_WRITE); + ev_io_init(&ps->ev_r_ssl, ssl_read, back, EV_READ); + + ps->ev_r_ssl.data = ps; + ps->ev_w_ssl.data = ps; + ps->ev_r_clear.data = ps; + ps->ev_w_clear.data = ps; + ps->ev_w_connect.data = ps; + ps->ev_r_handshake.data = ps; + ps->ev_w_handshake.data = ps; + + /* Link back proxystate to SSL state */ + SSL_set_app_data(ssl, ps); + + ev_io_start(loop, &ps->ev_r_clear); + start_connect(ps); /* start connect */ +} + +/* Set up the child (worker) process including libev event loop, read event + * on the bound socket, etc */ +static void handle_connections() { + LOG("{core} Process %d online\n", child_num); + + /* child cannot create new children... */ + create_workers = 0; + +#if defined(CPU_ZERO) && defined(CPU_SET) + cpu_set_t cpus; + + CPU_ZERO(&cpus); + CPU_SET(child_num, &cpus); + + int res = sched_setaffinity(0, sizeof(cpus), &cpus); + if (!res) + LOG("{core} Successfully attached to CPU #%d\n", child_num); + else + ERR("{core-warning} Unable to attach to CPU #%d; do you have that many cores?\n", child_num); +#endif + + loop = ev_default_loop(EVFLAG_AUTO); + + ev_timer timer_ppid_check; + ev_timer_init(&timer_ppid_check, check_ppid, 1.0, 1.0); + ev_timer_start(loop, &timer_ppid_check); + + ev_io_init(&listener, (CONFIG->PMODE == SSL_CLIENT) ? handle_clear_accept : handle_accept, listener_socket, EV_READ); + listener.data = default_ctx; + ev_io_start(loop, &listener); + + ev_loop(loop, 0); + ERR("{core} Child %d exiting.\n", child_num); + exit(1); +} + +void change_root() { + if (chroot(CONFIG->CHROOT) == -1) + fail("chroot"); + if (chdir("/")) + fail("chdir"); +} + +void drop_privileges() { + if (setgid(CONFIG->GID)) + fail("setgid failed"); + if (setuid(CONFIG->UID)) + fail("setuid failed"); +} + + +void init_globals() { + /* backaddr */ + struct addrinfo hints; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + const int gai_err = getaddrinfo(CONFIG->BACK_IP, CONFIG->BACK_PORT, + &hints, &backaddr); + if (gai_err != 0) { + ERR("{getaddrinfo}: [%s]", gai_strerror(gai_err)); + exit(1); + } + +#ifdef USE_SHARED_CACHE + if (CONFIG->SHARED_CACHE) { + /* cache update peers addresses */ + shcupd_peer_opt *spo = CONFIG->SHCUPD_PEERS; + struct addrinfo **pai = shcupd_peers; + + while (spo->ip) { + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = 0; + const int gai_err = getaddrinfo(spo->ip, + spo->port ? spo->port : CONFIG->SHCUPD_PORT, &hints, pai); + if (gai_err != 0) { + ERR("{getaddrinfo}: [%s]", gai_strerror(gai_err)); + exit(1); + } + spo++; + pai++; + } + } +#endif + /* child_pids */ + if ((child_pids = calloc(CONFIG->NCORES, sizeof(pid_t))) == NULL) + fail("calloc"); + + if (CONFIG->SYSLOG) + openlog("stud", LOG_CONS | LOG_PID | LOG_NDELAY, CONFIG->SYSLOG_FACILITY); +} + +/* Forks COUNT children starting with START_INDEX. + * Each child's index is stored in child_num and its pid is stored in child_pids[child_num] + * so the parent can manage it later. */ +void start_children(int start_index, int count) { + /* don't do anything if we're not allowed to create new children */ + if (!create_workers) return; + + for (child_num = start_index; child_num < start_index + count; child_num++) { + int pid = fork(); + if (pid == -1) { + ERR("{core} fork() failed: %s; Goodbye cruel world!\n", strerror(errno)); + exit(1); + } + else if (pid == 0) { /* child */ + handle_connections(); + exit(0); + } + else { /* parent. Track new child. */ + child_pids[child_num] = pid; + } + } +} + +/* Forks a new child to replace the old, dead, one with the given PID.*/ +void replace_child_with_pid(pid_t pid) { + int i; + + /* find old child's slot and put a new child there */ + for (i = 0; i < CONFIG->NCORES; i++) { + if (child_pids[i] == pid) { + start_children(i, 1); + return; + } + } + + ERR("Cannot find index for child pid %d", pid); +} + +/* Manage status changes in child processes */ +static void do_wait(int __attribute__ ((unused)) signo) { + + int status; + int pid = wait(&status); + + if (pid == -1) { + if (errno == ECHILD) { + ERR("{core} All children have exited! Restarting...\n"); + start_children(0, CONFIG->NCORES); + } + else if (errno == EINTR) { + ERR("{core} Interrupted wait\n"); + } + else { + fail("wait"); + } + } + else { + if (WIFEXITED(status)) { + ERR("{core} Child %d exited with status %d. Replacing...\n", pid, WEXITSTATUS(status)); + replace_child_with_pid(pid); + } + else if (WIFSIGNALED(status)) { + ERR("{core} Child %d was terminated by signal %d. Replacing...\n", pid, WTERMSIG(status)); + replace_child_with_pid(pid); + } + } +} + +static void sigh_terminate (int __attribute__ ((unused)) signo) { + /* don't create any more children */ + create_workers = 0; + + /* are we the master? */ + if (getpid() == master_pid) { + LOG("{core} Received signal %d, shutting down.\n", signo); + + /* kill all children */ + int i; + for (i = 0; i < CONFIG->NCORES; i++) { + /* LOG("Stopping worker pid %d.\n", child_pids[i]); */ + if (child_pids[i] > 1 && kill(child_pids[i], SIGTERM) != 0) { + ERR("{core} Unable to send SIGTERM to worker pid %d: %s\n", child_pids[i], strerror(errno)); + } + } + /* LOG("Shutdown complete.\n"); */ + } + + /* this is it, we're done... */ + exit(0); +} + +void init_signals() { + struct sigaction act; + + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SIG_IGN; + + /* Avoid getting PIPE signal when writing to a closed file descriptor */ + if (sigaction(SIGPIPE, &act, NULL) < 0) + fail("sigaction - sigpipe"); + + /* We don't care if someone stops and starts a child process with kill (1) */ + act.sa_flags = SA_NOCLDSTOP; + + act.sa_handler = do_wait; + + /* We do care when child processes change status */ + if (sigaction(SIGCHLD, &act, NULL) < 0) + fail("sigaction - sigchld"); + + /* catch INT and TERM signals */ + act.sa_flags = 0; + act.sa_handler = sigh_terminate; + if (sigaction(SIGINT, &act, NULL) < 0) { + ERR("Unable to register SIGINT signal handler: %s\n", strerror(errno)); + exit(1); + } + if (sigaction(SIGTERM, &act, NULL) < 0) { + ERR("Unable to register SIGTERM signal handler: %s\n", strerror(errno)); + exit(1); + } +} + +void daemonize () { + /* go to root directory */ + if (chdir("/") != 0) { + ERR("Unable change directory to /: %s\n", strerror(errno)); + exit(1); + } + + /* let's make some children, baby :) */ + pid_t pid = fork(); + if (pid < 0) { + ERR("Unable to daemonize: fork failed: %s\n", strerror(errno)); + exit(1); + } + + /* am i the parent? */ + if (pid != 0) { + printf("{core} Daemonized as pid %d.\n", pid); + exit(0); + } + + /* close standard streams */ + fclose(stdin); + fclose(stdout); + fclose(stderr); + + /* reopen standard streams to null device */ + stdin = fopen(NULL_DEV, "r"); + if (stdin == NULL) { + ERR("Unable to reopen stdin to %s: %s\n", NULL_DEV, strerror(errno)); + exit(1); + } + stdout = fopen(NULL_DEV, "w"); + if (stdout == NULL) { + ERR("Unable to reopen stdout to %s: %s\n", NULL_DEV, strerror(errno)); + exit(1); + } + stderr = fopen(NULL_DEV, "w"); + if (stderr == NULL) { + ERR("Unable to reopen stderr to %s: %s\n", NULL_DEV, strerror(errno)); + exit(1); + } + + /* this is child, the new master */ + pid_t s = setsid(); + if (s < 0) { + ERR("Unable to create new session, setsid(2) failed: %s :: %d\n", strerror(errno), s); + exit(1); + } + + LOG("Successfully daemonized as pid %d.\n", getpid()); +} + +void openssl_check_version() { + /* detect OpenSSL version in runtime */ + openssl_version = SSLeay(); + + /* check if we're running the same openssl that we were */ + /* compiled with */ + if ((openssl_version ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { + ERR( + "WARNING: {core} OpenSSL version mismatch; stud was compiled with %lx, now using %lx.\n", + (unsigned long int) OPENSSL_VERSION_NUMBER, + (unsigned long int) openssl_version + ); + /* now what? exit now? */ + /* exit(1); */ + } + + LOG("{core} Using OpenSSL version %lx.\n", (unsigned long int) openssl_version); +} + +/* Process command line args, create the bound socket, + * spawn child (worker) processes, and respawn if any die */ +int main(int argc, char **argv) { + // initialize configuration + CONFIG = config_new(); + + // parse command line + config_parse_cli(argc, argv, CONFIG); + + create_workers = 1; + + openssl_check_version(); + + init_signals(); + + init_globals(); + + listener_socket = create_main_socket(); + +#ifdef USE_SHARED_CACHE + if (CONFIG->SHCUPD_PORT) { + /* create socket to send(children) and + receive(parent) cache updates */ + shcupd_socket = create_shcupd_socket(); + } +#endif /* USE_SHARED_CACHE */ + + /* load certificates, pass to handle_connections */ + init_openssl(); + + if (CONFIG->CHROOT && CONFIG->CHROOT[0]) + change_root(); + + if (CONFIG->UID || CONFIG->GID) + drop_privileges(); + + /* should we daemonize ?*/ + if (CONFIG->DAEMONIZE) { + /* disable logging to stderr */ + CONFIG->QUIET = 1; + CONFIG->SYSLOG = 1; + + /* become a daemon */ + daemonize(); + } + + master_pid = getpid(); + + start_children(0, CONFIG->NCORES); + +#ifdef USE_SHARED_CACHE + if (CONFIG->SHCUPD_PORT) { + /* start event loop to receive cache updates */ + + loop = ev_default_loop(EVFLAG_AUTO); + + ev_io_init(&shcupd_listener, handle_shcupd, shcupd_socket, EV_READ); + ev_io_start(loop, &shcupd_listener); + + ev_loop(loop, 0); + } +#endif /* USE_SHARED_CACHE */ + + for (;;) { + /* Sleep and let the children work. + * Parent will be woken up if a signal arrives */ + pause(); + } + + exit(0); /* just a formality; we never get here */ +} diff --git a/hm_stud/version.h b/hm_stud/version.h new file mode 100644 index 0000000..114d262 --- /dev/null +++ b/hm_stud/version.h @@ -0,0 +1 @@ +#define STUD_VERSION "0.3-dev" diff --git a/hm_sunwell/LICENSE b/hm_sunwell/LICENSE new file mode 100644 index 0000000..d5278f2 --- /dev/null +++ b/hm_sunwell/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2016 Christian Engel + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/hm_sunwell/README.md b/hm_sunwell/README.md new file mode 100644 index 0000000..8ca125d --- /dev/null +++ b/hm_sunwell/README.md @@ -0,0 +1,143 @@ +node-sunwell +============ + +[![Build Status](https://travis-ci.org/matkl/node-sunwell.svg?branch=master)](https://travis-ci.org/matkl/node-sunwell) +[![Coverage Status](https://coveralls.io/repos/github/matkl/node-sunwell/badge.svg?branch=master)](https://coveralls.io/github/matkl/node-sunwell?branch=master) +[![npm version](http://img.shields.io/npm/v/node-sunwell.svg?style=flat)](https://npmjs.org/package/node-sunwell "View this project on npm") + + +An HTML5 canvas based renderer for hearthstone cards for node.js. Forked from [HearthSim/sunwell](https://github.com/HearthSim/sunwell). + +Requirements +------------ + +See [HearthSim/sunwell](https://github.com/HearthSim/sunwell) for detailed information. Card artworks and fonts are not included. Set `textureFolder` to the folder where you put the card artworks when creating the sunwell object. + +Installation +------------ +``` +$ npm install --save node-sunwell +``` + +Usage +----- +Set up sunwell with your own settings: + +```javascript +var Sunwell = require('node-sunwell'); +var sunwell = new Sunwell({ + titleFont: 'Belwe', + bodyFont: 'ITC Franklin Condensed', + bodyFontSize: 24, + bodyLineHeight: 55, + bodyFontOffset: {x: 0, y: 0}, + textureFolder: __dirname + '/artworks/', + smallTextureFolder: __dirname + '/smallArtworks/', + debug: false +}); +``` + +###Rendering a card +To render a specific card, you can call the method `createCard()` of the `sunwell` object. + +```javascript +var cardObj = sunwell.createCard(cardData, width, function(err, buffer) { + // buffer contains PNG data +}); +``` + +The `cardData` parameter is an object containing information about the card to be rendered. `width` +defines the width of the card to be rendered. Sunwell provides a "native" resolution up to 764x1100 +pixels. While you can set a higher value than 764 for the desired render, it will only result in blurry +results. The max supported resolution of sunwell is already by far greater than in the game itself. + +The callback will be invoked with the rendered card buffer. + +The object you pass as `cardData` can be obtained for example through [HearthstoneJSON](https://hearthstonejson.com/). + +```javascript +{ + "id":"CS2_087", + "artist":"Zoltan Boros", + "set":"CORE", + "type":"SPELL", + "rarity":"FREE", + "cost":1, + "name":"Blessing of Might", + "flavor":"\"As in, you MIGHT want to get out of my way.\" - Toad Mackle, recently buffed.", + "playRequirements":{"REQ_TARGET_TO_PLAY":0,"REQ_MINION_TARGET":0}, + "collectible":true, + "playerClass":"PALADIN", + "howToEarnGolden":"Unlocked at Level 45.", + "howToEarn":"Unlocked at Level 1.", + "text":"Give a minion +3 Attack.", + "texture":"W16_a053_D" +} +``` + +Some properties are purely optional, since they are not used by sunwell, but these ones are required: + +```javascript +{ + "id":"CS2_087", + "set":"CORE", + "type":"SPELL", + "rarity":"FREE", + "cost":1, + "name":"Blessing of Might", + "playerClass":"PALADIN", + "text":"Give a minion +3 Attack.", + "texture":"W16_a053_D" +} +``` + +In case of a minion or weapon card, you also need to pass `health` (or `durability`, but health is fine for weapons, too) and/or `attack`. + +The method will return an object that provides an interface to manipulate the card after its creation. + +If you want to update certain properties on the original `cardData`, simply call `cardObj.update()` and +pass an object with the properties you want to overwrite. + +###Changing the number colors + +If you want to make the numbers appear green/red, you can also pass in the following properties on your card object to both +`createCard()` and/or `cardObj.update()`: + +```javascript +{ + "costStyle": "0", + "attackStyle": "+", + "healthStyle": "-", + "durabilityStyle": "-" +} +``` + +All the style default to "0". Setting the style to "+" makes the number appear green, setting it to "-" makes it appear red. + + +###Silence a minion +To silence a minion, set `silenced: true` either when creating the card, or with the update function. + +###Let a card cost health instead of mana +Introduced by [Cho'gall](http://hearthstonelabs.com/cards#lang=enUS;detail=OG_121), cards may cost health instead of mana. +You can switch any cards cost icon by setting `costHealth: true` either when creating the card, or through the update function. + +## Examples + +See [examples/](examples/). + +## Author + +Original work by Christian Engel + +Node.js port by Matthias Klein + +## License + +Sunwell is licensed +[MIT](http://choosealicense.com/licenses/mit/). The full license text is +available in the `LICENSE` file in the respective implementations' folder. + +# This is not a standalone project! + +[hm_sunwell](https://github.com/farb3yonddriv3n/hm_sunwell) is part of [hearthmod software stack](https://github.com/hearthmod/hearthmod) diff --git a/hm_sunwell/artwork/AT_001.jpg b/hm_sunwell/artwork/AT_001.jpg new file mode 100644 index 0000000..72c5893 Binary files /dev/null and b/hm_sunwell/artwork/AT_001.jpg differ diff --git a/hm_sunwell/artwork/AT_018.jpg b/hm_sunwell/artwork/AT_018.jpg new file mode 100644 index 0000000..caac3be Binary files /dev/null and b/hm_sunwell/artwork/AT_018.jpg differ diff --git a/hm_sunwell/artwork/AT_074.jpg b/hm_sunwell/artwork/AT_074.jpg new file mode 100644 index 0000000..b8e5bb7 Binary files /dev/null and b/hm_sunwell/artwork/AT_074.jpg differ diff --git a/hm_sunwell/artwork/AT_128.jpg b/hm_sunwell/artwork/AT_128.jpg new file mode 100644 index 0000000..bf5d4d9 Binary files /dev/null and b/hm_sunwell/artwork/AT_128.jpg differ diff --git a/hm_sunwell/artwork/BRMA11_3.jpg b/hm_sunwell/artwork/BRMA11_3.jpg new file mode 100644 index 0000000..f5fe365 Binary files /dev/null and b/hm_sunwell/artwork/BRMA11_3.jpg differ diff --git a/hm_sunwell/artwork/BRM_003.jpg b/hm_sunwell/artwork/BRM_003.jpg new file mode 100644 index 0000000..d7eda72 Binary files /dev/null and b/hm_sunwell/artwork/BRM_003.jpg differ diff --git a/hm_sunwell/artwork/CS1_112.jpg b/hm_sunwell/artwork/CS1_112.jpg new file mode 100644 index 0000000..e9e07c3 Binary files /dev/null and b/hm_sunwell/artwork/CS1_112.jpg differ diff --git a/hm_sunwell/artwork/CS2_011.jpg b/hm_sunwell/artwork/CS2_011.jpg new file mode 100644 index 0000000..5905886 Binary files /dev/null and b/hm_sunwell/artwork/CS2_011.jpg differ diff --git a/hm_sunwell/artwork/CS2_023.jpg b/hm_sunwell/artwork/CS2_023.jpg new file mode 100644 index 0000000..e069964 Binary files /dev/null and b/hm_sunwell/artwork/CS2_023.jpg differ diff --git a/hm_sunwell/artwork/CS2_024.jpg b/hm_sunwell/artwork/CS2_024.jpg new file mode 100644 index 0000000..7709927 Binary files /dev/null and b/hm_sunwell/artwork/CS2_024.jpg differ diff --git a/hm_sunwell/artwork/CS2_026.jpg b/hm_sunwell/artwork/CS2_026.jpg new file mode 100644 index 0000000..7e6193a Binary files /dev/null and b/hm_sunwell/artwork/CS2_026.jpg differ diff --git a/hm_sunwell/artwork/CS2_042.jpg b/hm_sunwell/artwork/CS2_042.jpg new file mode 100644 index 0000000..8516fed Binary files /dev/null and b/hm_sunwell/artwork/CS2_042.jpg differ diff --git a/hm_sunwell/artwork/CS2_065.jpg b/hm_sunwell/artwork/CS2_065.jpg new file mode 100644 index 0000000..24883c6 Binary files /dev/null and b/hm_sunwell/artwork/CS2_065.jpg differ diff --git a/hm_sunwell/artwork/CS2_072.jpg b/hm_sunwell/artwork/CS2_072.jpg new file mode 100644 index 0000000..35d9010 Binary files /dev/null and b/hm_sunwell/artwork/CS2_072.jpg differ diff --git a/hm_sunwell/artwork/CS2_076.jpg b/hm_sunwell/artwork/CS2_076.jpg new file mode 100644 index 0000000..65a0d58 Binary files /dev/null and b/hm_sunwell/artwork/CS2_076.jpg differ diff --git a/hm_sunwell/artwork/CS2_077.jpg b/hm_sunwell/artwork/CS2_077.jpg new file mode 100644 index 0000000..1e8a468 Binary files /dev/null and b/hm_sunwell/artwork/CS2_077.jpg differ diff --git a/hm_sunwell/artwork/CS2_097.jpg b/hm_sunwell/artwork/CS2_097.jpg new file mode 100644 index 0000000..01808aa Binary files /dev/null and b/hm_sunwell/artwork/CS2_097.jpg differ diff --git a/hm_sunwell/artwork/CS2_118.jpg b/hm_sunwell/artwork/CS2_118.jpg new file mode 100644 index 0000000..ab518f7 Binary files /dev/null and b/hm_sunwell/artwork/CS2_118.jpg differ diff --git a/hm_sunwell/artwork/CS2_201.jpg b/hm_sunwell/artwork/CS2_201.jpg new file mode 100644 index 0000000..8127e06 Binary files /dev/null and b/hm_sunwell/artwork/CS2_201.jpg differ diff --git a/hm_sunwell/artwork/CS2_226.jpg b/hm_sunwell/artwork/CS2_226.jpg new file mode 100644 index 0000000..48d16e2 Binary files /dev/null and b/hm_sunwell/artwork/CS2_226.jpg differ diff --git a/hm_sunwell/artwork/CS2_231.jpg b/hm_sunwell/artwork/CS2_231.jpg new file mode 100644 index 0000000..49fab0f Binary files /dev/null and b/hm_sunwell/artwork/CS2_231.jpg differ diff --git a/hm_sunwell/artwork/CS2_234.jpg b/hm_sunwell/artwork/CS2_234.jpg new file mode 100644 index 0000000..e19f239 Binary files /dev/null and b/hm_sunwell/artwork/CS2_234.jpg differ diff --git a/hm_sunwell/artwork/DS1_185.jpg b/hm_sunwell/artwork/DS1_185.jpg new file mode 100644 index 0000000..c4d15a9 Binary files /dev/null and b/hm_sunwell/artwork/DS1_185.jpg differ diff --git a/hm_sunwell/artwork/EX1_011.jpg b/hm_sunwell/artwork/EX1_011.jpg new file mode 100644 index 0000000..c7af7cc Binary files /dev/null and b/hm_sunwell/artwork/EX1_011.jpg differ diff --git a/hm_sunwell/artwork/EX1_049.jpg b/hm_sunwell/artwork/EX1_049.jpg new file mode 100644 index 0000000..499c50b Binary files /dev/null and b/hm_sunwell/artwork/EX1_049.jpg differ diff --git a/hm_sunwell/artwork/EX1_097.jpg b/hm_sunwell/artwork/EX1_097.jpg new file mode 100644 index 0000000..3e30c5f Binary files /dev/null and b/hm_sunwell/artwork/EX1_097.jpg differ diff --git a/hm_sunwell/artwork/EX1_105.jpg b/hm_sunwell/artwork/EX1_105.jpg new file mode 100644 index 0000000..75ef9dd Binary files /dev/null and b/hm_sunwell/artwork/EX1_105.jpg differ diff --git a/hm_sunwell/artwork/EX1_165t2.jpg b/hm_sunwell/artwork/EX1_165t2.jpg new file mode 100644 index 0000000..6bbe8e2 Binary files /dev/null and b/hm_sunwell/artwork/EX1_165t2.jpg differ diff --git a/hm_sunwell/artwork/EX1_251.jpg b/hm_sunwell/artwork/EX1_251.jpg new file mode 100644 index 0000000..71ef6c9 Binary files /dev/null and b/hm_sunwell/artwork/EX1_251.jpg differ diff --git a/hm_sunwell/artwork/EX1_259.jpg b/hm_sunwell/artwork/EX1_259.jpg new file mode 100644 index 0000000..63f10bc Binary files /dev/null and b/hm_sunwell/artwork/EX1_259.jpg differ diff --git a/hm_sunwell/artwork/EX1_303.jpg b/hm_sunwell/artwork/EX1_303.jpg new file mode 100644 index 0000000..4c6d763 Binary files /dev/null and b/hm_sunwell/artwork/EX1_303.jpg differ diff --git a/hm_sunwell/artwork/EX1_306.jpg b/hm_sunwell/artwork/EX1_306.jpg new file mode 100644 index 0000000..cc78a75 Binary files /dev/null and b/hm_sunwell/artwork/EX1_306.jpg differ diff --git a/hm_sunwell/artwork/EX1_383.jpg b/hm_sunwell/artwork/EX1_383.jpg new file mode 100644 index 0000000..8114fa1 Binary files /dev/null and b/hm_sunwell/artwork/EX1_383.jpg differ diff --git a/hm_sunwell/artwork/EX1_559.jpg b/hm_sunwell/artwork/EX1_559.jpg new file mode 100644 index 0000000..847db03 Binary files /dev/null and b/hm_sunwell/artwork/EX1_559.jpg differ diff --git a/hm_sunwell/artwork/EX1_581.jpg b/hm_sunwell/artwork/EX1_581.jpg new file mode 100644 index 0000000..4f664c4 Binary files /dev/null and b/hm_sunwell/artwork/EX1_581.jpg differ diff --git a/hm_sunwell/artwork/EX1_593.jpg b/hm_sunwell/artwork/EX1_593.jpg new file mode 100644 index 0000000..288b72f Binary files /dev/null and b/hm_sunwell/artwork/EX1_593.jpg differ diff --git a/hm_sunwell/artwork/EX1_607.jpg b/hm_sunwell/artwork/EX1_607.jpg new file mode 100644 index 0000000..d1c09cc Binary files /dev/null and b/hm_sunwell/artwork/EX1_607.jpg differ diff --git a/hm_sunwell/artwork/EX1_614.jpg b/hm_sunwell/artwork/EX1_614.jpg new file mode 100644 index 0000000..1b1bf1e Binary files /dev/null and b/hm_sunwell/artwork/EX1_614.jpg differ diff --git a/hm_sunwell/artwork/GVG_010.jpg b/hm_sunwell/artwork/GVG_010.jpg new file mode 100644 index 0000000..b6203f6 Binary files /dev/null and b/hm_sunwell/artwork/GVG_010.jpg differ diff --git a/hm_sunwell/artwork/GVG_105.jpg b/hm_sunwell/artwork/GVG_105.jpg new file mode 100644 index 0000000..c6263ca Binary files /dev/null and b/hm_sunwell/artwork/GVG_105.jpg differ diff --git a/hm_sunwell/artwork/LOEA16_9.jpg b/hm_sunwell/artwork/LOEA16_9.jpg new file mode 100644 index 0000000..c96f012 Binary files /dev/null and b/hm_sunwell/artwork/LOEA16_9.jpg differ diff --git a/hm_sunwell/artwork/LOE_077.jpg b/hm_sunwell/artwork/LOE_077.jpg new file mode 100644 index 0000000..cedc00e Binary files /dev/null and b/hm_sunwell/artwork/LOE_077.jpg differ diff --git a/hm_sunwell/artwork/LOE_118.jpg b/hm_sunwell/artwork/LOE_118.jpg new file mode 100644 index 0000000..473c690 Binary files /dev/null and b/hm_sunwell/artwork/LOE_118.jpg differ diff --git a/hm_sunwell/artwork/NEW1_011.jpg b/hm_sunwell/artwork/NEW1_011.jpg new file mode 100644 index 0000000..51fac67 Binary files /dev/null and b/hm_sunwell/artwork/NEW1_011.jpg differ diff --git a/hm_sunwell/artwork/NEW1_030.jpg b/hm_sunwell/artwork/NEW1_030.jpg new file mode 100644 index 0000000..567dc13 Binary files /dev/null and b/hm_sunwell/artwork/NEW1_030.jpg differ diff --git a/hm_sunwell/artwork/NEW1_036.jpg b/hm_sunwell/artwork/NEW1_036.jpg new file mode 100644 index 0000000..97ddf18 Binary files /dev/null and b/hm_sunwell/artwork/NEW1_036.jpg differ diff --git a/hm_sunwell/artwork/OG_090.jpg b/hm_sunwell/artwork/OG_090.jpg new file mode 100644 index 0000000..cb2fcf3 Binary files /dev/null and b/hm_sunwell/artwork/OG_090.jpg differ diff --git a/hm_sunwell/artwork/OG_223.jpg b/hm_sunwell/artwork/OG_223.jpg new file mode 100644 index 0000000..26803dc Binary files /dev/null and b/hm_sunwell/artwork/OG_223.jpg differ diff --git a/hm_sunwell/artwork/README b/hm_sunwell/artwork/README new file mode 100644 index 0000000..40b9bb8 --- /dev/null +++ b/hm_sunwell/artwork/README @@ -0,0 +1 @@ +Place the card artworks here in JPG format. \ No newline at end of file diff --git a/hm_sunwell/artwork/axe.jpg b/hm_sunwell/artwork/axe.jpg new file mode 100644 index 0000000..51fac67 Binary files /dev/null and b/hm_sunwell/artwork/axe.jpg differ diff --git a/hm_sunwell/artwork/shifu.jpg b/hm_sunwell/artwork/shifu.jpg new file mode 100644 index 0000000..48a9a75 Binary files /dev/null and b/hm_sunwell/artwork/shifu.jpg differ diff --git a/hm_sunwell/assets/attack.png b/hm_sunwell/assets/attack.png new file mode 100644 index 0000000..526768d Binary files /dev/null and b/hm_sunwell/assets/attack.png differ diff --git a/hm_sunwell/assets/bg-brm.png b/hm_sunwell/assets/bg-brm.png new file mode 100644 index 0000000..c37b4cb Binary files /dev/null and b/hm_sunwell/assets/bg-brm.png differ diff --git a/hm_sunwell/assets/bg-cl.png b/hm_sunwell/assets/bg-cl.png new file mode 100644 index 0000000..ca9bf97 Binary files /dev/null and b/hm_sunwell/assets/bg-cl.png differ diff --git a/hm_sunwell/assets/bg-gvg.png b/hm_sunwell/assets/bg-gvg.png new file mode 100644 index 0000000..58580be Binary files /dev/null and b/hm_sunwell/assets/bg-gvg.png differ diff --git a/hm_sunwell/assets/bg-loe.png b/hm_sunwell/assets/bg-loe.png new file mode 100644 index 0000000..1835b7e Binary files /dev/null and b/hm_sunwell/assets/bg-loe.png differ diff --git a/hm_sunwell/assets/bg-nax.png b/hm_sunwell/assets/bg-nax.png new file mode 100644 index 0000000..4f07a83 Binary files /dev/null and b/hm_sunwell/assets/bg-nax.png differ diff --git a/hm_sunwell/assets/bg-og.png b/hm_sunwell/assets/bg-og.png new file mode 100644 index 0000000..aa66a7e Binary files /dev/null and b/hm_sunwell/assets/bg-og.png differ diff --git a/hm_sunwell/assets/bg-tgt.png b/hm_sunwell/assets/bg-tgt.png new file mode 100644 index 0000000..50ca692 Binary files /dev/null and b/hm_sunwell/assets/bg-tgt.png differ diff --git a/hm_sunwell/assets/dragon.png b/hm_sunwell/assets/dragon.png new file mode 100644 index 0000000..86c52f5 Binary files /dev/null and b/hm_sunwell/assets/dragon.png differ diff --git a/hm_sunwell/assets/gem.png b/hm_sunwell/assets/gem.png new file mode 100644 index 0000000..a2244af Binary files /dev/null and b/hm_sunwell/assets/gem.png differ diff --git a/hm_sunwell/assets/health.png b/hm_sunwell/assets/health.png new file mode 100644 index 0000000..b47e3b6 Binary files /dev/null and b/hm_sunwell/assets/health.png differ diff --git a/hm_sunwell/assets/mDruid.png b/hm_sunwell/assets/mDruid.png new file mode 100644 index 0000000..b871336 Binary files /dev/null and b/hm_sunwell/assets/mDruid.png differ diff --git a/hm_sunwell/assets/mHunter.png b/hm_sunwell/assets/mHunter.png new file mode 100644 index 0000000..cbd27f3 Binary files /dev/null and b/hm_sunwell/assets/mHunter.png differ diff --git a/hm_sunwell/assets/mMage.png b/hm_sunwell/assets/mMage.png new file mode 100644 index 0000000..f63926a Binary files /dev/null and b/hm_sunwell/assets/mMage.png differ diff --git a/hm_sunwell/assets/mNeutral.png b/hm_sunwell/assets/mNeutral.png new file mode 100644 index 0000000..6a1dfae Binary files /dev/null and b/hm_sunwell/assets/mNeutral.png differ diff --git a/hm_sunwell/assets/mPaladin.png b/hm_sunwell/assets/mPaladin.png new file mode 100644 index 0000000..3b2bdf8 Binary files /dev/null and b/hm_sunwell/assets/mPaladin.png differ diff --git a/hm_sunwell/assets/mPreload.jpg b/hm_sunwell/assets/mPreload.jpg new file mode 100644 index 0000000..e5a4bf1 Binary files /dev/null and b/hm_sunwell/assets/mPreload.jpg differ diff --git a/hm_sunwell/assets/mPriest.png b/hm_sunwell/assets/mPriest.png new file mode 100644 index 0000000..833a6f1 Binary files /dev/null and b/hm_sunwell/assets/mPriest.png differ diff --git a/hm_sunwell/assets/mRogue.png b/hm_sunwell/assets/mRogue.png new file mode 100644 index 0000000..b5cd1b0 Binary files /dev/null and b/hm_sunwell/assets/mRogue.png differ diff --git a/hm_sunwell/assets/mShaman.png b/hm_sunwell/assets/mShaman.png new file mode 100644 index 0000000..cc45abc Binary files /dev/null and b/hm_sunwell/assets/mShaman.png differ diff --git a/hm_sunwell/assets/mWarlock.png b/hm_sunwell/assets/mWarlock.png new file mode 100644 index 0000000..343d047 Binary files /dev/null and b/hm_sunwell/assets/mWarlock.png differ diff --git a/hm_sunwell/assets/mWarrior.png b/hm_sunwell/assets/mWarrior.png new file mode 100644 index 0000000..f3da6c2 Binary files /dev/null and b/hm_sunwell/assets/mWarrior.png differ diff --git a/hm_sunwell/assets/race.png b/hm_sunwell/assets/race.png new file mode 100644 index 0000000..b03c15d Binary files /dev/null and b/hm_sunwell/assets/race.png differ diff --git a/hm_sunwell/assets/rarity-common.png b/hm_sunwell/assets/rarity-common.png new file mode 100644 index 0000000..c4aeb04 Binary files /dev/null and b/hm_sunwell/assets/rarity-common.png differ diff --git a/hm_sunwell/assets/rarity-epic.png b/hm_sunwell/assets/rarity-epic.png new file mode 100644 index 0000000..9d22fa1 Binary files /dev/null and b/hm_sunwell/assets/rarity-epic.png differ diff --git a/hm_sunwell/assets/rarity-legendary.png b/hm_sunwell/assets/rarity-legendary.png new file mode 100644 index 0000000..20864b6 Binary files /dev/null and b/hm_sunwell/assets/rarity-legendary.png differ diff --git a/hm_sunwell/assets/rarity-rare.png b/hm_sunwell/assets/rarity-rare.png new file mode 100644 index 0000000..56be8e5 Binary files /dev/null and b/hm_sunwell/assets/rarity-rare.png differ diff --git a/hm_sunwell/assets/sDruid.png b/hm_sunwell/assets/sDruid.png new file mode 100644 index 0000000..8658e64 Binary files /dev/null and b/hm_sunwell/assets/sDruid.png differ diff --git a/hm_sunwell/assets/sHunter.png b/hm_sunwell/assets/sHunter.png new file mode 100644 index 0000000..36b8438 Binary files /dev/null and b/hm_sunwell/assets/sHunter.png differ diff --git a/hm_sunwell/assets/sMage.png b/hm_sunwell/assets/sMage.png new file mode 100644 index 0000000..6337675 Binary files /dev/null and b/hm_sunwell/assets/sMage.png differ diff --git a/hm_sunwell/assets/sNeutral.png b/hm_sunwell/assets/sNeutral.png new file mode 100644 index 0000000..4ac7744 Binary files /dev/null and b/hm_sunwell/assets/sNeutral.png differ diff --git a/hm_sunwell/assets/sPaladin.png b/hm_sunwell/assets/sPaladin.png new file mode 100644 index 0000000..dcf0883 Binary files /dev/null and b/hm_sunwell/assets/sPaladin.png differ diff --git a/hm_sunwell/assets/sPreload.jpg b/hm_sunwell/assets/sPreload.jpg new file mode 100644 index 0000000..d3520b9 Binary files /dev/null and b/hm_sunwell/assets/sPreload.jpg differ diff --git a/hm_sunwell/assets/sPriest.png b/hm_sunwell/assets/sPriest.png new file mode 100644 index 0000000..8ae577d Binary files /dev/null and b/hm_sunwell/assets/sPriest.png differ diff --git a/hm_sunwell/assets/sRogue.png b/hm_sunwell/assets/sRogue.png new file mode 100644 index 0000000..b40a711 Binary files /dev/null and b/hm_sunwell/assets/sRogue.png differ diff --git a/hm_sunwell/assets/sShaman.png b/hm_sunwell/assets/sShaman.png new file mode 100644 index 0000000..e7bc5d6 Binary files /dev/null and b/hm_sunwell/assets/sShaman.png differ diff --git a/hm_sunwell/assets/sWarlock.png b/hm_sunwell/assets/sWarlock.png new file mode 100644 index 0000000..484eef7 Binary files /dev/null and b/hm_sunwell/assets/sWarlock.png differ diff --git a/hm_sunwell/assets/sWarrior.png b/hm_sunwell/assets/sWarrior.png new file mode 100644 index 0000000..5a65ab7 Binary files /dev/null and b/hm_sunwell/assets/sWarrior.png differ diff --git a/hm_sunwell/assets/shield.png b/hm_sunwell/assets/shield.png new file mode 100644 index 0000000..ac33b88 Binary files /dev/null and b/hm_sunwell/assets/shield.png differ diff --git a/hm_sunwell/assets/silence-x.png b/hm_sunwell/assets/silence-x.png new file mode 100644 index 0000000..3a6685c Binary files /dev/null and b/hm_sunwell/assets/silence-x.png differ diff --git a/hm_sunwell/assets/spell-bg-brm.png b/hm_sunwell/assets/spell-bg-brm.png new file mode 100644 index 0000000..4928cde Binary files /dev/null and b/hm_sunwell/assets/spell-bg-brm.png differ diff --git a/hm_sunwell/assets/spell-bg-cl.png b/hm_sunwell/assets/spell-bg-cl.png new file mode 100644 index 0000000..f7e2284 Binary files /dev/null and b/hm_sunwell/assets/spell-bg-cl.png differ diff --git a/hm_sunwell/assets/spell-bg-gvg.png b/hm_sunwell/assets/spell-bg-gvg.png new file mode 100644 index 0000000..e42a871 Binary files /dev/null and b/hm_sunwell/assets/spell-bg-gvg.png differ diff --git a/hm_sunwell/assets/spell-bg-loe.png b/hm_sunwell/assets/spell-bg-loe.png new file mode 100644 index 0000000..c11a6df Binary files /dev/null and b/hm_sunwell/assets/spell-bg-loe.png differ diff --git a/hm_sunwell/assets/spell-bg-nax.png b/hm_sunwell/assets/spell-bg-nax.png new file mode 100644 index 0000000..f23bd3a Binary files /dev/null and b/hm_sunwell/assets/spell-bg-nax.png differ diff --git a/hm_sunwell/assets/spell-bg-og.png b/hm_sunwell/assets/spell-bg-og.png new file mode 100644 index 0000000..58bb51e Binary files /dev/null and b/hm_sunwell/assets/spell-bg-og.png differ diff --git a/hm_sunwell/assets/spell-bg-tgt.png b/hm_sunwell/assets/spell-bg-tgt.png new file mode 100644 index 0000000..940e194 Binary files /dev/null and b/hm_sunwell/assets/spell-bg-tgt.png differ diff --git a/hm_sunwell/assets/spell-rarity-common.png b/hm_sunwell/assets/spell-rarity-common.png new file mode 100644 index 0000000..3e20573 Binary files /dev/null and b/hm_sunwell/assets/spell-rarity-common.png differ diff --git a/hm_sunwell/assets/spell-rarity-epic.png b/hm_sunwell/assets/spell-rarity-epic.png new file mode 100644 index 0000000..832f67a Binary files /dev/null and b/hm_sunwell/assets/spell-rarity-epic.png differ diff --git a/hm_sunwell/assets/spell-rarity-legendary.png b/hm_sunwell/assets/spell-rarity-legendary.png new file mode 100644 index 0000000..f791df1 Binary files /dev/null and b/hm_sunwell/assets/spell-rarity-legendary.png differ diff --git a/hm_sunwell/assets/spell-rarity-rare.png b/hm_sunwell/assets/spell-rarity-rare.png new file mode 100644 index 0000000..f295463 Binary files /dev/null and b/hm_sunwell/assets/spell-rarity-rare.png differ diff --git a/hm_sunwell/assets/swords.png b/hm_sunwell/assets/swords.png new file mode 100644 index 0000000..73abecd Binary files /dev/null and b/hm_sunwell/assets/swords.png differ diff --git a/hm_sunwell/assets/title-spell.png b/hm_sunwell/assets/title-spell.png new file mode 100644 index 0000000..e256d0c Binary files /dev/null and b/hm_sunwell/assets/title-spell.png differ diff --git a/hm_sunwell/assets/title-weapon.png b/hm_sunwell/assets/title-weapon.png new file mode 100644 index 0000000..4ff34a1 Binary files /dev/null and b/hm_sunwell/assets/title-weapon.png differ diff --git a/hm_sunwell/assets/title.png b/hm_sunwell/assets/title.png new file mode 100644 index 0000000..4987762 Binary files /dev/null and b/hm_sunwell/assets/title.png differ diff --git a/hm_sunwell/assets/wDruid.png b/hm_sunwell/assets/wDruid.png new file mode 100644 index 0000000..7272581 Binary files /dev/null and b/hm_sunwell/assets/wDruid.png differ diff --git a/hm_sunwell/assets/wHunter.png b/hm_sunwell/assets/wHunter.png new file mode 100644 index 0000000..f9dbfa4 Binary files /dev/null and b/hm_sunwell/assets/wHunter.png differ diff --git a/hm_sunwell/assets/wMage.png b/hm_sunwell/assets/wMage.png new file mode 100644 index 0000000..37b47e2 Binary files /dev/null and b/hm_sunwell/assets/wMage.png differ diff --git a/hm_sunwell/assets/wNeutral.png b/hm_sunwell/assets/wNeutral.png new file mode 100644 index 0000000..33f1f81 Binary files /dev/null and b/hm_sunwell/assets/wNeutral.png differ diff --git a/hm_sunwell/assets/wPaladin.png b/hm_sunwell/assets/wPaladin.png new file mode 100644 index 0000000..89bd4fe Binary files /dev/null and b/hm_sunwell/assets/wPaladin.png differ diff --git a/hm_sunwell/assets/wPreload.jpg b/hm_sunwell/assets/wPreload.jpg new file mode 100644 index 0000000..09d2d65 Binary files /dev/null and b/hm_sunwell/assets/wPreload.jpg differ diff --git a/hm_sunwell/assets/wPriest.png b/hm_sunwell/assets/wPriest.png new file mode 100644 index 0000000..b48fde7 Binary files /dev/null and b/hm_sunwell/assets/wPriest.png differ diff --git a/hm_sunwell/assets/wRogue.png b/hm_sunwell/assets/wRogue.png new file mode 100644 index 0000000..7664d3c Binary files /dev/null and b/hm_sunwell/assets/wRogue.png differ diff --git a/hm_sunwell/assets/wShaman.png b/hm_sunwell/assets/wShaman.png new file mode 100644 index 0000000..cb7381e Binary files /dev/null and b/hm_sunwell/assets/wShaman.png differ diff --git a/hm_sunwell/assets/wWarlock.png b/hm_sunwell/assets/wWarlock.png new file mode 100644 index 0000000..c3020cb Binary files /dev/null and b/hm_sunwell/assets/wWarlock.png differ diff --git a/hm_sunwell/assets/wWarrior.png b/hm_sunwell/assets/wWarrior.png new file mode 100644 index 0000000..2c6cea1 Binary files /dev/null and b/hm_sunwell/assets/wWarrior.png differ diff --git a/hm_sunwell/assets/weapon-rarity-common.png b/hm_sunwell/assets/weapon-rarity-common.png new file mode 100644 index 0000000..de86f06 Binary files /dev/null and b/hm_sunwell/assets/weapon-rarity-common.png differ diff --git a/hm_sunwell/assets/weapon-rarity-epic.png b/hm_sunwell/assets/weapon-rarity-epic.png new file mode 100644 index 0000000..494a06d Binary files /dev/null and b/hm_sunwell/assets/weapon-rarity-epic.png differ diff --git a/hm_sunwell/assets/weapon-rarity-legendary.png b/hm_sunwell/assets/weapon-rarity-legendary.png new file mode 100644 index 0000000..f05a369 Binary files /dev/null and b/hm_sunwell/assets/weapon-rarity-legendary.png differ diff --git a/hm_sunwell/assets/weapon-rarity-rare.png b/hm_sunwell/assets/weapon-rarity-rare.png new file mode 100644 index 0000000..c2aa300 Binary files /dev/null and b/hm_sunwell/assets/weapon-rarity-rare.png differ diff --git a/hm_sunwell/examples/README.md b/hm_sunwell/examples/README.md new file mode 100644 index 0000000..4e609d7 --- /dev/null +++ b/hm_sunwell/examples/README.md @@ -0,0 +1,9 @@ +node-sunwell Examples +===================== + +To run the examples in your development environment: + +1. Clone this repo +2. Run `npm install` +3. Start the server with `npm start` +4. Point your browser to http://localhost:8080 diff --git a/hm_sunwell/examples/server.js b/hm_sunwell/examples/server.js new file mode 100644 index 0000000..ddb4e92 --- /dev/null +++ b/hm_sunwell/examples/server.js @@ -0,0 +1,48 @@ +var express = require('express'); + +var app = express(); +var Sunwell = require('../sunwell'); +var sunwell = new Sunwell({ bodyFontSize: 35 }); + +app.get('/', function(req, res) { + var width = 400; + + var card_name = ""; + var card_data = ""; + var fs = require('fs'); + + var obj; + fs.readFile(process.cwd() + '/examples/carddata', 'utf8', function (err, data) { + if (err) throw err; + obj = JSON.parse(data); + + var card = sunwell.createCard(obj, width, function(err, buffer) { + if (err) next(err); + + res.writeHead(200, { + //'Cache-Control': 'max-age=86400', + 'Content-Type': 'image/png' + }); + + res.write(buffer); + res.end(); + + fs.writeFile(process.cwd() + '/../hm_web/static/custom/' + obj['id'] + '.jpg', buffer, function(err) { + if(err) { + return console.log(err); + } + + console.log("The file " + obj['id'] + " was saved!"); + + }); + }); + }); +}); + +app.use(function(err, req, res, next) { + next(err); +}); + +var listener = app.listen(process.env.PORT || 8081, function() { + console.log('Server listening on port', listener.address().port); +}); diff --git a/hm_sunwell/node_modules/.bin/_mocha b/hm_sunwell/node_modules/.bin/_mocha new file mode 100644 index 0000000..f2a54ff --- /dev/null +++ b/hm_sunwell/node_modules/.bin/_mocha @@ -0,0 +1 @@ +../mocha/bin/_mocha \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/coveralls b/hm_sunwell/node_modules/.bin/coveralls new file mode 100644 index 0000000..05bb329 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/coveralls @@ -0,0 +1 @@ +../coveralls/bin/coveralls.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/escodegen b/hm_sunwell/node_modules/.bin/escodegen new file mode 100644 index 0000000..01a7c32 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/escodegen @@ -0,0 +1 @@ +../escodegen/bin/escodegen.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/esgenerate b/hm_sunwell/node_modules/.bin/esgenerate new file mode 100644 index 0000000..7d0293e --- /dev/null +++ b/hm_sunwell/node_modules/.bin/esgenerate @@ -0,0 +1 @@ +../escodegen/bin/esgenerate.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/esparse b/hm_sunwell/node_modules/.bin/esparse new file mode 100644 index 0000000..7423b18 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/esparse @@ -0,0 +1 @@ +../esprima/bin/esparse.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/esvalidate b/hm_sunwell/node_modules/.bin/esvalidate new file mode 100644 index 0000000..16069ef --- /dev/null +++ b/hm_sunwell/node_modules/.bin/esvalidate @@ -0,0 +1 @@ +../esprima/bin/esvalidate.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/handlebars b/hm_sunwell/node_modules/.bin/handlebars new file mode 100644 index 0000000..fb7d090 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/handlebars @@ -0,0 +1 @@ +../handlebars/bin/handlebars \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/har-validator b/hm_sunwell/node_modules/.bin/har-validator new file mode 100644 index 0000000..c6ec163 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/har-validator @@ -0,0 +1 @@ +../har-validator/bin/har-validator \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/istanbul b/hm_sunwell/node_modules/.bin/istanbul new file mode 100644 index 0000000..c129fe5 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/istanbul @@ -0,0 +1 @@ +../istanbul/lib/cli.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/jade b/hm_sunwell/node_modules/.bin/jade new file mode 100644 index 0000000..571fae7 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/jade @@ -0,0 +1 @@ +../jade/bin/jade \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/js-yaml b/hm_sunwell/node_modules/.bin/js-yaml new file mode 100644 index 0000000..9dbd010 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/js-yaml @@ -0,0 +1 @@ +../js-yaml/bin/js-yaml.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/mime b/hm_sunwell/node_modules/.bin/mime new file mode 100644 index 0000000..fbb7ee0 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/mime @@ -0,0 +1 @@ +../mime/cli.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/mkdirp b/hm_sunwell/node_modules/.bin/mkdirp new file mode 100644 index 0000000..017896c --- /dev/null +++ b/hm_sunwell/node_modules/.bin/mkdirp @@ -0,0 +1 @@ +../mkdirp/bin/cmd.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/mocha b/hm_sunwell/node_modules/.bin/mocha new file mode 100644 index 0000000..43c668d --- /dev/null +++ b/hm_sunwell/node_modules/.bin/mocha @@ -0,0 +1 @@ +../mocha/bin/mocha \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/nopt b/hm_sunwell/node_modules/.bin/nopt new file mode 100644 index 0000000..6b6566e --- /dev/null +++ b/hm_sunwell/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/sshpk-conv b/hm_sunwell/node_modules/.bin/sshpk-conv new file mode 100644 index 0000000..a2a295c --- /dev/null +++ b/hm_sunwell/node_modules/.bin/sshpk-conv @@ -0,0 +1 @@ +../sshpk/bin/sshpk-conv \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/sshpk-sign b/hm_sunwell/node_modules/.bin/sshpk-sign new file mode 100644 index 0000000..766b9b3 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/sshpk-sign @@ -0,0 +1 @@ +../sshpk/bin/sshpk-sign \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/sshpk-verify b/hm_sunwell/node_modules/.bin/sshpk-verify new file mode 100644 index 0000000..bfd7e3a --- /dev/null +++ b/hm_sunwell/node_modules/.bin/sshpk-verify @@ -0,0 +1 @@ +../sshpk/bin/sshpk-verify \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/uglifyjs b/hm_sunwell/node_modules/.bin/uglifyjs new file mode 100644 index 0000000..fef3468 --- /dev/null +++ b/hm_sunwell/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/uuid b/hm_sunwell/node_modules/.bin/uuid new file mode 100644 index 0000000..80eb14a --- /dev/null +++ b/hm_sunwell/node_modules/.bin/uuid @@ -0,0 +1 @@ +../node-uuid/bin/uuid \ No newline at end of file diff --git a/hm_sunwell/node_modules/.bin/which b/hm_sunwell/node_modules/.bin/which new file mode 100644 index 0000000..f62471c --- /dev/null +++ b/hm_sunwell/node_modules/.bin/which @@ -0,0 +1 @@ +../which/bin/which \ No newline at end of file diff --git a/hm_sunwell/node_modules/abbrev/LICENSE b/hm_sunwell/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/hm_sunwell/node_modules/abbrev/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/hm_sunwell/node_modules/abbrev/README.md b/hm_sunwell/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/hm_sunwell/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/hm_sunwell/node_modules/abbrev/abbrev.js b/hm_sunwell/node_modules/abbrev/abbrev.js new file mode 100644 index 0000000..69cfeac --- /dev/null +++ b/hm_sunwell/node_modules/abbrev/abbrev.js @@ -0,0 +1,62 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} diff --git a/hm_sunwell/node_modules/abbrev/package.json b/hm_sunwell/node_modules/abbrev/package.json new file mode 100644 index 0000000..70bd6b1 --- /dev/null +++ b/hm_sunwell/node_modules/abbrev/package.json @@ -0,0 +1,82 @@ +{ + "_args": [ + [ + "abbrev@1.0.x", + "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul" + ] + ], + "_from": "abbrev@>=1.0.0 <1.1.0", + "_id": "abbrev@1.0.9", + "_inCache": true, + "_installable": true, + "_location": "/abbrev", + "_nodeVersion": "4.4.4", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/abbrev-1.0.9.tgz_1466016055839_0.7825860097073019" + }, + "_npmUser": { + "email": "i@izs.me", + "name": "isaacs" + }, + "_npmVersion": "3.9.1", + "_phantomChildren": {}, + "_requested": { + "name": "abbrev", + "raw": "abbrev@1.0.x", + "rawSpec": "1.0.x", + "scope": null, + "spec": ">=1.0.0 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/istanbul", + "/nopt" + ], + "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "_shasum": "91b4792588a7738c25f35dd6f63752a2f8776135", + "_shrinkwrap": null, + "_spec": "abbrev@1.0.x", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul", + "author": { + "email": "i@izs.me", + "name": "Isaac Z. Schlueter" + }, + "bugs": { + "url": "https://github.com/isaacs/abbrev-js/issues" + }, + "dependencies": {}, + "description": "Like ruby's abbrev module, but in js", + "devDependencies": { + "tap": "^5.7.2" + }, + "directories": {}, + "dist": { + "shasum": "91b4792588a7738c25f35dd6f63752a2f8776135", + "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" + }, + "files": [ + "abbrev.js" + ], + "gitHead": "c386cd9dbb1d8d7581718c54d4ba944cc9298d6f", + "homepage": "https://github.com/isaacs/abbrev-js#readme", + "license": "ISC", + "main": "abbrev.js", + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "name": "abbrev", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/isaacs/abbrev-js.git" + }, + "scripts": { + "test": "tap test.js --cov" + }, + "version": "1.0.9" +} diff --git a/hm_sunwell/node_modules/accepts/HISTORY.md b/hm_sunwell/node_modules/accepts/HISTORY.md new file mode 100644 index 0000000..0477ed7 --- /dev/null +++ b/hm_sunwell/node_modules/accepts/HISTORY.md @@ -0,0 +1,212 @@ +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/hm_sunwell/node_modules/accepts/LICENSE b/hm_sunwell/node_modules/accepts/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/hm_sunwell/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/accepts/README.md b/hm_sunwell/node_modules/accepts/README.md new file mode 100644 index 0000000..ae36676 --- /dev/null +++ b/hm_sunwell/node_modules/accepts/README.md @@ -0,0 +1,135 @@ +# accepts + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +```sh +npm install accepts +``` + +## API + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME types is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app(req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch(accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('hello, world!') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/accepts.svg +[npm-url]: https://npmjs.org/package/accepts +[node-version-image]: https://img.shields.io/node/v/accepts.svg +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/accepts/master.svg +[travis-url]: https://travis-ci.org/jshttp/accepts +[coveralls-image]: https://img.shields.io/coveralls/jshttp/accepts/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/accepts +[downloads-image]: https://img.shields.io/npm/dm/accepts.svg +[downloads-url]: https://npmjs.org/package/accepts diff --git a/hm_sunwell/node_modules/accepts/index.js b/hm_sunwell/node_modules/accepts/index.js new file mode 100644 index 0000000..e80192a --- /dev/null +++ b/hm_sunwell/node_modules/accepts/index.js @@ -0,0 +1,231 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts(req) { + if (!(this instanceof Accepts)) + return new Accepts(req) + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + if (!this.headers.accept) return types[0]; + var mimes = types.map(extToMime); + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)); + var first = accepts[0]; + if (!first) return false; + return types[mimes.indexOf(first)]; +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime(type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {String} + * @private + */ + +function validMime(type) { + return typeof type === 'string'; +} diff --git a/hm_sunwell/node_modules/accepts/package.json b/hm_sunwell/node_modules/accepts/package.json new file mode 100644 index 0000000..71a78d6 --- /dev/null +++ b/hm_sunwell/node_modules/accepts/package.json @@ -0,0 +1,104 @@ +{ + "_args": [ + [ + "accepts@~1.3.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "accepts@>=1.3.3 <1.4.0", + "_id": "accepts@1.3.3", + "_inCache": true, + "_installable": true, + "_location": "/accepts", + "_nodeVersion": "4.4.3", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/accepts-1.3.3.tgz_1462251932032_0.7092335098423064" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "2.15.1", + "_phantomChildren": {}, + "_requested": { + "name": "accepts", + "raw": "accepts@~1.3.3", + "rawSpec": "~1.3.3", + "scope": null, + "spec": ">=1.3.3 <1.4.0", + "type": "range" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "_shasum": "c3ca7434938648c3e0d9c1e328dd68b622c284ca", + "_shrinkwrap": null, + "_spec": "accepts@~1.3.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "bugs": { + "url": "https://github.com/jshttp/accepts/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": { + "mime-types": "~2.1.11", + "negotiator": "0.6.1" + }, + "description": "Higher-level content negotiation", + "devDependencies": { + "istanbul": "0.4.3", + "mocha": "~1.21.5" + }, + "directories": {}, + "dist": { + "shasum": "c3ca7434938648c3e0d9c1e328dd68b622c284ca", + "tarball": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "gitHead": "3e925b1e65ed7da2798849683d49814680dfa426", + "homepage": "https://github.com/jshttp/accepts#readme", + "keywords": [ + "accept", + "accepts", + "content", + "negotiation" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "accepts", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/accepts.git" + }, + "scripts": { + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.3.3" +} diff --git a/hm_sunwell/node_modules/align-text/LICENSE b/hm_sunwell/node_modules/align-text/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/hm_sunwell/node_modules/align-text/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/align-text/README.md b/hm_sunwell/node_modules/align-text/README.md new file mode 100644 index 0000000..476b97f --- /dev/null +++ b/hm_sunwell/node_modules/align-text/README.md @@ -0,0 +1,236 @@ +# align-text [![NPM version](https://badge.fury.io/js/align-text.svg)](http://badge.fury.io/js/align-text) [![Build Status](https://travis-ci.org/jonschlinkert/align-text.svg)](https://travis-ci.org/jonschlinkert/align-text) + +> Align the text in a string. + +**Examples** + +Align text values in an array: + +```js +align([1, 2, 3, 100]); +//=> [' 1', ' 2', ' 3', '100'] +``` + +Or [do stuff like this](./example.js): + +[![screen shot 2015-06-09 at 2 08 34 am](https://cloud.githubusercontent.com/assets/383994/8051597/7b716fbc-0e4c-11e5-9aef-4493fd22db58.png)](./example.js) + +Visit [the example](./example.js) to see how this works. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i align-text --save +``` + +## Usage + +```js +var align = require('align-text'); +align(text, callback_function_or_integer); +``` + +**Params** + +* `text` can be a **string or array**. If a string is passed, a string will be returned. If an array is passed, an array will be returned. +* `callback|integer`: if an integer, the text will be indented by that amount. If a function, it must return an integer representing the amount of leading indentation to use as `align` loops over each line. + +**Example** + +```js +align(text, 4); +``` + +Would align: + +``` +abc +abc +abc +``` + +To: + +``` + abc + abc + abc +``` + +## callback + +### params + +The callback is used to determine the indentation of each line and gets the following params: + +* `len` the length of the "current" line +* `longest` the length of the longest line +* `line` the current line (string) being aligned +* `lines` the array of all lines + +### return + +The callback may return: + +* an integer that represents the number of spaces to use for padding, +* or an object with the following properties: + - `indent`: **{Number}** the amount of indentation to use. Default is `0` when an object is returned. + - `character`: **{String}** the character to use for indentation. Default is `''` (empty string) when an object is returned. + - `prefix`: **{String}** leading characters to use at the beginning of each line. `''` (empty string) when an object is returned. + +**Integer example:** + +```js +// calculate half the difference between the length +// of the current line and the longest line +function centerAlign(len, longest, line, lines) { + return Math.floor((longest - len) / 2); +} +``` + +**Object example:** + +```js +function centerAlign(len, longest, line, lines) { + return { + character: '\t', + indent: Math.floor((longest - len) / 2), + prefix: '~ ', + } +} +``` + +## Usage examples + +### Center align + +Using the `centerAlign` function from above: + +```js +align(text, centerAlign); +``` + +Would align this text: + +```js +Lorem ipsum dolor sit amet +consectetur adipiscin +elit, sed do eiusmod tempor incididun +ut labore et dolor +magna aliqua. Ut enim ad mini +veniam, quis +``` + +Resulting in this: + +``` + Lorem ipsum dolor sit amet, + consectetur adipiscing +elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim + veniam, quis +``` + +**Customize** + +If you wanted to add more padding on the left, just pass the number in the callback. + +For example, to add 4 spaces before every line: + +```js +function centerAlign(len, longest, line, lines) { + return 4 + Math.floor((longest - len) / 2); +} +``` + +Would result in: + +``` + Lorem ipsum dolor sit amet, + consectetur adipiscing + elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim + veniam, quis +``` + +### Bullets + +```js +align(text, function (len, max, line, lines) { + return {prefix: ' - '}; +}); +``` + +Would return: + +``` +- Lorem ipsum dolor sit amet, +- consectetur adipiscing +- elit, sed do eiusmod tempor incididunt +- ut labore et dolore +- magna aliqua. Ut enim ad minim +- veniam, quis +``` + +### Different indent character + +```js +align(text, function (len, max, line, lines) { + return { + indent: Math.floor((max - len) / 2), + character: '~', + }; +}); +``` + +Would return + +``` +~~~~~Lorem ipsum dolor sit amet, +~~~~~~~~consectetur adipiscing +elit, sed do eiusmod tempor incididunt +~~~~~~~~~ut labore et dolore +~~~~magna aliqua. Ut enim ad minim +~~~~~~~~~~~~~veniam, quis +``` + +## Related projects + +* [center-align](https://github.com/jonschlinkert/center-align): Center-align the text in a string. +* [justify](https://github.com/bahamas10/node-justify): Left or right (or both) justify text using a custom width and character +* [longest](https://github.com/jonschlinkert/longest): Get the longest item in an array. +* [right-align](https://github.com/jonschlinkert/right-align): Right-align the text in a string. +* [repeat-string](https://github.com/jonschlinkert/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. +* [word-wrap](https://github.com/jonschlinkert/word-wrap): Wrap words to a specified length. + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/align-text/issues/new) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert) +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 09, 2015._ diff --git a/hm_sunwell/node_modules/align-text/index.js b/hm_sunwell/node_modules/align-text/index.js new file mode 100644 index 0000000..75902a3 --- /dev/null +++ b/hm_sunwell/node_modules/align-text/index.js @@ -0,0 +1,52 @@ +/*! + * align-text + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var typeOf = require('kind-of'); +var repeat = require('repeat-string'); +var longest = require('longest'); + +module.exports = function alignText(val, fn) { + var lines, type = typeOf(val); + + if (type === 'array') { + lines = val; + } else if (type === 'string') { + lines = val.split(/(?:\r\n|\n)/); + } else { + throw new TypeError('align-text expects a string or array.'); + } + + var fnType = typeOf(fn); + var len = lines.length; + var max = longest(lines); + var res = [], i = 0; + + while (len--) { + var line = String(lines[i++]); + var diff; + + if (fnType === 'function') { + diff = fn(line.length, max.length, line, lines, i); + } else if (fnType === 'number') { + diff = fn; + } else { + diff = max.length - line.length; + } + + if (typeOf(diff) === 'number') { + res.push(repeat(' ', diff) + line); + } else if (typeOf(diff) === 'object') { + var result = repeat(diff.character || ' ', diff.indent || 0); + res.push((diff.prefix || '') + result + line); + } + } + + if (type === 'array') return res; + return res.join('\n'); +}; diff --git a/hm_sunwell/node_modules/align-text/package.json b/hm_sunwell/node_modules/align-text/package.json new file mode 100644 index 0000000..c8dc006 --- /dev/null +++ b/hm_sunwell/node_modules/align-text/package.json @@ -0,0 +1,109 @@ +{ + "_args": [ + [ + "align-text@^0.1.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/center-align" + ] + ], + "_from": "align-text@>=0.1.3 <0.2.0", + "_id": "align-text@0.1.4", + "_inCache": true, + "_installable": true, + "_location": "/align-text", + "_nodeVersion": "5.5.0", + "_npmOperationalInternal": { + "host": "packages-9-west.internal.npmjs.com", + "tmp": "tmp/align-text-0.1.4.tgz_1454377856920_0.9624228512402624" + }, + "_npmUser": { + "email": "snnskwtnb@gmail.com", + "name": "shinnn" + }, + "_npmVersion": "3.6.0", + "_phantomChildren": {}, + "_requested": { + "name": "align-text", + "raw": "align-text@^0.1.3", + "rawSpec": "^0.1.3", + "scope": null, + "spec": ">=0.1.3 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/center-align", + "/right-align" + ], + "_resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "_shasum": "0cd90a561093f35d0a99256c22b7069433fad117", + "_shrinkwrap": null, + "_spec": "align-text@^0.1.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/center-align", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/align-text/issues" + }, + "dependencies": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "description": "Align the text in a string.", + "devDependencies": { + "mocha": "*", + "should": "*", + "word-wrap": "^1.0.3" + }, + "directories": {}, + "dist": { + "shasum": "0cd90a561093f35d0a99256c22b7069433fad117", + "tarball": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "7f08e823a54c6bda319d875895813537a66a4c5e", + "homepage": "https://github.com/jonschlinkert/align-text", + "keywords": [ + "align", + "align-center", + "alignment", + "center", + "center-align", + "indent", + "pad", + "padding", + "right", + "right-align", + "text", + "typography" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "shinnn", + "email": "snnskwtnb@gmail.com" + } + ], + "name": "align-text", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/jonschlinkert/align-text.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.1.4" +} diff --git a/hm_sunwell/node_modules/amdefine/LICENSE b/hm_sunwell/node_modules/amdefine/LICENSE new file mode 100644 index 0000000..9b25ee0 --- /dev/null +++ b/hm_sunwell/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011-2016, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2011-2016, The Dojo Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/amdefine/README.md b/hm_sunwell/node_modules/amdefine/README.md new file mode 100644 index 0000000..037a6e8 --- /dev/null +++ b/hm_sunwell/node_modules/amdefine/README.md @@ -0,0 +1,171 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.1.0" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +### amdefine/intercept + +Consider this very experimental. + +Instead of pasting the piece of text for the amdefine setup of a `define` +variable in each module you create or consume, you can use `amdefine/intercept` +instead. It will automatically insert the above snippet in each .js file loaded +by Node. + +**Warning**: you should only use this if you are creating an application that +is consuming AMD style defined()'d modules that are distributed via npm and want +to run that code in Node. + +For library code where you are not sure if it will be used by others in Node or +in the browser, then explicitly depending on amdefine and placing the code +snippet above is suggested path, instead of using `amdefine/intercept`. The +intercept module affects all .js files loaded in the Node app, and it is +inconsiderate to modify global state like that unless you are also controlling +the top level app. + +#### Why distribute AMD-style modules via npm? + +npm has a lot of weaknesses for front-end use (installed layout is not great, +should have better support for the `baseUrl + moduleID + '.js' style of loading, +single file JS installs), but some people want a JS package manager and are +willing to live with those constraints. If that is you, but still want to author +in AMD style modules to get dynamic require([]), better direct source usage and +powerful loader plugin support in the browser, then this tool can help. + +#### amdefine/intercept usage + +Just require it in your top level app module (for example index.js, server.js): + +```javascript +require('amdefine/intercept'); +``` + +The module does not return a value, so no need to assign the result to a local +variable. + +Then just require() code as you normally would with Node's require(). Any .js +loaded after the intercept require will have the amdefine check injected in +the .js source as it is loaded. It does not modify the source on disk, just +prepends some content to the text of the module as it is loaded by Node. + +#### How amdefine/intercept works + +It overrides the `Module._extensions['.js']` in Node to automatically prepend +the amdefine snippet above. So, it will affect any .js file loaded by your +app. + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +node all-intercept.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/hm_sunwell/node_modules/amdefine/amdefine.js b/hm_sunwell/node_modules/amdefine/amdefine.js new file mode 100644 index 0000000..ca830ba --- /dev/null +++ b/hm_sunwell/node_modules/amdefine/amdefine.js @@ -0,0 +1,301 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [requireFn]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, requireFn) { + 'use strict'; + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + path = require('path'), + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + if (callback) { + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + requireFn = requireFn || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(requireFn, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(requireFn, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(m.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/hm_sunwell/node_modules/amdefine/intercept.js b/hm_sunwell/node_modules/amdefine/intercept.js new file mode 100644 index 0000000..771a983 --- /dev/null +++ b/hm_sunwell/node_modules/amdefine/intercept.js @@ -0,0 +1,36 @@ +/*jshint node: true */ +var inserted, + Module = require('module'), + fs = require('fs'), + existingExtFn = Module._extensions['.js'], + amdefineRegExp = /amdefine\.js/; + +inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}"; + +//From the node/lib/module.js source: +function stripBOM(content) { + // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + // because the buffer-to-string conversion in `fs.readFileSync()` + // translates it to FEFF, the UTF-16 BOM. + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +} + +//Also adapted from the node/lib/module.js source: +function intercept(module, filename) { + var content = stripBOM(fs.readFileSync(filename, 'utf8')); + + if (!amdefineRegExp.test(module.id)) { + content = inserted + content; + } + + module._compile(content, filename); +} + +intercept._id = 'amdefine/intercept'; + +if (!existingExtFn._id || existingExtFn._id !== intercept._id) { + Module._extensions['.js'] = intercept; +} diff --git a/hm_sunwell/node_modules/amdefine/package.json b/hm_sunwell/node_modules/amdefine/package.json new file mode 100644 index 0000000..b34427e --- /dev/null +++ b/hm_sunwell/node_modules/amdefine/package.json @@ -0,0 +1,79 @@ +{ + "_args": [ + [ + "amdefine@>=0.0.4", + "/home/xor/shared_vm/git/node-sunwell/node_modules/source-map" + ] + ], + "_from": "amdefine@>=0.0.4", + "_id": "amdefine@1.0.1", + "_inCache": true, + "_installable": true, + "_location": "/amdefine", + "_nodeVersion": "6.7.0", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/amdefine-1.0.1.tgz_1478062849665_0.19916908955201507" + }, + "_npmUser": { + "email": "jrburke@gmail.com", + "name": "jrburke" + }, + "_npmVersion": "3.10.3", + "_phantomChildren": {}, + "_requested": { + "name": "amdefine", + "raw": "amdefine@>=0.0.4", + "rawSpec": ">=0.0.4", + "scope": null, + "spec": ">=0.0.4", + "type": "range" + }, + "_requiredBy": [ + "/handlebars/source-map", + "/source-map" + ], + "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "_shasum": "4a5282ac164729e93619bcfd3ad151f817ce91f5", + "_shrinkwrap": null, + "_spec": "amdefine@>=0.0.4", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/source-map", + "author": { + "email": "jrburke@gmail.com", + "name": "James Burke", + "url": "http://github.com/jrburke" + }, + "bugs": { + "url": "https://github.com/jrburke/amdefine/issues" + }, + "dependencies": {}, + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "4a5282ac164729e93619bcfd3ad151f817ce91f5", + "tarball": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + }, + "engines": { + "node": ">=0.4.2" + }, + "gitHead": "e59edc9da24404ec7937098e3992f8fb0e260be7", + "homepage": "http://github.com/jrburke/amdefine", + "license": "BSD-3-Clause OR MIT", + "main": "./amdefine.js", + "maintainers": [ + { + "name": "jrburke", + "email": "jrburke@gmail.com" + } + ], + "name": "amdefine", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jrburke/amdefine.git" + }, + "scripts": {}, + "version": "1.0.1" +} diff --git a/hm_sunwell/node_modules/ansi-regex/index.js b/hm_sunwell/node_modules/ansi-regex/index.js new file mode 100644 index 0000000..4906755 --- /dev/null +++ b/hm_sunwell/node_modules/ansi-regex/index.js @@ -0,0 +1,4 @@ +'use strict'; +module.exports = function () { + return /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; +}; diff --git a/hm_sunwell/node_modules/ansi-regex/license b/hm_sunwell/node_modules/ansi-regex/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/hm_sunwell/node_modules/ansi-regex/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/ansi-regex/package.json b/hm_sunwell/node_modules/ansi-regex/package.json new file mode 100644 index 0000000..d4ed076 --- /dev/null +++ b/hm_sunwell/node_modules/ansi-regex/package.json @@ -0,0 +1,113 @@ +{ + "_args": [ + [ + "ansi-regex@^2.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/has-ansi" + ] + ], + "_from": "ansi-regex@>=2.0.0 <3.0.0", + "_id": "ansi-regex@2.0.0", + "_inCache": true, + "_installable": true, + "_location": "/ansi-regex", + "_nodeVersion": "0.12.5", + "_npmUser": { + "email": "sindresorhus@gmail.com", + "name": "sindresorhus" + }, + "_npmVersion": "2.11.2", + "_phantomChildren": {}, + "_requested": { + "name": "ansi-regex", + "raw": "ansi-regex@^2.0.0", + "rawSpec": "^2.0.0", + "scope": null, + "spec": ">=2.0.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/has-ansi", + "/strip-ansi" + ], + "_resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "_shasum": "c5061b6e0ef8a81775e50f5d66151bf6bf371107", + "_shrinkwrap": null, + "_spec": "ansi-regex@^2.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/has-ansi", + "author": { + "email": "sindresorhus@gmail.com", + "name": "Sindre Sorhus", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/ansi-regex/issues" + }, + "dependencies": {}, + "description": "Regular expression for matching ANSI escape codes", + "devDependencies": { + "mocha": "*" + }, + "directories": {}, + "dist": { + "shasum": "c5061b6e0ef8a81775e50f5d66151bf6bf371107", + "tarball": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "57c3f2941a73079fa8b081e02a522e3d29913e2f", + "homepage": "https://github.com/sindresorhus/ansi-regex", + "keywords": [ + "256", + "ansi", + "cli", + "color", + "colors", + "colour", + "command-line", + "console", + "escape", + "find", + "formatting", + "match", + "pattern", + "re", + "regex", + "regexp", + "rgb", + "shell", + "string", + "styles", + "terminal", + "test", + "text", + "tty", + "xterm" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + } + ], + "name": "ansi-regex", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/ansi-regex.git" + }, + "scripts": { + "test": "mocha test/test.js", + "view-supported": "node test/viewCodes.js" + }, + "version": "2.0.0" +} diff --git a/hm_sunwell/node_modules/ansi-regex/readme.md b/hm_sunwell/node_modules/ansi-regex/readme.md new file mode 100644 index 0000000..1a4894e --- /dev/null +++ b/hm_sunwell/node_modules/ansi-regex/readme.md @@ -0,0 +1,31 @@ +# ansi-regex [![Build Status](https://travis-ci.org/sindresorhus/ansi-regex.svg?branch=master)](https://travis-ci.org/sindresorhus/ansi-regex) + +> Regular expression for matching [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code) + + +## Install + +``` +$ npm install --save ansi-regex +``` + + +## Usage + +```js +var ansiRegex = require('ansi-regex'); + +ansiRegex().test('\u001b[4mcake\u001b[0m'); +//=> true + +ansiRegex().test('cake'); +//=> false + +'\u001b[4mcake\u001b[0m'.match(ansiRegex()); +//=> ['\u001b[4m', '\u001b[0m'] +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/hm_sunwell/node_modules/ansi-styles/index.js b/hm_sunwell/node_modules/ansi-styles/index.js new file mode 100644 index 0000000..7894527 --- /dev/null +++ b/hm_sunwell/node_modules/ansi-styles/index.js @@ -0,0 +1,65 @@ +'use strict'; + +function assembleStyles () { + var styles = { + modifiers: { + reset: [0, 0], + bold: [1, 22], // 21 isn't widely supported and 22 does the same thing + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + colors: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39] + }, + bgColors: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49] + } + }; + + // fix humans + styles.colors.grey = styles.colors.gray; + + Object.keys(styles).forEach(function (groupName) { + var group = styles[groupName]; + + Object.keys(group).forEach(function (styleName) { + var style = group[styleName]; + + styles[styleName] = group[styleName] = { + open: '\u001b[' + style[0] + 'm', + close: '\u001b[' + style[1] + 'm' + }; + }); + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + }); + + return styles; +} + +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); diff --git a/hm_sunwell/node_modules/ansi-styles/license b/hm_sunwell/node_modules/ansi-styles/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/hm_sunwell/node_modules/ansi-styles/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/ansi-styles/package.json b/hm_sunwell/node_modules/ansi-styles/package.json new file mode 100644 index 0000000..1577566 --- /dev/null +++ b/hm_sunwell/node_modules/ansi-styles/package.json @@ -0,0 +1,106 @@ +{ + "_args": [ + [ + "ansi-styles@^2.2.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/chalk" + ] + ], + "_from": "ansi-styles@>=2.2.1 <3.0.0", + "_id": "ansi-styles@2.2.1", + "_inCache": true, + "_installable": true, + "_location": "/ansi-styles", + "_nodeVersion": "4.3.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/ansi-styles-2.2.1.tgz_1459197317833_0.9694824463222176" + }, + "_npmUser": { + "email": "sindresorhus@gmail.com", + "name": "sindresorhus" + }, + "_npmVersion": "3.8.3", + "_phantomChildren": {}, + "_requested": { + "name": "ansi-styles", + "raw": "ansi-styles@^2.2.1", + "rawSpec": "^2.2.1", + "scope": null, + "spec": ">=2.2.1 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/chalk" + ], + "_resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "_shasum": "b432dd3358b634cf75e1e4664368240533c1ddbe", + "_shrinkwrap": null, + "_spec": "ansi-styles@^2.2.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/chalk", + "author": { + "email": "sindresorhus@gmail.com", + "name": "Sindre Sorhus", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/chalk/ansi-styles/issues" + }, + "dependencies": {}, + "description": "ANSI escape codes for styling strings in the terminal", + "devDependencies": { + "mocha": "*" + }, + "directories": {}, + "dist": { + "shasum": "b432dd3358b634cf75e1e4664368240533c1ddbe", + "tarball": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "95c59b23be760108b6530ca1c89477c21b258032", + "homepage": "https://github.com/chalk/ansi-styles#readme", + "keywords": [ + "256", + "ansi", + "cli", + "color", + "colors", + "colour", + "command-line", + "console", + "escape", + "formatting", + "log", + "logging", + "rgb", + "shell", + "string", + "styles", + "terminal", + "text", + "tty", + "xterm" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "name": "ansi-styles", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/ansi-styles.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "2.2.1" +} diff --git a/hm_sunwell/node_modules/ansi-styles/readme.md b/hm_sunwell/node_modules/ansi-styles/readme.md new file mode 100644 index 0000000..3f933f6 --- /dev/null +++ b/hm_sunwell/node_modules/ansi-styles/readme.md @@ -0,0 +1,86 @@ +# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles) + +> [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal + +You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings. + +![](screenshot.png) + + +## Install + +``` +$ npm install --save ansi-styles +``` + + +## Usage + +```js +var ansi = require('ansi-styles'); + +console.log(ansi.green.open + 'Hello world!' + ansi.green.close); +``` + + +## API + +Each style has an `open` and `close` property. + + +## Styles + +### Modifiers + +- `reset` +- `bold` +- `dim` +- `italic` *(not widely supported)* +- `underline` +- `inverse` +- `hidden` +- `strikethrough` *(not widely supported)* + +### Colors + +- `black` +- `red` +- `green` +- `yellow` +- `blue` +- `magenta` +- `cyan` +- `white` +- `gray` + +### Background colors + +- `bgBlack` +- `bgRed` +- `bgGreen` +- `bgYellow` +- `bgBlue` +- `bgMagenta` +- `bgCyan` +- `bgWhite` + + +## Advanced usage + +By default you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module. + +- `ansi.modifiers` +- `ansi.colors` +- `ansi.bgColors` + + +###### Example + +```js +console.log(ansi.colors.green.open); +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/hm_sunwell/node_modules/argparse/CHANGELOG.md b/hm_sunwell/node_modules/argparse/CHANGELOG.md new file mode 100644 index 0000000..e422115 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/CHANGELOG.md @@ -0,0 +1,179 @@ +1.0.9 / 2016-09-29 +------------------ + +- Rerelease after 1.0.8 - deps cleanup. + + +1.0.8 / 2016-09-29 +------------------ + +- Maintenance (deps bump, fix node 6.5+ tests, coverage report). + + +1.0.7 / 2016-03-17 +------------------ + +- Teach `addArgument` to accept string arg names. #97, @tomxtobin. + + +1.0.6 / 2016-02-06 +------------------ + +- Maintenance: moved to eslint & updated CS. + + +1.0.5 / 2016-02-05 +------------------ + +- Removed lodash dependency to significantly reduce install size. + Thanks to @mourner. + + +1.0.4 / 2016-01-17 +------------------ + +- Maintenance: lodash update to 4.0.0. + + +1.0.3 / 2015-10-27 +------------------ + +- Fix parse `=` in args: `--examplepath="C:\myfolder\env=x64"`. #84, @CatWithApple. + + +1.0.2 / 2015-03-22 +------------------ + +- Relaxed lodash version dependency. + + +1.0.1 / 2015-02-20 +------------------ + +- Changed dependencies to be compatible with ancient nodejs. + + +1.0.0 / 2015-02-19 +------------------ + +- Maintenance release. +- Replaced `underscore` with `lodash`. +- Bumped version to 1.0.0 to better reflect semver meaning. +- HISTORY.md -> CHANGELOG.md + + +0.1.16 / 2013-12-01 +------------------- + +- Maintenance release. Updated dependencies and docs. + + +0.1.15 / 2013-05-13 +------------------- + +- Fixed #55, @trebor89 + + +0.1.14 / 2013-05-12 +------------------- + +- Fixed #62, @maxtaco + + +0.1.13 / 2013-04-08 +------------------- + +- Added `.npmignore` to reduce package size + + +0.1.12 / 2013-02-10 +------------------- + +- Fixed conflictHandler (#46), @hpaulj + + +0.1.11 / 2013-02-07 +------------------- + +- Multiple bugfixes, @hpaulj +- Added 70+ tests (ported from python), @hpaulj +- Added conflictHandler, @applepicke +- Added fromfilePrefixChar, @hpaulj + + +0.1.10 / 2012-12-30 +------------------- + +- Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion) + support, thanks to @hpaulj +- Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj + + +0.1.9 / 2012-12-27 +------------------ + +- Fixed option dest interferens with other options (issue #23), thanks to @hpaulj +- Fixed default value behavior with `*` positionals, thanks to @hpaulj +- Improve `getDefault()` behavior, thanks to @hpaulj +- Imrove negative argument parsing, thanks to @hpaulj + + +0.1.8 / 2012-12-01 +------------------ + +- Fixed parser parents (issue #19), thanks to @hpaulj +- Fixed negative argument parse (issue #20), thanks to @hpaulj + + +0.1.7 / 2012-10-14 +------------------ + +- Fixed 'choices' argument parse (issue #16) +- Fixed stderr output (issue #15) + + +0.1.6 / 2012-09-09 +------------------ + +- Fixed check for conflict of options (thanks to @tomxtobin) + + +0.1.5 / 2012-09-03 +------------------ + +- Fix parser #setDefaults method (thanks to @tomxtobin) + + +0.1.4 / 2012-07-30 +------------------ + +- Fixed pseudo-argument support (thanks to @CGamesPlay) +- Fixed addHelp default (should be true), if not set (thanks to @benblank) + + +0.1.3 / 2012-06-27 +------------------ + +- Fixed formatter api name: Formatter -> HelpFormatter + + +0.1.2 / 2012-05-29 +------------------ + +- Added basic tests +- Removed excess whitespace in help +- Fixed error reporting, when parcer with subcommands + called with empty arguments + + +0.1.1 / 2012-05-23 +------------------ + +- Fixed line wrapping in help formatter +- Added better error reporting on invalid arguments + + +0.1.0 / 2012-05-16 +------------------ + +- First release. diff --git a/hm_sunwell/node_modules/argparse/LICENSE b/hm_sunwell/node_modules/argparse/LICENSE new file mode 100644 index 0000000..1afdae5 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/LICENSE @@ -0,0 +1,21 @@ +(The MIT License) + +Copyright (C) 2012 by Vitaly Puzrin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/argparse/README.md b/hm_sunwell/node_modules/argparse/README.md new file mode 100644 index 0000000..2d0bcab --- /dev/null +++ b/hm_sunwell/node_modules/argparse/README.md @@ -0,0 +1,253 @@ +argparse +======== + +[![Build Status](https://secure.travis-ci.org/nodeca/argparse.png?branch=master)](http://travis-ci.org/nodeca/argparse) +[![NPM version](https://img.shields.io/npm/v/argparse.svg)](https://www.npmjs.org/package/argparse) + +CLI arguments parser for node.js. Javascript port of python's +[argparse](http://docs.python.org/dev/library/argparse.html) module +(original version 3.2). That's a full port, except some very rare options, +recorded in issue tracker. + +**NB. Difference with original.** + +- Method names changed to camelCase. See [generated docs](http://nodeca.github.com/argparse/). +- Use `defaultValue` instead of `default`. + + +Example +======= + +test.js file: + +```javascript +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp:true, + description: 'Argparse example' +}); +parser.addArgument( + [ '-f', '--foo' ], + { + help: 'foo bar' + } +); +parser.addArgument( + [ '-b', '--bar' ], + { + help: 'bar foo' + } +); +parser.addArgument( + '--baz', + { + help: 'baz bar' + } +); +var args = parser.parseArgs(); +console.dir(args); +``` + +Display help: + +``` +$ ./test.js -h +usage: example.js [-h] [-v] [-f FOO] [-b BAR] [--baz BAZ] + +Argparse example + +Optional arguments: + -h, --help Show this help message and exit. + -v, --version Show program's version number and exit. + -f FOO, --foo FOO foo bar + -b BAR, --bar BAR bar foo + --baz BAZ baz bar +``` + +Parse arguments: + +``` +$ ./test.js -f=3 --bar=4 --baz 5 +{ foo: '3', bar: '4', baz: '5' } +``` + +More [examples](https://github.com/nodeca/argparse/tree/master/examples). + + +ArgumentParser objects +====================== + +``` +new ArgumentParser({paramters hash}); +``` + +Creates a new ArgumentParser object. + +**Supported params:** + +- ```description``` - Text to display before the argument help. +- ```epilog``` - Text to display after the argument help. +- ```addHelp``` - Add a -h/–help option to the parser. (default: true) +- ```argumentDefault``` - Set the global default value for arguments. (default: null) +- ```parents``` - A list of ArgumentParser objects whose arguments should also be included. +- ```prefixChars``` - The set of characters that prefix optional arguments. (default: ‘-‘) +- ```formatterClass``` - A class for customizing the help output. +- ```prog``` - The name of the program (default: `path.basename(process.argv[1])`) +- ```usage``` - The string describing the program usage (default: generated) +- ```conflictHandler``` - Usually unnecessary, defines strategy for resolving conflicting optionals. + +**Not supportied yet** + +- ```fromfilePrefixChars``` - The set of characters that prefix files from which additional arguments should be read. + + +Details in [original ArgumentParser guide](http://docs.python.org/dev/library/argparse.html#argumentparser-objects) + + +addArgument() method +==================== + +``` +ArgumentParser.addArgument(name or flag or [name] or [flags...], {options}) +``` + +Defines how a single command-line argument should be parsed. + +- ```name or flag or [name] or [flags...]``` - Either a positional name + (e.g., `'foo'`), a single option (e.g., `'-f'` or `'--foo'`), an array + of a single positional name (e.g., `['foo']`), or an array of options + (e.g., `['-f', '--foo']`). + +Options: + +- ```action``` - The basic type of action to be taken when this argument is encountered at the command line. +- ```nargs```- The number of command-line arguments that should be consumed. +- ```constant``` - A constant value required by some action and nargs selections. +- ```defaultValue``` - The value produced if the argument is absent from the command line. +- ```type``` - The type to which the command-line argument should be converted. +- ```choices``` - A container of the allowable values for the argument. +- ```required``` - Whether or not the command-line option may be omitted (optionals only). +- ```help``` - A brief description of what the argument does. +- ```metavar``` - A name for the argument in usage messages. +- ```dest``` - The name of the attribute to be added to the object returned by parseArgs(). + +Details in [original add_argument guide](http://docs.python.org/dev/library/argparse.html#the-add-argument-method) + + +Action (some details) +================ + +ArgumentParser objects associate command-line arguments with actions. +These actions can do just about anything with the command-line arguments associated +with them, though most actions simply add an attribute to the object returned by +parseArgs(). The action keyword argument specifies how the command-line arguments +should be handled. The supported actions are: + +- ```store``` - Just stores the argument’s value. This is the default action. +- ```storeConst``` - Stores value, specified by the const keyword argument. + (Note that the const keyword argument defaults to the rather unhelpful None.) + The 'storeConst' action is most commonly used with optional arguments, that + specify some sort of flag. +- ```storeTrue``` and ```storeFalse``` - Stores values True and False + respectively. These are special cases of 'storeConst'. +- ```append``` - Stores a list, and appends each argument value to the list. + This is useful to allow an option to be specified multiple times. +- ```appendConst``` - Stores a list, and appends value, specified by the + const keyword argument to the list. (Note, that the const keyword argument defaults + is None.) The 'appendConst' action is typically used when multiple arguments need + to store constants to the same list. +- ```count``` - Counts the number of times a keyword argument occurs. For example, + used for increasing verbosity levels. +- ```help``` - Prints a complete help message for all the options in the current + parser and then exits. By default a help action is automatically added to the parser. + See ArgumentParser for details of how the output is created. +- ```version``` - Prints version information and exit. Expects a `version=` + keyword argument in the addArgument() call. + +Details in [original action guide](http://docs.python.org/dev/library/argparse.html#action) + + +Sub-commands +============ + +ArgumentParser.addSubparsers() + +Many programs split their functionality into a number of sub-commands, for +example, the svn program can invoke sub-commands like `svn checkout`, `svn update`, +and `svn commit`. Splitting up functionality this way can be a particularly good +idea when a program performs several different functions which require different +kinds of command-line arguments. `ArgumentParser` supports creation of such +sub-commands with `addSubparsers()` method. The `addSubparsers()` method is +normally called with no arguments and returns an special action object. +This object has a single method `addParser()`, which takes a command name and +any `ArgumentParser` constructor arguments, and returns an `ArgumentParser` object +that can be modified as usual. + +Example: + +sub_commands.js +```javascript +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp:true, + description: 'Argparse examples: sub-commands', +}); + +var subparsers = parser.addSubparsers({ + title:'subcommands', + dest:"subcommand_name" +}); + +var bar = subparsers.addParser('c1', {addHelp:true}); +bar.addArgument( + [ '-f', '--foo' ], + { + action: 'store', + help: 'foo3 bar3' + } +); +var bar = subparsers.addParser( + 'c2', + {aliases:['co'], addHelp:true} +); +bar.addArgument( + [ '-b', '--bar' ], + { + action: 'store', + type: 'int', + help: 'foo3 bar3' + } +); + +var args = parser.parseArgs(); +console.dir(args); + +``` + +Details in [original sub-commands guide](http://docs.python.org/dev/library/argparse.html#sub-commands) + + +Contributors +============ + +- [Eugene Shkuropat](https://github.com/shkuropat) +- [Paul Jacobson](https://github.com/hpaulj) + +[others](https://github.com/nodeca/argparse/graphs/contributors) + +License +======= + +Copyright (c) 2012 [Vitaly Puzrin](https://github.com/puzrin). +Released under the MIT license. See +[LICENSE](https://github.com/nodeca/argparse/blob/master/LICENSE) for details. + + diff --git a/hm_sunwell/node_modules/argparse/index.js b/hm_sunwell/node_modules/argparse/index.js new file mode 100644 index 0000000..3bbc143 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/index.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./lib/argparse'); diff --git a/hm_sunwell/node_modules/argparse/lib/action.js b/hm_sunwell/node_modules/argparse/lib/action.js new file mode 100644 index 0000000..ef35989 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action.js @@ -0,0 +1,146 @@ +/** + * class Action + * + * Base class for all actions + * Do not call in your code, use this class only for inherits your own action + * + * Information about how to convert command line strings to Javascript objects. + * Action objects are used by an ArgumentParser to represent the information + * needed to parse a single argument from one or more strings from the command + * line. The keyword arguments to the Action constructor are also all attributes + * of Action instances. + * + * #####Alowed keywords: + * + * - `store` + * - `storeConstant` + * - `storeTrue` + * - `storeFalse` + * - `append` + * - `appendConstant` + * - `count` + * - `help` + * - `version` + * + * Information about action options see [[Action.new]] + * + * See also [original guide](http://docs.python.org/dev/library/argparse.html#action) + * + **/ + +'use strict'; + + +// Constants +var c = require('./const'); + + +/** + * new Action(options) + * + * Base class for all actions. Used only for inherits + * + * + * ##### Options: + * + * - `optionStrings` A list of command-line option strings for the action. + * - `dest` Attribute to hold the created object(s) + * - `nargs` The number of command-line arguments that should be consumed. + * By default, one argument will be consumed and a single value will be + * produced. + * - `constant` Default value for an action with no value. + * - `defaultValue` The value to be produced if the option is not specified. + * - `type` Cast to 'string'|'int'|'float'|'complex'|function (string). If + * None, 'string'. + * - `choices` The choices available. + * - `required` True if the action must always be specified at the command + * line. + * - `help` The help describing the argument. + * - `metavar` The name to be used for the option's argument with the help + * string. If None, the 'dest' value will be used as the name. + * + * ##### nargs supported values: + * + * - `N` (an integer) consumes N arguments (and produces a list) + * - `?` consumes zero or one arguments + * - `*` consumes zero or more arguments (and produces a list) + * - `+` consumes one or more arguments (and produces a list) + * + * Note: that the difference between the default and nargs=1 is that with the + * default, a single value will be produced, while with nargs=1, a list + * containing a single value will be produced. + **/ +var Action = module.exports = function Action(options) { + options = options || {}; + this.optionStrings = options.optionStrings || []; + this.dest = options.dest; + this.nargs = typeof options.nargs !== 'undefined' ? options.nargs : null; + this.constant = typeof options.constant !== 'undefined' ? options.constant : null; + this.defaultValue = options.defaultValue; + this.type = typeof options.type !== 'undefined' ? options.type : null; + this.choices = typeof options.choices !== 'undefined' ? options.choices : null; + this.required = typeof options.required !== 'undefined' ? options.required : false; + this.help = typeof options.help !== 'undefined' ? options.help : null; + this.metavar = typeof options.metavar !== 'undefined' ? options.metavar : null; + + if (!(this.optionStrings instanceof Array)) { + throw new Error('optionStrings should be an array'); + } + if (typeof this.required !== 'undefined' && typeof this.required !== 'boolean') { + throw new Error('required should be a boolean'); + } +}; + +/** + * Action#getName -> String + * + * Tells action name + **/ +Action.prototype.getName = function () { + if (this.optionStrings.length > 0) { + return this.optionStrings.join('/'); + } else if (this.metavar !== null && this.metavar !== c.SUPPRESS) { + return this.metavar; + } else if (typeof this.dest !== 'undefined' && this.dest !== c.SUPPRESS) { + return this.dest; + } + return null; +}; + +/** + * Action#isOptional -> Boolean + * + * Return true if optional + **/ +Action.prototype.isOptional = function () { + return !this.isPositional(); +}; + +/** + * Action#isPositional -> Boolean + * + * Return true if positional + **/ +Action.prototype.isPositional = function () { + return (this.optionStrings.length === 0); +}; + +/** + * Action#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Should be implemented in inherited classes + * + * ##### Example + * + * ActionCount.prototype.call = function (parser, namespace, values, optionString) { + * namespace.set(this.dest, (namespace[this.dest] || 0) + 1); + * }; + * + **/ +Action.prototype.call = function () { + throw new Error('.call() not defined');// Not Implemented error +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/append.js b/hm_sunwell/node_modules/argparse/lib/action/append.js new file mode 100644 index 0000000..b5da0de --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/append.js @@ -0,0 +1,53 @@ +/*:nodoc:* + * class ActionAppend + * + * This action stores a list, and appends each argument value to the list. + * This is useful to allow an option to be specified multiple times. + * This class inherided from [[Action]] + * + **/ + +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var c = require('../const'); + +/*:nodoc:* + * new ActionAppend(options) + * - options (object): options hash see [[Action.new]] + * + * Note: options.nargs should be optional for constants + * and more then zero for other + **/ +var ActionAppend = module.exports = function ActionAppend(options) { + options = options || {}; + if (this.nargs <= 0) { + throw new Error('nargs for append actions must be > 0; if arg ' + + 'strings are not supplying the value to append, ' + + 'the append const action may be more appropriate'); + } + if (!!this.constant && this.nargs !== c.OPTIONAL) { + throw new Error('nargs must be OPTIONAL to supply const'); + } + Action.call(this, options); +}; +util.inherits(ActionAppend, Action); + +/*:nodoc:* + * ActionAppend#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionAppend.prototype.call = function (parser, namespace, values) { + var items = (namespace[this.dest] || []).slice(); + items.push(values); + namespace.set(this.dest, items); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/append/constant.js b/hm_sunwell/node_modules/argparse/lib/action/append/constant.js new file mode 100644 index 0000000..313f5d2 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/append/constant.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionAppendConstant + * + * This stores a list, and appends the value specified by + * the const keyword argument to the list. + * (Note that the const keyword argument defaults to null.) + * The 'appendConst' action is typically useful when multiple + * arguments need to store constants to the same list. + * + * This class inherited from [[Action]] + **/ + +'use strict'; + +var util = require('util'); + +var Action = require('../../action'); + +/*:nodoc:* + * new ActionAppendConstant(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionAppendConstant = module.exports = function ActionAppendConstant(options) { + options = options || {}; + options.nargs = 0; + if (typeof options.constant === 'undefined') { + throw new Error('constant option is required for appendAction'); + } + Action.call(this, options); +}; +util.inherits(ActionAppendConstant, Action); + +/*:nodoc:* + * ActionAppendConstant#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionAppendConstant.prototype.call = function (parser, namespace) { + var items = [].concat(namespace[this.dest] || []); + items.push(this.constant); + namespace.set(this.dest, items); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/count.js b/hm_sunwell/node_modules/argparse/lib/action/count.js new file mode 100644 index 0000000..d6a5899 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/count.js @@ -0,0 +1,40 @@ +/*:nodoc:* + * class ActionCount + * + * This counts the number of times a keyword argument occurs. + * For example, this is useful for increasing verbosity levels + * + * This class inherided from [[Action]] + * + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +/*:nodoc:* + * new ActionCount(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionCount = module.exports = function ActionCount(options) { + options = options || {}; + options.nargs = 0; + + Action.call(this, options); +}; +util.inherits(ActionCount, Action); + +/*:nodoc:* + * ActionCount#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionCount.prototype.call = function (parser, namespace) { + namespace.set(this.dest, (namespace[this.dest] || 0) + 1); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/help.js b/hm_sunwell/node_modules/argparse/lib/action/help.js new file mode 100644 index 0000000..b40e05a --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/help.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionHelp + * + * Support action for printing help + * This class inherided from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var c = require('../const'); + +/*:nodoc:* + * new ActionHelp(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionHelp = module.exports = function ActionHelp(options) { + options = options || {}; + if (options.defaultValue !== null) { + options.defaultValue = options.defaultValue; + } else { + options.defaultValue = c.SUPPRESS; + } + options.dest = (options.dest !== null ? options.dest : c.SUPPRESS); + options.nargs = 0; + Action.call(this, options); + +}; +util.inherits(ActionHelp, Action); + +/*:nodoc:* + * ActionHelp#call(parser, namespace, values, optionString) + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Print help and exit + **/ +ActionHelp.prototype.call = function (parser) { + parser.printHelp(); + parser.exit(); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/store.js b/hm_sunwell/node_modules/argparse/lib/action/store.js new file mode 100644 index 0000000..283b860 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/store.js @@ -0,0 +1,50 @@ +/*:nodoc:* + * class ActionStore + * + * This action just stores the argument’s value. This is the default action. + * + * This class inherited from [[Action]] + * + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var c = require('../const'); + + +/*:nodoc:* + * new ActionStore(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStore = module.exports = function ActionStore(options) { + options = options || {}; + if (this.nargs <= 0) { + throw new Error('nargs for store actions must be > 0; if you ' + + 'have nothing to store, actions such as store ' + + 'true or store const may be more appropriate'); + + } + if (typeof this.constant !== 'undefined' && this.nargs !== c.OPTIONAL) { + throw new Error('nargs must be OPTIONAL to supply const'); + } + Action.call(this, options); +}; +util.inherits(ActionStore, Action); + +/*:nodoc:* + * ActionStore#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionStore.prototype.call = function (parser, namespace, values) { + namespace.set(this.dest, values); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/store/constant.js b/hm_sunwell/node_modules/argparse/lib/action/store/constant.js new file mode 100644 index 0000000..23caa89 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/store/constant.js @@ -0,0 +1,43 @@ +/*:nodoc:* + * class ActionStoreConstant + * + * This action stores the value specified by the const keyword argument. + * (Note that the const keyword argument defaults to the rather unhelpful null.) + * The 'store_const' action is most commonly used with optional + * arguments that specify some sort of flag. + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../../action'); + +/*:nodoc:* + * new ActionStoreConstant(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStoreConstant = module.exports = function ActionStoreConstant(options) { + options = options || {}; + options.nargs = 0; + if (typeof options.constant === 'undefined') { + throw new Error('constant option is required for storeAction'); + } + Action.call(this, options); +}; +util.inherits(ActionStoreConstant, Action); + +/*:nodoc:* + * ActionStoreConstant#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionStoreConstant.prototype.call = function (parser, namespace) { + namespace.set(this.dest, this.constant); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action/store/false.js b/hm_sunwell/node_modules/argparse/lib/action/store/false.js new file mode 100644 index 0000000..9924f46 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/store/false.js @@ -0,0 +1,27 @@ +/*:nodoc:* + * class ActionStoreFalse + * + * This action store the values False respectively. + * This is special cases of 'storeConst' + * + * This class inherited from [[Action]] + **/ + +'use strict'; + +var util = require('util'); + +var ActionStoreConstant = require('./constant'); + +/*:nodoc:* + * new ActionStoreFalse(options) + * - options (object): hash of options see [[Action.new]] + * + **/ +var ActionStoreFalse = module.exports = function ActionStoreFalse(options) { + options = options || {}; + options.constant = false; + options.defaultValue = options.defaultValue !== null ? options.defaultValue : true; + ActionStoreConstant.call(this, options); +}; +util.inherits(ActionStoreFalse, ActionStoreConstant); diff --git a/hm_sunwell/node_modules/argparse/lib/action/store/true.js b/hm_sunwell/node_modules/argparse/lib/action/store/true.js new file mode 100644 index 0000000..9e22f7d --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/store/true.js @@ -0,0 +1,26 @@ +/*:nodoc:* + * class ActionStoreTrue + * + * This action store the values True respectively. + * This isspecial cases of 'storeConst' + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var ActionStoreConstant = require('./constant'); + +/*:nodoc:* + * new ActionStoreTrue(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStoreTrue = module.exports = function ActionStoreTrue(options) { + options = options || {}; + options.constant = true; + options.defaultValue = options.defaultValue !== null ? options.defaultValue : false; + ActionStoreConstant.call(this, options); +}; +util.inherits(ActionStoreTrue, ActionStoreConstant); diff --git a/hm_sunwell/node_modules/argparse/lib/action/subparsers.js b/hm_sunwell/node_modules/argparse/lib/action/subparsers.js new file mode 100644 index 0000000..99dfedd --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/subparsers.js @@ -0,0 +1,149 @@ +/** internal + * class ActionSubparsers + * + * Support the creation of such sub-commands with the addSubparsers() + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); +var format = require('util').format; + + +var Action = require('../action'); + +// Constants +var c = require('../const'); + +// Errors +var argumentErrorHelper = require('../argument/error'); + + +/*:nodoc:* + * new ChoicesPseudoAction(name, help) + * + * Create pseudo action for correct help text + * + **/ +function ChoicesPseudoAction(name, help) { + var options = { + optionStrings: [], + dest: name, + help: help + }; + + Action.call(this, options); +} + +util.inherits(ChoicesPseudoAction, Action); + +/** + * new ActionSubparsers(options) + * - options (object): options hash see [[Action.new]] + * + **/ +function ActionSubparsers(options) { + options = options || {}; + options.dest = options.dest || c.SUPPRESS; + options.nargs = c.PARSER; + + this.debug = (options.debug === true); + + this._progPrefix = options.prog; + this._parserClass = options.parserClass; + this._nameParserMap = {}; + this._choicesActions = []; + + options.choices = this._nameParserMap; + Action.call(this, options); +} + +util.inherits(ActionSubparsers, Action); + +/*:nodoc:* + * ActionSubparsers#addParser(name, options) -> ArgumentParser + * - name (string): sub-command name + * - options (object): see [[ArgumentParser.new]] + * + * Note: + * addParser supports an additional aliases option, + * which allows multiple strings to refer to the same subparser. + * This example, like svn, aliases co as a shorthand for checkout + * + **/ +ActionSubparsers.prototype.addParser = function (name, options) { + var parser; + + var self = this; + + options = options || {}; + + options.debug = (this.debug === true); + + // set program from the existing prefix + if (!options.prog) { + options.prog = this._progPrefix + ' ' + name; + } + + var aliases = options.aliases || []; + + // create a pseudo-action to hold the choice help + if (!!options.help || typeof options.help === 'string') { + var help = options.help; + delete options.help; + + var choiceAction = new ChoicesPseudoAction(name, help); + this._choicesActions.push(choiceAction); + } + + // create the parser and add it to the map + parser = new this._parserClass(options); + this._nameParserMap[name] = parser; + + // make parser available under aliases also + aliases.forEach(function (alias) { + self._nameParserMap[alias] = parser; + }); + + return parser; +}; + +ActionSubparsers.prototype._getSubactions = function () { + return this._choicesActions; +}; + +/*:nodoc:* + * ActionSubparsers#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Parse input aguments + **/ +ActionSubparsers.prototype.call = function (parser, namespace, values) { + var parserName = values[0]; + var argStrings = values.slice(1); + + // set the parser name if requested + if (this.dest !== c.SUPPRESS) { + namespace[this.dest] = parserName; + } + + // select the parser + if (this._nameParserMap[parserName]) { + parser = this._nameParserMap[parserName]; + } else { + throw argumentErrorHelper(format( + 'Unknown parser "%s" (choices: [%s]).', + parserName, + Object.keys(this._nameParserMap).join(', ') + )); + } + + // parse all the remaining options into the namespace + parser.parseArgs(argStrings, namespace); +}; + +module.exports = ActionSubparsers; diff --git a/hm_sunwell/node_modules/argparse/lib/action/version.js b/hm_sunwell/node_modules/argparse/lib/action/version.js new file mode 100644 index 0000000..8053328 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action/version.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionVersion + * + * Support action for printing program version + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// +// Constants +// +var c = require('../const'); + +/*:nodoc:* + * new ActionVersion(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionVersion = module.exports = function ActionVersion(options) { + options = options || {}; + options.defaultValue = (options.defaultValue ? options.defaultValue : c.SUPPRESS); + options.dest = (options.dest || c.SUPPRESS); + options.nargs = 0; + this.version = options.version; + Action.call(this, options); +}; +util.inherits(ActionVersion, Action); + +/*:nodoc:* + * ActionVersion#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Print version and exit + **/ +ActionVersion.prototype.call = function (parser) { + var version = this.version || parser.version; + var formatter = parser._getFormatter(); + formatter.addText(version); + parser.exit(0, formatter.formatHelp()); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/action_container.js b/hm_sunwell/node_modules/argparse/lib/action_container.js new file mode 100644 index 0000000..6f1237b --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/action_container.js @@ -0,0 +1,482 @@ +/** internal + * class ActionContainer + * + * Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] + **/ + +'use strict'; + +var format = require('util').format; + +// Constants +var c = require('./const'); + +var $$ = require('./utils'); + +//Actions +var ActionHelp = require('./action/help'); +var ActionAppend = require('./action/append'); +var ActionAppendConstant = require('./action/append/constant'); +var ActionCount = require('./action/count'); +var ActionStore = require('./action/store'); +var ActionStoreConstant = require('./action/store/constant'); +var ActionStoreTrue = require('./action/store/true'); +var ActionStoreFalse = require('./action/store/false'); +var ActionVersion = require('./action/version'); +var ActionSubparsers = require('./action/subparsers'); + +// Errors +var argumentErrorHelper = require('./argument/error'); + +/** + * new ActionContainer(options) + * + * Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] + * + * ##### Options: + * + * - `description` -- A description of what the program does + * - `prefixChars` -- Characters that prefix optional arguments + * - `argumentDefault` -- The default value for all arguments + * - `conflictHandler` -- The conflict handler to use for duplicate arguments + **/ +var ActionContainer = module.exports = function ActionContainer(options) { + options = options || {}; + + this.description = options.description; + this.argumentDefault = options.argumentDefault; + this.prefixChars = options.prefixChars || ''; + this.conflictHandler = options.conflictHandler; + + // set up registries + this._registries = {}; + + // register actions + this.register('action', null, ActionStore); + this.register('action', 'store', ActionStore); + this.register('action', 'storeConst', ActionStoreConstant); + this.register('action', 'storeTrue', ActionStoreTrue); + this.register('action', 'storeFalse', ActionStoreFalse); + this.register('action', 'append', ActionAppend); + this.register('action', 'appendConst', ActionAppendConstant); + this.register('action', 'count', ActionCount); + this.register('action', 'help', ActionHelp); + this.register('action', 'version', ActionVersion); + this.register('action', 'parsers', ActionSubparsers); + + // raise an exception if the conflict handler is invalid + this._getHandler(); + + // action storage + this._actions = []; + this._optionStringActions = {}; + + // groups + this._actionGroups = []; + this._mutuallyExclusiveGroups = []; + + // defaults storage + this._defaults = {}; + + // determines whether an "option" looks like a negative number + // -1, -1.5 -5e+4 + this._regexpNegativeNumber = new RegExp('^[-]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$'); + + // whether or not there are any optionals that look like negative + // numbers -- uses a list so it can be shared and edited + this._hasNegativeNumberOptionals = []; +}; + +// Groups must be required, then ActionContainer already defined +var ArgumentGroup = require('./argument/group'); +var MutuallyExclusiveGroup = require('./argument/exclusive'); + +// +// Registration methods +// + +/** + * ActionContainer#register(registryName, value, object) -> Void + * - registryName (String) : object type action|type + * - value (string) : keyword + * - object (Object|Function) : handler + * + * Register handlers + **/ +ActionContainer.prototype.register = function (registryName, value, object) { + this._registries[registryName] = this._registries[registryName] || {}; + this._registries[registryName][value] = object; +}; + +ActionContainer.prototype._registryGet = function (registryName, value, defaultValue) { + if (arguments.length < 3) { + defaultValue = null; + } + return this._registries[registryName][value] || defaultValue; +}; + +// +// Namespace default accessor methods +// + +/** + * ActionContainer#setDefaults(options) -> Void + * - options (object):hash of options see [[Action.new]] + * + * Set defaults + **/ +ActionContainer.prototype.setDefaults = function (options) { + options = options || {}; + for (var property in options) { + if ($$.has(options, property)) { + this._defaults[property] = options[property]; + } + } + + // if these defaults match any existing arguments, replace the previous + // default on the object with the new one + this._actions.forEach(function (action) { + if ($$.has(options, action.dest)) { + action.defaultValue = options[action.dest]; + } + }); +}; + +/** + * ActionContainer#getDefault(dest) -> Mixed + * - dest (string): action destination + * + * Return action default value + **/ +ActionContainer.prototype.getDefault = function (dest) { + var result = $$.has(this._defaults, dest) ? this._defaults[dest] : null; + + this._actions.forEach(function (action) { + if (action.dest === dest && $$.has(action, 'defaultValue')) { + result = action.defaultValue; + } + }); + + return result; +}; +// +// Adding argument actions +// + +/** + * ActionContainer#addArgument(args, options) -> Object + * - args (String|Array): argument key, or array of argument keys + * - options (Object): action objects see [[Action.new]] + * + * #### Examples + * - addArgument([ '-f', '--foo' ], { action: 'store', defaultValue: 1, ... }) + * - addArgument([ 'bar' ], { action: 'store', nargs: 1, ... }) + * - addArgument('--baz', { action: 'store', nargs: 1, ... }) + **/ +ActionContainer.prototype.addArgument = function (args, options) { + args = args; + options = options || {}; + + if (typeof args === 'string') { + args = [ args ]; + } + if (!Array.isArray(args)) { + throw new TypeError('addArgument first argument should be a string or an array'); + } + if (typeof options !== 'object' || Array.isArray(options)) { + throw new TypeError('addArgument second argument should be a hash'); + } + + // if no positional args are supplied or only one is supplied and + // it doesn't look like an option string, parse a positional argument + if (!args || args.length === 1 && this.prefixChars.indexOf(args[0][0]) < 0) { + if (args && !!options.dest) { + throw new Error('dest supplied twice for positional argument'); + } + options = this._getPositional(args, options); + + // otherwise, we're adding an optional argument + } else { + options = this._getOptional(args, options); + } + + // if no default was supplied, use the parser-level default + if (typeof options.defaultValue === 'undefined') { + var dest = options.dest; + if ($$.has(this._defaults, dest)) { + options.defaultValue = this._defaults[dest]; + } else if (typeof this.argumentDefault !== 'undefined') { + options.defaultValue = this.argumentDefault; + } + } + + // create the action object, and add it to the parser + var ActionClass = this._popActionClass(options); + if (typeof ActionClass !== 'function') { + throw new Error(format('Unknown action "%s".', ActionClass)); + } + var action = new ActionClass(options); + + // throw an error if the action type is not callable + var typeFunction = this._registryGet('type', action.type, action.type); + if (typeof typeFunction !== 'function') { + throw new Error(format('"%s" is not callable', typeFunction)); + } + + return this._addAction(action); +}; + +/** + * ActionContainer#addArgumentGroup(options) -> ArgumentGroup + * - options (Object): hash of options see [[ArgumentGroup.new]] + * + * Create new arguments groups + **/ +ActionContainer.prototype.addArgumentGroup = function (options) { + var group = new ArgumentGroup(this, options); + this._actionGroups.push(group); + return group; +}; + +/** + * ActionContainer#addMutuallyExclusiveGroup(options) -> ArgumentGroup + * - options (Object): {required: false} + * + * Create new mutual exclusive groups + **/ +ActionContainer.prototype.addMutuallyExclusiveGroup = function (options) { + var group = new MutuallyExclusiveGroup(this, options); + this._mutuallyExclusiveGroups.push(group); + return group; +}; + +ActionContainer.prototype._addAction = function (action) { + var self = this; + + // resolve any conflicts + this._checkConflict(action); + + // add to actions list + this._actions.push(action); + action.container = this; + + // index the action by any option strings it has + action.optionStrings.forEach(function (optionString) { + self._optionStringActions[optionString] = action; + }); + + // set the flag if any option strings look like negative numbers + action.optionStrings.forEach(function (optionString) { + if (optionString.match(self._regexpNegativeNumber)) { + if (!self._hasNegativeNumberOptionals.some(Boolean)) { + self._hasNegativeNumberOptionals.push(true); + } + } + }); + + // return the created action + return action; +}; + +ActionContainer.prototype._removeAction = function (action) { + var actionIndex = this._actions.indexOf(action); + if (actionIndex >= 0) { + this._actions.splice(actionIndex, 1); + } +}; + +ActionContainer.prototype._addContainerActions = function (container) { + // collect groups by titles + var titleGroupMap = {}; + this._actionGroups.forEach(function (group) { + if (titleGroupMap[group.title]) { + throw new Error(format('Cannot merge actions - two groups are named "%s".', group.title)); + } + titleGroupMap[group.title] = group; + }); + + // map each action to its group + var groupMap = {}; + function actionHash(action) { + // unique (hopefully?) string suitable as dictionary key + return action.getName(); + } + container._actionGroups.forEach(function (group) { + // if a group with the title exists, use that, otherwise + // create a new group matching the container's group + if (!titleGroupMap[group.title]) { + titleGroupMap[group.title] = this.addArgumentGroup({ + title: group.title, + description: group.description + }); + } + + // map the actions to their new group + group._groupActions.forEach(function (action) { + groupMap[actionHash(action)] = titleGroupMap[group.title]; + }); + }, this); + + // add container's mutually exclusive groups + // NOTE: if add_mutually_exclusive_group ever gains title= and + // description= then this code will need to be expanded as above + var mutexGroup; + container._mutuallyExclusiveGroups.forEach(function (group) { + mutexGroup = this.addMutuallyExclusiveGroup({ + required: group.required + }); + // map the actions to their new mutex group + group._groupActions.forEach(function (action) { + groupMap[actionHash(action)] = mutexGroup; + }); + }, this); // forEach takes a 'this' argument + + // add all actions to this container or their group + container._actions.forEach(function (action) { + var key = actionHash(action); + if (groupMap[key]) { + groupMap[key]._addAction(action); + } else { + this._addAction(action); + } + }); +}; + +ActionContainer.prototype._getPositional = function (dest, options) { + if (Array.isArray(dest)) { + dest = dest[0]; + } + // make sure required is not specified + if (options.required) { + throw new Error('"required" is an invalid argument for positionals.'); + } + + // mark positional arguments as required if at least one is + // always required + if (options.nargs !== c.OPTIONAL && options.nargs !== c.ZERO_OR_MORE) { + options.required = true; + } + if (options.nargs === c.ZERO_OR_MORE && typeof options.defaultValue === 'undefined') { + options.required = true; + } + + // return the keyword arguments with no option strings + options.dest = dest; + options.optionStrings = []; + return options; +}; + +ActionContainer.prototype._getOptional = function (args, options) { + var prefixChars = this.prefixChars; + var optionStrings = []; + var optionStringsLong = []; + + // determine short and long option strings + args.forEach(function (optionString) { + // error on strings that don't start with an appropriate prefix + if (prefixChars.indexOf(optionString[0]) < 0) { + throw new Error(format('Invalid option string "%s": must start with a "%s".', + optionString, + prefixChars + )); + } + + // strings starting with two prefix characters are long options + optionStrings.push(optionString); + if (optionString.length > 1 && prefixChars.indexOf(optionString[1]) >= 0) { + optionStringsLong.push(optionString); + } + }); + + // infer dest, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' + var dest = options.dest || null; + delete options.dest; + + if (!dest) { + var optionStringDest = optionStringsLong.length ? optionStringsLong[0] : optionStrings[0]; + dest = $$.trimChars(optionStringDest, this.prefixChars); + + if (dest.length === 0) { + throw new Error( + format('dest= is required for options like "%s"', optionStrings.join(', ')) + ); + } + dest = dest.replace(/-/g, '_'); + } + + // return the updated keyword arguments + options.dest = dest; + options.optionStrings = optionStrings; + + return options; +}; + +ActionContainer.prototype._popActionClass = function (options, defaultValue) { + defaultValue = defaultValue || null; + + var action = (options.action || defaultValue); + delete options.action; + + var actionClass = this._registryGet('action', action, action); + return actionClass; +}; + +ActionContainer.prototype._getHandler = function () { + var handlerString = this.conflictHandler; + var handlerFuncName = '_handleConflict' + $$.capitalize(handlerString); + var func = this[handlerFuncName]; + if (typeof func === 'undefined') { + var msg = 'invalid conflict resolution value: ' + handlerString; + throw new Error(msg); + } else { + return func; + } +}; + +ActionContainer.prototype._checkConflict = function (action) { + var optionStringActions = this._optionStringActions; + var conflictOptionals = []; + + // find all options that conflict with this option + // collect pairs, the string, and an existing action that it conflicts with + action.optionStrings.forEach(function (optionString) { + var conflOptional = optionStringActions[optionString]; + if (typeof conflOptional !== 'undefined') { + conflictOptionals.push([ optionString, conflOptional ]); + } + }); + + if (conflictOptionals.length > 0) { + var conflictHandler = this._getHandler(); + conflictHandler.call(this, action, conflictOptionals); + } +}; + +ActionContainer.prototype._handleConflictError = function (action, conflOptionals) { + var conflicts = conflOptionals.map(function (pair) { return pair[0]; }); + conflicts = conflicts.join(', '); + throw argumentErrorHelper( + action, + format('Conflicting option string(s): %s', conflicts) + ); +}; + +ActionContainer.prototype._handleConflictResolve = function (action, conflOptionals) { + // remove all conflicting options + var self = this; + conflOptionals.forEach(function (pair) { + var optionString = pair[0]; + var conflictingAction = pair[1]; + // remove the conflicting option string + var i = conflictingAction.optionStrings.indexOf(optionString); + if (i >= 0) { + conflictingAction.optionStrings.splice(i, 1); + } + delete self._optionStringActions[optionString]; + // if the option now has no option string, remove it from the + // container holding it + if (conflictingAction.optionStrings.length === 0) { + conflictingAction.container._removeAction(conflictingAction); + } + }); +}; diff --git a/hm_sunwell/node_modules/argparse/lib/argparse.js b/hm_sunwell/node_modules/argparse/lib/argparse.js new file mode 100644 index 0000000..f2a2c51 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/argparse.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports.ArgumentParser = require('./argument_parser.js'); +module.exports.Namespace = require('./namespace'); +module.exports.Action = require('./action'); +module.exports.HelpFormatter = require('./help/formatter.js'); +module.exports.Const = require('./const.js'); + +module.exports.ArgumentDefaultsHelpFormatter = + require('./help/added_formatters.js').ArgumentDefaultsHelpFormatter; +module.exports.RawDescriptionHelpFormatter = + require('./help/added_formatters.js').RawDescriptionHelpFormatter; +module.exports.RawTextHelpFormatter = + require('./help/added_formatters.js').RawTextHelpFormatter; diff --git a/hm_sunwell/node_modules/argparse/lib/argument/error.js b/hm_sunwell/node_modules/argparse/lib/argument/error.js new file mode 100644 index 0000000..c8a02a0 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/argument/error.js @@ -0,0 +1,50 @@ +'use strict'; + + +var format = require('util').format; + + +var ERR_CODE = 'ARGError'; + +/*:nodoc:* + * argumentError(argument, message) -> TypeError + * - argument (Object): action with broken argument + * - message (String): error message + * + * Error format helper. An error from creating or using an argument + * (optional or positional). The string value of this exception + * is the message, augmented with information + * about the argument that caused it. + * + * #####Example + * + * var argumentErrorHelper = require('./argument/error'); + * if (conflictOptionals.length > 0) { + * throw argumentErrorHelper( + * action, + * format('Conflicting option string(s): %s', conflictOptionals.join(', ')) + * ); + * } + * + **/ +module.exports = function (argument, message) { + var argumentName = null; + var errMessage; + var err; + + if (argument.getName) { + argumentName = argument.getName(); + } else { + argumentName = '' + argument; + } + + if (!argumentName) { + errMessage = message; + } else { + errMessage = format('argument "%s": %s', argumentName, message); + } + + err = new TypeError(errMessage); + err.code = ERR_CODE; + return err; +}; diff --git a/hm_sunwell/node_modules/argparse/lib/argument/exclusive.js b/hm_sunwell/node_modules/argparse/lib/argument/exclusive.js new file mode 100644 index 0000000..8287e00 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/argument/exclusive.js @@ -0,0 +1,54 @@ +/** internal + * class MutuallyExclusiveGroup + * + * Group arguments. + * By default, ArgumentParser groups command-line arguments + * into “positional arguments” and “optional arguments” + * when displaying help messages. When there is a better + * conceptual grouping of arguments than this default one, + * appropriate groups can be created using the addArgumentGroup() method + * + * This class inherited from [[ArgumentContainer]] + **/ +'use strict'; + +var util = require('util'); + +var ArgumentGroup = require('./group'); + +/** + * new MutuallyExclusiveGroup(container, options) + * - container (object): main container + * - options (object): options.required -> true/false + * + * `required` could be an argument itself, but making it a property of + * the options argument is more consistent with the JS adaptation of the Python) + **/ +var MutuallyExclusiveGroup = module.exports = function MutuallyExclusiveGroup(container, options) { + var required; + options = options || {}; + required = options.required || false; + ArgumentGroup.call(this, container); + this.required = required; + +}; +util.inherits(MutuallyExclusiveGroup, ArgumentGroup); + + +MutuallyExclusiveGroup.prototype._addAction = function (action) { + var msg; + if (action.required) { + msg = 'mutually exclusive arguments must be optional'; + throw new Error(msg); + } + action = this._container._addAction(action); + this._groupActions.push(action); + return action; +}; + + +MutuallyExclusiveGroup.prototype._removeAction = function (action) { + this._container._removeAction(action); + this._groupActions.remove(action); +}; + diff --git a/hm_sunwell/node_modules/argparse/lib/argument/group.js b/hm_sunwell/node_modules/argparse/lib/argument/group.js new file mode 100644 index 0000000..58b271f --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/argument/group.js @@ -0,0 +1,75 @@ +/** internal + * class ArgumentGroup + * + * Group arguments. + * By default, ArgumentParser groups command-line arguments + * into “positional arguments” and “optional arguments” + * when displaying help messages. When there is a better + * conceptual grouping of arguments than this default one, + * appropriate groups can be created using the addArgumentGroup() method + * + * This class inherited from [[ArgumentContainer]] + **/ +'use strict'; + +var util = require('util'); + +var ActionContainer = require('../action_container'); + + +/** + * new ArgumentGroup(container, options) + * - container (object): main container + * - options (object): hash of group options + * + * #### options + * - **prefixChars** group name prefix + * - **argumentDefault** default argument value + * - **title** group title + * - **description** group description + * + **/ +var ArgumentGroup = module.exports = function ArgumentGroup(container, options) { + + options = options || {}; + + // add any missing keyword arguments by checking the container + options.conflictHandler = (options.conflictHandler || container.conflictHandler); + options.prefixChars = (options.prefixChars || container.prefixChars); + options.argumentDefault = (options.argumentDefault || container.argumentDefault); + + ActionContainer.call(this, options); + + // group attributes + this.title = options.title; + this._groupActions = []; + + // share most attributes with the container + this._container = container; + this._registries = container._registries; + this._actions = container._actions; + this._optionStringActions = container._optionStringActions; + this._defaults = container._defaults; + this._hasNegativeNumberOptionals = container._hasNegativeNumberOptionals; + this._mutuallyExclusiveGroups = container._mutuallyExclusiveGroups; +}; +util.inherits(ArgumentGroup, ActionContainer); + + +ArgumentGroup.prototype._addAction = function (action) { + // Parent add action + action = ActionContainer.prototype._addAction.call(this, action); + this._groupActions.push(action); + return action; +}; + + +ArgumentGroup.prototype._removeAction = function (action) { + // Parent remove action + ActionContainer.prototype._removeAction.call(this, action); + var actionIndex = this._groupActions.indexOf(action); + if (actionIndex >= 0) { + this._groupActions.splice(actionIndex, 1); + } +}; + diff --git a/hm_sunwell/node_modules/argparse/lib/argument_parser.js b/hm_sunwell/node_modules/argparse/lib/argument_parser.js new file mode 100644 index 0000000..bd9a59a --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/argument_parser.js @@ -0,0 +1,1161 @@ +/** + * class ArgumentParser + * + * Object for parsing command line strings into js objects. + * + * Inherited from [[ActionContainer]] + **/ +'use strict'; + +var util = require('util'); +var format = require('util').format; +var Path = require('path'); +var sprintf = require('sprintf-js').sprintf; + +// Constants +var c = require('./const'); + +var $$ = require('./utils'); + +var ActionContainer = require('./action_container'); + +// Errors +var argumentErrorHelper = require('./argument/error'); + +var HelpFormatter = require('./help/formatter'); + +var Namespace = require('./namespace'); + + +/** + * new ArgumentParser(options) + * + * Create a new ArgumentParser object. + * + * ##### Options: + * - `prog` The name of the program (default: Path.basename(process.argv[1])) + * - `usage` A usage message (default: auto-generated from arguments) + * - `description` A description of what the program does + * - `epilog` Text following the argument descriptions + * - `parents` Parsers whose arguments should be copied into this one + * - `formatterClass` HelpFormatter class for printing help messages + * - `prefixChars` Characters that prefix optional arguments + * - `fromfilePrefixChars` Characters that prefix files containing additional arguments + * - `argumentDefault` The default value for all arguments + * - `addHelp` Add a -h/-help option + * - `conflictHandler` Specifies how to handle conflicting argument names + * - `debug` Enable debug mode. Argument errors throw exception in + * debug mode and process.exit in normal. Used for development and + * testing (default: false) + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#argumentparser-objects + **/ +function ArgumentParser(options) { + if (!(this instanceof ArgumentParser)) { + return new ArgumentParser(options); + } + var self = this; + options = options || {}; + + options.description = (options.description || null); + options.argumentDefault = (options.argumentDefault || null); + options.prefixChars = (options.prefixChars || '-'); + options.conflictHandler = (options.conflictHandler || 'error'); + ActionContainer.call(this, options); + + options.addHelp = typeof options.addHelp === 'undefined' || !!options.addHelp; + options.parents = options.parents || []; + // default program name + options.prog = (options.prog || Path.basename(process.argv[1])); + this.prog = options.prog; + this.usage = options.usage; + this.epilog = options.epilog; + this.version = options.version; + + this.debug = (options.debug === true); + + this.formatterClass = (options.formatterClass || HelpFormatter); + this.fromfilePrefixChars = options.fromfilePrefixChars || null; + this._positionals = this.addArgumentGroup({ title: 'Positional arguments' }); + this._optionals = this.addArgumentGroup({ title: 'Optional arguments' }); + this._subparsers = null; + + // register types + function FUNCTION_IDENTITY(o) { + return o; + } + this.register('type', 'auto', FUNCTION_IDENTITY); + this.register('type', null, FUNCTION_IDENTITY); + this.register('type', 'int', function (x) { + var result = parseInt(x, 10); + if (isNaN(result)) { + throw new Error(x + ' is not a valid integer.'); + } + return result; + }); + this.register('type', 'float', function (x) { + var result = parseFloat(x); + if (isNaN(result)) { + throw new Error(x + ' is not a valid float.'); + } + return result; + }); + this.register('type', 'string', function (x) { + return '' + x; + }); + + // add help and version arguments if necessary + var defaultPrefix = (this.prefixChars.indexOf('-') > -1) ? '-' : this.prefixChars[0]; + if (options.addHelp) { + this.addArgument( + [ defaultPrefix + 'h', defaultPrefix + defaultPrefix + 'help' ], + { + action: 'help', + defaultValue: c.SUPPRESS, + help: 'Show this help message and exit.' + } + ); + } + if (typeof this.version !== 'undefined') { + this.addArgument( + [ defaultPrefix + 'v', defaultPrefix + defaultPrefix + 'version' ], + { + action: 'version', + version: this.version, + defaultValue: c.SUPPRESS, + help: "Show program's version number and exit." + } + ); + } + + // add parent arguments and defaults + options.parents.forEach(function (parent) { + self._addContainerActions(parent); + if (typeof parent._defaults !== 'undefined') { + for (var defaultKey in parent._defaults) { + if (parent._defaults.hasOwnProperty(defaultKey)) { + self._defaults[defaultKey] = parent._defaults[defaultKey]; + } + } + } + }); +} + +util.inherits(ArgumentParser, ActionContainer); + +/** + * ArgumentParser#addSubparsers(options) -> [[ActionSubparsers]] + * - options (object): hash of options see [[ActionSubparsers.new]] + * + * See also [subcommands][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#sub-commands + **/ +ArgumentParser.prototype.addSubparsers = function (options) { + if (this._subparsers) { + this.error('Cannot have multiple subparser arguments.'); + } + + options = options || {}; + options.debug = (this.debug === true); + options.optionStrings = []; + options.parserClass = (options.parserClass || ArgumentParser); + + + if (!!options.title || !!options.description) { + + this._subparsers = this.addArgumentGroup({ + title: (options.title || 'subcommands'), + description: options.description + }); + delete options.title; + delete options.description; + + } else { + this._subparsers = this._positionals; + } + + // prog defaults to the usage message of this parser, skipping + // optional arguments and with no "usage:" prefix + if (!options.prog) { + var formatter = this._getFormatter(); + var positionals = this._getPositionalActions(); + var groups = this._mutuallyExclusiveGroups; + formatter.addUsage(this.usage, positionals, groups, ''); + options.prog = formatter.formatHelp().trim(); + } + + // create the parsers action and add it to the positionals list + var ParsersClass = this._popActionClass(options, 'parsers'); + var action = new ParsersClass(options); + this._subparsers._addAction(action); + + // return the created parsers action + return action; +}; + +ArgumentParser.prototype._addAction = function (action) { + if (action.isOptional()) { + this._optionals._addAction(action); + } else { + this._positionals._addAction(action); + } + return action; +}; + +ArgumentParser.prototype._getOptionalActions = function () { + return this._actions.filter(function (action) { + return action.isOptional(); + }); +}; + +ArgumentParser.prototype._getPositionalActions = function () { + return this._actions.filter(function (action) { + return action.isPositional(); + }); +}; + + +/** + * ArgumentParser#parseArgs(args, namespace) -> Namespace|Object + * - args (array): input elements + * - namespace (Namespace|Object): result object + * + * Parsed args and throws error if some arguments are not recognized + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#the-parse-args-method + **/ +ArgumentParser.prototype.parseArgs = function (args, namespace) { + var argv; + var result = this.parseKnownArgs(args, namespace); + + args = result[0]; + argv = result[1]; + if (argv && argv.length > 0) { + this.error( + format('Unrecognized arguments: %s.', argv.join(' ')) + ); + } + return args; +}; + +/** + * ArgumentParser#parseKnownArgs(args, namespace) -> array + * - args (array): input options + * - namespace (Namespace|Object): result object + * + * Parse known arguments and return tuple of result object + * and unknown args + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#partial-parsing + **/ +ArgumentParser.prototype.parseKnownArgs = function (args, namespace) { + var self = this; + + // args default to the system args + args = args || process.argv.slice(2); + + // default Namespace built from parser defaults + namespace = namespace || new Namespace(); + + self._actions.forEach(function (action) { + if (action.dest !== c.SUPPRESS) { + if (!$$.has(namespace, action.dest)) { + if (action.defaultValue !== c.SUPPRESS) { + var defaultValue = action.defaultValue; + if (typeof action.defaultValue === 'string') { + defaultValue = self._getValue(action, defaultValue); + } + namespace[action.dest] = defaultValue; + } + } + } + }); + + Object.keys(self._defaults).forEach(function (dest) { + namespace[dest] = self._defaults[dest]; + }); + + // parse the arguments and exit if there are any errors + try { + var res = this._parseKnownArgs(args, namespace); + + namespace = res[0]; + args = res[1]; + if ($$.has(namespace, c._UNRECOGNIZED_ARGS_ATTR)) { + args = $$.arrayUnion(args, namespace[c._UNRECOGNIZED_ARGS_ATTR]); + delete namespace[c._UNRECOGNIZED_ARGS_ATTR]; + } + return [ namespace, args ]; + } catch (e) { + this.error(e); + } +}; + +ArgumentParser.prototype._parseKnownArgs = function (argStrings, namespace) { + var self = this; + + var extras = []; + + // replace arg strings that are file references + if (this.fromfilePrefixChars !== null) { + argStrings = this._readArgsFromFiles(argStrings); + } + // map all mutually exclusive arguments to the other arguments + // they can't occur with + // Python has 'conflicts = action_conflicts.setdefault(mutex_action, [])' + // though I can't conceive of a way in which an action could be a member + // of two different mutually exclusive groups. + + function actionHash(action) { + // some sort of hashable key for this action + // action itself cannot be a key in actionConflicts + // I think getName() (join of optionStrings) is unique enough + return action.getName(); + } + + var conflicts, key; + var actionConflicts = {}; + + this._mutuallyExclusiveGroups.forEach(function (mutexGroup) { + mutexGroup._groupActions.forEach(function (mutexAction, i, groupActions) { + key = actionHash(mutexAction); + if (!$$.has(actionConflicts, key)) { + actionConflicts[key] = []; + } + conflicts = actionConflicts[key]; + conflicts.push.apply(conflicts, groupActions.slice(0, i)); + conflicts.push.apply(conflicts, groupActions.slice(i + 1)); + }); + }); + + // find all option indices, and determine the arg_string_pattern + // which has an 'O' if there is an option at an index, + // an 'A' if there is an argument, or a '-' if there is a '--' + var optionStringIndices = {}; + + var argStringPatternParts = []; + + argStrings.forEach(function (argString, argStringIndex) { + if (argString === '--') { + argStringPatternParts.push('-'); + while (argStringIndex < argStrings.length) { + argStringPatternParts.push('A'); + argStringIndex++; + } + } else { + // otherwise, add the arg to the arg strings + // and note the index if it was an option + var pattern; + var optionTuple = self._parseOptional(argString); + if (!optionTuple) { + pattern = 'A'; + } else { + optionStringIndices[argStringIndex] = optionTuple; + pattern = 'O'; + } + argStringPatternParts.push(pattern); + } + }); + var argStringsPattern = argStringPatternParts.join(''); + + var seenActions = []; + var seenNonDefaultActions = []; + + + function takeAction(action, argumentStrings, optionString) { + seenActions.push(action); + var argumentValues = self._getValues(action, argumentStrings); + + // error if this argument is not allowed with other previously + // seen arguments, assuming that actions that use the default + // value don't really count as "present" + if (argumentValues !== action.defaultValue) { + seenNonDefaultActions.push(action); + if (actionConflicts[actionHash(action)]) { + actionConflicts[actionHash(action)].forEach(function (actionConflict) { + if (seenNonDefaultActions.indexOf(actionConflict) >= 0) { + throw argumentErrorHelper( + action, + format('Not allowed with argument "%s".', actionConflict.getName()) + ); + } + }); + } + } + + if (argumentValues !== c.SUPPRESS) { + action.call(self, namespace, argumentValues, optionString); + } + } + + function consumeOptional(startIndex) { + // get the optional identified at this index + var optionTuple = optionStringIndices[startIndex]; + var action = optionTuple[0]; + var optionString = optionTuple[1]; + var explicitArg = optionTuple[2]; + + // identify additional optionals in the same arg string + // (e.g. -xyz is the same as -x -y -z if no args are required) + var actionTuples = []; + + var args, argCount, start, stop; + + for (;;) { + if (!action) { + extras.push(argStrings[startIndex]); + return startIndex + 1; + } + if (explicitArg) { + argCount = self._matchArgument(action, 'A'); + + // if the action is a single-dash option and takes no + // arguments, try to parse more single-dash options out + // of the tail of the option string + var chars = self.prefixChars; + if (argCount === 0 && chars.indexOf(optionString[1]) < 0) { + actionTuples.push([ action, [], optionString ]); + optionString = optionString[0] + explicitArg[0]; + var newExplicitArg = explicitArg.slice(1) || null; + var optionalsMap = self._optionStringActions; + + if (Object.keys(optionalsMap).indexOf(optionString) >= 0) { + action = optionalsMap[optionString]; + explicitArg = newExplicitArg; + } else { + throw argumentErrorHelper(action, sprintf('ignored explicit argument %r', explicitArg)); + } + } else if (argCount === 1) { + // if the action expect exactly one argument, we've + // successfully matched the option; exit the loop + stop = startIndex + 1; + args = [ explicitArg ]; + actionTuples.push([ action, args, optionString ]); + break; + } else { + // error if a double-dash option did not use the + // explicit argument + throw argumentErrorHelper(action, sprintf('ignored explicit argument %r', explicitArg)); + } + } else { + // if there is no explicit argument, try to match the + // optional's string arguments with the following strings + // if successful, exit the loop + + start = startIndex + 1; + var selectedPatterns = argStringsPattern.substr(start); + + argCount = self._matchArgument(action, selectedPatterns); + stop = start + argCount; + + + args = argStrings.slice(start, stop); + + actionTuples.push([ action, args, optionString ]); + break; + } + + } + + // add the Optional to the list and return the index at which + // the Optional's string args stopped + if (actionTuples.length < 1) { + throw new Error('length should be > 0'); + } + for (var i = 0; i < actionTuples.length; i++) { + takeAction.apply(self, actionTuples[i]); + } + return stop; + } + + // the list of Positionals left to be parsed; this is modified + // by consume_positionals() + var positionals = self._getPositionalActions(); + + function consumePositionals(startIndex) { + // match as many Positionals as possible + var selectedPattern = argStringsPattern.substr(startIndex); + var argCounts = self._matchArgumentsPartial(positionals, selectedPattern); + + // slice off the appropriate arg strings for each Positional + // and add the Positional and its args to the list + for (var i = 0; i < positionals.length; i++) { + var action = positionals[i]; + var argCount = argCounts[i]; + if (typeof argCount === 'undefined') { + continue; + } + var args = argStrings.slice(startIndex, startIndex + argCount); + + startIndex += argCount; + takeAction(action, args); + } + + // slice off the Positionals that we just parsed and return the + // index at which the Positionals' string args stopped + positionals = positionals.slice(argCounts.length); + return startIndex; + } + + // consume Positionals and Optionals alternately, until we have + // passed the last option string + var startIndex = 0; + var position; + + var maxOptionStringIndex = -1; + + Object.keys(optionStringIndices).forEach(function (position) { + maxOptionStringIndex = Math.max(maxOptionStringIndex, parseInt(position, 10)); + }); + + var positionalsEndIndex, nextOptionStringIndex; + + while (startIndex <= maxOptionStringIndex) { + // consume any Positionals preceding the next option + nextOptionStringIndex = null; + for (position in optionStringIndices) { + if (!optionStringIndices.hasOwnProperty(position)) { continue; } + + position = parseInt(position, 10); + if (position >= startIndex) { + if (nextOptionStringIndex !== null) { + nextOptionStringIndex = Math.min(nextOptionStringIndex, position); + } else { + nextOptionStringIndex = position; + } + } + } + + if (startIndex !== nextOptionStringIndex) { + positionalsEndIndex = consumePositionals(startIndex); + // only try to parse the next optional if we didn't consume + // the option string during the positionals parsing + if (positionalsEndIndex > startIndex) { + startIndex = positionalsEndIndex; + continue; + } else { + startIndex = positionalsEndIndex; + } + } + + // if we consumed all the positionals we could and we're not + // at the index of an option string, there were extra arguments + if (!optionStringIndices[startIndex]) { + var strings = argStrings.slice(startIndex, nextOptionStringIndex); + extras = extras.concat(strings); + startIndex = nextOptionStringIndex; + } + // consume the next optional and any arguments for it + startIndex = consumeOptional(startIndex); + } + + // consume any positionals following the last Optional + var stopIndex = consumePositionals(startIndex); + + // if we didn't consume all the argument strings, there were extras + extras = extras.concat(argStrings.slice(stopIndex)); + + // if we didn't use all the Positional objects, there were too few + // arg strings supplied. + if (positionals.length > 0) { + self.error('too few arguments'); + } + + // make sure all required actions were present + self._actions.forEach(function (action) { + if (action.required) { + if (seenActions.indexOf(action) < 0) { + self.error(format('Argument "%s" is required', action.getName())); + } + } + }); + + // make sure all required groups have one option present + var actionUsed = false; + self._mutuallyExclusiveGroups.forEach(function (group) { + if (group.required) { + actionUsed = group._groupActions.some(function (action) { + return seenNonDefaultActions.indexOf(action) !== -1; + }); + + // if no actions were used, report the error + if (!actionUsed) { + var names = []; + group._groupActions.forEach(function (action) { + if (action.help !== c.SUPPRESS) { + names.push(action.getName()); + } + }); + names = names.join(' '); + var msg = 'one of the arguments ' + names + ' is required'; + self.error(msg); + } + } + }); + + // return the updated namespace and the extra arguments + return [ namespace, extras ]; +}; + +ArgumentParser.prototype._readArgsFromFiles = function (argStrings) { + // expand arguments referencing files + var self = this; + var fs = require('fs'); + var newArgStrings = []; + argStrings.forEach(function (argString) { + if (self.fromfilePrefixChars.indexOf(argString[0]) < 0) { + // for regular arguments, just add them back into the list + newArgStrings.push(argString); + } else { + // replace arguments referencing files with the file content + try { + var argstrs = []; + var filename = argString.slice(1); + var content = fs.readFileSync(filename, 'utf8'); + content = content.trim().split('\n'); + content.forEach(function (argLine) { + self.convertArgLineToArgs(argLine).forEach(function (arg) { + argstrs.push(arg); + }); + argstrs = self._readArgsFromFiles(argstrs); + }); + newArgStrings.push.apply(newArgStrings, argstrs); + } catch (error) { + return self.error(error.message); + } + } + }); + return newArgStrings; +}; + +ArgumentParser.prototype.convertArgLineToArgs = function (argLine) { + return [ argLine ]; +}; + +ArgumentParser.prototype._matchArgument = function (action, regexpArgStrings) { + + // match the pattern for this action to the arg strings + var regexpNargs = new RegExp('^' + this._getNargsPattern(action)); + var matches = regexpArgStrings.match(regexpNargs); + var message; + + // throw an exception if we weren't able to find a match + if (!matches) { + switch (action.nargs) { + /*eslint-disable no-undefined*/ + case undefined: + case null: + message = 'Expected one argument.'; + break; + case c.OPTIONAL: + message = 'Expected at most one argument.'; + break; + case c.ONE_OR_MORE: + message = 'Expected at least one argument.'; + break; + default: + message = 'Expected %s argument(s)'; + } + + throw argumentErrorHelper( + action, + format(message, action.nargs) + ); + } + // return the number of arguments matched + return matches[1].length; +}; + +ArgumentParser.prototype._matchArgumentsPartial = function (actions, regexpArgStrings) { + // progressively shorten the actions list by slicing off the + // final actions until we find a match + var self = this; + var result = []; + var actionSlice, pattern, matches; + var i, j; + + function getLength(string) { + return string.length; + } + + for (i = actions.length; i > 0; i--) { + pattern = ''; + actionSlice = actions.slice(0, i); + for (j = 0; j < actionSlice.length; j++) { + pattern += self._getNargsPattern(actionSlice[j]); + } + + pattern = new RegExp('^' + pattern); + matches = regexpArgStrings.match(pattern); + + if (matches && matches.length > 0) { + // need only groups + matches = matches.splice(1); + result = result.concat(matches.map(getLength)); + break; + } + } + + // return the list of arg string counts + return result; +}; + +ArgumentParser.prototype._parseOptional = function (argString) { + var action, optionString, argExplicit, optionTuples; + + // if it's an empty string, it was meant to be a positional + if (!argString) { + return null; + } + + // if it doesn't start with a prefix, it was meant to be positional + if (this.prefixChars.indexOf(argString[0]) < 0) { + return null; + } + + // if the option string is present in the parser, return the action + if (this._optionStringActions[argString]) { + return [ this._optionStringActions[argString], argString, null ]; + } + + // if it's just a single character, it was meant to be positional + if (argString.length === 1) { + return null; + } + + // if the option string before the "=" is present, return the action + if (argString.indexOf('=') >= 0) { + optionString = argString.split('=', 1)[0]; + argExplicit = argString.slice(optionString.length + 1); + + if (this._optionStringActions[optionString]) { + action = this._optionStringActions[optionString]; + return [ action, optionString, argExplicit ]; + } + } + + // search through all possible prefixes of the option string + // and all actions in the parser for possible interpretations + optionTuples = this._getOptionTuples(argString); + + // if multiple actions match, the option string was ambiguous + if (optionTuples.length > 1) { + var optionStrings = optionTuples.map(function (optionTuple) { + return optionTuple[1]; + }); + this.error(format( + 'Ambiguous option: "%s" could match %s.', + argString, optionStrings.join(', ') + )); + // if exactly one action matched, this segmentation is good, + // so return the parsed action + } else if (optionTuples.length === 1) { + return optionTuples[0]; + } + + // if it was not found as an option, but it looks like a negative + // number, it was meant to be positional + // unless there are negative-number-like options + if (argString.match(this._regexpNegativeNumber)) { + if (!this._hasNegativeNumberOptionals.some(Boolean)) { + return null; + } + } + // if it contains a space, it was meant to be a positional + if (argString.search(' ') >= 0) { + return null; + } + + // it was meant to be an optional but there is no such option + // in this parser (though it might be a valid option in a subparser) + return [ null, argString, null ]; +}; + +ArgumentParser.prototype._getOptionTuples = function (optionString) { + var result = []; + var chars = this.prefixChars; + var optionPrefix; + var argExplicit; + var action; + var actionOptionString; + + // option strings starting with two prefix characters are only split at + // the '=' + if (chars.indexOf(optionString[0]) >= 0 && chars.indexOf(optionString[1]) >= 0) { + if (optionString.indexOf('=') >= 0) { + var optionStringSplit = optionString.split('=', 1); + + optionPrefix = optionStringSplit[0]; + argExplicit = optionStringSplit[1]; + } else { + optionPrefix = optionString; + argExplicit = null; + } + + for (actionOptionString in this._optionStringActions) { + if (actionOptionString.substr(0, optionPrefix.length) === optionPrefix) { + action = this._optionStringActions[actionOptionString]; + result.push([ action, actionOptionString, argExplicit ]); + } + } + + // single character options can be concatenated with their arguments + // but multiple character options always have to have their argument + // separate + } else if (chars.indexOf(optionString[0]) >= 0 && chars.indexOf(optionString[1]) < 0) { + optionPrefix = optionString; + argExplicit = null; + var optionPrefixShort = optionString.substr(0, 2); + var argExplicitShort = optionString.substr(2); + + for (actionOptionString in this._optionStringActions) { + if (!$$.has(this._optionStringActions, actionOptionString)) continue; + + action = this._optionStringActions[actionOptionString]; + if (actionOptionString === optionPrefixShort) { + result.push([ action, actionOptionString, argExplicitShort ]); + } else if (actionOptionString.substr(0, optionPrefix.length) === optionPrefix) { + result.push([ action, actionOptionString, argExplicit ]); + } + } + + // shouldn't ever get here + } else { + throw new Error(format('Unexpected option string: %s.', optionString)); + } + // return the collected option tuples + return result; +}; + +ArgumentParser.prototype._getNargsPattern = function (action) { + // in all examples below, we have to allow for '--' args + // which are represented as '-' in the pattern + var regexpNargs; + + switch (action.nargs) { + // the default (null) is assumed to be a single argument + case undefined: + case null: + regexpNargs = '(-*A-*)'; + break; + // allow zero or more arguments + case c.OPTIONAL: + regexpNargs = '(-*A?-*)'; + break; + // allow zero or more arguments + case c.ZERO_OR_MORE: + regexpNargs = '(-*[A-]*)'; + break; + // allow one or more arguments + case c.ONE_OR_MORE: + regexpNargs = '(-*A[A-]*)'; + break; + // allow any number of options or arguments + case c.REMAINDER: + regexpNargs = '([-AO]*)'; + break; + // allow one argument followed by any number of options or arguments + case c.PARSER: + regexpNargs = '(-*A[-AO]*)'; + break; + // all others should be integers + default: + regexpNargs = '(-*' + $$.repeat('-*A', action.nargs) + '-*)'; + } + + // if this is an optional action, -- is not allowed + if (action.isOptional()) { + regexpNargs = regexpNargs.replace(/-\*/g, ''); + regexpNargs = regexpNargs.replace(/-/g, ''); + } + + // return the pattern + return regexpNargs; +}; + +// +// Value conversion methods +// + +ArgumentParser.prototype._getValues = function (action, argStrings) { + var self = this; + + // for everything but PARSER args, strip out '--' + if (action.nargs !== c.PARSER && action.nargs !== c.REMAINDER) { + argStrings = argStrings.filter(function (arrayElement) { + return arrayElement !== '--'; + }); + } + + var value, argString; + + // optional argument produces a default when not present + if (argStrings.length === 0 && action.nargs === c.OPTIONAL) { + + value = (action.isOptional()) ? action.constant : action.defaultValue; + + if (typeof (value) === 'string') { + value = this._getValue(action, value); + this._checkValue(action, value); + } + + // when nargs='*' on a positional, if there were no command-line + // args, use the default if it is anything other than None + } else if (argStrings.length === 0 && action.nargs === c.ZERO_OR_MORE && + action.optionStrings.length === 0) { + + value = (action.defaultValue || argStrings); + this._checkValue(action, value); + + // single argument or optional argument produces a single value + } else if (argStrings.length === 1 && + (!action.nargs || action.nargs === c.OPTIONAL)) { + + argString = argStrings[0]; + value = this._getValue(action, argString); + this._checkValue(action, value); + + // REMAINDER arguments convert all values, checking none + } else if (action.nargs === c.REMAINDER) { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + + // PARSER arguments convert all values, but check only the first + } else if (action.nargs === c.PARSER) { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + this._checkValue(action, value[0]); + + // all other types of nargs produce a list + } else { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + value.forEach(function (v) { + self._checkValue(action, v); + }); + } + + // return the converted value + return value; +}; + +ArgumentParser.prototype._getValue = function (action, argString) { + var result; + + var typeFunction = this._registryGet('type', action.type, action.type); + if (typeof typeFunction !== 'function') { + var message = format('%s is not callable', typeFunction); + throw argumentErrorHelper(action, message); + } + + // convert the value to the appropriate type + try { + result = typeFunction(argString); + + // ArgumentTypeErrors indicate errors + // If action.type is not a registered string, it is a function + // Try to deduce its name for inclusion in the error message + // Failing that, include the error message it raised. + } catch (e) { + var name = null; + if (typeof action.type === 'string') { + name = action.type; + } else { + name = action.type.name || action.type.displayName || ''; + } + var msg = format('Invalid %s value: %s', name, argString); + if (name === '') { msg += '\n' + e.message; } + throw argumentErrorHelper(action, msg); + } + // return the converted value + return result; +}; + +ArgumentParser.prototype._checkValue = function (action, value) { + // converted value must be one of the choices (if specified) + var choices = action.choices; + if (choices) { + // choise for argument can by array or string + if ((typeof choices === 'string' || Array.isArray(choices)) && + choices.indexOf(value) !== -1) { + return; + } + // choise for subparsers can by only hash + if (typeof choices === 'object' && !Array.isArray(choices) && choices[value]) { + return; + } + + if (typeof choices === 'string') { + choices = choices.split('').join(', '); + } else if (Array.isArray(choices)) { + choices = choices.join(', '); + } else { + choices = Object.keys(choices).join(', '); + } + var message = format('Invalid choice: %s (choose from [%s])', value, choices); + throw argumentErrorHelper(action, message); + } +}; + +// +// Help formatting methods +// + +/** + * ArgumentParser#formatUsage -> string + * + * Return usage string + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.formatUsage = function () { + var formatter = this._getFormatter(); + formatter.addUsage(this.usage, this._actions, this._mutuallyExclusiveGroups); + return formatter.formatHelp(); +}; + +/** + * ArgumentParser#formatHelp -> string + * + * Return help + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.formatHelp = function () { + var formatter = this._getFormatter(); + + // usage + formatter.addUsage(this.usage, this._actions, this._mutuallyExclusiveGroups); + + // description + formatter.addText(this.description); + + // positionals, optionals and user-defined groups + this._actionGroups.forEach(function (actionGroup) { + formatter.startSection(actionGroup.title); + formatter.addText(actionGroup.description); + formatter.addArguments(actionGroup._groupActions); + formatter.endSection(); + }); + + // epilog + formatter.addText(this.epilog); + + // determine help from format above + return formatter.formatHelp(); +}; + +ArgumentParser.prototype._getFormatter = function () { + var FormatterClass = this.formatterClass; + var formatter = new FormatterClass({ prog: this.prog }); + return formatter; +}; + +// +// Print functions +// + +/** + * ArgumentParser#printUsage() -> Void + * + * Print usage + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.printUsage = function () { + this._printMessage(this.formatUsage()); +}; + +/** + * ArgumentParser#printHelp() -> Void + * + * Print help + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.printHelp = function () { + this._printMessage(this.formatHelp()); +}; + +ArgumentParser.prototype._printMessage = function (message, stream) { + if (!stream) { + stream = process.stdout; + } + if (message) { + stream.write('' + message); + } +}; + +// +// Exit functions +// + +/** + * ArgumentParser#exit(status=0, message) -> Void + * - status (int): exit status + * - message (string): message + * + * Print message in stderr/stdout and exit program + **/ +ArgumentParser.prototype.exit = function (status, message) { + if (message) { + if (status === 0) { + this._printMessage(message); + } else { + this._printMessage(message, process.stderr); + } + } + + process.exit(status); +}; + +/** + * ArgumentParser#error(message) -> Void + * - err (Error|string): message + * + * Error method Prints a usage message incorporating the message to stderr and + * exits. If you override this in a subclass, + * it should not return -- it should + * either exit or throw an exception. + * + **/ +ArgumentParser.prototype.error = function (err) { + var message; + if (err instanceof Error) { + if (this.debug === true) { + throw err; + } + message = err.message; + } else { + message = err; + } + var msg = format('%s: error: %s', this.prog, message) + c.EOL; + + if (this.debug === true) { + throw new Error(msg); + } + + this.printUsage(process.stderr); + + return this.exit(2, msg); +}; + +module.exports = ArgumentParser; diff --git a/hm_sunwell/node_modules/argparse/lib/const.js b/hm_sunwell/node_modules/argparse/lib/const.js new file mode 100644 index 0000000..b1fd4ce --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/const.js @@ -0,0 +1,21 @@ +// +// Constants +// + +'use strict'; + +module.exports.EOL = '\n'; + +module.exports.SUPPRESS = '==SUPPRESS=='; + +module.exports.OPTIONAL = '?'; + +module.exports.ZERO_OR_MORE = '*'; + +module.exports.ONE_OR_MORE = '+'; + +module.exports.PARSER = 'A...'; + +module.exports.REMAINDER = '...'; + +module.exports._UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'; diff --git a/hm_sunwell/node_modules/argparse/lib/help/added_formatters.js b/hm_sunwell/node_modules/argparse/lib/help/added_formatters.js new file mode 100644 index 0000000..f8e4299 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/help/added_formatters.js @@ -0,0 +1,87 @@ +'use strict'; + +var util = require('util'); + +// Constants +var c = require('../const'); + +var $$ = require('../utils'); +var HelpFormatter = require('./formatter.js'); + +/** + * new RawDescriptionHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) + * + * Help message formatter which adds default values to argument help. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +function ArgumentDefaultsHelpFormatter(options) { + HelpFormatter.call(this, options); +} + +util.inherits(ArgumentDefaultsHelpFormatter, HelpFormatter); + +ArgumentDefaultsHelpFormatter.prototype._getHelpString = function (action) { + var help = action.help; + if (action.help.indexOf('%(defaultValue)s') === -1) { + if (action.defaultValue !== c.SUPPRESS) { + var defaulting_nargs = [ c.OPTIONAL, c.ZERO_OR_MORE ]; + if (action.isOptional() || (defaulting_nargs.indexOf(action.nargs) >= 0)) { + help += ' (default: %(defaultValue)s)'; + } + } + } + return help; +}; + +module.exports.ArgumentDefaultsHelpFormatter = ArgumentDefaultsHelpFormatter; + +/** + * new RawDescriptionHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) + * + * Help message formatter which retains any formatting in descriptions. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +function RawDescriptionHelpFormatter(options) { + HelpFormatter.call(this, options); +} + +util.inherits(RawDescriptionHelpFormatter, HelpFormatter); + +RawDescriptionHelpFormatter.prototype._fillText = function (text, width, indent) { + var lines = text.split('\n'); + lines = lines.map(function (line) { + return $$.trimEnd(indent + line); + }); + return lines.join('\n'); +}; +module.exports.RawDescriptionHelpFormatter = RawDescriptionHelpFormatter; + +/** + * new RawTextHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawTextHelpFormatter, ...}) + * + * Help message formatter which retains formatting of all help text. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +function RawTextHelpFormatter(options) { + RawDescriptionHelpFormatter.call(this, options); +} + +util.inherits(RawTextHelpFormatter, RawDescriptionHelpFormatter); + +RawTextHelpFormatter.prototype._splitLines = function (text) { + return text.split('\n'); +}; + +module.exports.RawTextHelpFormatter = RawTextHelpFormatter; diff --git a/hm_sunwell/node_modules/argparse/lib/help/formatter.js b/hm_sunwell/node_modules/argparse/lib/help/formatter.js new file mode 100644 index 0000000..a8e4148 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/help/formatter.js @@ -0,0 +1,795 @@ +/** + * class HelpFormatter + * + * Formatter for generating usage messages and argument help strings. Only the + * name of this class is considered a public API. All the methods provided by + * the class are considered an implementation detail. + * + * Do not call in your code, use this class only for inherits your own forvatter + * + * ToDo add [additonal formatters][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#formatter-class + **/ +'use strict'; + +var sprintf = require('sprintf-js').sprintf; + +// Constants +var c = require('../const'); + +var $$ = require('../utils'); + + +/*:nodoc:* internal + * new Support(parent, heding) + * - parent (object): parent section + * - heading (string): header string + * + **/ +function Section(parent, heading) { + this._parent = parent; + this._heading = heading; + this._items = []; +} + +/*:nodoc:* internal + * Section#addItem(callback) -> Void + * - callback (array): tuple with function and args + * + * Add function for single element + **/ +Section.prototype.addItem = function (callback) { + this._items.push(callback); +}; + +/*:nodoc:* internal + * Section#formatHelp(formatter) -> string + * - formatter (HelpFormatter): current formatter + * + * Form help section string + * + **/ +Section.prototype.formatHelp = function (formatter) { + var itemHelp, heading; + + // format the indented section + if (this._parent) { + formatter._indent(); + } + + itemHelp = this._items.map(function (item) { + var obj, func, args; + + obj = formatter; + func = item[0]; + args = item[1]; + return func.apply(obj, args); + }); + itemHelp = formatter._joinParts(itemHelp); + + if (this._parent) { + formatter._dedent(); + } + + // return nothing if the section was empty + if (!itemHelp) { + return ''; + } + + // add the heading if the section was non-empty + heading = ''; + if (this._heading && this._heading !== c.SUPPRESS) { + var currentIndent = formatter.currentIndent; + heading = $$.repeat(' ', currentIndent) + this._heading + ':' + c.EOL; + } + + // join the section-initialize newline, the heading and the help + return formatter._joinParts([ c.EOL, heading, itemHelp, c.EOL ]); +}; + +/** + * new HelpFormatter(options) + * + * #### Options: + * - `prog`: program name + * - `indentIncriment`: indent step, default value 2 + * - `maxHelpPosition`: max help position, default value = 24 + * - `width`: line width + * + **/ +var HelpFormatter = module.exports = function HelpFormatter(options) { + options = options || {}; + + this._prog = options.prog; + + this._maxHelpPosition = options.maxHelpPosition || 24; + this._width = (options.width || ((process.env.COLUMNS || 80) - 2)); + + this._currentIndent = 0; + this._indentIncriment = options.indentIncriment || 2; + this._level = 0; + this._actionMaxLength = 0; + + this._rootSection = new Section(null); + this._currentSection = this._rootSection; + + this._whitespaceMatcher = new RegExp('\\s+', 'g'); + this._longBreakMatcher = new RegExp(c.EOL + c.EOL + c.EOL + '+', 'g'); +}; + +HelpFormatter.prototype._indent = function () { + this._currentIndent += this._indentIncriment; + this._level += 1; +}; + +HelpFormatter.prototype._dedent = function () { + this._currentIndent -= this._indentIncriment; + this._level -= 1; + if (this._currentIndent < 0) { + throw new Error('Indent decreased below 0.'); + } +}; + +HelpFormatter.prototype._addItem = function (func, args) { + this._currentSection.addItem([ func, args ]); +}; + +// +// Message building methods +// + +/** + * HelpFormatter#startSection(heading) -> Void + * - heading (string): header string + * + * Start new help section + * + * See alse [code example][1] + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.startSection = function (heading) { + this._indent(); + var section = new Section(this._currentSection, heading); + var func = section.formatHelp.bind(section); + this._addItem(func, [ this ]); + this._currentSection = section; +}; + +/** + * HelpFormatter#endSection -> Void + * + * End help section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + **/ +HelpFormatter.prototype.endSection = function () { + this._currentSection = this._currentSection._parent; + this._dedent(); +}; + +/** + * HelpFormatter#addText(text) -> Void + * - text (string): plain text + * + * Add plain text into current section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.addText = function (text) { + if (text && text !== c.SUPPRESS) { + this._addItem(this._formatText, [ text ]); + } +}; + +/** + * HelpFormatter#addUsage(usage, actions, groups, prefix) -> Void + * - usage (string): usage text + * - actions (array): actions list + * - groups (array): groups list + * - prefix (string): usage prefix + * + * Add usage data into current section + * + * ##### Example + * + * formatter.addUsage(this.usage, this._actions, []); + * return formatter.formatHelp(); + * + **/ +HelpFormatter.prototype.addUsage = function (usage, actions, groups, prefix) { + if (usage !== c.SUPPRESS) { + this._addItem(this._formatUsage, [ usage, actions, groups, prefix ]); + } +}; + +/** + * HelpFormatter#addArgument(action) -> Void + * - action (object): action + * + * Add argument into current section + * + * Single variant of [[HelpFormatter#addArguments]] + **/ +HelpFormatter.prototype.addArgument = function (action) { + if (action.help !== c.SUPPRESS) { + var self = this; + + // find all invocations + var invocations = [ this._formatActionInvocation(action) ]; + var invocationLength = invocations[0].length; + + var actionLength; + + if (action._getSubactions) { + this._indent(); + action._getSubactions().forEach(function (subaction) { + + var invocationNew = self._formatActionInvocation(subaction); + invocations.push(invocationNew); + invocationLength = Math.max(invocationLength, invocationNew.length); + + }); + this._dedent(); + } + + // update the maximum item length + actionLength = invocationLength + this._currentIndent; + this._actionMaxLength = Math.max(this._actionMaxLength, actionLength); + + // add the item to the list + this._addItem(this._formatAction, [ action ]); + } +}; + +/** + * HelpFormatter#addArguments(actions) -> Void + * - actions (array): actions list + * + * Mass add arguments into current section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.addArguments = function (actions) { + var self = this; + actions.forEach(function (action) { + self.addArgument(action); + }); +}; + +// +// Help-formatting methods +// + +/** + * HelpFormatter#formatHelp -> string + * + * Format help + * + * ##### Example + * + * formatter.addText(this.epilog); + * return formatter.formatHelp(); + * + **/ +HelpFormatter.prototype.formatHelp = function () { + var help = this._rootSection.formatHelp(this); + if (help) { + help = help.replace(this._longBreakMatcher, c.EOL + c.EOL); + help = $$.trimChars(help, c.EOL) + c.EOL; + } + return help; +}; + +HelpFormatter.prototype._joinParts = function (partStrings) { + return partStrings.filter(function (part) { + return (part && part !== c.SUPPRESS); + }).join(''); +}; + +HelpFormatter.prototype._formatUsage = function (usage, actions, groups, prefix) { + if (!prefix && typeof prefix !== 'string') { + prefix = 'usage: '; + } + + actions = actions || []; + groups = groups || []; + + + // if usage is specified, use that + if (usage) { + usage = sprintf(usage, { prog: this._prog }); + + // if no optionals or positionals are available, usage is just prog + } else if (!usage && actions.length === 0) { + usage = this._prog; + + // if optionals and positionals are available, calculate usage + } else if (!usage) { + var prog = this._prog; + var optionals = []; + var positionals = []; + var actionUsage; + var textWidth; + + // split optionals from positionals + actions.forEach(function (action) { + if (action.isOptional()) { + optionals.push(action); + } else { + positionals.push(action); + } + }); + + // build full usage string + actionUsage = this._formatActionsUsage([].concat(optionals, positionals), groups); + usage = [ prog, actionUsage ].join(' '); + + // wrap the usage parts if it's too long + textWidth = this._width - this._currentIndent; + if ((prefix.length + usage.length) > textWidth) { + + // break usage into wrappable parts + var regexpPart = new RegExp('\\(.*?\\)+|\\[.*?\\]+|\\S+', 'g'); + var optionalUsage = this._formatActionsUsage(optionals, groups); + var positionalUsage = this._formatActionsUsage(positionals, groups); + + + var optionalParts = optionalUsage.match(regexpPart); + var positionalParts = positionalUsage.match(regexpPart) || []; + + if (optionalParts.join(' ') !== optionalUsage) { + throw new Error('assert "optionalParts.join(\' \') === optionalUsage"'); + } + if (positionalParts.join(' ') !== positionalUsage) { + throw new Error('assert "positionalParts.join(\' \') === positionalUsage"'); + } + + // helper for wrapping lines + /*eslint-disable func-style*/ // node 0.10 compat + var _getLines = function (parts, indent, prefix) { + var lines = []; + var line = []; + + var lineLength = prefix ? prefix.length - 1 : indent.length - 1; + + parts.forEach(function (part) { + if (lineLength + 1 + part.length > textWidth) { + lines.push(indent + line.join(' ')); + line = []; + lineLength = indent.length - 1; + } + line.push(part); + lineLength += part.length + 1; + }); + + if (line) { + lines.push(indent + line.join(' ')); + } + if (prefix) { + lines[0] = lines[0].substr(indent.length); + } + return lines; + }; + + var lines, indent, parts; + // if prog is short, follow it with optionals or positionals + if (prefix.length + prog.length <= 0.75 * textWidth) { + indent = $$.repeat(' ', (prefix.length + prog.length + 1)); + if (optionalParts) { + lines = [].concat( + _getLines([ prog ].concat(optionalParts), indent, prefix), + _getLines(positionalParts, indent) + ); + } else if (positionalParts) { + lines = _getLines([ prog ].concat(positionalParts), indent, prefix); + } else { + lines = [ prog ]; + } + + // if prog is long, put it on its own line + } else { + indent = $$.repeat(' ', prefix.length); + parts = optionalParts + positionalParts; + lines = _getLines(parts, indent); + if (lines.length > 1) { + lines = [].concat( + _getLines(optionalParts, indent), + _getLines(positionalParts, indent) + ); + } + lines = [ prog ] + lines; + } + // join lines into usage + usage = lines.join(c.EOL); + } + } + + // prefix with 'usage:' + return prefix + usage + c.EOL + c.EOL; +}; + +HelpFormatter.prototype._formatActionsUsage = function (actions, groups) { + // find group indices and identify actions in groups + var groupActions = []; + var inserts = []; + var self = this; + + groups.forEach(function (group) { + var end; + var i; + + var start = actions.indexOf(group._groupActions[0]); + if (start >= 0) { + end = start + group._groupActions.length; + + //if (actions.slice(start, end) === group._groupActions) { + if ($$.arrayEqual(actions.slice(start, end), group._groupActions)) { + group._groupActions.forEach(function (action) { + groupActions.push(action); + }); + + if (!group.required) { + if (inserts[start]) { + inserts[start] += ' ['; + } else { + inserts[start] = '['; + } + inserts[end] = ']'; + } else { + if (inserts[start]) { + inserts[start] += ' ('; + } else { + inserts[start] = '('; + } + inserts[end] = ')'; + } + for (i = start + 1; i < end; i += 1) { + inserts[i] = '|'; + } + } + } + }); + + // collect all actions format strings + var parts = []; + + actions.forEach(function (action, actionIndex) { + var part; + var optionString; + var argsDefault; + var argsString; + + // suppressed arguments are marked with None + // remove | separators for suppressed arguments + if (action.help === c.SUPPRESS) { + parts.push(null); + if (inserts[actionIndex] === '|') { + inserts.splice(actionIndex, actionIndex); + } else if (inserts[actionIndex + 1] === '|') { + inserts.splice(actionIndex + 1, actionIndex + 1); + } + + // produce all arg strings + } else if (!action.isOptional()) { + part = self._formatArgs(action, action.dest); + + // if it's in a group, strip the outer [] + if (groupActions.indexOf(action) >= 0) { + if (part[0] === '[' && part[part.length - 1] === ']') { + part = part.slice(1, -1); + } + } + // add the action string to the list + parts.push(part); + + // produce the first way to invoke the option in brackets + } else { + optionString = action.optionStrings[0]; + + // if the Optional doesn't take a value, format is: -s or --long + if (action.nargs === 0) { + part = '' + optionString; + + // if the Optional takes a value, format is: -s ARGS or --long ARGS + } else { + argsDefault = action.dest.toUpperCase(); + argsString = self._formatArgs(action, argsDefault); + part = optionString + ' ' + argsString; + } + // make it look optional if it's not required or in a group + if (!action.required && groupActions.indexOf(action) < 0) { + part = '[' + part + ']'; + } + // add the action string to the list + parts.push(part); + } + }); + + // insert things at the necessary indices + for (var i = inserts.length - 1; i >= 0; --i) { + if (inserts[i] !== null) { + parts.splice(i, 0, inserts[i]); + } + } + + // join all the action items with spaces + var text = parts.filter(function (part) { + return !!part; + }).join(' '); + + // clean up separators for mutually exclusive groups + text = text.replace(/([\[(]) /g, '$1'); // remove spaces + text = text.replace(/ ([\])])/g, '$1'); + text = text.replace(/\[ *\]/g, ''); // remove empty groups + text = text.replace(/\( *\)/g, ''); + text = text.replace(/\(([^|]*)\)/g, '$1'); // remove () from single action groups + + text = text.trim(); + + // return the text + return text; +}; + +HelpFormatter.prototype._formatText = function (text) { + text = sprintf(text, { prog: this._prog }); + var textWidth = this._width - this._currentIndent; + var indentIncriment = $$.repeat(' ', this._currentIndent); + return this._fillText(text, textWidth, indentIncriment) + c.EOL + c.EOL; +}; + +HelpFormatter.prototype._formatAction = function (action) { + var self = this; + + var helpText; + var helpLines; + var parts; + var indentFirst; + + // determine the required width and the entry label + var helpPosition = Math.min(this._actionMaxLength + 2, this._maxHelpPosition); + var helpWidth = this._width - helpPosition; + var actionWidth = helpPosition - this._currentIndent - 2; + var actionHeader = this._formatActionInvocation(action); + + // no help; start on same line and add a final newline + if (!action.help) { + actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL; + + // short action name; start on the same line and pad two spaces + } else if (actionHeader.length <= actionWidth) { + actionHeader = $$.repeat(' ', this._currentIndent) + + actionHeader + + ' ' + + $$.repeat(' ', actionWidth - actionHeader.length); + indentFirst = 0; + + // long action name; start on the next line + } else { + actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL; + indentFirst = helpPosition; + } + + // collect the pieces of the action help + parts = [ actionHeader ]; + + // if there was help for the action, add lines of help text + if (action.help) { + helpText = this._expandHelp(action); + helpLines = this._splitLines(helpText, helpWidth); + parts.push($$.repeat(' ', indentFirst) + helpLines[0] + c.EOL); + helpLines.slice(1).forEach(function (line) { + parts.push($$.repeat(' ', helpPosition) + line + c.EOL); + }); + + // or add a newline if the description doesn't end with one + } else if (actionHeader.charAt(actionHeader.length - 1) !== c.EOL) { + parts.push(c.EOL); + } + // if there are any sub-actions, add their help as well + if (action._getSubactions) { + this._indent(); + action._getSubactions().forEach(function (subaction) { + parts.push(self._formatAction(subaction)); + }); + this._dedent(); + } + // return a single string + return this._joinParts(parts); +}; + +HelpFormatter.prototype._formatActionInvocation = function (action) { + if (!action.isOptional()) { + var format_func = this._metavarFormatter(action, action.dest); + var metavars = format_func(1); + return metavars[0]; + } + + var parts = []; + var argsDefault; + var argsString; + + // if the Optional doesn't take a value, format is: -s, --long + if (action.nargs === 0) { + parts = parts.concat(action.optionStrings); + + // if the Optional takes a value, format is: -s ARGS, --long ARGS + } else { + argsDefault = action.dest.toUpperCase(); + argsString = this._formatArgs(action, argsDefault); + action.optionStrings.forEach(function (optionString) { + parts.push(optionString + ' ' + argsString); + }); + } + return parts.join(', '); +}; + +HelpFormatter.prototype._metavarFormatter = function (action, metavarDefault) { + var result; + + if (action.metavar || action.metavar === '') { + result = action.metavar; + } else if (action.choices) { + var choices = action.choices; + + if (typeof choices === 'string') { + choices = choices.split('').join(', '); + } else if (Array.isArray(choices)) { + choices = choices.join(','); + } else { + choices = Object.keys(choices).join(','); + } + result = '{' + choices + '}'; + } else { + result = metavarDefault; + } + + return function (size) { + if (Array.isArray(result)) { + return result; + } + + var metavars = []; + for (var i = 0; i < size; i += 1) { + metavars.push(result); + } + return metavars; + }; +}; + +HelpFormatter.prototype._formatArgs = function (action, metavarDefault) { + var result; + var metavars; + + var buildMetavar = this._metavarFormatter(action, metavarDefault); + + switch (action.nargs) { + /*eslint-disable no-undefined*/ + case undefined: + case null: + metavars = buildMetavar(1); + result = '' + metavars[0]; + break; + case c.OPTIONAL: + metavars = buildMetavar(1); + result = '[' + metavars[0] + ']'; + break; + case c.ZERO_OR_MORE: + metavars = buildMetavar(2); + result = '[' + metavars[0] + ' [' + metavars[1] + ' ...]]'; + break; + case c.ONE_OR_MORE: + metavars = buildMetavar(2); + result = '' + metavars[0] + ' [' + metavars[1] + ' ...]'; + break; + case c.REMAINDER: + result = '...'; + break; + case c.PARSER: + metavars = buildMetavar(1); + result = metavars[0] + ' ...'; + break; + default: + metavars = buildMetavar(action.nargs); + result = metavars.join(' '); + } + return result; +}; + +HelpFormatter.prototype._expandHelp = function (action) { + var params = { prog: this._prog }; + + Object.keys(action).forEach(function (actionProperty) { + var actionValue = action[actionProperty]; + + if (actionValue !== c.SUPPRESS) { + params[actionProperty] = actionValue; + } + }); + + if (params.choices) { + if (typeof params.choices === 'string') { + params.choices = params.choices.split('').join(', '); + } else if (Array.isArray(params.choices)) { + params.choices = params.choices.join(', '); + } else { + params.choices = Object.keys(params.choices).join(', '); + } + } + + return sprintf(this._getHelpString(action), params); +}; + +HelpFormatter.prototype._splitLines = function (text, width) { + var lines = []; + var delimiters = [ ' ', '.', ',', '!', '?' ]; + var re = new RegExp('[' + delimiters.join('') + '][^' + delimiters.join('') + ']*$'); + + text = text.replace(/[\n\|\t]/g, ' '); + + text = text.trim(); + text = text.replace(this._whitespaceMatcher, ' '); + + // Wraps the single paragraph in text (a string) so every line + // is at most width characters long. + text.split(c.EOL).forEach(function (line) { + if (width >= line.length) { + lines.push(line); + return; + } + + var wrapStart = 0; + var wrapEnd = width; + var delimiterIndex = 0; + while (wrapEnd <= line.length) { + if (wrapEnd !== line.length && delimiters.indexOf(line[wrapEnd] < -1)) { + delimiterIndex = (re.exec(line.substring(wrapStart, wrapEnd)) || {}).index; + wrapEnd = wrapStart + delimiterIndex + 1; + } + lines.push(line.substring(wrapStart, wrapEnd)); + wrapStart = wrapEnd; + wrapEnd += width; + } + if (wrapStart < line.length) { + lines.push(line.substring(wrapStart, wrapEnd)); + } + }); + + return lines; +}; + +HelpFormatter.prototype._fillText = function (text, width, indent) { + var lines = this._splitLines(text, width); + lines = lines.map(function (line) { + return indent + line; + }); + return lines.join(c.EOL); +}; + +HelpFormatter.prototype._getHelpString = function (action) { + return action.help; +}; diff --git a/hm_sunwell/node_modules/argparse/lib/namespace.js b/hm_sunwell/node_modules/argparse/lib/namespace.js new file mode 100644 index 0000000..a860de9 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/namespace.js @@ -0,0 +1,76 @@ +/** + * class Namespace + * + * Simple object for storing attributes. Implements equality by attribute names + * and values, and provides a simple string representation. + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#the-namespace-object + **/ +'use strict'; + +var $$ = require('./utils'); + +/** + * new Namespace(options) + * - options(object): predefined propertis for result object + * + **/ +var Namespace = module.exports = function Namespace(options) { + $$.extend(this, options); +}; + +/** + * Namespace#isset(key) -> Boolean + * - key (string|number): property name + * + * Tells whenever `namespace` contains given `key` or not. + **/ +Namespace.prototype.isset = function (key) { + return $$.has(this, key); +}; + +/** + * Namespace#set(key, value) -> self + * -key (string|number|object): propery name + * -value (mixed): new property value + * + * Set the property named key with value. + * If key object then set all key properties to namespace object + **/ +Namespace.prototype.set = function (key, value) { + if (typeof (key) === 'object') { + $$.extend(this, key); + } else { + this[key] = value; + } + return this; +}; + +/** + * Namespace#get(key, defaultValue) -> mixed + * - key (string|number): property name + * - defaultValue (mixed): default value + * + * Return the property key or defaulValue if not set + **/ +Namespace.prototype.get = function (key, defaultValue) { + return !this[key] ? defaultValue : this[key]; +}; + +/** + * Namespace#unset(key, defaultValue) -> mixed + * - key (string|number): property name + * - defaultValue (mixed): default value + * + * Return data[key](and delete it) or defaultValue + **/ +Namespace.prototype.unset = function (key, defaultValue) { + var value = this[key]; + if (value !== null) { + delete this[key]; + return value; + } + return defaultValue; +}; diff --git a/hm_sunwell/node_modules/argparse/lib/utils.js b/hm_sunwell/node_modules/argparse/lib/utils.js new file mode 100644 index 0000000..4a9cf3e --- /dev/null +++ b/hm_sunwell/node_modules/argparse/lib/utils.js @@ -0,0 +1,57 @@ +'use strict'; + +exports.repeat = function (str, num) { + var result = ''; + for (var i = 0; i < num; i++) { result += str; } + return result; +}; + +exports.arrayEqual = function (a, b) { + if (a.length !== b.length) { return false; } + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { return false; } + } + return true; +}; + +exports.trimChars = function (str, chars) { + var start = 0; + var end = str.length - 1; + while (chars.indexOf(str.charAt(start)) >= 0) { start++; } + while (chars.indexOf(str.charAt(end)) >= 0) { end--; } + return str.slice(start, end + 1); +}; + +exports.capitalize = function (str) { + return str.charAt(0).toUpperCase() + str.slice(1); +}; + +exports.arrayUnion = function () { + var result = []; + for (var i = 0, values = {}; i < arguments.length; i++) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; j++) { + if (!values[arr[j]]) { + values[arr[j]] = true; + result.push(arr[j]); + } + } + } + return result; +}; + +function has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +exports.has = has; + +exports.extend = function (dest, src) { + for (var i in src) { + if (has(src, i)) { dest[i] = src[i]; } + } +}; + +exports.trimEnd = function (str) { + return str.replace(/\s+$/g, ''); +}; diff --git a/hm_sunwell/node_modules/argparse/package.json b/hm_sunwell/node_modules/argparse/package.json new file mode 100644 index 0000000..bfaa953 --- /dev/null +++ b/hm_sunwell/node_modules/argparse/package.json @@ -0,0 +1,97 @@ +{ + "_args": [ + [ + "argparse@^1.0.7", + "/home/xor/shared_vm/git/node-sunwell/node_modules/js-yaml" + ] + ], + "_from": "argparse@>=1.0.7 <2.0.0", + "_id": "argparse@1.0.9", + "_inCache": true, + "_installable": true, + "_location": "/argparse", + "_nodeVersion": "6.5.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/argparse-1.0.9.tgz_1475177461025_0.33920647646300495" + }, + "_npmUser": { + "email": "vitaly@rcdesign.ru", + "name": "vitaly" + }, + "_npmVersion": "3.10.3", + "_phantomChildren": {}, + "_requested": { + "name": "argparse", + "raw": "argparse@^1.0.7", + "rawSpec": "^1.0.7", + "scope": null, + "spec": ">=1.0.7 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/js-yaml" + ], + "_resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "_shasum": "73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86", + "_shrinkwrap": null, + "_spec": "argparse@^1.0.7", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/js-yaml", + "bugs": { + "url": "https://github.com/nodeca/argparse/issues" + }, + "contributors": [ + { + "name": "Eugene Shkuropat" + }, + { + "name": "Paul Jacobson" + } + ], + "dependencies": { + "sprintf-js": "~1.0.2" + }, + "description": "Very powerful CLI arguments parser. Native port of argparse - python's options parsing library", + "devDependencies": { + "eslint": "^2.13.1", + "istanbul": "^0.4.5", + "mocha": "^3.1.0", + "ndoc": "^5.0.1" + }, + "directories": {}, + "dist": { + "shasum": "73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86", + "tarball": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz" + }, + "files": [ + "index.js", + "lib/" + ], + "gitHead": "acb39f2d726b90d2eadf9e6574a938d6250ad248", + "homepage": "https://github.com/nodeca/argparse#readme", + "keywords": [ + "argparse", + "args", + "cli", + "option", + "parser" + ], + "license": "MIT", + "maintainers": [ + { + "name": "vitaly", + "email": "vitaly@rcdesign.ru" + } + ], + "name": "argparse", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/nodeca/argparse.git" + }, + "scripts": { + "test": "make test" + }, + "version": "1.0.9" +} diff --git a/hm_sunwell/node_modules/array-flatten/LICENSE b/hm_sunwell/node_modules/array-flatten/LICENSE new file mode 100644 index 0000000..983fbe8 --- /dev/null +++ b/hm_sunwell/node_modules/array-flatten/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/array-flatten/README.md b/hm_sunwell/node_modules/array-flatten/README.md new file mode 100644 index 0000000..91fa5b6 --- /dev/null +++ b/hm_sunwell/node_modules/array-flatten/README.md @@ -0,0 +1,43 @@ +# Array Flatten + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][downloads-image]][downloads-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] + +> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. + +## Installation + +``` +npm install array-flatten --save +``` + +## Usage + +```javascript +var flatten = require('array-flatten') + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) +//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) +//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] + +(function () { + flatten(arguments) //=> [1, 2, 3] +})(1, [2, 3]) +``` + +## License + +MIT + +[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat +[npm-url]: https://npmjs.org/package/array-flatten +[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat +[downloads-url]: https://npmjs.org/package/array-flatten +[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat +[travis-url]: https://travis-ci.org/blakeembrey/array-flatten +[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat +[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master diff --git a/hm_sunwell/node_modules/array-flatten/array-flatten.js b/hm_sunwell/node_modules/array-flatten/array-flatten.js new file mode 100644 index 0000000..089117b --- /dev/null +++ b/hm_sunwell/node_modules/array-flatten/array-flatten.js @@ -0,0 +1,64 @@ +'use strict' + +/** + * Expose `arrayFlatten`. + */ +module.exports = arrayFlatten + +/** + * Recursive flatten function with depth. + * + * @param {Array} array + * @param {Array} result + * @param {Number} depth + * @return {Array} + */ +function flattenWithDepth (array, result, depth) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (depth > 0 && Array.isArray(value)) { + flattenWithDepth(value, result, depth - 1) + } else { + result.push(value) + } + } + + return result +} + +/** + * Recursive flatten function. Omitting depth is slightly faster. + * + * @param {Array} array + * @param {Array} result + * @return {Array} + */ +function flattenForever (array, result) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (Array.isArray(value)) { + flattenForever(value, result) + } else { + result.push(value) + } + } + + return result +} + +/** + * Flatten an array, with the ability to define a depth. + * + * @param {Array} array + * @param {Number} depth + * @return {Array} + */ +function arrayFlatten (array, depth) { + if (depth == null) { + return flattenForever(array, []) + } + + return flattenWithDepth(array, [], depth) +} diff --git a/hm_sunwell/node_modules/array-flatten/package.json b/hm_sunwell/node_modules/array-flatten/package.json new file mode 100644 index 0000000..5314336 --- /dev/null +++ b/hm_sunwell/node_modules/array-flatten/package.json @@ -0,0 +1,88 @@ +{ + "_args": [ + [ + "array-flatten@1.1.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "array-flatten@1.1.1", + "_id": "array-flatten@1.1.1", + "_inCache": true, + "_installable": true, + "_location": "/array-flatten", + "_nodeVersion": "2.3.3", + "_npmUser": { + "email": "hello@blakeembrey.com", + "name": "blakeembrey" + }, + "_npmVersion": "2.11.3", + "_phantomChildren": {}, + "_requested": { + "name": "array-flatten", + "raw": "array-flatten@1.1.1", + "rawSpec": "1.1.1", + "scope": null, + "spec": "1.1.1", + "type": "version" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "_shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", + "_shrinkwrap": null, + "_spec": "array-flatten@1.1.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "author": { + "email": "hello@blakeembrey.com", + "name": "Blake Embrey", + "url": "http://blakeembrey.me" + }, + "bugs": { + "url": "https://github.com/blakeembrey/array-flatten/issues" + }, + "dependencies": {}, + "description": "Flatten an array of nested arrays into a single flat array", + "devDependencies": { + "istanbul": "^0.3.13", + "mocha": "^2.2.4", + "pre-commit": "^1.0.7", + "standard": "^3.7.3" + }, + "directories": {}, + "dist": { + "shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", + "tarball": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "files": [ + "LICENSE", + "array-flatten.js" + ], + "gitHead": "1963a9189229d408e1e8f585a00c8be9edbd1803", + "homepage": "https://github.com/blakeembrey/array-flatten", + "keywords": [ + "arguments", + "array", + "depth", + "flatten" + ], + "license": "MIT", + "main": "array-flatten.js", + "maintainers": [ + { + "name": "blakeembrey", + "email": "hello@blakeembrey.com" + } + ], + "name": "array-flatten", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/blakeembrey/array-flatten.git" + }, + "scripts": { + "test": "istanbul cover _mocha -- -R spec" + }, + "version": "1.1.1" +} diff --git a/hm_sunwell/node_modules/asn1/.npmignore b/hm_sunwell/node_modules/asn1/.npmignore new file mode 100644 index 0000000..eb03e3e --- /dev/null +++ b/hm_sunwell/node_modules/asn1/.npmignore @@ -0,0 +1,2 @@ +node_modules +*.log diff --git a/hm_sunwell/node_modules/asn1/.travis.yml b/hm_sunwell/node_modules/asn1/.travis.yml new file mode 100644 index 0000000..09d3ef3 --- /dev/null +++ b/hm_sunwell/node_modules/asn1/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - 0.10 diff --git a/hm_sunwell/node_modules/asn1/LICENSE b/hm_sunwell/node_modules/asn1/LICENSE new file mode 100644 index 0000000..9b5dcdb --- /dev/null +++ b/hm_sunwell/node_modules/asn1/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Mark Cavage, All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE diff --git a/hm_sunwell/node_modules/asn1/README.md b/hm_sunwell/node_modules/asn1/README.md new file mode 100644 index 0000000..7cebf7a --- /dev/null +++ b/hm_sunwell/node_modules/asn1/README.md @@ -0,0 +1,50 @@ +node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS. +Currently BER encoding is supported; at some point I'll likely have to do DER. + +## Usage + +Mostly, if you're *actually* needing to read and write ASN.1, you probably don't +need this readme to explain what and why. If you have no idea what ASN.1 is, +see this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc + +The source is pretty much self-explanatory, and has read/write methods for the +common types out there. + +### Decoding + +The following reads an ASN.1 sequence with a boolean. + + var Ber = require('asn1').Ber; + + var reader = new Ber.Reader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff])); + + reader.readSequence(); + console.log('Sequence len: ' + reader.length); + if (reader.peek() === Ber.Boolean) + console.log(reader.readBoolean()); + +### Encoding + +The following generates the same payload as above. + + var Ber = require('asn1').Ber; + + var writer = new Ber.Writer(); + + writer.startSequence(); + writer.writeBoolean(true); + writer.endSequence(); + + console.log(writer.buffer); + +## Installation + + npm install asn1 + +## License + +MIT. + +## Bugs + +See . diff --git a/hm_sunwell/node_modules/asn1/lib/ber/errors.js b/hm_sunwell/node_modules/asn1/lib/ber/errors.js new file mode 100644 index 0000000..ff21d4f --- /dev/null +++ b/hm_sunwell/node_modules/asn1/lib/ber/errors.js @@ -0,0 +1,13 @@ +// Copyright 2011 Mark Cavage All rights reserved. + + +module.exports = { + + newInvalidAsn1Error: function(msg) { + var e = new Error(); + e.name = 'InvalidAsn1Error'; + e.message = msg || ''; + return e; + } + +}; diff --git a/hm_sunwell/node_modules/asn1/lib/ber/index.js b/hm_sunwell/node_modules/asn1/lib/ber/index.js new file mode 100644 index 0000000..4fb90ae --- /dev/null +++ b/hm_sunwell/node_modules/asn1/lib/ber/index.js @@ -0,0 +1,27 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var errors = require('./errors'); +var types = require('./types'); + +var Reader = require('./reader'); +var Writer = require('./writer'); + + +///--- Exports + +module.exports = { + + Reader: Reader, + + Writer: Writer + +}; + +for (var t in types) { + if (types.hasOwnProperty(t)) + module.exports[t] = types[t]; +} +for (var e in errors) { + if (errors.hasOwnProperty(e)) + module.exports[e] = errors[e]; +} diff --git a/hm_sunwell/node_modules/asn1/lib/ber/reader.js b/hm_sunwell/node_modules/asn1/lib/ber/reader.js new file mode 100644 index 0000000..0a00e98 --- /dev/null +++ b/hm_sunwell/node_modules/asn1/lib/ber/reader.js @@ -0,0 +1,261 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var assert = require('assert'); + +var ASN1 = require('./types'); +var errors = require('./errors'); + + +///--- Globals + +var newInvalidAsn1Error = errors.newInvalidAsn1Error; + + + +///--- API + +function Reader(data) { + if (!data || !Buffer.isBuffer(data)) + throw new TypeError('data must be a node Buffer'); + + this._buf = data; + this._size = data.length; + + // These hold the "current" state + this._len = 0; + this._offset = 0; +} + +Object.defineProperty(Reader.prototype, 'length', { + enumerable: true, + get: function () { return (this._len); } +}); + +Object.defineProperty(Reader.prototype, 'offset', { + enumerable: true, + get: function () { return (this._offset); } +}); + +Object.defineProperty(Reader.prototype, 'remain', { + get: function () { return (this._size - this._offset); } +}); + +Object.defineProperty(Reader.prototype, 'buffer', { + get: function () { return (this._buf.slice(this._offset)); } +}); + + +/** + * Reads a single byte and advances offset; you can pass in `true` to make this + * a "peek" operation (i.e., get the byte, but don't advance the offset). + * + * @param {Boolean} peek true means don't move offset. + * @return {Number} the next byte, null if not enough data. + */ +Reader.prototype.readByte = function(peek) { + if (this._size - this._offset < 1) + return null; + + var b = this._buf[this._offset] & 0xff; + + if (!peek) + this._offset += 1; + + return b; +}; + + +Reader.prototype.peek = function() { + return this.readByte(true); +}; + + +/** + * Reads a (potentially) variable length off the BER buffer. This call is + * not really meant to be called directly, as callers have to manipulate + * the internal buffer afterwards. + * + * As a result of this call, you can call `Reader.length`, until the + * next thing called that does a readLength. + * + * @return {Number} the amount of offset to advance the buffer. + * @throws {InvalidAsn1Error} on bad ASN.1 + */ +Reader.prototype.readLength = function(offset) { + if (offset === undefined) + offset = this._offset; + + if (offset >= this._size) + return null; + + var lenB = this._buf[offset++] & 0xff; + if (lenB === null) + return null; + + if ((lenB & 0x80) == 0x80) { + lenB &= 0x7f; + + if (lenB == 0) + throw newInvalidAsn1Error('Indefinite length not supported'); + + if (lenB > 4) + throw newInvalidAsn1Error('encoding too long'); + + if (this._size - offset < lenB) + return null; + + this._len = 0; + for (var i = 0; i < lenB; i++) + this._len = (this._len << 8) + (this._buf[offset++] & 0xff); + + } else { + // Wasn't a variable length + this._len = lenB; + } + + return offset; +}; + + +/** + * Parses the next sequence in this BER buffer. + * + * To get the length of the sequence, call `Reader.length`. + * + * @return {Number} the sequence's tag. + */ +Reader.prototype.readSequence = function(tag) { + var seq = this.peek(); + if (seq === null) + return null; + if (tag !== undefined && tag !== seq) + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + + ': got 0x' + seq.toString(16)); + + var o = this.readLength(this._offset + 1); // stored in `length` + if (o === null) + return null; + + this._offset = o; + return seq; +}; + + +Reader.prototype.readInt = function() { + return this._readTag(ASN1.Integer); +}; + + +Reader.prototype.readBoolean = function() { + return (this._readTag(ASN1.Boolean) === 0 ? false : true); +}; + + +Reader.prototype.readEnumeration = function() { + return this._readTag(ASN1.Enumeration); +}; + + +Reader.prototype.readString = function(tag, retbuf) { + if (!tag) + tag = ASN1.OctetString; + + var b = this.peek(); + if (b === null) + return null; + + if (b !== tag) + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + + ': got 0x' + b.toString(16)); + + var o = this.readLength(this._offset + 1); // stored in `length` + + if (o === null) + return null; + + if (this.length > this._size - o) + return null; + + this._offset = o; + + if (this.length === 0) + return retbuf ? new Buffer(0) : ''; + + var str = this._buf.slice(this._offset, this._offset + this.length); + this._offset += this.length; + + return retbuf ? str : str.toString('utf8'); +}; + +Reader.prototype.readOID = function(tag) { + if (!tag) + tag = ASN1.OID; + + var b = this.readString(tag, true); + if (b === null) + return null; + + var values = []; + var value = 0; + + for (var i = 0; i < b.length; i++) { + var byte = b[i] & 0xff; + + value <<= 7; + value += byte & 0x7f; + if ((byte & 0x80) == 0) { + values.push(value); + value = 0; + } + } + + value = values.shift(); + values.unshift(value % 40); + values.unshift((value / 40) >> 0); + + return values.join('.'); +}; + + +Reader.prototype._readTag = function(tag) { + assert.ok(tag !== undefined); + + var b = this.peek(); + + if (b === null) + return null; + + if (b !== tag) + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + + ': got 0x' + b.toString(16)); + + var o = this.readLength(this._offset + 1); // stored in `length` + if (o === null) + return null; + + if (this.length > 4) + throw newInvalidAsn1Error('Integer too long: ' + this.length); + + if (this.length > this._size - o) + return null; + this._offset = o; + + var fb = this._buf[this._offset]; + var value = 0; + + for (var i = 0; i < this.length; i++) { + value <<= 8; + value |= (this._buf[this._offset++] & 0xff); + } + + if ((fb & 0x80) == 0x80 && i !== 4) + value -= (1 << (i * 8)); + + return value >> 0; +}; + + + +///--- Exported API + +module.exports = Reader; diff --git a/hm_sunwell/node_modules/asn1/lib/ber/types.js b/hm_sunwell/node_modules/asn1/lib/ber/types.js new file mode 100644 index 0000000..8aea000 --- /dev/null +++ b/hm_sunwell/node_modules/asn1/lib/ber/types.js @@ -0,0 +1,36 @@ +// Copyright 2011 Mark Cavage All rights reserved. + + +module.exports = { + EOC: 0, + Boolean: 1, + Integer: 2, + BitString: 3, + OctetString: 4, + Null: 5, + OID: 6, + ObjectDescriptor: 7, + External: 8, + Real: 9, // float + Enumeration: 10, + PDV: 11, + Utf8String: 12, + RelativeOID: 13, + Sequence: 16, + Set: 17, + NumericString: 18, + PrintableString: 19, + T61String: 20, + VideotexString: 21, + IA5String: 22, + UTCTime: 23, + GeneralizedTime: 24, + GraphicString: 25, + VisibleString: 26, + GeneralString: 28, + UniversalString: 29, + CharacterString: 30, + BMPString: 31, + Constructor: 32, + Context: 128 +}; diff --git a/hm_sunwell/node_modules/asn1/lib/ber/writer.js b/hm_sunwell/node_modules/asn1/lib/ber/writer.js new file mode 100644 index 0000000..d9d99af --- /dev/null +++ b/hm_sunwell/node_modules/asn1/lib/ber/writer.js @@ -0,0 +1,316 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var assert = require('assert'); +var ASN1 = require('./types'); +var errors = require('./errors'); + + +///--- Globals + +var newInvalidAsn1Error = errors.newInvalidAsn1Error; + +var DEFAULT_OPTS = { + size: 1024, + growthFactor: 8 +}; + + +///--- Helpers + +function merge(from, to) { + assert.ok(from); + assert.equal(typeof(from), 'object'); + assert.ok(to); + assert.equal(typeof(to), 'object'); + + var keys = Object.getOwnPropertyNames(from); + keys.forEach(function(key) { + if (to[key]) + return; + + var value = Object.getOwnPropertyDescriptor(from, key); + Object.defineProperty(to, key, value); + }); + + return to; +} + + + +///--- API + +function Writer(options) { + options = merge(DEFAULT_OPTS, options || {}); + + this._buf = new Buffer(options.size || 1024); + this._size = this._buf.length; + this._offset = 0; + this._options = options; + + // A list of offsets in the buffer where we need to insert + // sequence tag/len pairs. + this._seq = []; +} + +Object.defineProperty(Writer.prototype, 'buffer', { + get: function () { + if (this._seq.length) + throw new InvalidAsn1Error(this._seq.length + ' unended sequence(s)'); + + return (this._buf.slice(0, this._offset)); + } +}); + +Writer.prototype.writeByte = function(b) { + if (typeof(b) !== 'number') + throw new TypeError('argument must be a Number'); + + this._ensure(1); + this._buf[this._offset++] = b; +}; + + +Writer.prototype.writeInt = function(i, tag) { + if (typeof(i) !== 'number') + throw new TypeError('argument must be a Number'); + if (typeof(tag) !== 'number') + tag = ASN1.Integer; + + var sz = 4; + + while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) && + (sz > 1)) { + sz--; + i <<= 8; + } + + if (sz > 4) + throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff'); + + this._ensure(2 + sz); + this._buf[this._offset++] = tag; + this._buf[this._offset++] = sz; + + while (sz-- > 0) { + this._buf[this._offset++] = ((i & 0xff000000) >>> 24); + i <<= 8; + } + +}; + + +Writer.prototype.writeNull = function() { + this.writeByte(ASN1.Null); + this.writeByte(0x00); +}; + + +Writer.prototype.writeEnumeration = function(i, tag) { + if (typeof(i) !== 'number') + throw new TypeError('argument must be a Number'); + if (typeof(tag) !== 'number') + tag = ASN1.Enumeration; + + return this.writeInt(i, tag); +}; + + +Writer.prototype.writeBoolean = function(b, tag) { + if (typeof(b) !== 'boolean') + throw new TypeError('argument must be a Boolean'); + if (typeof(tag) !== 'number') + tag = ASN1.Boolean; + + this._ensure(3); + this._buf[this._offset++] = tag; + this._buf[this._offset++] = 0x01; + this._buf[this._offset++] = b ? 0xff : 0x00; +}; + + +Writer.prototype.writeString = function(s, tag) { + if (typeof(s) !== 'string') + throw new TypeError('argument must be a string (was: ' + typeof(s) + ')'); + if (typeof(tag) !== 'number') + tag = ASN1.OctetString; + + var len = Buffer.byteLength(s); + this.writeByte(tag); + this.writeLength(len); + if (len) { + this._ensure(len); + this._buf.write(s, this._offset); + this._offset += len; + } +}; + + +Writer.prototype.writeBuffer = function(buf, tag) { + if (typeof(tag) !== 'number') + throw new TypeError('tag must be a number'); + if (!Buffer.isBuffer(buf)) + throw new TypeError('argument must be a buffer'); + + this.writeByte(tag); + this.writeLength(buf.length); + this._ensure(buf.length); + buf.copy(this._buf, this._offset, 0, buf.length); + this._offset += buf.length; +}; + + +Writer.prototype.writeStringArray = function(strings) { + if ((!strings instanceof Array)) + throw new TypeError('argument must be an Array[String]'); + + var self = this; + strings.forEach(function(s) { + self.writeString(s); + }); +}; + +// This is really to solve DER cases, but whatever for now +Writer.prototype.writeOID = function(s, tag) { + if (typeof(s) !== 'string') + throw new TypeError('argument must be a string'); + if (typeof(tag) !== 'number') + tag = ASN1.OID; + + if (!/^([0-9]+\.){3,}[0-9]+$/.test(s)) + throw new Error('argument is not a valid OID string'); + + function encodeOctet(bytes, octet) { + if (octet < 128) { + bytes.push(octet); + } else if (octet < 16384) { + bytes.push((octet >>> 7) | 0x80); + bytes.push(octet & 0x7F); + } else if (octet < 2097152) { + bytes.push((octet >>> 14) | 0x80); + bytes.push(((octet >>> 7) | 0x80) & 0xFF); + bytes.push(octet & 0x7F); + } else if (octet < 268435456) { + bytes.push((octet >>> 21) | 0x80); + bytes.push(((octet >>> 14) | 0x80) & 0xFF); + bytes.push(((octet >>> 7) | 0x80) & 0xFF); + bytes.push(octet & 0x7F); + } else { + bytes.push(((octet >>> 28) | 0x80) & 0xFF); + bytes.push(((octet >>> 21) | 0x80) & 0xFF); + bytes.push(((octet >>> 14) | 0x80) & 0xFF); + bytes.push(((octet >>> 7) | 0x80) & 0xFF); + bytes.push(octet & 0x7F); + } + } + + var tmp = s.split('.'); + var bytes = []; + bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10)); + tmp.slice(2).forEach(function(b) { + encodeOctet(bytes, parseInt(b, 10)); + }); + + var self = this; + this._ensure(2 + bytes.length); + this.writeByte(tag); + this.writeLength(bytes.length); + bytes.forEach(function(b) { + self.writeByte(b); + }); +}; + + +Writer.prototype.writeLength = function(len) { + if (typeof(len) !== 'number') + throw new TypeError('argument must be a Number'); + + this._ensure(4); + + if (len <= 0x7f) { + this._buf[this._offset++] = len; + } else if (len <= 0xff) { + this._buf[this._offset++] = 0x81; + this._buf[this._offset++] = len; + } else if (len <= 0xffff) { + this._buf[this._offset++] = 0x82; + this._buf[this._offset++] = len >> 8; + this._buf[this._offset++] = len; + } else if (len <= 0xffffff) { + this._buf[this._offset++] = 0x83; + this._buf[this._offset++] = len >> 16; + this._buf[this._offset++] = len >> 8; + this._buf[this._offset++] = len; + } else { + throw new InvalidAsn1ERror('Length too long (> 4 bytes)'); + } +}; + +Writer.prototype.startSequence = function(tag) { + if (typeof(tag) !== 'number') + tag = ASN1.Sequence | ASN1.Constructor; + + this.writeByte(tag); + this._seq.push(this._offset); + this._ensure(3); + this._offset += 3; +}; + + +Writer.prototype.endSequence = function() { + var seq = this._seq.pop(); + var start = seq + 3; + var len = this._offset - start; + + if (len <= 0x7f) { + this._shift(start, len, -2); + this._buf[seq] = len; + } else if (len <= 0xff) { + this._shift(start, len, -1); + this._buf[seq] = 0x81; + this._buf[seq + 1] = len; + } else if (len <= 0xffff) { + this._buf[seq] = 0x82; + this._buf[seq + 1] = len >> 8; + this._buf[seq + 2] = len; + } else if (len <= 0xffffff) { + this._shift(start, len, 1); + this._buf[seq] = 0x83; + this._buf[seq + 1] = len >> 16; + this._buf[seq + 2] = len >> 8; + this._buf[seq + 3] = len; + } else { + throw new InvalidAsn1Error('Sequence too long'); + } +}; + + +Writer.prototype._shift = function(start, len, shift) { + assert.ok(start !== undefined); + assert.ok(len !== undefined); + assert.ok(shift); + + this._buf.copy(this._buf, start + shift, start, start + len); + this._offset += shift; +}; + +Writer.prototype._ensure = function(len) { + assert.ok(len); + + if (this._size - this._offset < len) { + var sz = this._size * this._options.growthFactor; + if (sz - this._offset < len) + sz += len; + + var buf = new Buffer(sz); + + this._buf.copy(buf, 0, 0, this._offset); + this._buf = buf; + this._size = sz; + } +}; + + + +///--- Exported API + +module.exports = Writer; diff --git a/hm_sunwell/node_modules/asn1/lib/index.js b/hm_sunwell/node_modules/asn1/lib/index.js new file mode 100644 index 0000000..d1766e7 --- /dev/null +++ b/hm_sunwell/node_modules/asn1/lib/index.js @@ -0,0 +1,20 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +// If you have no idea what ASN.1 or BER is, see this: +// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc + +var Ber = require('./ber/index'); + + + +///--- Exported API + +module.exports = { + + Ber: Ber, + + BerReader: Ber.Reader, + + BerWriter: Ber.Writer + +}; diff --git a/hm_sunwell/node_modules/asn1/package.json b/hm_sunwell/node_modules/asn1/package.json new file mode 100644 index 0000000..780b177 --- /dev/null +++ b/hm_sunwell/node_modules/asn1/package.json @@ -0,0 +1,90 @@ +{ + "_args": [ + [ + "asn1@~0.2.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk" + ] + ], + "_from": "asn1@>=0.2.3 <0.3.0", + "_id": "asn1@0.2.3", + "_inCache": true, + "_installable": true, + "_location": "/asn1", + "_npmUser": { + "email": "patrick.f.mooney@gmail.com", + "name": "pfmooney" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "asn1", + "raw": "asn1@~0.2.3", + "rawSpec": "~0.2.3", + "scope": null, + "spec": ">=0.2.3 <0.3.0", + "type": "range" + }, + "_requiredBy": [ + "/sshpk" + ], + "_resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "_shasum": "dac8787713c9966849fc8180777ebe9c1ddf3b86", + "_shrinkwrap": null, + "_spec": "asn1@~0.2.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk", + "author": { + "email": "mcavage@gmail.com", + "name": "Mark Cavage" + }, + "bugs": { + "url": "https://github.com/mcavage/node-asn1/issues" + }, + "contributors": [ + { + "name": "David Gwynne", + "email": "loki@animata.net" + }, + { + "name": "Yunong Xiao", + "email": "yunong@joyent.com" + }, + { + "name": "Alex Wilson", + "email": "alex.wilson@joyent.com" + } + ], + "dependencies": {}, + "description": "Contains parsers and serializers for ASN.1 (currently BER only)", + "devDependencies": { + "tap": "0.4.8" + }, + "directories": {}, + "dist": { + "shasum": "dac8787713c9966849fc8180777ebe9c1ddf3b86", + "tarball": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + }, + "homepage": "https://github.com/mcavage/node-asn1", + "license": "MIT", + "main": "lib/index.js", + "maintainers": [ + { + "name": "mcavage", + "email": "mcavage@gmail.com" + }, + { + "name": "pfmooney", + "email": "patrick.f.mooney@gmail.com" + } + ], + "name": "asn1", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/mcavage/node-asn1.git" + }, + "scripts": { + "test": "tap ./tst" + }, + "version": "0.2.3" +} diff --git a/hm_sunwell/node_modules/asn1/tst/ber/reader.test.js b/hm_sunwell/node_modules/asn1/tst/ber/reader.test.js new file mode 100644 index 0000000..062fd7e --- /dev/null +++ b/hm_sunwell/node_modules/asn1/tst/ber/reader.test.js @@ -0,0 +1,208 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var test = require('tap').test; + + + +///--- Globals + +var BerReader; + + + +///--- Tests + +test('load library', function(t) { + BerReader = require('../../lib/index').BerReader; + t.ok(BerReader); + try { + new BerReader(); + t.fail('Should have thrown'); + } catch (e) { + t.ok(e instanceof TypeError, 'Should have been a type error'); + } + t.end(); +}); + + +test('read byte', function(t) { + var reader = new BerReader(new Buffer([0xde])); + t.ok(reader); + t.equal(reader.readByte(), 0xde, 'wrong value'); + t.end(); +}); + + +test('read 1 byte int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x01, 0x03])); + t.ok(reader); + t.equal(reader.readInt(), 0x03, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read 2 byte int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x02, 0x7e, 0xde])); + t.ok(reader); + t.equal(reader.readInt(), 0x7ede, 'wrong value'); + t.equal(reader.length, 0x02, 'wrong length'); + t.end(); +}); + + +test('read 3 byte int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x03, 0x7e, 0xde, 0x03])); + t.ok(reader); + t.equal(reader.readInt(), 0x7ede03, 'wrong value'); + t.equal(reader.length, 0x03, 'wrong length'); + t.end(); +}); + + +test('read 4 byte int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01])); + t.ok(reader); + t.equal(reader.readInt(), 0x7ede0301, 'wrong value'); + t.equal(reader.length, 0x04, 'wrong length'); + t.end(); +}); + + +test('read 1 byte negative int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x01, 0xdc])); + t.ok(reader); + t.equal(reader.readInt(), -36, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read 2 byte negative int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x02, 0xc0, 0x4e])); + t.ok(reader); + t.equal(reader.readInt(), -16306, 'wrong value'); + t.equal(reader.length, 0x02, 'wrong length'); + t.end(); +}); + + +test('read 3 byte negative int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x03, 0xff, 0x00, 0x19])); + t.ok(reader); + t.equal(reader.readInt(), -65511, 'wrong value'); + t.equal(reader.length, 0x03, 'wrong length'); + t.end(); +}); + + +test('read 4 byte negative int', function(t) { + var reader = new BerReader(new Buffer([0x02, 0x04, 0x91, 0x7c, 0x22, 0x1f])); + t.ok(reader); + t.equal(reader.readInt(), -1854135777, 'wrong value'); + t.equal(reader.length, 0x04, 'wrong length'); + t.end(); +}); + + +test('read boolean true', function(t) { + var reader = new BerReader(new Buffer([0x01, 0x01, 0xff])); + t.ok(reader); + t.equal(reader.readBoolean(), true, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read boolean false', function(t) { + var reader = new BerReader(new Buffer([0x01, 0x01, 0x00])); + t.ok(reader); + t.equal(reader.readBoolean(), false, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read enumeration', function(t) { + var reader = new BerReader(new Buffer([0x0a, 0x01, 0x20])); + t.ok(reader); + t.equal(reader.readEnumeration(), 0x20, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read string', function(t) { + var dn = 'cn=foo,ou=unit,o=test'; + var buf = new Buffer(dn.length + 2); + buf[0] = 0x04; + buf[1] = Buffer.byteLength(dn); + buf.write(dn, 2); + var reader = new BerReader(buf); + t.ok(reader); + t.equal(reader.readString(), dn, 'wrong value'); + t.equal(reader.length, dn.length, 'wrong length'); + t.end(); +}); + + +test('read sequence', function(t) { + var reader = new BerReader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff])); + t.ok(reader); + t.equal(reader.readSequence(), 0x30, 'wrong value'); + t.equal(reader.length, 0x03, 'wrong length'); + t.equal(reader.readBoolean(), true, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('anonymous LDAPv3 bind', function(t) { + var BIND = new Buffer(14); + BIND[0] = 0x30; // Sequence + BIND[1] = 12; // len + BIND[2] = 0x02; // ASN.1 Integer + BIND[3] = 1; // len + BIND[4] = 0x04; // msgid (make up 4) + BIND[5] = 0x60; // Bind Request + BIND[6] = 7; // len + BIND[7] = 0x02; // ASN.1 Integer + BIND[8] = 1; // len + BIND[9] = 0x03; // v3 + BIND[10] = 0x04; // String (bind dn) + BIND[11] = 0; // len + BIND[12] = 0x80; // ContextSpecific (choice) + BIND[13] = 0; // simple bind + + // Start testing ^^ + var ber = new BerReader(BIND); + t.equal(ber.readSequence(), 48, 'Not an ASN.1 Sequence'); + t.equal(ber.length, 12, 'Message length should be 12'); + t.equal(ber.readInt(), 4, 'Message id should have been 4'); + t.equal(ber.readSequence(), 96, 'Bind Request should have been 96'); + t.equal(ber.length, 7, 'Bind length should have been 7'); + t.equal(ber.readInt(), 3, 'LDAP version should have been 3'); + t.equal(ber.readString(), '', 'Bind DN should have been empty'); + t.equal(ber.length, 0, 'string length should have been 0'); + t.equal(ber.readByte(), 0x80, 'Should have been ContextSpecific (choice)'); + t.equal(ber.readByte(), 0, 'Should have been simple bind'); + t.equal(null, ber.readByte(), 'Should be out of data'); + t.end(); +}); + + +test('long string', function(t) { + var buf = new Buffer(256); + var o; + var s = + '2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' + + 'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' + + 'Teena Vradmin\'s description.'; + buf[0] = 0x04; + buf[1] = 0x81; + buf[2] = 0x94; + buf.write(s, 3); + var ber = new BerReader(buf.slice(0, 3 + s.length)); + t.equal(ber.readString(), s); + t.end(); +}); diff --git a/hm_sunwell/node_modules/asn1/tst/ber/writer.test.js b/hm_sunwell/node_modules/asn1/tst/ber/writer.test.js new file mode 100644 index 0000000..d87cb7b --- /dev/null +++ b/hm_sunwell/node_modules/asn1/tst/ber/writer.test.js @@ -0,0 +1,370 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var test = require('tap').test; +var sys = require('sys'); + +///--- Globals + +var BerWriter; + +var BerReader; + + +///--- Tests + +test('load library', function(t) { + BerWriter = require('../../lib/index').BerWriter; + t.ok(BerWriter); + t.ok(new BerWriter()); + t.end(); +}); + + +test('write byte', function(t) { + var writer = new BerWriter(); + + writer.writeByte(0xC2); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 1, 'Wrong length'); + t.equal(ber[0], 0xC2, 'value wrong'); + + t.end(); +}); + + +test('write 1 byte int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(0x7f); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 3, 'Wrong length for an int: ' + ber.length); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong (2) -> ' + ber[0]); + t.equal(ber[1], 0x01, 'length wrong(1) -> ' + ber[1]); + t.equal(ber[2], 0x7f, 'value wrong(3) -> ' + ber[2]); + + t.end(); +}); + + +test('write 2 byte int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(0x7ffe); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 4, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x02, 'length wrong'); + t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); + t.equal(ber[3], 0xfe, 'value wrong (byte 2)'); + + t.end(); +}); + + +test('write 3 byte int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(0x7ffffe); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 5, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x03, 'length wrong'); + t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); + t.equal(ber[3], 0xff, 'value wrong (byte 2)'); + t.equal(ber[4], 0xfe, 'value wrong (byte 3)'); + + t.end(); +}); + + +test('write 4 byte int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(0x7ffffffe); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 6, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x04, 'length wrong'); + t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); + t.equal(ber[3], 0xff, 'value wrong (byte 2)'); + t.equal(ber[4], 0xff, 'value wrong (byte 3)'); + t.equal(ber[5], 0xfe, 'value wrong (byte 4)'); + + t.end(); +}); + + +test('write 1 byte negative int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(-128); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 3, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x01, 'length wrong'); + t.equal(ber[2], 0x80, 'value wrong (byte 1)'); + + t.end(); +}); + + +test('write 2 byte negative int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(-22400); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 4, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x02, 'length wrong'); + t.equal(ber[2], 0xa8, 'value wrong (byte 1)'); + t.equal(ber[3], 0x80, 'value wrong (byte 2)'); + + t.end(); +}); + + +test('write 3 byte negative int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(-481653); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 5, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x03, 'length wrong'); + t.equal(ber[2], 0xf8, 'value wrong (byte 1)'); + t.equal(ber[3], 0xa6, 'value wrong (byte 2)'); + t.equal(ber[4], 0x8b, 'value wrong (byte 3)'); + + t.end(); +}); + + +test('write 4 byte negative int', function(t) { + var writer = new BerWriter(); + + writer.writeInt(-1522904131); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 6, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x04, 'length wrong'); + t.equal(ber[2], 0xa5, 'value wrong (byte 1)'); + t.equal(ber[3], 0x3a, 'value wrong (byte 2)'); + t.equal(ber[4], 0x53, 'value wrong (byte 3)'); + t.equal(ber[5], 0xbd, 'value wrong (byte 4)'); + + t.end(); +}); + + +test('write boolean', function(t) { + var writer = new BerWriter(); + + writer.writeBoolean(true); + writer.writeBoolean(false); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 6, 'Wrong length'); + t.equal(ber[0], 0x01, 'tag wrong'); + t.equal(ber[1], 0x01, 'length wrong'); + t.equal(ber[2], 0xff, 'value wrong'); + t.equal(ber[3], 0x01, 'tag wrong'); + t.equal(ber[4], 0x01, 'length wrong'); + t.equal(ber[5], 0x00, 'value wrong'); + + t.end(); +}); + + +test('write string', function(t) { + var writer = new BerWriter(); + writer.writeString('hello world'); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 13, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + +test('write buffer', function(t) { + var writer = new BerWriter(); + // write some stuff to start with + writer.writeString('hello world'); + var ber = writer.buffer; + var buf = new Buffer([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, + 0xff, 0x01, 0x01, 0xff]); + writer.writeBuffer(buf.slice(2, buf.length), 0x04); + ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 26, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value'); + t.equal(ber[13], buf[0], 'wrong tag'); + t.equal(ber[14], buf[1], 'wrong length'); + for (var i = 13, j = 0; i < ber.length && j < buf.length; i++, j++) { + t.equal(ber[i], buf[j], 'buffer contents not identical'); + } + t.end(); +}); + +test('write string array', function(t) { + var writer = new BerWriter(); + writer.writeStringArray(['hello world', 'fubar!']); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 21, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value'); + + t.equal(ber[13], 0x04, 'wrong tag'); + t.equal(ber[14], 6, 'wrong length'); + t.equal(ber.slice(15).toString('utf8'), 'fubar!', 'wrong value'); + + t.end(); +}); + + +test('resize internal buffer', function(t) { + var writer = new BerWriter({size: 2}); + writer.writeString('hello world'); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 13, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + + +test('sequence', function(t) { + var writer = new BerWriter({size: 25}); + writer.startSequence(); + writer.writeString('hello world'); + writer.endSequence(); + var ber = writer.buffer; + + t.ok(ber); + console.log(ber); + t.equal(ber.length, 15, 'wrong length'); + t.equal(ber[0], 0x30, 'wrong tag'); + t.equal(ber[1], 13, 'wrong length'); + t.equal(ber[2], 0x04, 'wrong tag'); + t.equal(ber[3], 11, 'wrong length'); + t.equal(ber.slice(4).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + + +test('nested sequence', function(t) { + var writer = new BerWriter({size: 25}); + writer.startSequence(); + writer.writeString('hello world'); + writer.startSequence(); + writer.writeString('hello world'); + writer.endSequence(); + writer.endSequence(); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 30, 'wrong length'); + t.equal(ber[0], 0x30, 'wrong tag'); + t.equal(ber[1], 28, 'wrong length'); + t.equal(ber[2], 0x04, 'wrong tag'); + t.equal(ber[3], 11, 'wrong length'); + t.equal(ber.slice(4, 15).toString('utf8'), 'hello world', 'wrong value'); + t.equal(ber[15], 0x30, 'wrong tag'); + t.equal(ber[16], 13, 'wrong length'); + t.equal(ber[17], 0x04, 'wrong tag'); + t.equal(ber[18], 11, 'wrong length'); + t.equal(ber.slice(19, 30).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + + +test('LDAP bind message', function(t) { + var dn = 'cn=foo,ou=unit,o=test'; + var writer = new BerWriter(); + writer.startSequence(); + writer.writeInt(3); // msgid = 3 + writer.startSequence(0x60); // ldap bind + writer.writeInt(3); // ldap v3 + writer.writeString(dn); + writer.writeByte(0x80); + writer.writeByte(0x00); + writer.endSequence(); + writer.endSequence(); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 35, 'wrong length (buffer)'); + t.equal(ber[0], 0x30, 'wrong tag'); + t.equal(ber[1], 33, 'wrong length'); + t.equal(ber[2], 0x02, 'wrong tag'); + t.equal(ber[3], 1, 'wrong length'); + t.equal(ber[4], 0x03, 'wrong value'); + t.equal(ber[5], 0x60, 'wrong tag'); + t.equal(ber[6], 28, 'wrong length'); + t.equal(ber[7], 0x02, 'wrong tag'); + t.equal(ber[8], 1, 'wrong length'); + t.equal(ber[9], 0x03, 'wrong value'); + t.equal(ber[10], 0x04, 'wrong tag'); + t.equal(ber[11], dn.length, 'wrong length'); + t.equal(ber.slice(12, 33).toString('utf8'), dn, 'wrong value'); + t.equal(ber[33], 0x80, 'wrong tag'); + t.equal(ber[34], 0x00, 'wrong len'); + + t.end(); +}); + + +test('Write OID', function(t) { + var oid = '1.2.840.113549.1.1.1'; + var writer = new BerWriter(); + writer.writeOID(oid); + + var ber = writer.buffer; + t.ok(ber); + console.log(require('util').inspect(ber)); + console.log(require('util').inspect(new Buffer([0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01]))); + + t.end(); +}); diff --git a/hm_sunwell/node_modules/assert-plus/AUTHORS b/hm_sunwell/node_modules/assert-plus/AUTHORS new file mode 100644 index 0000000..1923524 --- /dev/null +++ b/hm_sunwell/node_modules/assert-plus/AUTHORS @@ -0,0 +1,6 @@ +Dave Eddy +Fred Kuo +Lars-Magnus Skog +Mark Cavage +Patrick Mooney +Rob Gulewich diff --git a/hm_sunwell/node_modules/assert-plus/CHANGES.md b/hm_sunwell/node_modules/assert-plus/CHANGES.md new file mode 100644 index 0000000..d249d9b --- /dev/null +++ b/hm_sunwell/node_modules/assert-plus/CHANGES.md @@ -0,0 +1,8 @@ +# assert-plus Changelog + +## 0.2.0 + +- Fix `assert.object(null)` so it throws +- Fix optional/arrayOf exports for non-type-of asserts +- Add optiona/arrayOf exports for Stream/Date/Regex/uuid +- Add basic unit test coverage diff --git a/hm_sunwell/node_modules/assert-plus/README.md b/hm_sunwell/node_modules/assert-plus/README.md new file mode 100644 index 0000000..0b39593 --- /dev/null +++ b/hm_sunwell/node_modules/assert-plus/README.md @@ -0,0 +1,155 @@ +# assert-plus + +This library is a super small wrapper over node's assert module that has two +things: (1) the ability to disable assertions with the environment variable +NODE\_NDEBUG, and (2) some API wrappers for argument testing. Like +`assert.string(myArg, 'myArg')`. As a simple example, most of my code looks +like this: + +```javascript + var assert = require('assert-plus'); + + function fooAccount(options, callback) { + assert.object(options, 'options'); + assert.number(options.id, 'options.id'); + assert.bool(options.isManager, 'options.isManager'); + assert.string(options.name, 'options.name'); + assert.arrayOfString(options.email, 'options.email'); + assert.func(callback, 'callback'); + + // Do stuff + callback(null, {}); + } +``` + +# API + +All methods that *aren't* part of node's core assert API are simply assumed to +take an argument, and then a string 'name' that's not a message; `AssertionError` +will be thrown if the assertion fails with a message like: + + AssertionError: foo (string) is required + at test (/home/mark/work/foo/foo.js:3:9) + at Object. (/home/mark/work/foo/foo.js:15:1) + at Module._compile (module.js:446:26) + at Object..js (module.js:464:10) + at Module.load (module.js:353:31) + at Function._load (module.js:311:12) + at Array.0 (module.js:484:10) + at EventEmitter._tickCallback (node.js:190:38) + +from: + +```javascript + function test(foo) { + assert.string(foo, 'foo'); + } +``` + +There you go. You can check that arrays are of a homogeneous type with `Arrayof$Type`: + +```javascript + function test(foo) { + assert.arrayOfString(foo, 'foo'); + } +``` + +You can assert IFF an argument is not `undefined` (i.e., an optional arg): + +```javascript + assert.optionalString(foo, 'foo'); +``` + +Lastly, you can opt-out of assertion checking altogether by setting the +environment variable `NODE_NDEBUG=1`. This is pseudo-useful if you have +lots of assertions, and don't want to pay `typeof ()` taxes to v8 in +production. Be advised: The standard functions re-exported from `assert` are +also disabled in assert-plus if NDEBUG is specified. Using them directly from +the `assert` module avoids this behavior. + +The complete list of APIs is: + +* assert.array +* assert.bool +* assert.buffer +* assert.func +* assert.number +* assert.object +* assert.string +* assert.stream +* assert.date +* assert.regex +* assert.uuid +* assert.arrayOfArray +* assert.arrayOfBool +* assert.arrayOfBuffer +* assert.arrayOfFunc +* assert.arrayOfNumber +* assert.arrayOfObject +* assert.arrayOfString +* assert.arrayOfStream +* assert.arrayOfDate +* assert.arrayOfUuid +* assert.optionalArray +* assert.optionalBool +* assert.optionalBuffer +* assert.optionalFunc +* assert.optionalNumber +* assert.optionalObject +* assert.optionalString +* assert.optionalStream +* assert.optionalDate +* assert.optionalUuid +* assert.optionalArrayOfArray +* assert.optionalArrayOfBool +* assert.optionalArrayOfBuffer +* assert.optionalArrayOfFunc +* assert.optionalArrayOfNumber +* assert.optionalArrayOfObject +* assert.optionalArrayOfString +* assert.optionalArrayOfStream +* assert.optionalArrayOfDate +* assert.optionalArrayOfUuid +* assert.AssertionError +* assert.fail +* assert.ok +* assert.equal +* assert.notEqual +* assert.deepEqual +* assert.notDeepEqual +* assert.strictEqual +* assert.notStrictEqual +* assert.throws +* assert.doesNotThrow +* assert.ifError + +# Installation + + npm install assert-plus + +## License + +The MIT License (MIT) +Copyright (c) 2012 Mark Cavage + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +## Bugs + +See . diff --git a/hm_sunwell/node_modules/assert-plus/assert.js b/hm_sunwell/node_modules/assert-plus/assert.js new file mode 100644 index 0000000..6bce4d8 --- /dev/null +++ b/hm_sunwell/node_modules/assert-plus/assert.js @@ -0,0 +1,206 @@ +// Copyright (c) 2012, Mark Cavage. All rights reserved. +// Copyright 2015 Joyent, Inc. + +var assert = require('assert'); +var Stream = require('stream').Stream; +var util = require('util'); + + +///--- Globals + +/* JSSTYLED */ +var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/; + + +///--- Internal + +function _capitalize(str) { + return (str.charAt(0).toUpperCase() + str.slice(1)); +} + +function _toss(name, expected, oper, arg, actual) { + throw new assert.AssertionError({ + message: util.format('%s (%s) is required', name, expected), + actual: (actual === undefined) ? typeof (arg) : actual(arg), + expected: expected, + operator: oper || '===', + stackStartFunction: _toss.caller + }); +} + +function _getClass(arg) { + return (Object.prototype.toString.call(arg).slice(8, -1)); +} + +function noop() { + // Why even bother with asserts? +} + + +///--- Exports + +var types = { + bool: { + check: function (arg) { return typeof (arg) === 'boolean'; } + }, + func: { + check: function (arg) { return typeof (arg) === 'function'; } + }, + string: { + check: function (arg) { return typeof (arg) === 'string'; } + }, + object: { + check: function (arg) { + return typeof (arg) === 'object' && arg !== null; + } + }, + number: { + check: function (arg) { + return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg); + } + }, + buffer: { + check: function (arg) { return Buffer.isBuffer(arg); }, + operator: 'Buffer.isBuffer' + }, + array: { + check: function (arg) { return Array.isArray(arg); }, + operator: 'Array.isArray' + }, + stream: { + check: function (arg) { return arg instanceof Stream; }, + operator: 'instanceof', + actual: _getClass + }, + date: { + check: function (arg) { return arg instanceof Date; }, + operator: 'instanceof', + actual: _getClass + }, + regexp: { + check: function (arg) { return arg instanceof RegExp; }, + operator: 'instanceof', + actual: _getClass + }, + uuid: { + check: function (arg) { + return typeof (arg) === 'string' && UUID_REGEXP.test(arg); + }, + operator: 'isUUID' + } +}; + +function _setExports(ndebug) { + var keys = Object.keys(types); + var out; + + /* re-export standard assert */ + if (process.env.NODE_NDEBUG) { + out = noop; + } else { + out = function (arg, msg) { + if (!arg) { + _toss(msg, 'true', arg); + } + }; + } + + /* standard checks */ + keys.forEach(function (k) { + if (ndebug) { + out[k] = noop; + return; + } + var type = types[k]; + out[k] = function (arg, msg) { + if (!type.check(arg)) { + _toss(msg, k, type.operator, arg, type.actual); + } + }; + }); + + /* optional checks */ + keys.forEach(function (k) { + var name = 'optional' + _capitalize(k); + if (ndebug) { + out[name] = noop; + return; + } + var type = types[k]; + out[name] = function (arg, msg) { + if (arg === undefined || arg === null) { + return; + } + if (!type.check(arg)) { + _toss(msg, k, type.operator, arg, type.actual); + } + }; + }); + + /* arrayOf checks */ + keys.forEach(function (k) { + var name = 'arrayOf' + _capitalize(k); + if (ndebug) { + out[name] = noop; + return; + } + var type = types[k]; + var expected = '[' + k + ']'; + out[name] = function (arg, msg) { + if (!Array.isArray(arg)) { + _toss(msg, expected, type.operator, arg, type.actual); + } + var i; + for (i = 0; i < arg.length; i++) { + if (!type.check(arg[i])) { + _toss(msg, expected, type.operator, arg, type.actual); + } + } + }; + }); + + /* optionalArrayOf checks */ + keys.forEach(function (k) { + var name = 'optionalArrayOf' + _capitalize(k); + if (ndebug) { + out[name] = noop; + return; + } + var type = types[k]; + var expected = '[' + k + ']'; + out[name] = function (arg, msg) { + if (arg === undefined || arg === null) { + return; + } + if (!Array.isArray(arg)) { + _toss(msg, expected, type.operator, arg, type.actual); + } + var i; + for (i = 0; i < arg.length; i++) { + if (!type.check(arg[i])) { + _toss(msg, expected, type.operator, arg, type.actual); + } + } + }; + }); + + /* re-export built-in assertions */ + Object.keys(assert).forEach(function (k) { + if (k === 'AssertionError') { + out[k] = assert[k]; + return; + } + if (ndebug) { + out[k] = noop; + return; + } + out[k] = assert[k]; + }); + + /* export ourselves (for unit tests _only_) */ + out._setExports = _setExports; + + return out; +} + +module.exports = _setExports(process.env.NODE_NDEBUG); diff --git a/hm_sunwell/node_modules/assert-plus/package.json b/hm_sunwell/node_modules/assert-plus/package.json new file mode 100644 index 0000000..e0b327c --- /dev/null +++ b/hm_sunwell/node_modules/assert-plus/package.json @@ -0,0 +1,107 @@ +{ + "_args": [ + [ + "assert-plus@^0.2.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/http-signature" + ] + ], + "_from": "assert-plus@>=0.2.0 <0.3.0", + "_id": "assert-plus@0.2.0", + "_inCache": true, + "_installable": true, + "_location": "/assert-plus", + "_nodeVersion": "0.10.36", + "_npmUser": { + "email": "patrick.f.mooney@gmail.com", + "name": "pfmooney" + }, + "_npmVersion": "3.3.8", + "_phantomChildren": {}, + "_requested": { + "name": "assert-plus", + "raw": "assert-plus@^0.2.0", + "rawSpec": "^0.2.0", + "scope": null, + "spec": ">=0.2.0 <0.3.0", + "type": "range" + }, + "_requiredBy": [ + "/http-signature" + ], + "_resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "_shasum": "d74e1b87e7affc0db8aadb7021f3fe48101ab234", + "_shrinkwrap": null, + "_spec": "assert-plus@^0.2.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/http-signature", + "author": { + "email": "mcavage@gmail.com", + "name": "Mark Cavage" + }, + "bugs": { + "url": "https://github.com/mcavage/node-assert-plus/issues" + }, + "contributors": [ + { + "name": "Dave Eddy", + "email": "dave@daveeddy.com" + }, + { + "name": "Fred Kuo", + "email": "fred.kuo@joyent.com" + }, + { + "name": "Lars-Magnus Skog", + "email": "ralphtheninja@riseup.net" + }, + { + "name": "Mark Cavage", + "email": "mcavage@gmail.com" + }, + { + "name": "Patrick Mooney", + "email": "pmooney@pfmooney.com" + }, + { + "name": "Rob Gulewich", + "email": "robert.gulewich@joyent.com" + } + ], + "dependencies": {}, + "description": "Extra assertions on top of node's assert module", + "devDependencies": { + "faucet": "0.0.1", + "tape": "4.2.2" + }, + "directories": {}, + "dist": { + "shasum": "d74e1b87e7affc0db8aadb7021f3fe48101ab234", + "tarball": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" + }, + "engines": { + "node": ">=0.8" + }, + "homepage": "https://github.com/mcavage/node-assert-plus#readme", + "license": "MIT", + "main": "./assert.js", + "maintainers": [ + { + "name": "mcavage", + "email": "mcavage@gmail.com" + }, + { + "name": "pfmooney", + "email": "patrick.f.mooney@gmail.com" + } + ], + "name": "assert-plus", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/mcavage/node-assert-plus.git" + }, + "scripts": { + "test": "tape tests/*.js | ./node_modules/.bin/faucet" + }, + "version": "0.2.0" +} diff --git a/hm_sunwell/node_modules/assertion-error/.npmignore b/hm_sunwell/node_modules/assertion-error/.npmignore new file mode 100644 index 0000000..f105953 --- /dev/null +++ b/hm_sunwell/node_modules/assertion-error/.npmignore @@ -0,0 +1,11 @@ +docs/ +test/ +build/ +components/ +support/ +coverage.html +component.json +lib-cov +.travis.yml +Makefile +*.swp diff --git a/hm_sunwell/node_modules/assertion-error/History.md b/hm_sunwell/node_modules/assertion-error/History.md new file mode 100644 index 0000000..7285b55 --- /dev/null +++ b/hm_sunwell/node_modules/assertion-error/History.md @@ -0,0 +1,19 @@ +1.0.1 / 2015-03-04 +================== + + * Merge pull request #2 from simonzack/master + * fixes `.stack` on firefox + +1.0.0 / 2013-06-08 +================== + + * readme: change travis and component urls + * refactor: [*] prepare for move to chaijs gh org + +0.1.0 / 2013-04-07 +================== + + * test: use vanilla test runner/assert + * pgk: remove unused deps + * lib: implement + * "Initial commit" diff --git a/hm_sunwell/node_modules/assertion-error/README.md b/hm_sunwell/node_modules/assertion-error/README.md new file mode 100644 index 0000000..6cf03c8 --- /dev/null +++ b/hm_sunwell/node_modules/assertion-error/README.md @@ -0,0 +1,41 @@ +# AssertionError [![Build Status](https://travis-ci.org/chaijs/assertion-error.png?branch=master)](https://travis-ci.org/chaijs/assertion-error) + +> Error constructor for test and validation frameworks that implements standardized AssertionError specification. + +## Installation + +### Node.js + +`assertion-error` is available on [npm](http://npmjs.org). + + $ npm install assertion-error + +### Component + +`assertion-error` is available as a [component](https://github.com/component/component). + + $ component install chaijs/assertion-error + +## License + +(The MIT License) + +Copyright (c) 2013 Jake Luer (http://qualiancy.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/assertion-error/index.js b/hm_sunwell/node_modules/assertion-error/index.js new file mode 100644 index 0000000..5c01747 --- /dev/null +++ b/hm_sunwell/node_modules/assertion-error/index.js @@ -0,0 +1,116 @@ +/*! + * assertion-error + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ + +/*! + * Return a function that will copy properties from + * one object to another excluding any originally + * listed. Returned function will create a new `{}`. + * + * @param {String} excluded properties ... + * @return {Function} + */ + +function exclude () { + var excludes = [].slice.call(arguments); + + function excludeProps (res, obj) { + Object.keys(obj).forEach(function (key) { + if (!~excludes.indexOf(key)) res[key] = obj[key]; + }); + } + + return function extendExclude () { + var args = [].slice.call(arguments) + , i = 0 + , res = {}; + + for (; i < args.length; i++) { + excludeProps(res, args[i]); + } + + return res; + }; +}; + +/*! + * Primary Exports + */ + +module.exports = AssertionError; + +/** + * ### AssertionError + * + * An extension of the JavaScript `Error` constructor for + * assertion and validation scenarios. + * + * @param {String} message + * @param {Object} properties to include (optional) + * @param {callee} start stack function (optional) + */ + +function AssertionError (message, _props, ssf) { + var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON') + , props = extend(_props || {}); + + // default values + this.message = message || 'Unspecified AssertionError'; + this.showDiff = false; + + // copy from properties + for (var key in props) { + this[key] = props[key]; + } + + // capture stack trace + ssf = ssf || arguments.callee; + if (ssf && Error.captureStackTrace) { + Error.captureStackTrace(this, ssf); + } else { + try { + throw new Error(); + } catch(e) { + this.stack = e.stack; + } + } +} + +/*! + * Inherit from Error.prototype + */ + +AssertionError.prototype = Object.create(Error.prototype); + +/*! + * Statically set name + */ + +AssertionError.prototype.name = 'AssertionError'; + +/*! + * Ensure correct constructor + */ + +AssertionError.prototype.constructor = AssertionError; + +/** + * Allow errors to be converted to JSON for static transfer. + * + * @param {Boolean} include stack (default: `true`) + * @return {Object} object that can be `JSON.stringify` + */ + +AssertionError.prototype.toJSON = function (stack) { + var extend = exclude('constructor', 'toJSON', 'stack') + , props = extend({ name: this.name }, this); + + // include stack if exists and not turned off + if (false !== stack && this.stack) { + props.stack = this.stack; + } + + return props; +}; diff --git a/hm_sunwell/node_modules/assertion-error/package.json b/hm_sunwell/node_modules/assertion-error/package.json new file mode 100644 index 0000000..7ce89c2 --- /dev/null +++ b/hm_sunwell/node_modules/assertion-error/package.json @@ -0,0 +1,87 @@ +{ + "_args": [ + [ + "assertion-error@^1.0.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/chai" + ] + ], + "_from": "assertion-error@>=1.0.1 <2.0.0", + "_id": "assertion-error@1.0.2", + "_inCache": true, + "_installable": true, + "_location": "/assertion-error", + "_nodeVersion": "5.7.0", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/assertion-error-1.0.2.tgz_1465237527264_0.8082898685242981" + }, + "_npmUser": { + "email": "chaijs@keithcirkel.co.uk", + "name": "chaijs" + }, + "_npmVersion": "3.8.9", + "_phantomChildren": {}, + "_requested": { + "name": "assertion-error", + "raw": "assertion-error@^1.0.1", + "rawSpec": "^1.0.1", + "scope": null, + "spec": ">=1.0.1 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/chai" + ], + "_resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "_shasum": "13ca515d86206da0bac66e834dd397d87581094c", + "_shrinkwrap": null, + "_spec": "assertion-error@^1.0.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/chai", + "author": { + "email": "jake@qualiancy.com", + "name": "Jake Luer", + "url": "http://qualiancy.com" + }, + "bugs": { + "url": "https://github.com/chaijs/assertion-error/issues" + }, + "dependencies": {}, + "description": "Error constructor for test and validation frameworks that implements standardized AssertionError specification.", + "devDependencies": { + "component": "*" + }, + "directories": {}, + "dist": { + "shasum": "13ca515d86206da0bac66e834dd397d87581094c", + "tarball": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz" + }, + "engines": { + "node": "*" + }, + "gitHead": "b36f593951c1487fa33747c9911025734923f28c", + "homepage": "https://github.com/chaijs/assertion-error#readme", + "keywords": [ + "assertion", + "assertion-error", + "test" + ], + "license": "MIT", + "main": "./index", + "maintainers": [ + { + "name": "chaijs", + "email": "chaijs@keithcirkel.co.uk" + } + ], + "name": "assertion-error", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/chaijs/assertion-error.git" + }, + "scripts": { + "test": "make test" + }, + "version": "1.0.2" +} diff --git a/hm_sunwell/node_modules/async/CHANGELOG.md b/hm_sunwell/node_modules/async/CHANGELOG.md new file mode 100644 index 0000000..f15e081 --- /dev/null +++ b/hm_sunwell/node_modules/async/CHANGELOG.md @@ -0,0 +1,125 @@ +# v1.5.2 +- Allow using `"consructor"` as an argument in `memoize` (#998) +- Give a better error messsage when `auto` dependency checking fails (#994) +- Various doc updates (#936, #956, #979, #1002) + +# v1.5.1 +- Fix issue with `pause` in `queue` with concurrency enabled (#946) +- `while` and `until` now pass the final result to callback (#963) +- `auto` will properly handle concurrency when there is no callback (#966) +- `auto` will now properly stop execution when an error occurs (#988, #993) +- Various doc fixes (#971, #980) + +# v1.5.0 + +- Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) (#892) +- `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. (#873) +- `auto` now accepts an optional `concurrency` argument to limit the number of running tasks (#637) +- Added `queue#workersList()`, to retrieve the list of currently running tasks. (#891) +- Various code simplifications (#896, #904) +- Various doc fixes :scroll: (#890, #894, #903, #905, #912) + +# v1.4.2 + +- Ensure coverage files don't get published on npm (#879) + +# v1.4.1 + +- Add in overlooked `detectLimit` method (#866) +- Removed unnecessary files from npm releases (#861) +- Removed usage of a reserved word to prevent :boom: in older environments (#870) + +# v1.4.0 + +- `asyncify` now supports promises (#840) +- Added `Limit` versions of `filter` and `reject` (#836) +- Add `Limit` versions of `detect`, `some` and `every` (#828, #829) +- `some`, `every` and `detect` now short circuit early (#828, #829) +- Improve detection of the global object (#804), enabling use in WebWorkers +- `whilst` now called with arguments from iterator (#823) +- `during` now gets called with arguments from iterator (#824) +- Code simplifications and optimizations aplenty ([diff](https://github.com/caolan/async/compare/v1.3.0...v1.4.0)) + + +# v1.3.0 + +New Features: +- Added `constant` +- Added `asyncify`/`wrapSync` for making sync functions work with callbacks. (#671, #806) +- Added `during` and `doDuring`, which are like `whilst` with an async truth test. (#800) +- `retry` now accepts an `interval` parameter to specify a delay between retries. (#793) +- `async` should work better in Web Workers due to better `root` detection (#804) +- Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` (#642) +- Various internal updates (#786, #801, #802, #803) +- Various doc fixes (#790, #794) + +Bug Fixes: +- `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. (#740, #744, #783) + + +# v1.2.1 + +Bug Fix: + +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) + + +# v1.2.0 + +New Features: + +- Added `timesLimit` (#743) +- `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. (#747, #772) + +Bug Fixes: + +- Fixed a regression in `each` and family with empty arrays that have additional properties. (#775, #777) + + +# v1.1.1 + +Bug Fix: + +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) + + +# v1.1.0 + +New Features: + +- `cargo` now supports all of the same methods and event callbacks as `queue`. +- Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. (#769) +- Optimized `map`, `eachOf`, and `waterfall` families of functions +- Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array (#667). +- The callback is now optional for the composed results of `compose` and `seq`. (#618) +- Reduced file size by 4kb, (minified version by 1kb) +- Added code coverage through `nyc` and `coveralls` (#768) + +Bug Fixes: + +- `forever` will no longer stack overflow with a synchronous iterator (#622) +- `eachLimit` and other limit functions will stop iterating once an error occurs (#754) +- Always pass `null` in callbacks when there is no error (#439) +- Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue (#668) +- `each` and family will properly handle an empty array (#578) +- `eachSeries` and family will finish if the underlying array is modified during execution (#557) +- `queue` will throw if a non-function is passed to `q.push()` (#593) +- Doc fixes (#629, #766) + + +# v1.0.0 + +No known breaking changes, we are simply complying with semver from here on out. + +Changes: + +- Start using a changelog! +- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) (#168 #704 #321) +- Detect deadlocks in `auto` (#663) +- Better support for require.js (#527) +- Throw if queue created with concurrency `0` (#714) +- Fix unneeded iteration in `queue.resume()` (#758) +- Guard against timer mocking overriding `setImmediate` (#609 #611) +- Miscellaneous doc fixes (#542 #596 #615 #628 #631 #690 #729) +- Use single noop function internally (#546) +- Optimize internal `_each`, `_map` and `_keys` functions. diff --git a/hm_sunwell/node_modules/async/LICENSE b/hm_sunwell/node_modules/async/LICENSE new file mode 100644 index 0000000..8f29698 --- /dev/null +++ b/hm_sunwell/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2014 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/async/README.md b/hm_sunwell/node_modules/async/README.md new file mode 100644 index 0000000..316c405 --- /dev/null +++ b/hm_sunwell/node_modules/async/README.md @@ -0,0 +1,1877 @@ +# Async.js + +[![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async) +[![NPM version](http://img.shields.io/npm/v/async.svg)](https://www.npmjs.org/package/async) +[![Coverage Status](https://coveralls.io/repos/caolan/async/badge.svg?branch=master)](https://coveralls.io/r/caolan/async?branch=master) +[![Join the chat at https://gitter.im/caolan/async](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/caolan/async?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [Node.js](http://nodejs.org) and installable via `npm install async`, +it can also be used directly in the browser. + +Async is also installable via: + +- [bower](http://bower.io/): `bower install async` +- [component](https://github.com/component/component): `component install + caolan/async` +- [jam](http://jamjs.org/): `jam install async` +- [spm](http://spmjs.io/): `spm install async` + +Async provides around 20 functions that include the usual 'functional' +suspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns +for asynchronous control flow (`parallel`, `series`, `waterfall`…). All these +functions assume you follow the Node.js convention of providing a single +callback as the last argument of your `async` function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls [(StackOverflow)](http://stackoverflow.com/questions/tagged/async.js) +### Synchronous iteration functions + +If you get an error like `RangeError: Maximum call stack size exceeded.` or other stack overflow issues when using async, you are likely using a synchronous iterator. By *synchronous* we mean a function that calls its callback on the same tick in the javascript event loop, without doing any I/O or using any timers. Calling many callbacks iteratively will quickly overflow the stack. If you run into this issue, just defer your callback with `async.setImmediate` to start a new call stack on the next tick of the event loop. + +This can also arise by accident if you callback early in certain cases: + +```js +async.eachSeries(hugeArray, function iterator(item, callback) { + if (inCache(item)) { + callback(null, cache[item]); // if many items are cached, you'll overflow + } else { + doSomeIO(item, callback); + } +}, function done() { + //... +}); +``` + +Just change it to: + +```js +async.eachSeries(hugeArray, function iterator(item, callback) { + if (inCache(item)) { + async.setImmediate(function () { + callback(null, cache[item]); + }); + } else { + doSomeIO(item, callback); + //... +``` + +Async guards against synchronous functions in some, but not all, cases. If you are still running into stack overflows, you can defer as suggested above, or wrap functions with [`async.ensureAsync`](#ensureAsync) Functions that are asynchronous by their nature do not have this problem and don't need the extra callback deferral. + +If JavaScript's event loop is still a bit nebulous, check out [this article](http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/) or [this talk](http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html) for more detailed information about how it works. + + +### Multiple callbacks + +Make sure to always `return` when calling a callback early, otherwise you will cause multiple callbacks and unpredictable behavior in many cases. + +```js +async.waterfall([ + function (callback) { + getSomething(options, function (err, result) { + if (err) { + callback(new Error("failed getting something:" + err.message)); + // we should return here + } + // since we did not return, this callback still will be called and + // `processData` will be called twice + callback(null, result); + }); + }, + processData +], done) +``` + +It is always good practice to `return callback(err, result)` whenever a callback call is not the last statement of a function. + + +### Binding a context to an iterator + +This section is really about `bind`, not about `async`. If you are wondering how to +make `async` execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](https://github.com/caolan/async/blob/master/lib/async.js). +Alternatively, you can install using Node Package Manager (`npm`): + + npm install async + +As well as using Bower: + + bower install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. + +Usage: + +```html + + +``` + +## Documentation + +Some functions are also available in the following forms: +* `Series` - the same as `` but runs only a single async operation at a time +* `Limit` - the same as `` but runs a maximum of `limit` async operations at a time + +### Collections + +* [`each`](#each), `eachSeries`, `eachLimit` +* [`forEachOf`](#forEachOf), `forEachOfSeries`, `forEachOfLimit` +* [`map`](#map), `mapSeries`, `mapLimit` +* [`filter`](#filter), `filterSeries`, `filterLimit` +* [`reject`](#reject), `rejectSeries`, `rejectLimit` +* [`reduce`](#reduce), [`reduceRight`](#reduceRight) +* [`detect`](#detect), `detectSeries`, `detectLimit` +* [`sortBy`](#sortBy) +* [`some`](#some), `someLimit` +* [`every`](#every), `everyLimit` +* [`concat`](#concat), `concatSeries` + +### Control Flow + +* [`series`](#seriestasks-callback) +* [`parallel`](#parallel), `parallelLimit` +* [`whilst`](#whilst), [`doWhilst`](#doWhilst) +* [`until`](#until), [`doUntil`](#doUntil) +* [`during`](#during), [`doDuring`](#doDuring) +* [`forever`](#forever) +* [`waterfall`](#waterfall) +* [`compose`](#compose) +* [`seq`](#seq) +* [`applyEach`](#applyEach), `applyEachSeries` +* [`queue`](#queue), [`priorityQueue`](#priorityQueue) +* [`cargo`](#cargo) +* [`auto`](#auto) +* [`retry`](#retry) +* [`iterator`](#iterator) +* [`times`](#times), `timesSeries`, `timesLimit` + +### Utils + +* [`apply`](#apply) +* [`nextTick`](#nextTick) +* [`memoize`](#memoize) +* [`unmemoize`](#unmemoize) +* [`ensureAsync`](#ensureAsync) +* [`constant`](#constant) +* [`asyncify`](#asyncify) +* [`wrapSync`](#wrapSync) +* [`log`](#log) +* [`dir`](#dir) +* [`noConflict`](#noConflict) + +## Collections + + + +### each(arr, iterator, [callback]) + +Applies the function `iterator` to each item in `arr`, in parallel. +The `iterator` is called with an item from the list, and a callback for when it +has finished. If the `iterator` passes an error to its `callback`, the main +`callback` (for the `each` function) is immediately called with the error. + +Note, that since this function applies `iterator` to each item in parallel, +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err)` which must be called once it has + completed. If no error has occurred, the `callback` should be run without + arguments or with an explicit `null` argument. The array index is not passed + to the iterator. If you need the index, use [`forEachOf`](#forEachOf). +* `callback(err)` - *Optional* A callback which is called when all `iterator` functions + have finished, or an error occurs. + +__Examples__ + + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +```js +// assuming openFiles is an array of file names + +async.each(openFiles, function(file, callback) { + + // Perform operation on file here. + console.log('Processing file ' + file); + + if( file.length > 32 ) { + console.log('This file name is too long'); + callback('File name too long'); + } else { + // Do work to process file here + console.log('File processed'); + callback(); + } +}, function(err){ + // if any of the file processing produced an error, err would equal that error + if( err ) { + // One of the iterations produced an error. + // All processing will now stop. + console.log('A file failed to process'); + } else { + console.log('All files have been processed successfully'); + } +}); +``` + +__Related__ + +* eachSeries(arr, iterator, [callback]) +* eachLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + + + + +### forEachOf(obj, iterator, [callback]) + +Like `each`, except that it iterates over objects, and passes the key as the second argument to the iterator. + +__Arguments__ + +* `obj` - An object or array to iterate over. +* `iterator(item, key, callback)` - A function to apply to each item in `obj`. +The `key` is the item's key, or index in the case of an array. The iterator is +passed a `callback(err)` which must be called once it has completed. If no +error has occurred, the callback should be run without arguments or with an +explicit `null` argument. +* `callback(err)` - *Optional* A callback which is called when all `iterator` functions have finished, or an error occurs. + +__Example__ + +```js +var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"}; +var configs = {}; + +async.forEachOf(obj, function (value, key, callback) { + fs.readFile(__dirname + value, "utf8", function (err, data) { + if (err) return callback(err); + try { + configs[key] = JSON.parse(data); + } catch (e) { + return callback(e); + } + callback(); + }) +}, function (err) { + if (err) console.error(err.message); + // configs is now a map of JSON data + doSomethingWith(configs); +}) +``` + +__Related__ + +* forEachOfSeries(obj, iterator, [callback]) +* forEachOfLimit(obj, limit, iterator, [callback]) + +--------------------------------------- + + +### map(arr, iterator, [callback]) + +Produces a new array of values by mapping each value in `arr` through +the `iterator` function. The `iterator` is called with an item from `arr` and a +callback for when it has finished processing. Each of these callback takes 2 arguments: +an `error`, and the transformed item from `arr`. If `iterator` passes an error to its +callback, the main `callback` (for the `map` function) is immediately called with the error. + +Note, that since this function applies the `iterator` to each item in parallel, +there is no guarantee that the `iterator` functions will complete in order. +However, the results array will be in the same order as the original `arr`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, transformed)` which must be called once + it has completed with an error (which can be `null`) and a transformed item. +* `callback(err, results)` - *Optional* A callback which is called when all `iterator` + functions have finished, or an error occurs. Results is an array of the + transformed items from the `arr`. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +__Related__ +* mapSeries(arr, iterator, [callback]) +* mapLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + + + +### filter(arr, iterator, [callback]) + +__Alias:__ `select` + +Returns a new array of all the values in `arr` which pass an async truth test. +_The callback for each `iterator` call only accepts a single argument of `true` or +`false`; it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like `fs.exists`. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in `arr`. + The `iterator` is passed a `callback(truthValue)`, which must be called with a + boolean argument once it has completed. +* `callback(results)` - *Optional* A callback which is called after all the `iterator` + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +__Related__ + +* filterSeries(arr, iterator, [callback]) +* filterLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + + +### reject(arr, iterator, [callback]) + +The opposite of [`filter`](#filter). Removes values that pass an `async` truth test. + +__Related__ + +* rejectSeries(arr, iterator, [callback]) +* rejectLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + + +### reduce(arr, memo, iterator, [callback]) + +__Aliases:__ `inject`, `foldl` + +Reduces `arr` into a single value using an async `iterator` to return +each successive step. `memo` is the initial state of the reduction. +This function only operates in series. + +For performance reasons, it may make sense to split a call to this function into +a parallel map, and then use the normal `Array.prototype.reduce` on the results. +This function is for situations where each step in the reduction needs to be async; +if you can get the data before reducing it, then it's probably a good idea to do so. + +__Arguments__ + +* `arr` - An array to iterate over. +* `memo` - The initial state of the reduction. +* `iterator(memo, item, callback)` - A function applied to each item in the + array to produce the next step in the reduction. The `iterator` is passed a + `callback(err, reduction)` which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main `callback` is + immediately called with the error. +* `callback(err, result)` - *Optional* A callback which is called after all the `iterator` + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, [callback]) + +__Alias:__ `foldr` + +Same as [`reduce`](#reduce), only operates on `arr` in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, [callback]) + +Returns the first value in `arr` that passes an async truth test. The +`iterator` is applied in parallel, meaning the first iterator to return `true` will +fire the detect `callback` with that result. That means the result might not be +the first item in the original `arr` (in terms of order) that passes the test. + +If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries). + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in `arr`. + The iterator is passed a `callback(truthValue)` which must be called with a + boolean argument once it has completed. **Note: this callback does not take an error as its first argument.** +* `callback(result)` - *Optional* A callback which is called as soon as any iterator returns + `true`, or after all the `iterator` functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value `undefined` if none passed. **Note: this callback does not take an error as its first argument.** + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +__Related__ + +* detectSeries(arr, iterator, [callback]) +* detectLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + + +### sortBy(arr, iterator, [callback]) + +Sorts a list by the results of running each `arr` value through an async `iterator`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, sortValue)` which must be called once it + has completed with an error (which can be `null`) and a value to use as the sort + criteria. +* `callback(err, results)` - *Optional* A callback which is called after all the `iterator` + functions have finished, or an error occurs. Results is the items from + the original `arr` sorted by the values returned by the `iterator` calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +__Sort Order__ + +By modifying the callback parameter the sorting order can be influenced: + +```js +//ascending order +async.sortBy([1,9,3,5], function(x, callback){ + callback(null, x); +}, function(err,result){ + //result callback +} ); + +//descending order +async.sortBy([1,9,3,5], function(x, callback){ + callback(null, x*-1); //<- x*-1 instead of x, turns the order around +}, function(err,result){ + //result callback +} ); +``` + +--------------------------------------- + + +### some(arr, iterator, [callback]) + +__Alias:__ `any` + +Returns `true` if at least one element in the `arr` satisfies an async test. +_The callback for each iterator call only accepts a single argument of `true` or +`false`; it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like `fs.exists`. Once any iterator +call returns `true`, the main `callback` is immediately called. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in the array + in parallel. The iterator is passed a `callback(truthValue)`` which must be + called with a boolean argument once it has completed. +* `callback(result)` - *Optional* A callback which is called as soon as any iterator returns + `true`, or after all the iterator functions have finished. Result will be + either `true` or `false` depending on the values of the async tests. + + **Note: the callbacks do not take an error as their first argument.** +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +__Related__ + +* someLimit(arr, limit, iterator, callback) + +--------------------------------------- + + +### every(arr, iterator, [callback]) + +__Alias:__ `all` + +Returns `true` if every element in `arr` satisfies an async test. +_The callback for each `iterator` call only accepts a single argument of `true` or +`false`; it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like `fs.exists`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in the array + in parallel. The iterator is passed a `callback(truthValue)` which must be + called with a boolean argument once it has completed. +* `callback(result)` - *Optional* A callback which is called as soon as any iterator returns + `false`, or after all the iterator functions have finished. Result will be + either `true` or `false` depending on the values of the async tests. + + **Note: the callbacks do not take an error as their first argument.** + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +__Related__ + +* everyLimit(arr, limit, iterator, callback) + +--------------------------------------- + + +### concat(arr, iterator, [callback]) + +Applies `iterator` to each item in `arr`, concatenating the results. Returns the +concatenated list. The `iterator`s are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of `arr` passed to the `iterator` function. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, results)` which must be called once it + has completed with an error (which can be `null`) and an array of results. +* `callback(err, results)` - *Optional* A callback which is called after all the `iterator` + functions have finished, or an error occurs. Results is an array containing + the concatenated results of the `iterator` function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +__Related__ + +* concatSeries(arr, iterator, [callback]) + + +## Control Flow + + +### series(tasks, [callback]) + +Run the functions in the `tasks` array in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run, and `callback` is immediately called with the value of the error. +Otherwise, `callback` receives an array of results when `tasks` have completed. + +It is also possible to use an object instead of an array. Each property will be +run as a function, and the results will be passed to the final `callback` as an object +instead of an array. This can be a more readable way of handling results from +[`series`](#series). + +**Note** that while many implementations preserve the order of object properties, the +[ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) +explicitly states that + +> The mechanics and order of enumerating the properties is not specified. + +So if you rely on the order in which your series of functions are executed, and want +this to work on all platforms, consider using an array. + +__Arguments__ + +* `tasks` - An array or object containing functions to run, each function is passed + a `callback(err, result)` it must call on completion with an error `err` (which can + be `null`) and an optional `result` value. +* `callback(err, results)` - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the `task` callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run the `tasks` array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main `callback` is immediately called with the value of the error. +Once the `tasks` have completed, the results are passed to the final `callback` as an +array. + +**Note:** `parallel` is about kicking-off I/O tasks in parallel, not about parallel execution of code. If your tasks do not use any timers or perform any I/O, they will actually be executed in series. Any synchronous setup sections for each task will happen one after the other. JavaScript remains single-threaded. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final `callback` as an object +instead of an array. This can be a more readable way of handling results from +[`parallel`](#parallel). + + +__Arguments__ + +* `tasks` - An array or object containing functions to run. Each function is passed + a `callback(err, result)` which it must call on completion with an error `err` + (which can be `null`) and an optional `result` value. +* `callback(err, results)` - An optional callback to run once all the functions + have completed successfully. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +__Related__ + +* parallelLimit(tasks, limit, [callback]) + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped, +or an error occurs. + +__Arguments__ + +* `test()` - synchronous truth test to perform before each execution of `fn`. +* `fn(callback)` - A function which is called each time `test` passes. The function is + passed a `callback(err)`, which must be called once it has completed with an + optional `err` argument. +* `callback(err, [results])` - A callback which is called after the test + function has failed and repeated execution of `fn` has stopped. `callback` + will be passed an error and any arguments passed to the final `fn`'s callback. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(function () { + callback(null, count); + }, 1000); + }, + function (err, n) { + // 5 seconds have passed, n = 5 + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post-check version of [`whilst`](#whilst). To reflect the difference in +the order of operations, the arguments `test` and `fn` are switched. + +`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped, +or an error occurs. `callback` will be passed an error and any arguments passed +to the final `fn`'s callback. + +The inverse of [`whilst`](#whilst). + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### during(test, fn, callback) + +Like [`whilst`](#whilst), except the `test` is an asynchronous function that is passed a callback in the form of `function (err, truth)`. If error is passed to `test` or `fn`, the main callback is immediately called with the value of the error. + +__Example__ + +```js +var count = 0; + +async.during( + function (callback) { + return callback(null, count < 5); + }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doDuring(fn, test, callback) + +The post-check version of [`during`](#during). To reflect the difference in +the order of operations, the arguments `test` and `fn` are switched. + +Also a version of [`doWhilst`](#doWhilst) with asynchronous `test` function. + +--------------------------------------- + + +### forever(fn, [errback]) + +Calls the asynchronous function `fn` with a callback parameter that allows it to +call itself again, in series, indefinitely. + +If an error is passed to the callback then `errback` is called with the +error, and execution stops, otherwise it will never be called. + +```js +async.forever( + function(next) { + // next is suitable for passing to things that need a callback(err [, whatever]); + // it will result in this function being called again. + }, + function(err) { + // if next is called with a value in its first parameter, it will appear + // in here as 'err', and execution will stop. + } +); +``` + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs the `tasks` array of functions in series, each passing their results to the next in +the array. However, if any of the `tasks` pass an error to their own callback, the +next function is not executed, and the main `callback` is immediately called with +the error. + +__Arguments__ + +* `tasks` - An array of functions to run, each function is passed a + `callback(err, result1, result2, ...)` it must call on completion. The first + argument is an error (which can be `null`) and any further arguments will be + passed as arguments in order to the next task. +* `callback(err, [results])` - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback) { + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); + }, + function(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` +Or, with named functions: + +```js +async.waterfall([ + myFirstFunction, + mySecondFunction, + myLastFunction, +], function (err, result) { + // result now equals 'done' +}); +function myFirstFunction(callback) { + callback(null, 'one', 'two'); +} +function mySecondFunction(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); +} +function myLastFunction(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); +} +``` + +Or, if you need to pass any argument to the first function: + +```js +async.waterfall([ + async.apply(myFirstFunction, 'zero'), + mySecondFunction, + myLastFunction, +], function (err, result) { + // result now equals 'done' +}); +function myFirstFunction(arg1, callback) { + // arg1 now equals 'zero' + callback(null, 'one', 'two'); +} +function mySecondFunction(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); +} +function myLastFunction(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); +} +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions `f()`, `g()`, and `h()` would produce the result of +`f(g(h()))`, only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* `functions...` - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### seq(fn1, fn2...) + +Version of the compose function that is more natural to read. +Each function consumes the return value of the previous function. +It is the equivalent of [`compose`](#compose) with the arguments reversed. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* `functions...` - the asynchronous functions to compose + + +__Example__ + +```js +// Requires lodash (or underscore), express3 and dresende's orm2. +// Part of an app, that fetches cats of the logged user. +// This example uses `seq` function to avoid overnesting and error +// handling clutter. +app.get('/cats', function(request, response) { + var User = request.models.User; + async.seq( + _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data)) + function(user, fn) { + user.getCats(fn); // 'getCats' has signature (callback(err, data)) + } + )(req.session.user_id, function (err, cats) { + if (err) { + console.error(err); + response.json({ status: 'error', message: err.message }); + } else { + response.json({ status: 'ok', message: 'Cats found', data: cats }); + } + }); +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling +`callback` after all functions have completed. If you only provide the first +argument, then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* `fns` - the asynchronous functions to all call with the same arguments +* `args...` - any number of separate arguments to pass to the function +* `callback` - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +__Related__ + +* applyEachSeries(tasks, args..., [callback]) + +--------------------------------------- + + +### queue(worker, [concurrency]) + +Creates a `queue` object with the specified `concurrency`. Tasks added to the +`queue` are processed in parallel (up to the `concurrency` limit). If all +`worker`s are in progress, the task is queued until one becomes available. +Once a `worker` completes a `task`, that `task`'s callback is called. + +__Arguments__ + +* `worker(task, callback)` - An asynchronous function for processing a queued + task, which must call its `callback(err)` argument when finished, with an + optional `error` as an argument. If you want to handle errors from an individual task, pass a callback to `q.push()`. +* `concurrency` - An `integer` for determining how many `worker` functions should be + run in parallel. If omitted, the concurrency defaults to `1`. If the concurrency is `0`, an error is thrown. + +__Queue objects__ + +The `queue` object returned by this function has the following properties and +methods: + +* `length()` - a function returning the number of items waiting to be processed. +* `started` - a function returning whether or not any items have been pushed and processed by the queue +* `running()` - a function returning the number of items currently being processed. +* `workersList()` - a function returning the array of items currently being processed. +* `idle()` - a function returning false if there are items waiting or being processed, or true if not. +* `concurrency` - an integer for determining how many `worker` functions should be + run in parallel. This property can be changed after a `queue` is created to + alter the concurrency on-the-fly. +* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once + the `worker` has finished processing the task. Instead of a single task, a `tasks` array + can be submitted. The respective callback is used for every task in the list. +* `unshift(task, [callback])` - add a new task to the front of the `queue`. +* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, + and further tasks will be queued. +* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`. +* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`. +* `paused` - a boolean for determining whether the queue is in a paused state +* `pause()` - a function that pauses the processing of tasks until `resume()` is called. +* `resume()` - a function that resumes the processing of queued tasks when the queue is paused. +* `kill()` - a function that removes the `drain` callback and empties remaining tasks from the queue forcing it to go idle. + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing item'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + + +--------------------------------------- + + +### priorityQueue(worker, concurrency) + +The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects: + +* `push(task, priority, [callback])` - `priority` should be a number. If an array of + `tasks` is given, all tasks will be assigned the same priority. +* The `unshift` method was removed. + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a `cargo` object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the `payload` limit). If the +`worker` is in progress, the task is queued until it becomes available. Once +the `worker` has completed some tasks, each callback of those tasks is called. +Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) for how `cargo` and `queue` work. + +While [queue](#queue) passes only one task to one of a group of workers +at a time, cargo passes an array of tasks to a single worker, repeating +when the worker is finished. + +__Arguments__ + +* `worker(tasks, callback)` - An asynchronous function for processing an array of + queued tasks, which must call its `callback(err)` argument when finished, with + an optional `err` argument. +* `payload` - An optional `integer` for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The `cargo` object returned by this function has the following properties and +methods: + +* `length()` - A function returning the number of items waiting to be processed. +* `payload` - An `integer` for determining how many tasks should be + process per round. This property can be changed after a `cargo` is created to + alter the payload on-the-fly. +* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called + once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` + can be submitted. The respective callback is used for every task in the list. +* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued. +* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`. +* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`. +* `idle()`, `pause()`, `resume()`, `kill()` - cargo inherits all of the same methods and event calbacks as [`queue`](#queue) + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [concurrency], [callback]) + +Determines the best order for running the functions in `tasks`, based on their requirements. Each function can optionally depend on other functions being completed first, and each function is run as soon as its requirements are satisfied. + +If any of the functions pass an error to their callback, the `auto` sequence will stop. Further tasks will not execute (so any other functions depending on it will not run), and the main `callback` is immediately called with the error. Functions also receive an object containing the results of functions which have completed so far. + +Note, all functions are called with a `results` object as a second argument, +so it is unsafe to pass functions in the `tasks` object which cannot handle the +extra argument. + +For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8') +}, callback); +``` + +will have the effect of calling `readFile` with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to `readFile` in a function which does not forward the +`results` object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* `tasks` - An object. Each of its properties is either a function or an array of + requirements, with the function itself the last item in the array. The object's key + of a property serves as the name of the task defined by that property, + i.e. can be used when specifying requirements for other tasks. + The function receives two arguments: (1) a `callback(err, result)` which must be + called when finished, passing an `error` (which can be `null`) and the result of + the function's execution, and (2) a `results` object, containing the results of + the previously executed functions. +* `concurrency` - An optional `integer` for determining the maximum number of tasks that can be run in parallel. By default, as many as possible. +* `callback(err, results)` - An optional callback which is called when all the + tasks have been completed. It receives the `err` argument if any `tasks` + pass an error to their callback. Results are always returned; however, if + an error occurs, no further `tasks` will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + console.log('in get_data'); + // async code to get some data + callback(null, 'data', 'converted to array'); + }, + make_folder: function(callback){ + console.log('in make_folder'); + // async code to create a directory to store a file in + // this is run at the same time as getting the data + callback(null, 'folder'); + }, + write_file: ['get_data', 'make_folder', function(callback, results){ + console.log('in write_file', JSON.stringify(results)); + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, 'filename'); + }], + email_link: ['write_file', function(callback, results){ + console.log('in email_link', JSON.stringify(results)); + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + callback(null, {'file':results.write_file, 'email':'user@example.com'}); + }] +}, function(err, results) { + console.log('err = ', err); + console.log('results = ', results); +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + console.log('in get_data'); + // async code to get some data + callback(null, 'data', 'converted to array'); + }, + function(callback){ + console.log('in make_folder'); + // async code to create a directory to store a file in + // this is run at the same time as getting the data + callback(null, 'folder'); + } +], +function(err, results){ + async.series([ + function(callback){ + console.log('in write_file', JSON.stringify(results)); + // once there is some data and the directory exists, + // write the data to a file in the directory + results.push('filename'); + callback(null); + }, + function(callback){ + console.log('in email_link', JSON.stringify(results)); + // once the file is written let's email a link to it... + callback(null, {'file':results.pop(), 'email':'user@example.com'}); + } + ]); +}); +``` + +For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding +new tasks much easier (and the code more readable). + + +--------------------------------------- + + +### retry([opts = {times: 5, interval: 0}| 5], task, [callback]) + +Attempts to get a successful response from `task` no more than `times` times before +returning an error. If the task is successful, the `callback` will be passed the result +of the successful task. If all attempts fail, the callback will be passed the error and +result (if any) of the final attempt. + +__Arguments__ + +* `opts` - Can be either an object with `times` and `interval` or a number. + * `times` - The number of attempts to make before giving up. The default is `5`. + * `interval` - The time to wait between retries, in milliseconds. The default is `0`. + * If `opts` is a number, the number specifies the number of times to retry, with the default interval of `0`. +* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)` + which must be called when finished, passing `err` (which can be `null`) and the `result` of + the function's execution, and (2) a `results` object, containing the results of + the previously executed functions (if nested inside another control flow). +* `callback(err, results)` - An optional callback which is called when the + task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`. + +The [`retry`](#retry) function can be used as a stand-alone control flow by passing a callback, as shown below: + +```js +// try calling apiMethod 3 times +async.retry(3, apiMethod, function(err, result) { + // do something with the result +}); +``` + +```js +// try calling apiMethod 3 times, waiting 200 ms between each retry +async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { + // do something with the result +}); +``` + +```js +// try calling apiMethod the default 5 times no delay between each retry +async.retry(apiMethod, function(err, result) { + // do something with the result +}); +``` + +It can also be embedded within other control flow functions to retry individual methods +that are not as reliable, like this: + +```js +async.auto({ + users: api.getUsers.bind(api), + payments: async.retry(3, api.getPayments.bind(api)) +}, function(err, results) { + // do something with the results +}); +``` + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the `tasks` array, +returning a continuation to call the next one after that. It's also possible to +“peek” at the next iterator with `iterator.next()`. + +This function is used internally by the `async` module, but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* `tasks` - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied. + +Useful as a shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* `function` - The function you want to eventually apply all arguments to. +* `arguments...` - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback), setImmediate(callback) + +Calls `callback` on a later loop around the event loop. In Node.js this just +calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)` +if available, otherwise `setTimeout(callback, 0)`, which means other higher priority +events may precede the execution of `callback`. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* `callback` - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, iterator, [callback]) + +Calls the `iterator` function `n` times, and accumulates results in the same manner +you would use with [`map`](#map). + +__Arguments__ + +* `n` - The number of times to run the function. +* `iterator` - The function to call `n` times. +* `callback` - see [`map`](#map) + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + +__Related__ + +* timesSeries(n, iterator, [callback]) +* timesLimit(n, limit, iterator, [callback]) + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an `async` function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +If no hash function is specified, the first argument is used as a hash key, which may work reasonably if it is a string or a data type that converts to a distinct string. Note that objects and arrays will not behave reasonably. Neither will cases where the other arguments are significant. In such cases, specify your own hash function. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* `fn` - The function to proxy and cache results from. +* `hasher` - An optional function for generating a custom hash for storing + results. It has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized +form. Handy for testing. + +__Arguments__ + +* `fn` - the memoized function + +--------------------------------------- + + +### ensureAsync(fn) + +Wrap an async function and ensure it calls its callback on a later tick of the event loop. If the function already calls its callback on a next tick, no extra deferral is added. This is useful for preventing stack overflows (`RangeError: Maximum call stack size exceeded`) and generally keeping [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) contained. + +__Arguments__ + +* `fn` - an async function, one that expects a node-style callback as its last argument + +Returns a wrapped function with the exact same call signature as the function passed in. + +__Example__ + +```js +function sometimesAsync(arg, callback) { + if (cache[arg]) { + return callback(null, cache[arg]); // this would be synchronous!! + } else { + doSomeIO(arg, callback); // this IO would be asynchronous + } +} + +// this has a risk of stack overflows if many results are cached in a row +async.mapSeries(args, sometimesAsync, done); + +// this will defer sometimesAsync's callback if necessary, +// preventing stack overflows +async.mapSeries(args, async.ensureAsync(sometimesAsync), done); + +``` + +--------------------------------------- + + +### constant(values...) + +Returns a function that when called, calls-back with the values provided. Useful as the first function in a `waterfall`, or for plugging values in to `auto`. + +__Example__ + +```js +async.waterfall([ + async.constant(42), + function (value, next) { + // value === 42 + }, + //... +], callback); + +async.waterfall([ + async.constant(filename, "utf8"), + fs.readFile, + function (fileData, next) { + //... + } + //... +], callback); + +async.auto({ + hostname: async.constant("https://server.net/"), + port: findFreePort, + launchServer: ["hostname", "port", function (cb, options) { + startServer(options, cb); + }], + //... +}, callback); + +``` + +--------------------------------------- + + + +### asyncify(func) + +__Alias:__ `wrapSync` + +Take a sync function and make it async, passing its return value to a callback. This is useful for plugging sync functions into a waterfall, series, or other async functions. Any arguments passed to the generated function will be passed to the wrapped function (except for the final callback argument). Errors thrown will be passed to the callback. + +__Example__ + +```js +async.waterfall([ + async.apply(fs.readFile, filename, "utf8"), + async.asyncify(JSON.parse), + function (data, next) { + // data is the result of parsing the text. + // If there was a parsing error, it would have been caught. + } +], callback) +``` + +If the function passed to `asyncify` returns a Promise, that promises's resolved/rejected state will be used to call the callback, rather than simply the synchronous return value. Example: + +```js +async.waterfall([ + async.apply(fs.readFile, filename, "utf8"), + async.asyncify(function (contents) { + return db.model.create(contents); + }), + function (model, next) { + // `model` is the instantiated model object. + // If there was an error, this function would be skipped. + } +], callback) +``` + +This also means you can asyncify ES2016 `async` functions. + +```js +var q = async.queue(async.asyncify(async function (file) { + var intermediateStep = await processFile(file); + return await somePromise(intermediateStep) +})); + +q.push(files); +``` + +--------------------------------------- + + +### log(function, arguments) + +Logs the result of an `async` function to the `console`. Only works in Node.js or +in browsers that support `console.log` and `console.error` (such as FF and Chrome). +If multiple arguments are returned from the async function, `console.log` is +called on each argument in order. + +__Arguments__ + +* `function` - The function you want to eventually apply all arguments to. +* `arguments...` - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an `async` function to the `console` using `console.dir` to +display the properties of the resulting object. Only works in Node.js or +in browsers that support `console.dir` and `console.error` (such as FF and Chrome). +If multiple arguments are returned from the async function, `console.dir` is +called on each argument in order. + +__Arguments__ + +* `function` - The function you want to eventually apply all arguments to. +* `arguments...` - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of `async` back to its original value, returning a reference to the +`async` object. diff --git a/hm_sunwell/node_modules/async/dist/async.js b/hm_sunwell/node_modules/async/dist/async.js new file mode 100644 index 0000000..31e7620 --- /dev/null +++ b/hm_sunwell/node_modules/async/dist/async.js @@ -0,0 +1,1265 @@ +/*! + * async + * https://github.com/caolan/async + * + * Copyright 2010-2014 Caolan McMahon + * Released under the MIT license + */ +(function () { + + var async = {}; + function noop() {} + function identity(v) { + return v; + } + function toBool(v) { + return !!v; + } + function notId(v) { + return !v; + } + + // global on the server, window in the browser + var previous_async; + + // Establish the root object, `window` (`self`) in the browser, `global` + // on the server, or `this` in some virtual machines. We use `self` + // instead of `window` for `WebWorker` support. + var root = typeof self === 'object' && self.self === self && self || + typeof global === 'object' && global.global === global && global || + this; + + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + return function() { + if (fn === null) throw new Error("Callback was already called."); + fn.apply(this, arguments); + fn = null; + }; + } + + function _once(fn) { + return function() { + if (fn === null) return; + fn.apply(this, arguments); + fn = null; + }; + } + + //// cross-browser compatiblity functions //// + + var _toString = Object.prototype.toString; + + var _isArray = Array.isArray || function (obj) { + return _toString.call(obj) === '[object Array]'; + }; + + // Ported from underscore.js isObject + var _isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + function _isArrayLike(arr) { + return _isArray(arr) || ( + // has a positive integer length property + typeof arr.length === "number" && + arr.length >= 0 && + arr.length % 1 === 0 + ); + } + + function _arrayEach(arr, iterator) { + var index = -1, + length = arr.length; + + while (++index < length) { + iterator(arr[index], index, arr); + } + } + + function _map(arr, iterator) { + var index = -1, + length = arr.length, + result = Array(length); + + while (++index < length) { + result[index] = iterator(arr[index], index, arr); + } + return result; + } + + function _range(count) { + return _map(Array(count), function (v, i) { return i; }); + } + + function _reduce(arr, iterator, memo) { + _arrayEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + } + + function _forEachOf(object, iterator) { + _arrayEach(_keys(object), function (key) { + iterator(object[key], key); + }); + } + + function _indexOf(arr, item) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === item) return i; + } + return -1; + } + + var _keys = Object.keys || function (obj) { + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + function _keyIterator(coll) { + var i = -1; + var len; + var keys; + if (_isArrayLike(coll)) { + len = coll.length; + return function next() { + i++; + return i < len ? i : null; + }; + } else { + keys = _keys(coll); + len = keys.length; + return function next() { + i++; + return i < len ? keys[i] : null; + }; + } + } + + // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) + // This accumulates the arguments passed into an array, after a given index. + // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). + function _restParam(func, startIndex) { + startIndex = startIndex == null ? func.length - 1 : +startIndex; + return function() { + var length = Math.max(arguments.length - startIndex, 0); + var rest = Array(length); + for (var index = 0; index < length; index++) { + rest[index] = arguments[index + startIndex]; + } + switch (startIndex) { + case 0: return func.call(this, rest); + case 1: return func.call(this, arguments[0], rest); + } + // Currently unused but handle cases outside of the switch statement: + // var args = Array(startIndex + 1); + // for (index = 0; index < startIndex; index++) { + // args[index] = arguments[index]; + // } + // args[startIndex] = rest; + // return func.apply(this, args); + }; + } + + function _withoutIndex(iterator) { + return function (value, index, callback) { + return iterator(value, callback); + }; + } + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + + // capture the global reference to guard against fakeTimer mocks + var _setImmediate = typeof setImmediate === 'function' && setImmediate; + + var _delay = _setImmediate ? function(fn) { + // not a direct alias for IE10 compatibility + _setImmediate(fn); + } : function(fn) { + setTimeout(fn, 0); + }; + + if (typeof process === 'object' && typeof process.nextTick === 'function') { + async.nextTick = process.nextTick; + } else { + async.nextTick = _delay; + } + async.setImmediate = _setImmediate ? _delay : async.nextTick; + + + async.forEach = + async.each = function (arr, iterator, callback) { + return async.eachOf(arr, _withoutIndex(iterator), callback); + }; + + async.forEachSeries = + async.eachSeries = function (arr, iterator, callback) { + return async.eachOfSeries(arr, _withoutIndex(iterator), callback); + }; + + + async.forEachLimit = + async.eachLimit = function (arr, limit, iterator, callback) { + return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); + }; + + async.forEachOf = + async.eachOf = function (object, iterator, callback) { + callback = _once(callback || noop); + object = object || []; + + var iter = _keyIterator(object); + var key, completed = 0; + + while ((key = iter()) != null) { + completed += 1; + iterator(object[key], key, only_once(done)); + } + + if (completed === 0) callback(null); + + function done(err) { + completed--; + if (err) { + callback(err); + } + // Check key is null in case iterator isn't exhausted + // and done resolved synchronously. + else if (key === null && completed <= 0) { + callback(null); + } + } + }; + + async.forEachOfSeries = + async.eachOfSeries = function (obj, iterator, callback) { + callback = _once(callback || noop); + obj = obj || []; + var nextKey = _keyIterator(obj); + var key = nextKey(); + function iterate() { + var sync = true; + if (key === null) { + return callback(null); + } + iterator(obj[key], key, only_once(function (err) { + if (err) { + callback(err); + } + else { + key = nextKey(); + if (key === null) { + return callback(null); + } else { + if (sync) { + async.setImmediate(iterate); + } else { + iterate(); + } + } + } + })); + sync = false; + } + iterate(); + }; + + + + async.forEachOfLimit = + async.eachOfLimit = function (obj, limit, iterator, callback) { + _eachOfLimit(limit)(obj, iterator, callback); + }; + + function _eachOfLimit(limit) { + + return function (obj, iterator, callback) { + callback = _once(callback || noop); + obj = obj || []; + var nextKey = _keyIterator(obj); + if (limit <= 0) { + return callback(null); + } + var done = false; + var running = 0; + var errored = false; + + (function replenish () { + if (done && running <= 0) { + return callback(null); + } + + while (running < limit && !errored) { + var key = nextKey(); + if (key === null) { + done = true; + if (running <= 0) { + callback(null); + } + return; + } + running += 1; + iterator(obj[key], key, only_once(function (err) { + running -= 1; + if (err) { + callback(err); + errored = true; + } + else { + replenish(); + } + })); + } + })(); + }; + } + + + function doParallel(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOf, obj, iterator, callback); + }; + } + function doParallelLimit(fn) { + return function (obj, limit, iterator, callback) { + return fn(_eachOfLimit(limit), obj, iterator, callback); + }; + } + function doSeries(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOfSeries, obj, iterator, callback); + }; + } + + function _asyncMap(eachfn, arr, iterator, callback) { + callback = _once(callback || noop); + arr = arr || []; + var results = _isArrayLike(arr) ? [] : {}; + eachfn(arr, function (value, index, callback) { + iterator(value, function (err, v) { + results[index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = doParallelLimit(_asyncMap); + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.inject = + async.foldl = + async.reduce = function (arr, memo, iterator, callback) { + async.eachOfSeries(arr, function (x, i, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + + async.foldr = + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, identity).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + + async.transform = function (arr, memo, iterator, callback) { + if (arguments.length === 3) { + callback = iterator; + iterator = memo; + memo = _isArray(arr) ? [] : {}; + } + + async.eachOf(arr, function(v, k, cb) { + iterator(memo, v, k, cb); + }, function(err) { + callback(err, memo); + }); + }; + + function _filter(eachfn, arr, iterator, callback) { + var results = []; + eachfn(arr, function (x, index, callback) { + iterator(x, function (v) { + if (v) { + results.push({index: index, value: x}); + } + callback(); + }); + }, function () { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + } + + async.select = + async.filter = doParallel(_filter); + + async.selectLimit = + async.filterLimit = doParallelLimit(_filter); + + async.selectSeries = + async.filterSeries = doSeries(_filter); + + function _reject(eachfn, arr, iterator, callback) { + _filter(eachfn, arr, function(value, cb) { + iterator(value, function(v) { + cb(!v); + }); + }, callback); + } + async.reject = doParallel(_reject); + async.rejectLimit = doParallelLimit(_reject); + async.rejectSeries = doSeries(_reject); + + function _createTester(eachfn, check, getResult) { + return function(arr, limit, iterator, cb) { + function done() { + if (cb) cb(getResult(false, void 0)); + } + function iteratee(x, _, callback) { + if (!cb) return callback(); + iterator(x, function (v) { + if (cb && check(v)) { + cb(getResult(true, x)); + cb = iterator = false; + } + callback(); + }); + } + if (arguments.length > 3) { + eachfn(arr, limit, iteratee, done); + } else { + cb = iterator; + iterator = limit; + eachfn(arr, iteratee, done); + } + }; + } + + async.any = + async.some = _createTester(async.eachOf, toBool, identity); + + async.someLimit = _createTester(async.eachOfLimit, toBool, identity); + + async.all = + async.every = _createTester(async.eachOf, notId, notId); + + async.everyLimit = _createTester(async.eachOfLimit, notId, notId); + + function _findGetResult(v, x) { + return x; + } + async.detect = _createTester(async.eachOf, identity, _findGetResult); + async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); + async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult); + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + callback(null, _map(results.sort(comparator), function (x) { + return x.value; + })); + } + + }); + + function comparator(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + } + }; + + async.auto = function (tasks, concurrency, callback) { + if (typeof arguments[1] === 'function') { + // concurrency is optional, shift the args. + callback = concurrency; + concurrency = null; + } + callback = _once(callback || noop); + var keys = _keys(tasks); + var remainingTasks = keys.length; + if (!remainingTasks) { + return callback(null); + } + if (!concurrency) { + concurrency = remainingTasks; + } + + var results = {}; + var runningTasks = 0; + + var hasError = false; + + var listeners = []; + function addListener(fn) { + listeners.unshift(fn); + } + function removeListener(fn) { + var idx = _indexOf(listeners, fn); + if (idx >= 0) listeners.splice(idx, 1); + } + function taskComplete() { + remainingTasks--; + _arrayEach(listeners.slice(0), function (fn) { + fn(); + }); + } + + addListener(function () { + if (!remainingTasks) { + callback(null, results); + } + }); + + _arrayEach(keys, function (k) { + if (hasError) return; + var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; + var taskCallback = _restParam(function(err, args) { + runningTasks--; + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _forEachOf(results, function(val, rkey) { + safeResults[rkey] = val; + }); + safeResults[k] = args; + hasError = true; + + callback(err, safeResults); + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }); + var requires = task.slice(0, task.length - 1); + // prevent dead-locks + var len = requires.length; + var dep; + while (len--) { + if (!(dep = tasks[requires[len]])) { + throw new Error('Has nonexistent dependency in ' + requires.join(', ')); + } + if (_isArray(dep) && _indexOf(dep, k) >= 0) { + throw new Error('Has cyclic dependencies'); + } + } + function ready() { + return runningTasks < concurrency && _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + } + if (ready()) { + runningTasks++; + task[task.length - 1](taskCallback, results); + } + else { + addListener(listener); + } + function listener() { + if (ready()) { + runningTasks++; + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + } + }); + }; + + + + async.retry = function(times, task, callback) { + var DEFAULT_TIMES = 5; + var DEFAULT_INTERVAL = 0; + + var attempts = []; + + var opts = { + times: DEFAULT_TIMES, + interval: DEFAULT_INTERVAL + }; + + function parseTimes(acc, t){ + if(typeof t === 'number'){ + acc.times = parseInt(t, 10) || DEFAULT_TIMES; + } else if(typeof t === 'object'){ + acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; + acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; + } else { + throw new Error('Unsupported argument type for \'times\': ' + typeof t); + } + } + + var length = arguments.length; + if (length < 1 || length > 3) { + throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); + } else if (length <= 2 && typeof times === 'function') { + callback = task; + task = times; + } + if (typeof times !== 'function') { + parseTimes(opts, times); + } + opts.callback = callback; + opts.task = task; + + function wrappedTask(wrappedCallback, wrappedResults) { + function retryAttempt(task, finalAttempt) { + return function(seriesCallback) { + task(function(err, result){ + seriesCallback(!err || finalAttempt, {err: err, result: result}); + }, wrappedResults); + }; + } + + function retryInterval(interval){ + return function(seriesCallback){ + setTimeout(function(){ + seriesCallback(null); + }, interval); + }; + } + + while (opts.times) { + + var finalAttempt = !(opts.times-=1); + attempts.push(retryAttempt(opts.task, finalAttempt)); + if(!finalAttempt && opts.interval > 0){ + attempts.push(retryInterval(opts.interval)); + } + } + + async.series(attempts, function(done, data){ + data = data[data.length - 1]; + (wrappedCallback || opts.callback)(data.err, data.result); + }); + } + + // If a callback is passed, run this as a controll flow + return opts.callback ? wrappedTask() : wrappedTask; + }; + + async.waterfall = function (tasks, callback) { + callback = _once(callback || noop); + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + function wrapIterator(iterator) { + return _restParam(function (err, args) { + if (err) { + callback.apply(null, [err].concat(args)); + } + else { + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + ensureAsync(iterator).apply(null, args); + } + }); + } + wrapIterator(async.iterator(tasks))(); + }; + + function _parallel(eachfn, tasks, callback) { + callback = callback || noop; + var results = _isArrayLike(tasks) ? [] : {}; + + eachfn(tasks, function (task, key, callback) { + task(_restParam(function (err, args) { + if (args.length <= 1) { + args = args[0]; + } + results[key] = args; + callback(err); + })); + }, function (err) { + callback(err, results); + }); + } + + async.parallel = function (tasks, callback) { + _parallel(async.eachOf, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel(_eachOfLimit(limit), tasks, callback); + }; + + async.series = function(tasks, callback) { + _parallel(async.eachOfSeries, tasks, callback); + }; + + async.iterator = function (tasks) { + function makeCallback(index) { + function fn() { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + } + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + } + return makeCallback(0); + }; + + async.apply = _restParam(function (fn, args) { + return _restParam(function (callArgs) { + return fn.apply( + null, args.concat(callArgs) + ); + }); + }); + + function _concat(eachfn, arr, fn, callback) { + var result = []; + eachfn(arr, function (x, index, cb) { + fn(x, function (err, y) { + result = result.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, result); + }); + } + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + callback = callback || noop; + if (test()) { + var next = _restParam(function(err, args) { + if (err) { + callback(err); + } else if (test.apply(this, args)) { + iterator(next); + } else { + callback.apply(null, [null].concat(args)); + } + }); + iterator(next); + } else { + callback(null); + } + }; + + async.doWhilst = function (iterator, test, callback) { + var calls = 0; + return async.whilst(function() { + return ++calls <= 1 || test.apply(this, arguments); + }, iterator, callback); + }; + + async.until = function (test, iterator, callback) { + return async.whilst(function() { + return !test.apply(this, arguments); + }, iterator, callback); + }; + + async.doUntil = function (iterator, test, callback) { + return async.doWhilst(iterator, function() { + return !test.apply(this, arguments); + }, callback); + }; + + async.during = function (test, iterator, callback) { + callback = callback || noop; + + var next = _restParam(function(err, args) { + if (err) { + callback(err); + } else { + args.push(check); + test.apply(this, args); + } + }); + + var check = function(err, truth) { + if (err) { + callback(err); + } else if (truth) { + iterator(next); + } else { + callback(null); + } + }; + + test(check); + }; + + async.doDuring = function (iterator, test, callback) { + var calls = 0; + async.during(function(next) { + if (calls++ < 1) { + next(null, true); + } else { + test.apply(this, arguments); + } + }, iterator, callback); + }; + + function _queue(worker, concurrency, payload) { + if (concurrency == null) { + concurrency = 1; + } + else if(concurrency === 0) { + throw new Error('Concurrency must not be zero'); + } + function _insert(q, data, pos, callback) { + if (callback != null && typeof callback !== "function") { + throw new Error("task callback must be a function"); + } + q.started = true; + if (!_isArray(data)) { + data = [data]; + } + if(data.length === 0 && q.idle()) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + q.drain(); + }); + } + _arrayEach(data, function(task) { + var item = { + data: task, + callback: callback || noop + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.tasks.length === q.concurrency) { + q.saturated(); + } + }); + async.setImmediate(q.process); + } + function _next(q, tasks) { + return function(){ + workers -= 1; + + var removed = false; + var args = arguments; + _arrayEach(tasks, function (task) { + _arrayEach(workersList, function (worker, index) { + if (worker === task && !removed) { + workersList.splice(index, 1); + removed = true; + } + }); + + task.callback.apply(task, args); + }); + if (q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + } + + var workers = 0; + var workersList = []; + var q = { + tasks: [], + concurrency: concurrency, + payload: payload, + saturated: noop, + empty: noop, + drain: noop, + started: false, + paused: false, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + kill: function () { + q.drain = noop; + q.tasks = []; + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + while(!q.paused && workers < q.concurrency && q.tasks.length){ + + var tasks = q.payload ? + q.tasks.splice(0, q.payload) : + q.tasks.splice(0, q.tasks.length); + + var data = _map(tasks, function (task) { + return task.data; + }); + + if (q.tasks.length === 0) { + q.empty(); + } + workers += 1; + workersList.push(tasks[0]); + var cb = only_once(_next(q, tasks)); + worker(data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + }, + workersList: function () { + return workersList; + }, + idle: function() { + return q.tasks.length + workers === 0; + }, + pause: function () { + q.paused = true; + }, + resume: function () { + if (q.paused === false) { return; } + q.paused = false; + var resumeCount = Math.min(q.concurrency, q.tasks.length); + // Need to call q.process once per concurrent + // worker to preserve full concurrency after pause + for (var w = 1; w <= resumeCount; w++) { + async.setImmediate(q.process); + } + } + }; + return q; + } + + async.queue = function (worker, concurrency) { + var q = _queue(function (items, cb) { + worker(items[0], cb); + }, concurrency, 1); + + return q; + }; + + async.priorityQueue = function (worker, concurrency) { + + function _compareTasks(a, b){ + return a.priority - b.priority; + } + + function _binarySearch(sequence, item, compare) { + var beg = -1, + end = sequence.length - 1; + while (beg < end) { + var mid = beg + ((end - beg + 1) >>> 1); + if (compare(item, sequence[mid]) >= 0) { + beg = mid; + } else { + end = mid - 1; + } + } + return beg; + } + + function _insert(q, data, priority, callback) { + if (callback != null && typeof callback !== "function") { + throw new Error("task callback must be a function"); + } + q.started = true; + if (!_isArray(data)) { + data = [data]; + } + if(data.length === 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + q.drain(); + }); + } + _arrayEach(data, function(task) { + var item = { + data: task, + priority: priority, + callback: typeof callback === 'function' ? callback : noop + }; + + q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); + + if (q.tasks.length === q.concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + // Start with a normal queue + var q = async.queue(worker, concurrency); + + // Override push to accept second parameter representing priority + q.push = function (data, priority, callback) { + _insert(q, data, priority, callback); + }; + + // Remove unshift function + delete q.unshift; + + return q; + }; + + async.cargo = function (worker, payload) { + return _queue(worker, 1, payload); + }; + + function _console_fn(name) { + return _restParam(function (fn, args) { + fn.apply(null, args.concat([_restParam(function (err, args) { + if (typeof console === 'object') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _arrayEach(args, function (x) { + console[name](x); + }); + } + } + })])); + }); + } + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + var has = Object.prototype.hasOwnProperty; + hasher = hasher || identity; + var memoized = _restParam(function memoized(args) { + var callback = args.pop(); + var key = hasher.apply(null, args); + if (has.call(memo, key)) { + async.setImmediate(function () { + callback.apply(null, memo[key]); + }); + } + else if (has.call(queues, key)) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([_restParam(function (args) { + memo[key] = args; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, args); + } + })])); + } + }); + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + function _times(mapper) { + return function (count, iterator, callback) { + mapper(_range(count), iterator, callback); + }; + } + + async.times = _times(async.map); + async.timesSeries = _times(async.mapSeries); + async.timesLimit = function (count, limit, iterator, callback) { + return async.mapLimit(_range(count), limit, iterator, callback); + }; + + async.seq = function (/* functions... */) { + var fns = arguments; + return _restParam(function (args) { + var that = this; + + var callback = args[args.length - 1]; + if (typeof callback == 'function') { + args.pop(); + } else { + callback = noop; + } + + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { + cb(err, nextargs); + })])); + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }); + }; + + async.compose = function (/* functions... */) { + return async.seq.apply(null, Array.prototype.reverse.call(arguments)); + }; + + + function _applyEach(eachfn) { + return _restParam(function(fns, args) { + var go = _restParam(function(args) { + var that = this; + var callback = args.pop(); + return eachfn(fns, function (fn, _, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }); + if (args.length) { + return go.apply(this, args); + } + else { + return go; + } + }); + } + + async.applyEach = _applyEach(async.eachOf); + async.applyEachSeries = _applyEach(async.eachOfSeries); + + + async.forever = function (fn, callback) { + var done = only_once(callback || noop); + var task = ensureAsync(fn); + function next(err) { + if (err) { + return done(err); + } + task(next); + } + next(); + }; + + function ensureAsync(fn) { + return _restParam(function (args) { + var callback = args.pop(); + args.push(function () { + var innerArgs = arguments; + if (sync) { + async.setImmediate(function () { + callback.apply(null, innerArgs); + }); + } else { + callback.apply(null, innerArgs); + } + }); + var sync = true; + fn.apply(this, args); + sync = false; + }); + } + + async.ensureAsync = ensureAsync; + + async.constant = _restParam(function(values) { + var args = [null].concat(values); + return function (callback) { + return callback.apply(this, args); + }; + }); + + async.wrapSync = + async.asyncify = function asyncify(func) { + return _restParam(function (args) { + var callback = args.pop(); + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (_isObject(result) && typeof result.then === "function") { + result.then(function(value) { + callback(null, value); + })["catch"](function(err) { + callback(err.message ? err : new Error(err)); + }); + } else { + callback(null, result); + } + }); + }; + + // Node.js + if (typeof module === 'object' && module.exports) { + module.exports = async; + } + // AMD / RequireJS + else if (typeof define === 'function' && define.amd) { + define([], function () { + return async; + }); + } + // included directly via + +``` + +Open the above .html file in a browser and you should see + +Node Example + +**[Full online demo](http://kpdecker.github.com/jsdiff)** + +## License + +Software License Agreement (BSD License) + +Copyright (c) 2009-2011, Kevin Decker kpdecker@gmail.com + +All rights reserved. + +Redistribution and use of this software in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/kpdecker/jsdiff/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/hm_sunwell/node_modules/diff/diff.js b/hm_sunwell/node_modules/diff/diff.js new file mode 100644 index 0000000..421854a --- /dev/null +++ b/hm_sunwell/node_modules/diff/diff.js @@ -0,0 +1,619 @@ +/* See LICENSE file for terms of use */ + +/* + * Text diff implementation. + * + * This library supports the following APIS: + * JsDiff.diffChars: Character by character diff + * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace + * JsDiff.diffLines: Line based diff + * + * JsDiff.diffCss: Diff targeted at CSS content + * + * These methods are based on the implementation proposed in + * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 + */ +(function(global, undefined) { + var objectPrototypeToString = Object.prototype.toString; + + /*istanbul ignore next*/ + function map(arr, mapper, that) { + if (Array.prototype.map) { + return Array.prototype.map.call(arr, mapper, that); + } + + var other = new Array(arr.length); + + for (var i = 0, n = arr.length; i < n; i++) { + other[i] = mapper.call(that, arr[i], i, arr); + } + return other; + } + function clonePath(path) { + return { newPos: path.newPos, components: path.components.slice(0) }; + } + function removeEmpty(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + if (array[i]) { + ret.push(array[i]); + } + } + return ret; + } + function escapeHTML(s) { + var n = s; + n = n.replace(/&/g, '&'); + n = n.replace(//g, '>'); + n = n.replace(/"/g, '"'); + + return n; + } + + // This function handles the presence of circular references by bailing out when encountering an + // object that is already on the "stack" of items being processed. + function canonicalize(obj, stack, replacementStack) { + stack = stack || []; + replacementStack = replacementStack || []; + + var i; + + for (i = 0; i < stack.length; i += 1) { + if (stack[i] === obj) { + return replacementStack[i]; + } + } + + var canonicalizedObj; + + if ('[object Array]' === objectPrototypeToString.call(obj)) { + stack.push(obj); + canonicalizedObj = new Array(obj.length); + replacementStack.push(canonicalizedObj); + for (i = 0; i < obj.length; i += 1) { + canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack); + } + stack.pop(); + replacementStack.pop(); + } else if (typeof obj === 'object' && obj !== null) { + stack.push(obj); + canonicalizedObj = {}; + replacementStack.push(canonicalizedObj); + var sortedKeys = [], + key; + for (key in obj) { + sortedKeys.push(key); + } + sortedKeys.sort(); + for (i = 0; i < sortedKeys.length; i += 1) { + key = sortedKeys[i]; + canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack); + } + stack.pop(); + replacementStack.pop(); + } else { + canonicalizedObj = obj; + } + return canonicalizedObj; + } + + function buildValues(components, newString, oldString, useLongestToken) { + var componentPos = 0, + componentLen = components.length, + newPos = 0, + oldPos = 0; + + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + if (!component.removed) { + if (!component.added && useLongestToken) { + var value = newString.slice(newPos, newPos + component.count); + value = map(value, function(value, i) { + var oldValue = oldString[oldPos + i]; + return oldValue.length > value.length ? oldValue : value; + }); + + component.value = value.join(''); + } else { + component.value = newString.slice(newPos, newPos + component.count).join(''); + } + newPos += component.count; + + // Common case + if (!component.added) { + oldPos += component.count; + } + } else { + component.value = oldString.slice(oldPos, oldPos + component.count).join(''); + oldPos += component.count; + + // Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + if (componentPos && components[componentPos - 1].added) { + var tmp = components[componentPos - 1]; + components[componentPos - 1] = components[componentPos]; + components[componentPos] = tmp; + } + } + } + + return components; + } + + function Diff(ignoreWhitespace) { + this.ignoreWhitespace = ignoreWhitespace; + } + Diff.prototype = { + diff: function(oldString, newString, callback) { + var self = this; + + function done(value) { + if (callback) { + setTimeout(function() { callback(undefined, value); }, 0); + return true; + } else { + return value; + } + } + + // Handle the identity case (this is due to unrolling editLength == 0 + if (newString === oldString) { + return done([{ value: newString }]); + } + if (!newString) { + return done([{ value: oldString, removed: true }]); + } + if (!oldString) { + return done([{ value: newString, added: true }]); + } + + newString = this.tokenize(newString); + oldString = this.tokenize(oldString); + + var newLen = newString.length, oldLen = oldString.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + var bestPath = [{ newPos: -1, components: [] }]; + + // Seed editLength = 0, i.e. the content starts with the same values + var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + // Identity per the equality and tokenizer + return done([{value: newString.join('')}]); + } + + // Main worker method. checks all permutations of a given edit length for acceptance. + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath; + var addPath = bestPath[diagonalPath - 1], + removePath = bestPath[diagonalPath + 1], + oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath - 1] = undefined; + } + + var canAdd = addPath && addPath.newPos + 1 < newLen, + canRemove = removePath && 0 <= oldPos && oldPos < oldLen; + if (!canAdd && !canRemove) { + // If this path is a terminal then prune + bestPath[diagonalPath] = undefined; + continue; + } + + // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { + basePath = clonePath(removePath); + self.pushComponent(basePath.components, undefined, true); + } else { + basePath = addPath; // No need to clone, we've pulled it from the list + basePath.newPos++; + self.pushComponent(basePath.components, true, undefined); + } + + oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); + + // If we have hit the end of both strings, then we are done + if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + return done(buildValues(basePath.components, newString, oldString, self.useLongestToken)); + } else { + // Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath] = basePath; + } + } + + editLength++; + } + + // Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced. + if (callback) { + (function exec() { + setTimeout(function() { + // This should not happen, but we want to be safe. + /*istanbul ignore next */ + if (editLength > maxEditLength) { + return callback(); + } + + if (!execEditLength()) { + exec(); + } + }, 0); + }()); + } else { + while (editLength <= maxEditLength) { + var ret = execEditLength(); + if (ret) { + return ret; + } + } + } + }, + + pushComponent: function(components, added, removed) { + var last = components[components.length - 1]; + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length - 1] = {count: last.count + 1, added: added, removed: removed }; + } else { + components.push({count: 1, added: added, removed: removed }); + } + }, + extractCommon: function(basePath, newString, oldString, diagonalPath) { + var newLen = newString.length, + oldLen = oldString.length, + newPos = basePath.newPos, + oldPos = newPos - diagonalPath, + + commonCount = 0; + while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } + + if (commonCount) { + basePath.components.push({count: commonCount}); + } + + basePath.newPos = newPos; + return oldPos; + }, + + equals: function(left, right) { + var reWhitespace = /\S/; + return left === right || (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)); + }, + tokenize: function(value) { + return value.split(''); + } + }; + + var CharDiff = new Diff(); + + var WordDiff = new Diff(true); + var WordWithSpaceDiff = new Diff(); + WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) { + return removeEmpty(value.split(/(\s+|\b)/)); + }; + + var CssDiff = new Diff(true); + CssDiff.tokenize = function(value) { + return removeEmpty(value.split(/([{}:;,]|\s+)/)); + }; + + var LineDiff = new Diff(); + + var TrimmedLineDiff = new Diff(); + TrimmedLineDiff.ignoreTrim = true; + + LineDiff.tokenize = TrimmedLineDiff.tokenize = function(value) { + var retLines = [], + lines = value.split(/^/m); + for (var i = 0; i < lines.length; i++) { + var line = lines[i], + lastLine = lines[i - 1], + lastLineLastChar = lastLine && lastLine[lastLine.length - 1]; + + // Merge lines that may contain windows new lines + if (line === '\n' && lastLineLastChar === '\r') { + retLines[retLines.length - 1] = retLines[retLines.length - 1].slice(0, -1) + '\r\n'; + } else { + if (this.ignoreTrim) { + line = line.trim(); + // add a newline unless this is the last line. + if (i < lines.length - 1) { + line += '\n'; + } + } + retLines.push(line); + } + } + + return retLines; + }; + + var PatchDiff = new Diff(); + PatchDiff.tokenize = function(value) { + var ret = [], + linesAndNewlines = value.split(/(\n|\r\n)/); + + // Ignore the final empty token that occurs if the string ends with a new line + if (!linesAndNewlines[linesAndNewlines.length - 1]) { + linesAndNewlines.pop(); + } + + // Merge the content and line separators into single tokens + for (var i = 0; i < linesAndNewlines.length; i++) { + var line = linesAndNewlines[i]; + + if (i % 2) { + ret[ret.length - 1] += line; + } else { + ret.push(line); + } + } + return ret; + }; + + var SentenceDiff = new Diff(); + SentenceDiff.tokenize = function(value) { + return removeEmpty(value.split(/(\S.+?[.!?])(?=\s+|$)/)); + }; + + var JsonDiff = new Diff(); + // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a + // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: + JsonDiff.useLongestToken = true; + JsonDiff.tokenize = LineDiff.tokenize; + JsonDiff.equals = function(left, right) { + return LineDiff.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')); + }; + + var JsDiff = { + Diff: Diff, + + diffChars: function(oldStr, newStr, callback) { return CharDiff.diff(oldStr, newStr, callback); }, + diffWords: function(oldStr, newStr, callback) { return WordDiff.diff(oldStr, newStr, callback); }, + diffWordsWithSpace: function(oldStr, newStr, callback) { return WordWithSpaceDiff.diff(oldStr, newStr, callback); }, + diffLines: function(oldStr, newStr, callback) { return LineDiff.diff(oldStr, newStr, callback); }, + diffTrimmedLines: function(oldStr, newStr, callback) { return TrimmedLineDiff.diff(oldStr, newStr, callback); }, + + diffSentences: function(oldStr, newStr, callback) { return SentenceDiff.diff(oldStr, newStr, callback); }, + + diffCss: function(oldStr, newStr, callback) { return CssDiff.diff(oldStr, newStr, callback); }, + diffJson: function(oldObj, newObj, callback) { + return JsonDiff.diff( + typeof oldObj === 'string' ? oldObj : JSON.stringify(canonicalize(oldObj), undefined, ' '), + typeof newObj === 'string' ? newObj : JSON.stringify(canonicalize(newObj), undefined, ' '), + callback + ); + }, + + createTwoFilesPatch: function(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader) { + var ret = []; + + if (oldFileName == newFileName) { + ret.push('Index: ' + oldFileName); + } + ret.push('==================================================================='); + ret.push('--- ' + oldFileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); + ret.push('+++ ' + newFileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); + + var diff = PatchDiff.diff(oldStr, newStr); + diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier + + // Formats a given set of lines for printing as context lines in a patch + function contextLines(lines) { + return map(lines, function(entry) { return ' ' + entry; }); + } + + // Outputs the no newline at end of file warning if needed + function eofNL(curRange, i, current) { + var last = diff[diff.length - 2], + isLast = i === diff.length - 2, + isLastOfType = i === diff.length - 3 && current.added !== last.added; + + // Figure out if this is the last line for the given file and missing NL + if (!(/\n$/.test(current.value)) && (isLast || isLastOfType)) { + curRange.push('\\ No newline at end of file'); + } + } + + var oldRangeStart = 0, newRangeStart = 0, curRange = [], + oldLine = 1, newLine = 1; + for (var i = 0; i < diff.length; i++) { + var current = diff[i], + lines = current.lines || current.value.replace(/\n$/, '').split('\n'); + current.lines = lines; + + if (current.added || current.removed) { + // If we have previous context, start with that + if (!oldRangeStart) { + var prev = diff[i - 1]; + oldRangeStart = oldLine; + newRangeStart = newLine; + + if (prev) { + curRange = contextLines(prev.lines.slice(-4)); + oldRangeStart -= curRange.length; + newRangeStart -= curRange.length; + } + } + + // Output our changes + curRange.push.apply(curRange, map(lines, function(entry) { + return (current.added ? '+' : '-') + entry; + })); + eofNL(curRange, i, current); + + // Track the updated file position + if (current.added) { + newLine += lines.length; + } else { + oldLine += lines.length; + } + } else { + // Identical context lines. Track line changes + if (oldRangeStart) { + // Close out any changes that have been output (or join overlapping) + if (lines.length <= 8 && i < diff.length - 2) { + // Overlapping + curRange.push.apply(curRange, contextLines(lines)); + } else { + // end the range and output + var contextSize = Math.min(lines.length, 4); + ret.push( + '@@ -' + oldRangeStart + ',' + (oldLine - oldRangeStart + contextSize) + + ' +' + newRangeStart + ',' + (newLine - newRangeStart + contextSize) + + ' @@'); + ret.push.apply(ret, curRange); + ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); + if (lines.length <= 4) { + eofNL(ret, i, current); + } + + oldRangeStart = 0; + newRangeStart = 0; + curRange = []; + } + } + oldLine += lines.length; + newLine += lines.length; + } + } + + return ret.join('\n') + '\n'; + }, + + createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { + return JsDiff.createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader); + }, + + applyPatch: function(oldStr, uniDiff) { + var diffstr = uniDiff.split('\n'), + hunks = [], + i = 0, + remEOFNL = false, + addEOFNL = false; + + // Skip to the first change hunk + while (i < diffstr.length && !(/^@@/.test(diffstr[i]))) { + i++; + } + + // Parse the unified diff + for (; i < diffstr.length; i++) { + if (diffstr[i][0] === '@') { + var chnukHeader = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); + hunks.unshift({ + start: chnukHeader[3], + oldlength: +chnukHeader[2], + removed: [], + newlength: chnukHeader[4], + added: [] + }); + } else if (diffstr[i][0] === '+') { + hunks[0].added.push(diffstr[i].substr(1)); + } else if (diffstr[i][0] === '-') { + hunks[0].removed.push(diffstr[i].substr(1)); + } else if (diffstr[i][0] === ' ') { + hunks[0].added.push(diffstr[i].substr(1)); + hunks[0].removed.push(diffstr[i].substr(1)); + } else if (diffstr[i][0] === '\\') { + if (diffstr[i - 1][0] === '+') { + remEOFNL = true; + } else if (diffstr[i - 1][0] === '-') { + addEOFNL = true; + } + } + } + + // Apply the diff to the input + var lines = oldStr.split('\n'); + for (i = hunks.length - 1; i >= 0; i--) { + var hunk = hunks[i]; + // Sanity check the input string. Bail if we don't match. + for (var j = 0; j < hunk.oldlength; j++) { + if (lines[hunk.start - 1 + j] !== hunk.removed[j]) { + return false; + } + } + Array.prototype.splice.apply(lines, [hunk.start - 1, hunk.oldlength].concat(hunk.added)); + } + + // Handle EOFNL insertion/removal + if (remEOFNL) { + while (!lines[lines.length - 1]) { + lines.pop(); + } + } else if (addEOFNL) { + lines.push(''); + } + return lines.join('\n'); + }, + + convertChangesToXML: function(changes) { + var ret = []; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + + ret.push(escapeHTML(change.value)); + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + } + return ret.join(''); + }, + + // See: http://code.google.com/p/google-diff-match-patch/wiki/API + convertChangesToDMP: function(changes) { + var ret = [], + change, + operation; + for (var i = 0; i < changes.length; i++) { + change = changes[i]; + if (change.added) { + operation = 1; + } else if (change.removed) { + operation = -1; + } else { + operation = 0; + } + + ret.push([operation, change.value]); + } + return ret; + }, + + canonicalize: canonicalize + }; + + /*istanbul ignore next */ + /*global module */ + if (typeof module !== 'undefined' && module.exports) { + module.exports = JsDiff; + } else if (typeof define === 'function' && define.amd) { + /*global define */ + define([], function() { return JsDiff; }); + } else if (typeof global.JsDiff === 'undefined') { + global.JsDiff = JsDiff; + } +}(this)); diff --git a/hm_sunwell/node_modules/diff/package.json b/hm_sunwell/node_modules/diff/package.json new file mode 100644 index 0000000..092b588 --- /dev/null +++ b/hm_sunwell/node_modules/diff/package.json @@ -0,0 +1,88 @@ +{ + "_args": [ + [ + "diff@1.4.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha" + ] + ], + "_from": "diff@1.4.0", + "_id": "diff@1.4.0", + "_inCache": true, + "_installable": true, + "_location": "/diff", + "_npmUser": { + "email": "kpdecker@gmail.com", + "name": "kpdecker" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "diff", + "raw": "diff@1.4.0", + "rawSpec": "1.4.0", + "scope": null, + "spec": "1.4.0", + "type": "version" + }, + "_requiredBy": [ + "/mocha" + ], + "_resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "_shasum": "7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf", + "_shrinkwrap": null, + "_spec": "diff@1.4.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha", + "bugs": { + "email": "kpdecker@gmail.com", + "url": "http://github.com/kpdecker/jsdiff/issues" + }, + "dependencies": {}, + "description": "A javascript text diff implementation.", + "devDependencies": { + "colors": "^1.1.0", + "istanbul": "^0.3.2", + "mocha": "^2.2.4", + "should": "^6.0.1" + }, + "directories": {}, + "dist": { + "shasum": "7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf", + "tarball": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz" + }, + "engines": { + "node": ">=0.3.1" + }, + "files": [ + "diff.js" + ], + "gitHead": "27a750e9116e6ade6303bc24a9be72f6845e00ed", + "homepage": "https://github.com/kpdecker/jsdiff", + "keywords": [ + "diff", + "javascript" + ], + "licenses": [ + { + "type": "BSD", + "url": "http://github.com/kpdecker/jsdiff/blob/master/LICENSE" + } + ], + "main": "./diff", + "maintainers": [ + { + "name": "kpdecker", + "email": "kpdecker@gmail.com" + } + ], + "name": "diff", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/kpdecker/jsdiff.git" + }, + "scripts": { + "test": "istanbul cover node_modules/.bin/_mocha test/*.js && istanbul check-coverage --statements 100 --functions 100 --branches 100 --lines 100 coverage/coverage.json" + }, + "version": "1.4.0" +} diff --git a/hm_sunwell/node_modules/ecc-jsbn/.npmignore b/hm_sunwell/node_modules/ecc-jsbn/.npmignore new file mode 100644 index 0000000..a72b52e --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/.npmignore @@ -0,0 +1,15 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +npm-debug.log +node_modules diff --git a/hm_sunwell/node_modules/ecc-jsbn/LICENSE b/hm_sunwell/node_modules/ecc-jsbn/LICENSE new file mode 100644 index 0000000..f668fef --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jeremie Miller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/hm_sunwell/node_modules/ecc-jsbn/README.md b/hm_sunwell/node_modules/ecc-jsbn/README.md new file mode 100644 index 0000000..b5d0b9d --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/README.md @@ -0,0 +1,8 @@ +ecc-jsbn +======== + +ECC package based on [jsbn](https://github.com/andyperlitch/jsbn) from [Tom Wu](http://www-cs-students.stanford.edu/~tjw/). + +This is a subset of the same interface as the [node compiled module](https://github.com/quartzjer/ecc), but works in the browser too. + +Also uses point compression now from [https://github.com/kaielvin](https://github.com/kaielvin/jsbn-ec-point-compression). diff --git a/hm_sunwell/node_modules/ecc-jsbn/index.js b/hm_sunwell/node_modules/ecc-jsbn/index.js new file mode 100644 index 0000000..2437281 --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/index.js @@ -0,0 +1,57 @@ +var crypto = require("crypto"); +var BigInteger = require("jsbn").BigInteger; +var ECPointFp = require("./lib/ec.js").ECPointFp; +exports.ECCurves = require("./lib/sec.js"); + +// zero prepad +function unstupid(hex,len) +{ + return (hex.length >= len) ? hex : unstupid("0"+hex,len); +} + +exports.ECKey = function(curve, key, isPublic) +{ + var priv; + var c = curve(); + var n = c.getN(); + var bytes = Math.floor(n.bitLength()/8); + + if(key) + { + if(isPublic) + { + var curve = c.getCurve(); +// var x = key.slice(1,bytes+1); // skip the 04 for uncompressed format +// var y = key.slice(bytes+1); +// this.P = new ECPointFp(curve, +// curve.fromBigInteger(new BigInteger(x.toString("hex"), 16)), +// curve.fromBigInteger(new BigInteger(y.toString("hex"), 16))); + this.P = curve.decodePointHex(key.toString("hex")); + }else{ + if(key.length != bytes) return false; + priv = new BigInteger(key.toString("hex"), 16); + } + }else{ + var n1 = n.subtract(BigInteger.ONE); + var r = new BigInteger(crypto.randomBytes(n.bitLength())); + priv = r.mod(n1).add(BigInteger.ONE); + this.P = c.getG().multiply(priv); + } + if(this.P) + { +// var pubhex = unstupid(this.P.getX().toBigInteger().toString(16),bytes*2)+unstupid(this.P.getY().toBigInteger().toString(16),bytes*2); +// this.PublicKey = new Buffer("04"+pubhex,"hex"); + this.PublicKey = new Buffer(c.getCurve().encodeCompressedPointHex(this.P),"hex"); + } + if(priv) + { + this.PrivateKey = new Buffer(unstupid(priv.toString(16),bytes*2),"hex"); + this.deriveSharedSecret = function(key) + { + if(!key || !key.P) return false; + var S = key.P.multiply(priv); + return new Buffer(unstupid(S.getX().toBigInteger().toString(16),bytes*2),"hex"); + } + } +} + diff --git a/hm_sunwell/node_modules/ecc-jsbn/lib/LICENSE-jsbn b/hm_sunwell/node_modules/ecc-jsbn/lib/LICENSE-jsbn new file mode 100644 index 0000000..24502a9 --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/lib/LICENSE-jsbn @@ -0,0 +1,40 @@ +Licensing +--------- + +This software is covered under the following copyright: + +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + +Address all questions regarding this license to: + + Tom Wu + tjw@cs.Stanford.EDU diff --git a/hm_sunwell/node_modules/ecc-jsbn/lib/ec.js b/hm_sunwell/node_modules/ecc-jsbn/lib/ec.js new file mode 100644 index 0000000..3852671 --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/lib/ec.js @@ -0,0 +1,561 @@ +// Basic Javascript Elliptic Curve implementation +// Ported loosely from BouncyCastle's Java EC code +// Only Fp curves implemented for now + +// Requires jsbn.js and jsbn2.js +var BigInteger = require('jsbn').BigInteger +var Barrett = BigInteger.prototype.Barrett + +// ---------------- +// ECFieldElementFp + +// constructor +function ECFieldElementFp(q,x) { + this.x = x; + // TODO if(x.compareTo(q) >= 0) error + this.q = q; +} + +function feFpEquals(other) { + if(other == this) return true; + return (this.q.equals(other.q) && this.x.equals(other.x)); +} + +function feFpToBigInteger() { + return this.x; +} + +function feFpNegate() { + return new ECFieldElementFp(this.q, this.x.negate().mod(this.q)); +} + +function feFpAdd(b) { + return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q)); +} + +function feFpSubtract(b) { + return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q)); +} + +function feFpMultiply(b) { + return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q)); +} + +function feFpSquare() { + return new ECFieldElementFp(this.q, this.x.square().mod(this.q)); +} + +function feFpDivide(b) { + return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q)); +} + +ECFieldElementFp.prototype.equals = feFpEquals; +ECFieldElementFp.prototype.toBigInteger = feFpToBigInteger; +ECFieldElementFp.prototype.negate = feFpNegate; +ECFieldElementFp.prototype.add = feFpAdd; +ECFieldElementFp.prototype.subtract = feFpSubtract; +ECFieldElementFp.prototype.multiply = feFpMultiply; +ECFieldElementFp.prototype.square = feFpSquare; +ECFieldElementFp.prototype.divide = feFpDivide; + +// ---------------- +// ECPointFp + +// constructor +function ECPointFp(curve,x,y,z) { + this.curve = curve; + this.x = x; + this.y = y; + // Projective coordinates: either zinv == null or z * zinv == 1 + // z and zinv are just BigIntegers, not fieldElements + if(z == null) { + this.z = BigInteger.ONE; + } + else { + this.z = z; + } + this.zinv = null; + //TODO: compression flag +} + +function pointFpGetX() { + if(this.zinv == null) { + this.zinv = this.z.modInverse(this.curve.q); + } + var r = this.x.toBigInteger().multiply(this.zinv); + this.curve.reduce(r); + return this.curve.fromBigInteger(r); +} + +function pointFpGetY() { + if(this.zinv == null) { + this.zinv = this.z.modInverse(this.curve.q); + } + var r = this.y.toBigInteger().multiply(this.zinv); + this.curve.reduce(r); + return this.curve.fromBigInteger(r); +} + +function pointFpEquals(other) { + if(other == this) return true; + if(this.isInfinity()) return other.isInfinity(); + if(other.isInfinity()) return this.isInfinity(); + var u, v; + // u = Y2 * Z1 - Y1 * Z2 + u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q); + if(!u.equals(BigInteger.ZERO)) return false; + // v = X2 * Z1 - X1 * Z2 + v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q); + return v.equals(BigInteger.ZERO); +} + +function pointFpIsInfinity() { + if((this.x == null) && (this.y == null)) return true; + return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO); +} + +function pointFpNegate() { + return new ECPointFp(this.curve, this.x, this.y.negate(), this.z); +} + +function pointFpAdd(b) { + if(this.isInfinity()) return b; + if(b.isInfinity()) return this; + + // u = Y2 * Z1 - Y1 * Z2 + var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q); + // v = X2 * Z1 - X1 * Z2 + var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q); + + if(BigInteger.ZERO.equals(v)) { + if(BigInteger.ZERO.equals(u)) { + return this.twice(); // this == b, so double + } + return this.curve.getInfinity(); // this = -b, so infinity + } + + var THREE = new BigInteger("3"); + var x1 = this.x.toBigInteger(); + var y1 = this.y.toBigInteger(); + var x2 = b.x.toBigInteger(); + var y2 = b.y.toBigInteger(); + + var v2 = v.square(); + var v3 = v2.multiply(v); + var x1v2 = x1.multiply(v2); + var zu2 = u.square().multiply(this.z); + + // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) + var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q); + // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 + var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q); + // z3 = v^3 * z1 * z2 + var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q); + + return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); +} + +function pointFpTwice() { + if(this.isInfinity()) return this; + if(this.y.toBigInteger().signum() == 0) return this.curve.getInfinity(); + + // TODO: optimized handling of constants + var THREE = new BigInteger("3"); + var x1 = this.x.toBigInteger(); + var y1 = this.y.toBigInteger(); + + var y1z1 = y1.multiply(this.z); + var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q); + var a = this.curve.a.toBigInteger(); + + // w = 3 * x1^2 + a * z1^2 + var w = x1.square().multiply(THREE); + if(!BigInteger.ZERO.equals(a)) { + w = w.add(this.z.square().multiply(a)); + } + w = w.mod(this.curve.q); + //this.curve.reduce(w); + // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) + var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q); + // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 + var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q); + // z3 = 8 * (y1 * z1)^3 + var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q); + + return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); +} + +// Simple NAF (Non-Adjacent Form) multiplication algorithm +// TODO: modularize the multiplication algorithm +function pointFpMultiply(k) { + if(this.isInfinity()) return this; + if(k.signum() == 0) return this.curve.getInfinity(); + + var e = k; + var h = e.multiply(new BigInteger("3")); + + var neg = this.negate(); + var R = this; + + var i; + for(i = h.bitLength() - 2; i > 0; --i) { + R = R.twice(); + + var hBit = h.testBit(i); + var eBit = e.testBit(i); + + if (hBit != eBit) { + R = R.add(hBit ? this : neg); + } + } + + return R; +} + +// Compute this*j + x*k (simultaneous multiplication) +function pointFpMultiplyTwo(j,x,k) { + var i; + if(j.bitLength() > k.bitLength()) + i = j.bitLength() - 1; + else + i = k.bitLength() - 1; + + var R = this.curve.getInfinity(); + var both = this.add(x); + while(i >= 0) { + R = R.twice(); + if(j.testBit(i)) { + if(k.testBit(i)) { + R = R.add(both); + } + else { + R = R.add(this); + } + } + else { + if(k.testBit(i)) { + R = R.add(x); + } + } + --i; + } + + return R; +} + +ECPointFp.prototype.getX = pointFpGetX; +ECPointFp.prototype.getY = pointFpGetY; +ECPointFp.prototype.equals = pointFpEquals; +ECPointFp.prototype.isInfinity = pointFpIsInfinity; +ECPointFp.prototype.negate = pointFpNegate; +ECPointFp.prototype.add = pointFpAdd; +ECPointFp.prototype.twice = pointFpTwice; +ECPointFp.prototype.multiply = pointFpMultiply; +ECPointFp.prototype.multiplyTwo = pointFpMultiplyTwo; + +// ---------------- +// ECCurveFp + +// constructor +function ECCurveFp(q,a,b) { + this.q = q; + this.a = this.fromBigInteger(a); + this.b = this.fromBigInteger(b); + this.infinity = new ECPointFp(this, null, null); + this.reducer = new Barrett(this.q); +} + +function curveFpGetQ() { + return this.q; +} + +function curveFpGetA() { + return this.a; +} + +function curveFpGetB() { + return this.b; +} + +function curveFpEquals(other) { + if(other == this) return true; + return(this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)); +} + +function curveFpGetInfinity() { + return this.infinity; +} + +function curveFpFromBigInteger(x) { + return new ECFieldElementFp(this.q, x); +} + +function curveReduce(x) { + this.reducer.reduce(x); +} + +// for now, work with hex strings because they're easier in JS +function curveFpDecodePointHex(s) { + switch(parseInt(s.substr(0,2), 16)) { // first byte + case 0: + return this.infinity; + case 2: + case 3: + // point compression not supported yet + return null; + case 4: + case 6: + case 7: + var len = (s.length - 2) / 2; + var xHex = s.substr(2, len); + var yHex = s.substr(len+2, len); + + return new ECPointFp(this, + this.fromBigInteger(new BigInteger(xHex, 16)), + this.fromBigInteger(new BigInteger(yHex, 16))); + + default: // unsupported + return null; + } +} + +function curveFpEncodePointHex(p) { + if (p.isInfinity()) return "00"; + var xHex = p.getX().toBigInteger().toString(16); + var yHex = p.getY().toBigInteger().toString(16); + var oLen = this.getQ().toString(16).length; + if ((oLen % 2) != 0) oLen++; + while (xHex.length < oLen) { + xHex = "0" + xHex; + } + while (yHex.length < oLen) { + yHex = "0" + yHex; + } + return "04" + xHex + yHex; +} + +ECCurveFp.prototype.getQ = curveFpGetQ; +ECCurveFp.prototype.getA = curveFpGetA; +ECCurveFp.prototype.getB = curveFpGetB; +ECCurveFp.prototype.equals = curveFpEquals; +ECCurveFp.prototype.getInfinity = curveFpGetInfinity; +ECCurveFp.prototype.fromBigInteger = curveFpFromBigInteger; +ECCurveFp.prototype.reduce = curveReduce; +//ECCurveFp.prototype.decodePointHex = curveFpDecodePointHex; +ECCurveFp.prototype.encodePointHex = curveFpEncodePointHex; + +// from: https://github.com/kaielvin/jsbn-ec-point-compression +ECCurveFp.prototype.decodePointHex = function(s) +{ + var yIsEven; + switch(parseInt(s.substr(0,2), 16)) { // first byte + case 0: + return this.infinity; + case 2: + yIsEven = false; + case 3: + if(yIsEven == undefined) yIsEven = true; + var len = s.length - 2; + var xHex = s.substr(2, len); + var x = this.fromBigInteger(new BigInteger(xHex,16)); + var alpha = x.multiply(x.square().add(this.getA())).add(this.getB()); + var beta = alpha.sqrt(); + + if (beta == null) throw "Invalid point compression"; + + var betaValue = beta.toBigInteger(); + if (betaValue.testBit(0) != yIsEven) + { + // Use the other root + beta = this.fromBigInteger(this.getQ().subtract(betaValue)); + } + return new ECPointFp(this,x,beta); + case 4: + case 6: + case 7: + var len = (s.length - 2) / 2; + var xHex = s.substr(2, len); + var yHex = s.substr(len+2, len); + + return new ECPointFp(this, + this.fromBigInteger(new BigInteger(xHex, 16)), + this.fromBigInteger(new BigInteger(yHex, 16))); + + default: // unsupported + return null; + } +} +ECCurveFp.prototype.encodeCompressedPointHex = function(p) +{ + if (p.isInfinity()) return "00"; + var xHex = p.getX().toBigInteger().toString(16); + var oLen = this.getQ().toString(16).length; + if ((oLen % 2) != 0) oLen++; + while (xHex.length < oLen) + xHex = "0" + xHex; + var yPrefix; + if(p.getY().toBigInteger().isEven()) yPrefix = "02"; + else yPrefix = "03"; + + return yPrefix + xHex; +} + + +ECFieldElementFp.prototype.getR = function() +{ + if(this.r != undefined) return this.r; + + this.r = null; + var bitLength = this.q.bitLength(); + if (bitLength > 128) + { + var firstWord = this.q.shiftRight(bitLength - 64); + if (firstWord.intValue() == -1) + { + this.r = BigInteger.ONE.shiftLeft(bitLength).subtract(this.q); + } + } + return this.r; +} +ECFieldElementFp.prototype.modMult = function(x1,x2) +{ + return this.modReduce(x1.multiply(x2)); +} +ECFieldElementFp.prototype.modReduce = function(x) +{ + if (this.getR() != null) + { + var qLen = q.bitLength(); + while (x.bitLength() > (qLen + 1)) + { + var u = x.shiftRight(qLen); + var v = x.subtract(u.shiftLeft(qLen)); + if (!this.getR().equals(BigInteger.ONE)) + { + u = u.multiply(this.getR()); + } + x = u.add(v); + } + while (x.compareTo(q) >= 0) + { + x = x.subtract(q); + } + } + else + { + x = x.mod(q); + } + return x; +} +ECFieldElementFp.prototype.sqrt = function() +{ + if (!this.q.testBit(0)) throw "unsupported"; + + // p mod 4 == 3 + if (this.q.testBit(1)) + { + var z = new ECFieldElementFp(this.q,this.x.modPow(this.q.shiftRight(2).add(BigInteger.ONE),this.q)); + return z.square().equals(this) ? z : null; + } + + // p mod 4 == 1 + var qMinusOne = this.q.subtract(BigInteger.ONE); + + var legendreExponent = qMinusOne.shiftRight(1); + if (!(this.x.modPow(legendreExponent, this.q).equals(BigInteger.ONE))) + { + return null; + } + + var u = qMinusOne.shiftRight(2); + var k = u.shiftLeft(1).add(BigInteger.ONE); + + var Q = this.x; + var fourQ = modDouble(modDouble(Q)); + + var U, V; + do + { + var P; + do + { + P = new BigInteger(this.q.bitLength(), new SecureRandom()); + } + while (P.compareTo(this.q) >= 0 + || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, this.q).equals(qMinusOne))); + + var result = this.lucasSequence(P, Q, k); + U = result[0]; + V = result[1]; + + if (this.modMult(V, V).equals(fourQ)) + { + // Integer division by 2, mod q + if (V.testBit(0)) + { + V = V.add(q); + } + + V = V.shiftRight(1); + + return new ECFieldElementFp(q,V); + } + } + while (U.equals(BigInteger.ONE) || U.equals(qMinusOne)); + + return null; +} +ECFieldElementFp.prototype.lucasSequence = function(P,Q,k) +{ + var n = k.bitLength(); + var s = k.getLowestSetBit(); + + var Uh = BigInteger.ONE; + var Vl = BigInteger.TWO; + var Vh = P; + var Ql = BigInteger.ONE; + var Qh = BigInteger.ONE; + + for (var j = n - 1; j >= s + 1; --j) + { + Ql = this.modMult(Ql, Qh); + + if (k.testBit(j)) + { + Qh = this.modMult(Ql, Q); + Uh = this.modMult(Uh, Vh); + Vl = this.modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); + Vh = this.modReduce(Vh.multiply(Vh).subtract(Qh.shiftLeft(1))); + } + else + { + Qh = Ql; + Uh = this.modReduce(Uh.multiply(Vl).subtract(Ql)); + Vh = this.modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); + Vl = this.modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1))); + } + } + + Ql = this.modMult(Ql, Qh); + Qh = this.modMult(Ql, Q); + Uh = this.modReduce(Uh.multiply(Vl).subtract(Ql)); + Vl = this.modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); + Ql = this.modMult(Ql, Qh); + + for (var j = 1; j <= s; ++j) + { + Uh = this.modMult(Uh, Vl); + Vl = this.modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1))); + Ql = this.modMult(Ql, Ql); + } + + return [ Uh, Vl ]; +} + +var exports = { + ECCurveFp: ECCurveFp, + ECPointFp: ECPointFp, + ECFieldElementFp: ECFieldElementFp +} + +module.exports = exports diff --git a/hm_sunwell/node_modules/ecc-jsbn/lib/sec.js b/hm_sunwell/node_modules/ecc-jsbn/lib/sec.js new file mode 100644 index 0000000..5eec817 --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/lib/sec.js @@ -0,0 +1,170 @@ +// Named EC curves + +// Requires ec.js, jsbn.js, and jsbn2.js +var BigInteger = require('jsbn').BigInteger +var ECCurveFp = require('./ec.js').ECCurveFp + + +// ---------------- +// X9ECParameters + +// constructor +function X9ECParameters(curve,g,n,h) { + this.curve = curve; + this.g = g; + this.n = n; + this.h = h; +} + +function x9getCurve() { + return this.curve; +} + +function x9getG() { + return this.g; +} + +function x9getN() { + return this.n; +} + +function x9getH() { + return this.h; +} + +X9ECParameters.prototype.getCurve = x9getCurve; +X9ECParameters.prototype.getG = x9getG; +X9ECParameters.prototype.getN = x9getN; +X9ECParameters.prototype.getH = x9getH; + +// ---------------- +// SECNamedCurves + +function fromHex(s) { return new BigInteger(s, 16); } + +function secp128r1() { + // p = 2^128 - 2^97 - 1 + var p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); + var a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"); + var b = fromHex("E87579C11079F43DD824993C2CEE5ED3"); + //byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679"); + var n = fromHex("FFFFFFFE0000000075A30D1B9038A115"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "161FF7528B899B2D0C28607CA52C5B86" + + "CF5AC8395BAFEB13C02DA292DDED7A83"); + return new X9ECParameters(curve, G, n, h); +} + +function secp160k1() { + // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 + var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"); + var a = BigInteger.ZERO; + var b = fromHex("7"); + //byte[] S = null; + var n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" + + "938CF935318FDCED6BC28286531733C3F03C4FEE"); + return new X9ECParameters(curve, G, n, h); +} + +function secp160r1() { + // p = 2^160 - 2^31 - 1 + var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"); + var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"); + var b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"); + //byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345"); + var n = fromHex("0100000000000000000001F4C8F927AED3CA752257"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "4A96B5688EF573284664698968C38BB913CBFC82" + + "23A628553168947D59DCC912042351377AC5FB32"); + return new X9ECParameters(curve, G, n, h); +} + +function secp192k1() { + // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1 + var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"); + var a = BigInteger.ZERO; + var b = fromHex("3"); + //byte[] S = null; + var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" + + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"); + return new X9ECParameters(curve, G, n, h); +} + +function secp192r1() { + // p = 2^192 - 2^64 - 1 + var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"); + var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); + var b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"); + //byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); + var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" + + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"); + return new X9ECParameters(curve, G, n, h); +} + +function secp224r1() { + // p = 2^224 - 2^96 + 1 + var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"); + var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"); + var b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"); + //byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); + var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" + + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"); + return new X9ECParameters(curve, G, n, h); +} + +function secp256r1() { + // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1 + var p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); + var a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); + var b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); + //byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90"); + var n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); + var h = BigInteger.ONE; + var curve = new ECCurveFp(p, a, b); + var G = curve.decodePointHex("04" + + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"); + return new X9ECParameters(curve, G, n, h); +} + +// TODO: make this into a proper hashtable +function getSECCurveByName(name) { + if(name == "secp128r1") return secp128r1(); + if(name == "secp160k1") return secp160k1(); + if(name == "secp160r1") return secp160r1(); + if(name == "secp192k1") return secp192k1(); + if(name == "secp192r1") return secp192r1(); + if(name == "secp224r1") return secp224r1(); + if(name == "secp256r1") return secp256r1(); + return null; +} + +module.exports = { + "secp128r1":secp128r1, + "secp160k1":secp160k1, + "secp160r1":secp160r1, + "secp192k1":secp192k1, + "secp192r1":secp192r1, + "secp224r1":secp224r1, + "secp256r1":secp256r1 +} diff --git a/hm_sunwell/node_modules/ecc-jsbn/package.json b/hm_sunwell/node_modules/ecc-jsbn/package.json new file mode 100644 index 0000000..b28a053 --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/package.json @@ -0,0 +1,82 @@ +{ + "_args": [ + [ + "ecc-jsbn@~0.1.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk" + ] + ], + "_from": "ecc-jsbn@>=0.1.1 <0.2.0", + "_id": "ecc-jsbn@0.1.1", + "_inCache": true, + "_installable": true, + "_location": "/ecc-jsbn", + "_nodeVersion": "0.12.6", + "_npmUser": { + "email": "jeremie@jabber.org", + "name": "quartzjer" + }, + "_npmVersion": "2.11.2", + "_phantomChildren": {}, + "_requested": { + "name": "ecc-jsbn", + "raw": "ecc-jsbn@~0.1.1", + "rawSpec": "~0.1.1", + "scope": null, + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/sshpk" + ], + "_resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "_shasum": "0fc73a9ed5f0d53c38193398523ef7e543777505", + "_shrinkwrap": null, + "_spec": "ecc-jsbn@~0.1.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk", + "author": { + "email": "jeremie@jabber.org", + "name": "Jeremie Miller", + "url": "http://jeremie.com/" + }, + "bugs": { + "url": "https://github.com/quartzjer/ecc-jsbn/issues" + }, + "dependencies": { + "jsbn": "~0.1.0" + }, + "description": "ECC JS code based on JSBN", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "0fc73a9ed5f0d53c38193398523ef7e543777505", + "tarball": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + }, + "gitHead": "d35a360352496721030da645e8054f07efc22487", + "homepage": "https://github.com/quartzjer/ecc-jsbn", + "keywords": [ + "browserify", + "ecc", + "jsbn" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "quartzjer", + "email": "jeremie@jabber.org" + }, + { + "name": "rynomad", + "email": "nomad.ry@gmail.com" + } + ], + "name": "ecc-jsbn", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/quartzjer/ecc-jsbn.git" + }, + "scripts": {}, + "version": "0.1.1" +} diff --git a/hm_sunwell/node_modules/ecc-jsbn/test.js b/hm_sunwell/node_modules/ecc-jsbn/test.js new file mode 100644 index 0000000..bd52abf --- /dev/null +++ b/hm_sunwell/node_modules/ecc-jsbn/test.js @@ -0,0 +1,14 @@ +var ecc = require("./index.js"); +var key1 = new ecc.ECKey(ecc.ECCurves.secp160r1); +var key2 = new ecc.ECKey(ecc.ECCurves.secp160r1); +console.log(key1.deriveSharedSecret(key2)); +var key3 = new ecc.ECKey(ecc.ECCurves.secp160r1,key1.PrivateKey); +var key4 = new ecc.ECKey(ecc.ECCurves.secp160r1,key2.PublicKey,true); +console.log(key3.deriveSharedSecret(key4)); + +var key1 = new ecc.ECKey(ecc.ECCurves.secp256r1); +var key2 = new ecc.ECKey(ecc.ECCurves.secp256r1); +console.log(key1.deriveSharedSecret(key2)); +var key3 = new ecc.ECKey(ecc.ECCurves.secp256r1,key1.PrivateKey); +var key4 = new ecc.ECKey(ecc.ECCurves.secp256r1,key2.PublicKey,true); +console.log(key3.deriveSharedSecret(key4)); diff --git a/hm_sunwell/node_modules/ee-first/LICENSE b/hm_sunwell/node_modules/ee-first/LICENSE new file mode 100644 index 0000000..a7ae8ee --- /dev/null +++ b/hm_sunwell/node_modules/ee-first/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/ee-first/README.md b/hm_sunwell/node_modules/ee-first/README.md new file mode 100644 index 0000000..cbd2478 --- /dev/null +++ b/hm_sunwell/node_modules/ee-first/README.md @@ -0,0 +1,80 @@ +# EE First + +[![NPM version][npm-image]][npm-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] +[![Gittip][gittip-image]][gittip-url] + +Get the first event in a set of event emitters and event pairs, +then clean up after itself. + +## Install + +```sh +$ npm install ee-first +``` + +## API + +```js +var first = require('ee-first') +``` + +### first(arr, listener) + +Invoke `listener` on the first event from the list specified in `arr`. `arr` is +an array of arrays, with each array in the format `[ee, ...event]`. `listener` +will be called only once, the first time any of the given events are emitted. If +`error` is one of the listened events, then if that fires first, the `listener` +will be given the `err` argument. + +The `listener` is invoked as `listener(err, ee, event, args)`, where `err` is the +first argument emitted from an `error` event, if applicable; `ee` is the event +emitter that fired; `event` is the string event name that fired; and `args` is an +array of the arguments that were emitted on the event. + +```js +var ee1 = new EventEmitter() +var ee2 = new EventEmitter() + +first([ + [ee1, 'close', 'end', 'error'], + [ee2, 'error'] +], function (err, ee, event, args) { + // listener invoked +}) +``` + +#### .cancel() + +The group of listeners can be cancelled before being invoked and have all the event +listeners removed from the underlying event emitters. + +```js +var thunk = first([ + [ee1, 'close', 'end', 'error'], + [ee2, 'error'] +], function (err, ee, event, args) { + // listener invoked +}) + +// cancel and clean up +thunk.cancel() +``` + +[npm-image]: https://img.shields.io/npm/v/ee-first.svg?style=flat-square +[npm-url]: https://npmjs.org/package/ee-first +[github-tag]: http://img.shields.io/github/tag/jonathanong/ee-first.svg?style=flat-square +[github-url]: https://github.com/jonathanong/ee-first/tags +[travis-image]: https://img.shields.io/travis/jonathanong/ee-first.svg?style=flat-square +[travis-url]: https://travis-ci.org/jonathanong/ee-first +[coveralls-image]: https://img.shields.io/coveralls/jonathanong/ee-first.svg?style=flat-square +[coveralls-url]: https://coveralls.io/r/jonathanong/ee-first?branch=master +[license-image]: http://img.shields.io/npm/l/ee-first.svg?style=flat-square +[license-url]: LICENSE.md +[downloads-image]: http://img.shields.io/npm/dm/ee-first.svg?style=flat-square +[downloads-url]: https://npmjs.org/package/ee-first +[gittip-image]: https://img.shields.io/gittip/jonathanong.svg?style=flat-square +[gittip-url]: https://www.gittip.com/jonathanong/ diff --git a/hm_sunwell/node_modules/ee-first/index.js b/hm_sunwell/node_modules/ee-first/index.js new file mode 100644 index 0000000..501287c --- /dev/null +++ b/hm_sunwell/node_modules/ee-first/index.js @@ -0,0 +1,95 @@ +/*! + * ee-first + * Copyright(c) 2014 Jonathan Ong + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = first + +/** + * Get the first event in a set of event emitters and event pairs. + * + * @param {array} stuff + * @param {function} done + * @public + */ + +function first(stuff, done) { + if (!Array.isArray(stuff)) + throw new TypeError('arg must be an array of [ee, events...] arrays') + + var cleanups = [] + + for (var i = 0; i < stuff.length; i++) { + var arr = stuff[i] + + if (!Array.isArray(arr) || arr.length < 2) + throw new TypeError('each array member must be [ee, events...]') + + var ee = arr[0] + + for (var j = 1; j < arr.length; j++) { + var event = arr[j] + var fn = listener(event, callback) + + // listen to the event + ee.on(event, fn) + // push this listener to the list of cleanups + cleanups.push({ + ee: ee, + event: event, + fn: fn, + }) + } + } + + function callback() { + cleanup() + done.apply(null, arguments) + } + + function cleanup() { + var x + for (var i = 0; i < cleanups.length; i++) { + x = cleanups[i] + x.ee.removeListener(x.event, x.fn) + } + } + + function thunk(fn) { + done = fn + } + + thunk.cancel = cleanup + + return thunk +} + +/** + * Create the event listener. + * @private + */ + +function listener(event, done) { + return function onevent(arg1) { + var args = new Array(arguments.length) + var ee = this + var err = event === 'error' + ? arg1 + : null + + // copy args to prevent arguments escaping scope + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + + done(err, ee, event, args) + } +} diff --git a/hm_sunwell/node_modules/ee-first/package.json b/hm_sunwell/node_modules/ee-first/package.json new file mode 100644 index 0000000..945310d --- /dev/null +++ b/hm_sunwell/node_modules/ee-first/package.json @@ -0,0 +1,90 @@ +{ + "_args": [ + [ + "ee-first@1.1.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/on-finished" + ] + ], + "_from": "ee-first@1.1.1", + "_id": "ee-first@1.1.1", + "_inCache": true, + "_installable": true, + "_location": "/ee-first", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "ee-first", + "raw": "ee-first@1.1.1", + "rawSpec": "1.1.1", + "scope": null, + "spec": "1.1.1", + "type": "version" + }, + "_requiredBy": [ + "/on-finished" + ], + "_resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "_shasum": "590c61156b0ae2f4f0255732a158b266bc56b21d", + "_shrinkwrap": null, + "_spec": "ee-first@1.1.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/on-finished", + "author": { + "email": "me@jongleberry.com", + "name": "Jonathan Ong", + "url": "http://jongleberry.com" + }, + "bugs": { + "url": "https://github.com/jonathanong/ee-first/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "dependencies": {}, + "description": "return the first event in a set of ee/event pairs", + "devDependencies": { + "istanbul": "0.3.9", + "mocha": "2.2.5" + }, + "directories": {}, + "dist": { + "shasum": "590c61156b0ae2f4f0255732a158b266bc56b21d", + "tarball": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "files": [ + "LICENSE", + "index.js" + ], + "gitHead": "512e0ce4cc3643f603708f965a97b61b1a9c0441", + "homepage": "https://github.com/jonathanong/ee-first", + "license": "MIT", + "maintainers": [ + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "ee-first", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonathanong/ee-first.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.1.1" +} diff --git a/hm_sunwell/node_modules/encodeurl/HISTORY.md b/hm_sunwell/node_modules/encodeurl/HISTORY.md new file mode 100644 index 0000000..06d34a5 --- /dev/null +++ b/hm_sunwell/node_modules/encodeurl/HISTORY.md @@ -0,0 +1,9 @@ +1.0.1 / 2016-06-09 +================== + + * Fix encoding unpaired surrogates at start/end of string + +1.0.0 / 2016-06-08 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/encodeurl/LICENSE b/hm_sunwell/node_modules/encodeurl/LICENSE new file mode 100644 index 0000000..8812229 --- /dev/null +++ b/hm_sunwell/node_modules/encodeurl/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/encodeurl/README.md b/hm_sunwell/node_modules/encodeurl/README.md new file mode 100644 index 0000000..b086133 --- /dev/null +++ b/hm_sunwell/node_modules/encodeurl/README.md @@ -0,0 +1,124 @@ +# encodeurl + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Encode a URL to a percent-encoded form, excluding already-encoded sequences + +## Installation + +```sh +$ npm install encodeurl +``` + +## API + +```js +var encodeUrl = require('encodeurl') +``` + +### encodeUrl(url) + +Encode a URL to a percent-encoded form, excluding already-encoded sequences. + +This function will take an already-encoded URL and encode all the non-URL +code points (as UTF-8 byte sequences). This function will not encode the +"%" character unless it is not part of a valid sequence (`%20` will be +left as-is, but `%foo` will be encoded as `%25foo`). + +This encode is meant to be "safe" and does not throw errors. It will try as +hard as it can to properly encode the given URL, including replacing any raw, +unpaired surrogate pairs with the Unicode replacement character prior to +encoding. + +This function is _similar_ to the intrinsic function `encodeURI`, except it +will not encode the `%` character if that is part of a valid sequence, will +not encode `[` and `]` (for IPv6 hostnames) and will replace raw, unpaired +surrogate pairs with the Unicode replacement character (instead of throwing). + +## Examples + +### Encode a URL containing user-controled data + +```js +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') + +http.createServer(function onRequest (req, res) { + // get encoded form of inbound url + var url = encodeUrl(req.url) + + // create html message + var body = '

Location ' + escapeHtml(url) + ' not found

' + + // send a 404 + res.statusCode = 404 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8'))) + res.end(body, 'utf-8') +}) +``` + +### Encode a URL for use in a header field + +```js +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') +var url = require('url') + +http.createServer(function onRequest (req, res) { + // parse inbound url + var href = url.parse(req) + + // set new host for redirect + href.host = 'localhost' + href.protocol = 'https:' + href.slashes = true + + // create location header + var location = encodeUrl(url.format(href)) + + // create html message + var body = '

Redirecting to new site: ' + escapeHtml(location) + '

' + + // send a 301 + res.statusCode = 301 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8'))) + res.setHeader('Location', location) + res.end(body, 'utf-8') +}) +``` + +## Testing + +```sh +$ npm test +$ npm run lint +``` + +## References + +- [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax][rfc-3986] +- [WHATWG URL Living Standard][whatwg-url] + +[rfc-3986]: https://tools.ietf.org/html/rfc3986 +[whatwg-url]: https://url.spec.whatwg.org/ + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/encodeurl.svg +[npm-url]: https://npmjs.org/package/encodeurl +[node-version-image]: https://img.shields.io/node/v/encodeurl.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/pillarjs/encodeurl.svg +[travis-url]: https://travis-ci.org/pillarjs/encodeurl +[coveralls-image]: https://img.shields.io/coveralls/pillarjs/encodeurl.svg +[coveralls-url]: https://coveralls.io/r/pillarjs/encodeurl?branch=master +[downloads-image]: https://img.shields.io/npm/dm/encodeurl.svg +[downloads-url]: https://npmjs.org/package/encodeurl diff --git a/hm_sunwell/node_modules/encodeurl/index.js b/hm_sunwell/node_modules/encodeurl/index.js new file mode 100644 index 0000000..ae77cc9 --- /dev/null +++ b/hm_sunwell/node_modules/encodeurl/index.js @@ -0,0 +1,60 @@ +/*! + * encodeurl + * Copyright(c) 2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = encodeUrl + +/** + * RegExp to match non-URL code points, *after* encoding (i.e. not including "%") + * and including invalid escape sequences. + * @private + */ + +var ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]))+/g + +/** + * RegExp to match unmatched surrogate pair. + * @private + */ + +var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g + +/** + * String to replace unmatched surrogate pair with. + * @private + */ + +var UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2' + +/** + * Encode a URL to a percent-encoded form, excluding already-encoded sequences. + * + * This function will take an already-encoded URL and encode all the non-URL + * code points. This function will not encode the "%" character unless it is + * not part of a valid sequence (`%20` will be left as-is, but `%foo` will + * be encoded as `%25foo`). + * + * This encode is meant to be "safe" and does not throw errors. It will try as + * hard as it can to properly encode the given URL, including replacing any raw, + * unpaired surrogate pairs with the Unicode replacement character prior to + * encoding. + * + * @param {string} url + * @return {string} + * @public + */ + +function encodeUrl (url) { + return String(url) + .replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE) + .replace(ENCODE_CHARS_REGEXP, encodeURI) +} diff --git a/hm_sunwell/node_modules/encodeurl/package.json b/hm_sunwell/node_modules/encodeurl/package.json new file mode 100644 index 0000000..e8a26a0 --- /dev/null +++ b/hm_sunwell/node_modules/encodeurl/package.json @@ -0,0 +1,103 @@ +{ + "_args": [ + [ + "encodeurl@~1.0.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "encodeurl@>=1.0.1 <1.1.0", + "_id": "encodeurl@1.0.1", + "_inCache": true, + "_installable": true, + "_location": "/encodeurl", + "_nodeVersion": "4.4.3", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/encodeurl-1.0.1.tgz_1465519736251_0.09314409433864057" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "2.15.1", + "_phantomChildren": {}, + "_requested": { + "name": "encodeurl", + "raw": "encodeurl@~1.0.1", + "rawSpec": "~1.0.1", + "scope": null, + "spec": ">=1.0.1 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/express", + "/send", + "/serve-static" + ], + "_resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "_shasum": "79e3d58655346909fe6f0f45a5de68103b294d20", + "_shrinkwrap": null, + "_spec": "encodeurl@~1.0.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "bugs": { + "url": "https://github.com/pillarjs/encodeurl/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "dependencies": {}, + "description": "Encode a URL to a percent-encoded form, excluding already-encoded sequences", + "devDependencies": { + "eslint": "2.11.1", + "eslint-config-standard": "5.3.1", + "eslint-plugin-promise": "1.3.2", + "eslint-plugin-standard": "1.3.2", + "istanbul": "0.4.3", + "mocha": "2.5.3" + }, + "directories": {}, + "dist": { + "shasum": "79e3d58655346909fe6f0f45a5de68103b294d20", + "tarball": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "gitHead": "39ed0c235fed4cea7d012038fd6bb0480561d226", + "homepage": "https://github.com/pillarjs/encodeurl#readme", + "keywords": [ + "encode", + "encodeurl", + "url" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "encodeurl", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/pillarjs/encodeurl.git" + }, + "scripts": { + "lint": "eslint **/*.js", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.0.1" +} diff --git a/hm_sunwell/node_modules/escape-html/LICENSE b/hm_sunwell/node_modules/escape-html/LICENSE new file mode 100644 index 0000000..2e70de9 --- /dev/null +++ b/hm_sunwell/node_modules/escape-html/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012-2013 TJ Holowaychuk +Copyright (c) 2015 Andreas Lubbe +Copyright (c) 2015 Tiancheng "Timothy" Gu + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/escape-html/Readme.md b/hm_sunwell/node_modules/escape-html/Readme.md new file mode 100644 index 0000000..653d9ea --- /dev/null +++ b/hm_sunwell/node_modules/escape-html/Readme.md @@ -0,0 +1,43 @@ + +# escape-html + + Escape string for use in HTML + +## Example + +```js +var escape = require('escape-html'); +var html = escape('foo & bar'); +// -> foo & bar +``` + +## Benchmark + +``` +$ npm run-script bench + +> escape-html@1.0.3 bench nodejs-escape-html +> node benchmark/index.js + + + http_parser@1.0 + node@0.10.33 + v8@3.14.5.9 + ares@1.9.0-DEV + uv@0.10.29 + zlib@1.2.3 + modules@11 + openssl@1.0.1j + + 1 test completed. + 2 tests completed. + 3 tests completed. + + no special characters x 19,435,271 ops/sec ±0.85% (187 runs sampled) + single special character x 6,132,421 ops/sec ±0.67% (194 runs sampled) + many special characters x 3,175,826 ops/sec ±0.65% (193 runs sampled) +``` + +## License + + MIT \ No newline at end of file diff --git a/hm_sunwell/node_modules/escape-html/index.js b/hm_sunwell/node_modules/escape-html/index.js new file mode 100644 index 0000000..bf9e226 --- /dev/null +++ b/hm_sunwell/node_modules/escape-html/index.js @@ -0,0 +1,78 @@ +/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */ + +'use strict'; + +/** + * Module variables. + * @private + */ + +var matchHtmlRegExp = /["'&<>]/; + +/** + * Module exports. + * @public + */ + +module.exports = escapeHtml; + +/** + * Escape special characters in the given string of html. + * + * @param {string} string The string to escape for inserting into HTML + * @return {string} + * @public + */ + +function escapeHtml(string) { + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index = 0; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: // " + escape = '"'; + break; + case 38: // & + escape = '&'; + break; + case 39: // ' + escape = '''; + break; + case 60: // < + escape = '<'; + break; + case 62: // > + escape = '>'; + break; + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index + ? html + str.substring(lastIndex, index) + : html; +} diff --git a/hm_sunwell/node_modules/escape-html/package.json b/hm_sunwell/node_modules/escape-html/package.json new file mode 100644 index 0000000..20a6b4f --- /dev/null +++ b/hm_sunwell/node_modules/escape-html/package.json @@ -0,0 +1,86 @@ +{ + "_args": [ + [ + "escape-html@~1.0.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "escape-html@>=1.0.3 <1.1.0", + "_id": "escape-html@1.0.3", + "_inCache": true, + "_installable": true, + "_location": "/escape-html", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "escape-html", + "raw": "escape-html@~1.0.3", + "rawSpec": "~1.0.3", + "scope": null, + "spec": ">=1.0.3 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/express", + "/finalhandler", + "/send", + "/serve-static" + ], + "_resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "_shasum": "0258eae4d3d0c0974de1c169188ef0051d1d1988", + "_shrinkwrap": null, + "_spec": "escape-html@~1.0.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "bugs": { + "url": "https://github.com/component/escape-html/issues" + }, + "dependencies": {}, + "description": "Escape string for use in HTML", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "1.0.0" + }, + "directories": {}, + "dist": { + "shasum": "0258eae4d3d0c0974de1c169188ef0051d1d1988", + "tarball": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "files": [ + "LICENSE", + "Readme.md", + "index.js" + ], + "gitHead": "7ac2ea3977fcac3d4c5be8d2a037812820c65f28", + "homepage": "https://github.com/component/escape-html", + "keywords": [ + "escape", + "html", + "utility" + ], + "license": "MIT", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "escape-html", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/component/escape-html.git" + }, + "scripts": { + "bench": "node benchmark/index.js" + }, + "version": "1.0.3" +} diff --git a/hm_sunwell/node_modules/escape-string-regexp/index.js b/hm_sunwell/node_modules/escape-string-regexp/index.js new file mode 100644 index 0000000..7834bf9 --- /dev/null +++ b/hm_sunwell/node_modules/escape-string-regexp/index.js @@ -0,0 +1,11 @@ +'use strict'; + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(matchOperatorsRe, '\\$&'); +}; diff --git a/hm_sunwell/node_modules/escape-string-regexp/license b/hm_sunwell/node_modules/escape-string-regexp/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/hm_sunwell/node_modules/escape-string-regexp/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/escape-string-regexp/package.json b/hm_sunwell/node_modules/escape-string-regexp/package.json new file mode 100644 index 0000000..64c9ceb --- /dev/null +++ b/hm_sunwell/node_modules/escape-string-regexp/package.json @@ -0,0 +1,101 @@ +{ + "_args": [ + [ + "escape-string-regexp@^1.0.2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/chalk" + ] + ], + "_from": "escape-string-regexp@>=1.0.2 <2.0.0", + "_id": "escape-string-regexp@1.0.5", + "_inCache": true, + "_installable": true, + "_location": "/escape-string-regexp", + "_nodeVersion": "4.2.6", + "_npmOperationalInternal": { + "host": "packages-9-west.internal.npmjs.com", + "tmp": "tmp/escape-string-regexp-1.0.5.tgz_1456059312074_0.7245344955008477" + }, + "_npmUser": { + "email": "jappelman@xebia.com", + "name": "jbnicolai" + }, + "_npmVersion": "2.14.12", + "_phantomChildren": {}, + "_requested": { + "name": "escape-string-regexp", + "raw": "escape-string-regexp@^1.0.2", + "rawSpec": "^1.0.2", + "scope": null, + "spec": ">=1.0.2 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/chalk" + ], + "_resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "_shasum": "1b61c0562190a8dff6ae3bb2cf0200ca130b86d4", + "_shrinkwrap": null, + "_spec": "escape-string-regexp@^1.0.2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/chalk", + "author": { + "email": "sindresorhus@gmail.com", + "name": "Sindre Sorhus", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/escape-string-regexp/issues" + }, + "dependencies": {}, + "description": "Escape RegExp special characters", + "devDependencies": { + "ava": "*", + "xo": "*" + }, + "directories": {}, + "dist": { + "shasum": "1b61c0562190a8dff6ae3bb2cf0200ca130b86d4", + "tarball": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + }, + "engines": { + "node": ">=0.8.0" + }, + "files": [ + "index.js" + ], + "gitHead": "db124a3e1aae9d692c4899e42a5c6c3e329eaa20", + "homepage": "https://github.com/sindresorhus/escape-string-regexp", + "keywords": [ + "characters", + "escape", + "expression", + "re", + "regex", + "regexp", + "regular", + "special", + "str", + "string" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + } + ], + "name": "escape-string-regexp", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/escape-string-regexp.git" + }, + "scripts": { + "test": "xo && ava" + }, + "version": "1.0.5" +} diff --git a/hm_sunwell/node_modules/escape-string-regexp/readme.md b/hm_sunwell/node_modules/escape-string-regexp/readme.md new file mode 100644 index 0000000..87ac82d --- /dev/null +++ b/hm_sunwell/node_modules/escape-string-regexp/readme.md @@ -0,0 +1,27 @@ +# escape-string-regexp [![Build Status](https://travis-ci.org/sindresorhus/escape-string-regexp.svg?branch=master)](https://travis-ci.org/sindresorhus/escape-string-regexp) + +> Escape RegExp special characters + + +## Install + +``` +$ npm install --save escape-string-regexp +``` + + +## Usage + +```js +const escapeStringRegexp = require('escape-string-regexp'); + +const escapedString = escapeStringRegexp('how much $ for a unicorn?'); +//=> 'how much \$ for a unicorn\?' + +new RegExp(escapedString); +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/hm_sunwell/node_modules/escodegen/LICENSE.BSD b/hm_sunwell/node_modules/escodegen/LICENSE.BSD new file mode 100644 index 0000000..3e580c3 --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/LICENSE.BSD @@ -0,0 +1,19 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/escodegen/LICENSE.source-map b/hm_sunwell/node_modules/escodegen/LICENSE.source-map new file mode 100644 index 0000000..259c59f --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/LICENSE.source-map @@ -0,0 +1,27 @@ +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/escodegen/README.md b/hm_sunwell/node_modules/escodegen/README.md new file mode 100644 index 0000000..e867e4b --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/README.md @@ -0,0 +1,116 @@ +## Escodegen +[![npm version](https://badge.fury.io/js/escodegen.svg)](http://badge.fury.io/js/escodegen) +[![Build Status](https://secure.travis-ci.org/estools/escodegen.svg)](http://travis-ci.org/estools/escodegen) +[![Dependency Status](https://david-dm.org/estools/escodegen.svg)](https://david-dm.org/estools/escodegen) +[![devDependency Status](https://david-dm.org/estools/escodegen/dev-status.svg)](https://david-dm.org/estools/escodegen#info=devDependencies) + +Escodegen ([escodegen](http://github.com/estools/escodegen)) is an +[ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm) +(also popularly known as [JavaScript](http://en.wikipedia.org/wiki/JavaScript)) +code generator from [Mozilla's Parser API](https://developer.mozilla.org/en/SpiderMonkey/Parser_API) +AST. See the [online generator](https://estools.github.io/escodegen/demo/index.html) +for a demo. + + +### Install + +Escodegen can be used in a web browser: + + + +escodegen.browser.js can be found in tagged revisions on GitHub. + +Or in a Node.js application via npm: + + npm install escodegen + +### Usage + +A simple example: the program + + escodegen.generate({ + type: 'BinaryExpression', + operator: '+', + left: { type: 'Literal', value: 40 }, + right: { type: 'Literal', value: 2 } + }); + +produces the string `'40 + 2'`. + +See the [API page](https://github.com/estools/escodegen/wiki/API) for +options. To run the tests, execute `npm test` in the root directory. + +### Building browser bundle / minified browser bundle + +At first, execute `npm install` to install the all dev dependencies. +After that, + + npm run-script build + +will generate `escodegen.browser.js`, which can be used in browser environments. + +And, + + npm run-script build-min + +will generate the minified file `escodegen.browser.min.js`. + +### License + +#### Escodegen + +Copyright (C) 2012 [Yusuke Suzuki](http://github.com/Constellation) + (twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#### source-map + +SourceNodeMocks has a limited interface of mozilla/source-map SourceNode implementations. + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/escodegen/bin/escodegen.js b/hm_sunwell/node_modules/escodegen/bin/escodegen.js new file mode 100644 index 0000000..a7c38aa --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/bin/escodegen.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node +/* + Copyright (C) 2012 Yusuke Suzuki + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint sloppy:true node:true */ + +var fs = require('fs'), + path = require('path'), + root = path.join(path.dirname(fs.realpathSync(__filename)), '..'), + esprima = require('esprima'), + escodegen = require(root), + optionator = require('optionator')({ + prepend: 'Usage: escodegen [options] file...', + options: [ + { + option: 'config', + alias: 'c', + type: 'String', + description: 'configuration json for escodegen' + } + ] + }), + args = optionator.parse(process.argv), + files = args._, + options, + esprimaOptions = { + raw: true, + tokens: true, + range: true, + comment: true + }; + +if (files.length === 0) { + console.log(optionator.generateHelp()); + process.exit(1); +} + +if (args.config) { + try { + options = JSON.parse(fs.readFileSync(args.config, 'utf-8')); + } catch (err) { + console.error('Error parsing config: ', err); + } +} + +files.forEach(function (filename) { + var content = fs.readFileSync(filename, 'utf-8'), + syntax = esprima.parse(content, esprimaOptions); + + if (options.comment) { + escodegen.attachComments(syntax, syntax.comments, syntax.tokens); + } + + console.log(escodegen.generate(syntax, options)); +}); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/escodegen/bin/esgenerate.js b/hm_sunwell/node_modules/escodegen/bin/esgenerate.js new file mode 100644 index 0000000..449abcc --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/bin/esgenerate.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node +/* + Copyright (C) 2012 Yusuke Suzuki + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint sloppy:true node:true */ + +var fs = require('fs'), + path = require('path'), + root = path.join(path.dirname(fs.realpathSync(__filename)), '..'), + escodegen = require(root), + optionator = require('optionator')({ + prepend: 'Usage: esgenerate [options] file.json ...', + options: [ + { + option: 'config', + alias: 'c', + type: 'String', + description: 'configuration json for escodegen' + } + ] + }), + args = optionator.parse(process.argv), + files = args._, + options; + +if (files.length === 0) { + console.log(optionator.generateHelp()); + process.exit(1); +} + +if (args.config) { + try { + options = JSON.parse(fs.readFileSync(args.config, 'utf-8')) + } catch (err) { + console.error('Error parsing config: ', err); + } +} + +files.forEach(function (filename) { + var content = fs.readFileSync(filename, 'utf-8'); + console.log(escodegen.generate(JSON.parse(content), options)); +}); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/escodegen/escodegen.js b/hm_sunwell/node_modules/escodegen/escodegen.js new file mode 100644 index 0000000..6202819 --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/escodegen.js @@ -0,0 +1,2607 @@ +/* + Copyright (C) 2012-2014 Yusuke Suzuki + Copyright (C) 2015 Ingvar Stepanyan + Copyright (C) 2014 Ivan Nikulin + Copyright (C) 2012-2013 Michael Ficarra + Copyright (C) 2012-2013 Mathias Bynens + Copyright (C) 2013 Irakli Gozalishvili + Copyright (C) 2012 Robert Gust-Bardon + Copyright (C) 2012 John Freeman + Copyright (C) 2011-2012 Ariya Hidayat + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Arpad Borsos + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*global exports:true, require:true, global:true*/ +(function () { + 'use strict'; + + var Syntax, + Precedence, + BinaryPrecedence, + SourceNode, + estraverse, + esutils, + isArray, + base, + indent, + json, + renumber, + hexadecimal, + quotes, + escapeless, + newline, + space, + parentheses, + semicolons, + safeConcatenation, + directive, + extra, + parse, + sourceMap, + sourceCode, + preserveBlankLines, + FORMAT_MINIFY, + FORMAT_DEFAULTS; + + estraverse = require('estraverse'); + esutils = require('esutils'); + + Syntax = estraverse.Syntax; + + // Generation is done by generateExpression. + function isExpression(node) { + return CodeGenerator.Expression.hasOwnProperty(node.type); + } + + // Generation is done by generateStatement. + function isStatement(node) { + return CodeGenerator.Statement.hasOwnProperty(node.type); + } + + Precedence = { + Sequence: 0, + Yield: 1, + Await: 1, + Assignment: 1, + Conditional: 2, + ArrowFunction: 2, + LogicalOR: 3, + LogicalAND: 4, + BitwiseOR: 5, + BitwiseXOR: 6, + BitwiseAND: 7, + Equality: 8, + Relational: 9, + BitwiseSHIFT: 10, + Additive: 11, + Multiplicative: 12, + Unary: 13, + Postfix: 14, + Call: 15, + New: 16, + TaggedTemplate: 17, + Member: 18, + Primary: 19 + }; + + BinaryPrecedence = { + '||': Precedence.LogicalOR, + '&&': Precedence.LogicalAND, + '|': Precedence.BitwiseOR, + '^': Precedence.BitwiseXOR, + '&': Precedence.BitwiseAND, + '==': Precedence.Equality, + '!=': Precedence.Equality, + '===': Precedence.Equality, + '!==': Precedence.Equality, + 'is': Precedence.Equality, + 'isnt': Precedence.Equality, + '<': Precedence.Relational, + '>': Precedence.Relational, + '<=': Precedence.Relational, + '>=': Precedence.Relational, + 'in': Precedence.Relational, + 'instanceof': Precedence.Relational, + '<<': Precedence.BitwiseSHIFT, + '>>': Precedence.BitwiseSHIFT, + '>>>': Precedence.BitwiseSHIFT, + '+': Precedence.Additive, + '-': Precedence.Additive, + '*': Precedence.Multiplicative, + '%': Precedence.Multiplicative, + '/': Precedence.Multiplicative + }; + + //Flags + var F_ALLOW_IN = 1, + F_ALLOW_CALL = 1 << 1, + F_ALLOW_UNPARATH_NEW = 1 << 2, + F_FUNC_BODY = 1 << 3, + F_DIRECTIVE_CTX = 1 << 4, + F_SEMICOLON_OPT = 1 << 5; + + //Expression flag sets + //NOTE: Flag order: + // F_ALLOW_IN + // F_ALLOW_CALL + // F_ALLOW_UNPARATH_NEW + var E_FTT = F_ALLOW_CALL | F_ALLOW_UNPARATH_NEW, + E_TTF = F_ALLOW_IN | F_ALLOW_CALL, + E_TTT = F_ALLOW_IN | F_ALLOW_CALL | F_ALLOW_UNPARATH_NEW, + E_TFF = F_ALLOW_IN, + E_FFT = F_ALLOW_UNPARATH_NEW, + E_TFT = F_ALLOW_IN | F_ALLOW_UNPARATH_NEW; + + //Statement flag sets + //NOTE: Flag order: + // F_ALLOW_IN + // F_FUNC_BODY + // F_DIRECTIVE_CTX + // F_SEMICOLON_OPT + var S_TFFF = F_ALLOW_IN, + S_TFFT = F_ALLOW_IN | F_SEMICOLON_OPT, + S_FFFF = 0x00, + S_TFTF = F_ALLOW_IN | F_DIRECTIVE_CTX, + S_TTFF = F_ALLOW_IN | F_FUNC_BODY; + + function getDefaultOptions() { + // default options + return { + indent: null, + base: null, + parse: null, + comment: false, + format: { + indent: { + style: ' ', + base: 0, + adjustMultilineComment: false + }, + newline: '\n', + space: ' ', + json: false, + renumber: false, + hexadecimal: false, + quotes: 'single', + escapeless: false, + compact: false, + parentheses: true, + semicolons: true, + safeConcatenation: false, + preserveBlankLines: false + }, + moz: { + comprehensionExpressionStartsWithAssignment: false, + starlessGenerator: false + }, + sourceMap: null, + sourceMapRoot: null, + sourceMapWithCode: false, + directive: false, + raw: true, + verbatim: null, + sourceCode: null + }; + } + + function stringRepeat(str, num) { + var result = ''; + + for (num |= 0; num > 0; num >>>= 1, str += str) { + if (num & 1) { + result += str; + } + } + + return result; + } + + isArray = Array.isArray; + if (!isArray) { + isArray = function isArray(array) { + return Object.prototype.toString.call(array) === '[object Array]'; + }; + } + + function hasLineTerminator(str) { + return (/[\r\n]/g).test(str); + } + + function endsWithLineTerminator(str) { + var len = str.length; + return len && esutils.code.isLineTerminator(str.charCodeAt(len - 1)); + } + + function merge(target, override) { + var key; + for (key in override) { + if (override.hasOwnProperty(key)) { + target[key] = override[key]; + } + } + return target; + } + + function updateDeeply(target, override) { + var key, val; + + function isHashObject(target) { + return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp); + } + + for (key in override) { + if (override.hasOwnProperty(key)) { + val = override[key]; + if (isHashObject(val)) { + if (isHashObject(target[key])) { + updateDeeply(target[key], val); + } else { + target[key] = updateDeeply({}, val); + } + } else { + target[key] = val; + } + } + } + return target; + } + + function generateNumber(value) { + var result, point, temp, exponent, pos; + + if (value !== value) { + throw new Error('Numeric literal whose value is NaN'); + } + if (value < 0 || (value === 0 && 1 / value < 0)) { + throw new Error('Numeric literal whose value is negative'); + } + + if (value === 1 / 0) { + return json ? 'null' : renumber ? '1e400' : '1e+400'; + } + + result = '' + value; + if (!renumber || result.length < 3) { + return result; + } + + point = result.indexOf('.'); + if (!json && result.charCodeAt(0) === 0x30 /* 0 */ && point === 1) { + point = 0; + result = result.slice(1); + } + temp = result; + result = result.replace('e+', 'e'); + exponent = 0; + if ((pos = temp.indexOf('e')) > 0) { + exponent = +temp.slice(pos + 1); + temp = temp.slice(0, pos); + } + if (point >= 0) { + exponent -= temp.length - point - 1; + temp = +(temp.slice(0, point) + temp.slice(point + 1)) + ''; + } + pos = 0; + while (temp.charCodeAt(temp.length + pos - 1) === 0x30 /* 0 */) { + --pos; + } + if (pos !== 0) { + exponent -= pos; + temp = temp.slice(0, pos); + } + if (exponent !== 0) { + temp += 'e' + exponent; + } + if ((temp.length < result.length || + (hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) && + +temp === value) { + result = temp; + } + + return result; + } + + // Generate valid RegExp expression. + // This function is based on https://github.com/Constellation/iv Engine + + function escapeRegExpCharacter(ch, previousIsBackslash) { + // not handling '\' and handling \u2028 or \u2029 to unicode escape sequence + if ((ch & ~1) === 0x2028) { + return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029'); + } else if (ch === 10 || ch === 13) { // \n, \r + return (previousIsBackslash ? '' : '\\') + ((ch === 10) ? 'n' : 'r'); + } + return String.fromCharCode(ch); + } + + function generateRegExp(reg) { + var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash; + + result = reg.toString(); + + if (reg.source) { + // extract flag from toString result + match = result.match(/\/([^/]*)$/); + if (!match) { + return result; + } + + flags = match[1]; + result = ''; + + characterInBrack = false; + previousIsBackslash = false; + for (i = 0, iz = reg.source.length; i < iz; ++i) { + ch = reg.source.charCodeAt(i); + + if (!previousIsBackslash) { + if (characterInBrack) { + if (ch === 93) { // ] + characterInBrack = false; + } + } else { + if (ch === 47) { // / + result += '\\'; + } else if (ch === 91) { // [ + characterInBrack = true; + } + } + result += escapeRegExpCharacter(ch, previousIsBackslash); + previousIsBackslash = ch === 92; // \ + } else { + // if new RegExp("\\\n') is provided, create /\n/ + result += escapeRegExpCharacter(ch, previousIsBackslash); + // prevent like /\\[/]/ + previousIsBackslash = false; + } + } + + return '/' + result + '/' + flags; + } + + return result; + } + + function escapeAllowedCharacter(code, next) { + var hex; + + if (code === 0x08 /* \b */) { + return '\\b'; + } + + if (code === 0x0C /* \f */) { + return '\\f'; + } + + if (code === 0x09 /* \t */) { + return '\\t'; + } + + hex = code.toString(16).toUpperCase(); + if (json || code > 0xFF) { + return '\\u' + '0000'.slice(hex.length) + hex; + } else if (code === 0x0000 && !esutils.code.isDecimalDigit(next)) { + return '\\0'; + } else if (code === 0x000B /* \v */) { // '\v' + return '\\x0B'; + } else { + return '\\x' + '00'.slice(hex.length) + hex; + } + } + + function escapeDisallowedCharacter(code) { + if (code === 0x5C /* \ */) { + return '\\\\'; + } + + if (code === 0x0A /* \n */) { + return '\\n'; + } + + if (code === 0x0D /* \r */) { + return '\\r'; + } + + if (code === 0x2028) { + return '\\u2028'; + } + + if (code === 0x2029) { + return '\\u2029'; + } + + throw new Error('Incorrectly classified character'); + } + + function escapeDirective(str) { + var i, iz, code, quote; + + quote = quotes === 'double' ? '"' : '\''; + for (i = 0, iz = str.length; i < iz; ++i) { + code = str.charCodeAt(i); + if (code === 0x27 /* ' */) { + quote = '"'; + break; + } else if (code === 0x22 /* " */) { + quote = '\''; + break; + } else if (code === 0x5C /* \ */) { + ++i; + } + } + + return quote + str + quote; + } + + function escapeString(str) { + var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote; + + for (i = 0, len = str.length; i < len; ++i) { + code = str.charCodeAt(i); + if (code === 0x27 /* ' */) { + ++singleQuotes; + } else if (code === 0x22 /* " */) { + ++doubleQuotes; + } else if (code === 0x2F /* / */ && json) { + result += '\\'; + } else if (esutils.code.isLineTerminator(code) || code === 0x5C /* \ */) { + result += escapeDisallowedCharacter(code); + continue; + } else if (!esutils.code.isIdentifierPartES5(code) && (json && code < 0x20 /* SP */ || !json && !escapeless && (code < 0x20 /* SP */ || code > 0x7E /* ~ */))) { + result += escapeAllowedCharacter(code, str.charCodeAt(i + 1)); + continue; + } + result += String.fromCharCode(code); + } + + single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes)); + quote = single ? '\'' : '"'; + + if (!(single ? singleQuotes : doubleQuotes)) { + return quote + result + quote; + } + + str = result; + result = quote; + + for (i = 0, len = str.length; i < len; ++i) { + code = str.charCodeAt(i); + if ((code === 0x27 /* ' */ && single) || (code === 0x22 /* " */ && !single)) { + result += '\\'; + } + result += String.fromCharCode(code); + } + + return result + quote; + } + + /** + * flatten an array to a string, where the array can contain + * either strings or nested arrays + */ + function flattenToString(arr) { + var i, iz, elem, result = ''; + for (i = 0, iz = arr.length; i < iz; ++i) { + elem = arr[i]; + result += isArray(elem) ? flattenToString(elem) : elem; + } + return result; + } + + /** + * convert generated to a SourceNode when source maps are enabled. + */ + function toSourceNodeWhenNeeded(generated, node) { + if (!sourceMap) { + // with no source maps, generated is either an + // array or a string. if an array, flatten it. + // if a string, just return it + if (isArray(generated)) { + return flattenToString(generated); + } else { + return generated; + } + } + if (node == null) { + if (generated instanceof SourceNode) { + return generated; + } else { + node = {}; + } + } + if (node.loc == null) { + return new SourceNode(null, null, sourceMap, generated, node.name || null); + } + return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated, node.name || null); + } + + function noEmptySpace() { + return (space) ? space : ' '; + } + + function join(left, right) { + var leftSource, + rightSource, + leftCharCode, + rightCharCode; + + leftSource = toSourceNodeWhenNeeded(left).toString(); + if (leftSource.length === 0) { + return [right]; + } + + rightSource = toSourceNodeWhenNeeded(right).toString(); + if (rightSource.length === 0) { + return [left]; + } + + leftCharCode = leftSource.charCodeAt(leftSource.length - 1); + rightCharCode = rightSource.charCodeAt(0); + + if ((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode || + esutils.code.isIdentifierPartES5(leftCharCode) && esutils.code.isIdentifierPartES5(rightCharCode) || + leftCharCode === 0x2F /* / */ && rightCharCode === 0x69 /* i */) { // infix word operators all start with `i` + return [left, noEmptySpace(), right]; + } else if (esutils.code.isWhiteSpace(leftCharCode) || esutils.code.isLineTerminator(leftCharCode) || + esutils.code.isWhiteSpace(rightCharCode) || esutils.code.isLineTerminator(rightCharCode)) { + return [left, right]; + } + return [left, space, right]; + } + + function addIndent(stmt) { + return [base, stmt]; + } + + function withIndent(fn) { + var previousBase; + previousBase = base; + base += indent; + fn(base); + base = previousBase; + } + + function calculateSpaces(str) { + var i; + for (i = str.length - 1; i >= 0; --i) { + if (esutils.code.isLineTerminator(str.charCodeAt(i))) { + break; + } + } + return (str.length - 1) - i; + } + + function adjustMultilineComment(value, specialBase) { + var array, i, len, line, j, spaces, previousBase, sn; + + array = value.split(/\r\n|[\r\n]/); + spaces = Number.MAX_VALUE; + + // first line doesn't have indentation + for (i = 1, len = array.length; i < len; ++i) { + line = array[i]; + j = 0; + while (j < line.length && esutils.code.isWhiteSpace(line.charCodeAt(j))) { + ++j; + } + if (spaces > j) { + spaces = j; + } + } + + if (typeof specialBase !== 'undefined') { + // pattern like + // { + // var t = 20; /* + // * this is comment + // */ + // } + previousBase = base; + if (array[1][spaces] === '*') { + specialBase += ' '; + } + base = specialBase; + } else { + if (spaces & 1) { + // /* + // * + // */ + // If spaces are odd number, above pattern is considered. + // We waste 1 space. + --spaces; + } + previousBase = base; + } + + for (i = 1, len = array.length; i < len; ++i) { + sn = toSourceNodeWhenNeeded(addIndent(array[i].slice(spaces))); + array[i] = sourceMap ? sn.join('') : sn; + } + + base = previousBase; + + return array.join('\n'); + } + + function generateComment(comment, specialBase) { + if (comment.type === 'Line') { + if (endsWithLineTerminator(comment.value)) { + return '//' + comment.value; + } else { + // Always use LineTerminator + var result = '//' + comment.value; + if (!preserveBlankLines) { + result += '\n'; + } + return result; + } + } + if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) { + return adjustMultilineComment('/*' + comment.value + '*/', specialBase); + } + return '/*' + comment.value + '*/'; + } + + function addComments(stmt, result) { + var i, len, comment, save, tailingToStatement, specialBase, fragment, + extRange, range, prevRange, prefix, infix, suffix, count; + + if (stmt.leadingComments && stmt.leadingComments.length > 0) { + save = result; + + if (preserveBlankLines) { + comment = stmt.leadingComments[0]; + result = []; + + extRange = comment.extendedRange; + range = comment.range; + + prefix = sourceCode.substring(extRange[0], range[0]); + count = (prefix.match(/\n/g) || []).length; + if (count > 0) { + result.push(stringRepeat('\n', count)); + result.push(addIndent(generateComment(comment))); + } else { + result.push(prefix); + result.push(generateComment(comment)); + } + + prevRange = range; + + for (i = 1, len = stmt.leadingComments.length; i < len; i++) { + comment = stmt.leadingComments[i]; + range = comment.range; + + infix = sourceCode.substring(prevRange[1], range[0]); + count = (infix.match(/\n/g) || []).length; + result.push(stringRepeat('\n', count)); + result.push(addIndent(generateComment(comment))); + + prevRange = range; + } + + suffix = sourceCode.substring(range[1], extRange[1]); + count = (suffix.match(/\n/g) || []).length; + result.push(stringRepeat('\n', count)); + } else { + comment = stmt.leadingComments[0]; + result = []; + if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) { + result.push('\n'); + } + result.push(generateComment(comment)); + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push('\n'); + } + + for (i = 1, len = stmt.leadingComments.length; i < len; ++i) { + comment = stmt.leadingComments[i]; + fragment = [generateComment(comment)]; + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { + fragment.push('\n'); + } + result.push(addIndent(fragment)); + } + } + + result.push(addIndent(save)); + } + + if (stmt.trailingComments) { + + if (preserveBlankLines) { + comment = stmt.trailingComments[0]; + extRange = comment.extendedRange; + range = comment.range; + + prefix = sourceCode.substring(extRange[0], range[0]); + count = (prefix.match(/\n/g) || []).length; + + if (count > 0) { + result.push(stringRepeat('\n', count)); + result.push(addIndent(generateComment(comment))); + } else { + result.push(prefix); + result.push(generateComment(comment)); + } + } else { + tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString()); + specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([base, result, indent]).toString())); + for (i = 0, len = stmt.trailingComments.length; i < len; ++i) { + comment = stmt.trailingComments[i]; + if (tailingToStatement) { + // We assume target like following script + // + // var t = 20; /** + // * This is comment of t + // */ + if (i === 0) { + // first case + result = [result, indent]; + } else { + result = [result, specialBase]; + } + result.push(generateComment(comment, specialBase)); + } else { + result = [result, addIndent(generateComment(comment))]; + } + if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result = [result, '\n']; + } + } + } + } + + return result; + } + + function generateBlankLines(start, end, result) { + var j, newlineCount = 0; + + for (j = start; j < end; j++) { + if (sourceCode[j] === '\n') { + newlineCount++; + } + } + + for (j = 1; j < newlineCount; j++) { + result.push(newline); + } + } + + function parenthesize(text, current, should) { + if (current < should) { + return ['(', text, ')']; + } + return text; + } + + function generateVerbatimString(string) { + var i, iz, result; + result = string.split(/\r\n|\n/); + for (i = 1, iz = result.length; i < iz; i++) { + result[i] = newline + base + result[i]; + } + return result; + } + + function generateVerbatim(expr, precedence) { + var verbatim, result, prec; + verbatim = expr[extra.verbatim]; + + if (typeof verbatim === 'string') { + result = parenthesize(generateVerbatimString(verbatim), Precedence.Sequence, precedence); + } else { + // verbatim is object + result = generateVerbatimString(verbatim.content); + prec = (verbatim.precedence != null) ? verbatim.precedence : Precedence.Sequence; + result = parenthesize(result, prec, precedence); + } + + return toSourceNodeWhenNeeded(result, expr); + } + + function CodeGenerator() { + } + + // Helpers. + + CodeGenerator.prototype.maybeBlock = function(stmt, flags) { + var result, noLeadingComment, that = this; + + noLeadingComment = !extra.comment || !stmt.leadingComments; + + if (stmt.type === Syntax.BlockStatement && noLeadingComment) { + return [space, this.generateStatement(stmt, flags)]; + } + + if (stmt.type === Syntax.EmptyStatement && noLeadingComment) { + return ';'; + } + + withIndent(function () { + result = [ + newline, + addIndent(that.generateStatement(stmt, flags)) + ]; + }); + + return result; + }; + + CodeGenerator.prototype.maybeBlockSuffix = function (stmt, result) { + var ends = endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString()); + if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) { + return [result, space]; + } + if (ends) { + return [result, base]; + } + return [result, newline, base]; + }; + + function generateIdentifier(node) { + return toSourceNodeWhenNeeded(node.name, node); + } + + function generateAsyncPrefix(node, spaceRequired) { + return node.async ? 'async' + (spaceRequired ? noEmptySpace() : space) : ''; + } + + function generateStarSuffix(node) { + var isGenerator = node.generator && !extra.moz.starlessGenerator; + return isGenerator ? '*' + space : ''; + } + + function generateMethodPrefix(prop) { + var func = prop.value; + if (func.async) { + return generateAsyncPrefix(func, !prop.computed); + } else { + // avoid space before method name + return generateStarSuffix(func) ? '*' : ''; + } + } + + CodeGenerator.prototype.generatePattern = function (node, precedence, flags) { + if (node.type === Syntax.Identifier) { + return generateIdentifier(node); + } + return this.generateExpression(node, precedence, flags); + }; + + CodeGenerator.prototype.generateFunctionParams = function (node) { + var i, iz, result, hasDefault; + + hasDefault = false; + + if (node.type === Syntax.ArrowFunctionExpression && + !node.rest && (!node.defaults || node.defaults.length === 0) && + node.params.length === 1 && node.params[0].type === Syntax.Identifier) { + // arg => { } case + result = [generateAsyncPrefix(node, true), generateIdentifier(node.params[0])]; + } else { + result = node.type === Syntax.ArrowFunctionExpression ? [generateAsyncPrefix(node, false)] : []; + result.push('('); + if (node.defaults) { + hasDefault = true; + } + for (i = 0, iz = node.params.length; i < iz; ++i) { + if (hasDefault && node.defaults[i]) { + // Handle default values. + result.push(this.generateAssignment(node.params[i], node.defaults[i], '=', Precedence.Assignment, E_TTT)); + } else { + result.push(this.generatePattern(node.params[i], Precedence.Assignment, E_TTT)); + } + if (i + 1 < iz) { + result.push(',' + space); + } + } + + if (node.rest) { + if (node.params.length) { + result.push(',' + space); + } + result.push('...'); + result.push(generateIdentifier(node.rest)); + } + + result.push(')'); + } + + return result; + }; + + CodeGenerator.prototype.generateFunctionBody = function (node) { + var result, expr; + + result = this.generateFunctionParams(node); + + if (node.type === Syntax.ArrowFunctionExpression) { + result.push(space); + result.push('=>'); + } + + if (node.expression) { + result.push(space); + expr = this.generateExpression(node.body, Precedence.Assignment, E_TTT); + if (expr.toString().charAt(0) === '{') { + expr = ['(', expr, ')']; + } + result.push(expr); + } else { + result.push(this.maybeBlock(node.body, S_TTFF)); + } + + return result; + }; + + CodeGenerator.prototype.generateIterationForStatement = function (operator, stmt, flags) { + var result = ['for' + space + '('], that = this; + withIndent(function () { + if (stmt.left.type === Syntax.VariableDeclaration) { + withIndent(function () { + result.push(stmt.left.kind + noEmptySpace()); + result.push(that.generateStatement(stmt.left.declarations[0], S_FFFF)); + }); + } else { + result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT)); + } + + result = join(result, operator); + result = [join( + result, + that.generateExpression(stmt.right, Precedence.Sequence, E_TTT) + ), ')']; + }); + result.push(this.maybeBlock(stmt.body, flags)); + return result; + }; + + CodeGenerator.prototype.generatePropertyKey = function (expr, computed, value) { + var result = []; + + if (computed) { + result.push('['); + } + + if (value.type === 'AssignmentPattern') { + result.push(this.AssignmentPattern(value, Precedence.Sequence, E_TTT)); + } else { + result.push(this.generateExpression(expr, Precedence.Sequence, E_TTT)); + } + + if (computed) { + result.push(']'); + } + + return result; + }; + + CodeGenerator.prototype.generateAssignment = function (left, right, operator, precedence, flags) { + if (Precedence.Assignment < precedence) { + flags |= F_ALLOW_IN; + } + + return parenthesize( + [ + this.generateExpression(left, Precedence.Call, flags), + space + operator + space, + this.generateExpression(right, Precedence.Assignment, flags) + ], + Precedence.Assignment, + precedence + ); + }; + + CodeGenerator.prototype.semicolon = function (flags) { + if (!semicolons && flags & F_SEMICOLON_OPT) { + return ''; + } + return ';'; + }; + + // Statements. + + CodeGenerator.Statement = { + + BlockStatement: function (stmt, flags) { + var range, content, result = ['{', newline], that = this; + + withIndent(function () { + // handle functions without any code + if (stmt.body.length === 0 && preserveBlankLines) { + range = stmt.range; + if (range[1] - range[0] > 2) { + content = sourceCode.substring(range[0] + 1, range[1] - 1); + if (content[0] === '\n') { + result = ['{']; + } + result.push(content); + } + } + + var i, iz, fragment, bodyFlags; + bodyFlags = S_TFFF; + if (flags & F_FUNC_BODY) { + bodyFlags |= F_DIRECTIVE_CTX; + } + + for (i = 0, iz = stmt.body.length; i < iz; ++i) { + if (preserveBlankLines) { + // handle spaces before the first line + if (i === 0) { + if (stmt.body[0].leadingComments) { + range = stmt.body[0].leadingComments[0].extendedRange; + content = sourceCode.substring(range[0], range[1]); + if (content[0] === '\n') { + result = ['{']; + } + } + if (!stmt.body[0].leadingComments) { + generateBlankLines(stmt.range[0], stmt.body[0].range[0], result); + } + } + + // handle spaces between lines + if (i > 0) { + if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) { + generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result); + } + } + } + + if (i === iz - 1) { + bodyFlags |= F_SEMICOLON_OPT; + } + + if (stmt.body[i].leadingComments && preserveBlankLines) { + fragment = that.generateStatement(stmt.body[i], bodyFlags); + } else { + fragment = addIndent(that.generateStatement(stmt.body[i], bodyFlags)); + } + + result.push(fragment); + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { + if (preserveBlankLines && i < iz - 1) { + // don't add a new line if there are leading coments + // in the next statement + if (!stmt.body[i + 1].leadingComments) { + result.push(newline); + } + } else { + result.push(newline); + } + } + + if (preserveBlankLines) { + // handle spaces after the last line + if (i === iz - 1) { + if (!stmt.body[i].trailingComments) { + generateBlankLines(stmt.body[i].range[1], stmt.range[1], result); + } + } + } + } + }); + + result.push(addIndent('}')); + return result; + }, + + BreakStatement: function (stmt, flags) { + if (stmt.label) { + return 'break ' + stmt.label.name + this.semicolon(flags); + } + return 'break' + this.semicolon(flags); + }, + + ContinueStatement: function (stmt, flags) { + if (stmt.label) { + return 'continue ' + stmt.label.name + this.semicolon(flags); + } + return 'continue' + this.semicolon(flags); + }, + + ClassBody: function (stmt, flags) { + var result = [ '{', newline], that = this; + + withIndent(function (indent) { + var i, iz; + + for (i = 0, iz = stmt.body.length; i < iz; ++i) { + result.push(indent); + result.push(that.generateExpression(stmt.body[i], Precedence.Sequence, E_TTT)); + if (i + 1 < iz) { + result.push(newline); + } + } + }); + + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + result.push(base); + result.push('}'); + return result; + }, + + ClassDeclaration: function (stmt, flags) { + var result, fragment; + result = ['class']; + if (stmt.id) { + result = join(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT)); + } + if (stmt.superClass) { + fragment = join('extends', this.generateExpression(stmt.superClass, Precedence.Assignment, E_TTT)); + result = join(result, fragment); + } + result.push(space); + result.push(this.generateStatement(stmt.body, S_TFFT)); + return result; + }, + + DirectiveStatement: function (stmt, flags) { + if (extra.raw && stmt.raw) { + return stmt.raw + this.semicolon(flags); + } + return escapeDirective(stmt.directive) + this.semicolon(flags); + }, + + DoWhileStatement: function (stmt, flags) { + // Because `do 42 while (cond)` is Syntax Error. We need semicolon. + var result = join('do', this.maybeBlock(stmt.body, S_TFFF)); + result = this.maybeBlockSuffix(stmt.body, result); + return join(result, [ + 'while' + space + '(', + this.generateExpression(stmt.test, Precedence.Sequence, E_TTT), + ')' + this.semicolon(flags) + ]); + }, + + CatchClause: function (stmt, flags) { + var result, that = this; + withIndent(function () { + var guard; + + result = [ + 'catch' + space + '(', + that.generateExpression(stmt.param, Precedence.Sequence, E_TTT), + ')' + ]; + + if (stmt.guard) { + guard = that.generateExpression(stmt.guard, Precedence.Sequence, E_TTT); + result.splice(2, 0, ' if ', guard); + } + }); + result.push(this.maybeBlock(stmt.body, S_TFFF)); + return result; + }, + + DebuggerStatement: function (stmt, flags) { + return 'debugger' + this.semicolon(flags); + }, + + EmptyStatement: function (stmt, flags) { + return ';'; + }, + + ExportDefaultDeclaration: function (stmt, flags) { + var result = [ 'export' ], bodyFlags; + + bodyFlags = (flags & F_SEMICOLON_OPT) ? S_TFFT : S_TFFF; + + // export default HoistableDeclaration[Default] + // export default AssignmentExpression[In] ; + result = join(result, 'default'); + if (isStatement(stmt.declaration)) { + result = join(result, this.generateStatement(stmt.declaration, bodyFlags)); + } else { + result = join(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags)); + } + return result; + }, + + ExportNamedDeclaration: function (stmt, flags) { + var result = [ 'export' ], bodyFlags, that = this; + + bodyFlags = (flags & F_SEMICOLON_OPT) ? S_TFFT : S_TFFF; + + // export VariableStatement + // export Declaration[Default] + if (stmt.declaration) { + return join(result, this.generateStatement(stmt.declaration, bodyFlags)); + } + + // export ExportClause[NoReference] FromClause ; + // export ExportClause ; + if (stmt.specifiers) { + if (stmt.specifiers.length === 0) { + result = join(result, '{' + space + '}'); + } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) { + result = join(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT)); + } else { + result = join(result, '{'); + withIndent(function (indent) { + var i, iz; + result.push(newline); + for (i = 0, iz = stmt.specifiers.length; i < iz; ++i) { + result.push(indent); + result.push(that.generateExpression(stmt.specifiers[i], Precedence.Sequence, E_TTT)); + if (i + 1 < iz) { + result.push(',' + newline); + } + } + }); + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + result.push(base + '}'); + } + + if (stmt.source) { + result = join(result, [ + 'from' + space, + // ModuleSpecifier + this.generateExpression(stmt.source, Precedence.Sequence, E_TTT), + this.semicolon(flags) + ]); + } else { + result.push(this.semicolon(flags)); + } + } + return result; + }, + + ExportAllDeclaration: function (stmt, flags) { + // export * FromClause ; + return [ + 'export' + space, + '*' + space, + 'from' + space, + // ModuleSpecifier + this.generateExpression(stmt.source, Precedence.Sequence, E_TTT), + this.semicolon(flags) + ]; + }, + + ExpressionStatement: function (stmt, flags) { + var result, fragment; + + function isClassPrefixed(fragment) { + var code; + if (fragment.slice(0, 5) !== 'class') { + return false; + } + code = fragment.charCodeAt(5); + return code === 0x7B /* '{' */ || esutils.code.isWhiteSpace(code) || esutils.code.isLineTerminator(code); + } + + function isFunctionPrefixed(fragment) { + var code; + if (fragment.slice(0, 8) !== 'function') { + return false; + } + code = fragment.charCodeAt(8); + return code === 0x28 /* '(' */ || esutils.code.isWhiteSpace(code) || code === 0x2A /* '*' */ || esutils.code.isLineTerminator(code); + } + + function isAsyncPrefixed(fragment) { + var code, i, iz; + if (fragment.slice(0, 5) !== 'async') { + return false; + } + if (!esutils.code.isWhiteSpace(fragment.charCodeAt(5))) { + return false; + } + for (i = 6, iz = fragment.length; i < iz; ++i) { + if (!esutils.code.isWhiteSpace(fragment.charCodeAt(i))) { + break; + } + } + if (i === iz) { + return false; + } + if (fragment.slice(i, i + 8) !== 'function') { + return false; + } + code = fragment.charCodeAt(i + 8); + return code === 0x28 /* '(' */ || esutils.code.isWhiteSpace(code) || code === 0x2A /* '*' */ || esutils.code.isLineTerminator(code); + } + + result = [this.generateExpression(stmt.expression, Precedence.Sequence, E_TTT)]; + // 12.4 '{', 'function', 'class' is not allowed in this position. + // wrap expression with parentheses + fragment = toSourceNodeWhenNeeded(result).toString(); + if (fragment.charCodeAt(0) === 0x7B /* '{' */ || // ObjectExpression + isClassPrefixed(fragment) || + isFunctionPrefixed(fragment) || + isAsyncPrefixed(fragment) || + (directive && (flags & F_DIRECTIVE_CTX) && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) { + result = ['(', result, ')' + this.semicolon(flags)]; + } else { + result.push(this.semicolon(flags)); + } + return result; + }, + + ImportDeclaration: function (stmt, flags) { + // ES6: 15.2.1 valid import declarations: + // - import ImportClause FromClause ; + // - import ModuleSpecifier ; + var result, cursor, that = this; + + // If no ImportClause is present, + // this should be `import ModuleSpecifier` so skip `from` + // ModuleSpecifier is StringLiteral. + if (stmt.specifiers.length === 0) { + // import ModuleSpecifier ; + return [ + 'import', + space, + // ModuleSpecifier + this.generateExpression(stmt.source, Precedence.Sequence, E_TTT), + this.semicolon(flags) + ]; + } + + // import ImportClause FromClause ; + result = [ + 'import' + ]; + cursor = 0; + + // ImportedBinding + if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) { + result = join(result, [ + this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT) + ]); + ++cursor; + } + + if (stmt.specifiers[cursor]) { + if (cursor !== 0) { + result.push(','); + } + + if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) { + // NameSpaceImport + result = join(result, [ + space, + this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT) + ]); + } else { + // NamedImports + result.push(space + '{'); + + if ((stmt.specifiers.length - cursor) === 1) { + // import { ... } from "..."; + result.push(space); + result.push(this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)); + result.push(space + '}' + space); + } else { + // import { + // ..., + // ..., + // } from "..."; + withIndent(function (indent) { + var i, iz; + result.push(newline); + for (i = cursor, iz = stmt.specifiers.length; i < iz; ++i) { + result.push(indent); + result.push(that.generateExpression(stmt.specifiers[i], Precedence.Sequence, E_TTT)); + if (i + 1 < iz) { + result.push(',' + newline); + } + } + }); + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + result.push(base + '}' + space); + } + } + } + + result = join(result, [ + 'from' + space, + // ModuleSpecifier + this.generateExpression(stmt.source, Precedence.Sequence, E_TTT), + this.semicolon(flags) + ]); + return result; + }, + + VariableDeclarator: function (stmt, flags) { + var itemFlags = (flags & F_ALLOW_IN) ? E_TTT : E_FTT; + if (stmt.init) { + return [ + this.generateExpression(stmt.id, Precedence.Assignment, itemFlags), + space, + '=', + space, + this.generateExpression(stmt.init, Precedence.Assignment, itemFlags) + ]; + } + return this.generatePattern(stmt.id, Precedence.Assignment, itemFlags); + }, + + VariableDeclaration: function (stmt, flags) { + // VariableDeclarator is typed as Statement, + // but joined with comma (not LineTerminator). + // So if comment is attached to target node, we should specialize. + var result, i, iz, node, bodyFlags, that = this; + + result = [ stmt.kind ]; + + bodyFlags = (flags & F_ALLOW_IN) ? S_TFFF : S_FFFF; + + function block() { + node = stmt.declarations[0]; + if (extra.comment && node.leadingComments) { + result.push('\n'); + result.push(addIndent(that.generateStatement(node, bodyFlags))); + } else { + result.push(noEmptySpace()); + result.push(that.generateStatement(node, bodyFlags)); + } + + for (i = 1, iz = stmt.declarations.length; i < iz; ++i) { + node = stmt.declarations[i]; + if (extra.comment && node.leadingComments) { + result.push(',' + newline); + result.push(addIndent(that.generateStatement(node, bodyFlags))); + } else { + result.push(',' + space); + result.push(that.generateStatement(node, bodyFlags)); + } + } + } + + if (stmt.declarations.length > 1) { + withIndent(block); + } else { + block(); + } + + result.push(this.semicolon(flags)); + + return result; + }, + + ThrowStatement: function (stmt, flags) { + return [join( + 'throw', + this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT) + ), this.semicolon(flags)]; + }, + + TryStatement: function (stmt, flags) { + var result, i, iz, guardedHandlers; + + result = ['try', this.maybeBlock(stmt.block, S_TFFF)]; + result = this.maybeBlockSuffix(stmt.block, result); + + if (stmt.handlers) { + // old interface + for (i = 0, iz = stmt.handlers.length; i < iz; ++i) { + result = join(result, this.generateStatement(stmt.handlers[i], S_TFFF)); + if (stmt.finalizer || i + 1 !== iz) { + result = this.maybeBlockSuffix(stmt.handlers[i].body, result); + } + } + } else { + guardedHandlers = stmt.guardedHandlers || []; + + for (i = 0, iz = guardedHandlers.length; i < iz; ++i) { + result = join(result, this.generateStatement(guardedHandlers[i], S_TFFF)); + if (stmt.finalizer || i + 1 !== iz) { + result = this.maybeBlockSuffix(guardedHandlers[i].body, result); + } + } + + // new interface + if (stmt.handler) { + if (isArray(stmt.handler)) { + for (i = 0, iz = stmt.handler.length; i < iz; ++i) { + result = join(result, this.generateStatement(stmt.handler[i], S_TFFF)); + if (stmt.finalizer || i + 1 !== iz) { + result = this.maybeBlockSuffix(stmt.handler[i].body, result); + } + } + } else { + result = join(result, this.generateStatement(stmt.handler, S_TFFF)); + if (stmt.finalizer) { + result = this.maybeBlockSuffix(stmt.handler.body, result); + } + } + } + } + if (stmt.finalizer) { + result = join(result, ['finally', this.maybeBlock(stmt.finalizer, S_TFFF)]); + } + return result; + }, + + SwitchStatement: function (stmt, flags) { + var result, fragment, i, iz, bodyFlags, that = this; + withIndent(function () { + result = [ + 'switch' + space + '(', + that.generateExpression(stmt.discriminant, Precedence.Sequence, E_TTT), + ')' + space + '{' + newline + ]; + }); + if (stmt.cases) { + bodyFlags = S_TFFF; + for (i = 0, iz = stmt.cases.length; i < iz; ++i) { + if (i === iz - 1) { + bodyFlags |= F_SEMICOLON_OPT; + } + fragment = addIndent(this.generateStatement(stmt.cases[i], bodyFlags)); + result.push(fragment); + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { + result.push(newline); + } + } + } + result.push(addIndent('}')); + return result; + }, + + SwitchCase: function (stmt, flags) { + var result, fragment, i, iz, bodyFlags, that = this; + withIndent(function () { + if (stmt.test) { + result = [ + join('case', that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)), + ':' + ]; + } else { + result = ['default:']; + } + + i = 0; + iz = stmt.consequent.length; + if (iz && stmt.consequent[0].type === Syntax.BlockStatement) { + fragment = that.maybeBlock(stmt.consequent[0], S_TFFF); + result.push(fragment); + i = 1; + } + + if (i !== iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + + bodyFlags = S_TFFF; + for (; i < iz; ++i) { + if (i === iz - 1 && flags & F_SEMICOLON_OPT) { + bodyFlags |= F_SEMICOLON_OPT; + } + fragment = addIndent(that.generateStatement(stmt.consequent[i], bodyFlags)); + result.push(fragment); + if (i + 1 !== iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { + result.push(newline); + } + } + }); + return result; + }, + + IfStatement: function (stmt, flags) { + var result, bodyFlags, semicolonOptional, that = this; + withIndent(function () { + result = [ + 'if' + space + '(', + that.generateExpression(stmt.test, Precedence.Sequence, E_TTT), + ')' + ]; + }); + semicolonOptional = flags & F_SEMICOLON_OPT; + bodyFlags = S_TFFF; + if (semicolonOptional) { + bodyFlags |= F_SEMICOLON_OPT; + } + if (stmt.alternate) { + result.push(this.maybeBlock(stmt.consequent, S_TFFF)); + result = this.maybeBlockSuffix(stmt.consequent, result); + if (stmt.alternate.type === Syntax.IfStatement) { + result = join(result, ['else ', this.generateStatement(stmt.alternate, bodyFlags)]); + } else { + result = join(result, join('else', this.maybeBlock(stmt.alternate, bodyFlags))); + } + } else { + result.push(this.maybeBlock(stmt.consequent, bodyFlags)); + } + return result; + }, + + ForStatement: function (stmt, flags) { + var result, that = this; + withIndent(function () { + result = ['for' + space + '(']; + if (stmt.init) { + if (stmt.init.type === Syntax.VariableDeclaration) { + result.push(that.generateStatement(stmt.init, S_FFFF)); + } else { + // F_ALLOW_IN becomes false. + result.push(that.generateExpression(stmt.init, Precedence.Sequence, E_FTT)); + result.push(';'); + } + } else { + result.push(';'); + } + + if (stmt.test) { + result.push(space); + result.push(that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)); + result.push(';'); + } else { + result.push(';'); + } + + if (stmt.update) { + result.push(space); + result.push(that.generateExpression(stmt.update, Precedence.Sequence, E_TTT)); + result.push(')'); + } else { + result.push(')'); + } + }); + + result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF)); + return result; + }, + + ForInStatement: function (stmt, flags) { + return this.generateIterationForStatement('in', stmt, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF); + }, + + ForOfStatement: function (stmt, flags) { + return this.generateIterationForStatement('of', stmt, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF); + }, + + LabeledStatement: function (stmt, flags) { + return [stmt.label.name + ':', this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF)]; + }, + + Program: function (stmt, flags) { + var result, fragment, i, iz, bodyFlags; + iz = stmt.body.length; + result = [safeConcatenation && iz > 0 ? '\n' : '']; + bodyFlags = S_TFTF; + for (i = 0; i < iz; ++i) { + if (!safeConcatenation && i === iz - 1) { + bodyFlags |= F_SEMICOLON_OPT; + } + + if (preserveBlankLines) { + // handle spaces before the first line + if (i === 0) { + if (!stmt.body[0].leadingComments) { + generateBlankLines(stmt.range[0], stmt.body[i].range[0], result); + } + } + + // handle spaces between lines + if (i > 0) { + if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) { + generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result); + } + } + } + + fragment = addIndent(this.generateStatement(stmt.body[i], bodyFlags)); + result.push(fragment); + if (i + 1 < iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { + if (preserveBlankLines) { + if (!stmt.body[i + 1].leadingComments) { + result.push(newline); + } + } else { + result.push(newline); + } + } + + if (preserveBlankLines) { + // handle spaces after the last line + if (i === iz - 1) { + if (!stmt.body[i].trailingComments) { + generateBlankLines(stmt.body[i].range[1], stmt.range[1], result); + } + } + } + } + return result; + }, + + FunctionDeclaration: function (stmt, flags) { + return [ + generateAsyncPrefix(stmt, true), + 'function', + generateStarSuffix(stmt) || noEmptySpace(), + stmt.id ? generateIdentifier(stmt.id) : '', + this.generateFunctionBody(stmt) + ]; + }, + + ReturnStatement: function (stmt, flags) { + if (stmt.argument) { + return [join( + 'return', + this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT) + ), this.semicolon(flags)]; + } + return ['return' + this.semicolon(flags)]; + }, + + WhileStatement: function (stmt, flags) { + var result, that = this; + withIndent(function () { + result = [ + 'while' + space + '(', + that.generateExpression(stmt.test, Precedence.Sequence, E_TTT), + ')' + ]; + }); + result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF)); + return result; + }, + + WithStatement: function (stmt, flags) { + var result, that = this; + withIndent(function () { + result = [ + 'with' + space + '(', + that.generateExpression(stmt.object, Precedence.Sequence, E_TTT), + ')' + ]; + }); + result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF)); + return result; + } + + }; + + merge(CodeGenerator.prototype, CodeGenerator.Statement); + + // Expressions. + + CodeGenerator.Expression = { + + SequenceExpression: function (expr, precedence, flags) { + var result, i, iz; + if (Precedence.Sequence < precedence) { + flags |= F_ALLOW_IN; + } + result = []; + for (i = 0, iz = expr.expressions.length; i < iz; ++i) { + result.push(this.generateExpression(expr.expressions[i], Precedence.Assignment, flags)); + if (i + 1 < iz) { + result.push(',' + space); + } + } + return parenthesize(result, Precedence.Sequence, precedence); + }, + + AssignmentExpression: function (expr, precedence, flags) { + return this.generateAssignment(expr.left, expr.right, expr.operator, precedence, flags); + }, + + ArrowFunctionExpression: function (expr, precedence, flags) { + return parenthesize(this.generateFunctionBody(expr), Precedence.ArrowFunction, precedence); + }, + + ConditionalExpression: function (expr, precedence, flags) { + if (Precedence.Conditional < precedence) { + flags |= F_ALLOW_IN; + } + return parenthesize( + [ + this.generateExpression(expr.test, Precedence.LogicalOR, flags), + space + '?' + space, + this.generateExpression(expr.consequent, Precedence.Assignment, flags), + space + ':' + space, + this.generateExpression(expr.alternate, Precedence.Assignment, flags) + ], + Precedence.Conditional, + precedence + ); + }, + + LogicalExpression: function (expr, precedence, flags) { + return this.BinaryExpression(expr, precedence, flags); + }, + + BinaryExpression: function (expr, precedence, flags) { + var result, currentPrecedence, fragment, leftSource; + currentPrecedence = BinaryPrecedence[expr.operator]; + + if (currentPrecedence < precedence) { + flags |= F_ALLOW_IN; + } + + fragment = this.generateExpression(expr.left, currentPrecedence, flags); + + leftSource = fragment.toString(); + + if (leftSource.charCodeAt(leftSource.length - 1) === 0x2F /* / */ && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) { + result = [fragment, noEmptySpace(), expr.operator]; + } else { + result = join(fragment, expr.operator); + } + + fragment = this.generateExpression(expr.right, currentPrecedence + 1, flags); + + if (expr.operator === '/' && fragment.toString().charAt(0) === '/' || + expr.operator.slice(-1) === '<' && fragment.toString().slice(0, 3) === '!--') { + // If '/' concats with '/' or `<` concats with `!--`, it is interpreted as comment start + result.push(noEmptySpace()); + result.push(fragment); + } else { + result = join(result, fragment); + } + + if (expr.operator === 'in' && !(flags & F_ALLOW_IN)) { + return ['(', result, ')']; + } + return parenthesize(result, currentPrecedence, precedence); + }, + + CallExpression: function (expr, precedence, flags) { + var result, i, iz; + // F_ALLOW_UNPARATH_NEW becomes false. + result = [this.generateExpression(expr.callee, Precedence.Call, E_TTF)]; + result.push('('); + for (i = 0, iz = expr['arguments'].length; i < iz; ++i) { + result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT)); + if (i + 1 < iz) { + result.push(',' + space); + } + } + result.push(')'); + + if (!(flags & F_ALLOW_CALL)) { + return ['(', result, ')']; + } + return parenthesize(result, Precedence.Call, precedence); + }, + + NewExpression: function (expr, precedence, flags) { + var result, length, i, iz, itemFlags; + length = expr['arguments'].length; + + // F_ALLOW_CALL becomes false. + // F_ALLOW_UNPARATH_NEW may become false. + itemFlags = (flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0) ? E_TFT : E_TFF; + + result = join( + 'new', + this.generateExpression(expr.callee, Precedence.New, itemFlags) + ); + + if (!(flags & F_ALLOW_UNPARATH_NEW) || parentheses || length > 0) { + result.push('('); + for (i = 0, iz = length; i < iz; ++i) { + result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT)); + if (i + 1 < iz) { + result.push(',' + space); + } + } + result.push(')'); + } + + return parenthesize(result, Precedence.New, precedence); + }, + + MemberExpression: function (expr, precedence, flags) { + var result, fragment; + + // F_ALLOW_UNPARATH_NEW becomes false. + result = [this.generateExpression(expr.object, Precedence.Call, (flags & F_ALLOW_CALL) ? E_TTF : E_TFF)]; + + if (expr.computed) { + result.push('['); + result.push(this.generateExpression(expr.property, Precedence.Sequence, flags & F_ALLOW_CALL ? E_TTT : E_TFT)); + result.push(']'); + } else { + if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') { + fragment = toSourceNodeWhenNeeded(result).toString(); + // When the following conditions are all true, + // 1. No floating point + // 2. Don't have exponents + // 3. The last character is a decimal digit + // 4. Not hexadecimal OR octal number literal + // we should add a floating point. + if ( + fragment.indexOf('.') < 0 && + !/[eExX]/.test(fragment) && + esutils.code.isDecimalDigit(fragment.charCodeAt(fragment.length - 1)) && + !(fragment.length >= 2 && fragment.charCodeAt(0) === 48) // '0' + ) { + result.push('.'); + } + } + result.push('.'); + result.push(generateIdentifier(expr.property)); + } + + return parenthesize(result, Precedence.Member, precedence); + }, + + MetaProperty: function (expr, precedence, flags) { + var result; + result = []; + result.push(expr.meta); + result.push('.'); + result.push(expr.property); + return parenthesize(result, Precedence.Member, precedence); + }, + + UnaryExpression: function (expr, precedence, flags) { + var result, fragment, rightCharCode, leftSource, leftCharCode; + fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT); + + if (space === '') { + result = join(expr.operator, fragment); + } else { + result = [expr.operator]; + if (expr.operator.length > 2) { + // delete, void, typeof + // get `typeof []`, not `typeof[]` + result = join(result, fragment); + } else { + // Prevent inserting spaces between operator and argument if it is unnecessary + // like, `!cond` + leftSource = toSourceNodeWhenNeeded(result).toString(); + leftCharCode = leftSource.charCodeAt(leftSource.length - 1); + rightCharCode = fragment.toString().charCodeAt(0); + + if (((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode) || + (esutils.code.isIdentifierPartES5(leftCharCode) && esutils.code.isIdentifierPartES5(rightCharCode))) { + result.push(noEmptySpace()); + result.push(fragment); + } else { + result.push(fragment); + } + } + } + return parenthesize(result, Precedence.Unary, precedence); + }, + + YieldExpression: function (expr, precedence, flags) { + var result; + if (expr.delegate) { + result = 'yield*'; + } else { + result = 'yield'; + } + if (expr.argument) { + result = join( + result, + this.generateExpression(expr.argument, Precedence.Yield, E_TTT) + ); + } + return parenthesize(result, Precedence.Yield, precedence); + }, + + AwaitExpression: function (expr, precedence, flags) { + var result = join( + expr.all ? 'await*' : 'await', + this.generateExpression(expr.argument, Precedence.Await, E_TTT) + ); + return parenthesize(result, Precedence.Await, precedence); + }, + + UpdateExpression: function (expr, precedence, flags) { + if (expr.prefix) { + return parenthesize( + [ + expr.operator, + this.generateExpression(expr.argument, Precedence.Unary, E_TTT) + ], + Precedence.Unary, + precedence + ); + } + return parenthesize( + [ + this.generateExpression(expr.argument, Precedence.Postfix, E_TTT), + expr.operator + ], + Precedence.Postfix, + precedence + ); + }, + + FunctionExpression: function (expr, precedence, flags) { + var result = [ + generateAsyncPrefix(expr, true), + 'function' + ]; + if (expr.id) { + result.push(generateStarSuffix(expr) || noEmptySpace()); + result.push(generateIdentifier(expr.id)); + } else { + result.push(generateStarSuffix(expr) || space); + } + result.push(this.generateFunctionBody(expr)); + return result; + }, + + ArrayPattern: function (expr, precedence, flags) { + return this.ArrayExpression(expr, precedence, flags, true); + }, + + ArrayExpression: function (expr, precedence, flags, isPattern) { + var result, multiline, that = this; + if (!expr.elements.length) { + return '[]'; + } + multiline = isPattern ? false : expr.elements.length > 1; + result = ['[', multiline ? newline : '']; + withIndent(function (indent) { + var i, iz; + for (i = 0, iz = expr.elements.length; i < iz; ++i) { + if (!expr.elements[i]) { + if (multiline) { + result.push(indent); + } + if (i + 1 === iz) { + result.push(','); + } + } else { + result.push(multiline ? indent : ''); + result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT)); + } + if (i + 1 < iz) { + result.push(',' + (multiline ? newline : space)); + } + } + }); + if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + result.push(multiline ? base : ''); + result.push(']'); + return result; + }, + + RestElement: function(expr, precedence, flags) { + return '...' + this.generatePattern(expr.argument); + }, + + ClassExpression: function (expr, precedence, flags) { + var result, fragment; + result = ['class']; + if (expr.id) { + result = join(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT)); + } + if (expr.superClass) { + fragment = join('extends', this.generateExpression(expr.superClass, Precedence.Assignment, E_TTT)); + result = join(result, fragment); + } + result.push(space); + result.push(this.generateStatement(expr.body, S_TFFT)); + return result; + }, + + MethodDefinition: function (expr, precedence, flags) { + var result, fragment; + if (expr['static']) { + result = ['static' + space]; + } else { + result = []; + } + if (expr.kind === 'get' || expr.kind === 'set') { + fragment = [ + join(expr.kind, this.generatePropertyKey(expr.key, expr.computed, expr.value)), + this.generateFunctionBody(expr.value) + ]; + } else { + fragment = [ + generateMethodPrefix(expr), + this.generatePropertyKey(expr.key, expr.computed, expr.value), + this.generateFunctionBody(expr.value) + ]; + } + return join(result, fragment); + }, + + Property: function (expr, precedence, flags) { + if (expr.kind === 'get' || expr.kind === 'set') { + return [ + expr.kind, noEmptySpace(), + this.generatePropertyKey(expr.key, expr.computed, expr.value), + this.generateFunctionBody(expr.value) + ]; + } + + if (expr.shorthand) { + return this.generatePropertyKey(expr.key, expr.computed, expr.value); + } + + if (expr.method) { + return [ + generateMethodPrefix(expr), + this.generatePropertyKey(expr.key, expr.computed, expr.value), + this.generateFunctionBody(expr.value) + ]; + } + + return [ + this.generatePropertyKey(expr.key, expr.computed, expr.value), + ':' + space, + this.generateExpression(expr.value, Precedence.Assignment, E_TTT) + ]; + }, + + ObjectExpression: function (expr, precedence, flags) { + var multiline, result, fragment, that = this; + + if (!expr.properties.length) { + return '{}'; + } + multiline = expr.properties.length > 1; + + withIndent(function () { + fragment = that.generateExpression(expr.properties[0], Precedence.Sequence, E_TTT); + }); + + if (!multiline) { + // issues 4 + // Do not transform from + // dejavu.Class.declare({ + // method2: function () {} + // }); + // to + // dejavu.Class.declare({method2: function () { + // }}); + if (!hasLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { + return [ '{', space, fragment, space, '}' ]; + } + } + + withIndent(function (indent) { + var i, iz; + result = [ '{', newline, indent, fragment ]; + + if (multiline) { + result.push(',' + newline); + for (i = 1, iz = expr.properties.length; i < iz; ++i) { + result.push(indent); + result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT)); + if (i + 1 < iz) { + result.push(',' + newline); + } + } + } + }); + + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + result.push(base); + result.push('}'); + return result; + }, + + AssignmentPattern: function(expr, precedence, flags) { + return this.generateAssignment(expr.left, expr.right, '=', precedence, flags); + }, + + ObjectPattern: function (expr, precedence, flags) { + var result, i, iz, multiline, property, that = this; + if (!expr.properties.length) { + return '{}'; + } + + multiline = false; + if (expr.properties.length === 1) { + property = expr.properties[0]; + if (property.value.type !== Syntax.Identifier) { + multiline = true; + } + } else { + for (i = 0, iz = expr.properties.length; i < iz; ++i) { + property = expr.properties[i]; + if (!property.shorthand) { + multiline = true; + break; + } + } + } + result = ['{', multiline ? newline : '' ]; + + withIndent(function (indent) { + var i, iz; + for (i = 0, iz = expr.properties.length; i < iz; ++i) { + result.push(multiline ? indent : ''); + result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT)); + if (i + 1 < iz) { + result.push(',' + (multiline ? newline : space)); + } + } + }); + + if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + result.push(newline); + } + result.push(multiline ? base : ''); + result.push('}'); + return result; + }, + + ThisExpression: function (expr, precedence, flags) { + return 'this'; + }, + + Super: function (expr, precedence, flags) { + return 'super'; + }, + + Identifier: function (expr, precedence, flags) { + return generateIdentifier(expr); + }, + + ImportDefaultSpecifier: function (expr, precedence, flags) { + return generateIdentifier(expr.id || expr.local); + }, + + ImportNamespaceSpecifier: function (expr, precedence, flags) { + var result = ['*']; + var id = expr.id || expr.local; + if (id) { + result.push(space + 'as' + noEmptySpace() + generateIdentifier(id)); + } + return result; + }, + + ImportSpecifier: function (expr, precedence, flags) { + var imported = expr.imported; + var result = [ imported.name ]; + var local = expr.local; + if (local && local.name !== imported.name) { + result.push(noEmptySpace() + 'as' + noEmptySpace() + generateIdentifier(local)); + } + return result; + }, + + ExportSpecifier: function (expr, precedence, flags) { + var local = expr.local; + var result = [ local.name ]; + var exported = expr.exported; + if (exported && exported.name !== local.name) { + result.push(noEmptySpace() + 'as' + noEmptySpace() + generateIdentifier(exported)); + } + return result; + }, + + Literal: function (expr, precedence, flags) { + var raw; + if (expr.hasOwnProperty('raw') && parse && extra.raw) { + try { + raw = parse(expr.raw).body[0].expression; + if (raw.type === Syntax.Literal) { + if (raw.value === expr.value) { + return expr.raw; + } + } + } catch (e) { + // not use raw property + } + } + + if (expr.value === null) { + return 'null'; + } + + if (typeof expr.value === 'string') { + return escapeString(expr.value); + } + + if (typeof expr.value === 'number') { + return generateNumber(expr.value); + } + + if (typeof expr.value === 'boolean') { + return expr.value ? 'true' : 'false'; + } + + return generateRegExp(expr.value); + }, + + GeneratorExpression: function (expr, precedence, flags) { + return this.ComprehensionExpression(expr, precedence, flags); + }, + + ComprehensionExpression: function (expr, precedence, flags) { + // GeneratorExpression should be parenthesized with (...), ComprehensionExpression with [...] + // Due to https://bugzilla.mozilla.org/show_bug.cgi?id=883468 position of expr.body can differ in Spidermonkey and ES6 + + var result, i, iz, fragment, that = this; + result = (expr.type === Syntax.GeneratorExpression) ? ['('] : ['[']; + + if (extra.moz.comprehensionExpressionStartsWithAssignment) { + fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT); + result.push(fragment); + } + + if (expr.blocks) { + withIndent(function () { + for (i = 0, iz = expr.blocks.length; i < iz; ++i) { + fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT); + if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) { + result = join(result, fragment); + } else { + result.push(fragment); + } + } + }); + } + + if (expr.filter) { + result = join(result, 'if' + space); + fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT); + result = join(result, [ '(', fragment, ')' ]); + } + + if (!extra.moz.comprehensionExpressionStartsWithAssignment) { + fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT); + + result = join(result, fragment); + } + + result.push((expr.type === Syntax.GeneratorExpression) ? ')' : ']'); + return result; + }, + + ComprehensionBlock: function (expr, precedence, flags) { + var fragment; + if (expr.left.type === Syntax.VariableDeclaration) { + fragment = [ + expr.left.kind, noEmptySpace(), + this.generateStatement(expr.left.declarations[0], S_FFFF) + ]; + } else { + fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT); + } + + fragment = join(fragment, expr.of ? 'of' : 'in'); + fragment = join(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT)); + + return [ 'for' + space + '(', fragment, ')' ]; + }, + + SpreadElement: function (expr, precedence, flags) { + return [ + '...', + this.generateExpression(expr.argument, Precedence.Assignment, E_TTT) + ]; + }, + + TaggedTemplateExpression: function (expr, precedence, flags) { + var itemFlags = E_TTF; + if (!(flags & F_ALLOW_CALL)) { + itemFlags = E_TFF; + } + var result = [ + this.generateExpression(expr.tag, Precedence.Call, itemFlags), + this.generateExpression(expr.quasi, Precedence.Primary, E_FFT) + ]; + return parenthesize(result, Precedence.TaggedTemplate, precedence); + }, + + TemplateElement: function (expr, precedence, flags) { + // Don't use "cooked". Since tagged template can use raw template + // representation. So if we do so, it breaks the script semantics. + return expr.value.raw; + }, + + TemplateLiteral: function (expr, precedence, flags) { + var result, i, iz; + result = [ '`' ]; + for (i = 0, iz = expr.quasis.length; i < iz; ++i) { + result.push(this.generateExpression(expr.quasis[i], Precedence.Primary, E_TTT)); + if (i + 1 < iz) { + result.push('${' + space); + result.push(this.generateExpression(expr.expressions[i], Precedence.Sequence, E_TTT)); + result.push(space + '}'); + } + } + result.push('`'); + return result; + }, + + ModuleSpecifier: function (expr, precedence, flags) { + return this.Literal(expr, precedence, flags); + } + + }; + + merge(CodeGenerator.prototype, CodeGenerator.Expression); + + CodeGenerator.prototype.generateExpression = function (expr, precedence, flags) { + var result, type; + + type = expr.type || Syntax.Property; + + if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) { + return generateVerbatim(expr, precedence); + } + + result = this[type](expr, precedence, flags); + + + if (extra.comment) { + result = addComments(expr, result); + } + return toSourceNodeWhenNeeded(result, expr); + }; + + CodeGenerator.prototype.generateStatement = function (stmt, flags) { + var result, + fragment; + + result = this[stmt.type](stmt, flags); + + // Attach comments + + if (extra.comment) { + result = addComments(stmt, result); + } + + fragment = toSourceNodeWhenNeeded(result).toString(); + if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') { + result = sourceMap ? toSourceNodeWhenNeeded(result).replaceRight(/\s+$/, '') : fragment.replace(/\s+$/, ''); + } + + return toSourceNodeWhenNeeded(result, stmt); + }; + + function generateInternal(node) { + var codegen; + + codegen = new CodeGenerator(); + if (isStatement(node)) { + return codegen.generateStatement(node, S_TFFF); + } + + if (isExpression(node)) { + return codegen.generateExpression(node, Precedence.Sequence, E_TTT); + } + + throw new Error('Unknown node type: ' + node.type); + } + + function generate(node, options) { + var defaultOptions = getDefaultOptions(), result, pair; + + if (options != null) { + // Obsolete options + // + // `options.indent` + // `options.base` + // + // Instead of them, we can use `option.format.indent`. + if (typeof options.indent === 'string') { + defaultOptions.format.indent.style = options.indent; + } + if (typeof options.base === 'number') { + defaultOptions.format.indent.base = options.base; + } + options = updateDeeply(defaultOptions, options); + indent = options.format.indent.style; + if (typeof options.base === 'string') { + base = options.base; + } else { + base = stringRepeat(indent, options.format.indent.base); + } + } else { + options = defaultOptions; + indent = options.format.indent.style; + base = stringRepeat(indent, options.format.indent.base); + } + json = options.format.json; + renumber = options.format.renumber; + hexadecimal = json ? false : options.format.hexadecimal; + quotes = json ? 'double' : options.format.quotes; + escapeless = options.format.escapeless; + newline = options.format.newline; + space = options.format.space; + if (options.format.compact) { + newline = space = indent = base = ''; + } + parentheses = options.format.parentheses; + semicolons = options.format.semicolons; + safeConcatenation = options.format.safeConcatenation; + directive = options.directive; + parse = json ? null : options.parse; + sourceMap = options.sourceMap; + sourceCode = options.sourceCode; + preserveBlankLines = options.format.preserveBlankLines && sourceCode !== null; + extra = options; + + if (sourceMap) { + if (!exports.browser) { + // We assume environment is node.js + // And prevent from including source-map by browserify + SourceNode = require('source-map').SourceNode; + } else { + SourceNode = global.sourceMap.SourceNode; + } + } + + result = generateInternal(node); + + if (!sourceMap) { + pair = {code: result.toString(), map: null}; + return options.sourceMapWithCode ? pair : pair.code; + } + + + pair = result.toStringWithSourceMap({ + file: options.file, + sourceRoot: options.sourceMapRoot + }); + + if (options.sourceContent) { + pair.map.setSourceContent(options.sourceMap, + options.sourceContent); + } + + if (options.sourceMapWithCode) { + return pair; + } + + return pair.map.toString(); + } + + FORMAT_MINIFY = { + indent: { + style: '', + base: 0 + }, + renumber: true, + hexadecimal: true, + quotes: 'auto', + escapeless: true, + compact: true, + parentheses: false, + semicolons: false + }; + + FORMAT_DEFAULTS = getDefaultOptions().format; + + exports.version = require('./package.json').version; + exports.generate = generate; + exports.attachComments = estraverse.attachComments; + exports.Precedence = updateDeeply({}, Precedence); + exports.browser = false; + exports.FORMAT_MINIFY = FORMAT_MINIFY; + exports.FORMAT_DEFAULTS = FORMAT_DEFAULTS; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/escodegen/package.json b/hm_sunwell/node_modules/escodegen/package.json new file mode 100644 index 0000000..13c9e93 --- /dev/null +++ b/hm_sunwell/node_modules/escodegen/package.json @@ -0,0 +1,114 @@ +{ + "_args": [ + [ + "escodegen@1.8.x", + "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul" + ] + ], + "_from": "escodegen@>=1.8.0 <1.9.0", + "_id": "escodegen@1.8.1", + "_inCache": true, + "_installable": true, + "_location": "/escodegen", + "_nodeVersion": "6.3.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/escodegen-1.8.1.tgz_1470506723009_0.12818681285716593" + }, + "_npmUser": { + "email": "npm@michael.ficarra.me", + "name": "michaelficarra" + }, + "_npmVersion": "3.10.3", + "_phantomChildren": {}, + "_requested": { + "name": "escodegen", + "raw": "escodegen@1.8.x", + "rawSpec": "1.8.x", + "scope": null, + "spec": ">=1.8.0 <1.9.0", + "type": "range" + }, + "_requiredBy": [ + "/istanbul" + ], + "_resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "_shasum": "5a5b53af4693110bebb0867aa3430dd3b70a1018", + "_shrinkwrap": null, + "_spec": "escodegen@1.8.x", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul", + "bin": { + "escodegen": "./bin/escodegen.js", + "esgenerate": "./bin/esgenerate.js" + }, + "bugs": { + "url": "https://github.com/estools/escodegen/issues" + }, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, + "description": "ECMAScript code generator", + "devDependencies": { + "acorn": "^2.7.0", + "bluebird": "^2.3.11", + "bower-registry-client": "^0.2.1", + "chai": "^1.10.0", + "commonjs-everywhere": "^0.9.7", + "gulp": "^3.8.10", + "gulp-eslint": "^0.2.0", + "gulp-mocha": "^2.0.0", + "semver": "^5.1.0" + }, + "directories": {}, + "dist": { + "shasum": "5a5b53af4693110bebb0867aa3430dd3b70a1018", + "tarball": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz" + }, + "engines": { + "node": ">=0.12.0" + }, + "files": [ + "LICENSE.BSD", + "LICENSE.source-map", + "README.md", + "bin", + "escodegen.js", + "package.json" + ], + "gitHead": "ba4faabb224b2d5e0080c8e4f964702b699c7d1f", + "homepage": "http://github.com/estools/escodegen", + "license": "BSD-2-Clause", + "main": "escodegen.js", + "maintainers": [ + { + "name": "constellation", + "email": "utatane.tea@gmail.com" + }, + { + "name": "michaelficarra", + "email": "npm@michael.ficarra.me" + } + ], + "name": "escodegen", + "optionalDependencies": { + "source-map": "~0.2.0" + }, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/estools/escodegen.git" + }, + "scripts": { + "build": "cjsify -a path: tools/entry-point.js > escodegen.browser.js", + "build-min": "cjsify -ma path: tools/entry-point.js > escodegen.browser.min.js", + "lint": "gulp lint", + "release": "node tools/release.js", + "test": "gulp travis", + "unit-test": "gulp test" + }, + "version": "1.8.1" +} diff --git a/hm_sunwell/node_modules/esprima/ChangeLog b/hm_sunwell/node_modules/esprima/ChangeLog new file mode 100644 index 0000000..fd687ae --- /dev/null +++ b/hm_sunwell/node_modules/esprima/ChangeLog @@ -0,0 +1,174 @@ +2016-08-23: Version 2.7.3 + + * Fix tokenizer confusion with a comment (issue 1493, 1516) + +2016-02-02: Version 2.7.2 + + * Fix out-of-bound error location in an invalid string literal (issue 1457) + * Fix shorthand object destructuring defaults in variable declarations (issue 1459) + +2015-12-10: Version 2.7.1 + + * Do not allow trailing comma in a variable declaration (issue 1360) + * Fix assignment to `let` in non-strict mode (issue 1376) + * Fix missing delegate property in YieldExpression (issue 1407) + +2015-10-22: Version 2.7.0 + + * Fix the handling of semicolon in a break statement (issue 1044) + * Run the test suite with major web browsers (issue 1259, 1317) + * Allow `let` as an identifier in non-strict mode (issue 1289) + * Attach orphaned comments as `innerComments` (issue 1328) + * Add the support for token delegator (issue 1332) + +2015-09-01: Version 2.6.0 + + * Properly allow or prohibit `let` in a binding identifier/pattern (issue 1048, 1098) + * Add sourceType field for Program node (issue 1159) + * Ensure that strict mode reserved word binding throw an error (issue 1171) + * Run the test suite with Node.js and IE 11 on Windows (issue 1294) + * Allow binding pattern with no initializer in a for statement (issue 1301) + +2015-07-31: Version 2.5.0 + + * Run the test suite in a browser environment (issue 1004) + * Ensure a comma between imported default binding and named imports (issue 1046) + * Distinguish `yield` as a keyword vs an identifier (issue 1186) + * Support ES6 meta property `new.target` (issue 1203) + * Fix the syntax node for yield with expression (issue 1223) + * Fix the check of duplicated proto in property names (issue 1225) + * Fix ES6 Unicode escape in identifier name (issue 1229) + * Support ES6 IdentifierStart and IdentifierPart (issue 1232) + * Treat await as a reserved word when parsing as a module (issue 1234) + * Recognize identifier characters from Unicode SMP (issue 1244) + * Ensure that export and import can be followed by a comma (issue 1250) + * Fix yield operator precedence (issue 1262) + +2015-07-01: Version 2.4.1 + + * Fix some cases of comment attachment (issue 1071, 1175) + * Fix the handling of destructuring in function arguments (issue 1193) + * Fix invalid ranges in assignment expression (issue 1201) + +2015-06-26: Version 2.4.0 + + * Support ES6 for-of iteration (issue 1047) + * Support ES6 spread arguments (issue 1169) + * Minimize npm payload (issue 1191) + +2015-06-16: Version 2.3.0 + + * Support ES6 generator (issue 1033) + * Improve parsing of regular expressions with `u` flag (issue 1179) + +2015-04-17: Version 2.2.0 + + * Support ES6 import and export declarations (issue 1000) + * Fix line terminator before arrow not recognized as error (issue 1009) + * Support ES6 destructuring (issue 1045) + * Support ES6 template literal (issue 1074) + * Fix the handling of invalid/incomplete string escape sequences (issue 1106) + * Fix ES3 static member access restriction (issue 1120) + * Support for `super` in ES6 class (issue 1147) + +2015-03-09: Version 2.1.0 + + * Support ES6 class (issue 1001) + * Support ES6 rest parameter (issue 1011) + * Expand the location of property getter, setter, and methods (issue 1029) + * Enable TryStatement transition to a single handler (issue 1031) + * Support ES6 computed property name (issue 1037) + * Tolerate unclosed block comment (issue 1041) + * Support ES6 lexical declaration (issue 1065) + +2015-02-06: Version 2.0.0 + + * Support ES6 arrow function (issue 517) + * Support ES6 Unicode code point escape (issue 521) + * Improve the speed and accuracy of comment attachment (issue 522) + * Support ES6 default parameter (issue 519) + * Support ES6 regular expression flags (issue 557) + * Fix scanning of implicit octal literals (issue 565) + * Fix the handling of automatic semicolon insertion (issue 574) + * Support ES6 method definition (issue 620) + * Support ES6 octal integer literal (issue 621) + * Support ES6 binary integer literal (issue 622) + * Support ES6 object literal property value shorthand (issue 624) + +2015-03-03: Version 1.2.5 + + * Fix scanning of implicit octal literals (issue 565) + +2015-02-05: Version 1.2.4 + + * Fix parsing of LeftHandSideExpression in ForInStatement (issue 560) + * Fix the handling of automatic semicolon insertion (issue 574) + +2015-01-18: Version 1.2.3 + + * Fix division by this (issue 616) + +2014-05-18: Version 1.2.2 + + * Fix duplicated tokens when collecting comments (issue 537) + +2014-05-04: Version 1.2.1 + + * Ensure that Program node may still have leading comments (issue 536) + +2014-04-29: Version 1.2.0 + + * Fix semicolon handling for expression statement (issue 462, 533) + * Disallow escaped characters in regular expression flags (issue 503) + * Performance improvement for location tracking (issue 520) + * Improve the speed of comment attachment (issue 522) + +2014-03-26: Version 1.1.1 + + * Fix token handling of forward slash after an array literal (issue 512) + +2014-03-23: Version 1.1.0 + + * Optionally attach comments to the owning syntax nodes (issue 197) + * Simplify binary parsing with stack-based shift reduce (issue 352) + * Always include the raw source of literals (issue 376) + * Add optional input source information (issue 386) + * Tokenizer API for pure lexical scanning (issue 398) + * Improve the web site and its online demos (issue 337, 400, 404) + * Performance improvement for location tracking (issue 417, 424) + * Support HTML comment syntax (issue 451) + * Drop support for legacy browsers (issue 474) + +2013-08-27: Version 1.0.4 + + * Minimize the payload for packages (issue 362) + * Fix missing cases on an empty switch statement (issue 436) + * Support escaped ] in regexp literal character classes (issue 442) + * Tolerate invalid left-hand side expression (issue 130) + +2013-05-17: Version 1.0.3 + + * Variable declaration needs at least one declarator (issue 391) + * Fix benchmark's variance unit conversion (issue 397) + * IE < 9: \v should be treated as vertical tab (issue 405) + * Unary expressions should always have prefix: true (issue 418) + * Catch clause should only accept an identifier (issue 423) + * Tolerate setters without parameter (issue 426) + +2012-11-02: Version 1.0.2 + + Improvement: + + * Fix esvalidate JUnit output upon a syntax error (issue 374) + +2012-10-28: Version 1.0.1 + + Improvements: + + * esvalidate understands shebang in a Unix shell script (issue 361) + * esvalidate treats fatal parsing failure as an error (issue 361) + * Reduce Node.js package via .npmignore (issue 362) + +2012-10-22: Version 1.0.0 + + Initial release. diff --git a/hm_sunwell/node_modules/esprima/LICENSE.BSD b/hm_sunwell/node_modules/esprima/LICENSE.BSD new file mode 100644 index 0000000..17557ec --- /dev/null +++ b/hm_sunwell/node_modules/esprima/LICENSE.BSD @@ -0,0 +1,21 @@ +Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/esprima/README.md b/hm_sunwell/node_modules/esprima/README.md new file mode 100644 index 0000000..749454f --- /dev/null +++ b/hm_sunwell/node_modules/esprima/README.md @@ -0,0 +1,27 @@ +[![NPM version](https://img.shields.io/npm/v/esprima.svg)](https://www.npmjs.com/package/esprima) +[![npm download](https://img.shields.io/npm/dm/esprima.svg)](https://www.npmjs.com/package/esprima) +[![Build Status](https://img.shields.io/travis/jquery/esprima/master.svg)](https://travis-ci.org/jquery/esprima) +[![Coverage Status](https://img.shields.io/codecov/c/github/jquery/esprima/master.svg)](https://codecov.io/github/jquery/esprima) + +**Esprima** ([esprima.org](http://esprima.org), BSD license) is a high performance, +standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm) +parser written in ECMAScript (also popularly known as +[JavaScript](https://en.wikipedia.org/wiki/JavaScript)). +Esprima is created and maintained by [Ariya Hidayat](https://twitter.com/ariyahidayat), +with the help of [many contributors](https://github.com/jquery/esprima/contributors). + +### Features + +- Full support for ECMAScript 6 ([ECMA-262](http://www.ecma-international.org/publications/standards/Ecma-262.htm)) +- Sensible [syntax tree format](https://github.com/estree/estree/blob/master/spec.md) as standardized by [ESTree project](https://github.com/estree/estree) +- Optional tracking of syntax node location (index-based and line-column) +- [Heavily tested](http://esprima.org/test/ci.html) (~1250 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://codecov.io/github/jquery/esprima)) + +Esprima serves as a **building block** for some JavaScript +language tools, from [code instrumentation](http://esprima.org/demo/functiontrace.html) +to [editor autocompletion](http://esprima.org/demo/autocomplete.html). + +Esprima runs on many popular web browsers, as well as other ECMAScript platforms such as +[Rhino](http://www.mozilla.org/rhino), [Nashorn](http://openjdk.java.net/projects/nashorn/), and [Node.js](https://npmjs.org/package/esprima). + +For more information, check the web site [esprima.org](http://esprima.org). diff --git a/hm_sunwell/node_modules/esprima/bin/esparse.js b/hm_sunwell/node_modules/esprima/bin/esparse.js new file mode 100644 index 0000000..98bdbf4 --- /dev/null +++ b/hm_sunwell/node_modules/esprima/bin/esparse.js @@ -0,0 +1,126 @@ +#!/usr/bin/env node +/* + Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint sloppy:true node:true rhino:true */ + +var fs, esprima, fname, content, options, syntax; + +if (typeof require === 'function') { + fs = require('fs'); + esprima = require('esprima'); +} else if (typeof load === 'function') { + try { + load('esprima.js'); + } catch (e) { + load('../esprima.js'); + } +} + +// Shims to Node.js objects when running under Rhino. +if (typeof console === 'undefined' && typeof process === 'undefined') { + console = { log: print }; + fs = { readFileSync: readFile }; + process = { argv: arguments, exit: quit }; + process.argv.unshift('esparse.js'); + process.argv.unshift('rhino'); +} + +function showUsage() { + console.log('Usage:'); + console.log(' esparse [options] file.js'); + console.log(); + console.log('Available options:'); + console.log(); + console.log(' --comment Gather all line and block comments in an array'); + console.log(' --loc Include line-column location info for each syntax node'); + console.log(' --range Include index-based range for each syntax node'); + console.log(' --raw Display the raw value of literals'); + console.log(' --tokens List all tokens in an array'); + console.log(' --tolerant Tolerate errors on a best-effort basis (experimental)'); + console.log(' -v, --version Shows program version'); + console.log(); + process.exit(1); +} + +if (process.argv.length <= 2) { + showUsage(); +} + +options = {}; + +process.argv.splice(2).forEach(function (entry) { + + if (entry === '-h' || entry === '--help') { + showUsage(); + } else if (entry === '-v' || entry === '--version') { + console.log('ECMAScript Parser (using Esprima version', esprima.version, ')'); + console.log(); + process.exit(0); + } else if (entry === '--comment') { + options.comment = true; + } else if (entry === '--loc') { + options.loc = true; + } else if (entry === '--range') { + options.range = true; + } else if (entry === '--raw') { + options.raw = true; + } else if (entry === '--tokens') { + options.tokens = true; + } else if (entry === '--tolerant') { + options.tolerant = true; + } else if (entry.slice(0, 2) === '--') { + console.log('Error: unknown option ' + entry + '.'); + process.exit(1); + } else if (typeof fname === 'string') { + console.log('Error: more than one input file.'); + process.exit(1); + } else { + fname = entry; + } +}); + +if (typeof fname !== 'string') { + console.log('Error: no input file.'); + process.exit(1); +} + +// Special handling for regular expression literal since we need to +// convert it to a string literal, otherwise it will be decoded +// as object "{}" and the regular expression would be lost. +function adjustRegexLiteral(key, value) { + if (key === 'value' && value instanceof RegExp) { + value = value.toString(); + } + return value; +} + +try { + content = fs.readFileSync(fname, 'utf-8'); + syntax = esprima.parse(content, options); + console.log(JSON.stringify(syntax, adjustRegexLiteral, 4)); +} catch (e) { + console.log('Error: ' + e.message); + process.exit(1); +} diff --git a/hm_sunwell/node_modules/esprima/bin/esvalidate.js b/hm_sunwell/node_modules/esprima/bin/esvalidate.js new file mode 100644 index 0000000..f522dec --- /dev/null +++ b/hm_sunwell/node_modules/esprima/bin/esvalidate.js @@ -0,0 +1,199 @@ +#!/usr/bin/env node +/* + Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint sloppy:true plusplus:true node:true rhino:true */ +/*global phantom:true */ + +var fs, system, esprima, options, fnames, count; + +if (typeof esprima === 'undefined') { + // PhantomJS can only require() relative files + if (typeof phantom === 'object') { + fs = require('fs'); + system = require('system'); + esprima = require('./esprima'); + } else if (typeof require === 'function') { + fs = require('fs'); + esprima = require('esprima'); + } else if (typeof load === 'function') { + try { + load('esprima.js'); + } catch (e) { + load('../esprima.js'); + } + } +} + +// Shims to Node.js objects when running under PhantomJS 1.7+. +if (typeof phantom === 'object') { + fs.readFileSync = fs.read; + process = { + argv: [].slice.call(system.args), + exit: phantom.exit + }; + process.argv.unshift('phantomjs'); +} + +// Shims to Node.js objects when running under Rhino. +if (typeof console === 'undefined' && typeof process === 'undefined') { + console = { log: print }; + fs = { readFileSync: readFile }; + process = { argv: arguments, exit: quit }; + process.argv.unshift('esvalidate.js'); + process.argv.unshift('rhino'); +} + +function showUsage() { + console.log('Usage:'); + console.log(' esvalidate [options] file.js'); + console.log(); + console.log('Available options:'); + console.log(); + console.log(' --format=type Set the report format, plain (default) or junit'); + console.log(' -v, --version Print program version'); + console.log(); + process.exit(1); +} + +if (process.argv.length <= 2) { + showUsage(); +} + +options = { + format: 'plain' +}; + +fnames = []; + +process.argv.splice(2).forEach(function (entry) { + + if (entry === '-h' || entry === '--help') { + showUsage(); + } else if (entry === '-v' || entry === '--version') { + console.log('ECMAScript Validator (using Esprima version', esprima.version, ')'); + console.log(); + process.exit(0); + } else if (entry.slice(0, 9) === '--format=') { + options.format = entry.slice(9); + if (options.format !== 'plain' && options.format !== 'junit') { + console.log('Error: unknown report format ' + options.format + '.'); + process.exit(1); + } + } else if (entry.slice(0, 2) === '--') { + console.log('Error: unknown option ' + entry + '.'); + process.exit(1); + } else { + fnames.push(entry); + } +}); + +if (fnames.length === 0) { + console.log('Error: no input file.'); + process.exit(1); +} + +if (options.format === 'junit') { + console.log(''); + console.log(''); +} + +count = 0; +fnames.forEach(function (fname) { + var content, timestamp, syntax, name; + try { + content = fs.readFileSync(fname, 'utf-8'); + + if (content[0] === '#' && content[1] === '!') { + content = '//' + content.substr(2, content.length); + } + + timestamp = Date.now(); + syntax = esprima.parse(content, { tolerant: true }); + + if (options.format === 'junit') { + + name = fname; + if (name.lastIndexOf('/') >= 0) { + name = name.slice(name.lastIndexOf('/') + 1); + } + + console.log(''); + + syntax.errors.forEach(function (error) { + var msg = error.message; + msg = msg.replace(/^Line\ [0-9]*\:\ /, ''); + console.log(' '); + console.log(' ' + + error.message + '(' + name + ':' + error.lineNumber + ')' + + ''); + console.log(' '); + }); + + console.log(''); + + } else if (options.format === 'plain') { + + syntax.errors.forEach(function (error) { + var msg = error.message; + msg = msg.replace(/^Line\ [0-9]*\:\ /, ''); + msg = fname + ':' + error.lineNumber + ': ' + msg; + console.log(msg); + ++count; + }); + + } + } catch (e) { + ++count; + if (options.format === 'junit') { + console.log(''); + console.log(' '); + console.log(' ' + + e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') + + ')'); + console.log(' '); + console.log(''); + } else { + console.log('Error: ' + e.message); + } + } +}); + +if (options.format === 'junit') { + console.log(''); +} + +if (count > 0) { + process.exit(1); +} + +if (count === 0 && typeof phantom === 'object') { + process.exit(0); +} diff --git a/hm_sunwell/node_modules/esprima/esprima.js b/hm_sunwell/node_modules/esprima/esprima.js new file mode 100644 index 0000000..0cb0a93 --- /dev/null +++ b/hm_sunwell/node_modules/esprima/esprima.js @@ -0,0 +1,5740 @@ +/* + Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + + /* istanbul ignore next */ + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + FnExprTokens, + Syntax, + PlaceHolders, + Messages, + Regex, + source, + strict, + index, + lineNumber, + lineStart, + hasLineTerminator, + lastIndex, + lastLineNumber, + lastLineStart, + startIndex, + startLineNumber, + startLineStart, + scanning, + length, + lookahead, + state, + extra, + isBindingElement, + isAssignmentTarget, + firstCoverInitializedNameError; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8, + RegularExpression: 9, + Template: 10 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.RegularExpression] = 'RegularExpression'; + TokenName[Token.Template] = 'Template'; + + // A function following one of those tokens is an expression. + FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', + 'return', 'case', 'delete', 'throw', 'void', + // assignment operators + '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=', + '&=', '|=', '^=', ',', + // binary/unary operators + '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&', + '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', + '<=', '<', '>', '!=', '!==']; + + Syntax = { + AssignmentExpression: 'AssignmentExpression', + AssignmentPattern: 'AssignmentPattern', + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExportAllDeclaration: 'ExportAllDeclaration', + ExportDefaultDeclaration: 'ExportDefaultDeclaration', + ExportNamedDeclaration: 'ExportNamedDeclaration', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForOfStatement: 'ForOfStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', + ImportSpecifier: 'ImportSpecifier', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MetaProperty: 'MetaProperty', + MethodDefinition: 'MethodDefinition', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + RestElement: 'RestElement', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + Super: 'Super', + SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + YieldExpression: 'YieldExpression' + }; + + PlaceHolders = { + ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder' + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalReturn: 'Illegal return statement', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode', + TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', + ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', + DefaultRestParameter: 'Unexpected token =', + ObjectPatternAsRestParameter: 'Unexpected token {', + DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', + ConstructorSpecialMethod: 'Class constructor may not be an accessor', + DuplicateConstructor: 'A class may only have one constructor', + StaticPrototype: 'Classes may not have static property named prototype', + MissingFromClause: 'Unexpected token', + NoAsAfterImportNamespace: 'Unexpected token', + InvalidModuleSpecifier: 'Unexpected token', + IllegalImportDeclaration: 'Unexpected token', + IllegalExportDeclaration: 'Unexpected token', + DuplicateBinding: 'Duplicate binding %0' + }; + + // See also tools/generate-unicode-regex.js. + Regex = { + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/, + + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + /* istanbul ignore if */ + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function isDecimalDigit(ch) { + return (ch >= 0x30 && ch <= 0x39); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + function octalToDecimal(ch) { + // \0 is not octal escape sequence + var octal = (ch !== '0'), code = '01234567'.indexOf(ch); + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + + return { + code: code, + octal: octal + }; + } + + // ECMA-262 11.2 White Space + + function isWhiteSpace(ch) { + return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || + (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0); + } + + // ECMA-262 11.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029); + } + + // ECMA-262 11.6 Identifier Names and Identifiers + + function fromCodePoint(cp) { + return (cp < 0x10000) ? String.fromCharCode(cp) : + String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + + String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); + } + + function isIdentifierStart(ch) { + return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) + (ch >= 0x41 && ch <= 0x5A) || // A..Z + (ch >= 0x61 && ch <= 0x7A) || // a..z + (ch === 0x5C) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch))); + } + + function isIdentifierPart(ch) { + return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) + (ch >= 0x41 && ch <= 0x5A) || // A..Z + (ch >= 0x61 && ch <= 0x7A) || // a..z + (ch >= 0x30 && ch <= 0x39) || // 0..9 + (ch === 0x5C) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch))); + } + + // ECMA-262 11.6.2.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + case 'enum': + case 'export': + case 'import': + case 'super': + return true; + default: + return false; + } + } + + function isStrictModeReservedWord(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + default: + return false; + } + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // ECMA-262 11.6.2.1 Keywords + + function isKeyword(id) { + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + // ECMA-262 11.4 Comments + + function addComment(type, value, start, end, loc) { + var comment; + + assert(typeof start === 'number', 'Comment must have valid position'); + + state.lastCommentStart = start; + + comment = { + type: type, + value: value + }; + if (extra.range) { + comment.range = [start, end]; + } + if (extra.loc) { + comment.loc = loc; + } + extra.comments.push(comment); + if (extra.attachComment) { + extra.leadingComments.push(comment); + extra.trailingComments.push(comment); + } + if (extra.tokenize) { + comment.type = comment.type + 'Comment'; + if (extra.delegate) { + comment = extra.delegate(comment); + } + extra.tokens.push(comment); + } + } + + function skipSingleLineComment(offset) { + var start, loc, ch, comment; + + start = index - offset; + loc = { + start: { + line: lineNumber, + column: index - lineStart - offset + } + }; + + while (index < length) { + ch = source.charCodeAt(index); + ++index; + if (isLineTerminator(ch)) { + hasLineTerminator = true; + if (extra.comments) { + comment = source.slice(start + offset, index - 1); + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + addComment('Line', comment, start, index - 1, loc); + } + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + return; + } + } + + if (extra.comments) { + comment = source.slice(start + offset, index); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Line', comment, start, index, loc); + } + } + + function skipMultiLineComment() { + var start, loc, ch, comment; + + if (extra.comments) { + start = index - 2; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (isLineTerminator(ch)) { + if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) { + ++index; + } + hasLineTerminator = true; + ++lineNumber; + ++index; + lineStart = index; + } else if (ch === 0x2A) { + // Block comment ends with '*/'. + if (source.charCodeAt(index + 1) === 0x2F) { + ++index; + ++index; + if (extra.comments) { + comment = source.slice(start + 2, index - 2); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + } + return; + } + ++index; + } else { + ++index; + } + } + + // Ran off the end of the file - the whole thing is a comment + if (extra.comments) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + comment = source.slice(start + 2, index); + addComment('Block', comment, start, index, loc); + } + tolerateUnexpectedToken(); + } + + function skipComment() { + var ch, start; + hasLineTerminator = false; + + start = (index === 0); + while (index < length) { + ch = source.charCodeAt(index); + + if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + hasLineTerminator = true; + ++index; + if (ch === 0x0D && source.charCodeAt(index) === 0x0A) { + ++index; + } + ++lineNumber; + lineStart = index; + start = true; + } else if (ch === 0x2F) { // U+002F is '/' + ch = source.charCodeAt(index + 1); + if (ch === 0x2F) { + ++index; + ++index; + skipSingleLineComment(2); + start = true; + } else if (ch === 0x2A) { // U+002A is '*' + ++index; + ++index; + skipMultiLineComment(); + } else { + break; + } + } else if (start && ch === 0x2D) { // U+002D is '-' + // U+003E is '>' + if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) { + // '-->' is a single-line comment + index += 3; + skipSingleLineComment(3); + } else { + break; + } + } else if (ch === 0x3C) { // U+003C is '<' + if (source.slice(index + 1, index + 4) === '!--') { + ++index; // `<` + ++index; // `!` + ++index; // `-` + ++index; // `-` + skipSingleLineComment(4); + } else { + break; + } + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanUnicodeCodePointEscape() { + var ch, code; + + ch = source[index]; + code = 0; + + // At least, one hex digit is required. + if (ch === '}') { + throwUnexpectedToken(); + } + + while (index < length) { + ch = source[index++]; + if (!isHexDigit(ch)) { + break; + } + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + + if (code > 0x10FFFF || ch !== '}') { + throwUnexpectedToken(); + } + + return fromCodePoint(code); + } + + function codePointAt(i) { + var cp, first, second; + + cp = source.charCodeAt(i); + if (cp >= 0xD800 && cp <= 0xDBFF) { + second = source.charCodeAt(i + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { + first = cp; + cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + } + } + + return cp; + } + + function getComplexIdentifier() { + var cp, ch, id; + + cp = codePointAt(index); + id = fromCodePoint(cp); + index += id.length; + + // '\u' (U+005C, U+0075) denotes an escaped character. + if (cp === 0x5C) { + if (source.charCodeAt(index) !== 0x75) { + throwUnexpectedToken(); + } + ++index; + if (source[index] === '{') { + ++index; + ch = scanUnicodeCodePointEscape(); + } else { + ch = scanHexEscape('u'); + cp = ch.charCodeAt(0); + if (!ch || ch === '\\' || !isIdentifierStart(cp)) { + throwUnexpectedToken(); + } + } + id = ch; + } + + while (index < length) { + cp = codePointAt(index); + if (!isIdentifierPart(cp)) { + break; + } + ch = fromCodePoint(cp); + id += ch; + index += ch.length; + + // '\u' (U+005C, U+0075) denotes an escaped character. + if (cp === 0x5C) { + id = id.substr(0, id.length - 1); + if (source.charCodeAt(index) !== 0x75) { + throwUnexpectedToken(); + } + ++index; + if (source[index] === '{') { + ++index; + ch = scanUnicodeCodePointEscape(); + } else { + ch = scanHexEscape('u'); + cp = ch.charCodeAt(0); + if (!ch || ch === '\\' || !isIdentifierPart(cp)) { + throwUnexpectedToken(); + } + } + id += ch; + } + } + + return id; + } + + function getIdentifier() { + var start, ch; + + start = index++; + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 0x5C) { + // Blackslash (U+005C) marks Unicode escape sequence. + index = start; + return getComplexIdentifier(); + } else if (ch >= 0xD800 && ch < 0xDFFF) { + // Need to handle surrogate pairs. + index = start; + return getComplexIdentifier(); + } + if (isIdentifierPart(ch)) { + ++index; + } else { + break; + } + } + + return source.slice(start, index); + } + + function scanIdentifier() { + var start, id, type; + + start = index; + + // Backslash (U+005C) starts an escaped character. + id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier(); + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + type = Token.Identifier; + } else if (isKeyword(id)) { + type = Token.Keyword; + } else if (id === 'null') { + type = Token.NullLiteral; + } else if (id === 'true' || id === 'false') { + type = Token.BooleanLiteral; + } else { + type = Token.Identifier; + } + + return { + type: type, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + + // ECMA-262 11.7 Punctuators + + function scanPunctuator() { + var token, str; + + token = { + type: Token.Punctuator, + value: '', + lineNumber: lineNumber, + lineStart: lineStart, + start: index, + end: index + }; + + // Check for most common single-character punctuators. + str = source[index]; + switch (str) { + + case '(': + if (extra.tokenize) { + extra.openParenToken = extra.tokenValues.length; + } + ++index; + break; + + case '{': + if (extra.tokenize) { + extra.openCurlyToken = extra.tokenValues.length; + } + state.curlyStack.push('{'); + ++index; + break; + + case '.': + ++index; + if (source[index] === '.' && source[index + 1] === '.') { + // Spread operator: ... + index += 2; + str = '...'; + } + break; + + case '}': + ++index; + state.curlyStack.pop(); + break; + case ')': + case ';': + case ',': + case '[': + case ']': + case ':': + case '?': + case '~': + ++index; + break; + + default: + // 4-character punctuator. + str = source.substr(index, 4); + if (str === '>>>=') { + index += 4; + } else { + + // 3-character punctuators. + str = str.substr(0, 3); + if (str === '===' || str === '!==' || str === '>>>' || + str === '<<=' || str === '>>=') { + index += 3; + } else { + + // 2-character punctuators. + str = str.substr(0, 2); + if (str === '&&' || str === '||' || str === '==' || str === '!=' || + str === '+=' || str === '-=' || str === '*=' || str === '/=' || + str === '++' || str === '--' || str === '<<' || str === '>>' || + str === '&=' || str === '|=' || str === '^=' || str === '%=' || + str === '<=' || str === '>=' || str === '=>') { + index += 2; + } else { + + // 1-character punctuators. + str = source[index]; + if ('<>=!+-*%&|^/'.indexOf(str) >= 0) { + ++index; + } + } + } + } + } + + if (index === token.start) { + throwUnexpectedToken(); + } + + token.end = index; + token.value = str; + return token; + } + + // ECMA-262 11.8.3 Numeric Literals + + function scanHexLiteral(start) { + var number = ''; + + while (index < length) { + if (!isHexDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + throwUnexpectedToken(); + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseInt('0x' + number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function scanBinaryLiteral(start) { + var ch, number; + + number = ''; + + while (index < length) { + ch = source[index]; + if (ch !== '0' && ch !== '1') { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + // only 0b or 0B + throwUnexpectedToken(); + } + + if (index < length) { + ch = source.charCodeAt(index); + /* istanbul ignore else */ + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwUnexpectedToken(); + } + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function scanOctalLiteral(prefix, start) { + var number, octal; + + if (isOctalDigit(prefix)) { + octal = true; + number = '0' + source[index++]; + } else { + octal = false; + ++index; + number = ''; + } + + while (index < length) { + if (!isOctalDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (!octal && number.length === 0) { + // only 0o or 0O + throwUnexpectedToken(); + } + + if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function isImplicitOctalLiteral() { + var i, ch; + + // Implicit octal, unless there is a non-octal digit. + // (Annex B.1.1 on Numeric Literals) + for (i = index + 1; i < length; ++i) { + ch = source[i]; + if (ch === '8' || ch === '9') { + return false; + } + if (!isOctalDigit(ch)) { + return true; + } + } + + return true; + } + + function scanNumericLiteral() { + var number, start, ch; + + ch = source[index]; + assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + // Octal number in ES6 starts with '0o'. + // Binary number in ES6 starts with '0b'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + ++index; + return scanHexLiteral(start); + } + if (ch === 'b' || ch === 'B') { + ++index; + return scanBinaryLiteral(start); + } + if (ch === 'o' || ch === 'O') { + return scanOctalLiteral(ch, start); + } + + if (isOctalDigit(ch)) { + if (isImplicitOctalLiteral()) { + return scanOctalLiteral(ch, start); + } + } + } + + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === '.') { + number += source[index++]; + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + if (isDecimalDigit(source.charCodeAt(index))) { + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + } else { + throwUnexpectedToken(); + } + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // ECMA-262 11.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, unescaped, octToDec, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!ch || !isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + str += scanUnicodeCodePointEscape(); + } else { + unescaped = scanHexEscape(ch); + if (!unescaped) { + throw throwUnexpectedToken(); + } + str += unescaped; + } + break; + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + case '8': + case '9': + str += ch; + tolerateUnexpectedToken(); + break; + + default: + if (isOctalDigit(ch)) { + octToDec = octalToDecimal(ch); + + octal = octToDec.octal || octal; + str += String.fromCharCode(octToDec.code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + index = start; + throwUnexpectedToken(); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: startLineNumber, + lineStart: startLineStart, + start: start, + end: index + }; + } + + // ECMA-262 11.8.6 Template Literal Lexical Components + + function scanTemplate() { + var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped; + + terminated = false; + tail = false; + start = index; + head = (source[index] === '`'); + rawOffset = 2; + + ++index; + + while (index < length) { + ch = source[index++]; + if (ch === '`') { + rawOffset = 1; + tail = true; + terminated = true; + break; + } else if (ch === '$') { + if (source[index] === '{') { + state.curlyStack.push('${'); + ++index; + terminated = true; + break; + } + cooked += ch; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + cooked += '\n'; + break; + case 'r': + cooked += '\r'; + break; + case 't': + cooked += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + cooked += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + cooked += unescaped; + } else { + index = restore; + cooked += ch; + } + } + break; + case 'b': + cooked += '\b'; + break; + case 'f': + cooked += '\f'; + break; + case 'v': + cooked += '\v'; + break; + + default: + if (ch === '0') { + if (isDecimalDigit(source.charCodeAt(index))) { + // Illegal: \01 \02 and so on + throwError(Messages.TemplateOctalLiteral); + } + cooked += '\0'; + } else if (isOctalDigit(ch)) { + // Illegal: \1 \2 + throwError(Messages.TemplateOctalLiteral); + } else { + cooked += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + cooked += '\n'; + } else { + cooked += ch; + } + } + + if (!terminated) { + throwUnexpectedToken(); + } + + if (!head) { + state.curlyStack.pop(); + } + + return { + type: Token.Template, + value: { + cooked: cooked, + raw: source.slice(start + 1, index - rawOffset) + }, + head: head, + tail: tail, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // ECMA-262 11.8.5 Regular Expression Literals + + function testRegExp(pattern, flags) { + // The BMP character to use as a replacement for astral symbols when + // translating an ES6 "u"-flagged pattern to an ES5-compatible + // approximation. + // Note: replacing with '\uFFFF' enables false positives in unlikely + // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid + // pattern that would not be detected by this substitution. + var astralSubstitute = '\uFFFF', + tmp = pattern; + + if (flags.indexOf('u') >= 0) { + tmp = tmp + // Replace every Unicode escape sequence with the equivalent + // BMP character or a constant ASCII code point in the case of + // astral symbols. (See the above note on `astralSubstitute` + // for more information.) + .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) { + var codePoint = parseInt($1 || $2, 16); + if (codePoint > 0x10FFFF) { + throwUnexpectedToken(null, Messages.InvalidRegExp); + } + if (codePoint <= 0xFFFF) { + return String.fromCharCode(codePoint); + } + return astralSubstitute; + }) + // Replace each paired surrogate with a single ASCII symbol to + // avoid throwing on regular expressions that are only valid in + // combination with the "u" flag. + .replace( + /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + astralSubstitute + ); + } + + // First, detect invalid regular expressions. + try { + RegExp(tmp); + } catch (e) { + throwUnexpectedToken(null, Messages.InvalidRegExp); + } + + // Return a regular expression object for this pattern-flag pair, or + // `null` in case the current environment doesn't support the flags it + // uses. + try { + return new RegExp(pattern, flags); + } catch (exception) { + /* istanbul ignore next */ + return null; + } + } + + function scanRegExpBody() { + var ch, str, classMarker, terminated, body; + + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + classMarker = false; + terminated = false; + while (index < length) { + ch = source[index++]; + str += ch; + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwUnexpectedToken(null, Messages.UnterminatedRegExp); + } + str += ch; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwUnexpectedToken(null, Messages.UnterminatedRegExp); + } else if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } + } + } + + if (!terminated) { + throwUnexpectedToken(null, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + body = str.substr(1, str.length - 2); + return { + value: body, + literal: str + }; + } + + function scanRegExpFlags() { + var ch, str, flags, restore; + + str = ''; + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch.charCodeAt(0))) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + for (str += '\\u'; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + tolerateUnexpectedToken(); + } else { + str += '\\'; + tolerateUnexpectedToken(); + } + } else { + flags += ch; + str += ch; + } + } + + return { + value: flags, + literal: str + }; + } + + function scanRegExp() { + var start, body, flags, value; + scanning = true; + + lookahead = null; + skipComment(); + start = index; + + body = scanRegExpBody(); + flags = scanRegExpFlags(); + value = testRegExp(body.value, flags.value); + scanning = false; + if (extra.tokenize) { + return { + type: Token.RegularExpression, + value: value, + regex: { + pattern: body.value, + flags: flags.value + }, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + return { + literal: body.literal + flags.literal, + value: value, + regex: { + pattern: body.value, + flags: flags.value + }, + start: start, + end: index + }; + } + + function collectRegex() { + var pos, loc, regex, token; + + skipComment(); + + pos = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + regex = scanRegExp(); + + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + /* istanbul ignore next */ + if (!extra.tokenize) { + // Pop the previous token, which is likely '/' or '/=' + if (extra.tokens.length > 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + regex: regex.regex, + range: [pos, index], + loc: loc + }); + } + + return regex; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + // Using the following algorithm: + // https://github.com/mozilla/sweet.js/wiki/design + + function advanceSlash() { + var regex, previous, check; + + function testKeyword(value) { + return value && (value.length > 1) && (value[0] >= 'a') && (value[0] <= 'z'); + } + + previous = extra.tokenValues[extra.tokenValues.length - 1]; + regex = (previous !== null); + + switch (previous) { + case 'this': + case ']': + regex = false; + break; + + case ')': + check = extra.tokenValues[extra.openParenToken - 1]; + regex = (check === 'if' || check === 'while' || check === 'for' || check === 'with'); + break; + + case '}': + // Dividing a function by anything makes little sense, + // but we have to check for that. + regex = false; + if (testKeyword(extra.tokenValues[extra.openCurlyToken - 3])) { + // Anonymous function, e.g. function(){} /42 + check = extra.tokenValues[extra.openCurlyToken - 4]; + regex = check ? (FnExprTokens.indexOf(check) < 0) : false; + } else if (testKeyword(extra.tokenValues[extra.openCurlyToken - 4])) { + // Named function, e.g. function f(){} /42/ + check = extra.tokenValues[extra.openCurlyToken - 5]; + regex = check ? (FnExprTokens.indexOf(check) < 0) : true; + } + } + + return regex ? collectRegex() : scanPunctuator(); + } + + function advance() { + var cp, token; + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + start: index, + end: index + }; + } + + cp = source.charCodeAt(index); + + if (isIdentifierStart(cp)) { + token = scanIdentifier(); + if (strict && isStrictModeReservedWord(token.value)) { + token.type = Token.Keyword; + } + return token; + } + + // Very common: ( and ) and ; + if (cp === 0x28 || cp === 0x29 || cp === 0x3B) { + return scanPunctuator(); + } + + // String literal starts with single quote (U+0027) or double quote (U+0022). + if (cp === 0x27 || cp === 0x22) { + return scanStringLiteral(); + } + + // Dot (.) U+002E can also start a floating-point number, hence the need + // to check the next character. + if (cp === 0x2E) { + if (isDecimalDigit(source.charCodeAt(index + 1))) { + return scanNumericLiteral(); + } + return scanPunctuator(); + } + + if (isDecimalDigit(cp)) { + return scanNumericLiteral(); + } + + // Slash (/) U+002F can also start a regex. + if (extra.tokenize && cp === 0x2F) { + return advanceSlash(); + } + + // Template literals start with ` (U+0060) for template head + // or } (U+007D) for template middle or template tail. + if (cp === 0x60 || (cp === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) { + return scanTemplate(); + } + + // Possible identifier start in a surrogate pair. + if (cp >= 0xD800 && cp < 0xDFFF) { + cp = codePointAt(index); + if (isIdentifierStart(cp)) { + return scanIdentifier(); + } + } + + return scanPunctuator(); + } + + function collectToken() { + var loc, token, value, entry; + + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + token = advance(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (token.type !== Token.EOF) { + value = source.slice(token.start, token.end); + entry = { + type: TokenName[token.type], + value: value, + range: [token.start, token.end], + loc: loc + }; + if (token.regex) { + entry.regex = { + pattern: token.regex.pattern, + flags: token.regex.flags + }; + } + if (extra.tokenValues) { + extra.tokenValues.push((entry.type === 'Punctuator' || entry.type === 'Keyword') ? entry.value : null); + } + if (extra.tokenize) { + if (!extra.range) { + delete entry.range; + } + if (!extra.loc) { + delete entry.loc; + } + if (extra.delegate) { + entry = extra.delegate(entry); + } + } + extra.tokens.push(entry); + } + + return token; + } + + function lex() { + var token; + scanning = true; + + lastIndex = index; + lastLineNumber = lineNumber; + lastLineStart = lineStart; + + skipComment(); + + token = lookahead; + + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + + lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); + scanning = false; + return token; + } + + function peek() { + scanning = true; + + skipComment(); + + lastIndex = index; + lastLineNumber = lineNumber; + lastLineStart = lineStart; + + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + + lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); + scanning = false; + } + + function Position() { + this.line = startLineNumber; + this.column = startIndex - startLineStart; + } + + function SourceLocation() { + this.start = new Position(); + this.end = null; + } + + function WrappingSourceLocation(startToken) { + this.start = { + line: startToken.lineNumber, + column: startToken.start - startToken.lineStart + }; + this.end = null; + } + + function Node() { + if (extra.range) { + this.range = [startIndex, 0]; + } + if (extra.loc) { + this.loc = new SourceLocation(); + } + } + + function WrappingNode(startToken) { + if (extra.range) { + this.range = [startToken.start, 0]; + } + if (extra.loc) { + this.loc = new WrappingSourceLocation(startToken); + } + } + + WrappingNode.prototype = Node.prototype = { + + processComment: function () { + var lastChild, + innerComments, + leadingComments, + trailingComments, + bottomRight = extra.bottomRightStack, + i, + comment, + last = bottomRight[bottomRight.length - 1]; + + if (this.type === Syntax.Program) { + if (this.body.length > 0) { + return; + } + } + /** + * patch innnerComments for properties empty block + * `function a() {/** comments **\/}` + */ + + if (this.type === Syntax.BlockStatement && this.body.length === 0) { + innerComments = []; + for (i = extra.leadingComments.length - 1; i >= 0; --i) { + comment = extra.leadingComments[i]; + if (this.range[1] >= comment.range[1]) { + innerComments.unshift(comment); + extra.leadingComments.splice(i, 1); + extra.trailingComments.splice(i, 1); + } + } + if (innerComments.length) { + this.innerComments = innerComments; + //bottomRight.push(this); + return; + } + } + + if (extra.trailingComments.length > 0) { + trailingComments = []; + for (i = extra.trailingComments.length - 1; i >= 0; --i) { + comment = extra.trailingComments[i]; + if (comment.range[0] >= this.range[1]) { + trailingComments.unshift(comment); + extra.trailingComments.splice(i, 1); + } + } + extra.trailingComments = []; + } else { + if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) { + trailingComments = last.trailingComments; + delete last.trailingComments; + } + } + + // Eating the stack. + while (last && last.range[0] >= this.range[0]) { + lastChild = bottomRight.pop(); + last = bottomRight[bottomRight.length - 1]; + } + + if (lastChild) { + if (lastChild.leadingComments) { + leadingComments = []; + for (i = lastChild.leadingComments.length - 1; i >= 0; --i) { + comment = lastChild.leadingComments[i]; + if (comment.range[1] <= this.range[0]) { + leadingComments.unshift(comment); + lastChild.leadingComments.splice(i, 1); + } + } + + if (!lastChild.leadingComments.length) { + lastChild.leadingComments = undefined; + } + } + } else if (extra.leadingComments.length > 0) { + leadingComments = []; + for (i = extra.leadingComments.length - 1; i >= 0; --i) { + comment = extra.leadingComments[i]; + if (comment.range[1] <= this.range[0]) { + leadingComments.unshift(comment); + extra.leadingComments.splice(i, 1); + } + } + } + + + if (leadingComments && leadingComments.length > 0) { + this.leadingComments = leadingComments; + } + if (trailingComments && trailingComments.length > 0) { + this.trailingComments = trailingComments; + } + + bottomRight.push(this); + }, + + finish: function () { + if (extra.range) { + this.range[1] = lastIndex; + } + if (extra.loc) { + this.loc.end = { + line: lastLineNumber, + column: lastIndex - lastLineStart + }; + if (extra.source) { + this.loc.source = extra.source; + } + } + + if (extra.attachComment) { + this.processComment(); + } + }, + + finishArrayExpression: function (elements) { + this.type = Syntax.ArrayExpression; + this.elements = elements; + this.finish(); + return this; + }, + + finishArrayPattern: function (elements) { + this.type = Syntax.ArrayPattern; + this.elements = elements; + this.finish(); + return this; + }, + + finishArrowFunctionExpression: function (params, defaults, body, expression) { + this.type = Syntax.ArrowFunctionExpression; + this.id = null; + this.params = params; + this.defaults = defaults; + this.body = body; + this.generator = false; + this.expression = expression; + this.finish(); + return this; + }, + + finishAssignmentExpression: function (operator, left, right) { + this.type = Syntax.AssignmentExpression; + this.operator = operator; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishAssignmentPattern: function (left, right) { + this.type = Syntax.AssignmentPattern; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishBinaryExpression: function (operator, left, right) { + this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression; + this.operator = operator; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishBlockStatement: function (body) { + this.type = Syntax.BlockStatement; + this.body = body; + this.finish(); + return this; + }, + + finishBreakStatement: function (label) { + this.type = Syntax.BreakStatement; + this.label = label; + this.finish(); + return this; + }, + + finishCallExpression: function (callee, args) { + this.type = Syntax.CallExpression; + this.callee = callee; + this.arguments = args; + this.finish(); + return this; + }, + + finishCatchClause: function (param, body) { + this.type = Syntax.CatchClause; + this.param = param; + this.body = body; + this.finish(); + return this; + }, + + finishClassBody: function (body) { + this.type = Syntax.ClassBody; + this.body = body; + this.finish(); + return this; + }, + + finishClassDeclaration: function (id, superClass, body) { + this.type = Syntax.ClassDeclaration; + this.id = id; + this.superClass = superClass; + this.body = body; + this.finish(); + return this; + }, + + finishClassExpression: function (id, superClass, body) { + this.type = Syntax.ClassExpression; + this.id = id; + this.superClass = superClass; + this.body = body; + this.finish(); + return this; + }, + + finishConditionalExpression: function (test, consequent, alternate) { + this.type = Syntax.ConditionalExpression; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + this.finish(); + return this; + }, + + finishContinueStatement: function (label) { + this.type = Syntax.ContinueStatement; + this.label = label; + this.finish(); + return this; + }, + + finishDebuggerStatement: function () { + this.type = Syntax.DebuggerStatement; + this.finish(); + return this; + }, + + finishDoWhileStatement: function (body, test) { + this.type = Syntax.DoWhileStatement; + this.body = body; + this.test = test; + this.finish(); + return this; + }, + + finishEmptyStatement: function () { + this.type = Syntax.EmptyStatement; + this.finish(); + return this; + }, + + finishExpressionStatement: function (expression) { + this.type = Syntax.ExpressionStatement; + this.expression = expression; + this.finish(); + return this; + }, + + finishForStatement: function (init, test, update, body) { + this.type = Syntax.ForStatement; + this.init = init; + this.test = test; + this.update = update; + this.body = body; + this.finish(); + return this; + }, + + finishForOfStatement: function (left, right, body) { + this.type = Syntax.ForOfStatement; + this.left = left; + this.right = right; + this.body = body; + this.finish(); + return this; + }, + + finishForInStatement: function (left, right, body) { + this.type = Syntax.ForInStatement; + this.left = left; + this.right = right; + this.body = body; + this.each = false; + this.finish(); + return this; + }, + + finishFunctionDeclaration: function (id, params, defaults, body, generator) { + this.type = Syntax.FunctionDeclaration; + this.id = id; + this.params = params; + this.defaults = defaults; + this.body = body; + this.generator = generator; + this.expression = false; + this.finish(); + return this; + }, + + finishFunctionExpression: function (id, params, defaults, body, generator) { + this.type = Syntax.FunctionExpression; + this.id = id; + this.params = params; + this.defaults = defaults; + this.body = body; + this.generator = generator; + this.expression = false; + this.finish(); + return this; + }, + + finishIdentifier: function (name) { + this.type = Syntax.Identifier; + this.name = name; + this.finish(); + return this; + }, + + finishIfStatement: function (test, consequent, alternate) { + this.type = Syntax.IfStatement; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + this.finish(); + return this; + }, + + finishLabeledStatement: function (label, body) { + this.type = Syntax.LabeledStatement; + this.label = label; + this.body = body; + this.finish(); + return this; + }, + + finishLiteral: function (token) { + this.type = Syntax.Literal; + this.value = token.value; + this.raw = source.slice(token.start, token.end); + if (token.regex) { + this.regex = token.regex; + } + this.finish(); + return this; + }, + + finishMemberExpression: function (accessor, object, property) { + this.type = Syntax.MemberExpression; + this.computed = accessor === '['; + this.object = object; + this.property = property; + this.finish(); + return this; + }, + + finishMetaProperty: function (meta, property) { + this.type = Syntax.MetaProperty; + this.meta = meta; + this.property = property; + this.finish(); + return this; + }, + + finishNewExpression: function (callee, args) { + this.type = Syntax.NewExpression; + this.callee = callee; + this.arguments = args; + this.finish(); + return this; + }, + + finishObjectExpression: function (properties) { + this.type = Syntax.ObjectExpression; + this.properties = properties; + this.finish(); + return this; + }, + + finishObjectPattern: function (properties) { + this.type = Syntax.ObjectPattern; + this.properties = properties; + this.finish(); + return this; + }, + + finishPostfixExpression: function (operator, argument) { + this.type = Syntax.UpdateExpression; + this.operator = operator; + this.argument = argument; + this.prefix = false; + this.finish(); + return this; + }, + + finishProgram: function (body, sourceType) { + this.type = Syntax.Program; + this.body = body; + this.sourceType = sourceType; + this.finish(); + return this; + }, + + finishProperty: function (kind, key, computed, value, method, shorthand) { + this.type = Syntax.Property; + this.key = key; + this.computed = computed; + this.value = value; + this.kind = kind; + this.method = method; + this.shorthand = shorthand; + this.finish(); + return this; + }, + + finishRestElement: function (argument) { + this.type = Syntax.RestElement; + this.argument = argument; + this.finish(); + return this; + }, + + finishReturnStatement: function (argument) { + this.type = Syntax.ReturnStatement; + this.argument = argument; + this.finish(); + return this; + }, + + finishSequenceExpression: function (expressions) { + this.type = Syntax.SequenceExpression; + this.expressions = expressions; + this.finish(); + return this; + }, + + finishSpreadElement: function (argument) { + this.type = Syntax.SpreadElement; + this.argument = argument; + this.finish(); + return this; + }, + + finishSwitchCase: function (test, consequent) { + this.type = Syntax.SwitchCase; + this.test = test; + this.consequent = consequent; + this.finish(); + return this; + }, + + finishSuper: function () { + this.type = Syntax.Super; + this.finish(); + return this; + }, + + finishSwitchStatement: function (discriminant, cases) { + this.type = Syntax.SwitchStatement; + this.discriminant = discriminant; + this.cases = cases; + this.finish(); + return this; + }, + + finishTaggedTemplateExpression: function (tag, quasi) { + this.type = Syntax.TaggedTemplateExpression; + this.tag = tag; + this.quasi = quasi; + this.finish(); + return this; + }, + + finishTemplateElement: function (value, tail) { + this.type = Syntax.TemplateElement; + this.value = value; + this.tail = tail; + this.finish(); + return this; + }, + + finishTemplateLiteral: function (quasis, expressions) { + this.type = Syntax.TemplateLiteral; + this.quasis = quasis; + this.expressions = expressions; + this.finish(); + return this; + }, + + finishThisExpression: function () { + this.type = Syntax.ThisExpression; + this.finish(); + return this; + }, + + finishThrowStatement: function (argument) { + this.type = Syntax.ThrowStatement; + this.argument = argument; + this.finish(); + return this; + }, + + finishTryStatement: function (block, handler, finalizer) { + this.type = Syntax.TryStatement; + this.block = block; + this.guardedHandlers = []; + this.handlers = handler ? [handler] : []; + this.handler = handler; + this.finalizer = finalizer; + this.finish(); + return this; + }, + + finishUnaryExpression: function (operator, argument) { + this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression; + this.operator = operator; + this.argument = argument; + this.prefix = true; + this.finish(); + return this; + }, + + finishVariableDeclaration: function (declarations) { + this.type = Syntax.VariableDeclaration; + this.declarations = declarations; + this.kind = 'var'; + this.finish(); + return this; + }, + + finishLexicalDeclaration: function (declarations, kind) { + this.type = Syntax.VariableDeclaration; + this.declarations = declarations; + this.kind = kind; + this.finish(); + return this; + }, + + finishVariableDeclarator: function (id, init) { + this.type = Syntax.VariableDeclarator; + this.id = id; + this.init = init; + this.finish(); + return this; + }, + + finishWhileStatement: function (test, body) { + this.type = Syntax.WhileStatement; + this.test = test; + this.body = body; + this.finish(); + return this; + }, + + finishWithStatement: function (object, body) { + this.type = Syntax.WithStatement; + this.object = object; + this.body = body; + this.finish(); + return this; + }, + + finishExportSpecifier: function (local, exported) { + this.type = Syntax.ExportSpecifier; + this.exported = exported || local; + this.local = local; + this.finish(); + return this; + }, + + finishImportDefaultSpecifier: function (local) { + this.type = Syntax.ImportDefaultSpecifier; + this.local = local; + this.finish(); + return this; + }, + + finishImportNamespaceSpecifier: function (local) { + this.type = Syntax.ImportNamespaceSpecifier; + this.local = local; + this.finish(); + return this; + }, + + finishExportNamedDeclaration: function (declaration, specifiers, src) { + this.type = Syntax.ExportNamedDeclaration; + this.declaration = declaration; + this.specifiers = specifiers; + this.source = src; + this.finish(); + return this; + }, + + finishExportDefaultDeclaration: function (declaration) { + this.type = Syntax.ExportDefaultDeclaration; + this.declaration = declaration; + this.finish(); + return this; + }, + + finishExportAllDeclaration: function (src) { + this.type = Syntax.ExportAllDeclaration; + this.source = src; + this.finish(); + return this; + }, + + finishImportSpecifier: function (local, imported) { + this.type = Syntax.ImportSpecifier; + this.local = local || imported; + this.imported = imported; + this.finish(); + return this; + }, + + finishImportDeclaration: function (specifiers, src) { + this.type = Syntax.ImportDeclaration; + this.specifiers = specifiers; + this.source = src; + this.finish(); + return this; + }, + + finishYieldExpression: function (argument, delegate) { + this.type = Syntax.YieldExpression; + this.argument = argument; + this.delegate = delegate; + this.finish(); + return this; + } + }; + + + function recordError(error) { + var e, existing; + + for (e = 0; e < extra.errors.length; e++) { + existing = extra.errors[e]; + // Prevent duplicated error. + /* istanbul ignore next */ + if (existing.index === error.index && existing.message === error.message) { + return; + } + } + + extra.errors.push(error); + } + + function constructError(msg, column) { + var error = new Error(msg); + try { + throw error; + } catch (base) { + /* istanbul ignore else */ + if (Object.create && Object.defineProperty) { + error = Object.create(base); + Object.defineProperty(error, 'column', { value: column }); + } + } finally { + return error; + } + } + + function createError(line, pos, description) { + var msg, column, error; + + msg = 'Line ' + line + ': ' + description; + column = pos - (scanning ? lineStart : lastLineStart) + 1; + error = constructError(msg, column); + error.lineNumber = line; + error.description = description; + error.index = pos; + return error; + } + + // Throw an exception + + function throwError(messageFormat) { + var args, msg; + + args = Array.prototype.slice.call(arguments, 1); + msg = messageFormat.replace(/%(\d)/g, + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + } + ); + + throw createError(lastLineNumber, lastIndex, msg); + } + + function tolerateError(messageFormat) { + var args, msg, error; + + args = Array.prototype.slice.call(arguments, 1); + /* istanbul ignore next */ + msg = messageFormat.replace(/%(\d)/g, + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + } + ); + + error = createError(lineNumber, lastIndex, msg); + if (extra.errors) { + recordError(error); + } else { + throw error; + } + } + + // Throw an exception because of the token. + + function unexpectedTokenError(token, message) { + var value, msg = message || Messages.UnexpectedToken; + + if (token) { + if (!message) { + msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS : + (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier : + (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber : + (token.type === Token.StringLiteral) ? Messages.UnexpectedString : + (token.type === Token.Template) ? Messages.UnexpectedTemplate : + Messages.UnexpectedToken; + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + msg = Messages.UnexpectedReserved; + } else if (strict && isStrictModeReservedWord(token.value)) { + msg = Messages.StrictReservedWord; + } + } + } + + value = (token.type === Token.Template) ? token.value.raw : token.value; + } else { + value = 'ILLEGAL'; + } + + msg = msg.replace('%0', value); + + return (token && typeof token.lineNumber === 'number') ? + createError(token.lineNumber, token.start, msg) : + createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg); + } + + function throwUnexpectedToken(token, message) { + throw unexpectedTokenError(token, message); + } + + function tolerateUnexpectedToken(token, message) { + var error = unexpectedTokenError(token, message); + if (extra.errors) { + recordError(error); + } else { + throw error; + } + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpectedToken(token); + } + } + + /** + * @name expectCommaSeparator + * @description Quietly expect a comma when in tolerant mode, otherwise delegates + * to expect(value) + * @since 2.0 + */ + function expectCommaSeparator() { + var token; + + if (extra.errors) { + token = lookahead; + if (token.type === Token.Punctuator && token.value === ',') { + lex(); + } else if (token.type === Token.Punctuator && token.value === ';') { + lex(); + tolerateUnexpectedToken(token); + } else { + tolerateUnexpectedToken(token, Messages.UnexpectedToken); + } + } else { + expect(','); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpectedToken(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + return lookahead.type === Token.Punctuator && lookahead.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + return lookahead.type === Token.Keyword && lookahead.value === keyword; + } + + // Return true if the next token matches the specified contextual keyword + // (where an identifier is sometimes a keyword depending on the context) + + function matchContextualKeyword(keyword) { + return lookahead.type === Token.Identifier && lookahead.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var op; + + if (lookahead.type !== Token.Punctuator) { + return false; + } + op = lookahead.value; + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + // Catch the very common case first: immediately a semicolon (U+003B). + if (source.charCodeAt(startIndex) === 0x3B || match(';')) { + lex(); + return; + } + + if (hasLineTerminator) { + return; + } + + // FIXME(ikarienator): this is seemingly an issue in the previous location info convention. + lastIndex = startIndex; + lastLineNumber = startLineNumber; + lastLineStart = startLineStart; + + if (lookahead.type !== Token.EOF && !match('}')) { + throwUnexpectedToken(lookahead); + } + } + + // Cover grammar support. + // + // When an assignment expression position starts with an left parenthesis, the determination of the type + // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) + // or the first comma. This situation also defers the determination of all the expressions nested in the pair. + // + // There are three productions that can be parsed in a parentheses pair that needs to be determined + // after the outermost pair is closed. They are: + // + // 1. AssignmentExpression + // 2. BindingElements + // 3. AssignmentTargets + // + // In order to avoid exponential backtracking, we use two flags to denote if the production can be + // binding element or assignment target. + // + // The three productions have the relationship: + // + // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression + // + // with a single exception that CoverInitializedName when used directly in an Expression, generates + // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the + // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. + // + // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not + // effect the current flags. This means the production the parser parses is only used as an expression. Therefore + // the CoverInitializedName check is conducted. + // + // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates + // the flags outside of the parser. This means the production the parser parses is used as a part of a potential + // pattern. The CoverInitializedName check is deferred. + function isolateCoverGrammar(parser) { + var oldIsBindingElement = isBindingElement, + oldIsAssignmentTarget = isAssignmentTarget, + oldFirstCoverInitializedNameError = firstCoverInitializedNameError, + result; + isBindingElement = true; + isAssignmentTarget = true; + firstCoverInitializedNameError = null; + result = parser(); + if (firstCoverInitializedNameError !== null) { + throwUnexpectedToken(firstCoverInitializedNameError); + } + isBindingElement = oldIsBindingElement; + isAssignmentTarget = oldIsAssignmentTarget; + firstCoverInitializedNameError = oldFirstCoverInitializedNameError; + return result; + } + + function inheritCoverGrammar(parser) { + var oldIsBindingElement = isBindingElement, + oldIsAssignmentTarget = isAssignmentTarget, + oldFirstCoverInitializedNameError = firstCoverInitializedNameError, + result; + isBindingElement = true; + isAssignmentTarget = true; + firstCoverInitializedNameError = null; + result = parser(); + isBindingElement = isBindingElement && oldIsBindingElement; + isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget; + firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError; + return result; + } + + // ECMA-262 13.3.3 Destructuring Binding Patterns + + function parseArrayPattern(params, kind) { + var node = new Node(), elements = [], rest, restNode; + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else { + if (match('...')) { + restNode = new Node(); + lex(); + params.push(lookahead); + rest = parseVariableIdentifier(kind); + elements.push(restNode.finishRestElement(rest)); + break; + } else { + elements.push(parsePatternWithDefault(params, kind)); + } + if (!match(']')) { + expect(','); + } + } + + } + + expect(']'); + + return node.finishArrayPattern(elements); + } + + function parsePropertyPattern(params, kind) { + var node = new Node(), key, keyToken, computed = match('['), init; + if (lookahead.type === Token.Identifier) { + keyToken = lookahead; + key = parseVariableIdentifier(); + if (match('=')) { + params.push(keyToken); + lex(); + init = parseAssignmentExpression(); + + return node.finishProperty( + 'init', key, false, + new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, true); + } else if (!match(':')) { + params.push(keyToken); + return node.finishProperty('init', key, false, key, false, true); + } + } else { + key = parseObjectPropertyKey(); + } + expect(':'); + init = parsePatternWithDefault(params, kind); + return node.finishProperty('init', key, computed, init, false, false); + } + + function parseObjectPattern(params, kind) { + var node = new Node(), properties = []; + + expect('{'); + + while (!match('}')) { + properties.push(parsePropertyPattern(params, kind)); + if (!match('}')) { + expect(','); + } + } + + lex(); + + return node.finishObjectPattern(properties); + } + + function parsePattern(params, kind) { + if (match('[')) { + return parseArrayPattern(params, kind); + } else if (match('{')) { + return parseObjectPattern(params, kind); + } else if (matchKeyword('let')) { + if (kind === 'const' || kind === 'let') { + tolerateUnexpectedToken(lookahead, Messages.UnexpectedToken); + } + } + + params.push(lookahead); + return parseVariableIdentifier(kind); + } + + function parsePatternWithDefault(params, kind) { + var startToken = lookahead, pattern, previousAllowYield, right; + pattern = parsePattern(params, kind); + if (match('=')) { + lex(); + previousAllowYield = state.allowYield; + state.allowYield = true; + right = isolateCoverGrammar(parseAssignmentExpression); + state.allowYield = previousAllowYield; + pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right); + } + return pattern; + } + + // ECMA-262 12.2.5 Array Initializer + + function parseArrayInitializer() { + var elements = [], node = new Node(), restSpread; + + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else if (match('...')) { + restSpread = new Node(); + lex(); + restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression)); + + if (!match(']')) { + isAssignmentTarget = isBindingElement = false; + expect(','); + } + elements.push(restSpread); + } else { + elements.push(inheritCoverGrammar(parseAssignmentExpression)); + + if (!match(']')) { + expect(','); + } + } + } + + lex(); + + return node.finishArrayExpression(elements); + } + + // ECMA-262 12.2.6 Object Initializer + + function parsePropertyFunction(node, paramInfo, isGenerator) { + var previousStrict, body; + + isAssignmentTarget = isBindingElement = false; + + previousStrict = strict; + body = isolateCoverGrammar(parseFunctionSourceElements); + + if (strict && paramInfo.firstRestricted) { + tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message); + } + if (strict && paramInfo.stricted) { + tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message); + } + + strict = previousStrict; + return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator); + } + + function parsePropertyMethodFunction() { + var params, method, node = new Node(), + previousAllowYield = state.allowYield; + + state.allowYield = false; + params = parseParams(); + state.allowYield = previousAllowYield; + + state.allowYield = false; + method = parsePropertyFunction(node, params, false); + state.allowYield = previousAllowYield; + + return method; + } + + function parseObjectPropertyKey() { + var token, node = new Node(), expr; + + token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + switch (token.type) { + case Token.StringLiteral: + case Token.NumericLiteral: + if (strict && token.octal) { + tolerateUnexpectedToken(token, Messages.StrictOctalLiteral); + } + return node.finishLiteral(token); + case Token.Identifier: + case Token.BooleanLiteral: + case Token.NullLiteral: + case Token.Keyword: + return node.finishIdentifier(token.value); + case Token.Punctuator: + if (token.value === '[') { + expr = isolateCoverGrammar(parseAssignmentExpression); + expect(']'); + return expr; + } + break; + } + throwUnexpectedToken(token); + } + + function lookaheadPropertyName() { + switch (lookahead.type) { + case Token.Identifier: + case Token.StringLiteral: + case Token.BooleanLiteral: + case Token.NullLiteral: + case Token.NumericLiteral: + case Token.Keyword: + return true; + case Token.Punctuator: + return lookahead.value === '['; + } + return false; + } + + // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals, + // it might be called at a position where there is in fact a short hand identifier pattern or a data property. + // This can only be determined after we consumed up to the left parentheses. + // + // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller + // is responsible to visit other options. + function tryParseMethodDefinition(token, key, computed, node) { + var value, options, methodNode, params, + previousAllowYield = state.allowYield; + + if (token.type === Token.Identifier) { + // check for `get` and `set`; + + if (token.value === 'get' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + expect('('); + expect(')'); + + state.allowYield = false; + value = parsePropertyFunction(methodNode, { + params: [], + defaults: [], + stricted: null, + firstRestricted: null, + message: null + }, false); + state.allowYield = previousAllowYield; + + return node.finishProperty('get', key, computed, value, false, false); + } else if (token.value === 'set' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + expect('('); + + options = { + params: [], + defaultCount: 0, + defaults: [], + firstRestricted: null, + paramSet: {} + }; + if (match(')')) { + tolerateUnexpectedToken(lookahead); + } else { + state.allowYield = false; + parseParam(options); + state.allowYield = previousAllowYield; + if (options.defaultCount === 0) { + options.defaults = []; + } + } + expect(')'); + + state.allowYield = false; + value = parsePropertyFunction(methodNode, options, false); + state.allowYield = previousAllowYield; + + return node.finishProperty('set', key, computed, value, false, false); + } + } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + + state.allowYield = true; + params = parseParams(); + state.allowYield = previousAllowYield; + + state.allowYield = false; + value = parsePropertyFunction(methodNode, params, true); + state.allowYield = previousAllowYield; + + return node.finishProperty('init', key, computed, value, true, false); + } + + if (key && match('(')) { + value = parsePropertyMethodFunction(); + return node.finishProperty('init', key, computed, value, true, false); + } + + // Not a MethodDefinition. + return null; + } + + function parseObjectProperty(hasProto) { + var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value; + + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + } + maybeMethod = tryParseMethodDefinition(token, key, computed, node); + if (maybeMethod) { + return maybeMethod; + } + + if (!key) { + throwUnexpectedToken(lookahead); + } + + // Check for duplicated __proto__ + if (!computed) { + proto = (key.type === Syntax.Identifier && key.name === '__proto__') || + (key.type === Syntax.Literal && key.value === '__proto__'); + if (hasProto.value && proto) { + tolerateError(Messages.DuplicateProtoProperty); + } + hasProto.value |= proto; + } + + if (match(':')) { + lex(); + value = inheritCoverGrammar(parseAssignmentExpression); + return node.finishProperty('init', key, computed, value, false, false); + } + + if (token.type === Token.Identifier) { + if (match('=')) { + firstCoverInitializedNameError = lookahead; + lex(); + value = isolateCoverGrammar(parseAssignmentExpression); + return node.finishProperty('init', key, computed, + new WrappingNode(token).finishAssignmentPattern(key, value), false, true); + } + return node.finishProperty('init', key, computed, key, false, true); + } + + throwUnexpectedToken(lookahead); + } + + function parseObjectInitializer() { + var properties = [], hasProto = {value: false}, node = new Node(); + + expect('{'); + + while (!match('}')) { + properties.push(parseObjectProperty(hasProto)); + + if (!match('}')) { + expectCommaSeparator(); + } + } + + expect('}'); + + return node.finishObjectExpression(properties); + } + + function reinterpretExpressionAsPattern(expr) { + var i; + switch (expr.type) { + case Syntax.Identifier: + case Syntax.MemberExpression: + case Syntax.RestElement: + case Syntax.AssignmentPattern: + break; + case Syntax.SpreadElement: + expr.type = Syntax.RestElement; + reinterpretExpressionAsPattern(expr.argument); + break; + case Syntax.ArrayExpression: + expr.type = Syntax.ArrayPattern; + for (i = 0; i < expr.elements.length; i++) { + if (expr.elements[i] !== null) { + reinterpretExpressionAsPattern(expr.elements[i]); + } + } + break; + case Syntax.ObjectExpression: + expr.type = Syntax.ObjectPattern; + for (i = 0; i < expr.properties.length; i++) { + reinterpretExpressionAsPattern(expr.properties[i].value); + } + break; + case Syntax.AssignmentExpression: + expr.type = Syntax.AssignmentPattern; + reinterpretExpressionAsPattern(expr.left); + break; + default: + // Allow other node type for tolerant parsing. + break; + } + } + + // ECMA-262 12.2.9 Template Literals + + function parseTemplateElement(option) { + var node, token; + + if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) { + throwUnexpectedToken(); + } + + node = new Node(); + token = lex(); + + return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); + } + + function parseTemplateLiteral() { + var quasi, quasis, expressions, node = new Node(); + + quasi = parseTemplateElement({ head: true }); + quasis = [quasi]; + expressions = []; + + while (!quasi.tail) { + expressions.push(parseExpression()); + quasi = parseTemplateElement({ head: false }); + quasis.push(quasi); + } + + return node.finishTemplateLiteral(quasis, expressions); + } + + // ECMA-262 12.2.10 The Grouping Operator + + function parseGroupExpression() { + var expr, expressions, startToken, i, params = []; + + expect('('); + + if (match(')')) { + lex(); + if (!match('=>')) { + expect('=>'); + } + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: [], + rawParams: [] + }; + } + + startToken = lookahead; + if (match('...')) { + expr = parseRestElement(params); + expect(')'); + if (!match('=>')) { + expect('=>'); + } + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: [expr] + }; + } + + isBindingElement = true; + expr = inheritCoverGrammar(parseAssignmentExpression); + + if (match(',')) { + isAssignmentTarget = false; + expressions = [expr]; + + while (startIndex < length) { + if (!match(',')) { + break; + } + lex(); + + if (match('...')) { + if (!isBindingElement) { + throwUnexpectedToken(lookahead); + } + expressions.push(parseRestElement(params)); + expect(')'); + if (!match('=>')) { + expect('=>'); + } + isBindingElement = false; + for (i = 0; i < expressions.length; i++) { + reinterpretExpressionAsPattern(expressions[i]); + } + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: expressions + }; + } + + expressions.push(inheritCoverGrammar(parseAssignmentExpression)); + } + + expr = new WrappingNode(startToken).finishSequenceExpression(expressions); + } + + + expect(')'); + + if (match('=>')) { + if (expr.type === Syntax.Identifier && expr.name === 'yield') { + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: [expr] + }; + } + + if (!isBindingElement) { + throwUnexpectedToken(lookahead); + } + + if (expr.type === Syntax.SequenceExpression) { + for (i = 0; i < expr.expressions.length; i++) { + reinterpretExpressionAsPattern(expr.expressions[i]); + } + } else { + reinterpretExpressionAsPattern(expr); + } + + expr = { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr] + }; + } + isBindingElement = false; + return expr; + } + + + // ECMA-262 12.2 Primary Expressions + + function parsePrimaryExpression() { + var type, token, expr, node; + + if (match('(')) { + isBindingElement = false; + return inheritCoverGrammar(parseGroupExpression); + } + + if (match('[')) { + return inheritCoverGrammar(parseArrayInitializer); + } + + if (match('{')) { + return inheritCoverGrammar(parseObjectInitializer); + } + + type = lookahead.type; + node = new Node(); + + if (type === Token.Identifier) { + if (state.sourceType === 'module' && lookahead.value === 'await') { + tolerateUnexpectedToken(lookahead); + } + expr = node.finishIdentifier(lex().value); + } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { + isAssignmentTarget = isBindingElement = false; + if (strict && lookahead.octal) { + tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral); + } + expr = node.finishLiteral(lex()); + } else if (type === Token.Keyword) { + if (!strict && state.allowYield && matchKeyword('yield')) { + return parseNonComputedProperty(); + } + if (!strict && matchKeyword('let')) { + return node.finishIdentifier(lex().value); + } + isAssignmentTarget = isBindingElement = false; + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + if (matchKeyword('this')) { + lex(); + return node.finishThisExpression(); + } + if (matchKeyword('class')) { + return parseClassExpression(); + } + throwUnexpectedToken(lex()); + } else if (type === Token.BooleanLiteral) { + isAssignmentTarget = isBindingElement = false; + token = lex(); + token.value = (token.value === 'true'); + expr = node.finishLiteral(token); + } else if (type === Token.NullLiteral) { + isAssignmentTarget = isBindingElement = false; + token = lex(); + token.value = null; + expr = node.finishLiteral(token); + } else if (match('/') || match('/=')) { + isAssignmentTarget = isBindingElement = false; + index = startIndex; + + if (typeof extra.tokens !== 'undefined') { + token = collectRegex(); + } else { + token = scanRegExp(); + } + lex(); + expr = node.finishLiteral(token); + } else if (type === Token.Template) { + expr = parseTemplateLiteral(); + } else { + throwUnexpectedToken(lex()); + } + + return expr; + } + + // ECMA-262 12.3 Left-Hand-Side Expressions + + function parseArguments() { + var args = [], expr; + + expect('('); + + if (!match(')')) { + while (startIndex < length) { + if (match('...')) { + expr = new Node(); + lex(); + expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression)); + } else { + expr = isolateCoverGrammar(parseAssignmentExpression); + } + args.push(expr); + if (match(')')) { + break; + } + expectCommaSeparator(); + } + } + + expect(')'); + + return args; + } + + function parseNonComputedProperty() { + var token, node = new Node(); + + token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpectedToken(token); + } + + return node.finishIdentifier(token.value); + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = isolateCoverGrammar(parseExpression); + + expect(']'); + + return expr; + } + + // ECMA-262 12.3.3 The new Operator + + function parseNewExpression() { + var callee, args, node = new Node(); + + expectKeyword('new'); + + if (match('.')) { + lex(); + if (lookahead.type === Token.Identifier && lookahead.value === 'target') { + if (state.inFunctionBody) { + lex(); + return node.finishMetaProperty('new', 'target'); + } + } + throwUnexpectedToken(lookahead); + } + + callee = isolateCoverGrammar(parseLeftHandSideExpression); + args = match('(') ? parseArguments() : []; + + isAssignmentTarget = isBindingElement = false; + + return node.finishNewExpression(callee, args); + } + + // ECMA-262 12.3.4 Function Calls + + function parseLeftHandSideExpressionAllowCall() { + var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn; + + startToken = lookahead; + state.allowIn = true; + + if (matchKeyword('super') && state.inFunctionBody) { + expr = new Node(); + lex(); + expr = expr.finishSuper(); + if (!match('(') && !match('.') && !match('[')) { + throwUnexpectedToken(lookahead); + } + } else { + expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression); + } + + for (;;) { + if (match('.')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseNonComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else if (match('(')) { + isBindingElement = false; + isAssignmentTarget = false; + args = parseArguments(); + expr = new WrappingNode(startToken).finishCallExpression(expr, args); + } else if (match('[')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else if (lookahead.type === Token.Template && lookahead.head) { + quasi = parseTemplateLiteral(); + expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi); + } else { + break; + } + } + state.allowIn = previousAllowIn; + + return expr; + } + + // ECMA-262 12.3 Left-Hand-Side Expressions + + function parseLeftHandSideExpression() { + var quasi, expr, property, startToken; + assert(state.allowIn, 'callee of new expression always allow in keyword.'); + + startToken = lookahead; + + if (matchKeyword('super') && state.inFunctionBody) { + expr = new Node(); + lex(); + expr = expr.finishSuper(); + if (!match('[') && !match('.')) { + throwUnexpectedToken(lookahead); + } + } else { + expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression); + } + + for (;;) { + if (match('[')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else if (match('.')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseNonComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else if (lookahead.type === Token.Template && lookahead.head) { + quasi = parseTemplateLiteral(); + expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi); + } else { + break; + } + } + return expr; + } + + // ECMA-262 12.4 Postfix Expressions + + function parsePostfixExpression() { + var expr, token, startToken = lookahead; + + expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall); + + if (!hasLineTerminator && lookahead.type === Token.Punctuator) { + if (match('++') || match('--')) { + // ECMA-262 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateError(Messages.StrictLHSPostfix); + } + + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + isAssignmentTarget = isBindingElement = false; + + token = lex(); + expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr); + } + } + + return expr; + } + + // ECMA-262 12.5 Unary Operators + + function parseUnaryExpression() { + var token, expr, startToken; + + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { + expr = parsePostfixExpression(); + } else if (match('++') || match('--')) { + startToken = lookahead; + token = lex(); + expr = inheritCoverGrammar(parseUnaryExpression); + // ECMA-262 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateError(Messages.StrictLHSPrefix); + } + + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInAssignment); + } + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + isAssignmentTarget = isBindingElement = false; + } else if (match('+') || match('-') || match('~') || match('!')) { + startToken = lookahead; + token = lex(); + expr = inheritCoverGrammar(parseUnaryExpression); + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + isAssignmentTarget = isBindingElement = false; + } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + startToken = lookahead; + token = lex(); + expr = inheritCoverGrammar(parseUnaryExpression); + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + tolerateError(Messages.StrictDelete); + } + isAssignmentTarget = isBindingElement = false; + } else { + expr = parsePostfixExpression(); + } + + return expr; + } + + function binaryPrecedence(token, allowIn) { + var prec = 0; + + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return 0; + } + + switch (token.value) { + case '||': + prec = 1; + break; + + case '&&': + prec = 2; + break; + + case '|': + prec = 3; + break; + + case '^': + prec = 4; + break; + + case '&': + prec = 5; + break; + + case '==': + case '!=': + case '===': + case '!==': + prec = 6; + break; + + case '<': + case '>': + case '<=': + case '>=': + case 'instanceof': + prec = 7; + break; + + case 'in': + prec = allowIn ? 7 : 0; + break; + + case '<<': + case '>>': + case '>>>': + prec = 8; + break; + + case '+': + case '-': + prec = 9; + break; + + case '*': + case '/': + case '%': + prec = 11; + break; + + default: + break; + } + + return prec; + } + + // ECMA-262 12.6 Multiplicative Operators + // ECMA-262 12.7 Additive Operators + // ECMA-262 12.8 Bitwise Shift Operators + // ECMA-262 12.9 Relational Operators + // ECMA-262 12.10 Equality Operators + // ECMA-262 12.11 Binary Bitwise Operators + // ECMA-262 12.12 Binary Logical Operators + + function parseBinaryExpression() { + var marker, markers, expr, token, prec, stack, right, operator, left, i; + + marker = lookahead; + left = inheritCoverGrammar(parseUnaryExpression); + + token = lookahead; + prec = binaryPrecedence(token, state.allowIn); + if (prec === 0) { + return left; + } + isAssignmentTarget = isBindingElement = false; + token.prec = prec; + lex(); + + markers = [marker, lookahead]; + right = isolateCoverGrammar(parseUnaryExpression); + + stack = [left, token, right]; + + while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) { + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop().value; + left = stack.pop(); + markers.pop(); + expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right); + stack.push(expr); + } + + // Shift. + token = lex(); + token.prec = prec; + stack.push(token); + markers.push(lookahead); + expr = isolateCoverGrammar(parseUnaryExpression); + stack.push(expr); + } + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + markers.pop(); + while (i > 1) { + expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr); + i -= 2; + } + + return expr; + } + + + // ECMA-262 12.13 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent, alternate, startToken; + + startToken = lookahead; + + expr = inheritCoverGrammar(parseBinaryExpression); + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = isolateCoverGrammar(parseAssignmentExpression); + state.allowIn = previousAllowIn; + expect(':'); + alternate = isolateCoverGrammar(parseAssignmentExpression); + + expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate); + isAssignmentTarget = isBindingElement = false; + } + + return expr; + } + + // ECMA-262 14.2 Arrow Function Definitions + + function parseConciseBody() { + if (match('{')) { + return parseFunctionSourceElements(); + } + return isolateCoverGrammar(parseAssignmentExpression); + } + + function checkPatternParam(options, param) { + var i; + switch (param.type) { + case Syntax.Identifier: + validateParam(options, param, param.name); + break; + case Syntax.RestElement: + checkPatternParam(options, param.argument); + break; + case Syntax.AssignmentPattern: + checkPatternParam(options, param.left); + break; + case Syntax.ArrayPattern: + for (i = 0; i < param.elements.length; i++) { + if (param.elements[i] !== null) { + checkPatternParam(options, param.elements[i]); + } + } + break; + case Syntax.YieldExpression: + break; + default: + assert(param.type === Syntax.ObjectPattern, 'Invalid type'); + for (i = 0; i < param.properties.length; i++) { + checkPatternParam(options, param.properties[i].value); + } + break; + } + } + function reinterpretAsCoverFormalsList(expr) { + var i, len, param, params, defaults, defaultCount, options, token; + + defaults = []; + defaultCount = 0; + params = [expr]; + + switch (expr.type) { + case Syntax.Identifier: + break; + case PlaceHolders.ArrowParameterPlaceHolder: + params = expr.params; + break; + default: + return null; + } + + options = { + paramSet: {} + }; + + for (i = 0, len = params.length; i < len; i += 1) { + param = params[i]; + switch (param.type) { + case Syntax.AssignmentPattern: + params[i] = param.left; + if (param.right.type === Syntax.YieldExpression) { + if (param.right.argument) { + throwUnexpectedToken(lookahead); + } + param.right.type = Syntax.Identifier; + param.right.name = 'yield'; + delete param.right.argument; + delete param.right.delegate; + } + defaults.push(param.right); + ++defaultCount; + checkPatternParam(options, param.left); + break; + default: + checkPatternParam(options, param); + params[i] = param; + defaults.push(null); + break; + } + } + + if (strict || !state.allowYield) { + for (i = 0, len = params.length; i < len; i += 1) { + param = params[i]; + if (param.type === Syntax.YieldExpression) { + throwUnexpectedToken(lookahead); + } + } + } + + if (options.message === Messages.StrictParamDupe) { + token = strict ? options.stricted : options.firstRestricted; + throwUnexpectedToken(token, options.message); + } + + if (defaultCount === 0) { + defaults = []; + } + + return { + params: params, + defaults: defaults, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseArrowFunctionExpression(options, node) { + var previousStrict, previousAllowYield, body; + + if (hasLineTerminator) { + tolerateUnexpectedToken(lookahead); + } + expect('=>'); + + previousStrict = strict; + previousAllowYield = state.allowYield; + state.allowYield = true; + + body = parseConciseBody(); + + if (strict && options.firstRestricted) { + throwUnexpectedToken(options.firstRestricted, options.message); + } + if (strict && options.stricted) { + tolerateUnexpectedToken(options.stricted, options.message); + } + + strict = previousStrict; + state.allowYield = previousAllowYield; + + return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement); + } + + // ECMA-262 14.4 Yield expression + + function parseYieldExpression() { + var argument, expr, delegate, previousAllowYield; + + argument = null; + expr = new Node(); + delegate = false; + + expectKeyword('yield'); + + if (!hasLineTerminator) { + previousAllowYield = state.allowYield; + state.allowYield = false; + delegate = match('*'); + if (delegate) { + lex(); + argument = parseAssignmentExpression(); + } else { + if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) { + argument = parseAssignmentExpression(); + } + } + state.allowYield = previousAllowYield; + } + + return expr.finishYieldExpression(argument, delegate); + } + + // ECMA-262 12.14 Assignment Operators + + function parseAssignmentExpression() { + var token, expr, right, list, startToken; + + startToken = lookahead; + token = lookahead; + + if (!state.allowYield && matchKeyword('yield')) { + return parseYieldExpression(); + } + + expr = parseConditionalExpression(); + + if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) { + isAssignmentTarget = isBindingElement = false; + list = reinterpretAsCoverFormalsList(expr); + + if (list) { + firstCoverInitializedNameError = null; + return parseArrowFunctionExpression(list, new WrappingNode(startToken)); + } + + return expr; + } + + if (matchAssign()) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + // ECMA-262 12.1.1 + if (strict && expr.type === Syntax.Identifier) { + if (isRestrictedWord(expr.name)) { + tolerateUnexpectedToken(token, Messages.StrictLHSAssignment); + } + if (isStrictModeReservedWord(expr.name)) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } + } + + if (!match('=')) { + isAssignmentTarget = isBindingElement = false; + } else { + reinterpretExpressionAsPattern(expr); + } + + token = lex(); + right = isolateCoverGrammar(parseAssignmentExpression); + expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right); + firstCoverInitializedNameError = null; + } + + return expr; + } + + // ECMA-262 12.15 Comma Operator + + function parseExpression() { + var expr, startToken = lookahead, expressions; + + expr = isolateCoverGrammar(parseAssignmentExpression); + + if (match(',')) { + expressions = [expr]; + + while (startIndex < length) { + if (!match(',')) { + break; + } + lex(); + expressions.push(isolateCoverGrammar(parseAssignmentExpression)); + } + + expr = new WrappingNode(startToken).finishSequenceExpression(expressions); + } + + return expr; + } + + // ECMA-262 13.2 Block + + function parseStatementListItem() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'export': + if (state.sourceType !== 'module') { + tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration); + } + return parseExportDeclaration(); + case 'import': + if (state.sourceType !== 'module') { + tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration); + } + return parseImportDeclaration(); + case 'const': + return parseLexicalDeclaration({inFor: false}); + case 'function': + return parseFunctionDeclaration(new Node()); + case 'class': + return parseClassDeclaration(); + } + } + + if (matchKeyword('let') && isLexicalDeclaration()) { + return parseLexicalDeclaration({inFor: false}); + } + + return parseStatement(); + } + + function parseStatementList() { + var list = []; + while (startIndex < length) { + if (match('}')) { + break; + } + list.push(parseStatementListItem()); + } + + return list; + } + + function parseBlock() { + var block, node = new Node(); + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return node.finishBlockStatement(block); + } + + // ECMA-262 13.3.2 Variable Statement + + function parseVariableIdentifier(kind) { + var token, node = new Node(); + + token = lex(); + + if (token.type === Token.Keyword && token.value === 'yield') { + if (strict) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } if (!state.allowYield) { + throwUnexpectedToken(token); + } + } else if (token.type !== Token.Identifier) { + if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } else { + if (strict || token.value !== 'let' || kind !== 'var') { + throwUnexpectedToken(token); + } + } + } else if (state.sourceType === 'module' && token.type === Token.Identifier && token.value === 'await') { + tolerateUnexpectedToken(token); + } + + return node.finishIdentifier(token.value); + } + + function parseVariableDeclaration(options) { + var init = null, id, node = new Node(), params = []; + + id = parsePattern(params, 'var'); + + // ECMA-262 12.2.1 + if (strict && isRestrictedWord(id.name)) { + tolerateError(Messages.StrictVarName); + } + + if (match('=')) { + lex(); + init = isolateCoverGrammar(parseAssignmentExpression); + } else if (id.type !== Syntax.Identifier && !options.inFor) { + expect('='); + } + + return node.finishVariableDeclarator(id, init); + } + + function parseVariableDeclarationList(options) { + var opt, list; + + opt = { inFor: options.inFor }; + list = [parseVariableDeclaration(opt)]; + + while (match(',')) { + lex(); + list.push(parseVariableDeclaration(opt)); + } + + return list; + } + + function parseVariableStatement(node) { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList({ inFor: false }); + + consumeSemicolon(); + + return node.finishVariableDeclaration(declarations); + } + + // ECMA-262 13.3.1 Let and Const Declarations + + function parseLexicalBinding(kind, options) { + var init = null, id, node = new Node(), params = []; + + id = parsePattern(params, kind); + + // ECMA-262 12.2.1 + if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) { + tolerateError(Messages.StrictVarName); + } + + if (kind === 'const') { + if (!matchKeyword('in') && !matchContextualKeyword('of')) { + expect('='); + init = isolateCoverGrammar(parseAssignmentExpression); + } + } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) { + expect('='); + init = isolateCoverGrammar(parseAssignmentExpression); + } + + return node.finishVariableDeclarator(id, init); + } + + function parseBindingList(kind, options) { + var list = [parseLexicalBinding(kind, options)]; + + while (match(',')) { + lex(); + list.push(parseLexicalBinding(kind, options)); + } + + return list; + } + + + function tokenizerState() { + return { + index: index, + lineNumber: lineNumber, + lineStart: lineStart, + hasLineTerminator: hasLineTerminator, + lastIndex: lastIndex, + lastLineNumber: lastLineNumber, + lastLineStart: lastLineStart, + startIndex: startIndex, + startLineNumber: startLineNumber, + startLineStart: startLineStart, + lookahead: lookahead, + tokenCount: extra.tokens ? extra.tokens.length : 0 + }; + } + + function resetTokenizerState(ts) { + index = ts.index; + lineNumber = ts.lineNumber; + lineStart = ts.lineStart; + hasLineTerminator = ts.hasLineTerminator; + lastIndex = ts.lastIndex; + lastLineNumber = ts.lastLineNumber; + lastLineStart = ts.lastLineStart; + startIndex = ts.startIndex; + startLineNumber = ts.startLineNumber; + startLineStart = ts.startLineStart; + lookahead = ts.lookahead; + if (extra.tokens) { + extra.tokens.splice(ts.tokenCount, extra.tokens.length); + } + } + + function isLexicalDeclaration() { + var lexical, ts; + + ts = tokenizerState(); + + lex(); + lexical = (lookahead.type === Token.Identifier) || match('[') || match('{') || + matchKeyword('let') || matchKeyword('yield'); + + resetTokenizerState(ts); + + return lexical; + } + + function parseLexicalDeclaration(options) { + var kind, declarations, node = new Node(); + + kind = lex().value; + assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); + + declarations = parseBindingList(kind, options); + + consumeSemicolon(); + + return node.finishLexicalDeclaration(declarations, kind); + } + + function parseRestElement(params) { + var param, node = new Node(); + + lex(); + + if (match('{')) { + throwError(Messages.ObjectPatternAsRestParameter); + } + + params.push(lookahead); + + param = parseVariableIdentifier(); + + if (match('=')) { + throwError(Messages.DefaultRestParameter); + } + + if (!match(')')) { + throwError(Messages.ParameterAfterRestParameter); + } + + return node.finishRestElement(param); + } + + // ECMA-262 13.4 Empty Statement + + function parseEmptyStatement(node) { + expect(';'); + return node.finishEmptyStatement(); + } + + // ECMA-262 12.4 Expression Statement + + function parseExpressionStatement(node) { + var expr = parseExpression(); + consumeSemicolon(); + return node.finishExpressionStatement(expr); + } + + // ECMA-262 13.6 If statement + + function parseIfStatement(node) { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return node.finishIfStatement(test, consequent, alternate); + } + + // ECMA-262 13.7 Iteration Statements + + function parseDoWhileStatement(node) { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return node.finishDoWhileStatement(body, test); + } + + function parseWhileStatement(node) { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return node.finishWhileStatement(test, body); + } + + function parseForStatement(node) { + var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations, + body, oldInIteration, previousAllowIn = state.allowIn; + + init = test = update = null; + forIn = true; + + expectKeyword('for'); + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var')) { + init = new Node(); + lex(); + + state.allowIn = false; + declarations = parseVariableDeclarationList({ inFor: true }); + state.allowIn = previousAllowIn; + + if (declarations.length === 1 && matchKeyword('in')) { + init = init.finishVariableDeclaration(declarations); + lex(); + left = init; + right = parseExpression(); + init = null; + } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) { + init = init.finishVariableDeclaration(declarations); + lex(); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; + } else { + init = init.finishVariableDeclaration(declarations); + expect(';'); + } + } else if (matchKeyword('const') || matchKeyword('let')) { + init = new Node(); + kind = lex().value; + + if (!strict && lookahead.value === 'in') { + init = init.finishIdentifier(kind); + lex(); + left = init; + right = parseExpression(); + init = null; + } else { + state.allowIn = false; + declarations = parseBindingList(kind, {inFor: true}); + state.allowIn = previousAllowIn; + + if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) { + init = init.finishLexicalDeclaration(declarations, kind); + lex(); + left = init; + right = parseExpression(); + init = null; + } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) { + init = init.finishLexicalDeclaration(declarations, kind); + lex(); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; + } else { + consumeSemicolon(); + init = init.finishLexicalDeclaration(declarations, kind); + } + } + } else { + initStartToken = lookahead; + state.allowIn = false; + init = inheritCoverGrammar(parseAssignmentExpression); + state.allowIn = previousAllowIn; + + if (matchKeyword('in')) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInForIn); + } + + lex(); + reinterpretExpressionAsPattern(init); + left = init; + right = parseExpression(); + init = null; + } else if (matchContextualKeyword('of')) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInForLoop); + } + + lex(); + reinterpretExpressionAsPattern(init); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; + } else { + if (match(',')) { + initSeq = [init]; + while (match(',')) { + lex(); + initSeq.push(isolateCoverGrammar(parseAssignmentExpression)); + } + init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq); + } + expect(';'); + } + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = isolateCoverGrammar(parseStatement); + + state.inIteration = oldInIteration; + + return (typeof left === 'undefined') ? + node.finishForStatement(init, test, update, body) : + forIn ? node.finishForInStatement(left, right, body) : + node.finishForOfStatement(left, right, body); + } + + // ECMA-262 13.8 The continue statement + + function parseContinueStatement(node) { + var label = null, key; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source.charCodeAt(startIndex) === 0x3B) { + lex(); + + if (!state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(null); + } + + if (hasLineTerminator) { + if (!state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(label); + } + + // ECMA-262 13.9 The break statement + + function parseBreakStatement(node) { + var label = null, key; + + expectKeyword('break'); + + // Catch the very common case first: immediately a semicolon (U+003B). + if (source.charCodeAt(lastIndex) === 0x3B) { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(null); + } + + if (hasLineTerminator) { + if (!(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + } else if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(label); + } + + // ECMA-262 13.10 The return statement + + function parseReturnStatement(node) { + var argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + tolerateError(Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source.charCodeAt(lastIndex) === 0x20) { + if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) { + argument = parseExpression(); + consumeSemicolon(); + return node.finishReturnStatement(argument); + } + } + + if (hasLineTerminator) { + // HACK + return node.finishReturnStatement(null); + } + + if (!match(';')) { + if (!match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return node.finishReturnStatement(argument); + } + + // ECMA-262 13.11 The with statement + + function parseWithStatement(node) { + var object, body; + + if (strict) { + tolerateError(Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return node.finishWithStatement(object, body); + } + + // ECMA-262 13.12 The switch statement + + function parseSwitchCase() { + var test, consequent = [], statement, node = new Node(); + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (startIndex < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + statement = parseStatementListItem(); + consequent.push(statement); + } + + return node.finishSwitchCase(test, consequent); + } + + function parseSwitchStatement(node) { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return node.finishSwitchStatement(discriminant, cases); + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (startIndex < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError(Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return node.finishSwitchStatement(discriminant, cases); + } + + // ECMA-262 13.14 The throw statement + + function parseThrowStatement(node) { + var argument; + + expectKeyword('throw'); + + if (hasLineTerminator) { + throwError(Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return node.finishThrowStatement(argument); + } + + // ECMA-262 13.15 The try statement + + function parseCatchClause() { + var param, params = [], paramMap = {}, key, i, body, node = new Node(); + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpectedToken(lookahead); + } + + param = parsePattern(params); + for (i = 0; i < params.length; i++) { + key = '$' + params[i].value; + if (Object.prototype.hasOwnProperty.call(paramMap, key)) { + tolerateError(Messages.DuplicateBinding, params[i].value); + } + paramMap[key] = true; + } + + // ECMA-262 12.14.1 + if (strict && isRestrictedWord(param.name)) { + tolerateError(Messages.StrictCatchVariable); + } + + expect(')'); + body = parseBlock(); + return node.finishCatchClause(param, body); + } + + function parseTryStatement(node) { + var block, handler = null, finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handler = parseCatchClause(); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (!handler && !finalizer) { + throwError(Messages.NoCatchOrFinally); + } + + return node.finishTryStatement(block, handler, finalizer); + } + + // ECMA-262 13.16 The debugger statement + + function parseDebuggerStatement(node) { + expectKeyword('debugger'); + + consumeSemicolon(); + + return node.finishDebuggerStatement(); + } + + // 13 Statements + + function parseStatement() { + var type = lookahead.type, + expr, + labeledBody, + key, + node; + + if (type === Token.EOF) { + throwUnexpectedToken(lookahead); + } + + if (type === Token.Punctuator && lookahead.value === '{') { + return parseBlock(); + } + isAssignmentTarget = isBindingElement = true; + node = new Node(); + + if (type === Token.Punctuator) { + switch (lookahead.value) { + case ';': + return parseEmptyStatement(node); + case '(': + return parseExpressionStatement(node); + default: + break; + } + } else if (type === Token.Keyword) { + switch (lookahead.value) { + case 'break': + return parseBreakStatement(node); + case 'continue': + return parseContinueStatement(node); + case 'debugger': + return parseDebuggerStatement(node); + case 'do': + return parseDoWhileStatement(node); + case 'for': + return parseForStatement(node); + case 'function': + return parseFunctionDeclaration(node); + case 'if': + return parseIfStatement(node); + case 'return': + return parseReturnStatement(node); + case 'switch': + return parseSwitchStatement(node); + case 'throw': + return parseThrowStatement(node); + case 'try': + return parseTryStatement(node); + case 'var': + return parseVariableStatement(node); + case 'while': + return parseWhileStatement(node); + case 'with': + return parseWithStatement(node); + default: + break; + } + } + + expr = parseExpression(); + + // ECMA-262 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + key = '$' + expr.name; + if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[key] = true; + labeledBody = parseStatement(); + delete state.labelSet[key]; + return node.finishLabeledStatement(expr, labeledBody); + } + + consumeSemicolon(); + + return node.finishExpressionStatement(expr); + } + + // ECMA-262 14.1 Function Definition + + function parseFunctionSourceElements() { + var statement, body = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, + node = new Node(); + + expect('{'); + + while (startIndex < length) { + if (lookahead.type !== Token.StringLiteral) { + break; + } + token = lookahead; + + statement = parseStatementListItem(); + body.push(statement); + if (statement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.start + 1, token.end - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + + while (startIndex < length) { + if (match('}')) { + break; + } + body.push(parseStatementListItem()); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + + return node.finishBlockStatement(body); + } + + function validateParam(options, param, name) { + var key = '$' + name; + if (strict) { + if (isRestrictedWord(name)) { + options.stricted = param; + options.message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } else if (!options.firstRestricted) { + if (isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } + options.paramSet[key] = true; + } + + function parseParam(options) { + var token, param, params = [], i, def; + + token = lookahead; + if (token.value === '...') { + param = parseRestElement(params); + validateParam(options, param.argument, param.argument.name); + options.params.push(param); + options.defaults.push(null); + return false; + } + + param = parsePatternWithDefault(params); + for (i = 0; i < params.length; i++) { + validateParam(options, params[i], params[i].value); + } + + if (param.type === Syntax.AssignmentPattern) { + def = param.right; + param = param.left; + ++options.defaultCount; + } + + options.params.push(param); + options.defaults.push(def); + + return !match(')'); + } + + function parseParams(firstRestricted) { + var options; + + options = { + params: [], + defaultCount: 0, + defaults: [], + firstRestricted: firstRestricted + }; + + expect('('); + + if (!match(')')) { + options.paramSet = {}; + while (startIndex < length) { + if (!parseParam(options)) { + break; + } + expect(','); + } + } + + expect(')'); + + if (options.defaultCount === 0) { + options.defaults = []; + } + + return { + params: options.params, + defaults: options.defaults, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseFunctionDeclaration(node, identifierIsOptional) { + var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, + isGenerator, previousAllowYield; + + previousAllowYield = state.allowYield; + + expectKeyword('function'); + + isGenerator = match('*'); + if (isGenerator) { + lex(); + } + + if (!identifierIsOptional || !match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + state.allowYield = !isGenerator; + tmp = parseParams(firstRestricted); + params = tmp.params; + defaults = tmp.defaults; + stricted = tmp.stricted; + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwUnexpectedToken(firstRestricted, message); + } + if (strict && stricted) { + tolerateUnexpectedToken(stricted, message); + } + + strict = previousStrict; + state.allowYield = previousAllowYield; + + return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator); + } + + function parseFunctionExpression() { + var token, id = null, stricted, firstRestricted, message, tmp, + params = [], defaults = [], body, previousStrict, node = new Node(), + isGenerator, previousAllowYield; + + previousAllowYield = state.allowYield; + + expectKeyword('function'); + + isGenerator = match('*'); + if (isGenerator) { + lex(); + } + + state.allowYield = !isGenerator; + if (!match('(')) { + token = lookahead; + id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + tmp = parseParams(firstRestricted); + params = tmp.params; + defaults = tmp.defaults; + stricted = tmp.stricted; + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwUnexpectedToken(firstRestricted, message); + } + if (strict && stricted) { + tolerateUnexpectedToken(stricted, message); + } + strict = previousStrict; + state.allowYield = previousAllowYield; + + return node.finishFunctionExpression(id, params, defaults, body, isGenerator); + } + + // ECMA-262 14.5 Class Definitions + + function parseClassBody() { + var classBody, token, isStatic, hasConstructor = false, body, method, computed, key; + + classBody = new Node(); + + expect('{'); + body = []; + while (!match('}')) { + if (match(';')) { + lex(); + } else { + method = new Node(); + token = lookahead; + isStatic = false; + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) { + token = lookahead; + isStatic = true; + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + } + } + } + method = tryParseMethodDefinition(token, key, computed, method); + if (method) { + method['static'] = isStatic; // jscs:ignore requireDotNotation + if (method.kind === 'init') { + method.kind = 'method'; + } + if (!isStatic) { + if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') { + if (method.kind !== 'method' || !method.method || method.value.generator) { + throwUnexpectedToken(token, Messages.ConstructorSpecialMethod); + } + if (hasConstructor) { + throwUnexpectedToken(token, Messages.DuplicateConstructor); + } else { + hasConstructor = true; + } + method.kind = 'constructor'; + } + } else { + if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') { + throwUnexpectedToken(token, Messages.StaticPrototype); + } + } + method.type = Syntax.MethodDefinition; + delete method.method; + delete method.shorthand; + body.push(method); + } else { + throwUnexpectedToken(lookahead); + } + } + } + lex(); + return classBody.finishClassBody(body); + } + + function parseClassDeclaration(identifierIsOptional) { + var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict; + strict = true; + + expectKeyword('class'); + + if (!identifierIsOptional || lookahead.type === Token.Identifier) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + lex(); + superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall); + } + classBody = parseClassBody(); + strict = previousStrict; + + return classNode.finishClassDeclaration(id, superClass, classBody); + } + + function parseClassExpression() { + var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict; + strict = true; + + expectKeyword('class'); + + if (lookahead.type === Token.Identifier) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + lex(); + superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall); + } + classBody = parseClassBody(); + strict = previousStrict; + + return classNode.finishClassExpression(id, superClass, classBody); + } + + // ECMA-262 15.2 Modules + + function parseModuleSpecifier() { + var node = new Node(); + + if (lookahead.type !== Token.StringLiteral) { + throwError(Messages.InvalidModuleSpecifier); + } + return node.finishLiteral(lex()); + } + + // ECMA-262 15.2.3 Exports + + function parseExportSpecifier() { + var exported, local, node = new Node(), def; + if (matchKeyword('default')) { + // export {default} from 'something'; + def = new Node(); + lex(); + local = def.finishIdentifier('default'); + } else { + local = parseVariableIdentifier(); + } + if (matchContextualKeyword('as')) { + lex(); + exported = parseNonComputedProperty(); + } + return node.finishExportSpecifier(local, exported); + } + + function parseExportNamedDeclaration(node) { + var declaration = null, + isExportFromIdentifier, + src = null, specifiers = []; + + // non-default export + if (lookahead.type === Token.Keyword) { + // covers: + // export var f = 1; + switch (lookahead.value) { + case 'let': + case 'const': + declaration = parseLexicalDeclaration({inFor: false}); + return node.finishExportNamedDeclaration(declaration, specifiers, null); + case 'var': + case 'class': + case 'function': + declaration = parseStatementListItem(); + return node.finishExportNamedDeclaration(declaration, specifiers, null); + } + } + + expect('{'); + while (!match('}')) { + isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); + specifiers.push(parseExportSpecifier()); + if (!match('}')) { + expect(','); + if (match('}')) { + break; + } + } + } + expect('}'); + + if (matchContextualKeyword('from')) { + // covering: + // export {default} from 'foo'; + // export {foo} from 'foo'; + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + } else if (isExportFromIdentifier) { + // covering: + // export {default}; // missing fromClause + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } else { + // cover + // export {foo}; + consumeSemicolon(); + } + return node.finishExportNamedDeclaration(declaration, specifiers, src); + } + + function parseExportDefaultDeclaration(node) { + var declaration = null, + expression = null; + + // covers: + // export default ... + expectKeyword('default'); + + if (matchKeyword('function')) { + // covers: + // export default function foo () {} + // export default function () {} + declaration = parseFunctionDeclaration(new Node(), true); + return node.finishExportDefaultDeclaration(declaration); + } + if (matchKeyword('class')) { + declaration = parseClassDeclaration(true); + return node.finishExportDefaultDeclaration(declaration); + } + + if (matchContextualKeyword('from')) { + throwError(Messages.UnexpectedToken, lookahead.value); + } + + // covers: + // export default {}; + // export default []; + // export default (1 + 2); + if (match('{')) { + expression = parseObjectInitializer(); + } else if (match('[')) { + expression = parseArrayInitializer(); + } else { + expression = parseAssignmentExpression(); + } + consumeSemicolon(); + return node.finishExportDefaultDeclaration(expression); + } + + function parseExportAllDeclaration(node) { + var src; + + // covers: + // export * from 'foo'; + expect('*'); + if (!matchContextualKeyword('from')) { + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + + return node.finishExportAllDeclaration(src); + } + + function parseExportDeclaration() { + var node = new Node(); + if (state.inFunctionBody) { + throwError(Messages.IllegalExportDeclaration); + } + + expectKeyword('export'); + + if (matchKeyword('default')) { + return parseExportDefaultDeclaration(node); + } + if (match('*')) { + return parseExportAllDeclaration(node); + } + return parseExportNamedDeclaration(node); + } + + // ECMA-262 15.2.2 Imports + + function parseImportSpecifier() { + // import {} ...; + var local, imported, node = new Node(); + + imported = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { + lex(); + local = parseVariableIdentifier(); + } + + return node.finishImportSpecifier(local, imported); + } + + function parseNamedImports() { + var specifiers = []; + // {foo, bar as bas} + expect('{'); + while (!match('}')) { + specifiers.push(parseImportSpecifier()); + if (!match('}')) { + expect(','); + if (match('}')) { + break; + } + } + } + expect('}'); + return specifiers; + } + + function parseImportDefaultSpecifier() { + // import ...; + var local, node = new Node(); + + local = parseNonComputedProperty(); + + return node.finishImportDefaultSpecifier(local); + } + + function parseImportNamespaceSpecifier() { + // import <* as foo> ...; + var local, node = new Node(); + + expect('*'); + if (!matchContextualKeyword('as')) { + throwError(Messages.NoAsAfterImportNamespace); + } + lex(); + local = parseNonComputedProperty(); + + return node.finishImportNamespaceSpecifier(local); + } + + function parseImportDeclaration() { + var specifiers = [], src, node = new Node(); + + if (state.inFunctionBody) { + throwError(Messages.IllegalImportDeclaration); + } + + expectKeyword('import'); + + if (lookahead.type === Token.StringLiteral) { + // import 'foo'; + src = parseModuleSpecifier(); + } else { + + if (match('{')) { + // import {bar} + specifiers = specifiers.concat(parseNamedImports()); + } else if (match('*')) { + // import * as foo + specifiers.push(parseImportNamespaceSpecifier()); + } else if (isIdentifierName(lookahead) && !matchKeyword('default')) { + // import foo + specifiers.push(parseImportDefaultSpecifier()); + if (match(',')) { + lex(); + if (match('*')) { + // import foo, * as foo + specifiers.push(parseImportNamespaceSpecifier()); + } else if (match('{')) { + // import foo, {bar} + specifiers = specifiers.concat(parseNamedImports()); + } else { + throwUnexpectedToken(lookahead); + } + } + } else { + throwUnexpectedToken(lex()); + } + + if (!matchContextualKeyword('from')) { + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + } + + consumeSemicolon(); + return node.finishImportDeclaration(specifiers, src); + } + + // ECMA-262 15.1 Scripts + + function parseScriptBody() { + var statement, body = [], token, directive, firstRestricted; + + while (startIndex < length) { + token = lookahead; + if (token.type !== Token.StringLiteral) { + break; + } + + statement = parseStatementListItem(); + body.push(statement); + if (statement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.start + 1, token.end - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (startIndex < length) { + statement = parseStatementListItem(); + /* istanbul ignore if */ + if (typeof statement === 'undefined') { + break; + } + body.push(statement); + } + return body; + } + + function parseProgram() { + var body, node; + + peek(); + node = new Node(); + + body = parseScriptBody(); + return node.finishProgram(body, state.sourceType); + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (entry.regex) { + token.regex = { + pattern: entry.regex.pattern, + flags: entry.regex.flags + }; + } + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function tokenize(code, options, delegate) { + var toString, + tokens; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + length = source.length; + lookahead = null; + state = { + allowIn: true, + allowYield: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + lastCommentStart: -1, + curlyStack: [] + }; + + extra = {}; + + // Options matching. + options = options || {}; + + // Of course we collect tokens here. + options.tokens = true; + extra.tokens = []; + extra.tokenValues = []; + extra.tokenize = true; + extra.delegate = delegate; + + // The following two fields are necessary to compute the Regex tokens. + extra.openParenToken = -1; + extra.openCurlyToken = -1; + + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + + try { + peek(); + if (lookahead.type === Token.EOF) { + return extra.tokens; + } + + lex(); + while (lookahead.type !== Token.EOF) { + try { + lex(); + } catch (lexError) { + if (extra.errors) { + recordError(lexError); + // We have to break on the first error + // to avoid infinite loops. + break; + } else { + throw lexError; + } + } + } + + tokens = extra.tokens; + if (typeof extra.errors !== 'undefined') { + tokens.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + extra = {}; + } + return tokens; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + length = source.length; + lookahead = null; + state = { + allowIn: true, + allowYield: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + lastCommentStart: -1, + curlyStack: [], + sourceType: 'script' + }; + strict = false; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment; + + if (extra.loc && options.source !== null && options.source !== undefined) { + extra.source = toString(options.source); + } + + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + if (extra.attachComment) { + extra.range = true; + extra.comments = []; + extra.bottomRightStack = []; + extra.trailingComments = []; + extra.leadingComments = []; + } + if (options.sourceType === 'module') { + // very restrictive condition for now + state.sourceType = options.sourceType; + strict = true; + } + } + + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + extra = {}; + } + + return program; + } + + // Sync with *.json manifests. + exports.version = '2.7.3'; + + exports.tokenize = tokenize; + + exports.parse = parse; + + // Deep copy. + /* istanbul ignore next */ + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/esprima/package.json b/hm_sunwell/node_modules/esprima/package.json new file mode 100644 index 0000000..454d26d --- /dev/null +++ b/hm_sunwell/node_modules/esprima/package.json @@ -0,0 +1,147 @@ +{ + "_args": [ + [ + "esprima@^2.6.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/js-yaml" + ] + ], + "_from": "esprima@>=2.6.0 <3.0.0", + "_id": "esprima@2.7.3", + "_inCache": true, + "_installable": true, + "_location": "/esprima", + "_nodeVersion": "6.1.0", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/esprima-2.7.3.tgz_1472013602345_0.010668299393728375" + }, + "_npmUser": { + "email": "ariya.hidayat@gmail.com", + "name": "ariya" + }, + "_npmVersion": "3.8.6", + "_phantomChildren": {}, + "_requested": { + "name": "esprima", + "raw": "esprima@^2.6.0", + "rawSpec": "^2.6.0", + "scope": null, + "spec": ">=2.6.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/escodegen", + "/istanbul", + "/js-yaml" + ], + "_resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "_shasum": "96e3b70d5779f6ad49cd032673d1c312767ba581", + "_shrinkwrap": null, + "_spec": "esprima@^2.6.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/js-yaml", + "author": { + "email": "ariya.hidayat@gmail.com", + "name": "Ariya Hidayat" + }, + "bin": { + "esparse": "./bin/esparse.js", + "esvalidate": "./bin/esvalidate.js" + }, + "bugs": { + "url": "https://github.com/jquery/esprima/issues" + }, + "dependencies": {}, + "description": "ECMAScript parsing infrastructure for multipurpose analysis", + "devDependencies": { + "codecov.io": "~0.1.6", + "escomplex-js": "1.2.0", + "eslint": "~1.7.2", + "everything.js": "~1.0.3", + "glob": "^5.0.15", + "istanbul": "~0.4.0", + "jscs": "~2.3.5", + "json-diff": "~0.3.1", + "karma": "^0.13.11", + "karma-chrome-launcher": "^0.2.1", + "karma-detect-browsers": "^2.0.2", + "karma-firefox-launcher": "^0.1.6", + "karma-ie-launcher": "^0.2.0", + "karma-mocha": "^0.2.0", + "karma-safari-launcher": "^0.1.1", + "karma-sauce-launcher": "^0.2.14", + "lodash": "^3.10.0", + "mocha": "^2.3.3", + "node-tick-processor": "~0.0.2", + "regenerate": "~1.2.1", + "temp": "~0.8.3", + "unicode-7.0.0": "~0.1.5" + }, + "directories": {}, + "dist": { + "shasum": "96e3b70d5779f6ad49cd032673d1c312767ba581", + "tarball": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "bin", + "esprima.js", + "unit-tests.js" + ], + "gitHead": "abaaf7f12040f0b31fac6fee342ffec8feab15d0", + "homepage": "http://esprima.org", + "keywords": [ + "ast", + "ecmascript", + "javascript", + "parser", + "syntax" + ], + "license": "BSD-2-Clause", + "main": "esprima.js", + "maintainers": [ + { + "name": "ariya", + "email": "ariya.hidayat@gmail.com" + } + ], + "name": "esprima", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jquery/esprima.git" + }, + "scripts": { + "all-tests": "npm run generate-fixtures && npm run unit-tests && npm run grammar-tests && npm run regression-tests", + "analyze-coverage": "istanbul cover test/unit-tests.js", + "appveyor": "npm run all-tests && npm run browser-tests && npm run dynamic-analysis", + "benchmark": "node test/benchmarks.js", + "benchmark-quick": "node test/benchmarks.js quick", + "browser-tests": "npm run generate-fixtures && cd test && karma start --single-run", + "check-coverage": "istanbul check-coverage --statement 100 --branch 100 --function 100", + "check-version": "node test/check-version.js", + "circleci": "npm test && npm run codecov && npm run downstream", + "codecov": "istanbul report cobertura && codecov < ./coverage/cobertura-coverage.xml", + "complexity": "node test/check-complexity.js", + "downstream": "node test/downstream.js", + "droneio": "npm test && npm run saucelabs-evergreen && npm run saucelabs-ie && npm run saucelabs-safari", + "dynamic-analysis": "npm run analyze-coverage && npm run check-coverage", + "eslint": "node node_modules/eslint/bin/eslint.js -c .lintrc esprima.js", + "generate-fixtures": "node tools/generate-fixtures.js", + "generate-regex": "node tools/generate-identifier-regex.js", + "grammar-tests": "node test/grammar-tests.js", + "jscs": "jscs -p crockford esprima.js && jscs -p crockford test/*.js", + "profile": "node --prof test/profile.js && mv isolate*.log v8.log && node-tick-processor", + "regression-tests": "node test/regression-tests.js", + "saucelabs-evergreen": "cd test && karma start saucelabs-evergreen.conf.js", + "saucelabs-ie": "cd test && karma start saucelabs-ie.conf.js", + "saucelabs-safari": "cd test && karma start saucelabs-safari.conf.js", + "static-analysis": "npm run check-version && npm run jscs && npm run eslint && npm run complexity", + "test": "npm run all-tests && npm run static-analysis && npm run dynamic-analysis", + "travis": "npm test", + "unit-tests": "node test/unit-tests.js" + }, + "version": "2.7.3" +} diff --git a/hm_sunwell/node_modules/estraverse/.editorconfig b/hm_sunwell/node_modules/estraverse/.editorconfig new file mode 100644 index 0000000..1d4fc22 --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/.editorconfig @@ -0,0 +1,10 @@ +# top-most EditorConfig file +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 +tab_width = 4 diff --git a/hm_sunwell/node_modules/estraverse/.jshintrc b/hm_sunwell/node_modules/estraverse/.jshintrc new file mode 100644 index 0000000..f642dae --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/.jshintrc @@ -0,0 +1,16 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "eqnull": true, + "latedef": true, + "noarg": true, + "noempty": true, + "quotmark": "single", + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + + "node": true +} diff --git a/hm_sunwell/node_modules/estraverse/LICENSE.BSD b/hm_sunwell/node_modules/estraverse/LICENSE.BSD new file mode 100644 index 0000000..3e580c3 --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/LICENSE.BSD @@ -0,0 +1,19 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/estraverse/README.md b/hm_sunwell/node_modules/estraverse/README.md new file mode 100644 index 0000000..4242c51 --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/README.md @@ -0,0 +1,124 @@ +### Estraverse [![Build Status](https://secure.travis-ci.org/estools/estraverse.png)](http://travis-ci.org/estools/estraverse) + +Estraverse ([estraverse](http://github.com/estools/estraverse)) is +[ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm) +traversal functions from [esmangle project](http://github.com/estools/esmangle). + +### Documentation + +You can find usage docs at [wiki page](https://github.com/estools/estraverse/wiki/Usage). + +### Example Usage + +The following code will output all variables declared at the root of a file. + +```javascript +estraverse.traverse(ast, { + enter: function (node, parent) { + if (node.type == 'FunctionExpression' || node.type == 'FunctionDeclaration') + return estraverse.VisitorOption.Skip; + }, + leave: function (node, parent) { + if (node.type == 'VariableDeclarator') + console.log(node.id.name); + } +}); +``` + +We can use `this.skip`, `this.remove` and `this.break` functions instead of using Skip, Remove and Break. + +```javascript +estraverse.traverse(ast, { + enter: function (node) { + this.break(); + } +}); +``` + +And estraverse provides `estraverse.replace` function. When returning node from `enter`/`leave`, current node is replaced with it. + +```javascript +result = estraverse.replace(tree, { + enter: function (node) { + // Replace it with replaced. + if (node.type === 'Literal') + return replaced; + } +}); +``` + +By passing `visitor.keys` mapping, we can extend estraverse traversing functionality. + +```javascript +// This tree contains a user-defined `TestExpression` node. +var tree = { + type: 'TestExpression', + + // This 'argument' is the property containing the other **node**. + argument: { + type: 'Literal', + value: 20 + }, + + // This 'extended' is the property not containing the other **node**. + extended: true +}; +estraverse.traverse(tree, { + enter: function (node) { }, + + // Extending the exising traversing rules. + keys: { + // TargetNodeName: [ 'keys', 'containing', 'the', 'other', '**node**' ] + TestExpression: ['argument'] + } +}); +``` + +By passing `visitor.fallback` option, we can control the behavior when encountering unknown nodes. +```javascript +// This tree contains a user-defined `TestExpression` node. +var tree = { + type: 'TestExpression', + + // This 'argument' is the property containing the other **node**. + argument: { + type: 'Literal', + value: 20 + }, + + // This 'extended' is the property not containing the other **node**. + extended: true +}; +estraverse.traverse(tree, { + enter: function (node) { }, + + // Iterating the child **nodes** of unknown nodes. + fallback: 'iteration' +}); +``` + +### License + +Copyright (C) 2012-2013 [Yusuke Suzuki](http://github.com/Constellation) + (twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/estraverse/estraverse.js b/hm_sunwell/node_modules/estraverse/estraverse.js new file mode 100644 index 0000000..99bbb8c --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/estraverse.js @@ -0,0 +1,845 @@ +/* + Copyright (C) 2012-2013 Yusuke Suzuki + Copyright (C) 2012 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*jslint vars:false, bitwise:true*/ +/*jshint indent:4*/ +/*global exports:true, define:true*/ +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // and plain browser loading, + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.estraverse = {})); + } +}(this, function clone(exports) { + 'use strict'; + + var Syntax, + isArray, + VisitorOption, + VisitorKeys, + objectCreate, + objectKeys, + BREAK, + SKIP, + REMOVE; + + function ignoreJSHintError() { } + + isArray = Array.isArray; + if (!isArray) { + isArray = function isArray(array) { + return Object.prototype.toString.call(array) === '[object Array]'; + }; + } + + function deepCopy(obj) { + var ret = {}, key, val; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + val = obj[key]; + if (typeof val === 'object' && val !== null) { + ret[key] = deepCopy(val); + } else { + ret[key] = val; + } + } + } + return ret; + } + + function shallowCopy(obj) { + var ret = {}, key; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + ignoreJSHintError(shallowCopy); + + // based on LLVM libc++ upper_bound / lower_bound + // MIT License + + function upperBound(array, func) { + var diff, len, i, current; + + len = array.length; + i = 0; + + while (len) { + diff = len >>> 1; + current = i + diff; + if (func(array[current])) { + len = diff; + } else { + i = current + 1; + len -= diff + 1; + } + } + return i; + } + + function lowerBound(array, func) { + var diff, len, i, current; + + len = array.length; + i = 0; + + while (len) { + diff = len >>> 1; + current = i + diff; + if (func(array[current])) { + i = current + 1; + len -= diff + 1; + } else { + len = diff; + } + } + return i; + } + ignoreJSHintError(lowerBound); + + objectCreate = Object.create || (function () { + function F() { } + + return function (o) { + F.prototype = o; + return new F(); + }; + })(); + + objectKeys = Object.keys || function (o) { + var keys = [], key; + for (key in o) { + keys.push(key); + } + return keys; + }; + + function extend(to, from) { + var keys = objectKeys(from), key, i, len; + for (i = 0, len = keys.length; i < len; i += 1) { + key = keys[i]; + to[key] = from[key]; + } + return to; + } + + Syntax = { + AssignmentExpression: 'AssignmentExpression', + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + AwaitExpression: 'AwaitExpression', // CAUTION: It's deferred to ES7. + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ComprehensionBlock: 'ComprehensionBlock', // CAUTION: It's deferred to ES7. + ComprehensionExpression: 'ComprehensionExpression', // CAUTION: It's deferred to ES7. + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DebuggerStatement: 'DebuggerStatement', + DirectiveStatement: 'DirectiveStatement', + DoWhileStatement: 'DoWhileStatement', + EmptyStatement: 'EmptyStatement', + ExportBatchSpecifier: 'ExportBatchSpecifier', + ExportDeclaration: 'ExportDeclaration', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForInStatement: 'ForInStatement', + ForOfStatement: 'ForOfStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + GeneratorExpression: 'GeneratorExpression', // CAUTION: It's deferred to ES7. + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', + ImportSpecifier: 'ImportSpecifier', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MethodDefinition: 'MethodDefinition', + ModuleSpecifier: 'ModuleSpecifier', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + SwitchStatement: 'SwitchStatement', + SwitchCase: 'SwitchCase', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + YieldExpression: 'YieldExpression' + }; + + VisitorKeys = { + AssignmentExpression: ['left', 'right'], + ArrayExpression: ['elements'], + ArrayPattern: ['elements'], + ArrowFunctionExpression: ['params', 'defaults', 'rest', 'body'], + AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7. + BlockStatement: ['body'], + BinaryExpression: ['left', 'right'], + BreakStatement: ['label'], + CallExpression: ['callee', 'arguments'], + CatchClause: ['param', 'body'], + ClassBody: ['body'], + ClassDeclaration: ['id', 'body', 'superClass'], + ClassExpression: ['id', 'body', 'superClass'], + ComprehensionBlock: ['left', 'right'], // CAUTION: It's deferred to ES7. + ComprehensionExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7. + ConditionalExpression: ['test', 'consequent', 'alternate'], + ContinueStatement: ['label'], + DebuggerStatement: [], + DirectiveStatement: [], + DoWhileStatement: ['body', 'test'], + EmptyStatement: [], + ExportBatchSpecifier: [], + ExportDeclaration: ['declaration', 'specifiers', 'source'], + ExportSpecifier: ['id', 'name'], + ExpressionStatement: ['expression'], + ForStatement: ['init', 'test', 'update', 'body'], + ForInStatement: ['left', 'right', 'body'], + ForOfStatement: ['left', 'right', 'body'], + FunctionDeclaration: ['id', 'params', 'defaults', 'rest', 'body'], + FunctionExpression: ['id', 'params', 'defaults', 'rest', 'body'], + GeneratorExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7. + Identifier: [], + IfStatement: ['test', 'consequent', 'alternate'], + ImportDeclaration: ['specifiers', 'source'], + ImportDefaultSpecifier: ['id'], + ImportNamespaceSpecifier: ['id'], + ImportSpecifier: ['id', 'name'], + Literal: [], + LabeledStatement: ['label', 'body'], + LogicalExpression: ['left', 'right'], + MemberExpression: ['object', 'property'], + MethodDefinition: ['key', 'value'], + ModuleSpecifier: [], + NewExpression: ['callee', 'arguments'], + ObjectExpression: ['properties'], + ObjectPattern: ['properties'], + Program: ['body'], + Property: ['key', 'value'], + ReturnStatement: ['argument'], + SequenceExpression: ['expressions'], + SpreadElement: ['argument'], + SwitchStatement: ['discriminant', 'cases'], + SwitchCase: ['test', 'consequent'], + TaggedTemplateExpression: ['tag', 'quasi'], + TemplateElement: [], + TemplateLiteral: ['quasis', 'expressions'], + ThisExpression: [], + ThrowStatement: ['argument'], + TryStatement: ['block', 'handlers', 'handler', 'guardedHandlers', 'finalizer'], + UnaryExpression: ['argument'], + UpdateExpression: ['argument'], + VariableDeclaration: ['declarations'], + VariableDeclarator: ['id', 'init'], + WhileStatement: ['test', 'body'], + WithStatement: ['object', 'body'], + YieldExpression: ['argument'] + }; + + // unique id + BREAK = {}; + SKIP = {}; + REMOVE = {}; + + VisitorOption = { + Break: BREAK, + Skip: SKIP, + Remove: REMOVE + }; + + function Reference(parent, key) { + this.parent = parent; + this.key = key; + } + + Reference.prototype.replace = function replace(node) { + this.parent[this.key] = node; + }; + + Reference.prototype.remove = function remove() { + if (isArray(this.parent)) { + this.parent.splice(this.key, 1); + return true; + } else { + this.replace(null); + return false; + } + }; + + function Element(node, path, wrap, ref) { + this.node = node; + this.path = path; + this.wrap = wrap; + this.ref = ref; + } + + function Controller() { } + + // API: + // return property path array from root to current node + Controller.prototype.path = function path() { + var i, iz, j, jz, result, element; + + function addToPath(result, path) { + if (isArray(path)) { + for (j = 0, jz = path.length; j < jz; ++j) { + result.push(path[j]); + } + } else { + result.push(path); + } + } + + // root node + if (!this.__current.path) { + return null; + } + + // first node is sentinel, second node is root element + result = []; + for (i = 2, iz = this.__leavelist.length; i < iz; ++i) { + element = this.__leavelist[i]; + addToPath(result, element.path); + } + addToPath(result, this.__current.path); + return result; + }; + + // API: + // return type of current node + Controller.prototype.type = function () { + var node = this.current(); + return node.type || this.__current.wrap; + }; + + // API: + // return array of parent elements + Controller.prototype.parents = function parents() { + var i, iz, result; + + // first node is sentinel + result = []; + for (i = 1, iz = this.__leavelist.length; i < iz; ++i) { + result.push(this.__leavelist[i].node); + } + + return result; + }; + + // API: + // return current node + Controller.prototype.current = function current() { + return this.__current.node; + }; + + Controller.prototype.__execute = function __execute(callback, element) { + var previous, result; + + result = undefined; + + previous = this.__current; + this.__current = element; + this.__state = null; + if (callback) { + result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node); + } + this.__current = previous; + + return result; + }; + + // API: + // notify control skip / break + Controller.prototype.notify = function notify(flag) { + this.__state = flag; + }; + + // API: + // skip child nodes of current node + Controller.prototype.skip = function () { + this.notify(SKIP); + }; + + // API: + // break traversals + Controller.prototype['break'] = function () { + this.notify(BREAK); + }; + + // API: + // remove node + Controller.prototype.remove = function () { + this.notify(REMOVE); + }; + + Controller.prototype.__initialize = function(root, visitor) { + this.visitor = visitor; + this.root = root; + this.__worklist = []; + this.__leavelist = []; + this.__current = null; + this.__state = null; + this.__fallback = visitor.fallback === 'iteration'; + this.__keys = VisitorKeys; + if (visitor.keys) { + this.__keys = extend(objectCreate(this.__keys), visitor.keys); + } + }; + + function isNode(node) { + if (node == null) { + return false; + } + return typeof node === 'object' && typeof node.type === 'string'; + } + + function isProperty(nodeType, key) { + return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key; + } + + Controller.prototype.traverse = function traverse(root, visitor) { + var worklist, + leavelist, + element, + node, + nodeType, + ret, + key, + current, + current2, + candidates, + candidate, + sentinel; + + this.__initialize(root, visitor); + + sentinel = {}; + + // reference + worklist = this.__worklist; + leavelist = this.__leavelist; + + // initialize + worklist.push(new Element(root, null, null, null)); + leavelist.push(new Element(null, null, null, null)); + + while (worklist.length) { + element = worklist.pop(); + + if (element === sentinel) { + element = leavelist.pop(); + + ret = this.__execute(visitor.leave, element); + + if (this.__state === BREAK || ret === BREAK) { + return; + } + continue; + } + + if (element.node) { + + ret = this.__execute(visitor.enter, element); + + if (this.__state === BREAK || ret === BREAK) { + return; + } + + worklist.push(sentinel); + leavelist.push(element); + + if (this.__state === SKIP || ret === SKIP) { + continue; + } + + node = element.node; + nodeType = element.wrap || node.type; + candidates = this.__keys[nodeType]; + if (!candidates) { + if (this.__fallback) { + candidates = objectKeys(node); + } else { + throw new Error('Unknown node type ' + nodeType + '.'); + } + } + + current = candidates.length; + while ((current -= 1) >= 0) { + key = candidates[current]; + candidate = node[key]; + if (!candidate) { + continue; + } + + if (isArray(candidate)) { + current2 = candidate.length; + while ((current2 -= 1) >= 0) { + if (!candidate[current2]) { + continue; + } + if (isProperty(nodeType, candidates[current])) { + element = new Element(candidate[current2], [key, current2], 'Property', null); + } else if (isNode(candidate[current2])) { + element = new Element(candidate[current2], [key, current2], null, null); + } else { + continue; + } + worklist.push(element); + } + } else if (isNode(candidate)) { + worklist.push(new Element(candidate, key, null, null)); + } + } + } + } + }; + + Controller.prototype.replace = function replace(root, visitor) { + function removeElem(element) { + var i, + key, + nextElem, + parent; + + if (element.ref.remove()) { + // When the reference is an element of an array. + key = element.ref.key; + parent = element.ref.parent; + + // If removed from array, then decrease following items' keys. + i = worklist.length; + while (i--) { + nextElem = worklist[i]; + if (nextElem.ref && nextElem.ref.parent === parent) { + if (nextElem.ref.key < key) { + break; + } + --nextElem.ref.key; + } + } + } + } + + var worklist, + leavelist, + node, + nodeType, + target, + element, + current, + current2, + candidates, + candidate, + sentinel, + outer, + key; + + this.__initialize(root, visitor); + + sentinel = {}; + + // reference + worklist = this.__worklist; + leavelist = this.__leavelist; + + // initialize + outer = { + root: root + }; + element = new Element(root, null, null, new Reference(outer, 'root')); + worklist.push(element); + leavelist.push(element); + + while (worklist.length) { + element = worklist.pop(); + + if (element === sentinel) { + element = leavelist.pop(); + + target = this.__execute(visitor.leave, element); + + // node may be replaced with null, + // so distinguish between undefined and null in this place + if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) { + // replace + element.ref.replace(target); + } + + if (this.__state === REMOVE || target === REMOVE) { + removeElem(element); + } + + if (this.__state === BREAK || target === BREAK) { + return outer.root; + } + continue; + } + + target = this.__execute(visitor.enter, element); + + // node may be replaced with null, + // so distinguish between undefined and null in this place + if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) { + // replace + element.ref.replace(target); + element.node = target; + } + + if (this.__state === REMOVE || target === REMOVE) { + removeElem(element); + element.node = null; + } + + if (this.__state === BREAK || target === BREAK) { + return outer.root; + } + + // node may be null + node = element.node; + if (!node) { + continue; + } + + worklist.push(sentinel); + leavelist.push(element); + + if (this.__state === SKIP || target === SKIP) { + continue; + } + + nodeType = element.wrap || node.type; + candidates = this.__keys[nodeType]; + if (!candidates) { + if (this.__fallback) { + candidates = objectKeys(node); + } else { + throw new Error('Unknown node type ' + nodeType + '.'); + } + } + + current = candidates.length; + while ((current -= 1) >= 0) { + key = candidates[current]; + candidate = node[key]; + if (!candidate) { + continue; + } + + if (isArray(candidate)) { + current2 = candidate.length; + while ((current2 -= 1) >= 0) { + if (!candidate[current2]) { + continue; + } + if (isProperty(nodeType, candidates[current])) { + element = new Element(candidate[current2], [key, current2], 'Property', new Reference(candidate, current2)); + } else if (isNode(candidate[current2])) { + element = new Element(candidate[current2], [key, current2], null, new Reference(candidate, current2)); + } else { + continue; + } + worklist.push(element); + } + } else if (isNode(candidate)) { + worklist.push(new Element(candidate, key, null, new Reference(node, key))); + } + } + } + + return outer.root; + }; + + function traverse(root, visitor) { + var controller = new Controller(); + return controller.traverse(root, visitor); + } + + function replace(root, visitor) { + var controller = new Controller(); + return controller.replace(root, visitor); + } + + function extendCommentRange(comment, tokens) { + var target; + + target = upperBound(tokens, function search(token) { + return token.range[0] > comment.range[0]; + }); + + comment.extendedRange = [comment.range[0], comment.range[1]]; + + if (target !== tokens.length) { + comment.extendedRange[1] = tokens[target].range[0]; + } + + target -= 1; + if (target >= 0) { + comment.extendedRange[0] = tokens[target].range[1]; + } + + return comment; + } + + function attachComments(tree, providedComments, tokens) { + // At first, we should calculate extended comment ranges. + var comments = [], comment, len, i, cursor; + + if (!tree.range) { + throw new Error('attachComments needs range information'); + } + + // tokens array is empty, we attach comments to tree as 'leadingComments' + if (!tokens.length) { + if (providedComments.length) { + for (i = 0, len = providedComments.length; i < len; i += 1) { + comment = deepCopy(providedComments[i]); + comment.extendedRange = [0, tree.range[0]]; + comments.push(comment); + } + tree.leadingComments = comments; + } + return tree; + } + + for (i = 0, len = providedComments.length; i < len; i += 1) { + comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens)); + } + + // This is based on John Freeman's implementation. + cursor = 0; + traverse(tree, { + enter: function (node) { + var comment; + + while (cursor < comments.length) { + comment = comments[cursor]; + if (comment.extendedRange[1] > node.range[0]) { + break; + } + + if (comment.extendedRange[1] === node.range[0]) { + if (!node.leadingComments) { + node.leadingComments = []; + } + node.leadingComments.push(comment); + comments.splice(cursor, 1); + } else { + cursor += 1; + } + } + + // already out of owned node + if (cursor === comments.length) { + return VisitorOption.Break; + } + + if (comments[cursor].extendedRange[0] > node.range[1]) { + return VisitorOption.Skip; + } + } + }); + + cursor = 0; + traverse(tree, { + leave: function (node) { + var comment; + + while (cursor < comments.length) { + comment = comments[cursor]; + if (node.range[1] < comment.extendedRange[0]) { + break; + } + + if (node.range[1] === comment.extendedRange[0]) { + if (!node.trailingComments) { + node.trailingComments = []; + } + node.trailingComments.push(comment); + comments.splice(cursor, 1); + } else { + cursor += 1; + } + } + + // already out of owned node + if (cursor === comments.length) { + return VisitorOption.Break; + } + + if (comments[cursor].extendedRange[0] > node.range[1]) { + return VisitorOption.Skip; + } + } + }); + + return tree; + } + + exports.version = '1.8.1-dev'; + exports.Syntax = Syntax; + exports.traverse = traverse; + exports.replace = replace; + exports.attachComments = attachComments; + exports.VisitorKeys = VisitorKeys; + exports.VisitorOption = VisitorOption; + exports.Controller = Controller; + exports.cloneEnvironment = function () { return clone({}); }; + + return exports; +})); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/estraverse/gulpfile.js b/hm_sunwell/node_modules/estraverse/gulpfile.js new file mode 100644 index 0000000..8772bbc --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/gulpfile.js @@ -0,0 +1,70 @@ +/* + Copyright (C) 2014 Yusuke Suzuki + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +'use strict'; + +var gulp = require('gulp'), + git = require('gulp-git'), + bump = require('gulp-bump'), + filter = require('gulp-filter'), + tagVersion = require('gulp-tag-version'); + +var TEST = [ 'test/*.js' ]; +var POWERED = [ 'powered-test/*.js' ]; +var SOURCE = [ 'src/**/*.js' ]; + +/** + * Bumping version number and tagging the repository with it. + * Please read http://semver.org/ + * + * You can use the commands + * + * gulp patch # makes v0.1.0 -> v0.1.1 + * gulp feature # makes v0.1.1 -> v0.2.0 + * gulp release # makes v0.2.1 -> v1.0.0 + * + * To bump the version numbers accordingly after you did a patch, + * introduced a feature or made a backwards-incompatible release. + */ + +function inc(importance) { + // get all the files to bump version in + return gulp.src(['./package.json']) + // bump the version number in those files + .pipe(bump({type: importance})) + // save it back to filesystem + .pipe(gulp.dest('./')) + // commit the changed version number + .pipe(git.commit('Bumps package version')) + // read only one file to get the version number + .pipe(filter('package.json')) + // **tag it in the repository** + .pipe(tagVersion({ + prefix: '' + })); +} + +gulp.task('patch', [ ], function () { return inc('patch'); }) +gulp.task('minor', [ ], function () { return inc('minor'); }) +gulp.task('major', [ ], function () { return inc('major'); }) diff --git a/hm_sunwell/node_modules/estraverse/package.json b/hm_sunwell/node_modules/estraverse/package.json new file mode 100644 index 0000000..df6a7aa --- /dev/null +++ b/hm_sunwell/node_modules/estraverse/package.json @@ -0,0 +1,87 @@ +{ + "_args": [ + [ + "estraverse@^1.9.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/escodegen" + ] + ], + "_from": "estraverse@>=1.9.1 <2.0.0", + "_id": "estraverse@1.9.3", + "_inCache": true, + "_installable": true, + "_location": "/estraverse", + "_npmUser": { + "email": "utatane.tea@gmail.com", + "name": "constellation" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "estraverse", + "raw": "estraverse@^1.9.1", + "rawSpec": "^1.9.1", + "scope": null, + "spec": ">=1.9.1 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/escodegen" + ], + "_resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "_shasum": "af67f2dc922582415950926091a4005d29c9bb44", + "_shrinkwrap": null, + "_spec": "estraverse@^1.9.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/escodegen", + "bugs": { + "url": "https://github.com/estools/estraverse/issues" + }, + "dependencies": {}, + "description": "ECMAScript JS AST traversal functions", + "devDependencies": { + "chai": "^2.1.1", + "coffee-script": "^1.8.0", + "gulp": "^3.8.10", + "gulp-bump": "^0.2.2", + "gulp-filter": "^2.0.0", + "gulp-git": "^1.0.1", + "gulp-tag-version": "^1.2.1", + "jshint": "^2.5.6", + "mocha": "^2.1.0" + }, + "directories": {}, + "dist": { + "shasum": "af67f2dc922582415950926091a4005d29c9bb44", + "tarball": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "gitHead": "9c249de6b2ea08655d3c68bfc30b5d7d81dc8703", + "homepage": "https://github.com/estools/estraverse", + "licenses": [ + { + "type": "BSD", + "url": "http://github.com/estools/estraverse/raw/master/LICENSE.BSD" + } + ], + "main": "estraverse.js", + "maintainers": [ + { + "name": "constellation", + "email": "utatane.tea@gmail.com" + } + ], + "name": "estraverse", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/estools/estraverse.git" + }, + "scripts": { + "lint": "jshint estraverse.js", + "test": "npm run-script lint && npm run-script unit-test", + "unit-test": "mocha --compilers coffee:coffee-script/register" + }, + "version": "1.9.3" +} diff --git a/hm_sunwell/node_modules/esutils/LICENSE.BSD b/hm_sunwell/node_modules/esutils/LICENSE.BSD new file mode 100644 index 0000000..3e580c3 --- /dev/null +++ b/hm_sunwell/node_modules/esutils/LICENSE.BSD @@ -0,0 +1,19 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/esutils/README.md b/hm_sunwell/node_modules/esutils/README.md new file mode 100644 index 0000000..610d8bd --- /dev/null +++ b/hm_sunwell/node_modules/esutils/README.md @@ -0,0 +1,169 @@ +### esutils [![Build Status](https://secure.travis-ci.org/estools/esutils.svg)](http://travis-ci.org/estools/esutils) +esutils ([esutils](http://github.com/estools/esutils)) is +utility box for ECMAScript language tools. + +### API + +### ast + +#### ast.isExpression(node) + +Returns true if `node` is an Expression as defined in ECMA262 edition 5.1 section +[11](https://es5.github.io/#x11). + +#### ast.isStatement(node) + +Returns true if `node` is a Statement as defined in ECMA262 edition 5.1 section +[12](https://es5.github.io/#x12). + +#### ast.isIterationStatement(node) + +Returns true if `node` is an IterationStatement as defined in ECMA262 edition +5.1 section [12.6](https://es5.github.io/#x12.6). + +#### ast.isSourceElement(node) + +Returns true if `node` is a SourceElement as defined in ECMA262 edition 5.1 +section [14](https://es5.github.io/#x14). + +#### ast.trailingStatement(node) + +Returns `Statement?` if `node` has trailing `Statement`. +```js +if (cond) + consequent; +``` +When taking this `IfStatement`, returns `consequent;` statement. + +#### ast.isProblematicIfStatement(node) + +Returns true if `node` is a problematic IfStatement. If `node` is a problematic `IfStatement`, `node` cannot be represented as an one on one JavaScript code. +```js +{ + type: 'IfStatement', + consequent: { + type: 'WithStatement', + body: { + type: 'IfStatement', + consequent: {type: 'EmptyStatement'} + } + }, + alternate: {type: 'EmptyStatement'} +} +``` +The above node cannot be represented as a JavaScript code, since the top level `else` alternate belongs to an inner `IfStatement`. + + +### code + +#### code.isDecimalDigit(code) + +Return true if provided code is decimal digit. + +#### code.isHexDigit(code) + +Return true if provided code is hexadecimal digit. + +#### code.isOctalDigit(code) + +Return true if provided code is octal digit. + +#### code.isWhiteSpace(code) + +Return true if provided code is white space. White space characters are formally defined in ECMA262. + +#### code.isLineTerminator(code) + +Return true if provided code is line terminator. Line terminator characters are formally defined in ECMA262. + +#### code.isIdentifierStart(code) + +Return true if provided code can be the first character of ECMA262 Identifier. They are formally defined in ECMA262. + +#### code.isIdentifierPart(code) + +Return true if provided code can be the trailing character of ECMA262 Identifier. They are formally defined in ECMA262. + +### keyword + +#### keyword.isKeywordES5(id, strict) + +Returns `true` if provided identifier string is a Keyword or Future Reserved Word +in ECMA262 edition 5.1. They are formally defined in ECMA262 sections +[7.6.1.1](http://es5.github.io/#x7.6.1.1) and [7.6.1.2](http://es5.github.io/#x7.6.1.2), +respectively. If the `strict` flag is truthy, this function additionally checks whether +`id` is a Keyword or Future Reserved Word under strict mode. + +#### keyword.isKeywordES6(id, strict) + +Returns `true` if provided identifier string is a Keyword or Future Reserved Word +in ECMA262 edition 6. They are formally defined in ECMA262 sections +[11.6.2.1](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-keywords) and +[11.6.2.2](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-future-reserved-words), +respectively. If the `strict` flag is truthy, this function additionally checks whether +`id` is a Keyword or Future Reserved Word under strict mode. + +#### keyword.isReservedWordES5(id, strict) + +Returns `true` if provided identifier string is a Reserved Word in ECMA262 edition 5.1. +They are formally defined in ECMA262 section [7.6.1](http://es5.github.io/#x7.6.1). +If the `strict` flag is truthy, this function additionally checks whether `id` +is a Reserved Word under strict mode. + +#### keyword.isReservedWordES6(id, strict) + +Returns `true` if provided identifier string is a Reserved Word in ECMA262 edition 6. +They are formally defined in ECMA262 section [11.6.2](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-reserved-words). +If the `strict` flag is truthy, this function additionally checks whether `id` +is a Reserved Word under strict mode. + +#### keyword.isRestrictedWord(id) + +Returns `true` if provided identifier string is one of `eval` or `arguments`. +They are restricted in strict mode code throughout ECMA262 edition 5.1 and +in ECMA262 edition 6 section [12.1.1](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-identifiers-static-semantics-early-errors). + +#### keyword.isIdentifierName(id) + +Return true if provided identifier string is an IdentifierName as specified in +ECMA262 edition 5.1 section [7.6](https://es5.github.io/#x7.6). + +#### keyword.isIdentifierES5(id, strict) + +Return true if provided identifier string is an Identifier as specified in +ECMA262 edition 5.1 section [7.6](https://es5.github.io/#x7.6). If the `strict` +flag is truthy, this function additionally checks whether `id` is an Identifier +under strict mode. + +#### keyword.isIdentifierES6(id, strict) + +Return true if provided identifier string is an Identifier as specified in +ECMA262 edition 6 section [12.1](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-identifiers). +If the `strict` flag is truthy, this function additionally checks whether `id` +is an Identifier under strict mode. + +### License + +Copyright (C) 2013 [Yusuke Suzuki](http://github.com/Constellation) + (twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hm_sunwell/node_modules/esutils/lib/ast.js b/hm_sunwell/node_modules/esutils/lib/ast.js new file mode 100644 index 0000000..8faadae --- /dev/null +++ b/hm_sunwell/node_modules/esutils/lib/ast.js @@ -0,0 +1,144 @@ +/* + Copyright (C) 2013 Yusuke Suzuki + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +(function () { + 'use strict'; + + function isExpression(node) { + if (node == null) { return false; } + switch (node.type) { + case 'ArrayExpression': + case 'AssignmentExpression': + case 'BinaryExpression': + case 'CallExpression': + case 'ConditionalExpression': + case 'FunctionExpression': + case 'Identifier': + case 'Literal': + case 'LogicalExpression': + case 'MemberExpression': + case 'NewExpression': + case 'ObjectExpression': + case 'SequenceExpression': + case 'ThisExpression': + case 'UnaryExpression': + case 'UpdateExpression': + return true; + } + return false; + } + + function isIterationStatement(node) { + if (node == null) { return false; } + switch (node.type) { + case 'DoWhileStatement': + case 'ForInStatement': + case 'ForStatement': + case 'WhileStatement': + return true; + } + return false; + } + + function isStatement(node) { + if (node == null) { return false; } + switch (node.type) { + case 'BlockStatement': + case 'BreakStatement': + case 'ContinueStatement': + case 'DebuggerStatement': + case 'DoWhileStatement': + case 'EmptyStatement': + case 'ExpressionStatement': + case 'ForInStatement': + case 'ForStatement': + case 'IfStatement': + case 'LabeledStatement': + case 'ReturnStatement': + case 'SwitchStatement': + case 'ThrowStatement': + case 'TryStatement': + case 'VariableDeclaration': + case 'WhileStatement': + case 'WithStatement': + return true; + } + return false; + } + + function isSourceElement(node) { + return isStatement(node) || node != null && node.type === 'FunctionDeclaration'; + } + + function trailingStatement(node) { + switch (node.type) { + case 'IfStatement': + if (node.alternate != null) { + return node.alternate; + } + return node.consequent; + + case 'LabeledStatement': + case 'ForStatement': + case 'ForInStatement': + case 'WhileStatement': + case 'WithStatement': + return node.body; + } + return null; + } + + function isProblematicIfStatement(node) { + var current; + + if (node.type !== 'IfStatement') { + return false; + } + if (node.alternate == null) { + return false; + } + current = node.consequent; + do { + if (current.type === 'IfStatement') { + if (current.alternate == null) { + return true; + } + } + current = trailingStatement(current); + } while (current); + + return false; + } + + module.exports = { + isExpression: isExpression, + isStatement: isStatement, + isIterationStatement: isIterationStatement, + isSourceElement: isSourceElement, + isProblematicIfStatement: isProblematicIfStatement, + + trailingStatement: trailingStatement + }; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/esutils/lib/code.js b/hm_sunwell/node_modules/esutils/lib/code.js new file mode 100644 index 0000000..2a7c19d --- /dev/null +++ b/hm_sunwell/node_modules/esutils/lib/code.js @@ -0,0 +1,135 @@ +/* + Copyright (C) 2013-2014 Yusuke Suzuki + Copyright (C) 2014 Ivan Nikulin + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +(function () { + 'use strict'; + + var ES6Regex, ES5Regex, NON_ASCII_WHITESPACES, IDENTIFIER_START, IDENTIFIER_PART, ch; + + // See `tools/generate-identifier-regex.js`. + ES5Regex = { + // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/, + // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/ + }; + + ES6Regex = { + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/, + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ + }; + + function isDecimalDigit(ch) { + return 0x30 <= ch && ch <= 0x39; // 0..9 + } + + function isHexDigit(ch) { + return 0x30 <= ch && ch <= 0x39 || // 0..9 + 0x61 <= ch && ch <= 0x66 || // a..f + 0x41 <= ch && ch <= 0x46; // A..F + } + + function isOctalDigit(ch) { + return ch >= 0x30 && ch <= 0x37; // 0..7 + } + + // 7.2 White Space + + NON_ASCII_WHITESPACES = [ + 0x1680, 0x180E, + 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, + 0x202F, 0x205F, + 0x3000, + 0xFEFF + ]; + + function isWhiteSpace(ch) { + return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 || + ch >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0; + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029; + } + + // 7.6 Identifier Names and Identifiers + + function fromCodePoint(cp) { + if (cp <= 0xFFFF) { return String.fromCharCode(cp); } + var cu1 = String.fromCharCode(Math.floor((cp - 0x10000) / 0x400) + 0xD800); + var cu2 = String.fromCharCode(((cp - 0x10000) % 0x400) + 0xDC00); + return cu1 + cu2; + } + + IDENTIFIER_START = new Array(0x80); + for(ch = 0; ch < 0x80; ++ch) { + IDENTIFIER_START[ch] = + ch >= 0x61 && ch <= 0x7A || // a..z + ch >= 0x41 && ch <= 0x5A || // A..Z + ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore) + } + + IDENTIFIER_PART = new Array(0x80); + for(ch = 0; ch < 0x80; ++ch) { + IDENTIFIER_PART[ch] = + ch >= 0x61 && ch <= 0x7A || // a..z + ch >= 0x41 && ch <= 0x5A || // A..Z + ch >= 0x30 && ch <= 0x39 || // 0..9 + ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore) + } + + function isIdentifierStartES5(ch) { + return ch < 0x80 ? IDENTIFIER_START[ch] : ES5Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)); + } + + function isIdentifierPartES5(ch) { + return ch < 0x80 ? IDENTIFIER_PART[ch] : ES5Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)); + } + + function isIdentifierStartES6(ch) { + return ch < 0x80 ? IDENTIFIER_START[ch] : ES6Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)); + } + + function isIdentifierPartES6(ch) { + return ch < 0x80 ? IDENTIFIER_PART[ch] : ES6Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)); + } + + module.exports = { + isDecimalDigit: isDecimalDigit, + isHexDigit: isHexDigit, + isOctalDigit: isOctalDigit, + isWhiteSpace: isWhiteSpace, + isLineTerminator: isLineTerminator, + isIdentifierStartES5: isIdentifierStartES5, + isIdentifierPartES5: isIdentifierPartES5, + isIdentifierStartES6: isIdentifierStartES6, + isIdentifierPartES6: isIdentifierPartES6 + }; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/esutils/lib/keyword.js b/hm_sunwell/node_modules/esutils/lib/keyword.js new file mode 100644 index 0000000..13c8c6a --- /dev/null +++ b/hm_sunwell/node_modules/esutils/lib/keyword.js @@ -0,0 +1,165 @@ +/* + Copyright (C) 2013 Yusuke Suzuki + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +(function () { + 'use strict'; + + var code = require('./code'); + + function isStrictModeReservedWordES6(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'let': + return true; + default: + return false; + } + } + + function isKeywordES5(id, strict) { + // yield should not be treated as keyword under non-strict mode. + if (!strict && id === 'yield') { + return false; + } + return isKeywordES6(id, strict); + } + + function isKeywordES6(id, strict) { + if (strict && isStrictModeReservedWordES6(id)) { + return true; + } + + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + function isReservedWordES5(id, strict) { + return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict); + } + + function isReservedWordES6(id, strict) { + return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict); + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + function isIdentifierNameES5(id) { + var i, iz, ch; + + if (id.length === 0) { return false; } + + ch = id.charCodeAt(0); + if (!code.isIdentifierStartES5(ch)) { + return false; + } + + for (i = 1, iz = id.length; i < iz; ++i) { + ch = id.charCodeAt(i); + if (!code.isIdentifierPartES5(ch)) { + return false; + } + } + return true; + } + + function decodeUtf16(lead, trail) { + return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; + } + + function isIdentifierNameES6(id) { + var i, iz, ch, lowCh, check; + + if (id.length === 0) { return false; } + + check = code.isIdentifierStartES6; + for (i = 0, iz = id.length; i < iz; ++i) { + ch = id.charCodeAt(i); + if (0xD800 <= ch && ch <= 0xDBFF) { + ++i; + if (i >= iz) { return false; } + lowCh = id.charCodeAt(i); + if (!(0xDC00 <= lowCh && lowCh <= 0xDFFF)) { + return false; + } + ch = decodeUtf16(ch, lowCh); + } + if (!check(ch)) { + return false; + } + check = code.isIdentifierPartES6; + } + return true; + } + + function isIdentifierES5(id, strict) { + return isIdentifierNameES5(id) && !isReservedWordES5(id, strict); + } + + function isIdentifierES6(id, strict) { + return isIdentifierNameES6(id) && !isReservedWordES6(id, strict); + } + + module.exports = { + isKeywordES5: isKeywordES5, + isKeywordES6: isKeywordES6, + isReservedWordES5: isReservedWordES5, + isReservedWordES6: isReservedWordES6, + isRestrictedWord: isRestrictedWord, + isIdentifierNameES5: isIdentifierNameES5, + isIdentifierNameES6: isIdentifierNameES6, + isIdentifierES5: isIdentifierES5, + isIdentifierES6: isIdentifierES6 + }; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/esutils/lib/utils.js b/hm_sunwell/node_modules/esutils/lib/utils.js new file mode 100644 index 0000000..ce18faa --- /dev/null +++ b/hm_sunwell/node_modules/esutils/lib/utils.js @@ -0,0 +1,33 @@ +/* + Copyright (C) 2013 Yusuke Suzuki + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +(function () { + 'use strict'; + + exports.ast = require('./ast'); + exports.code = require('./code'); + exports.keyword = require('./keyword'); +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/hm_sunwell/node_modules/esutils/package.json b/hm_sunwell/node_modules/esutils/package.json new file mode 100644 index 0000000..8c2a7d4 --- /dev/null +++ b/hm_sunwell/node_modules/esutils/package.json @@ -0,0 +1,97 @@ +{ + "_args": [ + [ + "esutils@^2.0.2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/escodegen" + ] + ], + "_from": "esutils@>=2.0.2 <3.0.0", + "_id": "esutils@2.0.2", + "_inCache": true, + "_installable": true, + "_location": "/esutils", + "_nodeVersion": "0.12.0", + "_npmUser": { + "email": "npm@michael.ficarra.me", + "name": "michaelficarra" + }, + "_npmVersion": "2.5.1", + "_phantomChildren": {}, + "_requested": { + "name": "esutils", + "raw": "esutils@^2.0.2", + "rawSpec": "^2.0.2", + "scope": null, + "spec": ">=2.0.2 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/escodegen" + ], + "_resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "_shasum": "0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b", + "_shrinkwrap": null, + "_spec": "esutils@^2.0.2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/escodegen", + "bugs": { + "url": "https://github.com/estools/esutils/issues" + }, + "dependencies": {}, + "description": "utility box for ECMAScript language tools", + "devDependencies": { + "chai": "~1.7.2", + "coffee-script": "~1.6.3", + "jshint": "2.6.3", + "mocha": "~2.2.1", + "regenerate": "~1.2.1", + "unicode-7.0.0": "^0.1.5" + }, + "directories": { + "lib": "./lib" + }, + "dist": { + "shasum": "0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b", + "tarball": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "LICENSE.BSD", + "README.md", + "lib" + ], + "gitHead": "3ffd1c403f3f29db9e8a9574b1895682e57b6a7f", + "homepage": "https://github.com/estools/esutils", + "licenses": [ + { + "type": "BSD", + "url": "http://github.com/estools/esutils/raw/master/LICENSE.BSD" + } + ], + "main": "lib/utils.js", + "maintainers": [ + { + "name": "constellation", + "email": "utatane.tea@gmail.com" + }, + { + "name": "michaelficarra", + "email": "npm@michael.ficarra.me" + } + ], + "name": "esutils", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/estools/esutils.git" + }, + "scripts": { + "generate-regex": "node tools/generate-identifier-regex.js", + "lint": "jshint lib/*.js", + "test": "npm run-script lint && npm run-script unit-test", + "unit-test": "mocha --compilers coffee:coffee-script -R spec" + }, + "version": "2.0.2" +} diff --git a/hm_sunwell/node_modules/etag/HISTORY.md b/hm_sunwell/node_modules/etag/HISTORY.md new file mode 100644 index 0000000..bd0f26d --- /dev/null +++ b/hm_sunwell/node_modules/etag/HISTORY.md @@ -0,0 +1,71 @@ +1.7.0 / 2015-06-08 +================== + + * Always include entity length in ETags for hash length extensions + * Generate non-Stats ETags using MD5 only (no longer CRC32) + * Improve stat performance by removing hashing + * Remove base64 padding in ETags to shorten + * Use MD5 instead of MD4 in weak ETags over 1KB + +1.6.0 / 2015-05-10 +================== + + * Improve support for JXcore + * Remove requirement of `atime` in the stats object + * Support "fake" stats objects in environments without `fs` + +1.5.1 / 2014-11-19 +================== + + * deps: crc@3.2.1 + - Minor fixes + +1.5.0 / 2014-10-14 +================== + + * Improve string performance + * Slightly improve speed for weak ETags over 1KB + +1.4.0 / 2014-09-21 +================== + + * Support "fake" stats objects + * Support Node.js 0.6 + +1.3.1 / 2014-09-14 +================== + + * Use the (new and improved) `crc` for crc32 + +1.3.0 / 2014-08-29 +================== + + * Default strings to strong ETags + * Improve speed for weak ETags over 1KB + +1.2.1 / 2014-08-29 +================== + + * Use the (much faster) `buffer-crc32` for crc32 + +1.2.0 / 2014-08-24 +================== + + * Add support for file stat objects + +1.1.0 / 2014-08-24 +================== + + * Add fast-path for empty entity + * Add weak ETag generation + * Shrink size of generated ETags + +1.0.1 / 2014-08-24 +================== + + * Fix behavior of string containing Unicode + +1.0.0 / 2014-05-18 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/etag/LICENSE b/hm_sunwell/node_modules/etag/LICENSE new file mode 100644 index 0000000..142ede3 --- /dev/null +++ b/hm_sunwell/node_modules/etag/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/etag/README.md b/hm_sunwell/node_modules/etag/README.md new file mode 100644 index 0000000..8da9e05 --- /dev/null +++ b/hm_sunwell/node_modules/etag/README.md @@ -0,0 +1,165 @@ +# etag + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Create simple ETags + +## Installation + +```sh +$ npm install etag +``` + +## API + +```js +var etag = require('etag') +``` + +### etag(entity, [options]) + +Generate a strong ETag for the given entity. This should be the complete +body of the entity. Strings, `Buffer`s, and `fs.Stats` are accepted. By +default, a strong ETag is generated except for `fs.Stats`, which will +generate a weak ETag (this can be overwritten by `options.weak`). + +```js +res.setHeader('ETag', etag(body)) +``` + +#### Options + +`etag` accepts these properties in the options object. + +##### weak + +Specifies if the generated ETag will include the weak validator mark (that +is, the leading `W/`). The actual entity tag is the same. The default value +is `false`, unless the `entity` is `fs.Stats`, in which case it is `true`. + +## Testing + +```sh +$ npm test +``` + +## Benchmark + +```bash +$ npm run-script bench + +> etag@1.6.0 bench nodejs-etag +> node benchmark/index.js + + http_parser@1.0 + node@0.10.33 + v8@3.14.5.9 + ares@1.9.0-DEV + uv@0.10.29 + zlib@1.2.3 + modules@11 + openssl@1.0.1j + +> node benchmark/body0-100b.js + + 100B body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 289,198 ops/sec ±1.09% (190 runs sampled) +* buffer - weak x 287,838 ops/sec ±0.91% (189 runs sampled) +* string - strong x 284,586 ops/sec ±1.05% (192 runs sampled) +* string - weak x 287,439 ops/sec ±0.82% (192 runs sampled) + +> node benchmark/body1-1kb.js + + 1KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 212,423 ops/sec ±0.75% (193 runs sampled) +* buffer - weak x 211,871 ops/sec ±0.74% (194 runs sampled) + string - strong x 205,291 ops/sec ±0.86% (194 runs sampled) + string - weak x 208,463 ops/sec ±0.79% (192 runs sampled) + +> node benchmark/body2-5kb.js + + 5KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 92,901 ops/sec ±0.58% (195 runs sampled) +* buffer - weak x 93,045 ops/sec ±0.65% (192 runs sampled) + string - strong x 89,621 ops/sec ±0.68% (194 runs sampled) + string - weak x 90,070 ops/sec ±0.70% (196 runs sampled) + +> node benchmark/body3-10kb.js + + 10KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 54,220 ops/sec ±0.85% (192 runs sampled) +* buffer - weak x 54,069 ops/sec ±0.83% (191 runs sampled) + string - strong x 53,078 ops/sec ±0.53% (194 runs sampled) + string - weak x 53,849 ops/sec ±0.47% (197 runs sampled) + +> node benchmark/body4-100kb.js + + 100KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 6,673 ops/sec ±0.15% (197 runs sampled) +* buffer - weak x 6,716 ops/sec ±0.12% (198 runs sampled) + string - strong x 6,357 ops/sec ±0.14% (197 runs sampled) + string - weak x 6,344 ops/sec ±0.21% (197 runs sampled) + +> node benchmark/stats.js + + stats + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* real - strong x 1,671,989 ops/sec ±0.13% (197 runs sampled) +* real - weak x 1,681,297 ops/sec ±0.12% (198 runs sampled) + fake - strong x 927,063 ops/sec ±0.14% (198 runs sampled) + fake - weak x 914,461 ops/sec ±0.41% (191 runs sampled) +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/etag.svg +[npm-url]: https://npmjs.org/package/etag +[node-version-image]: https://img.shields.io/node/v/etag.svg +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/etag/master.svg +[travis-url]: https://travis-ci.org/jshttp/etag +[coveralls-image]: https://img.shields.io/coveralls/jshttp/etag/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/etag?branch=master +[downloads-image]: https://img.shields.io/npm/dm/etag.svg +[downloads-url]: https://npmjs.org/package/etag diff --git a/hm_sunwell/node_modules/etag/index.js b/hm_sunwell/node_modules/etag/index.js new file mode 100644 index 0000000..b582c84 --- /dev/null +++ b/hm_sunwell/node_modules/etag/index.js @@ -0,0 +1,132 @@ +/*! + * etag + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = etag + +/** + * Module dependencies. + * @private + */ + +var crypto = require('crypto') +var Stats = require('fs').Stats + +/** + * Module variables. + * @private + */ + +var base64PadCharRegExp = /=+$/ +var toString = Object.prototype.toString + +/** + * Generate an entity tag. + * + * @param {Buffer|string} entity + * @return {string} + * @private + */ + +function entitytag(entity) { + if (entity.length === 0) { + // fast-path empty + return '"0-1B2M2Y8AsgTpgAmY7PhCfg"' + } + + // compute hash of entity + var hash = crypto + .createHash('md5') + .update(entity, 'utf8') + .digest('base64') + .replace(base64PadCharRegExp, '') + + // compute length of entity + var len = typeof entity === 'string' + ? Buffer.byteLength(entity, 'utf8') + : entity.length + + return '"' + len.toString(16) + '-' + hash + '"' +} + +/** + * Create a simple ETag. + * + * @param {string|Buffer|Stats} entity + * @param {object} [options] + * @param {boolean} [options.weak] + * @return {String} + * @public + */ + +function etag(entity, options) { + if (entity == null) { + throw new TypeError('argument entity is required') + } + + // support fs.Stats object + var isStats = isstats(entity) + var weak = options && typeof options.weak === 'boolean' + ? options.weak + : isStats + + // validate argument + if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) { + throw new TypeError('argument entity must be string, Buffer, or fs.Stats') + } + + // generate entity tag + var tag = isStats + ? stattag(entity) + : entitytag(entity) + + return weak + ? 'W/' + tag + : tag +} + +/** + * Determine if object is a Stats object. + * + * @param {object} obj + * @return {boolean} + * @api private + */ + +function isstats(obj) { + // genuine fs.Stats + if (typeof Stats === 'function' && obj instanceof Stats) { + return true + } + + // quack quack + return obj && typeof obj === 'object' + && 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' + && 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' + && 'ino' in obj && typeof obj.ino === 'number' + && 'size' in obj && typeof obj.size === 'number' +} + +/** + * Generate a tag for a stat. + * + * @param {object} stat + * @return {string} + * @private + */ + +function stattag(stat) { + var mtime = stat.mtime.getTime().toString(16) + var size = stat.size.toString(16) + + return '"' + size + '-' + mtime + '"' +} diff --git a/hm_sunwell/node_modules/etag/package.json b/hm_sunwell/node_modules/etag/package.json new file mode 100644 index 0000000..9ec1e57 --- /dev/null +++ b/hm_sunwell/node_modules/etag/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + "etag@~1.7.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "etag@>=1.7.0 <1.8.0", + "_id": "etag@1.7.0", + "_inCache": true, + "_installable": true, + "_location": "/etag", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "etag", + "raw": "etag@~1.7.0", + "rawSpec": "~1.7.0", + "scope": null, + "spec": ">=1.7.0 <1.8.0", + "type": "range" + }, + "_requiredBy": [ + "/express", + "/send" + ], + "_resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "_shasum": "03d30b5f67dd6e632d2945d30d6652731a34d5d8", + "_shrinkwrap": null, + "_spec": "etag@~1.7.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "bugs": { + "url": "https://github.com/jshttp/etag/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "David Björklund", + "email": "david.bjorklund@gmail.com" + } + ], + "dependencies": {}, + "description": "Create simple ETags", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "1.0.0", + "istanbul": "0.3.14", + "mocha": "~1.21.4", + "seedrandom": "2.3.11" + }, + "directories": {}, + "dist": { + "shasum": "03d30b5f67dd6e632d2945d30d6652731a34d5d8", + "tarball": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "gitHead": "a511f5c8c930fd9546dbd88acb080f96bc788cfc", + "homepage": "https://github.com/jshttp/etag", + "keywords": [ + "etag", + "http", + "res" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "etag", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/etag.git" + }, + "scripts": { + "bench": "node benchmark/index.js", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.7.0" +} diff --git a/hm_sunwell/node_modules/express/History.md b/hm_sunwell/node_modules/express/History.md new file mode 100644 index 0000000..40a5ed7 --- /dev/null +++ b/hm_sunwell/node_modules/express/History.md @@ -0,0 +1,3142 @@ +4.14.0 / 2016-06-16 +=================== + + * Add `acceptRanges` option to `res.sendFile`/`res.sendfile` + * Add `cacheControl` option to `res.sendFile`/`res.sendfile` + * Add `options` argument to `req.range` + - Includes the `combine` option + * Encode URL in `res.location`/`res.redirect` if not already encoded + * Fix some redirect handling in `res.sendFile`/`res.sendfile` + * Fix Windows absolute path check using forward slashes + * Improve error with invalid arguments to `req.get()` + * Improve performance for `res.json`/`res.jsonp` in most cases + * Improve `Range` header handling in `res.sendFile`/`res.sendfile` + * deps: accepts@~1.3.3 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Many performance improvments + - deps: mime-types@~2.1.11 + - deps: negotiator@0.6.1 + * deps: content-type@~1.0.2 + - perf: enable strict mode + * deps: cookie@0.3.1 + - Add `sameSite` option + - Fix cookie `Max-Age` to never be a floating point number + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - Throw better error for invalid argument to parse + - Throw on invalid values provided to `serialize` + - perf: enable strict mode + - perf: hoist regular expression + - perf: use for loop in parse + - perf: use string concatination for serialization + * deps: finalhandler@0.5.0 + - Change invalid or non-numeric status code to 500 + - Overwrite status message to match set status code + - Prefer `err.statusCode` if `err.status` is invalid + - Set response headers from `err.headers` object + - Use `statuses` instead of `http` module for status messages + * deps: proxy-addr@~1.1.2 + - Fix accepting various invalid netmasks + - Fix IPv6-mapped IPv4 validation edge cases + - IPv4 netmasks must be contingous + - IPv6 addresses cannot be used as a netmask + - deps: ipaddr.js@1.1.1 + * deps: qs@6.2.0 + - Add `decoder` option in `parse` function + * deps: range-parser@~1.2.0 + - Add `combine` option to combine overlapping ranges + - Fix incorrectly returning -1 when there is at least one valid range + - perf: remove internal function + * deps: send@0.14.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Correctly inherit from `Stream` class + - Fix `Content-Range` header in 416 responses when using `start`/`end` options + - Fix `Content-Range` header missing from default 416 responses + - Fix redirect error when `path` contains raw non-URL characters + - Fix redirect when `path` starts with multiple forward slashes + - Ignore non-byte `Range` headers + - deps: http-errors@~1.5.0 + - deps: range-parser@~1.2.0 + - deps: statuses@~1.3.0 + - perf: remove argument reassignment + * deps: serve-static@~1.11.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Fix redirect error when `req.url` contains raw non-URL characters + - Ignore non-byte `Range` headers + - Use status code 301 for redirects + - deps: send@0.14.1 + * deps: type-is@~1.6.13 + - Fix type error when given invalid type to match against + - deps: mime-types@~2.1.11 + * deps: vary@~1.1.0 + - Only accept valid field names in the `field` argument + * perf: use strict equality when possible + +4.13.4 / 2016-01-21 +=================== + + * deps: content-disposition@0.5.1 + - perf: enable strict mode + * deps: cookie@0.1.5 + - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Support web browser loading + - perf: enable strict mode + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: finalhandler@0.4.1 + - deps: escape-html@~1.0.3 + * deps: merge-descriptors@1.0.1 + - perf: enable strict mode + * deps: methods@~1.1.2 + - perf: enable strict mode + * deps: parseurl@~1.3.1 + - perf: enable strict mode + * deps: proxy-addr@~1.0.10 + - deps: ipaddr.js@1.0.5 + - perf: enable strict mode + * deps: range-parser@~1.0.3 + - perf: enable strict mode + * deps: send@0.13.1 + - deps: depd@~1.1.0 + - deps: destroy@~1.0.4 + - deps: escape-html@~1.0.3 + - deps: range-parser@~1.0.3 + * deps: serve-static@~1.10.2 + - deps: escape-html@~1.0.3 + - deps: parseurl@~1.3.0 + - deps: send@0.13.1 + +4.13.3 / 2015-08-02 +=================== + + * Fix infinite loop condition using `mergeParams: true` + * Fix inner numeric indices incorrectly altering parent `req.params` + +4.13.2 / 2015-07-31 +=================== + + * deps: accepts@~1.2.12 + - deps: mime-types@~2.1.4 + * deps: array-flatten@1.1.1 + - perf: enable strict mode + * deps: path-to-regexp@0.1.7 + - Fix regression with escaped round brackets and matching groups + * deps: type-is@~1.6.6 + - deps: mime-types@~2.1.4 + +4.13.1 / 2015-07-05 +=================== + + * deps: accepts@~1.2.10 + - deps: mime-types@~2.1.2 + * deps: qs@4.0.0 + - Fix dropping parameters like `hasOwnProperty` + - Fix various parsing edge cases + * deps: type-is@~1.6.4 + - deps: mime-types@~2.1.2 + - perf: enable strict mode + - perf: remove argument reassignment + +4.13.0 / 2015-06-20 +=================== + + * Add settings to debug output + * Fix `res.format` error when only `default` provided + * Fix issue where `next('route')` in `app.param` would incorrectly skip values + * Fix hiding platform issues with `decodeURIComponent` + - Only `URIError`s are a 400 + * Fix using `*` before params in routes + * Fix using capture groups before params in routes + * Simplify `res.cookie` to call `res.append` + * Use `array-flatten` module for flattening arrays + * deps: accepts@~1.2.9 + - deps: mime-types@~2.1.1 + - perf: avoid argument reassignment & argument slice + - perf: avoid negotiator recursive construction + - perf: enable strict mode + - perf: remove unnecessary bitwise operator + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: finalhandler@0.4.0 + - Fix a false-positive when unpiping in Node.js 0.8 + - Support `statusCode` property on `Error` objects + - Use `unpipe` module for unpiping requests + - deps: escape-html@1.0.2 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove argument reassignment + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * deps: path-to-regexp@0.1.6 + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + * deps: serve-static@~1.10.0 + - Add `fallthrough` option + - Fix reading options from options prototype + - Improve the default redirect response headers + - Malformed URLs now `next()` instead of 400 + - deps: escape-html@1.0.2 + - deps: send@0.13.0 + - perf: enable strict mode + - perf: remove argument reassignment + * deps: type-is@~1.6.3 + - deps: mime-types@~2.1.1 + - perf: reduce try block size + - perf: remove bitwise operations + * perf: enable strict mode + * perf: isolate `app.render` try block + * perf: remove argument reassignments in application + * perf: remove argument reassignments in request prototype + * perf: remove argument reassignments in response prototype + * perf: remove argument reassignments in routing + * perf: remove argument reassignments in `View` + * perf: skip attempting to decode zero length string + * perf: use saved reference to `http.STATUS_CODES` + +4.12.4 / 2015-05-17 +=================== + + * deps: accepts@~1.2.7 + - deps: mime-types@~2.0.11 + - deps: negotiator@0.5.3 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: etag@~1.6.0 + - Improve support for JXcore + - Support "fake" stats objects in environments without `fs` + * deps: finalhandler@0.3.6 + - deps: debug@~2.2.0 + - deps: on-finished@~2.2.1 + * deps: on-finished@~2.2.1 + - Fix `isFinished(req)` when data buffered + * deps: proxy-addr@~1.0.8 + - deps: ipaddr.js@1.0.1 + * deps: qs@2.4.2 + - Fix allowing parameters like `constructor` + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + * deps: serve-static@~1.9.3 + - deps: send@0.12.3 + * deps: type-is@~1.6.2 + - deps: mime-types@~2.0.11 + +4.12.3 / 2015-03-17 +=================== + + * deps: accepts@~1.2.5 + - deps: mime-types@~2.0.10 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: finalhandler@0.3.4 + - deps: debug@~2.1.3 + * deps: proxy-addr@~1.0.7 + - deps: ipaddr.js@0.1.9 + * deps: qs@2.4.1 + - Fix error when parameter `hasOwnProperty` is present + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + * deps: serve-static@~1.9.2 + - deps: send@0.12.2 + * deps: type-is@~1.6.1 + - deps: mime-types@~2.0.10 + +4.12.2 / 2015-03-02 +=================== + + * Fix regression where `"Request aborted"` is logged using `res.sendFile` + +4.12.1 / 2015-03-01 +=================== + + * Fix constructing application with non-configurable prototype properties + * Fix `ECONNRESET` errors from `res.sendFile` usage + * Fix `req.host` when using "trust proxy" hops count + * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count + * Fix wrong `code` on aborted connections from `res.sendFile` + * deps: merge-descriptors@1.0.0 + +4.12.0 / 2015-02-23 +=================== + + * Fix `"trust proxy"` setting to inherit when app is mounted + * Generate `ETag`s for all request responses + - No longer restricted to only responses for `GET` and `HEAD` requests + * Use `content-type` to parse `Content-Type` headers + * deps: accepts@~1.2.4 + - Fix preference sorting to be stable for long acceptable lists + - deps: mime-types@~2.0.9 + - deps: negotiator@0.5.1 + * deps: cookie-signature@1.0.6 + * deps: send@0.12.1 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + * deps: serve-static@~1.9.1 + - deps: send@0.12.1 + * deps: type-is@~1.6.0 + - fix argument reassignment + - fix false-positives in `hasBody` `Transfer-Encoding` check + - support wildcard for both type and subtype (`*/*`) + - deps: mime-types@~2.0.9 + +4.11.2 / 2015-02-01 +=================== + + * Fix `res.redirect` double-calling `res.end` for `HEAD` requests + * deps: accepts@~1.2.3 + - deps: mime-types@~2.0.8 + * deps: proxy-addr@~1.0.6 + - deps: ipaddr.js@0.1.8 + * deps: type-is@~1.5.6 + - deps: mime-types@~2.0.8 + +4.11.1 / 2015-01-20 +=================== + + * deps: send@0.11.1 + - Fix root path disclosure + * deps: serve-static@~1.8.1 + - Fix redirect loop in Node.js 0.11.14 + - Fix root path disclosure + - deps: send@0.11.1 + +4.11.0 / 2015-01-13 +=================== + + * Add `res.append(field, val)` to append headers + * Deprecate leading `:` in `name` for `app.param(name, fn)` + * Deprecate `req.param()` -- use `req.params`, `req.body`, or `req.query` instead + * Deprecate `app.param(fn)` + * Fix `OPTIONS` responses to include the `HEAD` method properly + * Fix `res.sendFile` not always detecting aborted connection + * Match routes iteratively to prevent stack overflows + * deps: accepts@~1.2.2 + - deps: mime-types@~2.0.7 + - deps: negotiator@0.5.0 + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + * deps: serve-static@~1.8.0 + - deps: send@0.11.0 + +4.10.8 / 2015-01-13 +=================== + + * Fix crash from error within `OPTIONS` response handler + * deps: proxy-addr@~1.0.5 + - deps: ipaddr.js@0.1.6 + +4.10.7 / 2015-01-04 +=================== + + * Fix `Allow` header for `OPTIONS` to not contain duplicate methods + * Fix incorrect "Request aborted" for `res.sendFile` when `HEAD` or 304 + * deps: debug@~2.1.1 + * deps: finalhandler@0.3.3 + - deps: debug@~2.1.1 + - deps: on-finished@~2.2.0 + * deps: methods@~1.1.1 + * deps: on-finished@~2.2.0 + * deps: serve-static@~1.7.2 + - Fix potential open redirect when mounted at root + * deps: type-is@~1.5.5 + - deps: mime-types@~2.0.7 + +4.10.6 / 2014-12-12 +=================== + + * Fix exception in `req.fresh`/`req.stale` without response headers + +4.10.5 / 2014-12-10 +=================== + + * Fix `res.send` double-calling `res.end` for `HEAD` requests + * deps: accepts@~1.1.4 + - deps: mime-types@~2.0.4 + * deps: type-is@~1.5.4 + - deps: mime-types@~2.0.4 + +4.10.4 / 2014-11-24 +=================== + + * Fix `res.sendfile` logging standard write errors + +4.10.3 / 2014-11-23 +=================== + + * Fix `res.sendFile` logging standard write errors + * deps: etag@~1.5.1 + * deps: proxy-addr@~1.0.4 + - deps: ipaddr.js@0.1.5 + * deps: qs@2.3.3 + - Fix `arrayLimit` behavior + +4.10.2 / 2014-11-09 +=================== + + * Correctly invoke async router callback asynchronously + * deps: accepts@~1.1.3 + - deps: mime-types@~2.0.3 + * deps: type-is@~1.5.3 + - deps: mime-types@~2.0.3 + +4.10.1 / 2014-10-28 +=================== + + * Fix handling of URLs containing `://` in the path + * deps: qs@2.3.2 + - Fix parsing of mixed objects and values + +4.10.0 / 2014-10-23 +=================== + + * Add support for `app.set('views', array)` + - Views are looked up in sequence in array of directories + * Fix `res.send(status)` to mention `res.sendStatus(status)` + * Fix handling of invalid empty URLs + * Use `content-disposition` module for `res.attachment`/`res.download` + - Sends standards-compliant `Content-Disposition` header + - Full Unicode support + * Use `path.resolve` in view lookup + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: etag@~1.5.0 + - Improve string performance + - Slightly improve speed for weak ETags over 1KB + * deps: finalhandler@0.3.2 + - Terminate in progress response only on error + - Use `on-finished` to determine request status + - deps: debug@~2.1.0 + - deps: on-finished@~2.1.1 + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + * deps: qs@2.3.0 + - Fix parsing of mixed implicit and explicit arrays + * deps: send@0.10.1 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + - deps: on-finished@~2.1.1 + * deps: serve-static@~1.7.1 + - deps: send@0.10.1 + +4.9.8 / 2014-10-17 +================== + + * Fix `res.redirect` body when redirect status specified + * deps: accepts@~1.1.2 + - Fix error when media type has invalid parameter + - deps: negotiator@0.4.9 + +4.9.7 / 2014-10-10 +================== + + * Fix using same param name in array of paths + +4.9.6 / 2014-10-08 +================== + + * deps: accepts@~1.1.1 + - deps: mime-types@~2.0.2 + - deps: negotiator@0.4.8 + * deps: serve-static@~1.6.4 + - Fix redirect loop when index file serving disabled + * deps: type-is@~1.5.2 + - deps: mime-types@~2.0.2 + +4.9.5 / 2014-09-24 +================== + + * deps: etag@~1.4.0 + * deps: proxy-addr@~1.0.3 + - Use `forwarded` npm module + * deps: send@0.9.3 + - deps: etag@~1.4.0 + * deps: serve-static@~1.6.3 + - deps: send@0.9.3 + +4.9.4 / 2014-09-19 +================== + + * deps: qs@2.2.4 + - Fix issue with object keys starting with numbers truncated + +4.9.3 / 2014-09-18 +================== + + * deps: proxy-addr@~1.0.2 + - Fix a global leak when multiple subnets are trusted + - deps: ipaddr.js@0.1.3 + +4.9.2 / 2014-09-17 +================== + + * Fix regression for empty string `path` in `app.use` + * Fix `router.use` to accept array of middleware without path + * Improve error message for bad `app.use` arguments + +4.9.1 / 2014-09-16 +================== + + * Fix `app.use` to accept array of middleware without path + * deps: depd@0.4.5 + * deps: etag@~1.3.1 + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + * deps: serve-static@~1.6.2 + - deps: send@0.9.2 + +4.9.0 / 2014-09-08 +================== + + * Add `res.sendStatus` + * Invoke callback for sendfile when client aborts + - Applies to `res.sendFile`, `res.sendfile`, and `res.download` + - `err` will be populated with request aborted error + * Support IP address host in `req.subdomains` + * Use `etag` to generate `ETag` headers + * deps: accepts@~1.1.0 + - update `mime-types` + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + * deps: finalhandler@0.2.0 + - Set `X-Content-Type-Options: nosniff` header + - deps: debug@~2.0.0 + * deps: fresh@0.2.4 + * deps: media-typer@0.3.0 + - Throw error when parameter format invalid on parse + * deps: qs@2.2.3 + - Fix issue where first empty value in array is discarded + * deps: range-parser@~1.0.2 + * deps: send@0.9.1 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + - deps: fresh@0.2.4 + * deps: serve-static@~1.6.1 + - Add `lastModified` option + - deps: send@0.9.1 + * deps: type-is@~1.5.1 + - fix `hasbody` to be true for `content-length: 0` + - deps: media-typer@0.3.0 + - deps: mime-types@~2.0.1 + * deps: vary@~1.0.0 + - Accept valid `Vary` header string as `field` + +4.8.8 / 2014-09-04 +================== + + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + * deps: serve-static@~1.5.4 + - deps: send@0.8.5 + +4.8.7 / 2014-08-29 +================== + + * deps: qs@2.2.2 + - Remove unnecessary cloning + +4.8.6 / 2014-08-27 +================== + + * deps: qs@2.2.0 + - Array parsing fix + - Performance improvements + +4.8.5 / 2014-08-18 +================== + + * deps: send@0.8.3 + - deps: destroy@1.0.3 + - deps: on-finished@2.1.0 + * deps: serve-static@~1.5.3 + - deps: send@0.8.3 + +4.8.4 / 2014-08-14 +================== + + * deps: qs@1.2.2 + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + * deps: serve-static@~1.5.2 + - deps: send@0.8.2 + +4.8.3 / 2014-08-10 +================== + + * deps: parseurl@~1.3.0 + * deps: qs@1.2.1 + * deps: serve-static@~1.5.1 + - Fix parsing of weird `req.originalUrl` values + - deps: parseurl@~1.3.0 + - deps: utils-merge@1.0.0 + +4.8.2 / 2014-08-07 +================== + + * deps: qs@1.2.0 + - Fix parsing array of objects + +4.8.1 / 2014-08-06 +================== + + * fix incorrect deprecation warnings on `res.download` + * deps: qs@1.1.0 + - Accept urlencoded square brackets + - Accept empty values in implicit array notation + +4.8.0 / 2014-08-05 +================== + + * add `res.sendFile` + - accepts a file system path instead of a URL + - requires an absolute path or `root` option specified + * deprecate `res.sendfile` -- use `res.sendFile` instead + * support mounted app as any argument to `app.use()` + * deps: qs@1.0.2 + - Complete rewrite + - Limits array length to 20 + - Limits object depth to 5 + - Limits parameters to 1,000 + * deps: send@0.8.1 + - Add `extensions` option + * deps: serve-static@~1.5.0 + - Add `extensions` option + - deps: send@0.8.1 + +4.7.4 / 2014-08-04 +================== + + * fix `res.sendfile` regression for serving directory index files + * deps: send@0.7.4 + - Fix incorrect 403 on Windows and Node.js 0.11 + - Fix serving index files without root dir + * deps: serve-static@~1.4.4 + - deps: send@0.7.4 + +4.7.3 / 2014-08-04 +================== + + * deps: send@0.7.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + * deps: serve-static@~1.4.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + - deps: send@0.7.3 + +4.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + * deps: send@0.7.2 + - deps: depd@0.4.4 + * deps: serve-static@~1.4.2 + +4.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + * deps: send@0.7.1 + - deps: depd@0.4.3 + * deps: serve-static@~1.4.1 + +4.7.0 / 2014-07-25 +================== + + * fix `req.protocol` for proxy-direct connections + * configurable query parser with `app.set('query parser', parser)` + - `app.set('query parser', 'extended')` parse with "qs" module + - `app.set('query parser', 'simple')` parse with "querystring" core module + - `app.set('query parser', false)` disable query string parsing + - `app.set('query parser', true)` enable simple parsing + * deprecate `res.json(status, obj)` -- use `res.status(status).json(obj)` instead + * deprecate `res.jsonp(status, obj)` -- use `res.status(status).jsonp(obj)` instead + * deprecate `res.send(status, body)` -- use `res.status(status).send(body)` instead + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: finalhandler@0.1.0 + - Respond after request fully read + - deps: debug@1.0.4 + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - Cap `maxAge` value to 1 year + - deps: debug@1.0.4 + - deps: depd@0.4.2 + * deps: serve-static@~1.4.0 + - deps: parseurl@~1.2.0 + - deps: send@0.7.0 + * perf: prevent multiple `Buffer` creation in `res.send` + +4.6.1 / 2014-07-12 +================== + + * fix `subapp.mountpath` regression for `app.use(subapp)` + +4.6.0 / 2014-07-11 +================== + + * accept multiple callbacks to `app.use()` + * add explicit "Rosetta Flash JSONP abuse" protection + - previous versions are not vulnerable; this is just explicit protection + * catch errors in multiple `req.param(name, fn)` handlers + * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead + * fix `res.send(status, num)` to send `num` as json (not error) + * remove unnecessary escaping when `res.jsonp` returns JSON response + * support non-string `path` in `app.use(path, fn)` + - supports array of paths + - supports `RegExp` + * router: fix optimization on router exit + * router: refactor location of `try` blocks + * router: speed up standard `app.use(fn)` + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + * deps: finalhandler@0.0.3 + - deps: debug@1.0.3 + * deps: methods@1.1.0 + - add `CONNECT` + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + * deps: path-to-regexp@0.1.3 + * deps: send@0.6.0 + - deps: debug@1.0.3 + * deps: serve-static@~1.3.2 + - deps: parseurl@~1.1.3 + - deps: send@0.6.0 + * perf: fix arguments reassign deopt in some `res` methods + +4.5.1 / 2014-07-06 +================== + + * fix routing regression when altering `req.method` + +4.5.0 / 2014-07-04 +================== + + * add deprecation message to non-plural `req.accepts*` + * add deprecation message to `res.send(body, status)` + * add deprecation message to `res.vary()` + * add `headers` option to `res.sendfile` + - use to set headers on successful file transfer + * add `mergeParams` option to `Router` + - merges `req.params` from parent routes + * add `req.hostname` -- correct name for what `req.host` returns + * deprecate things with `depd` module + * deprecate `req.host` -- use `req.hostname` instead + * fix behavior when handling request without routes + * fix handling when `route.all` is only route + * invoke `router.param()` only when route matches + * restore `req.params` after invoking router + * use `finalhandler` for final response handling + * use `media-typer` to alter content-type charset + * deps: accepts@~1.0.7 + * deps: send@0.5.0 + - Accept string for `maxage` (converted by `ms`) + - Include link in default redirect response + * deps: serve-static@~1.3.0 + - Accept string for `maxAge` (converted by `ms`) + - Add `setHeaders` option + - Include HTML link in redirect response + - deps: send@0.5.0 + * deps: type-is@~1.3.2 + +4.4.5 / 2014-06-26 +================== + + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +4.4.4 / 2014-06-20 +================== + + * fix `res.attachment` Unicode filenames in Safari + * fix "trim prefix" debug message in `express:router` + * deps: accepts@~1.0.5 + * deps: buffer-crc32@0.2.3 + +4.4.3 / 2014-06-11 +================== + + * fix persistence of modified `req.params[name]` from `app.param()` + * deps: accepts@1.0.3 + - deps: negotiator@0.4.6 + * deps: debug@1.0.2 + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + * deps: serve-static@1.2.3 + - Do not throw un-catchable error on file open race condition + - deps: send@0.4.3 + +4.4.2 / 2014-06-09 +================== + + * fix catching errors from top-level handlers + * use `vary` module for `res.vary` + * deps: debug@1.0.1 + * deps: proxy-addr@1.0.1 + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: debug@1.0.1 + - deps: finished@1.2.1 + * deps: serve-static@1.2.2 + - fix "event emitter leak" warnings + - deps: send@0.4.2 + * deps: type-is@1.2.1 + +4.4.1 / 2014-06-02 +================== + + * deps: methods@1.0.1 + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + * deps: serve-static@1.2.1 + - use `escape-html` for escaping + - deps: send@0.4.1 + +4.4.0 / 2014-05-30 +================== + + * custom etag control with `app.set('etag', val)` + - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation + - `app.set('etag', 'weak')` weak tag + - `app.set('etag', 'strong')` strong etag + - `app.set('etag', false)` turn off + - `app.set('etag', true)` standard etag + * mark `res.send` ETag as weak and reduce collisions + * update accepts to 1.0.2 + - Fix interpretation when header not in request + * update send to 0.4.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: debug@0.8.1 + * update serve-static to 1.2.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: send@0.4.0 + +4.3.2 / 2014-05-28 +================== + + * fix handling of errors from `router.param()` callbacks + +4.3.1 / 2014-05-23 +================== + + * revert "fix behavior of multiple `app.VERB` for the same path" + - this caused a regression in the order of route execution + +4.3.0 / 2014-05-21 +================== + + * add `req.baseUrl` to access the path stripped from `req.url` in routes + * fix behavior of multiple `app.VERB` for the same path + * fix issue routing requests among sub routers + * invoke `router.param()` only when necessary instead of every match + * proper proxy trust with `app.set('trust proxy', trust)` + - `app.set('trust proxy', 1)` trust first hop + - `app.set('trust proxy', 'loopback')` trust loopback addresses + - `app.set('trust proxy', '10.0.0.1')` trust single IP + - `app.set('trust proxy', '10.0.0.1/16')` trust subnet + - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list + - `app.set('trust proxy', false)` turn off + - `app.set('trust proxy', true)` trust everything + * set proper `charset` in `Content-Type` for `res.send` + * update type-is to 1.2.0 + - support suffix matching + +4.2.0 / 2014-05-11 +================== + + * deprecate `app.del()` -- use `app.delete()` instead + * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead + - the edge-case `res.json(status, num)` requires `res.status(status).json(num)` + * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead + - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)` + * fix `req.next` when inside router instance + * include `ETag` header in `HEAD` requests + * keep previous `Content-Type` for `res.jsonp` + * support PURGE method + - add `app.purge` + - add `router.purge` + - include PURGE in `app.all` + * update debug to 0.8.0 + - add `enable()` method + - change from stderr to stdout + * update methods to 1.0.0 + - add PURGE + +4.1.2 / 2014-05-08 +================== + + * fix `req.host` for IPv6 literals + * fix `res.jsonp` error if callback param is object + +4.1.1 / 2014-04-27 +================== + + * fix package.json to reflect supported node version + +4.1.0 / 2014-04-24 +================== + + * pass options from `res.sendfile` to `send` + * preserve casing of headers in `res.header` and `res.set` + * support unicode file names in `res.attachment` and `res.download` + * update accepts to 1.0.1 + - deps: negotiator@0.4.0 + * update cookie to 0.1.2 + - Fix for maxAge == 0 + - made compat with expires field + * update send to 0.3.0 + - Accept API options in options object + - Coerce option types + - Control whether to generate etags + - Default directory access to 403 when index disabled + - Fix sending files with dots without root set + - Include file path in etag + - Make "Can't set headers after they are sent." catchable + - Send full entity-body for multi range requests + - Set etags to "weak" + - Support "If-Range" header + - Support multiple index paths + - deps: mime@1.2.11 + * update serve-static to 1.1.0 + - Accept options directly to `send` module + - Resolve relative paths at middleware setup + - Use parseurl to parse the URL from request + - deps: send@0.3.0 + * update type-is to 1.1.0 + - add non-array values support + - add `multipart` as a shorthand + +4.0.0 / 2014-04-09 +================== + + * remove: + - node 0.8 support + - connect and connect's patches except for charset handling + - express(1) - moved to [express-generator](https://github.com/expressjs/generator) + - `express.createServer()` - it has been deprecated for a long time. Use `express()` + - `app.configure` - use logic in your own app code + - `app.router` - is removed + - `req.auth` - use `basic-auth` instead + - `req.accepted*` - use `req.accepts*()` instead + - `res.location` - relative URL resolution is removed + - `res.charset` - include the charset in the content type when using `res.set()` + - all bundled middleware except `static` + * change: + - `app.route` -> `app.mountpath` when mounting an express app in another express app + - `json spaces` no longer enabled by default in development + - `req.accepts*` -> `req.accepts*s` - i.e. `req.acceptsEncoding` -> `req.acceptsEncodings` + - `req.params` is now an object instead of an array + - `res.locals` is no longer a function. It is a plain js object. Treat it as such. + - `res.headerSent` -> `res.headersSent` to match node.js ServerResponse object + * refactor: + - `req.accepts*` with [accepts](https://github.com/expressjs/accepts) + - `req.is` with [type-is](https://github.com/expressjs/type-is) + - [path-to-regexp](https://github.com/component/path-to-regexp) + * add: + - `app.router()` - returns the app Router instance + - `app.route()` - Proxy to the app's `Router#route()` method to create a new route + - Router & Route - public API + +3.21.2 / 2015-07-31 +=================== + + * deps: connect@2.30.2 + - deps: body-parser@~1.13.3 + - deps: compression@~1.5.2 + - deps: errorhandler@~1.4.2 + - deps: method-override@~2.3.5 + - deps: serve-index@~1.7.2 + - deps: type-is@~1.6.6 + - deps: vhost@~3.0.1 + * deps: vary@~1.0.1 + - Fix setting empty header from empty `field` + - perf: enable strict mode + - perf: remove argument reassignments + +3.21.1 / 2015-07-05 +=================== + + * deps: basic-auth@~1.0.3 + * deps: connect@2.30.1 + - deps: body-parser@~1.13.2 + - deps: compression@~1.5.1 + - deps: errorhandler@~1.4.1 + - deps: morgan@~1.6.1 + - deps: pause@0.1.0 + - deps: qs@4.0.0 + - deps: serve-index@~1.7.1 + - deps: type-is@~1.6.4 + +3.21.0 / 2015-06-18 +=================== + + * deps: basic-auth@1.0.2 + - perf: enable strict mode + - perf: hoist regular expression + - perf: parse with regular expressions + - perf: remove argument reassignment + * deps: connect@2.30.0 + - deps: body-parser@~1.13.1 + - deps: bytes@2.1.0 + - deps: compression@~1.5.0 + - deps: cookie@0.1.3 + - deps: cookie-parser@~1.3.5 + - deps: csurf@~1.8.3 + - deps: errorhandler@~1.4.0 + - deps: express-session@~1.11.3 + - deps: finalhandler@0.4.0 + - deps: fresh@0.3.0 + - deps: morgan@~1.6.0 + - deps: serve-favicon@~2.3.0 + - deps: serve-index@~1.7.0 + - deps: serve-static@~1.10.0 + - deps: type-is@~1.6.3 + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: mkdirp@0.5.1 + - Work in global strict mode + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + +3.20.3 / 2015-05-17 +=================== + + * deps: connect@2.29.2 + - deps: body-parser@~1.12.4 + - deps: compression@~1.4.4 + - deps: connect-timeout@~1.6.2 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: errorhandler@~1.3.6 + - deps: finalhandler@0.3.6 + - deps: method-override@~2.3.3 + - deps: morgan@~1.5.3 + - deps: qs@2.4.2 + - deps: response-time@~2.3.1 + - deps: serve-favicon@~2.2.1 + - deps: serve-index@~1.6.4 + - deps: serve-static@~1.9.3 + - deps: type-is@~1.6.2 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: proxy-addr@~1.0.8 + - deps: ipaddr.js@1.0.1 + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + +3.20.2 / 2015-03-16 +=================== + + * deps: connect@2.29.1 + - deps: body-parser@~1.12.2 + - deps: compression@~1.4.3 + - deps: connect-timeout@~1.6.1 + - deps: debug@~2.1.3 + - deps: errorhandler@~1.3.5 + - deps: express-session@~1.10.4 + - deps: finalhandler@0.3.4 + - deps: method-override@~2.3.2 + - deps: morgan@~1.5.2 + - deps: qs@2.4.1 + - deps: serve-index@~1.6.3 + - deps: serve-static@~1.9.2 + - deps: type-is@~1.6.1 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: merge-descriptors@1.0.0 + * deps: proxy-addr@~1.0.7 + - deps: ipaddr.js@0.1.9 + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + +3.20.1 / 2015-02-28 +=================== + + * Fix `req.host` when using "trust proxy" hops count + * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count + +3.20.0 / 2015-02-18 +=================== + + * Fix `"trust proxy"` setting to inherit when app is mounted + * Generate `ETag`s for all request responses + - No longer restricted to only responses for `GET` and `HEAD` requests + * Use `content-type` to parse `Content-Type` headers + * deps: connect@2.29.0 + - Use `content-type` to parse `Content-Type` headers + - deps: body-parser@~1.12.0 + - deps: compression@~1.4.1 + - deps: connect-timeout@~1.6.0 + - deps: cookie-parser@~1.3.4 + - deps: cookie-signature@1.0.6 + - deps: csurf@~1.7.0 + - deps: errorhandler@~1.3.4 + - deps: express-session@~1.10.3 + - deps: http-errors@~1.3.1 + - deps: response-time@~2.3.0 + - deps: serve-index@~1.6.2 + - deps: serve-static@~1.9.1 + - deps: type-is@~1.6.0 + * deps: cookie-signature@1.0.6 + * deps: send@0.12.1 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + +3.19.2 / 2015-02-01 +=================== + + * deps: connect@2.28.3 + - deps: compression@~1.3.1 + - deps: csurf@~1.6.6 + - deps: errorhandler@~1.3.3 + - deps: express-session@~1.10.2 + - deps: serve-index@~1.6.1 + - deps: type-is@~1.5.6 + * deps: proxy-addr@~1.0.6 + - deps: ipaddr.js@0.1.8 + +3.19.1 / 2015-01-20 +=================== + + * deps: connect@2.28.2 + - deps: body-parser@~1.10.2 + - deps: serve-static@~1.8.1 + * deps: send@0.11.1 + - Fix root path disclosure + +3.19.0 / 2015-01-09 +=================== + + * Fix `OPTIONS` responses to include the `HEAD` method property + * Use `readline` for prompt in `express(1)` + * deps: commander@2.6.0 + * deps: connect@2.28.1 + - deps: body-parser@~1.10.1 + - deps: compression@~1.3.0 + - deps: connect-timeout@~1.5.0 + - deps: csurf@~1.6.4 + - deps: debug@~2.1.1 + - deps: errorhandler@~1.3.2 + - deps: express-session@~1.10.1 + - deps: finalhandler@0.3.3 + - deps: method-override@~2.3.1 + - deps: morgan@~1.5.1 + - deps: serve-favicon@~2.2.0 + - deps: serve-index@~1.6.0 + - deps: serve-static@~1.8.0 + - deps: type-is@~1.5.5 + * deps: debug@~2.1.1 + * deps: methods@~1.1.1 + * deps: proxy-addr@~1.0.5 + - deps: ipaddr.js@0.1.6 + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + +3.18.6 / 2014-12-12 +=================== + + * Fix exception in `req.fresh`/`req.stale` without response headers + +3.18.5 / 2014-12-11 +=================== + + * deps: connect@2.27.6 + - deps: compression@~1.2.2 + - deps: express-session@~1.9.3 + - deps: http-errors@~1.2.8 + - deps: serve-index@~1.5.3 + - deps: type-is@~1.5.4 + +3.18.4 / 2014-11-23 +=================== + + * deps: connect@2.27.4 + - deps: body-parser@~1.9.3 + - deps: compression@~1.2.1 + - deps: errorhandler@~1.2.3 + - deps: express-session@~1.9.2 + - deps: qs@2.3.3 + - deps: serve-favicon@~2.1.7 + - deps: serve-static@~1.5.1 + - deps: type-is@~1.5.3 + * deps: etag@~1.5.1 + * deps: proxy-addr@~1.0.4 + - deps: ipaddr.js@0.1.5 + +3.18.3 / 2014-11-09 +=================== + + * deps: connect@2.27.3 + - Correctly invoke async callback asynchronously + - deps: csurf@~1.6.3 + +3.18.2 / 2014-10-28 +=================== + + * deps: connect@2.27.2 + - Fix handling of URLs containing `://` in the path + - deps: body-parser@~1.9.2 + - deps: qs@2.3.2 + +3.18.1 / 2014-10-22 +=================== + + * Fix internal `utils.merge` deprecation warnings + * deps: connect@2.27.1 + - deps: body-parser@~1.9.1 + - deps: express-session@~1.9.1 + - deps: finalhandler@0.3.2 + - deps: morgan@~1.4.1 + - deps: qs@2.3.0 + - deps: serve-static@~1.7.1 + * deps: send@0.10.1 + - deps: on-finished@~2.1.1 + +3.18.0 / 2014-10-17 +=================== + + * Use `content-disposition` module for `res.attachment`/`res.download` + - Sends standards-compliant `Content-Disposition` header + - Full Unicode support + * Use `etag` module to generate `ETag` headers + * deps: connect@2.27.0 + - Use `http-errors` module for creating errors + - Use `utils-merge` module for merging objects + - deps: body-parser@~1.9.0 + - deps: compression@~1.2.0 + - deps: connect-timeout@~1.4.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: express-session@~1.9.0 + - deps: finalhandler@0.3.1 + - deps: method-override@~2.3.0 + - deps: morgan@~1.4.0 + - deps: response-time@~2.2.0 + - deps: serve-favicon@~2.1.6 + - deps: serve-index@~1.5.0 + - deps: serve-static@~1.7.0 + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: send@0.10.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + +3.17.8 / 2014-10-15 +=================== + + * deps: connect@2.26.6 + - deps: compression@~1.1.2 + - deps: csurf@~1.6.2 + - deps: errorhandler@~1.2.2 + +3.17.7 / 2014-10-08 +=================== + + * deps: connect@2.26.5 + - Fix accepting non-object arguments to `logger` + - deps: serve-static@~1.6.4 + +3.17.6 / 2014-10-02 +=================== + + * deps: connect@2.26.4 + - deps: morgan@~1.3.2 + - deps: type-is@~1.5.2 + +3.17.5 / 2014-09-24 +=================== + + * deps: connect@2.26.3 + - deps: body-parser@~1.8.4 + - deps: serve-favicon@~2.1.5 + - deps: serve-static@~1.6.3 + * deps: proxy-addr@~1.0.3 + - Use `forwarded` npm module + * deps: send@0.9.3 + - deps: etag@~1.4.0 + +3.17.4 / 2014-09-19 +=================== + + * deps: connect@2.26.2 + - deps: body-parser@~1.8.3 + - deps: qs@2.2.4 + +3.17.3 / 2014-09-18 +=================== + + * deps: proxy-addr@~1.0.2 + - Fix a global leak when multiple subnets are trusted + - deps: ipaddr.js@0.1.3 + +3.17.2 / 2014-09-15 +=================== + + * Use `crc` instead of `buffer-crc32` for speed + * deps: connect@2.26.1 + - deps: body-parser@~1.8.2 + - deps: depd@0.4.5 + - deps: express-session@~1.8.2 + - deps: morgan@~1.3.1 + - deps: serve-favicon@~2.1.3 + - deps: serve-static@~1.6.2 + * deps: depd@0.4.5 + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + +3.17.1 / 2014-09-08 +=================== + + * Fix error in `req.subdomains` on empty host + +3.17.0 / 2014-09-08 +=================== + + * Support `X-Forwarded-Host` in `req.subdomains` + * Support IP address host in `req.subdomains` + * deps: connect@2.26.0 + - deps: body-parser@~1.8.1 + - deps: compression@~1.1.0 + - deps: connect-timeout@~1.3.0 + - deps: cookie-parser@~1.3.3 + - deps: cookie-signature@1.0.5 + - deps: csurf@~1.6.1 + - deps: debug@~2.0.0 + - deps: errorhandler@~1.2.0 + - deps: express-session@~1.8.1 + - deps: finalhandler@0.2.0 + - deps: fresh@0.2.4 + - deps: media-typer@0.3.0 + - deps: method-override@~2.2.0 + - deps: morgan@~1.3.0 + - deps: qs@2.2.3 + - deps: serve-favicon@~2.1.3 + - deps: serve-index@~1.2.1 + - deps: serve-static@~1.6.1 + - deps: type-is@~1.5.1 + - deps: vhost@~3.0.0 + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + * deps: fresh@0.2.4 + * deps: media-typer@0.3.0 + - Throw error when parameter format invalid on parse + * deps: range-parser@~1.0.2 + * deps: send@0.9.1 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + - deps: fresh@0.2.4 + * deps: vary@~1.0.0 + - Accept valid `Vary` header string as `field` + +3.16.10 / 2014-09-04 +==================== + + * deps: connect@2.25.10 + - deps: serve-static@~1.5.4 + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + +3.16.9 / 2014-08-29 +=================== + + * deps: connect@2.25.9 + - deps: body-parser@~1.6.7 + - deps: qs@2.2.2 + +3.16.8 / 2014-08-27 +=================== + + * deps: connect@2.25.8 + - deps: body-parser@~1.6.6 + - deps: csurf@~1.4.1 + - deps: qs@2.2.0 + +3.16.7 / 2014-08-18 +=================== + + * deps: connect@2.25.7 + - deps: body-parser@~1.6.5 + - deps: express-session@~1.7.6 + - deps: morgan@~1.2.3 + - deps: serve-static@~1.5.3 + * deps: send@0.8.3 + - deps: destroy@1.0.3 + - deps: on-finished@2.1.0 + +3.16.6 / 2014-08-14 +=================== + + * deps: connect@2.25.6 + - deps: body-parser@~1.6.4 + - deps: qs@1.2.2 + - deps: serve-static@~1.5.2 + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + +3.16.5 / 2014-08-11 +=================== + + * deps: connect@2.25.5 + - Fix backwards compatibility in `logger` + +3.16.4 / 2014-08-10 +=================== + + * Fix original URL parsing in `res.location` + * deps: connect@2.25.4 + - Fix `query` middleware breaking with argument + - deps: body-parser@~1.6.3 + - deps: compression@~1.0.11 + - deps: connect-timeout@~1.2.2 + - deps: express-session@~1.7.5 + - deps: method-override@~2.1.3 + - deps: on-headers@~1.0.0 + - deps: parseurl@~1.3.0 + - deps: qs@1.2.1 + - deps: response-time@~2.0.1 + - deps: serve-index@~1.1.6 + - deps: serve-static@~1.5.1 + * deps: parseurl@~1.3.0 + +3.16.3 / 2014-08-07 +=================== + + * deps: connect@2.25.3 + - deps: multiparty@3.3.2 + +3.16.2 / 2014-08-07 +=================== + + * deps: connect@2.25.2 + - deps: body-parser@~1.6.2 + - deps: qs@1.2.0 + +3.16.1 / 2014-08-06 +=================== + + * deps: connect@2.25.1 + - deps: body-parser@~1.6.1 + - deps: qs@1.1.0 + +3.16.0 / 2014-08-05 +=================== + + * deps: connect@2.25.0 + - deps: body-parser@~1.6.0 + - deps: compression@~1.0.10 + - deps: csurf@~1.4.0 + - deps: express-session@~1.7.4 + - deps: qs@1.0.2 + - deps: serve-static@~1.5.0 + * deps: send@0.8.1 + - Add `extensions` option + +3.15.3 / 2014-08-04 +=================== + + * fix `res.sendfile` regression for serving directory index files + * deps: connect@2.24.3 + - deps: serve-index@~1.1.5 + - deps: serve-static@~1.4.4 + * deps: send@0.7.4 + - Fix incorrect 403 on Windows and Node.js 0.11 + - Fix serving index files without root dir + +3.15.2 / 2014-07-27 +=================== + + * deps: connect@2.24.2 + - deps: body-parser@~1.5.2 + - deps: depd@0.4.4 + - deps: express-session@~1.7.2 + - deps: morgan@~1.2.2 + - deps: serve-static@~1.4.2 + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + * deps: send@0.7.2 + - deps: depd@0.4.4 + +3.15.1 / 2014-07-26 +=================== + + * deps: connect@2.24.1 + - deps: body-parser@~1.5.1 + - deps: depd@0.4.3 + - deps: express-session@~1.7.1 + - deps: morgan@~1.2.1 + - deps: serve-index@~1.1.4 + - deps: serve-static@~1.4.1 + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + * deps: send@0.7.1 + - deps: depd@0.4.3 + +3.15.0 / 2014-07-22 +=================== + + * Fix `req.protocol` for proxy-direct connections + * Pass options from `res.sendfile` to `send` + * deps: connect@2.24.0 + - deps: body-parser@~1.5.0 + - deps: compression@~1.0.9 + - deps: connect-timeout@~1.2.1 + - deps: debug@1.0.4 + - deps: depd@0.4.2 + - deps: express-session@~1.7.0 + - deps: finalhandler@0.1.0 + - deps: method-override@~2.1.2 + - deps: morgan@~1.2.0 + - deps: multiparty@3.3.1 + - deps: parseurl@~1.2.0 + - deps: serve-static@~1.4.0 + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - Cap `maxAge` value to 1 year + - deps: debug@1.0.4 + - deps: depd@0.4.2 + +3.14.0 / 2014-07-11 +=================== + + * add explicit "Rosetta Flash JSONP abuse" protection + - previous versions are not vulnerable; this is just explicit protection + * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead + * fix `res.send(status, num)` to send `num` as json (not error) + * remove unnecessary escaping when `res.jsonp` returns JSON response + * deps: basic-auth@1.0.0 + - support empty password + - support empty username + * deps: connect@2.23.0 + - deps: debug@1.0.3 + - deps: express-session@~1.6.4 + - deps: method-override@~2.1.0 + - deps: parseurl@~1.1.3 + - deps: serve-static@~1.3.1 + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + * deps: methods@1.1.0 + - add `CONNECT` + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + +3.13.0 / 2014-07-03 +=================== + + * add deprecation message to `app.configure` + * add deprecation message to `req.auth` + * use `basic-auth` to parse `Authorization` header + * deps: connect@2.22.0 + - deps: csurf@~1.3.0 + - deps: express-session@~1.6.1 + - deps: multiparty@3.3.0 + - deps: serve-static@~1.3.0 + * deps: send@0.5.0 + - Accept string for `maxage` (converted by `ms`) + - Include link in default redirect response + +3.12.1 / 2014-06-26 +=================== + + * deps: connect@2.21.1 + - deps: cookie-parser@1.3.2 + - deps: cookie-signature@1.0.4 + - deps: express-session@~1.5.2 + - deps: type-is@~1.3.2 + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +3.12.0 / 2014-06-21 +=================== + + * use `media-typer` to alter content-type charset + * deps: connect@2.21.0 + - deprecate `connect(middleware)` -- use `app.use(middleware)` instead + - deprecate `connect.createServer()` -- use `connect()` instead + - fix `res.setHeader()` patch to work with with get -> append -> set pattern + - deps: compression@~1.0.8 + - deps: errorhandler@~1.1.1 + - deps: express-session@~1.5.0 + - deps: serve-index@~1.1.3 + +3.11.0 / 2014-06-19 +=================== + + * deprecate things with `depd` module + * deps: buffer-crc32@0.2.3 + * deps: connect@2.20.2 + - deprecate `verify` option to `json` -- use `body-parser` npm module instead + - deprecate `verify` option to `urlencoded` -- use `body-parser` npm module instead + - deprecate things with `depd` module + - use `finalhandler` for final response handling + - use `media-typer` to parse `content-type` for charset + - deps: body-parser@1.4.3 + - deps: connect-timeout@1.1.1 + - deps: cookie-parser@1.3.1 + - deps: csurf@1.2.2 + - deps: errorhandler@1.1.0 + - deps: express-session@1.4.0 + - deps: multiparty@3.2.9 + - deps: serve-index@1.1.2 + - deps: type-is@1.3.1 + - deps: vhost@2.0.0 + +3.10.5 / 2014-06-11 +=================== + + * deps: connect@2.19.6 + - deps: body-parser@1.3.1 + - deps: compression@1.0.7 + - deps: debug@1.0.2 + - deps: serve-index@1.1.1 + - deps: serve-static@1.2.3 + * deps: debug@1.0.2 + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + +3.10.4 / 2014-06-09 +=================== + + * deps: connect@2.19.5 + - fix "event emitter leak" warnings + - deps: csurf@1.2.1 + - deps: debug@1.0.1 + - deps: serve-static@1.2.2 + - deps: type-is@1.2.1 + * deps: debug@1.0.1 + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: finished@1.2.1 + - deps: debug@1.0.1 + +3.10.3 / 2014-06-05 +=================== + + * use `vary` module for `res.vary` + * deps: connect@2.19.4 + - deps: errorhandler@1.0.2 + - deps: method-override@2.0.2 + - deps: serve-favicon@2.0.1 + * deps: debug@1.0.0 + +3.10.2 / 2014-06-03 +=================== + + * deps: connect@2.19.3 + - deps: compression@1.0.6 + +3.10.1 / 2014-06-03 +=================== + + * deps: connect@2.19.2 + - deps: compression@1.0.4 + * deps: proxy-addr@1.0.1 + +3.10.0 / 2014-06-02 +=================== + + * deps: connect@2.19.1 + - deprecate `methodOverride()` -- use `method-override` npm module instead + - deps: body-parser@1.3.0 + - deps: method-override@2.0.1 + - deps: multiparty@3.2.8 + - deps: response-time@2.0.0 + - deps: serve-static@1.2.1 + * deps: methods@1.0.1 + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + +3.9.0 / 2014-05-30 +================== + + * custom etag control with `app.set('etag', val)` + - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation + - `app.set('etag', 'weak')` weak tag + - `app.set('etag', 'strong')` strong etag + - `app.set('etag', false)` turn off + - `app.set('etag', true)` standard etag + * Include ETag in HEAD requests + * mark `res.send` ETag as weak and reduce collisions + * update connect to 2.18.0 + - deps: compression@1.0.3 + - deps: serve-index@1.1.0 + - deps: serve-static@1.2.0 + * update send to 0.4.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: debug@0.8.1 + +3.8.1 / 2014-05-27 +================== + + * update connect to 2.17.3 + - deps: body-parser@1.2.2 + - deps: express-session@1.2.1 + - deps: method-override@1.0.2 + +3.8.0 / 2014-05-21 +================== + + * keep previous `Content-Type` for `res.jsonp` + * set proper `charset` in `Content-Type` for `res.send` + * update connect to 2.17.1 + - fix `res.charset` appending charset when `content-type` has one + - deps: express-session@1.2.0 + - deps: morgan@1.1.1 + - deps: serve-index@1.0.3 + +3.7.0 / 2014-05-18 +================== + + * proper proxy trust with `app.set('trust proxy', trust)` + - `app.set('trust proxy', 1)` trust first hop + - `app.set('trust proxy', 'loopback')` trust loopback addresses + - `app.set('trust proxy', '10.0.0.1')` trust single IP + - `app.set('trust proxy', '10.0.0.1/16')` trust subnet + - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list + - `app.set('trust proxy', false)` turn off + - `app.set('trust proxy', true)` trust everything + * update connect to 2.16.2 + - deprecate `res.headerSent` -- use `res.headersSent` + - deprecate `res.on("header")` -- use on-headers module instead + - fix edge-case in `res.appendHeader` that would append in wrong order + - json: use body-parser + - urlencoded: use body-parser + - dep: bytes@1.0.0 + - dep: cookie-parser@1.1.0 + - dep: csurf@1.2.0 + - dep: express-session@1.1.0 + - dep: method-override@1.0.1 + +3.6.0 / 2014-05-09 +================== + + * deprecate `app.del()` -- use `app.delete()` instead + * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead + - the edge-case `res.json(status, num)` requires `res.status(status).json(num)` + * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead + - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)` + * support PURGE method + - add `app.purge` + - add `router.purge` + - include PURGE in `app.all` + * update connect to 2.15.0 + * Add `res.appendHeader` + * Call error stack even when response has been sent + * Patch `res.headerSent` to return Boolean + * Patch `res.headersSent` for node.js 0.8 + * Prevent default 404 handler after response sent + * dep: compression@1.0.2 + * dep: connect-timeout@1.1.0 + * dep: debug@^0.8.0 + * dep: errorhandler@1.0.1 + * dep: express-session@1.0.4 + * dep: morgan@1.0.1 + * dep: serve-favicon@2.0.0 + * dep: serve-index@1.0.2 + * update debug to 0.8.0 + * add `enable()` method + * change from stderr to stdout + * update methods to 1.0.0 + - add PURGE + * update mkdirp to 0.5.0 + +3.5.3 / 2014-05-08 +================== + + * fix `req.host` for IPv6 literals + * fix `res.jsonp` error if callback param is object + +3.5.2 / 2014-04-24 +================== + + * update connect to 2.14.5 + * update cookie to 0.1.2 + * update mkdirp to 0.4.0 + * update send to 0.3.0 + +3.5.1 / 2014-03-25 +================== + + * pin less-middleware in generated app + +3.5.0 / 2014-03-06 +================== + + * bump deps + +3.4.8 / 2014-01-13 +================== + + * prevent incorrect automatic OPTIONS responses #1868 @dpatti + * update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi + * throw 400 in case of malformed paths @rlidwka + +3.4.7 / 2013-12-10 +================== + + * update connect + +3.4.6 / 2013-12-01 +================== + + * update connect (raw-body) + +3.4.5 / 2013-11-27 +================== + + * update connect + * res.location: remove leading ./ #1802 @kapouer + * res.redirect: fix `res.redirect('toString') #1829 @michaelficarra + * res.send: always send ETag when content-length > 0 + * router: add Router.all() method + +3.4.4 / 2013-10-29 +================== + + * update connect + * update supertest + * update methods + * express(1): replace bodyParser() with urlencoded() and json() #1795 @chirag04 + +3.4.3 / 2013-10-23 +================== + + * update connect + +3.4.2 / 2013-10-18 +================== + + * update connect + * downgrade commander + +3.4.1 / 2013-10-15 +================== + + * update connect + * update commander + * jsonp: check if callback is a function + * router: wrap encodeURIComponent in a try/catch #1735 (@lxe) + * res.format: now includes charset @1747 (@sorribas) + * res.links: allow multiple calls @1746 (@sorribas) + +3.4.0 / 2013-09-07 +================== + + * add res.vary(). Closes #1682 + * update connect + +3.3.8 / 2013-09-02 +================== + + * update connect + +3.3.7 / 2013-08-28 +================== + + * update connect + +3.3.6 / 2013-08-27 +================== + + * Revert "remove charset from json responses. Closes #1631" (causes issues in some clients) + * add: req.accepts take an argument list + +3.3.4 / 2013-07-08 +================== + + * update send and connect + +3.3.3 / 2013-07-04 +================== + + * update connect + +3.3.2 / 2013-07-03 +================== + + * update connect + * update send + * remove .version export + +3.3.1 / 2013-06-27 +================== + + * update connect + +3.3.0 / 2013-06-26 +================== + + * update connect + * add support for multiple X-Forwarded-Proto values. Closes #1646 + * change: remove charset from json responses. Closes #1631 + * change: return actual booleans from req.accept* functions + * fix jsonp callback array throw + +3.2.6 / 2013-06-02 +================== + + * update connect + +3.2.5 / 2013-05-21 +================== + + * update connect + * update node-cookie + * add: throw a meaningful error when there is no default engine + * change generation of ETags with res.send() to GET requests only. Closes #1619 + +3.2.4 / 2013-05-09 +================== + + * fix `req.subdomains` when no Host is present + * fix `req.host` when no Host is present, return undefined + +3.2.3 / 2013-05-07 +================== + + * update connect / qs + +3.2.2 / 2013-05-03 +================== + + * update qs + +3.2.1 / 2013-04-29 +================== + + * add app.VERB() paths array deprecation warning + * update connect + * update qs and remove all ~ semver crap + * fix: accept number as value of Signed Cookie + +3.2.0 / 2013-04-15 +================== + + * add "view" constructor setting to override view behaviour + * add req.acceptsEncoding(name) + * add req.acceptedEncodings + * revert cookie signature change causing session race conditions + * fix sorting of Accept values of the same quality + +3.1.2 / 2013-04-12 +================== + + * add support for custom Accept parameters + * update cookie-signature + +3.1.1 / 2013-04-01 +================== + + * add X-Forwarded-Host support to `req.host` + * fix relative redirects + * update mkdirp + * update buffer-crc32 + * remove legacy app.configure() method from app template. + +3.1.0 / 2013-01-25 +================== + + * add support for leading "." in "view engine" setting + * add array support to `res.set()` + * add node 0.8.x to travis.yml + * add "subdomain offset" setting for tweaking `req.subdomains` + * add `res.location(url)` implementing `res.redirect()`-like setting of Location + * use app.get() for x-powered-by setting for inheritance + * fix colons in passwords for `req.auth` + +3.0.6 / 2013-01-04 +================== + + * add http verb methods to Router + * update connect + * fix mangling of the `res.cookie()` options object + * fix jsonp whitespace escape. Closes #1132 + +3.0.5 / 2012-12-19 +================== + + * add throwing when a non-function is passed to a route + * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses + * revert "add 'etag' option" + +3.0.4 / 2012-12-05 +================== + + * add 'etag' option to disable `res.send()` Etags + * add escaping of urls in text/plain in `res.redirect()` + for old browsers interpreting as html + * change crc32 module for a more liberal license + * update connect + +3.0.3 / 2012-11-13 +================== + + * update connect + * update cookie module + * fix cookie max-age + +3.0.2 / 2012-11-08 +================== + + * add OPTIONS to cors example. Closes #1398 + * fix route chaining regression. Closes #1397 + +3.0.1 / 2012-11-01 +================== + + * update connect + +3.0.0 / 2012-10-23 +================== + + * add `make clean` + * add "Basic" check to req.auth + * add `req.auth` test coverage + * add cb && cb(payload) to `res.jsonp()`. Closes #1374 + * add backwards compat for `res.redirect()` status. Closes #1336 + * add support for `res.json()` to retain previously defined Content-Types. Closes #1349 + * update connect + * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382 + * remove non-primitive string support for `res.send()` + * fix view-locals example. Closes #1370 + * fix route-separation example + +3.0.0rc5 / 2012-09-18 +================== + + * update connect + * add redis search example + * add static-files example + * add "x-powered-by" setting (`app.disable('x-powered-by')`) + * add "application/octet-stream" redirect Accept test case. Closes #1317 + +3.0.0rc4 / 2012-08-30 +================== + + * add `res.jsonp()`. Closes #1307 + * add "verbose errors" option to error-pages example + * add another route example to express(1) so people are not so confused + * add redis online user activity tracking example + * update connect dep + * fix etag quoting. Closes #1310 + * fix error-pages 404 status + * fix jsonp callback char restrictions + * remove old OPTIONS default response + +3.0.0rc3 / 2012-08-13 +================== + + * update connect dep + * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds] + * fix `res.render()` clobbering of "locals" + +3.0.0rc2 / 2012-08-03 +================== + + * add CORS example + * update connect dep + * deprecate `.createServer()` & remove old stale examples + * fix: escape `res.redirect()` link + * fix vhost example + +3.0.0rc1 / 2012-07-24 +================== + + * add more examples to view-locals + * add scheme-relative redirects (`res.redirect("//foo.com")`) support + * update cookie dep + * update connect dep + * update send dep + * fix `express(1)` -h flag, use -H for hogan. Closes #1245 + * fix `res.sendfile()` socket error handling regression + +3.0.0beta7 / 2012-07-16 +================== + + * update connect dep for `send()` root normalization regression + +3.0.0beta6 / 2012-07-13 +================== + + * add `err.view` property for view errors. Closes #1226 + * add "jsonp callback name" setting + * add support for "/foo/:bar*" non-greedy matches + * change `res.sendfile()` to use `send()` module + * change `res.send` to use "response-send" module + * remove `app.locals.use` and `res.locals.use`, use regular middleware + +3.0.0beta5 / 2012-07-03 +================== + + * add "make check" support + * add route-map example + * add `res.json(obj, status)` support back for BC + * add "methods" dep, remove internal methods module + * update connect dep + * update auth example to utilize cores pbkdf2 + * updated tests to use "supertest" + +3.0.0beta4 / 2012-06-25 +================== + + * Added `req.auth` + * Added `req.range(size)` + * Added `res.links(obj)` + * Added `res.send(body, status)` support back for backwards compat + * Added `.default()` support to `res.format()` + * Added 2xx / 304 check to `req.fresh` + * Revert "Added + support to the router" + * Fixed `res.send()` freshness check, respect res.statusCode + +3.0.0beta3 / 2012-06-15 +================== + + * Added hogan `--hjs` to express(1) [nullfirm] + * Added another example to content-negotiation + * Added `fresh` dep + * Changed: `res.send()` always checks freshness + * Fixed: expose connects mime module. Closes #1165 + +3.0.0beta2 / 2012-06-06 +================== + + * Added `+` support to the router + * Added `req.host` + * Changed `req.param()` to check route first + * Update connect dep + +3.0.0beta1 / 2012-06-01 +================== + + * Added `res.format()` callback to override default 406 behaviour + * Fixed `res.redirect()` 406. Closes #1154 + +3.0.0alpha5 / 2012-05-30 +================== + + * Added `req.ip` + * Added `{ signed: true }` option to `res.cookie()` + * Removed `res.signedCookie()` + * Changed: dont reverse `req.ips` + * Fixed "trust proxy" setting check for `req.ips` + +3.0.0alpha4 / 2012-05-09 +================== + + * Added: allow `[]` in jsonp callback. Closes #1128 + * Added `PORT` env var support in generated template. Closes #1118 [benatkin] + * Updated: connect 2.2.2 + +3.0.0alpha3 / 2012-05-04 +================== + + * Added public `app.routes`. Closes #887 + * Added _view-locals_ example + * Added _mvc_ example + * Added `res.locals.use()`. Closes #1120 + * Added conditional-GET support to `res.send()` + * Added: coerce `res.set()` values to strings + * Changed: moved `static()` in generated apps below router + * Changed: `res.send()` only set ETag when not previously set + * Changed connect 2.2.1 dep + * Changed: `make test` now runs unit / acceptance tests + * Fixed req/res proto inheritance + +3.0.0alpha2 / 2012-04-26 +================== + + * Added `make benchmark` back + * Added `res.send()` support for `String` objects + * Added client-side data exposing example + * Added `res.header()` and `req.header()` aliases for BC + * Added `express.createServer()` for BC + * Perf: memoize parsed urls + * Perf: connect 2.2.0 dep + * Changed: make `expressInit()` middleware self-aware + * Fixed: use app.get() for all core settings + * Fixed redis session example + * Fixed session example. Closes #1105 + * Fixed generated express dep. Closes #1078 + +3.0.0alpha1 / 2012-04-15 +================== + + * Added `app.locals.use(callback)` + * Added `app.locals` object + * Added `app.locals(obj)` + * Added `res.locals` object + * Added `res.locals(obj)` + * Added `res.format()` for content-negotiation + * Added `app.engine()` + * Added `res.cookie()` JSON cookie support + * Added "trust proxy" setting + * Added `req.subdomains` + * Added `req.protocol` + * Added `req.secure` + * Added `req.path` + * Added `req.ips` + * Added `req.fresh` + * Added `req.stale` + * Added comma-delimited / array support for `req.accepts()` + * Added debug instrumentation + * Added `res.set(obj)` + * Added `res.set(field, value)` + * Added `res.get(field)` + * Added `app.get(setting)`. Closes #842 + * Added `req.acceptsLanguage()` + * Added `req.acceptsCharset()` + * Added `req.accepted` + * Added `req.acceptedLanguages` + * Added `req.acceptedCharsets` + * Added "json replacer" setting + * Added "json spaces" setting + * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92 + * Added `--less` support to express(1) + * Added `express.response` prototype + * Added `express.request` prototype + * Added `express.application` prototype + * Added `app.path()` + * Added `app.render()` + * Added `res.type()` to replace `res.contentType()` + * Changed: `res.redirect()` to add relative support + * Changed: enable "jsonp callback" by default + * Changed: renamed "case sensitive routes" to "case sensitive routing" + * Rewrite of all tests with mocha + * Removed "root" setting + * Removed `res.redirect('home')` support + * Removed `req.notify()` + * Removed `app.register()` + * Removed `app.redirect()` + * Removed `app.is()` + * Removed `app.helpers()` + * Removed `app.dynamicHelpers()` + * Fixed `res.sendfile()` with non-GET. Closes #723 + * Fixed express(1) public dir for windows. Closes #866 + +2.5.9/ 2012-04-02 +================== + + * Added support for PURGE request method [pbuyle] + * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki] + +2.5.8 / 2012-02-08 +================== + + * Update mkdirp dep. Closes #991 + +2.5.7 / 2012-02-06 +================== + + * Fixed `app.all` duplicate DELETE requests [mscdex] + +2.5.6 / 2012-01-13 +================== + + * Updated hamljs dev dep. Closes #953 + +2.5.5 / 2012-01-08 +================== + + * Fixed: set `filename` on cached templates [matthewleon] + +2.5.4 / 2012-01-02 +================== + + * Fixed `express(1)` eol on 0.4.x. Closes #947 + +2.5.3 / 2011-12-30 +================== + + * Fixed `req.is()` when a charset is present + +2.5.2 / 2011-12-10 +================== + + * Fixed: express(1) LF -> CRLF for windows + +2.5.1 / 2011-11-17 +================== + + * Changed: updated connect to 1.8.x + * Removed sass.js support from express(1) + +2.5.0 / 2011-10-24 +================== + + * Added ./routes dir for generated app by default + * Added npm install reminder to express(1) app gen + * Added 0.5.x support + * Removed `make test-cov` since it wont work with node 0.5.x + * Fixed express(1) public dir for windows. Closes #866 + +2.4.7 / 2011-10-05 +================== + + * Added mkdirp to express(1). Closes #795 + * Added simple _json-config_ example + * Added shorthand for the parsed request's pathname via `req.path` + * Changed connect dep to 1.7.x to fix npm issue... + * Fixed `res.redirect()` __HEAD__ support. [reported by xerox] + * Fixed `req.flash()`, only escape args + * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] + +2.4.6 / 2011-08-22 +================== + + * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] + +2.4.5 / 2011-08-19 +================== + + * Added support for routes to handle errors. Closes #809 + * Added `app.routes.all()`. Closes #803 + * Added "basepath" setting to work in conjunction with reverse proxies etc. + * Refactored `Route` to use a single array of callbacks + * Added support for multiple callbacks for `app.param()`. Closes #801 +Closes #805 + * Changed: removed .call(self) for route callbacks + * Dependency: `qs >= 0.3.1` + * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808 + +2.4.4 / 2011-08-05 +================== + + * Fixed `res.header()` intention of a set, even when `undefined` + * Fixed `*`, value no longer required + * Fixed `res.send(204)` support. Closes #771 + +2.4.3 / 2011-07-14 +================== + + * Added docs for `status` option special-case. Closes #739 + * Fixed `options.filename`, exposing the view path to template engines + +2.4.2. / 2011-07-06 +================== + + * Revert "removed jsonp stripping" for XSS + +2.4.1 / 2011-07-06 +================== + + * Added `res.json()` JSONP support. Closes #737 + * Added _extending-templates_ example. Closes #730 + * Added "strict routing" setting for trailing slashes + * Added support for multiple envs in `app.configure()` calls. Closes #735 + * Changed: `res.send()` using `res.json()` + * Changed: when cookie `path === null` don't default it + * Changed; default cookie path to "home" setting. Closes #731 + * Removed _pids/logs_ creation from express(1) + +2.4.0 / 2011-06-28 +================== + + * Added chainable `res.status(code)` + * Added `res.json()`, an explicit version of `res.send(obj)` + * Added simple web-service example + +2.3.12 / 2011-06-22 +================== + + * \#express is now on freenode! come join! + * Added `req.get(field, param)` + * Added links to Japanese documentation, thanks @hideyukisaito! + * Added; the `express(1)` generated app outputs the env + * Added `content-negotiation` example + * Dependency: connect >= 1.5.1 < 2.0.0 + * Fixed view layout bug. Closes #720 + * Fixed; ignore body on 304. Closes #701 + +2.3.11 / 2011-06-04 +================== + + * Added `npm test` + * Removed generation of dummy test file from `express(1)` + * Fixed; `express(1)` adds express as a dep + * Fixed; prune on `prepublish` + +2.3.10 / 2011-05-27 +================== + + * Added `req.route`, exposing the current route + * Added _package.json_ generation support to `express(1)` + * Fixed call to `app.param()` function for optional params. Closes #682 + +2.3.9 / 2011-05-25 +================== + + * Fixed bug-ish with `../' in `res.partial()` calls + +2.3.8 / 2011-05-24 +================== + + * Fixed `app.options()` + +2.3.7 / 2011-05-23 +================== + + * Added route `Collection`, ex: `app.get('/user/:id').remove();` + * Added support for `app.param(fn)` to define param logic + * Removed `app.param()` support for callback with return value + * Removed module.parent check from express(1) generated app. Closes #670 + * Refactored router. Closes #639 + +2.3.6 / 2011-05-20 +================== + + * Changed; using devDependencies instead of git submodules + * Fixed redis session example + * Fixed markdown example + * Fixed view caching, should not be enabled in development + +2.3.5 / 2011-05-20 +================== + + * Added export `.view` as alias for `.View` + +2.3.4 / 2011-05-08 +================== + + * Added `./examples/say` + * Fixed `res.sendfile()` bug preventing the transfer of files with spaces + +2.3.3 / 2011-05-03 +================== + + * Added "case sensitive routes" option. + * Changed; split methods supported per rfc [slaskis] + * Fixed route-specific middleware when using the same callback function several times + +2.3.2 / 2011-04-27 +================== + + * Fixed view hints + +2.3.1 / 2011-04-26 +================== + + * Added `app.match()` as `app.match.all()` + * Added `app.lookup()` as `app.lookup.all()` + * Added `app.remove()` for `app.remove.all()` + * Added `app.remove.VERB()` + * Fixed template caching collision issue. Closes #644 + * Moved router over from connect and started refactor + +2.3.0 / 2011-04-25 +================== + + * Added options support to `res.clearCookie()` + * Added `res.helpers()` as alias of `res.locals()` + * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0` + * Changed; auto set Content-Type in res.attachement [Aaron Heckmann] + * Renamed "cache views" to "view cache". Closes #628 + * Fixed caching of views when using several apps. Closes #637 + * Fixed gotcha invoking `app.param()` callbacks once per route middleware. +Closes #638 + * Fixed partial lookup precedence. Closes #631 +Shaw] + +2.2.2 / 2011-04-12 +================== + + * Added second callback support for `res.download()` connection errors + * Fixed `filename` option passing to template engine + +2.2.1 / 2011-04-04 +================== + + * Added `layout(path)` helper to change the layout within a view. Closes #610 + * Fixed `partial()` collection object support. + Previously only anything with `.length` would work. + When `.length` is present one must still be aware of holes, + however now `{ collection: {foo: 'bar'}}` is valid, exposes + `keyInCollection` and `keysInCollection`. + + * Performance improved with better view caching + * Removed `request` and `response` locals + * Changed; errorHandler page title is now `Express` instead of `Connect` + +2.2.0 / 2011-03-30 +================== + + * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606 + * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606 + * Added `app.VERB(path)` as alias of `app.lookup.VERB()`. + * Dependency `connect >= 1.2.0` + +2.1.1 / 2011-03-29 +================== + + * Added; expose `err.view` object when failing to locate a view + * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann] + * Fixed; `res.send(undefined)` responds with 204 [aheckmann] + +2.1.0 / 2011-03-24 +================== + + * Added `/_?` partial lookup support. Closes #447 + * Added `request`, `response`, and `app` local variables + * Added `settings` local variable, containing the app's settings + * Added `req.flash()` exception if `req.session` is not available + * Added `res.send(bool)` support (json response) + * Fixed stylus example for latest version + * Fixed; wrap try/catch around `res.render()` + +2.0.0 / 2011-03-17 +================== + + * Fixed up index view path alternative. + * Changed; `res.locals()` without object returns the locals + +2.0.0rc3 / 2011-03-17 +================== + + * Added `res.locals(obj)` to compliment `res.local(key, val)` + * Added `res.partial()` callback support + * Fixed recursive error reporting issue in `res.render()` + +2.0.0rc2 / 2011-03-17 +================== + + * Changed; `partial()` "locals" are now optional + * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01] + * Fixed .filename view engine option [reported by drudge] + * Fixed blog example + * Fixed `{req,res}.app` reference when mounting [Ben Weaver] + +2.0.0rc / 2011-03-14 +================== + + * Fixed; expose `HTTPSServer` constructor + * Fixed express(1) default test charset. Closes #579 [reported by secoif] + * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP] + +2.0.0beta3 / 2011-03-09 +================== + + * Added support for `res.contentType()` literal + The original `res.contentType('.json')`, + `res.contentType('application/json')`, and `res.contentType('json')` + will work now. + * Added `res.render()` status option support back + * Added charset option for `res.render()` + * Added `.charset` support (via connect 1.0.4) + * Added view resolution hints when in development and a lookup fails + * Added layout lookup support relative to the page view. + For example while rendering `./views/user/index.jade` if you create + `./views/user/layout.jade` it will be used in favour of the root layout. + * Fixed `res.redirect()`. RFC states absolute url [reported by unlink] + * Fixed; default `res.send()` string charset to utf8 + * Removed `Partial` constructor (not currently used) + +2.0.0beta2 / 2011-03-07 +================== + + * Added res.render() `.locals` support back to aid in migration process + * Fixed flash example + +2.0.0beta / 2011-03-03 +================== + + * Added HTTPS support + * Added `res.cookie()` maxAge support + * Added `req.header()` _Referrer_ / _Referer_ special-case, either works + * Added mount support for `res.redirect()`, now respects the mount-point + * Added `union()` util, taking place of `merge(clone())` combo + * Added stylus support to express(1) generated app + * Added secret to session middleware used in examples and generated app + * Added `res.local(name, val)` for progressive view locals + * Added default param support to `req.param(name, default)` + * Added `app.disabled()` and `app.enabled()` + * Added `app.register()` support for omitting leading ".", either works + * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539 + * Added `app.param()` to map route params to async/sync logic + * Added; aliased `app.helpers()` as `app.locals()`. Closes #481 + * Added extname with no leading "." support to `res.contentType()` + * Added `cache views` setting, defaulting to enabled in "production" env + * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_. + * Added `req.accepts()` support for extensions + * Changed; `res.download()` and `res.sendfile()` now utilize Connect's + static file server `connect.static.send()`. + * Changed; replaced `connect.utils.mime()` with npm _mime_ module + * Changed; allow `req.query` to be pre-defined (via middleware or other parent + * Changed view partial resolution, now relative to parent view + * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`. + * Fixed `req.param()` bug returning Array.prototype methods. Closes #552 + * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()` + * Fixed; using _qs_ module instead of _querystring_ + * Fixed; strip unsafe chars from jsonp callbacks + * Removed "stream threshold" setting + +1.0.8 / 2011-03-01 +================== + + * Allow `req.query` to be pre-defined (via middleware or other parent app) + * "connect": ">= 0.5.0 < 1.0.0". Closes #547 + * Removed the long deprecated __EXPRESS_ENV__ support + +1.0.7 / 2011-02-07 +================== + + * Fixed `render()` setting inheritance. + Mounted apps would not inherit "view engine" + +1.0.6 / 2011-02-07 +================== + + * Fixed `view engine` setting bug when period is in dirname + +1.0.5 / 2011-02-05 +================== + + * Added secret to generated app `session()` call + +1.0.4 / 2011-02-05 +================== + + * Added `qs` dependency to _package.json_ + * Fixed namespaced `require()`s for latest connect support + +1.0.3 / 2011-01-13 +================== + + * Remove unsafe characters from JSONP callback names [Ryan Grove] + +1.0.2 / 2011-01-10 +================== + + * Removed nested require, using `connect.router` + +1.0.1 / 2010-12-29 +================== + + * Fixed for middleware stacked via `createServer()` + previously the `foo` middleware passed to `createServer(foo)` + would not have access to Express methods such as `res.send()` + or props like `req.query` etc. + +1.0.0 / 2010-11-16 +================== + + * Added; deduce partial object names from the last segment. + For example by default `partial('forum/post', postObject)` will + give you the _post_ object, providing a meaningful default. + * Added http status code string representation to `res.redirect()` body + * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__. + * Added `req.is()` to aid in content negotiation + * Added partial local inheritance [suggested by masylum]. Closes #102 + providing access to parent template locals. + * Added _-s, --session[s]_ flag to express(1) to add session related middleware + * Added _--template_ flag to express(1) to specify the + template engine to use. + * Added _--css_ flag to express(1) to specify the + stylesheet engine to use (or just plain css by default). + * Added `app.all()` support [thanks aheckmann] + * Added partial direct object support. + You may now `partial('user', user)` providing the "user" local, + vs previously `partial('user', { object: user })`. + * Added _route-separation_ example since many people question ways + to do this with CommonJS modules. Also view the _blog_ example for + an alternative. + * Performance; caching view path derived partial object names + * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454 + * Fixed jsonp support; _text/javascript_ as per mailinglist discussion + +1.0.0rc4 / 2010-10-14 +================== + + * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0 + * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware)) + * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass] + * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass] + * Added `partial()` support for array-like collections. Closes #434 + * Added support for swappable querystring parsers + * Added session usage docs. Closes #443 + * Added dynamic helper caching. Closes #439 [suggested by maritz] + * Added authentication example + * Added basic Range support to `res.sendfile()` (and `res.download()` etc) + * Changed; `express(1)` generated app using 2 spaces instead of 4 + * Default env to "development" again [aheckmann] + * Removed _context_ option is no more, use "scope" + * Fixed; exposing _./support_ libs to examples so they can run without installs + * Fixed mvc example + +1.0.0rc3 / 2010-09-20 +================== + + * Added confirmation for `express(1)` app generation. Closes #391 + * Added extending of flash formatters via `app.flashFormatters` + * Added flash formatter support. Closes #411 + * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold" + * Added _stream threshold_ setting for `res.sendfile()` + * Added `res.send()` __HEAD__ support + * Added `res.clearCookie()` + * Added `res.cookie()` + * Added `res.render()` headers option + * Added `res.redirect()` response bodies + * Added `res.render()` status option support. Closes #425 [thanks aheckmann] + * Fixed `res.sendfile()` responding with 403 on malicious path + * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_ + * Fixed; mounted apps settings now inherit from parent app [aheckmann] + * Fixed; stripping Content-Length / Content-Type when 204 + * Fixed `res.send()` 204. Closes #419 + * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402 + * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo] + + +1.0.0rc2 / 2010-08-17 +================== + + * Added `app.register()` for template engine mapping. Closes #390 + * Added `res.render()` callback support as second argument (no options) + * Added callback support to `res.download()` + * Added callback support for `res.sendfile()` + * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()` + * Added "partials" setting to docs + * Added default expresso tests to `express(1)` generated app. Closes #384 + * Fixed `res.sendfile()` error handling, defer via `next()` + * Fixed `res.render()` callback when a layout is used [thanks guillermo] + * Fixed; `make install` creating ~/.node_libraries when not present + * Fixed issue preventing error handlers from being defined anywhere. Closes #387 + +1.0.0rc / 2010-07-28 +================== + + * Added mounted hook. Closes #369 + * Added connect dependency to _package.json_ + + * Removed "reload views" setting and support code + development env never caches, production always caches. + + * Removed _param_ in route callbacks, signature is now + simply (req, res, next), previously (req, res, params, next). + Use _req.params_ for path captures, _req.query_ for GET params. + + * Fixed "home" setting + * Fixed middleware/router precedence issue. Closes #366 + * Fixed; _configure()_ callbacks called immediately. Closes #368 + +1.0.0beta2 / 2010-07-23 +================== + + * Added more examples + * Added; exporting `Server` constructor + * Added `Server#helpers()` for view locals + * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349 + * Added support for absolute view paths + * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363 + * Added Guillermo Rauch to the contributor list + * Added support for "as" for non-collection partials. Closes #341 + * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf] + * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo] + * Fixed instanceof `Array` checks, now `Array.isArray()` + * Fixed express(1) expansion of public dirs. Closes #348 + * Fixed middleware precedence. Closes #345 + * Fixed view watcher, now async [thanks aheckmann] + +1.0.0beta / 2010-07-15 +================== + + * Re-write + - much faster + - much lighter + - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs + +0.14.0 / 2010-06-15 +================== + + * Utilize relative requires + * Added Static bufferSize option [aheckmann] + * Fixed caching of view and partial subdirectories [aheckmann] + * Fixed mime.type() comments now that ".ext" is not supported + * Updated haml submodule + * Updated class submodule + * Removed bin/express + +0.13.0 / 2010-06-01 +================== + + * Added node v0.1.97 compatibility + * Added support for deleting cookies via Request#cookie('key', null) + * Updated haml submodule + * Fixed not-found page, now using using charset utf-8 + * Fixed show-exceptions page, now using using charset utf-8 + * Fixed view support due to fs.readFile Buffers + * Changed; mime.type() no longer accepts ".type" due to node extname() changes + +0.12.0 / 2010-05-22 +================== + + * Added node v0.1.96 compatibility + * Added view `helpers` export which act as additional local variables + * Updated haml submodule + * Changed ETag; removed inode, modified time only + * Fixed LF to CRLF for setting multiple cookies + * Fixed cookie complation; values are now urlencoded + * Fixed cookies parsing; accepts quoted values and url escaped cookies + +0.11.0 / 2010-05-06 +================== + + * Added support for layouts using different engines + - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' }) + - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml' + - this.render('page.html.haml', { layout: false }) // no layout + * Updated ext submodule + * Updated haml submodule + * Fixed EJS partial support by passing along the context. Issue #307 + +0.10.1 / 2010-05-03 +================== + + * Fixed binary uploads. + +0.10.0 / 2010-04-30 +================== + + * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s + encoding is set to 'utf8' or 'utf-8'. + * Added "encoding" option to Request#render(). Closes #299 + * Added "dump exceptions" setting, which is enabled by default. + * Added simple ejs template engine support + * Added error response support for text/plain, application/json. Closes #297 + * Added callback function param to Request#error() + * Added Request#sendHead() + * Added Request#stream() + * Added support for Request#respond(304, null) for empty response bodies + * Added ETag support to Request#sendfile() + * Added options to Request#sendfile(), passed to fs.createReadStream() + * Added filename arg to Request#download() + * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request + * Performance enhanced by preventing several calls to toLowerCase() in Router#match() + * Changed; Request#sendfile() now streams + * Changed; Renamed Request#halt() to Request#respond(). Closes #289 + * Changed; Using sys.inspect() instead of JSON.encode() for error output + * Changed; run() returns the http.Server instance. Closes #298 + * Changed; Defaulting Server#host to null (INADDR_ANY) + * Changed; Logger "common" format scale of 0.4f + * Removed Logger "request" format + * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found + * Fixed several issues with http client + * Fixed Logger Content-Length output + * Fixed bug preventing Opera from retaining the generated session id. Closes #292 + +0.9.0 / 2010-04-14 +================== + + * Added DSL level error() route support + * Added DSL level notFound() route support + * Added Request#error() + * Added Request#notFound() + * Added Request#render() callback function. Closes #258 + * Added "max upload size" setting + * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254 + * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js + * Added callback function support to Request#halt() as 3rd/4th arg + * Added preprocessing of route param wildcards using param(). Closes #251 + * Added view partial support (with collections etc) + * Fixed bug preventing falsey params (such as ?page=0). Closes #286 + * Fixed setting of multiple cookies. Closes #199 + * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml) + * Changed; session cookie is now httpOnly + * Changed; Request is no longer global + * Changed; Event is no longer global + * Changed; "sys" module is no longer global + * Changed; moved Request#download to Static plugin where it belongs + * Changed; Request instance created before body parsing. Closes #262 + * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253 + * Changed; Pre-caching view partials in memory when "cache view partials" is enabled + * Updated support to node --version 0.1.90 + * Updated dependencies + * Removed set("session cookie") in favour of use(Session, { cookie: { ... }}) + * Removed utils.mixin(); use Object#mergeDeep() + +0.8.0 / 2010-03-19 +================== + + * Added coffeescript example app. Closes #242 + * Changed; cache api now async friendly. Closes #240 + * Removed deprecated 'express/static' support. Use 'express/plugins/static' + +0.7.6 / 2010-03-19 +================== + + * Added Request#isXHR. Closes #229 + * Added `make install` (for the executable) + * Added `express` executable for setting up simple app templates + * Added "GET /public/*" to Static plugin, defaulting to /public + * Added Static plugin + * Fixed; Request#render() only calls cache.get() once + * Fixed; Namespacing View caches with "view:" + * Fixed; Namespacing Static caches with "static:" + * Fixed; Both example apps now use the Static plugin + * Fixed set("views"). Closes #239 + * Fixed missing space for combined log format + * Deprecated Request#sendfile() and 'express/static' + * Removed Server#running + +0.7.5 / 2010-03-16 +================== + + * Added Request#flash() support without args, now returns all flashes + * Updated ext submodule + +0.7.4 / 2010-03-16 +================== + + * Fixed session reaper + * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft) + +0.7.3 / 2010-03-16 +================== + + * Added package.json + * Fixed requiring of haml / sass due to kiwi removal + +0.7.2 / 2010-03-16 +================== + + * Fixed GIT submodules (HAH!) + +0.7.1 / 2010-03-16 +================== + + * Changed; Express now using submodules again until a PM is adopted + * Changed; chat example using millisecond conversions from ext + +0.7.0 / 2010-03-15 +================== + + * Added Request#pass() support (finds the next matching route, or the given path) + * Added Logger plugin (default "common" format replaces CommonLogger) + * Removed Profiler plugin + * Removed CommonLogger plugin + +0.6.0 / 2010-03-11 +================== + + * Added seed.yml for kiwi package management support + * Added HTTP client query string support when method is GET. Closes #205 + + * Added support for arbitrary view engines. + For example "foo.engine.html" will now require('engine'), + the exports from this module are cached after the first require(). + + * Added async plugin support + + * Removed usage of RESTful route funcs as http client + get() etc, use http.get() and friends + + * Removed custom exceptions + +0.5.0 / 2010-03-10 +================== + + * Added ext dependency (library of js extensions) + * Removed extname() / basename() utils. Use path module + * Removed toArray() util. Use arguments.values + * Removed escapeRegexp() util. Use RegExp.escape() + * Removed process.mixin() dependency. Use utils.mixin() + * Removed Collection + * Removed ElementCollection + * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;) + +0.4.0 / 2010-02-11 +================== + + * Added flash() example to sample upload app + * Added high level restful http client module (express/http) + * Changed; RESTful route functions double as HTTP clients. Closes #69 + * Changed; throwing error when routes are added at runtime + * Changed; defaulting render() context to the current Request. Closes #197 + * Updated haml submodule + +0.3.0 / 2010-02-11 +================== + + * Updated haml / sass submodules. Closes #200 + * Added flash message support. Closes #64 + * Added accepts() now allows multiple args. fixes #117 + * Added support for plugins to halt. Closes #189 + * Added alternate layout support. Closes #119 + * Removed Route#run(). Closes #188 + * Fixed broken specs due to use(Cookie) missing + +0.2.1 / 2010-02-05 +================== + + * Added "plot" format option for Profiler (for gnuplot processing) + * Added request number to Profiler plugin + * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8 + * Fixed issue with routes not firing when not files are present. Closes #184 + * Fixed process.Promise -> events.Promise + +0.2.0 / 2010-02-03 +================== + + * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180 + * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174 + * Added expiration support to cache api with reaper. Closes #133 + * Added cache Store.Memory#reap() + * Added Cache; cache api now uses first class Cache instances + * Added abstract session Store. Closes #172 + * Changed; cache Memory.Store#get() utilizing Collection + * Renamed MemoryStore -> Store.Memory + * Fixed use() of the same plugin several time will always use latest options. Closes #176 + +0.1.0 / 2010-02-03 +================== + + * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context + * Updated node support to 0.1.27 Closes #169 + * Updated dirname(__filename) -> __dirname + * Updated libxmljs support to v0.2.0 + * Added session support with memory store / reaping + * Added quick uid() helper + * Added multi-part upload support + * Added Sass.js support / submodule + * Added production env caching view contents and static files + * Added static file caching. Closes #136 + * Added cache plugin with memory stores + * Added support to StaticFile so that it works with non-textual files. + * Removed dirname() helper + * Removed several globals (now their modules must be required) + +0.0.2 / 2010-01-10 +================== + + * Added view benchmarks; currently haml vs ejs + * Added Request#attachment() specs. Closes #116 + * Added use of node's parseQuery() util. Closes #123 + * Added `make init` for submodules + * Updated Haml + * Updated sample chat app to show messages on load + * Updated libxmljs parseString -> parseHtmlString + * Fixed `make init` to work with older versions of git + * Fixed specs can now run independent specs for those who cant build deps. Closes #127 + * Fixed issues introduced by the node url module changes. Closes 126. + * Fixed two assertions failing due to Collection#keys() returning strings + * Fixed faulty Collection#toArray() spec due to keys() returning strings + * Fixed `make test` now builds libxmljs.node before testing + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/express/LICENSE b/hm_sunwell/node_modules/express/LICENSE new file mode 100644 index 0000000..aa927e4 --- /dev/null +++ b/hm_sunwell/node_modules/express/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2009-2014 TJ Holowaychuk +Copyright (c) 2013-2014 Roman Shtylman +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/express/Readme.md b/hm_sunwell/node_modules/express/Readme.md new file mode 100644 index 0000000..e9bfaeb --- /dev/null +++ b/hm_sunwell/node_modules/express/Readme.md @@ -0,0 +1,142 @@ +[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) + + Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). + + [![NPM Version][npm-image]][npm-url] + [![NPM Downloads][downloads-image]][downloads-url] + [![Linux Build][travis-image]][travis-url] + [![Windows Build][appveyor-image]][appveyor-url] + [![Test Coverage][coveralls-image]][coveralls-url] + +```js +var express = require('express') +var app = express() + +app.get('/', function (req, res) { + res.send('Hello World') +}) + +app.listen(3000) +``` + +## Installation + +```bash +$ npm install express +``` + +## Features + + * Robust routing + * Focus on high performance + * Super-high test coverage + * HTTP helpers (redirection, caching, etc) + * View system supporting 14+ template engines + * Content negotiation + * Executable for generating applications quickly + +## Docs & Community + + * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)] + * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC + * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules + * Visit the [Wiki](https://github.com/expressjs/express/wiki) + * [Google Group](https://groups.google.com/group/express-js) for discussion + * [Gitter](https://gitter.im/expressjs/express) for support and discussion + * [Русскоязычная документация](http://jsman.ru/express/) + +**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). + +###Security Issues + +If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). + +## Quick Start + + The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below: + + Install the executable. The executable's major version will match Express's: + +```bash +$ npm install -g express-generator@4 +``` + + Create the app: + +```bash +$ express /tmp/foo && cd /tmp/foo +``` + + Install dependencies: + +```bash +$ npm install +``` + + Start the server: + +```bash +$ npm start +``` + +## Philosophy + + The Express philosophy is to provide small, robust tooling for HTTP servers, making + it a great solution for single page applications, web sites, hybrids, or public + HTTP APIs. + + Express does not force you to use any specific ORM or template engine. With support for over + 14 template engines via [Consolidate.js](https://github.com/tj/consolidate.js), + you can quickly craft your perfect framework. + +## Examples + + To view the examples, clone the Express repo and install the dependencies: + +```bash +$ git clone git://github.com/expressjs/express.git --depth 1 +$ cd express +$ npm install +``` + + Then run whichever example you want: + +```bash +$ node examples/content-negotiation +``` + +## Tests + + To run the test suite, first install the dependencies, then run `npm test`: + +```bash +$ npm install +$ npm test +``` + +## People + +The original author of Express is [TJ Holowaychuk](https://github.com/tj) [![TJ's Gratipay][gratipay-image-visionmedia]][gratipay-url-visionmedia] + +The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson] + +[List of all contributors](https://github.com/expressjs/express/graphs/contributors) + +## License + + [MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/express.svg +[npm-url]: https://npmjs.org/package/express +[downloads-image]: https://img.shields.io/npm/dm/express.svg +[downloads-url]: https://npmjs.org/package/express +[travis-image]: https://img.shields.io/travis/expressjs/express/master.svg?label=linux +[travis-url]: https://travis-ci.org/expressjs/express +[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/express/master.svg?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express +[coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master +[gratipay-image-visionmedia]: https://img.shields.io/gratipay/visionmedia.svg +[gratipay-url-visionmedia]: https://gratipay.com/visionmedia/ +[gratipay-image-dougwilson]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url-dougwilson]: https://gratipay.com/dougwilson/ diff --git a/hm_sunwell/node_modules/express/index.js b/hm_sunwell/node_modules/express/index.js new file mode 100644 index 0000000..d219b0c --- /dev/null +++ b/hm_sunwell/node_modules/express/index.js @@ -0,0 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +module.exports = require('./lib/express'); diff --git a/hm_sunwell/node_modules/express/lib/application.js b/hm_sunwell/node_modules/express/lib/application.js new file mode 100644 index 0000000..0ee4def --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/application.js @@ -0,0 +1,643 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var finalhandler = require('finalhandler'); +var Router = require('./router'); +var methods = require('methods'); +var middleware = require('./middleware/init'); +var query = require('./middleware/query'); +var debug = require('debug')('express:application'); +var View = require('./view'); +var http = require('http'); +var compileETag = require('./utils').compileETag; +var compileQueryParser = require('./utils').compileQueryParser; +var compileTrust = require('./utils').compileTrust; +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var merge = require('utils-merge'); +var resolve = require('path').resolve; +var slice = Array.prototype.slice; + +/** + * Application prototype. + */ + +var app = exports = module.exports = {}; + +/** + * Variable for trust proxy inheritance back-compat + * @private + */ + +var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default'; + +/** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + * + * @private + */ + +app.init = function init() { + this.cache = {}; + this.engines = {}; + this.settings = {}; + + this.defaultConfiguration(); +}; + +/** + * Initialize application configuration. + * @private + */ + +app.defaultConfiguration = function defaultConfiguration() { + var env = process.env.NODE_ENV || 'development'; + + // default settings + this.enable('x-powered-by'); + this.set('etag', 'weak'); + this.set('env', env); + this.set('query parser', 'extended'); + this.set('subdomain offset', 2); + this.set('trust proxy', false); + + // trust proxy inherit back-compat + Object.defineProperty(this.settings, trustProxyDefaultSymbol, { + configurable: true, + value: true + }); + + debug('booting in %s mode', env); + + this.on('mount', function onmount(parent) { + // inherit trust proxy + if (this.settings[trustProxyDefaultSymbol] === true + && typeof parent.settings['trust proxy fn'] === 'function') { + delete this.settings['trust proxy']; + delete this.settings['trust proxy fn']; + } + + // inherit protos + this.request.__proto__ = parent.request; + this.response.__proto__ = parent.response; + this.engines.__proto__ = parent.engines; + this.settings.__proto__ = parent.settings; + }); + + // setup locals + this.locals = Object.create(null); + + // top-most app is mounted at / + this.mountpath = '/'; + + // default locals + this.locals.settings = this.settings; + + // default configuration + this.set('view', View); + this.set('views', resolve('views')); + this.set('jsonp callback name', 'callback'); + + if (env === 'production') { + this.enable('view cache'); + } + + Object.defineProperty(this, 'router', { + get: function() { + throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.'); + } + }); +}; + +/** + * lazily adds the base router if it has not yet been added. + * + * We cannot add the base router in the defaultConfiguration because + * it reads app settings which might be set after that has run. + * + * @private + */ +app.lazyrouter = function lazyrouter() { + if (!this._router) { + this._router = new Router({ + caseSensitive: this.enabled('case sensitive routing'), + strict: this.enabled('strict routing') + }); + + this._router.use(query(this.get('query parser fn'))); + this._router.use(middleware.init(this)); + } +}; + +/** + * Dispatch a req, res pair into the application. Starts pipeline processing. + * + * If no callback is provided, then default error handlers will respond + * in the event of an error bubbling through the stack. + * + * @private + */ + +app.handle = function handle(req, res, callback) { + var router = this._router; + + // final handler + var done = callback || finalhandler(req, res, { + env: this.get('env'), + onerror: logerror.bind(this) + }); + + // no routes + if (!router) { + debug('no routes defined on app'); + done(); + return; + } + + router.handle(req, res, done); +}; + +/** + * Proxy `Router#use()` to add middleware to the app router. + * See Router#use() documentation for details. + * + * If the _fn_ parameter is an express app, then it will be + * mounted at the _route_ specified. + * + * @public + */ + +app.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate app.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var fns = flatten(slice.call(arguments, offset)); + + if (fns.length === 0) { + throw new TypeError('app.use() requires middleware functions'); + } + + // setup router + this.lazyrouter(); + var router = this._router; + + fns.forEach(function (fn) { + // non-express app + if (!fn || !fn.handle || !fn.set) { + return router.use(path, fn); + } + + debug('.use app under %s', path); + fn.mountpath = path; + fn.parent = this; + + // restore .app property on req and res + router.use(path, function mounted_app(req, res, next) { + var orig = req.app; + fn.handle(req, res, function (err) { + req.__proto__ = orig.request; + res.__proto__ = orig.response; + next(err); + }); + }); + + // mounted an app + fn.emit('mount', this); + }, this); + + return this; +}; + +/** + * Proxy to the app `Router#route()` + * Returns a new `Route` instance for the _path_. + * + * Routes are isolated middleware stacks for specific paths. + * See the Route api docs for details. + * + * @public + */ + +app.route = function route(path) { + this.lazyrouter(); + return this._router.route(path); +}; + +/** + * Register the given template engine callback `fn` + * as `ext`. + * + * By default will `require()` the engine based on the + * file extension. For example if you try to render + * a "foo.jade" file Express will invoke the following internally: + * + * app.engine('jade', require('jade').__express); + * + * For engines that do not provide `.__express` out of the box, + * or if you wish to "map" a different extension to the template engine + * you may use this method. For example mapping the EJS template engine to + * ".html" files: + * + * app.engine('html', require('ejs').renderFile); + * + * In this case EJS provides a `.renderFile()` method with + * the same signature that Express expects: `(path, options, callback)`, + * though note that it aliases this method as `ejs.__express` internally + * so if you're using ".ejs" extensions you dont need to do anything. + * + * Some template engines do not follow this convention, the + * [Consolidate.js](https://github.com/tj/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seamlessly within Express. + * + * @param {String} ext + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +app.engine = function engine(ext, fn) { + if (typeof fn !== 'function') { + throw new Error('callback function required'); + } + + // get file extension + var extension = ext[0] !== '.' + ? '.' + ext + : ext; + + // store engine + this.engines[extension] = fn; + + return this; +}; + +/** + * Proxy to `Router#param()` with one added api feature. The _name_ parameter + * can be an array of names. + * + * See the Router#param() docs for more details. + * + * @param {String|Array} name + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +app.param = function param(name, fn) { + this.lazyrouter(); + + if (Array.isArray(name)) { + for (var i = 0; i < name.length; i++) { + this.param(name[i], fn); + } + + return this; + } + + this._router.param(name, fn); + + return this; +}; + +/** + * Assign `setting` to `val`, or return `setting`'s value. + * + * app.set('foo', 'bar'); + * app.get('foo'); + * // => "bar" + * + * Mounted servers inherit their parent server's settings. + * + * @param {String} setting + * @param {*} [val] + * @return {Server} for chaining + * @public + */ + +app.set = function set(setting, val) { + if (arguments.length === 1) { + // app.get(setting) + return this.settings[setting]; + } + + debug('set "%s" to %o', setting, val); + + // set value + this.settings[setting] = val; + + // trigger matched settings + switch (setting) { + case 'etag': + this.set('etag fn', compileETag(val)); + break; + case 'query parser': + this.set('query parser fn', compileQueryParser(val)); + break; + case 'trust proxy': + this.set('trust proxy fn', compileTrust(val)); + + // trust proxy inherit back-compat + Object.defineProperty(this.settings, trustProxyDefaultSymbol, { + configurable: true, + value: false + }); + + break; + } + + return this; +}; + +/** + * Return the app's absolute pathname + * based on the parent(s) that have + * mounted it. + * + * For example if the application was + * mounted as "/admin", which itself + * was mounted as "/blog" then the + * return value would be "/blog/admin". + * + * @return {String} + * @private + */ + +app.path = function path() { + return this.parent + ? this.parent.path() + this.mountpath + : ''; +}; + +/** + * Check if `setting` is enabled (truthy). + * + * app.enabled('foo') + * // => false + * + * app.enable('foo') + * app.enabled('foo') + * // => true + * + * @param {String} setting + * @return {Boolean} + * @public + */ + +app.enabled = function enabled(setting) { + return Boolean(this.set(setting)); +}; + +/** + * Check if `setting` is disabled. + * + * app.disabled('foo') + * // => true + * + * app.enable('foo') + * app.disabled('foo') + * // => false + * + * @param {String} setting + * @return {Boolean} + * @public + */ + +app.disabled = function disabled(setting) { + return !this.set(setting); +}; + +/** + * Enable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @public + */ + +app.enable = function enable(setting) { + return this.set(setting, true); +}; + +/** + * Disable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @public + */ + +app.disable = function disable(setting) { + return this.set(setting, false); +}; + +/** + * Delegate `.VERB(...)` calls to `router.VERB(...)`. + */ + +methods.forEach(function(method){ + app[method] = function(path){ + if (method === 'get' && arguments.length === 1) { + // app.get(setting) + return this.set(path); + } + + this.lazyrouter(); + + var route = this._router.route(path); + route[method].apply(route, slice.call(arguments, 1)); + return this; + }; +}); + +/** + * Special-cased "all" method, applying the given route `path`, + * middleware, and callback to _every_ HTTP method. + * + * @param {String} path + * @param {Function} ... + * @return {app} for chaining + * @public + */ + +app.all = function all(path) { + this.lazyrouter(); + + var route = this._router.route(path); + var args = slice.call(arguments, 1); + + for (var i = 0; i < methods.length; i++) { + route[methods[i]].apply(route, args); + } + + return this; +}; + +// del -> delete alias + +app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); + +/** + * Render the given view `name` name with `options` + * and a callback accepting an error and the + * rendered template string. + * + * Example: + * + * app.render('email', { name: 'Tobi' }, function(err, html){ + * // ... + * }) + * + * @param {String} name + * @param {Object|Function} options or fn + * @param {Function} callback + * @public + */ + +app.render = function render(name, options, callback) { + var cache = this.cache; + var done = callback; + var engines = this.engines; + var opts = options; + var renderOptions = {}; + var view; + + // support callback function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // merge app.locals + merge(renderOptions, this.locals); + + // merge options._locals + if (opts._locals) { + merge(renderOptions, opts._locals); + } + + // merge options + merge(renderOptions, opts); + + // set .cache unless explicitly provided + if (renderOptions.cache == null) { + renderOptions.cache = this.enabled('view cache'); + } + + // primed cache + if (renderOptions.cache) { + view = cache[name]; + } + + // view + if (!view) { + var View = this.get('view'); + + view = new View(name, { + defaultEngine: this.get('view engine'), + root: this.get('views'), + engines: engines + }); + + if (!view.path) { + var dirs = Array.isArray(view.root) && view.root.length > 1 + ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"' + : 'directory "' + view.root + '"' + var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs); + err.view = view; + return done(err); + } + + // prime the cache + if (renderOptions.cache) { + cache[name] = view; + } + } + + // render + tryRender(view, renderOptions, done); +}; + +/** + * Listen for connections. + * + * A node `http.Server` is returned, with this + * application (which is a `Function`) as its + * callback. If you wish to create both an HTTP + * and HTTPS server you may do so with the "http" + * and "https" modules as shown here: + * + * var http = require('http') + * , https = require('https') + * , express = require('express') + * , app = express(); + * + * http.createServer(app).listen(80); + * https.createServer({ ... }, app).listen(443); + * + * @return {http.Server} + * @public + */ + +app.listen = function listen() { + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; + +/** + * Log error using console.error. + * + * @param {Error} err + * @private + */ + +function logerror(err) { + /* istanbul ignore next */ + if (this.get('env') !== 'test') console.error(err.stack || err.toString()); +} + +/** + * Try rendering a view. + * @private + */ + +function tryRender(view, options, callback) { + try { + view.render(options, callback); + } catch (err) { + callback(err); + } +} diff --git a/hm_sunwell/node_modules/express/lib/express.js b/hm_sunwell/node_modules/express/lib/express.js new file mode 100644 index 0000000..540c8be --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/express.js @@ -0,0 +1,103 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var mixin = require('merge-descriptors'); +var proto = require('./application'); +var Route = require('./router/route'); +var Router = require('./router'); +var req = require('./request'); +var res = require('./response'); + +/** + * Expose `createApplication()`. + */ + +exports = module.exports = createApplication; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + +function createApplication() { + var app = function(req, res, next) { + app.handle(req, res, next); + }; + + mixin(app, EventEmitter.prototype, false); + mixin(app, proto, false); + + app.request = { __proto__: req, app: app }; + app.response = { __proto__: res, app: app }; + app.init(); + return app; +} + +/** + * Expose the prototypes. + */ + +exports.application = proto; +exports.request = req; +exports.response = res; + +/** + * Expose constructors. + */ + +exports.Route = Route; +exports.Router = Router; + +/** + * Expose middleware + */ + +exports.query = require('./middleware/query'); +exports.static = require('serve-static'); + +/** + * Replace removed middleware with an appropriate error message. + */ + +[ + 'json', + 'urlencoded', + 'bodyParser', + 'compress', + 'cookieSession', + 'session', + 'logger', + 'cookieParser', + 'favicon', + 'responseTime', + 'errorHandler', + 'timeout', + 'methodOverride', + 'vhost', + 'csrf', + 'directory', + 'limit', + 'multipart', + 'staticCache', +].forEach(function (name) { + Object.defineProperty(exports, name, { + get: function () { + throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.'); + }, + configurable: true + }); +}); diff --git a/hm_sunwell/node_modules/express/lib/middleware/init.js b/hm_sunwell/node_modules/express/lib/middleware/init.js new file mode 100644 index 0000000..f3119ed --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/middleware/init.js @@ -0,0 +1,36 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Initialization middleware, exposing the + * request and response to each other, as well + * as defaulting the X-Powered-By header field. + * + * @param {Function} app + * @return {Function} + * @api private + */ + +exports.init = function(app){ + return function expressInit(req, res, next){ + if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); + req.res = res; + res.req = req; + req.next = next; + + req.__proto__ = app.request; + res.__proto__ = app.response; + + res.locals = res.locals || Object.create(null); + + next(); + }; +}; + diff --git a/hm_sunwell/node_modules/express/lib/middleware/query.js b/hm_sunwell/node_modules/express/lib/middleware/query.js new file mode 100644 index 0000000..5f76f84 --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/middleware/query.js @@ -0,0 +1,46 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var parseUrl = require('parseurl'); +var qs = require('qs'); + +/** + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function query(options) { + var opts = Object.create(options || null); + var queryparse = qs.parse; + + if (typeof options === 'function') { + queryparse = options; + opts = undefined; + } + + if (opts !== undefined && opts.allowPrototypes === undefined) { + // back-compat for qs module + opts.allowPrototypes = true; + } + + return function query(req, res, next){ + if (!req.query) { + var val = parseUrl(req).query; + req.query = queryparse(val, opts); + } + + next(); + }; +}; diff --git a/hm_sunwell/node_modules/express/lib/request.js b/hm_sunwell/node_modules/express/lib/request.js new file mode 100644 index 0000000..557d050 --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/request.js @@ -0,0 +1,502 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var accepts = require('accepts'); +var deprecate = require('depd')('express'); +var isIP = require('net').isIP; +var typeis = require('type-is'); +var http = require('http'); +var fresh = require('fresh'); +var parseRange = require('range-parser'); +var parse = require('parseurl'); +var proxyaddr = require('proxy-addr'); + +/** + * Request prototype. + */ + +var req = exports = module.exports = { + __proto__: http.IncomingMessage.prototype +}; + +/** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param {String} name + * @return {String} + * @public + */ + +req.get = +req.header = function header(name) { + if (!name) { + throw new TypeError('name argument is required to req.get'); + } + + if (typeof name !== 'string') { + throw new TypeError('name must be a string to req.get'); + } + + var lc = name.toLowerCase(); + + switch (lc) { + case 'referer': + case 'referrer': + return this.headers.referrer + || this.headers.referer; + default: + return this.headers[lc]; + } +}; + +/** + * To do: update docs. + * + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single MIME type string + * such as "application/json", an extension name + * such as "json", a comma-delimited list such as "json, html, text/plain", + * an argument list such as `"json", "html", "text/plain"`, + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given, the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html', 'json'); + * req.accepts('html, json'); + * // => "json" + * + * @param {String|Array} type(s) + * @return {String|Array|Boolean} + * @public + */ + +req.accepts = function(){ + var accept = accepts(this); + return accept.types.apply(accept, arguments); +}; + +/** + * Check if the given `encoding`s are accepted. + * + * @param {String} ...encoding + * @return {String|Array} + * @public + */ + +req.acceptsEncodings = function(){ + var accept = accepts(this); + return accept.encodings.apply(accept, arguments); +}; + +req.acceptsEncoding = deprecate.function(req.acceptsEncodings, + 'req.acceptsEncoding: Use acceptsEncodings instead'); + +/** + * Check if the given `charset`s are acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} ...charset + * @return {String|Array} + * @public + */ + +req.acceptsCharsets = function(){ + var accept = accepts(this); + return accept.charsets.apply(accept, arguments); +}; + +req.acceptsCharset = deprecate.function(req.acceptsCharsets, + 'req.acceptsCharset: Use acceptsCharsets instead'); + +/** + * Check if the given `lang`s are acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} ...lang + * @return {String|Array} + * @public + */ + +req.acceptsLanguages = function(){ + var accept = accepts(this); + return accept.languages.apply(accept, arguments); +}; + +req.acceptsLanguage = deprecate.function(req.acceptsLanguages, + 'req.acceptsLanguage: Use acceptsLanguages instead'); + +/** + * Parse Range header field, capping to the given `size`. + * + * Unspecified ranges such as "0-" require knowledge of your resource length. In + * the case of a byte range this is of course the total number of bytes. If the + * Range header field is not given `undefined` is returned, `-1` when unsatisfiable, + * and `-2` when syntactically invalid. + * + * When ranges are returned, the array has a "type" property which is the type of + * range that is required (most commonly, "bytes"). Each array element is an object + * with a "start" and "end" property for the portion of the range. + * + * The "combine" option can be set to `true` and overlapping & adjacent ranges + * will be combined into a single range. + * + * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3" + * should respond with 4 users when available, not 3. + * + * @param {number} size + * @param {object} [options] + * @param {boolean} [options.combine=false] + * @return {number|array} + * @public + */ + +req.range = function range(size, options) { + var range = this.get('Range'); + if (!range) return; + return parseRange(size, range, options); +}; + +/** + * Return the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `bodyParser()` middleware. + * + * @param {String} name + * @param {Mixed} [defaultValue] + * @return {String} + * @public + */ + +req.param = function param(name, defaultValue) { + var params = this.params || {}; + var body = this.body || {}; + var query = this.query || {}; + + var args = arguments.length === 1 + ? 'name' + : 'name, default'; + deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead'); + + if (null != params[name] && params.hasOwnProperty(name)) return params[name]; + if (null != body[name]) return body[name]; + if (null != query[name]) return query[name]; + + return defaultValue; +}; + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param {String|Array} types... + * @return {String|false|null} + * @public + */ + +req.is = function is(types) { + var arr = types; + + // support flattened arguments + if (!Array.isArray(types)) { + arr = new Array(arguments.length); + for (var i = 0; i < arr.length; i++) { + arr[i] = arguments[i]; + } + } + + return typeis(this, arr); +}; + +/** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting trusts the socket address, the + * "X-Forwarded-Proto" header field will be trusted + * and used if present. + * + * If you're running behind a reverse proxy that + * supplies https for you this may be enabled. + * + * @return {String} + * @public + */ + +defineGetter(req, 'protocol', function protocol(){ + var proto = this.connection.encrypted + ? 'https' + : 'http'; + var trust = this.app.get('trust proxy fn'); + + if (!trust(this.connection.remoteAddress, 0)) { + return proto; + } + + // Note: X-Forwarded-Proto is normally only ever a + // single value, but this is to be safe. + proto = this.get('X-Forwarded-Proto') || proto; + return proto.split(/\s*,\s*/)[0]; +}); + +/** + * Short-hand for: + * + * req.protocol === 'https' + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'secure', function secure(){ + return this.protocol === 'https'; +}); + +/** + * Return the remote address from the trusted proxy. + * + * The is the remote address on the socket unless + * "trust proxy" is set. + * + * @return {String} + * @public + */ + +defineGetter(req, 'ip', function ip(){ + var trust = this.app.get('trust proxy fn'); + return proxyaddr(this, trust); +}); + +/** + * When "trust proxy" is set, trusted proxy addresses + client. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream and "proxy1" and + * "proxy2" were trusted. + * + * @return {Array} + * @public + */ + +defineGetter(req, 'ips', function ips() { + var trust = this.app.get('trust proxy fn'); + var addrs = proxyaddr.all(this, trust); + return addrs.slice(1).reverse(); +}); + +/** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + * + * @return {Array} + * @public + */ + +defineGetter(req, 'subdomains', function subdomains() { + var hostname = this.hostname; + + if (!hostname) return []; + + var offset = this.app.get('subdomain offset'); + var subdomains = !isIP(hostname) + ? hostname.split('.').reverse() + : [hostname]; + + return subdomains.slice(offset); +}); + +/** + * Short-hand for `url.parse(req.url).pathname`. + * + * @return {String} + * @public + */ + +defineGetter(req, 'path', function path() { + return parse(this).pathname; +}); + +/** + * Parse the "Host" header field to a hostname. + * + * When the "trust proxy" setting trusts the socket + * address, the "X-Forwarded-Host" header field will + * be trusted. + * + * @return {String} + * @public + */ + +defineGetter(req, 'hostname', function hostname(){ + var trust = this.app.get('trust proxy fn'); + var host = this.get('X-Forwarded-Host'); + + if (!host || !trust(this.connection.remoteAddress, 0)) { + host = this.get('Host'); + } + + if (!host) return; + + // IPv6 literal support + var offset = host[0] === '[' + ? host.indexOf(']') + 1 + : 0; + var index = host.indexOf(':', offset); + + return index !== -1 + ? host.substring(0, index) + : host; +}); + +// TODO: change req.host to return host in next major + +defineGetter(req, 'host', deprecate.function(function host(){ + return this.hostname; +}, 'req.host: Use req.hostname instead')); + +/** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'fresh', function(){ + var method = this.method; + var s = this.res.statusCode; + + // GET or HEAD for weak freshness validation only + if ('GET' !== method && 'HEAD' !== method) return false; + + // 2xx or 304 as per rfc2616 14.26 + if ((s >= 200 && s < 300) || 304 === s) { + return fresh(this.headers, (this.res._headers || {})); + } + + return false; +}); + +/** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'stale', function stale(){ + return !this.fresh; +}); + +/** + * Check if the request was an _XMLHttpRequest_. + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'xhr', function xhr(){ + var val = this.get('X-Requested-With') || ''; + return val.toLowerCase() === 'xmlhttprequest'; +}); + +/** + * Helper function for creating a getter on an object. + * + * @param {Object} obj + * @param {String} name + * @param {Function} getter + * @private + */ +function defineGetter(obj, name, getter) { + Object.defineProperty(obj, name, { + configurable: true, + enumerable: true, + get: getter + }); +}; diff --git a/hm_sunwell/node_modules/express/lib/response.js b/hm_sunwell/node_modules/express/lib/response.js new file mode 100644 index 0000000..6128f45 --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/response.js @@ -0,0 +1,1065 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var contentDisposition = require('content-disposition'); +var deprecate = require('depd')('express'); +var encodeUrl = require('encodeurl'); +var escapeHtml = require('escape-html'); +var http = require('http'); +var isAbsolute = require('./utils').isAbsolute; +var onFinished = require('on-finished'); +var path = require('path'); +var merge = require('utils-merge'); +var sign = require('cookie-signature').sign; +var normalizeType = require('./utils').normalizeType; +var normalizeTypes = require('./utils').normalizeTypes; +var setCharset = require('./utils').setCharset; +var statusCodes = http.STATUS_CODES; +var cookie = require('cookie'); +var send = require('send'); +var extname = path.extname; +var mime = send.mime; +var resolve = path.resolve; +var vary = require('vary'); + +/** + * Response prototype. + */ + +var res = module.exports = { + __proto__: http.ServerResponse.prototype +}; + +/** + * Module variables. + * @private + */ + +var charsetRegExp = /;\s*charset\s*=/; + +/** + * Set status `code`. + * + * @param {Number} code + * @return {ServerResponse} + * @public + */ + +res.status = function status(code) { + this.statusCode = code; + return this; +}; + +/** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param {Object} links + * @return {ServerResponse} + * @public + */ + +res.links = function(links){ + var link = this.get('Link') || ''; + if (link) link += ', '; + return this.set('Link', link + Object.keys(links).map(function(rel){ + return '<' + links[rel] + '>; rel="' + rel + '"'; + }).join(', ')); +}; + +/** + * Send a response. + * + * Examples: + * + * res.send(new Buffer('wahoo')); + * res.send({ some: 'json' }); + * res.send('

some html

'); + * + * @param {string|number|boolean|object|Buffer} body + * @public + */ + +res.send = function send(body) { + var chunk = body; + var encoding; + var len; + var req = this.req; + var type; + + // settings + var app = this.app; + + // allow status / body + if (arguments.length === 2) { + // res.send(body, status) backwards compat + if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') { + deprecate('res.send(body, status): Use res.status(status).send(body) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.send(status, body): Use res.status(status).send(body) instead'); + this.statusCode = arguments[0]; + chunk = arguments[1]; + } + } + + // disambiguate res.send(status) and res.send(status, num) + if (typeof chunk === 'number' && arguments.length === 1) { + // res.send(status) will set status message as text string + if (!this.get('Content-Type')) { + this.type('txt'); + } + + deprecate('res.send(status): Use res.sendStatus(status) instead'); + this.statusCode = chunk; + chunk = statusCodes[chunk]; + } + + switch (typeof chunk) { + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.type('html'); + } + break; + case 'boolean': + case 'number': + case 'object': + if (chunk === null) { + chunk = ''; + } else if (Buffer.isBuffer(chunk)) { + if (!this.get('Content-Type')) { + this.type('bin'); + } + } else { + return this.json(chunk); + } + break; + } + + // write strings in utf-8 + if (typeof chunk === 'string') { + encoding = 'utf8'; + type = this.get('Content-Type'); + + // reflect this in content-type + if (typeof type === 'string') { + this.set('Content-Type', setCharset(type, 'utf-8')); + } + } + + // populate Content-Length + if (chunk !== undefined) { + if (!Buffer.isBuffer(chunk)) { + // convert chunk to Buffer; saves later double conversions + chunk = new Buffer(chunk, encoding); + encoding = undefined; + } + + len = chunk.length; + this.set('Content-Length', len); + } + + // populate ETag + var etag; + var generateETag = len !== undefined && app.get('etag fn'); + if (typeof generateETag === 'function' && !this.get('ETag')) { + if ((etag = generateETag(chunk, encoding))) { + this.set('ETag', etag); + } + } + + // freshness + if (req.fresh) this.statusCode = 304; + + // strip irrelevant headers + if (204 === this.statusCode || 304 === this.statusCode) { + this.removeHeader('Content-Type'); + this.removeHeader('Content-Length'); + this.removeHeader('Transfer-Encoding'); + chunk = ''; + } + + if (req.method === 'HEAD') { + // skip body for HEAD + this.end(); + } else { + // respond + this.end(chunk, encoding); + } + + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @public + */ + +res.json = function json(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = stringify(val, replacer, spaces); + + // content-type + if (!this.get('Content-Type')) { + this.set('Content-Type', 'application/json'); + } + + return this.send(body); +}; + +/** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @public + */ + +res.jsonp = function jsonp(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = stringify(val, replacer, spaces); + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + if (!this.get('Content-Type')) { + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'application/json'); + } + + // fixup callback + if (Array.isArray(callback)) { + callback = callback[0]; + } + + // jsonp + if (typeof callback === 'string' && callback.length !== 0) { + this.charset = 'utf-8'; + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'text/javascript'); + + // restrict callback charset + callback = callback.replace(/[^\[\]\w$.]/g, ''); + + // replace chars not allowed in JavaScript that are in JSON + body = body + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + + // the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse" + // the typeof check is just to reduce client error noise + body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Send given HTTP status code. + * + * Sets the response status to `statusCode` and the body of the + * response to the standard description from node's http.STATUS_CODES + * or the statusCode number if no description. + * + * Examples: + * + * res.sendStatus(200); + * + * @param {number} statusCode + * @public + */ + +res.sendStatus = function sendStatus(statusCode) { + var body = statusCodes[statusCode] || String(statusCode); + + this.statusCode = statusCode; + this.type('txt'); + + return this.send(body); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `callback(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendFile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendFile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendFile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @public + */ + +res.sendFile = function sendFile(path, options, callback) { + var done = callback; + var req = this.req; + var res = this; + var next = req.next; + var opts = options || {}; + + if (!path) { + throw new TypeError('path argument is required to res.sendFile'); + } + + // support function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + if (!opts.root && !isAbsolute(path)) { + throw new TypeError('path must be absolute or specify root to res.sendFile'); + } + + // create file stream + var pathname = encodeURI(path); + var file = send(req, pathname, opts); + + // transfer + sendfile(res, file, opts, function (err) { + if (done) return done(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORTED' && err.syscall !== 'write') { + next(err); + } + }); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `callback(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendfile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendfile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendfile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @public + */ + +res.sendfile = function (path, options, callback) { + var done = callback; + var req = this.req; + var res = this; + var next = req.next; + var opts = options || {}; + + // support function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // create file stream + var file = send(req, path, opts); + + // transfer + sendfile(res, file, opts, function (err) { + if (done) return done(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORT' && err.syscall !== 'write') { + next(err); + } + }); +}; + +res.sendfile = deprecate.function(res.sendfile, + 'res.sendfile: Use res.sendFile instead'); + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `callback(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headersSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + * + * @public + */ + +res.download = function download(path, filename, callback) { + var done = callback; + var name = filename; + + // support function as second arg + if (typeof filename === 'function') { + done = filename; + name = null; + } + + // set Content-Disposition when file is sent + var headers = { + 'Content-Disposition': contentDisposition(name || path) + }; + + // Resolve the full path for sendFile + var fullPath = resolve(path); + + return this.sendFile(fullPath, { headers: headers }, done); +}; + +/** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param {String} type + * @return {ServerResponse} for chaining + * @public + */ + +res.contentType = +res.type = function contentType(type) { + var ct = type.indexOf('/') === -1 + ? mime.lookup(type) + : type; + + return this.set('Content-Type', ct); +}; + +/** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('

hey

'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('

hey

'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param {Object} obj + * @return {ServerResponse} for chaining + * @public + */ + +res.format = function(obj){ + var req = this.req; + var next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = keys.length > 0 + ? req.accepts(keys) + : false; + + this.vary("Accept"); + + if (key) { + this.set('Content-Type', normalizeType(key).value); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = err.statusCode = 406; + err.types = normalizeTypes(keys).map(function(o){ return o.value }); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @public + */ + +res.attachment = function attachment(filename) { + if (filename) { + this.type(extname(filename)); + } + + this.set('Content-Disposition', contentDisposition(filename)); + + return this; +}; + +/** + * Append additional header `field` with value `val`. + * + * Example: + * + * res.append('Link', ['', '']); + * res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly'); + * res.append('Warning', '199 Miscellaneous warning'); + * + * @param {String} field + * @param {String|Array} val + * @return {ServerResponse} for chaining + * @public + */ + +res.append = function append(field, val) { + var prev = this.get(field); + var value = val; + + if (prev) { + // concat the new and prev vals + value = Array.isArray(prev) ? prev.concat(val) + : Array.isArray(val) ? [prev].concat(val) + : [prev, val]; + } + + return this.set(field, value); +}; + +/** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + * + * @param {String|Object} field + * @param {String|Array} val + * @return {ServerResponse} for chaining + * @public + */ + +res.set = +res.header = function header(field, val) { + if (arguments.length === 2) { + var value = Array.isArray(val) + ? val.map(String) + : String(val); + + // add charset to content-type + if (field.toLowerCase() === 'content-type' && !charsetRegExp.test(value)) { + var charset = mime.charsets.lookup(value.split(';')[0]); + if (charset) value += '; charset=' + charset.toLowerCase(); + } + + this.setHeader(field, value); + } else { + for (var key in field) { + this.set(key, field[key]); + } + } + return this; +}; + +/** + * Get value for header `field`. + * + * @param {String} field + * @return {String} + * @public + */ + +res.get = function(field){ + return this.getHeader(field); +}; + +/** + * Clear cookie `name`. + * + * @param {String} name + * @param {Object} [options] + * @return {ServerResponse} for chaining + * @public + */ + +res.clearCookie = function clearCookie(name, options) { + var opts = merge({ expires: new Date(1), path: '/' }, options); + + return this.cookie(name, '', opts); +}; + +/** + * Set cookie `name` to `value`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + * + * @param {String} name + * @param {String|Object} value + * @param {Options} options + * @return {ServerResponse} for chaining + * @public + */ + +res.cookie = function (name, value, options) { + var opts = merge({}, options); + var secret = this.req.secret; + var signed = opts.signed; + + if (signed && !secret) { + throw new Error('cookieParser("secret") required for signed cookies'); + } + + var val = typeof value === 'object' + ? 'j:' + JSON.stringify(value) + : String(value); + + if (signed) { + val = 's:' + sign(val, secret); + } + + if ('maxAge' in opts) { + opts.expires = new Date(Date.now() + opts.maxAge); + opts.maxAge /= 1000; + } + + if (opts.path == null) { + opts.path = '/'; + } + + this.append('Set-Cookie', cookie.serialize(name, String(val), opts)); + + return this; +}; + +/** + * Set the location header to `url`. + * + * The given `url` can also be "back", which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com'); + * res.location('../login'); + * + * @param {String} url + * @return {ServerResponse} for chaining + * @public + */ + +res.location = function location(url) { + var loc = url; + + // "back" is an alias for the referrer + if (url === 'back') { + loc = this.req.get('Referrer') || '/'; + } + + // set location + return this.set('Location', encodeUrl(loc)); +}; + +/** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com'); + * res.redirect(301, 'http://example.com'); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + * + * @public + */ + +res.redirect = function redirect(url) { + var address = url; + var body; + var status = 302; + + // allow status / url + if (arguments.length === 2) { + if (typeof arguments[0] === 'number') { + status = arguments[0]; + address = arguments[1]; + } else { + deprecate('res.redirect(url, status): Use res.redirect(status, url) instead'); + status = arguments[1]; + } + } + + // Set location header + address = this.location(address).get('Location'); + + // Support text/{plain,html} by default + this.format({ + text: function(){ + body = statusCodes[status] + '. Redirecting to ' + address; + }, + + html: function(){ + var u = escapeHtml(address); + body = '

' + statusCodes[status] + '. Redirecting to ' + u + '

'; + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + + if (this.req.method === 'HEAD') { + this.end(); + } else { + this.end(body); + } +}; + +/** + * Add `field` to Vary. If already present in the Vary set, then + * this call is simply ignored. + * + * @param {Array|String} field + * @return {ServerResponse} for chaining + * @public + */ + +res.vary = function(field){ + // checks for back-compat + if (!field || (Array.isArray(field) && !field.length)) { + deprecate('res.vary(): Provide a field name'); + return this; + } + + vary(this, field); + + return this; +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @public + */ + +res.render = function render(view, options, callback) { + var app = this.req.app; + var done = callback; + var opts = options || {}; + var req = this.req; + var self = this; + + // support callback function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // merge res.locals + opts._locals = self.locals; + + // default callback to respond + done = done || function (err, str) { + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, opts, done); +}; + +// pipe the send file stream +function sendfile(res, file, options, callback) { + var done = false; + var streaming; + + // request aborted + function onaborted() { + if (done) return; + done = true; + + var err = new Error('Request aborted'); + err.code = 'ECONNABORTED'; + callback(err); + } + + // directory + function ondirectory() { + if (done) return; + done = true; + + var err = new Error('EISDIR, read'); + err.code = 'EISDIR'; + callback(err); + } + + // errors + function onerror(err) { + if (done) return; + done = true; + callback(err); + } + + // ended + function onend() { + if (done) return; + done = true; + callback(); + } + + // file + function onfile() { + streaming = false; + } + + // finished + function onfinish(err) { + if (err && err.code === 'ECONNRESET') return onaborted(); + if (err) return onerror(err); + if (done) return; + + setImmediate(function () { + if (streaming !== false && !done) { + onaborted(); + return; + } + + if (done) return; + done = true; + callback(); + }); + } + + // streaming + function onstream() { + streaming = true; + } + + file.on('directory', ondirectory); + file.on('end', onend); + file.on('error', onerror); + file.on('file', onfile); + file.on('stream', onstream); + onFinished(res, onfinish); + + if (options.headers) { + // set headers on successful transfer + file.on('headers', function headers(res) { + var obj = options.headers; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + res.setHeader(k, obj[k]); + } + }); + } + + // pipe + file.pipe(res); +} + +/** + * Stringify JSON, like JSON.stringify, but v8 optimized. + * @private + */ + +function stringify(value, replacer, spaces) { + // v8 checks arguments.length for optimizing simple call + // https://bugs.chromium.org/p/v8/issues/detail?id=4730 + return replacer || spaces + ? JSON.stringify(value, replacer, spaces) + : JSON.stringify(value); +} diff --git a/hm_sunwell/node_modules/express/lib/router/index.js b/hm_sunwell/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..dac2514 --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/router/index.js @@ -0,0 +1,645 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Route = require('./route'); +var Layer = require('./layer'); +var methods = require('methods'); +var mixin = require('utils-merge'); +var debug = require('debug')('express:router'); +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var parseUrl = require('parseurl'); + +/** + * Module variables. + * @private + */ + +var objectRegExp = /^\[object (\S+)\]$/; +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @return {Router} which is an callable function + * @public + */ + +var proto = module.exports = function(options) { + var opts = options || {}; + + function router(req, res, next) { + router.handle(req, res, next); + } + + // mixin Router class functions + router.__proto__ = proto; + + router.params = {}; + router._params = []; + router.caseSensitive = opts.caseSensitive; + router.mergeParams = opts.mergeParams; + router.strict = opts.strict; + router.stack = []; + + return router; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback. + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the same signature as middleware, the only difference + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * Just like in middleware, you must either respond to the request or call next + * to avoid stalling the request. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * return next(err); + * } else if (!user) { + * return next(new Error('failed to load user')); + * } + * req.user = user; + * next(); + * }); + * }); + * + * @param {String} name + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +proto.param = function param(name, fn) { + // param logic + if (typeof name === 'function') { + deprecate('router.param(fn): Refactor to use path params'); + this._params.push(name); + return; + } + + // apply param functions + var params = this._params; + var len = params.length; + var ret; + + if (name[0] === ':') { + deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead'); + name = name.substr(1); + } + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' !== typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Dispatch a req, res into the router. + * @private + */ + +proto.handle = function handle(req, res, out) { + var self = this; + + debug('dispatching %s %s', req.method, req.url); + + var search = 1 + req.url.indexOf('?'); + var pathlength = search ? search - 1 : req.url.length; + var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://'); + var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''; + var idx = 0; + var removed = ''; + var slashAdded = false; + var paramcalled = {}; + + // store options for OPTIONS request + // only used if OPTIONS request + var options = []; + + // middleware and routes + var stack = self.stack; + + // manage inter-router variables + var parentParams = req.params; + var parentUrl = req.baseUrl || ''; + var done = restore(out, req, 'baseUrl', 'next', 'params'); + + // setup next layer + req.next = next; + + // for options requests, respond with a default if nothing else responds + if (req.method === 'OPTIONS') { + done = wrap(done, function(old, err) { + if (err || options.length === 0) return old(err); + sendOptionsResponse(res, options, old); + }); + } + + // setup basic req values + req.baseUrl = parentUrl; + req.originalUrl = req.originalUrl || req.url; + + next(); + + function next(err) { + var layerError = err === 'route' + ? null + : err; + + // remove added slash + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + // restore altered req.url + if (removed.length !== 0) { + req.baseUrl = parentUrl; + req.url = protohost + removed + req.url.substr(protohost.length); + removed = ''; + } + + // no more matching layers + if (idx >= stack.length) { + setImmediate(done, layerError); + return; + } + + // get pathname of request + var path = getPathname(req); + + if (path == null) { + return done(layerError); + } + + // find next matching layer + var layer; + var match; + var route; + + while (match !== true && idx < stack.length) { + layer = stack[idx++]; + match = matchLayer(layer, path); + route = layer.route; + + if (typeof match !== 'boolean') { + // hold on to layerError + layerError = layerError || match; + } + + if (match !== true) { + continue; + } + + if (!route) { + // process non-route handlers normally + continue; + } + + if (layerError) { + // routes do not match with a pending error + match = false; + continue; + } + + var method = req.method; + var has_method = route._handles_method(method); + + // build up automatic options response + if (!has_method && method === 'OPTIONS') { + appendMethods(options, route._options()); + } + + // don't even bother matching route + if (!has_method && method !== 'HEAD') { + match = false; + continue; + } + } + + // no match + if (match !== true) { + return done(layerError); + } + + // store route for dispatch on change + if (route) { + req.route = route; + } + + // Capture one-time layer values + req.params = self.mergeParams + ? mergeParams(layer.params, parentParams) + : layer.params; + var layerPath = layer.path; + + // this should be done for the layer + self.process_params(layer, paramcalled, req, res, function (err) { + if (err) { + return next(layerError || err); + } + + if (route) { + return layer.handle_request(req, res, next); + } + + trim_prefix(layer, layerError, layerPath, path); + }); + } + + function trim_prefix(layer, layerError, layerPath, path) { + var c = path[layerPath.length]; + if (c && '/' !== c && '.' !== c) return next(layerError); + + // Trim off the part of the url that matches the route + // middleware (.use stuff) needs to have the path stripped + if (layerPath.length !== 0) { + debug('trim prefix (%s) from url %s', layerPath, req.url); + removed = layerPath; + req.url = protohost + req.url.substr(protohost.length + removed.length); + + // Ensure leading slash + if (!fqdn && req.url[0] !== '/') { + req.url = '/' + req.url; + slashAdded = true; + } + + // Setup base URL (no trailing slash) + req.baseUrl = parentUrl + (removed[removed.length - 1] === '/' + ? removed.substring(0, removed.length - 1) + : removed); + } + + debug('%s %s : %s', layer.name, layerPath, req.originalUrl); + + if (layerError) { + layer.handle_error(layerError, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Process any parameters for the layer. + * @private + */ + +proto.process_params = function process_params(layer, called, req, res, done) { + var params = this.params; + + // captured parameters from the layer, keys and values + var keys = layer.keys; + + // fast track + if (!keys || keys.length === 0) { + return done(); + } + + var i = 0; + var name; + var paramIndex = 0; + var key; + var paramVal; + var paramCallbacks; + var paramCalled; + + // process params in order + // param callbacks can be async + function param(err) { + if (err) { + return done(err); + } + + if (i >= keys.length ) { + return done(); + } + + paramIndex = 0; + key = keys[i++]; + + if (!key) { + return done(); + } + + name = key.name; + paramVal = req.params[name]; + paramCallbacks = params[name]; + paramCalled = called[name]; + + if (paramVal === undefined || !paramCallbacks) { + return param(); + } + + // param previously called with same value or error occurred + if (paramCalled && (paramCalled.match === paramVal + || (paramCalled.error && paramCalled.error !== 'route'))) { + // restore value + req.params[name] = paramCalled.value; + + // next param + return param(paramCalled.error); + } + + called[name] = paramCalled = { + error: null, + match: paramVal, + value: paramVal + }; + + paramCallback(); + } + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + + // store updated value + paramCalled.value = req.params[key.name]; + + if (err) { + // store error + paramCalled.error = err; + param(err); + return; + } + + if (!fn) return param(); + + try { + fn(req, res, paramCallback, paramVal, key.name); + } catch (e) { + paramCallback(e); + } + } + + param(); +}; + +/** + * Use the given middleware function, with optional path, defaulting to "/". + * + * Use (like `.all`) will run for any http METHOD, but it will not add + * handlers for those methods so OPTIONS requests will not consider `.use` + * functions even if they could respond. + * + * The other difference is that _route_ path is stripped and not visible + * to the handler function. The main effect of this feature is that mounted + * handlers can operate without any code changes regardless of the "prefix" + * pathname. + * + * @public + */ + +proto.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate router.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var callbacks = flatten(slice.call(arguments, offset)); + + if (callbacks.length === 0) { + throw new TypeError('Router.use() requires middleware functions'); + } + + for (var i = 0; i < callbacks.length; i++) { + var fn = callbacks[i]; + + if (typeof fn !== 'function') { + throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn)); + } + + // add the middleware + debug('use %s %s', path, fn.name || ''); + + var layer = new Layer(path, { + sensitive: this.caseSensitive, + strict: false, + end: false + }, fn); + + layer.route = undefined; + + this.stack.push(layer); + } + + return this; +}; + +/** + * Create a new Route for the given path. + * + * Each route contains a separate middleware stack and VERB handlers. + * + * See the Route api documentation for details on adding handlers + * and middleware to routes. + * + * @param {String} path + * @return {Route} + * @public + */ + +proto.route = function route(path) { + var route = new Route(path); + + var layer = new Layer(path, { + sensitive: this.caseSensitive, + strict: this.strict, + end: true + }, route.dispatch.bind(route)); + + layer.route = route; + + this.stack.push(layer); + return route; +}; + +// create Router#VERB functions +methods.concat('all').forEach(function(method){ + proto[method] = function(path){ + var route = this.route(path) + route[method].apply(route, slice.call(arguments, 1)); + return this; + }; +}); + +// append methods to a list of methods +function appendMethods(list, addition) { + for (var i = 0; i < addition.length; i++) { + var method = addition[i]; + if (list.indexOf(method) === -1) { + list.push(method); + } + } +} + +// get pathname of request +function getPathname(req) { + try { + return parseUrl(req).pathname; + } catch (err) { + return undefined; + } +} + +// get type for error message +function gettype(obj) { + var type = typeof obj; + + if (type !== 'object') { + return type; + } + + // inspect [[Class]] for objects + return toString.call(obj) + .replace(objectRegExp, '$1'); +} + +/** + * Match path to a layer. + * + * @param {Layer} layer + * @param {string} path + * @private + */ + +function matchLayer(layer, path) { + try { + return layer.match(path); + } catch (err) { + return err; + } +} + +// merge params with parent params +function mergeParams(params, parent) { + if (typeof parent !== 'object' || !parent) { + return params; + } + + // make copy of parent for base + var obj = mixin({}, parent); + + // simple non-numeric merging + if (!(0 in params) || !(0 in parent)) { + return mixin(obj, params); + } + + var i = 0; + var o = 0; + + // determine numeric gaps + while (i in params) { + i++; + } + + while (o in parent) { + o++; + } + + // offset numeric indices in params before merge + for (i--; i >= 0; i--) { + params[i + o] = params[i]; + + // create holes for the merge when necessary + if (i < o) { + delete params[i]; + } + } + + return mixin(obj, params); +} + +// restore obj props after function +function restore(fn, obj) { + var props = new Array(arguments.length - 2); + var vals = new Array(arguments.length - 2); + + for (var i = 0; i < props.length; i++) { + props[i] = arguments[i + 2]; + vals[i] = obj[props[i]]; + } + + return function(err){ + // restore vals + for (var i = 0; i < props.length; i++) { + obj[props[i]] = vals[i]; + } + + return fn.apply(this, arguments); + }; +} + +// send an OPTIONS response +function sendOptionsResponse(res, options, next) { + try { + var body = options.join(','); + res.set('Allow', body); + res.send(body); + } catch (err) { + next(err); + } +} + +// wrap a function +function wrap(old, fn) { + return function proxy() { + var args = new Array(arguments.length + 1); + + args[0] = old; + for (var i = 0, len = arguments.length; i < len; i++) { + args[i + 1] = arguments[i]; + } + + fn.apply(this, args); + }; +} diff --git a/hm_sunwell/node_modules/express/lib/router/layer.js b/hm_sunwell/node_modules/express/lib/router/layer.js new file mode 100644 index 0000000..fe9210c --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/router/layer.js @@ -0,0 +1,176 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var pathRegexp = require('path-to-regexp'); +var debug = require('debug')('express:router:layer'); + +/** + * Module variables. + * @private + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Module exports. + * @public + */ + +module.exports = Layer; + +function Layer(path, options, fn) { + if (!(this instanceof Layer)) { + return new Layer(path, options, fn); + } + + debug('new %s', path); + var opts = options || {}; + + this.handle = fn; + this.name = fn.name || ''; + this.params = undefined; + this.path = undefined; + this.regexp = pathRegexp(path, this.keys = [], opts); + + if (path === '/' && opts.end === false) { + this.regexp.fast_slash = true; + } +} + +/** + * Handle the error for the layer. + * + * @param {Error} error + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handle_error = function handle_error(error, req, res, next) { + var fn = this.handle; + + if (fn.length !== 4) { + // not a standard error handler + return next(error); + } + + try { + fn(error, req, res, next); + } catch (err) { + next(err); + } +}; + +/** + * Handle the request for the layer. + * + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handle_request = function handle(req, res, next) { + var fn = this.handle; + + if (fn.length > 3) { + // not a standard request handler + return next(); + } + + try { + fn(req, res, next); + } catch (err) { + next(err); + } +}; + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Layer.prototype.match = function match(path) { + if (path == null) { + // no path, nothing matches + this.params = undefined; + this.path = undefined; + return false; + } + + if (this.regexp.fast_slash) { + // fast path non-ending match for / (everything matches) + this.params = {}; + this.path = ''; + return true; + } + + var m = this.regexp.exec(path); + + if (!m) { + this.params = undefined; + this.path = undefined; + return false; + } + + // store values + this.params = {}; + this.path = m[0]; + + var keys = this.keys; + var params = this.params; + + for (var i = 1; i < m.length; i++) { + var key = keys[i - 1]; + var prop = key.name; + var val = decode_param(m[i]); + + if (val !== undefined || !(hasOwnProperty.call(params, prop))) { + params[prop] = val; + } + } + + return true; +}; + +/** + * Decode param value. + * + * @param {string} val + * @return {string} + * @private + */ + +function decode_param(val) { + if (typeof val !== 'string' || val.length === 0) { + return val; + } + + try { + return decodeURIComponent(val); + } catch (err) { + if (err instanceof URIError) { + err.message = 'Failed to decode param \'' + val + '\''; + err.status = err.statusCode = 400; + } + + throw err; + } +} diff --git a/hm_sunwell/node_modules/express/lib/router/route.js b/hm_sunwell/node_modules/express/lib/router/route.js new file mode 100644 index 0000000..2788d7b --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/router/route.js @@ -0,0 +1,210 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var debug = require('debug')('express:router:route'); +var flatten = require('array-flatten'); +var Layer = require('./layer'); +var methods = require('methods'); + +/** + * Module variables. + * @private + */ + +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Module exports. + * @public + */ + +module.exports = Route; + +/** + * Initialize `Route` with the given `path`, + * + * @param {String} path + * @public + */ + +function Route(path) { + this.path = path; + this.stack = []; + + debug('new %s', path); + + // route handlers for various http methods + this.methods = {}; +} + +/** + * Determine if the route handles a given method. + * @private + */ + +Route.prototype._handles_method = function _handles_method(method) { + if (this.methods._all) { + return true; + } + + var name = method.toLowerCase(); + + if (name === 'head' && !this.methods['head']) { + name = 'get'; + } + + return Boolean(this.methods[name]); +}; + +/** + * @return {Array} supported HTTP methods + * @private + */ + +Route.prototype._options = function _options() { + var methods = Object.keys(this.methods); + + // append automatic head + if (this.methods.get && !this.methods.head) { + methods.push('head'); + } + + for (var i = 0; i < methods.length; i++) { + // make upper case + methods[i] = methods[i].toUpperCase(); + } + + return methods; +}; + +/** + * dispatch req, res into this route + * @private + */ + +Route.prototype.dispatch = function dispatch(req, res, done) { + var idx = 0; + var stack = this.stack; + if (stack.length === 0) { + return done(); + } + + var method = req.method.toLowerCase(); + if (method === 'head' && !this.methods['head']) { + method = 'get'; + } + + req.route = this; + + next(); + + function next(err) { + if (err && err === 'route') { + return done(); + } + + var layer = stack[idx++]; + if (!layer) { + return done(err); + } + + if (layer.method && layer.method !== method) { + return next(err); + } + + if (err) { + layer.handle_error(err, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Add a handler for all HTTP verbs to this route. + * + * Behaves just like middleware and can respond or call `next` + * to continue processing. + * + * You can use multiple `.all` call to add multiple handlers. + * + * function check_something(req, res, next){ + * next(); + * }; + * + * function validate_user(req, res, next){ + * next(); + * }; + * + * route + * .all(validate_user) + * .all(check_something) + * .get(function(req, res, next){ + * res.send('hello world'); + * }); + * + * @param {function} handler + * @return {Route} for chaining + * @api public + */ + +Route.prototype.all = function all() { + var handles = flatten(slice.call(arguments)); + + for (var i = 0; i < handles.length; i++) { + var handle = handles[i]; + + if (typeof handle !== 'function') { + var type = toString.call(handle); + var msg = 'Route.all() requires callback functions but got a ' + type; + throw new TypeError(msg); + } + + var layer = Layer('/', {}, handle); + layer.method = undefined; + + this.methods._all = true; + this.stack.push(layer); + } + + return this; +}; + +methods.forEach(function(method){ + Route.prototype[method] = function(){ + var handles = flatten(slice.call(arguments)); + + for (var i = 0; i < handles.length; i++) { + var handle = handles[i]; + + if (typeof handle !== 'function') { + var type = toString.call(handle); + var msg = 'Route.' + method + '() requires callback functions but got a ' + type; + throw new Error(msg); + } + + debug('%s %s', method, this.path); + + var layer = Layer('/', {}, handle); + layer.method = method; + + this.methods[method] = true; + this.stack.push(layer); + } + + return this; + }; +}); diff --git a/hm_sunwell/node_modules/express/lib/utils.js b/hm_sunwell/node_modules/express/lib/utils.js new file mode 100644 index 0000000..f418c58 --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/utils.js @@ -0,0 +1,299 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @api private + */ + +var contentDisposition = require('content-disposition'); +var contentType = require('content-type'); +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var mime = require('send').mime; +var basename = require('path').basename; +var etag = require('etag'); +var proxyaddr = require('proxy-addr'); +var qs = require('qs'); +var querystring = require('querystring'); + +/** + * Return strong ETag for `body`. + * + * @param {String|Buffer} body + * @param {String} [encoding] + * @return {String} + * @api private + */ + +exports.etag = function (body, encoding) { + var buf = !Buffer.isBuffer(body) + ? new Buffer(body, encoding) + : body; + + return etag(buf, {weak: false}); +}; + +/** + * Return weak ETag for `body`. + * + * @param {String|Buffer} body + * @param {String} [encoding] + * @return {String} + * @api private + */ + +exports.wetag = function wetag(body, encoding){ + var buf = !Buffer.isBuffer(body) + ? new Buffer(body, encoding) + : body; + + return etag(buf, {weak: true}); +}; + +/** + * Check if `path` looks absolute. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +exports.isAbsolute = function(path){ + if ('/' === path[0]) return true; + if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path + if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = deprecate.function(flatten, + 'utils.flatten: use array-flatten npm module instead'); + +/** + * Normalize the given `type`, for example "html" becomes "text/html". + * + * @param {String} type + * @return {Object} + * @api private + */ + +exports.normalizeType = function(type){ + return ~type.indexOf('/') + ? acceptParams(type) + : { value: mime.lookup(type), params: {} }; +}; + +/** + * Normalize `types`, for example "html" becomes "text/html". + * + * @param {Array} types + * @return {Array} + * @api private + */ + +exports.normalizeTypes = function(types){ + var ret = []; + + for (var i = 0; i < types.length; ++i) { + ret.push(exports.normalizeType(types[i])); + } + + return ret; +}; + +/** + * Generate Content-Disposition header appropriate for the filename. + * non-ascii filenames are urlencoded and a filename* parameter is added + * + * @param {String} filename + * @return {String} + * @api private + */ + +exports.contentDisposition = deprecate.function(contentDisposition, + 'utils.contentDisposition: use content-disposition npm module instead'); + +/** + * Parse accept params `str` returning an + * object with `.value`, `.quality` and `.params`. + * also includes `.originalIndex` for stable sorting + * + * @param {String} str + * @return {Object} + * @api private + */ + +function acceptParams(str, index) { + var parts = str.split(/ *; */); + var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; + + for (var i = 1; i < parts.length; ++i) { + var pms = parts[i].split(/ *= */); + if ('q' === pms[0]) { + ret.quality = parseFloat(pms[1]); + } else { + ret.params[pms[0]] = pms[1]; + } + } + + return ret; +} + +/** + * Compile "etag" value to function. + * + * @param {Boolean|String|Function} val + * @return {Function} + * @api private + */ + +exports.compileETag = function(val) { + var fn; + + if (typeof val === 'function') { + return val; + } + + switch (val) { + case true: + fn = exports.wetag; + break; + case false: + break; + case 'strong': + fn = exports.etag; + break; + case 'weak': + fn = exports.wetag; + break; + default: + throw new TypeError('unknown value for etag function: ' + val); + } + + return fn; +} + +/** + * Compile "query parser" value to function. + * + * @param {String|Function} val + * @return {Function} + * @api private + */ + +exports.compileQueryParser = function compileQueryParser(val) { + var fn; + + if (typeof val === 'function') { + return val; + } + + switch (val) { + case true: + fn = querystring.parse; + break; + case false: + fn = newObject; + break; + case 'extended': + fn = parseExtendedQueryString; + break; + case 'simple': + fn = querystring.parse; + break; + default: + throw new TypeError('unknown value for query parser function: ' + val); + } + + return fn; +} + +/** + * Compile "proxy trust" value to function. + * + * @param {Boolean|String|Number|Array|Function} val + * @return {Function} + * @api private + */ + +exports.compileTrust = function(val) { + if (typeof val === 'function') return val; + + if (val === true) { + // Support plain true/false + return function(){ return true }; + } + + if (typeof val === 'number') { + // Support trusting hop count + return function(a, i){ return i < val }; + } + + if (typeof val === 'string') { + // Support comma-separated values + val = val.split(/ *, */); + } + + return proxyaddr.compile(val || []); +} + +/** + * Set the charset in a given Content-Type string. + * + * @param {String} type + * @param {String} charset + * @return {String} + * @api private + */ + +exports.setCharset = function setCharset(type, charset) { + if (!type || !charset) { + return type; + } + + // parse type + var parsed = contentType.parse(type); + + // set charset + parsed.parameters.charset = charset; + + // format type + return contentType.format(parsed); +}; + +/** + * Parse an extended query string with qs. + * + * @return {Object} + * @private + */ + +function parseExtendedQueryString(str) { + return qs.parse(str, { + allowPrototypes: true + }); +} + +/** + * Return new empty object. + * + * @return {Object} + * @api private + */ + +function newObject() { + return {}; +} diff --git a/hm_sunwell/node_modules/express/lib/view.js b/hm_sunwell/node_modules/express/lib/view.js new file mode 100644 index 0000000..52415d4 --- /dev/null +++ b/hm_sunwell/node_modules/express/lib/view.js @@ -0,0 +1,173 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var debug = require('debug')('express:view'); +var path = require('path'); +var fs = require('fs'); +var utils = require('./utils'); + +/** + * Module variables. + * @private + */ + +var dirname = path.dirname; +var basename = path.basename; +var extname = path.extname; +var join = path.join; +var resolve = path.resolve; + +/** + * Module exports. + * @public + */ + +module.exports = View; + +/** + * Initialize a new `View` with the given `name`. + * + * Options: + * + * - `defaultEngine` the default template engine name + * - `engines` template engine require() cache + * - `root` root path for view lookup + * + * @param {string} name + * @param {object} options + * @public + */ + +function View(name, options) { + var opts = options || {}; + + this.defaultEngine = opts.defaultEngine; + this.ext = extname(name); + this.name = name; + this.root = opts.root; + + if (!this.ext && !this.defaultEngine) { + throw new Error('No default engine was specified and no extension was provided.'); + } + + var fileName = name; + + if (!this.ext) { + // get extension from default engine name + this.ext = this.defaultEngine[0] !== '.' + ? '.' + this.defaultEngine + : this.defaultEngine; + + fileName += this.ext; + } + + if (!opts.engines[this.ext]) { + // load engine + opts.engines[this.ext] = require(this.ext.substr(1)).__express; + } + + // store loaded engine + this.engine = opts.engines[this.ext]; + + // lookup path + this.path = this.lookup(fileName); +} + +/** + * Lookup view by the given `name` + * + * @param {string} name + * @private + */ + +View.prototype.lookup = function lookup(name) { + var path; + var roots = [].concat(this.root); + + debug('lookup "%s"', name); + + for (var i = 0; i < roots.length && !path; i++) { + var root = roots[i]; + + // resolve the path + var loc = resolve(root, name); + var dir = dirname(loc); + var file = basename(loc); + + // resolve the file + path = this.resolve(dir, file); + } + + return path; +}; + +/** + * Render with the given options. + * + * @param {object} options + * @param {function} callback + * @private + */ + +View.prototype.render = function render(options, callback) { + debug('render "%s"', this.path); + this.engine(this.path, options, callback); +}; + +/** + * Resolve the file within the given directory. + * + * @param {string} dir + * @param {string} file + * @private + */ + +View.prototype.resolve = function resolve(dir, file) { + var ext = this.ext; + + // . + var path = join(dir, file); + var stat = tryStat(path); + + if (stat && stat.isFile()) { + return path; + } + + // /index. + path = join(dir, basename(file, ext), 'index' + ext); + stat = tryStat(path); + + if (stat && stat.isFile()) { + return path; + } +}; + +/** + * Return a stat, maybe. + * + * @param {string} path + * @return {fs.Stats} + * @private + */ + +function tryStat(path) { + debug('stat "%s"', path); + + try { + return fs.statSync(path); + } catch (e) { + return undefined; + } +} diff --git a/hm_sunwell/node_modules/express/node_modules/qs/.eslintignore b/hm_sunwell/node_modules/express/node_modules/qs/.eslintignore new file mode 100644 index 0000000..1521c8b --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/.eslintignore @@ -0,0 +1 @@ +dist diff --git a/hm_sunwell/node_modules/express/node_modules/qs/.eslintrc b/hm_sunwell/node_modules/express/node_modules/qs/.eslintrc new file mode 100644 index 0000000..1faac27 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/.eslintrc @@ -0,0 +1,19 @@ +{ + "root": true, + + "extends": "@ljharb", + + "rules": { + "complexity": [2, 22], + "consistent-return": [1], + "id-length": [2, { "min": 1, "max": 25, "properties": "never" }], + "indent": [2, 4], + "max-params": [2, 9], + "max-statements": [2, 36], + "no-extra-parens": [1], + "no-continue": [1], + "no-magic-numbers": 0, + "no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"], + "operator-linebreak": 1 + } +} diff --git a/hm_sunwell/node_modules/express/node_modules/qs/.jscs.json b/hm_sunwell/node_modules/express/node_modules/qs/.jscs.json new file mode 100644 index 0000000..3d099c4 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/.jscs.json @@ -0,0 +1,176 @@ +{ + "es3": true, + + "additionalRules": [], + + "requireSemicolons": true, + + "disallowMultipleSpaces": true, + + "disallowIdentifierNames": [], + + "requireCurlyBraces": { + "allExcept": [], + "keywords": ["if", "else", "for", "while", "do", "try", "catch"] + }, + + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"], + + "disallowSpaceAfterKeywords": [], + + "disallowSpaceBeforeComma": true, + "disallowSpaceAfterComma": false, + "disallowSpaceBeforeSemicolon": true, + + "disallowNodeTypes": [ + "DebuggerStatement", + "ForInStatement", + "LabeledStatement", + "SwitchCase", + "SwitchStatement", + "WithStatement" + ], + + "requireObjectKeysOnNewLine": { "allExcept": ["sameLine"] }, + + "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true }, + "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, + "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, + "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, + "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, + + "requireSpaceBetweenArguments": true, + + "disallowSpacesInsideParentheses": true, + + "disallowSpacesInsideArrayBrackets": true, + + "disallowQuotedKeysInObjects": { "allExcept": ["reserved"] }, + + "disallowSpaceAfterObjectKeys": true, + + "requireCommaBeforeLineBreak": true, + + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], + "requireSpaceAfterPrefixUnaryOperators": [], + + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "requireSpaceBeforePostfixUnaryOperators": [], + + "disallowSpaceBeforeBinaryOperators": [], + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + "disallowSpaceAfterBinaryOperators": [], + + "disallowImplicitTypeConversion": ["binary", "string"], + + "disallowKeywords": ["with", "eval"], + + "requireKeywordsOnNewLine": [], + "disallowKeywordsOnNewLine": ["else"], + + "requireLineFeedAtFileEnd": true, + + "disallowTrailingWhitespace": true, + + "disallowTrailingComma": true, + + "excludeFiles": ["node_modules/**", "vendor/**"], + + "disallowMultipleLineStrings": true, + + "requireDotNotation": { "allExcept": ["keywords"] }, + + "requireParenthesesAroundIIFE": true, + + "validateLineBreaks": "LF", + + "validateQuoteMarks": { + "escape": true, + "mark": "'" + }, + + "disallowOperatorBeforeLineBreak": [], + + "requireSpaceBeforeKeywords": [ + "do", + "for", + "if", + "else", + "switch", + "case", + "try", + "catch", + "finally", + "while", + "with", + "return" + ], + + "validateAlignedFunctionParameters": { + "lineBreakAfterOpeningBraces": true, + "lineBreakBeforeClosingBraces": true + }, + + "requirePaddingNewLinesBeforeExport": true, + + "validateNewlineAfterArrayElements": { + "maximum": 1 + }, + + "requirePaddingNewLinesAfterUseStrict": true, + + "disallowArrowFunctions": true, + + "disallowMultiLineTernary": true, + + "validateOrderInObjectKeys": "asc-insensitive", + + "disallowIdenticalDestructuringNames": true, + + "disallowNestedTernaries": { "maxLevel": 1 }, + + "requireSpaceAfterComma": { "allExcept": ["trailing"] }, + "requireAlignedMultilineParams": false, + + "requireSpacesInGenerator": { + "afterStar": true + }, + + "disallowSpacesInGenerator": { + "beforeStar": true + }, + + "disallowVar": false, + + "requireArrayDestructuring": false, + + "requireEnhancedObjectLiterals": false, + + "requireObjectDestructuring": false, + + "requireEarlyReturn": false, + + "requireCapitalizedConstructorsNew": { + "allExcept": ["Function", "String", "Object", "Symbol", "Number", "Date", "RegExp", "Error", "Boolean", "Array"] + }, + + "requireImportAlphabetized": false, + + "requireSpaceBeforeObjectValues": true, + "requireSpaceBeforeDestructuredValues": true, + + "disallowSpacesInsideTemplateStringPlaceholders": true, + + "disallowArrayDestructuringReturn": false, + + "requireNewlineBeforeSingleStatementsInIf": false, + + "disallowUnusedVariables": true, + + "requireSpacesInsideImportedObjectBraces": true, + + "requireUseStrict": true +} + diff --git a/hm_sunwell/node_modules/express/node_modules/qs/CHANGELOG.md b/hm_sunwell/node_modules/express/node_modules/qs/CHANGELOG.md new file mode 100644 index 0000000..e318a05 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/CHANGELOG.md @@ -0,0 +1,120 @@ +## [**6.2.0**](https://github.com/ljharb/qs/issues?milestone=36&state=closed) +- [New] pass Buffers to the encoder/decoder directly (#161) +- [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160) +- [Fix] fix compacting of nested sparse arrays (#150) + +## [**6.1.0**](https://github.com/ljharb/qs/issues?milestone=35&state=closed) +- [New] allowDots option for `stringify` (#151) +- [Fix] "sort" option should work at a depth of 3 or more (#151) +- [Fix] Restore `dist` directory; will be removed in v7 (#148) + +## [**6.0.2**](https://github.com/ljharb/qs/issues?milestone=33&state=closed) +- Revert ES6 requirement and restore support for node down to v0.8. + +## [**6.0.1**](https://github.com/ljharb/qs/issues?milestone=32&state=closed) +- [**#127**](https://github.com/ljharb/qs/pull/127) Fix engines definition in package.json + +## [**6.0.0**](https://github.com/ljharb/qs/issues?milestone=31&state=closed) +- [**#124**](https://github.com/ljharb/qs/issues/124) Use ES6 and drop support for node < v4 + +## [**5.2.0**](https://github.com/ljharb/qs/issues?milestone=30&state=closed) +- [**#64**](https://github.com/ljharb/qs/issues/64) Add option to sort object keys in the query string + +## [**5.1.0**](https://github.com/ljharb/qs/issues?milestone=29&state=closed) +- [**#117**](https://github.com/ljharb/qs/issues/117) make URI encoding stringified results optional +- [**#106**](https://github.com/ljharb/qs/issues/106) Add flag `skipNulls` to optionally skip null values in stringify + +## [**5.0.0**](https://github.com/ljharb/qs/issues?milestone=28&state=closed) +- [**#114**](https://github.com/ljharb/qs/issues/114) default allowDots to false +- [**#100**](https://github.com/ljharb/qs/issues/100) include dist to npm + +## [**4.0.0**](https://github.com/ljharb/qs/issues?milestone=26&state=closed) +- [**#98**](https://github.com/ljharb/qs/issues/98) make returning plain objects and allowing prototype overwriting properties optional + +## [**3.1.0**](https://github.com/ljharb/qs/issues?milestone=24&state=closed) +- [**#89**](https://github.com/ljharb/qs/issues/89) Add option to disable "Transform dot notation to bracket notation" + +## [**3.0.0**](https://github.com/ljharb/qs/issues?milestone=23&state=closed) +- [**#80**](https://github.com/ljharb/qs/issues/80) qs.parse silently drops properties +- [**#77**](https://github.com/ljharb/qs/issues/77) Perf boost +- [**#60**](https://github.com/ljharb/qs/issues/60) Add explicit option to disable array parsing +- [**#74**](https://github.com/ljharb/qs/issues/74) Bad parse when turning array into object +- [**#81**](https://github.com/ljharb/qs/issues/81) Add a `filter` option +- [**#68**](https://github.com/ljharb/qs/issues/68) Fixed issue with recursion and passing strings into objects. +- [**#66**](https://github.com/ljharb/qs/issues/66) Add mixed array and object dot notation support Closes: #47 +- [**#76**](https://github.com/ljharb/qs/issues/76) RFC 3986 +- [**#85**](https://github.com/ljharb/qs/issues/85) No equal sign +- [**#84**](https://github.com/ljharb/qs/issues/84) update license attribute + +## [**2.4.1**](https://github.com/ljharb/qs/issues?milestone=20&state=closed) +- [**#73**](https://github.com/ljharb/qs/issues/73) Property 'hasOwnProperty' of object # is not a function + +## [**2.4.0**](https://github.com/ljharb/qs/issues?milestone=19&state=closed) +- [**#70**](https://github.com/ljharb/qs/issues/70) Add arrayFormat option + +## [**2.3.3**](https://github.com/ljharb/qs/issues?milestone=18&state=closed) +- [**#59**](https://github.com/ljharb/qs/issues/59) make sure array indexes are >= 0, closes #57 +- [**#58**](https://github.com/ljharb/qs/issues/58) make qs usable for browser loader + +## [**2.3.2**](https://github.com/ljharb/qs/issues?milestone=17&state=closed) +- [**#55**](https://github.com/ljharb/qs/issues/55) allow merging a string into an object + +## [**2.3.1**](https://github.com/ljharb/qs/issues?milestone=16&state=closed) +- [**#52**](https://github.com/ljharb/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError". + +## [**2.3.0**](https://github.com/ljharb/qs/issues?milestone=15&state=closed) +- [**#50**](https://github.com/ljharb/qs/issues/50) add option to omit array indices, closes #46 + +## [**2.2.5**](https://github.com/ljharb/qs/issues?milestone=14&state=closed) +- [**#39**](https://github.com/ljharb/qs/issues/39) Is there an alternative to Buffer.isBuffer? +- [**#49**](https://github.com/ljharb/qs/issues/49) refactor utils.merge, fixes #45 +- [**#41**](https://github.com/ljharb/qs/issues/41) avoid browserifying Buffer, for #39 + +## [**2.2.4**](https://github.com/ljharb/qs/issues?milestone=13&state=closed) +- [**#38**](https://github.com/ljharb/qs/issues/38) how to handle object keys beginning with a number + +## [**2.2.3**](https://github.com/ljharb/qs/issues?milestone=12&state=closed) +- [**#37**](https://github.com/ljharb/qs/issues/37) parser discards first empty value in array +- [**#36**](https://github.com/ljharb/qs/issues/36) Update to lab 4.x + +## [**2.2.2**](https://github.com/ljharb/qs/issues?milestone=11&state=closed) +- [**#33**](https://github.com/ljharb/qs/issues/33) Error when plain object in a value +- [**#34**](https://github.com/ljharb/qs/issues/34) use Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty +- [**#24**](https://github.com/ljharb/qs/issues/24) Changelog? Semver? + +## [**2.2.1**](https://github.com/ljharb/qs/issues?milestone=10&state=closed) +- [**#32**](https://github.com/ljharb/qs/issues/32) account for circular references properly, closes #31 +- [**#31**](https://github.com/ljharb/qs/issues/31) qs.parse stackoverflow on circular objects + +## [**2.2.0**](https://github.com/ljharb/qs/issues?milestone=9&state=closed) +- [**#26**](https://github.com/ljharb/qs/issues/26) Don't use Buffer global if it's not present +- [**#30**](https://github.com/ljharb/qs/issues/30) Bug when merging non-object values into arrays +- [**#29**](https://github.com/ljharb/qs/issues/29) Don't call Utils.clone at the top of Utils.merge +- [**#23**](https://github.com/ljharb/qs/issues/23) Ability to not limit parameters? + +## [**2.1.0**](https://github.com/ljharb/qs/issues?milestone=8&state=closed) +- [**#22**](https://github.com/ljharb/qs/issues/22) Enable using a RegExp as delimiter + +## [**2.0.0**](https://github.com/ljharb/qs/issues?milestone=7&state=closed) +- [**#18**](https://github.com/ljharb/qs/issues/18) Why is there arrayLimit? +- [**#20**](https://github.com/ljharb/qs/issues/20) Configurable parametersLimit +- [**#21**](https://github.com/ljharb/qs/issues/21) make all limits optional, for #18, for #20 + +## [**1.2.2**](https://github.com/ljharb/qs/issues?milestone=6&state=closed) +- [**#19**](https://github.com/ljharb/qs/issues/19) Don't overwrite null values + +## [**1.2.1**](https://github.com/ljharb/qs/issues?milestone=5&state=closed) +- [**#16**](https://github.com/ljharb/qs/issues/16) ignore non-string delimiters +- [**#15**](https://github.com/ljharb/qs/issues/15) Close code block + +## [**1.2.0**](https://github.com/ljharb/qs/issues?milestone=4&state=closed) +- [**#12**](https://github.com/ljharb/qs/issues/12) Add optional delim argument +- [**#13**](https://github.com/ljharb/qs/issues/13) fix #11: flattened keys in array are now correctly parsed + +## [**1.1.0**](https://github.com/ljharb/qs/issues?milestone=3&state=closed) +- [**#7**](https://github.com/ljharb/qs/issues/7) Empty values of a POST array disappear after being submitted +- [**#9**](https://github.com/ljharb/qs/issues/9) Should not omit equals signs (=) when value is null +- [**#6**](https://github.com/ljharb/qs/issues/6) Minor grammar fix in README + +## [**1.0.2**](https://github.com/ljharb/qs/issues?milestone=2&state=closed) +- [**#5**](https://github.com/ljharb/qs/issues/5) array holes incorrectly copied into object on large index diff --git a/hm_sunwell/node_modules/express/node_modules/qs/CONTRIBUTING.md b/hm_sunwell/node_modules/express/node_modules/qs/CONTRIBUTING.md new file mode 100644 index 0000000..8928361 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/CONTRIBUTING.md @@ -0,0 +1 @@ +Please view our [hapijs contributing guide](https://github.com/hapijs/hapi/blob/master/CONTRIBUTING.md). diff --git a/hm_sunwell/node_modules/express/node_modules/qs/LICENSE b/hm_sunwell/node_modules/express/node_modules/qs/LICENSE new file mode 100644 index 0000000..d456948 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2014 Nathan LaFreniere and other contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors diff --git a/hm_sunwell/node_modules/express/node_modules/qs/dist/qs.js b/hm_sunwell/node_modules/express/node_modules/qs/dist/qs.js new file mode 100644 index 0000000..4cc6f30 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/dist/qs.js @@ -0,0 +1,487 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0 && + (options.parseArrays && index <= options.arrayLimit) + ) { + obj = []; + obj[index] = parseObject(chain, val, options); + } else { + obj[cleanRoot] = parseObject(chain, val, options); + } + } + + return obj; +}; + +var parseKeys = function parseKeys(givenKey, val, options) { + if (!givenKey) { + return; + } + + // Transform dot notation to bracket notation + var key = options.allowDots ? givenKey.replace(/\.([^\.\[]+)/g, '[$1]') : givenKey; + + // The regex chunks + + var parent = /^([^\[\]]*)/; + var child = /(\[[^\[\]]*\])/g; + + // Get the parent + + var segment = parent.exec(key); + + // Stash the parent if it exists + + var keys = []; + if (segment[1]) { + // If we aren't using plain objects, optionally prefix keys + // that would overwrite object prototype properties + if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1])) { + if (!options.allowPrototypes) { + return; + } + } + + keys.push(segment[1]); + } + + // Loop through children appending to the array until we hit depth + + var i = 0; + while ((segment = child.exec(key)) !== null && i < options.depth) { + i += 1; + if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) { + if (!options.allowPrototypes) { + continue; + } + } + keys.push(segment[1]); + } + + // If there's a remainder, just add whatever is left + + if (segment) { + keys.push('[' + key.slice(segment.index) + ']'); + } + + return parseObject(keys, val, options); +}; + +module.exports = function (str, opts) { + var options = opts || {}; + + if (options.decoder !== null && options.decoder !== undefined && typeof options.decoder !== 'function') { + throw new TypeError('Decoder has to be a function.'); + } + + options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter; + options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth; + options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit; + options.parseArrays = options.parseArrays !== false; + options.decoder = typeof options.decoder === 'function' ? options.decoder : defaults.decoder; + options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : defaults.allowDots; + options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : defaults.plainObjects; + options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : defaults.allowPrototypes; + options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults.parameterLimit; + options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling; + + if (str === '' || str === null || typeof str === 'undefined') { + return options.plainObjects ? Object.create(null) : {}; + } + + var tempObj = typeof str === 'string' ? parseValues(str, options) : str; + var obj = options.plainObjects ? Object.create(null) : {}; + + // Iterate over the keys and setup the new object + + var keys = Object.keys(tempObj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var newObj = parseKeys(key, tempObj[key], options); + obj = Utils.merge(obj, newObj, options); + } + + return Utils.compact(obj); +}; + +},{"./utils":4}],3:[function(require,module,exports){ +'use strict'; + +var Utils = require('./utils'); + +var arrayPrefixGenerators = { + brackets: function brackets(prefix) { + return prefix + '[]'; + }, + indices: function indices(prefix, key) { + return prefix + '[' + key + ']'; + }, + repeat: function repeat(prefix) { + return prefix; + } +}; + +var defaults = { + delimiter: '&', + strictNullHandling: false, + skipNulls: false, + encode: true, + encoder: Utils.encode +}; + +var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots) { + var obj = object; + if (typeof filter === 'function') { + obj = filter(prefix, obj); + } else if (obj instanceof Date) { + obj = obj.toISOString(); + } else if (obj === null) { + if (strictNullHandling) { + return encoder ? encoder(prefix) : prefix; + } + + obj = ''; + } + + if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || Utils.isBuffer(obj)) { + if (encoder) { + return [encoder(prefix) + '=' + encoder(obj)]; + } + return [prefix + '=' + String(obj)]; + } + + var values = []; + + if (typeof obj === 'undefined') { + return values; + } + + var objKeys; + if (Array.isArray(filter)) { + objKeys = filter; + } else { + var keys = Object.keys(obj); + objKeys = sort ? keys.sort(sort) : keys; + } + + for (var i = 0; i < objKeys.length; ++i) { + var key = objKeys[i]; + + if (skipNulls && obj[key] === null) { + continue; + } + + if (Array.isArray(obj)) { + values = values.concat(stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots)); + } else { + values = values.concat(stringify(obj[key], prefix + (allowDots ? '.' + key : '[' + key + ']'), generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots)); + } + } + + return values; +}; + +module.exports = function (object, opts) { + var obj = object; + var options = opts || {}; + var delimiter = typeof options.delimiter === 'undefined' ? defaults.delimiter : options.delimiter; + var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling; + var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls; + var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode; + var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null; + var sort = typeof options.sort === 'function' ? options.sort : null; + var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots; + var objKeys; + var filter; + + if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') { + throw new TypeError('Encoder has to be a function.'); + } + + if (typeof options.filter === 'function') { + filter = options.filter; + obj = filter('', obj); + } else if (Array.isArray(options.filter)) { + objKeys = filter = options.filter; + } + + var keys = []; + + if (typeof obj !== 'object' || obj === null) { + return ''; + } + + var arrayFormat; + if (options.arrayFormat in arrayPrefixGenerators) { + arrayFormat = options.arrayFormat; + } else if ('indices' in options) { + arrayFormat = options.indices ? 'indices' : 'repeat'; + } else { + arrayFormat = 'indices'; + } + + var generateArrayPrefix = arrayPrefixGenerators[arrayFormat]; + + if (!objKeys) { + objKeys = Object.keys(obj); + } + + if (sort) { + objKeys.sort(sort); + } + + for (var i = 0; i < objKeys.length; ++i) { + var key = objKeys[i]; + + if (skipNulls && obj[key] === null) { + continue; + } + + keys = keys.concat(stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots)); + } + + return keys.join(delimiter); +}; + +},{"./utils":4}],4:[function(require,module,exports){ +'use strict'; + +var hexTable = (function () { + var array = new Array(256); + for (var i = 0; i < 256; ++i) { + array[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase(); + } + + return array; +}()); + +exports.arrayToObject = function (source, options) { + var obj = options.plainObjects ? Object.create(null) : {}; + for (var i = 0; i < source.length; ++i) { + if (typeof source[i] !== 'undefined') { + obj[i] = source[i]; + } + } + + return obj; +}; + +exports.merge = function (target, source, options) { + if (!source) { + return target; + } + + if (typeof source !== 'object') { + if (Array.isArray(target)) { + target.push(source); + } else if (typeof target === 'object') { + target[source] = true; + } else { + return [target, source]; + } + + return target; + } + + if (typeof target !== 'object') { + return [target].concat(source); + } + + var mergeTarget = target; + if (Array.isArray(target) && !Array.isArray(source)) { + mergeTarget = exports.arrayToObject(target, options); + } + + return Object.keys(source).reduce(function (acc, key) { + var value = source[key]; + + if (Object.prototype.hasOwnProperty.call(acc, key)) { + acc[key] = exports.merge(acc[key], value, options); + } else { + acc[key] = value; + } + return acc; + }, mergeTarget); +}; + +exports.decode = function (str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (e) { + return str; + } +}; + +exports.encode = function (str) { + // This code was originally written by Brian White (mscdex) for the io.js core querystring library. + // It has been adapted here for stricter adherence to RFC 3986 + if (str.length === 0) { + return str; + } + + var string = typeof str === 'string' ? str : String(str); + + var out = ''; + for (var i = 0; i < string.length; ++i) { + var c = string.charCodeAt(i); + + if ( + c === 0x2D || // - + c === 0x2E || // . + c === 0x5F || // _ + c === 0x7E || // ~ + (c >= 0x30 && c <= 0x39) || // 0-9 + (c >= 0x41 && c <= 0x5A) || // a-z + (c >= 0x61 && c <= 0x7A) // A-Z + ) { + out += string.charAt(i); + continue; + } + + if (c < 0x80) { + out = out + hexTable[c]; + continue; + } + + if (c < 0x800) { + out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]); + continue; + } + + if (c < 0xD800 || c >= 0xE000) { + out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]); + continue; + } + + i += 1; + c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); + out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; + } + + return out; +}; + +exports.compact = function (obj, references) { + if (typeof obj !== 'object' || obj === null) { + return obj; + } + + var refs = references || []; + var lookup = refs.indexOf(obj); + if (lookup !== -1) { + return refs[lookup]; + } + + refs.push(obj); + + if (Array.isArray(obj)) { + var compacted = []; + + for (var i = 0; i < obj.length; ++i) { + if (obj[i] && typeof obj[i] === 'object') { + compacted.push(exports.compact(obj[i], refs)); + } else if (typeof obj[i] !== 'undefined') { + compacted.push(obj[i]); + } + } + + return compacted; + } + + var keys = Object.keys(obj); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + obj[key] = exports.compact(obj[key], refs); + } + + return obj; +}; + +exports.isRegExp = function (obj) { + return Object.prototype.toString.call(obj) === '[object RegExp]'; +}; + +exports.isBuffer = function (obj) { + if (obj === null || typeof obj === 'undefined') { + return false; + } + + return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); +}; + +},{}]},{},[1])(1) +}); \ No newline at end of file diff --git a/hm_sunwell/node_modules/express/node_modules/qs/lib/index.js b/hm_sunwell/node_modules/express/node_modules/qs/lib/index.js new file mode 100644 index 0000000..1901959 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/lib/index.js @@ -0,0 +1,9 @@ +'use strict'; + +var Stringify = require('./stringify'); +var Parse = require('./parse'); + +module.exports = { + stringify: Stringify, + parse: Parse +}; diff --git a/hm_sunwell/node_modules/express/node_modules/qs/lib/parse.js b/hm_sunwell/node_modules/express/node_modules/qs/lib/parse.js new file mode 100644 index 0000000..bf70fd8 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/lib/parse.js @@ -0,0 +1,167 @@ +'use strict'; + +var Utils = require('./utils'); + +var defaults = { + delimiter: '&', + depth: 5, + arrayLimit: 20, + parameterLimit: 1000, + strictNullHandling: false, + plainObjects: false, + allowPrototypes: false, + allowDots: false, + decoder: Utils.decode +}; + +var parseValues = function parseValues(str, options) { + var obj = {}; + var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); + + for (var i = 0; i < parts.length; ++i) { + var part = parts[i]; + var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1; + + if (pos === -1) { + obj[options.decoder(part)] = ''; + + if (options.strictNullHandling) { + obj[options.decoder(part)] = null; + } + } else { + var key = options.decoder(part.slice(0, pos)); + var val = options.decoder(part.slice(pos + 1)); + + if (Object.prototype.hasOwnProperty.call(obj, key)) { + obj[key] = [].concat(obj[key]).concat(val); + } else { + obj[key] = val; + } + } + } + + return obj; +}; + +var parseObject = function parseObject(chain, val, options) { + if (!chain.length) { + return val; + } + + var root = chain.shift(); + + var obj; + if (root === '[]') { + obj = []; + obj = obj.concat(parseObject(chain, val, options)); + } else { + obj = options.plainObjects ? Object.create(null) : {}; + var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root; + var index = parseInt(cleanRoot, 10); + if ( + !isNaN(index) && + root !== cleanRoot && + String(index) === cleanRoot && + index >= 0 && + (options.parseArrays && index <= options.arrayLimit) + ) { + obj = []; + obj[index] = parseObject(chain, val, options); + } else { + obj[cleanRoot] = parseObject(chain, val, options); + } + } + + return obj; +}; + +var parseKeys = function parseKeys(givenKey, val, options) { + if (!givenKey) { + return; + } + + // Transform dot notation to bracket notation + var key = options.allowDots ? givenKey.replace(/\.([^\.\[]+)/g, '[$1]') : givenKey; + + // The regex chunks + + var parent = /^([^\[\]]*)/; + var child = /(\[[^\[\]]*\])/g; + + // Get the parent + + var segment = parent.exec(key); + + // Stash the parent if it exists + + var keys = []; + if (segment[1]) { + // If we aren't using plain objects, optionally prefix keys + // that would overwrite object prototype properties + if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1])) { + if (!options.allowPrototypes) { + return; + } + } + + keys.push(segment[1]); + } + + // Loop through children appending to the array until we hit depth + + var i = 0; + while ((segment = child.exec(key)) !== null && i < options.depth) { + i += 1; + if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) { + if (!options.allowPrototypes) { + continue; + } + } + keys.push(segment[1]); + } + + // If there's a remainder, just add whatever is left + + if (segment) { + keys.push('[' + key.slice(segment.index) + ']'); + } + + return parseObject(keys, val, options); +}; + +module.exports = function (str, opts) { + var options = opts || {}; + + if (options.decoder !== null && options.decoder !== undefined && typeof options.decoder !== 'function') { + throw new TypeError('Decoder has to be a function.'); + } + + options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter; + options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth; + options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit; + options.parseArrays = options.parseArrays !== false; + options.decoder = typeof options.decoder === 'function' ? options.decoder : defaults.decoder; + options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : defaults.allowDots; + options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : defaults.plainObjects; + options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : defaults.allowPrototypes; + options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults.parameterLimit; + options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling; + + if (str === '' || str === null || typeof str === 'undefined') { + return options.plainObjects ? Object.create(null) : {}; + } + + var tempObj = typeof str === 'string' ? parseValues(str, options) : str; + var obj = options.plainObjects ? Object.create(null) : {}; + + // Iterate over the keys and setup the new object + + var keys = Object.keys(tempObj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var newObj = parseKeys(key, tempObj[key], options); + obj = Utils.merge(obj, newObj, options); + } + + return Utils.compact(obj); +}; diff --git a/hm_sunwell/node_modules/express/node_modules/qs/lib/stringify.js b/hm_sunwell/node_modules/express/node_modules/qs/lib/stringify.js new file mode 100644 index 0000000..6e1c9a2 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/lib/stringify.js @@ -0,0 +1,137 @@ +'use strict'; + +var Utils = require('./utils'); + +var arrayPrefixGenerators = { + brackets: function brackets(prefix) { + return prefix + '[]'; + }, + indices: function indices(prefix, key) { + return prefix + '[' + key + ']'; + }, + repeat: function repeat(prefix) { + return prefix; + } +}; + +var defaults = { + delimiter: '&', + strictNullHandling: false, + skipNulls: false, + encode: true, + encoder: Utils.encode +}; + +var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots) { + var obj = object; + if (typeof filter === 'function') { + obj = filter(prefix, obj); + } else if (obj instanceof Date) { + obj = obj.toISOString(); + } else if (obj === null) { + if (strictNullHandling) { + return encoder ? encoder(prefix) : prefix; + } + + obj = ''; + } + + if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || Utils.isBuffer(obj)) { + if (encoder) { + return [encoder(prefix) + '=' + encoder(obj)]; + } + return [prefix + '=' + String(obj)]; + } + + var values = []; + + if (typeof obj === 'undefined') { + return values; + } + + var objKeys; + if (Array.isArray(filter)) { + objKeys = filter; + } else { + var keys = Object.keys(obj); + objKeys = sort ? keys.sort(sort) : keys; + } + + for (var i = 0; i < objKeys.length; ++i) { + var key = objKeys[i]; + + if (skipNulls && obj[key] === null) { + continue; + } + + if (Array.isArray(obj)) { + values = values.concat(stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots)); + } else { + values = values.concat(stringify(obj[key], prefix + (allowDots ? '.' + key : '[' + key + ']'), generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots)); + } + } + + return values; +}; + +module.exports = function (object, opts) { + var obj = object; + var options = opts || {}; + var delimiter = typeof options.delimiter === 'undefined' ? defaults.delimiter : options.delimiter; + var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling; + var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls; + var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode; + var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null; + var sort = typeof options.sort === 'function' ? options.sort : null; + var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots; + var objKeys; + var filter; + + if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') { + throw new TypeError('Encoder has to be a function.'); + } + + if (typeof options.filter === 'function') { + filter = options.filter; + obj = filter('', obj); + } else if (Array.isArray(options.filter)) { + objKeys = filter = options.filter; + } + + var keys = []; + + if (typeof obj !== 'object' || obj === null) { + return ''; + } + + var arrayFormat; + if (options.arrayFormat in arrayPrefixGenerators) { + arrayFormat = options.arrayFormat; + } else if ('indices' in options) { + arrayFormat = options.indices ? 'indices' : 'repeat'; + } else { + arrayFormat = 'indices'; + } + + var generateArrayPrefix = arrayPrefixGenerators[arrayFormat]; + + if (!objKeys) { + objKeys = Object.keys(obj); + } + + if (sort) { + objKeys.sort(sort); + } + + for (var i = 0; i < objKeys.length; ++i) { + var key = objKeys[i]; + + if (skipNulls && obj[key] === null) { + continue; + } + + keys = keys.concat(stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots)); + } + + return keys.join(delimiter); +}; diff --git a/hm_sunwell/node_modules/express/node_modules/qs/lib/utils.js b/hm_sunwell/node_modules/express/node_modules/qs/lib/utils.js new file mode 100644 index 0000000..2c5c8ee --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/lib/utils.js @@ -0,0 +1,164 @@ +'use strict'; + +var hexTable = (function () { + var array = new Array(256); + for (var i = 0; i < 256; ++i) { + array[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase(); + } + + return array; +}()); + +exports.arrayToObject = function (source, options) { + var obj = options.plainObjects ? Object.create(null) : {}; + for (var i = 0; i < source.length; ++i) { + if (typeof source[i] !== 'undefined') { + obj[i] = source[i]; + } + } + + return obj; +}; + +exports.merge = function (target, source, options) { + if (!source) { + return target; + } + + if (typeof source !== 'object') { + if (Array.isArray(target)) { + target.push(source); + } else if (typeof target === 'object') { + target[source] = true; + } else { + return [target, source]; + } + + return target; + } + + if (typeof target !== 'object') { + return [target].concat(source); + } + + var mergeTarget = target; + if (Array.isArray(target) && !Array.isArray(source)) { + mergeTarget = exports.arrayToObject(target, options); + } + + return Object.keys(source).reduce(function (acc, key) { + var value = source[key]; + + if (Object.prototype.hasOwnProperty.call(acc, key)) { + acc[key] = exports.merge(acc[key], value, options); + } else { + acc[key] = value; + } + return acc; + }, mergeTarget); +}; + +exports.decode = function (str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (e) { + return str; + } +}; + +exports.encode = function (str) { + // This code was originally written by Brian White (mscdex) for the io.js core querystring library. + // It has been adapted here for stricter adherence to RFC 3986 + if (str.length === 0) { + return str; + } + + var string = typeof str === 'string' ? str : String(str); + + var out = ''; + for (var i = 0; i < string.length; ++i) { + var c = string.charCodeAt(i); + + if ( + c === 0x2D || // - + c === 0x2E || // . + c === 0x5F || // _ + c === 0x7E || // ~ + (c >= 0x30 && c <= 0x39) || // 0-9 + (c >= 0x41 && c <= 0x5A) || // a-z + (c >= 0x61 && c <= 0x7A) // A-Z + ) { + out += string.charAt(i); + continue; + } + + if (c < 0x80) { + out = out + hexTable[c]; + continue; + } + + if (c < 0x800) { + out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]); + continue; + } + + if (c < 0xD800 || c >= 0xE000) { + out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]); + continue; + } + + i += 1; + c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); + out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; + } + + return out; +}; + +exports.compact = function (obj, references) { + if (typeof obj !== 'object' || obj === null) { + return obj; + } + + var refs = references || []; + var lookup = refs.indexOf(obj); + if (lookup !== -1) { + return refs[lookup]; + } + + refs.push(obj); + + if (Array.isArray(obj)) { + var compacted = []; + + for (var i = 0; i < obj.length; ++i) { + if (obj[i] && typeof obj[i] === 'object') { + compacted.push(exports.compact(obj[i], refs)); + } else if (typeof obj[i] !== 'undefined') { + compacted.push(obj[i]); + } + } + + return compacted; + } + + var keys = Object.keys(obj); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + obj[key] = exports.compact(obj[key], refs); + } + + return obj; +}; + +exports.isRegExp = function (obj) { + return Object.prototype.toString.call(obj) === '[object RegExp]'; +}; + +exports.isBuffer = function (obj) { + if (obj === null || typeof obj === 'undefined') { + return false; + } + + return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); +}; diff --git a/hm_sunwell/node_modules/express/node_modules/qs/package.json b/hm_sunwell/node_modules/express/node_modules/qs/package.json new file mode 100644 index 0000000..2f83a1b --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/package.json @@ -0,0 +1,111 @@ +{ + "_args": [ + [ + "qs@6.2.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "qs@6.2.0", + "_id": "qs@6.2.0", + "_inCache": true, + "_installable": true, + "_location": "/express/qs", + "_nodeVersion": "6.1.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/qs-6.2.0.tgz_1462749349998_0.03372702235355973" + }, + "_npmUser": { + "email": "ljharb@gmail.com", + "name": "ljharb" + }, + "_npmVersion": "3.8.6", + "_phantomChildren": {}, + "_requested": { + "name": "qs", + "raw": "qs@6.2.0", + "rawSpec": "6.2.0", + "scope": null, + "spec": "6.2.0", + "type": "version" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", + "_shasum": "3b7848c03c2dece69a9522b0fae8c4126d745f3b", + "_shrinkwrap": null, + "_spec": "qs@6.2.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "bugs": { + "url": "https://github.com/ljharb/qs/issues" + }, + "contributors": [ + { + "name": "Jordan Harband", + "email": "ljharb@gmail.com", + "url": "http://ljharb.codes" + } + ], + "dependencies": {}, + "description": "A querystring parser that supports nesting and arrays, with a depth limit", + "devDependencies": { + "@ljharb/eslint-config": "^4.0.0", + "browserify": "^13.0.1", + "covert": "^1.1.0", + "eslint": "^2.9.0", + "evalmd": "^0.0.17", + "iconv-lite": "^0.4.13", + "mkdirp": "^0.5.1", + "parallelshell": "^2.0.0", + "tape": "^4.5.1" + }, + "directories": {}, + "dist": { + "shasum": "3b7848c03c2dece69a9522b0fae8c4126d745f3b", + "tarball": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + }, + "engines": { + "node": ">=0.6" + }, + "gitHead": "d67d315b606c6bb809fedcbeebbbdb7f863852aa", + "homepage": "https://github.com/ljharb/qs", + "keywords": [ + "qs", + "querystring" + ], + "license": "BSD-3-Clause", + "main": "lib/index.js", + "maintainers": [ + { + "name": "hueniverse", + "email": "eran@hammer.io" + }, + { + "name": "ljharb", + "email": "ljharb@gmail.com" + }, + { + "name": "nlf", + "email": "quitlahok@gmail.com" + } + ], + "name": "qs", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/ljharb/qs.git" + }, + "scripts": { + "coverage": "covert test", + "dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js", + "lint": "eslint lib/*.js text/*.js", + "prepublish": "npm run dist", + "pretest": "parallelshell 'npm run --silent readme' 'npm run --silent lint'", + "readme": "evalmd README.md", + "test": "npm run --silent coverage", + "tests-only": "node test" + }, + "version": "6.2.0" +} diff --git a/hm_sunwell/node_modules/express/node_modules/qs/test/index.js b/hm_sunwell/node_modules/express/node_modules/qs/test/index.js new file mode 100644 index 0000000..b6a7d95 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/test/index.js @@ -0,0 +1,5 @@ +require('./parse'); + +require('./stringify'); + +require('./utils'); diff --git a/hm_sunwell/node_modules/express/node_modules/qs/test/parse.js b/hm_sunwell/node_modules/express/node_modules/qs/test/parse.js new file mode 100644 index 0000000..1b79daf --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/test/parse.js @@ -0,0 +1,423 @@ +'use strict'; + +var test = require('tape'); +var qs = require('../'); +var iconv = require('iconv-lite'); + +test('parse()', function (t) { + t.test('parses a simple string', function (st) { + st.deepEqual(qs.parse('0=foo'), { '0': 'foo' }); + st.deepEqual(qs.parse('foo=c++'), { foo: 'c ' }); + st.deepEqual(qs.parse('a[>=]=23'), { a: { '>=': '23' } }); + st.deepEqual(qs.parse('a[<=>]==23'), { a: { '<=>': '=23' } }); + st.deepEqual(qs.parse('a[==]=23'), { a: { '==': '23' } }); + st.deepEqual(qs.parse('foo', { strictNullHandling: true }), { foo: null }); + st.deepEqual(qs.parse('foo'), { foo: '' }); + st.deepEqual(qs.parse('foo='), { foo: '' }); + st.deepEqual(qs.parse('foo=bar'), { foo: 'bar' }); + st.deepEqual(qs.parse(' foo = bar = baz '), { ' foo ': ' bar = baz ' }); + st.deepEqual(qs.parse('foo=bar=baz'), { foo: 'bar=baz' }); + st.deepEqual(qs.parse('foo=bar&bar=baz'), { foo: 'bar', bar: 'baz' }); + st.deepEqual(qs.parse('foo2=bar2&baz2='), { foo2: 'bar2', baz2: '' }); + st.deepEqual(qs.parse('foo=bar&baz', { strictNullHandling: true }), { foo: 'bar', baz: null }); + st.deepEqual(qs.parse('foo=bar&baz'), { foo: 'bar', baz: '' }); + st.deepEqual(qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'), { + cht: 'p3', + chd: 't:60,40', + chs: '250x100', + chl: 'Hello|World' + }); + st.end(); + }); + + t.test('allows enabling dot notation', function (st) { + st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' }); + st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } }); + st.end(); + }); + + t.deepEqual(qs.parse('a[b]=c'), { a: { b: 'c' } }, 'parses a single nested string'); + t.deepEqual(qs.parse('a[b][c]=d'), { a: { b: { c: 'd' } } }, 'parses a double nested string'); + t.deepEqual( + qs.parse('a[b][c][d][e][f][g][h]=i'), + { a: { b: { c: { d: { e: { f: { '[g][h]': 'i' } } } } } } }, + 'defaults to a depth of 5' + ); + + t.test('only parses one level when depth = 1', function (st) { + st.deepEqual(qs.parse('a[b][c]=d', { depth: 1 }), { a: { b: { '[c]': 'd' } } }); + st.deepEqual(qs.parse('a[b][c][d]=e', { depth: 1 }), { a: { b: { '[c][d]': 'e' } } }); + st.end(); + }); + + t.deepEqual(qs.parse('a=b&a=c'), { a: ['b', 'c'] }, 'parses a simple array'); + + t.test('parses an explicit array', function (st) { + st.deepEqual(qs.parse('a[]=b'), { a: ['b'] }); + st.deepEqual(qs.parse('a[]=b&a[]=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[]=b&a[]=c&a[]=d'), { a: ['b', 'c', 'd'] }); + st.end(); + }); + + t.test('parses a mix of simple and explicit arrays', function (st) { + st.deepEqual(qs.parse('a=b&a[]=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[]=b&a=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[0]=b&a=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a=b&a[0]=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[1]=b&a=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a=b&a[1]=c'), { a: ['b', 'c'] }); + st.end(); + }); + + t.test('parses a nested array', function (st) { + st.deepEqual(qs.parse('a[b][]=c&a[b][]=d'), { a: { b: ['c', 'd'] } }); + st.deepEqual(qs.parse('a[>=]=25'), { a: { '>=': '25' } }); + st.end(); + }); + + t.test('allows to specify array indices', function (st) { + st.deepEqual(qs.parse('a[1]=c&a[0]=b&a[2]=d'), { a: ['b', 'c', 'd'] }); + st.deepEqual(qs.parse('a[1]=c&a[0]=b'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[1]=c'), { a: ['c'] }); + st.end(); + }); + + t.test('limits specific array indices to 20', function (st) { + st.deepEqual(qs.parse('a[20]=a'), { a: ['a'] }); + st.deepEqual(qs.parse('a[21]=a'), { a: { '21': 'a' } }); + st.end(); + }); + + t.deepEqual(qs.parse('a[12b]=c'), { a: { '12b': 'c' } }, 'supports keys that begin with a number'); + + t.test('supports encoded = signs', function (st) { + st.deepEqual(qs.parse('he%3Dllo=th%3Dere'), { 'he=llo': 'th=ere' }); + st.end(); + }); + + t.test('is ok with url encoded strings', function (st) { + st.deepEqual(qs.parse('a[b%20c]=d'), { a: { 'b c': 'd' } }); + st.deepEqual(qs.parse('a[b]=c%20d'), { a: { b: 'c d' } }); + st.end(); + }); + + t.test('allows brackets in the value', function (st) { + st.deepEqual(qs.parse('pets=["tobi"]'), { pets: '["tobi"]' }); + st.deepEqual(qs.parse('operators=[">=", "<="]'), { operators: '[">=", "<="]' }); + st.end(); + }); + + t.test('allows empty values', function (st) { + st.deepEqual(qs.parse(''), {}); + st.deepEqual(qs.parse(null), {}); + st.deepEqual(qs.parse(undefined), {}); + st.end(); + }); + + t.test('transforms arrays to objects', function (st) { + st.deepEqual(qs.parse('foo[0]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } }); + st.deepEqual(qs.parse('foo[bad]=baz&foo[0]=bar'), { foo: { bad: 'baz', '0': 'bar' } }); + st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar'), { foo: { bad: 'baz', '0': 'bar' } }); + st.deepEqual(qs.parse('foo[]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } }); + st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo'), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } }); + st.deepEqual(qs.parse('foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb'), { foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] }); + st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c'), { a: { '0': 'b', t: 'u', c: true } }); + st.deepEqual(qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y'), { a: { '0': 'b', '1': 'c', x: 'y' } }); + st.end(); + }); + + t.test('transforms arrays to objects (dot notation)', function (st) { + st.deepEqual(qs.parse('foo[0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [{ baz: 'bar' }], fool: { bad: 'baz' } }); + st.deepEqual(qs.parse('foo[0].baz=bar&fool.bad.boo=baz', { allowDots: true }), { foo: [{ baz: 'bar' }], fool: { bad: { boo: 'baz' } } }); + st.deepEqual(qs.parse('foo[0][0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [[{ baz: 'bar' }]], fool: { bad: 'baz' } }); + st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15'], bar: '2' }] }); + st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].baz[1]=16&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15', '16'], bar: '2' }] }); + st.deepEqual(qs.parse('foo.bad=baz&foo[0]=bar', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar' } }); + st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar' } }); + st.deepEqual(qs.parse('foo[]=bar&foo.bad=baz', { allowDots: true }), { foo: { '0': 'bar', bad: 'baz' } }); + st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } }); + st.deepEqual(qs.parse('foo[0].a=a&foo[0].b=b&foo[1].a=aa&foo[1].b=bb', { allowDots: true }), { foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] }); + st.end(); + }); + + t.deepEqual(qs.parse('a[b]=c&a=d'), { a: { b: 'c', d: true } }, 'can add keys to objects'); + + t.test('correctly prunes undefined values when converting an array to an object', function (st) { + st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { '2': 'b', '99999999': 'c' } }); + st.end(); + }); + + t.test('supports malformed uri characters', function (st) { + st.deepEqual(qs.parse('{%:%}', { strictNullHandling: true }), { '{%:%}': null }); + st.deepEqual(qs.parse('{%:%}='), { '{%:%}': '' }); + st.deepEqual(qs.parse('foo=%:%}'), { foo: '%:%}' }); + st.end(); + }); + + t.test('doesn\'t produce empty keys', function (st) { + st.deepEqual(qs.parse('_r=1&'), { '_r': '1' }); + st.end(); + }); + + t.test('cannot access Object prototype', function (st) { + qs.parse('constructor[prototype][bad]=bad'); + qs.parse('bad[constructor][prototype][bad]=bad'); + st.equal(typeof Object.prototype.bad, 'undefined'); + st.end(); + }); + + t.test('parses arrays of objects', function (st) { + st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] }); + st.deepEqual(qs.parse('a[0][b]=c'), { a: [{ b: 'c' }] }); + st.end(); + }); + + t.test('allows for empty strings in arrays', function (st) { + st.deepEqual(qs.parse('a[]=b&a[]=&a[]=c'), { a: ['b', '', 'c'] }); + st.deepEqual(qs.parse('a[0]=b&a[1]&a[2]=c&a[19]=', { strictNullHandling: true }), { a: ['b', null, 'c', ''] }); + st.deepEqual(qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]', { strictNullHandling: true }), { a: ['b', '', 'c', null] }); + st.deepEqual(qs.parse('a[]=&a[]=b&a[]=c'), { a: ['', 'b', 'c'] }); + st.end(); + }); + + t.test('compacts sparse arrays', function (st) { + st.deepEqual(qs.parse('a[10]=1&a[2]=2'), { a: ['2', '1'] }); + st.deepEqual(qs.parse('a[1][b][2][c]=1'), { a: [{ b: [{ c: '1' }] }] }); + st.deepEqual(qs.parse('a[1][2][3][c]=1'), { a: [[[{ c: '1' }]]] }); + st.deepEqual(qs.parse('a[1][2][3][c][1]=1'), { a: [[[{ c: ['1'] }]]] }); + st.end(); + }); + + t.test('parses semi-parsed strings', function (st) { + st.deepEqual(qs.parse({ 'a[b]': 'c' }), { a: { b: 'c' } }); + st.deepEqual(qs.parse({ 'a[b]': 'c', 'a[d]': 'e' }), { a: { b: 'c', d: 'e' } }); + st.end(); + }); + + t.test('parses buffers correctly', function (st) { + var b = new Buffer('test'); + st.deepEqual(qs.parse({ a: b }), { a: b }); + st.end(); + }); + + t.test('continues parsing when no parent is found', function (st) { + st.deepEqual(qs.parse('[]=&a=b'), { '0': '', a: 'b' }); + st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { '0': null, a: 'b' }); + st.deepEqual(qs.parse('[foo]=bar'), { foo: 'bar' }); + st.end(); + }); + + t.test('does not error when parsing a very long array', function (st) { + var str = 'a[]=a'; + while (Buffer.byteLength(str) < 128 * 1024) { + str = str + '&' + str; + } + + st.doesNotThrow(function () { qs.parse(str); }); + + st.end(); + }); + + t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) { + Object.prototype.crash = ''; + Array.prototype.crash = ''; + st.doesNotThrow(qs.parse.bind(null, 'a=b')); + st.deepEqual(qs.parse('a=b'), { a: 'b' }); + st.doesNotThrow(qs.parse.bind(null, 'a[][b]=c')); + st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] }); + delete Object.prototype.crash; + delete Array.prototype.crash; + st.end(); + }); + + t.test('parses a string with an alternative string delimiter', function (st) { + st.deepEqual(qs.parse('a=b;c=d', { delimiter: ';' }), { a: 'b', c: 'd' }); + st.end(); + }); + + t.test('parses a string with an alternative RegExp delimiter', function (st) { + st.deepEqual(qs.parse('a=b; c=d', { delimiter: /[;,] */ }), { a: 'b', c: 'd' }); + st.end(); + }); + + t.test('does not use non-splittable objects as delimiters', function (st) { + st.deepEqual(qs.parse('a=b&c=d', { delimiter: true }), { a: 'b', c: 'd' }); + st.end(); + }); + + t.test('allows overriding parameter limit', function (st) { + st.deepEqual(qs.parse('a=b&c=d', { parameterLimit: 1 }), { a: 'b' }); + st.end(); + }); + + t.test('allows setting the parameter limit to Infinity', function (st) { + st.deepEqual(qs.parse('a=b&c=d', { parameterLimit: Infinity }), { a: 'b', c: 'd' }); + st.end(); + }); + + t.test('allows overriding array limit', function (st) { + st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { '0': 'b' } }); + st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } }); + st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 }), { a: { '0': 'b', '1': 'c' } }); + st.end(); + }); + + t.test('allows disabling array parsing', function (st) { + st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { '0': 'b', '1': 'c' } }); + st.end(); + }); + + t.test('parses an object', function (st) { + var input = { + 'user[name]': { 'pop[bob]': 3 }, + 'user[email]': null + }; + + var expected = { + user: { + name: { 'pop[bob]': 3 }, + email: null + } + }; + + var result = qs.parse(input); + + st.deepEqual(result, expected); + st.end(); + }); + + t.test('parses an object in dot notation', function (st) { + var input = { + 'user.name': { 'pop[bob]': 3 }, + 'user.email.': null + }; + + var expected = { + user: { + name: { 'pop[bob]': 3 }, + email: null + } + }; + + var result = qs.parse(input, { allowDots: true }); + + st.deepEqual(result, expected); + st.end(); + }); + + t.test('parses an object and not child values', function (st) { + var input = { + 'user[name]': { 'pop[bob]': { 'test': 3 } }, + 'user[email]': null + }; + + var expected = { + user: { + name: { 'pop[bob]': { 'test': 3 } }, + email: null + } + }; + + var result = qs.parse(input); + + st.deepEqual(result, expected); + st.end(); + }); + + t.test('does not blow up when Buffer global is missing', function (st) { + var tempBuffer = global.Buffer; + delete global.Buffer; + var result = qs.parse('a=b&c=d'); + global.Buffer = tempBuffer; + st.deepEqual(result, { a: 'b', c: 'd' }); + st.end(); + }); + + t.test('does not crash when parsing circular references', function (st) { + var a = {}; + a.b = a; + + var parsed; + + st.doesNotThrow(function () { + parsed = qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a }); + }); + + st.equal('foo' in parsed, true, 'parsed has "foo" property'); + st.equal('bar' in parsed.foo, true); + st.equal('baz' in parsed.foo, true); + st.equal(parsed.foo.bar, 'baz'); + st.deepEqual(parsed.foo.baz, a); + st.end(); + }); + + t.test('parses plain objects correctly', function (st) { + var a = Object.create(null); + a.b = 'c'; + + st.deepEqual(qs.parse(a), { b: 'c' }); + var result = qs.parse({ a: a }); + st.equal('a' in result, true, 'result has "a" property'); + st.deepEqual(result.a, a); + st.end(); + }); + + t.test('parses dates correctly', function (st) { + var now = new Date(); + st.deepEqual(qs.parse({ a: now }), { a: now }); + st.end(); + }); + + t.test('parses regular expressions correctly', function (st) { + var re = /^test$/; + st.deepEqual(qs.parse({ a: re }), { a: re }); + st.end(); + }); + + t.test('can allow overwriting prototype properties', function (st) { + st.deepEqual(qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true }), { a: { hasOwnProperty: 'b' } }, { prototype: false }); + st.deepEqual(qs.parse('hasOwnProperty=b', { allowPrototypes: true }), { hasOwnProperty: 'b' }, { prototype: false }); + st.end(); + }); + + t.test('can return plain objects', function (st) { + var expected = Object.create(null); + expected.a = Object.create(null); + expected.a.b = 'c'; + expected.a.hasOwnProperty = 'd'; + st.deepEqual(qs.parse('a[b]=c&a[hasOwnProperty]=d', { plainObjects: true }), expected); + st.deepEqual(qs.parse(null, { plainObjects: true }), Object.create(null)); + var expectedArray = Object.create(null); + expectedArray.a = Object.create(null); + expectedArray.a['0'] = 'b'; + expectedArray.a.c = 'd'; + st.deepEqual(qs.parse('a[]=b&a[c]=d', { plainObjects: true }), expectedArray); + st.end(); + }); + + t.test('can parse with custom encoding', function (st) { + st.deepEqual(qs.parse('%8c%a7=%91%e5%8d%e3%95%7b', { + decoder: function (str) { + var reg = /\%([0-9A-F]{2})/ig; + var result = []; + var parts; + var last = 0; + while (parts = reg.exec(str)) { + result.push(parseInt(parts[1], 16)); + last = parts.index + parts[0].length; + } + return iconv.decode(new Buffer(result), 'shift_jis').toString(); + } + }), { 県: '大阪府' }); + st.end(); + }); + + t.test('throws error with wrong decoder', function (st) { + st.throws(function () { + qs.parse({}, { + decoder: 'string' + }); + }, new TypeError('Decoder has to be a function.')); + st.end(); + }); +}); diff --git a/hm_sunwell/node_modules/express/node_modules/qs/test/stringify.js b/hm_sunwell/node_modules/express/node_modules/qs/test/stringify.js new file mode 100644 index 0000000..699397e --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/test/stringify.js @@ -0,0 +1,305 @@ +'use strict'; + +var test = require('tape'); +var qs = require('../'); +var iconv = require('iconv-lite'); + +test('stringify()', function (t) { + t.test('stringifies a querystring object', function (st) { + st.equal(qs.stringify({ a: 'b' }), 'a=b'); + st.equal(qs.stringify({ a: 1 }), 'a=1'); + st.equal(qs.stringify({ a: 1, b: 2 }), 'a=1&b=2'); + st.equal(qs.stringify({ a: 'A_Z' }), 'a=A_Z'); + st.equal(qs.stringify({ a: '€' }), 'a=%E2%82%AC'); + st.equal(qs.stringify({ a: '' }), 'a=%EE%80%80'); + st.equal(qs.stringify({ a: 'א' }), 'a=%D7%90'); + st.equal(qs.stringify({ a: '𐐷' }), 'a=%F0%90%90%B7'); + st.end(); + }); + + t.test('stringifies a nested object', function (st) { + st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c'); + st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e'); + st.end(); + }); + + t.test('stringifies a nested object with dots notation', function (st) { + st.equal(qs.stringify({ a: { b: 'c' } }, { allowDots: true }), 'a.b=c'); + st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true }), 'a.b.c.d=e'); + st.end(); + }); + + t.test('stringifies an array value', function (st) { + st.equal(qs.stringify({ a: ['b', 'c', 'd'] }), 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d'); + st.end(); + }); + + t.test('omits nulls when asked', function (st) { + st.equal(qs.stringify({ a: 'b', c: null }, { skipNulls: true }), 'a=b'); + st.end(); + }); + + + t.test('omits nested nulls when asked', function (st) { + st.equal(qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true }), 'a%5Bb%5D=c'); + st.end(); + }); + + t.test('omits array indices when asked', function (st) { + st.equal(qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }), 'a=b&a=c&a=d'); + st.end(); + }); + + t.test('stringifies a nested array value', function (st) { + st.equal(qs.stringify({ a: { b: ['c', 'd'] } }), 'a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d'); + st.end(); + }); + + t.test('stringifies a nested array value with dots notation', function (st) { + st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { allowDots: true, encode: false }), 'a.b[0]=c&a.b[1]=d'); + st.end(); + }); + + t.test('stringifies an object inside an array', function (st) { + st.equal(qs.stringify({ a: [{ b: 'c' }] }), 'a%5B0%5D%5Bb%5D=c'); + st.equal(qs.stringify({ a: [{ b: { c: [1] } }] }), 'a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1'); + st.end(); + }); + + t.test('stringifies an array with mixed objects and primitives', function (st) { + st.equal(qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false }), 'a[0][b]=1&a[1]=2&a[2]=3'); + st.end(); + }); + + t.test('stringifies an object inside an array with dots notation', function (st) { + st.equal(qs.stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false }), 'a[0].b=c'); + st.equal(qs.stringify({ a: [{ b: { c: [1] } }] }, { allowDots: true, encode: false }), 'a[0].b.c[0]=1'); + st.end(); + }); + + t.test('does not omit object keys when indices = false', function (st) { + st.equal(qs.stringify({ a: [{ b: 'c' }] }, { indices: false }), 'a%5Bb%5D=c'); + st.end(); + }); + + t.test('uses indices notation for arrays when indices=true', function (st) { + st.equal(qs.stringify({ a: ['b', 'c'] }, { indices: true }), 'a%5B0%5D=b&a%5B1%5D=c'); + st.end(); + }); + + t.test('uses indices notation for arrays when no arrayFormat is specified', function (st) { + st.equal(qs.stringify({ a: ['b', 'c'] }), 'a%5B0%5D=b&a%5B1%5D=c'); + st.end(); + }); + + t.test('uses indices notation for arrays when no arrayFormat=indices', function (st) { + st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }), 'a%5B0%5D=b&a%5B1%5D=c'); + st.end(); + }); + + t.test('uses repeat notation for arrays when no arrayFormat=repeat', function (st) { + st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }), 'a=b&a=c'); + st.end(); + }); + + t.test('uses brackets notation for arrays when no arrayFormat=brackets', function (st) { + st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }), 'a%5B%5D=b&a%5B%5D=c'); + st.end(); + }); + + t.test('stringifies a complicated object', function (st) { + st.equal(qs.stringify({ a: { b: 'c', d: 'e' } }), 'a%5Bb%5D=c&a%5Bd%5D=e'); + st.end(); + }); + + t.test('stringifies an empty value', function (st) { + st.equal(qs.stringify({ a: '' }), 'a='); + st.equal(qs.stringify({ a: null }, { strictNullHandling: true }), 'a'); + + st.equal(qs.stringify({ a: '', b: '' }), 'a=&b='); + st.equal(qs.stringify({ a: null, b: '' }, { strictNullHandling: true }), 'a&b='); + + st.equal(qs.stringify({ a: { b: '' } }), 'a%5Bb%5D='); + st.equal(qs.stringify({ a: { b: null } }, { strictNullHandling: true }), 'a%5Bb%5D'); + st.equal(qs.stringify({ a: { b: null } }, { strictNullHandling: false }), 'a%5Bb%5D='); + + st.end(); + }); + + t.test('stringifies an empty object', function (st) { + var obj = Object.create(null); + obj.a = 'b'; + st.equal(qs.stringify(obj), 'a=b'); + st.end(); + }); + + t.test('returns an empty string for invalid input', function (st) { + st.equal(qs.stringify(undefined), ''); + st.equal(qs.stringify(false), ''); + st.equal(qs.stringify(null), ''); + st.equal(qs.stringify(''), ''); + st.end(); + }); + + t.test('stringifies an object with an empty object as a child', function (st) { + var obj = { + a: Object.create(null) + }; + + obj.a.b = 'c'; + st.equal(qs.stringify(obj), 'a%5Bb%5D=c'); + st.end(); + }); + + t.test('drops keys with a value of undefined', function (st) { + st.equal(qs.stringify({ a: undefined }), ''); + + st.equal(qs.stringify({ a: { b: undefined, c: null } }, { strictNullHandling: true }), 'a%5Bc%5D'); + st.equal(qs.stringify({ a: { b: undefined, c: null } }, { strictNullHandling: false }), 'a%5Bc%5D='); + st.equal(qs.stringify({ a: { b: undefined, c: '' } }), 'a%5Bc%5D='); + st.end(); + }); + + t.test('url encodes values', function (st) { + st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c'); + st.end(); + }); + + t.test('stringifies a date', function (st) { + var now = new Date(); + var str = 'a=' + encodeURIComponent(now.toISOString()); + st.equal(qs.stringify({ a: now }), str); + st.end(); + }); + + t.test('stringifies the weird object from qs', function (st) { + st.equal(qs.stringify({ 'my weird field': '~q1!2"\'w$5&7/z8)?' }), 'my%20weird%20field=~q1%212%22%27w%245%267%2Fz8%29%3F'); + st.end(); + }); + + t.test('skips properties that are part of the object prototype', function (st) { + Object.prototype.crash = 'test'; + st.equal(qs.stringify({ a: 'b' }), 'a=b'); + st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c'); + delete Object.prototype.crash; + st.end(); + }); + + t.test('stringifies boolean values', function (st) { + st.equal(qs.stringify({ a: true }), 'a=true'); + st.equal(qs.stringify({ a: { b: true } }), 'a%5Bb%5D=true'); + st.equal(qs.stringify({ b: false }), 'b=false'); + st.equal(qs.stringify({ b: { c: false } }), 'b%5Bc%5D=false'); + st.end(); + }); + + t.test('stringifies buffer values', function (st) { + st.equal(qs.stringify({ a: new Buffer('test') }), 'a=test'); + st.equal(qs.stringify({ a: { b: new Buffer('test') } }), 'a%5Bb%5D=test'); + st.end(); + }); + + t.test('stringifies an object using an alternative delimiter', function (st) { + st.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d'); + st.end(); + }); + + t.test('doesn\'t blow up when Buffer global is missing', function (st) { + var tempBuffer = global.Buffer; + delete global.Buffer; + var result = qs.stringify({ a: 'b', c: 'd' }); + global.Buffer = tempBuffer; + st.equal(result, 'a=b&c=d'); + st.end(); + }); + + t.test('selects properties when filter=array', function (st) { + st.equal(qs.stringify({ a: 'b' }, { filter: ['a'] }), 'a=b'); + st.equal(qs.stringify({ a: 1 }, { filter: [] }), ''); + st.equal(qs.stringify({ a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, { filter: ['a', 'b', 0, 2] }), 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3'); + st.end(); + }); + + t.test('supports custom representations when filter=function', function (st) { + var calls = 0; + var obj = { a: 'b', c: 'd', e: { f: new Date(1257894000000) } }; + var filterFunc = function (prefix, value) { + calls++; + if (calls === 1) { + st.equal(prefix, '', 'prefix is empty'); + st.equal(value, obj); + } else if (prefix === 'c') { + return; + } else if (value instanceof Date) { + st.equal(prefix, 'e[f]'); + return value.getTime(); + } + return value; + }; + + st.equal(qs.stringify(obj, { filter: filterFunc }), 'a=b&e%5Bf%5D=1257894000000'); + st.equal(calls, 5); + st.end(); + }); + + t.test('can disable uri encoding', function (st) { + st.equal(qs.stringify({ a: 'b' }, { encode: false }), 'a=b'); + st.equal(qs.stringify({ a: { b: 'c' } }, { encode: false }), 'a[b]=c'); + st.equal(qs.stringify({ a: 'b', c: null }, { strictNullHandling: true, encode: false }), 'a=b&c'); + st.end(); + }); + + t.test('can sort the keys', function (st) { + var sort = function (a, b) { return a.localeCompare(b); }; + st.equal(qs.stringify({ a: 'c', z: 'y', b: 'f' }, { sort: sort }), 'a=c&b=f&z=y'); + st.equal(qs.stringify({ a: 'c', z: { j: 'a', i: 'b' }, b: 'f' }, { sort: sort }), 'a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a'); + st.end(); + }); + + t.test('can sort the keys at depth 3 or more too', function (st) { + var sort = function (a, b) { return a.localeCompare(b); }; + st.equal(qs.stringify({ a: 'a', z: { zj: {zjb: 'zjb', zja: 'zja'}, zi: {zib: 'zib', zia: 'zia'} }, b: 'b' }, { sort: sort, encode: false }), 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb'); + st.equal(qs.stringify({ a: 'a', z: { zj: {zjb: 'zjb', zja: 'zja'}, zi: {zib: 'zib', zia: 'zia'} }, b: 'b' }, { sort: null, encode: false }), 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b'); + st.end(); + }); + + t.test('can stringify with custom encoding', function (st) { + st.equal(qs.stringify({ 県: '大阪府', '': ''}, { + encoder: function (str) { + if (str.length === 0) { + return ''; + } + var buf = iconv.encode(str, 'shiftjis'); + var result = []; + for (var i=0; i < buf.length; ++i) { + result.push(buf.readUInt8(i).toString(16)); + } + return '%' + result.join('%'); + } + }), '%8c%a7=%91%e5%8d%e3%95%7b&='); + st.end(); + }); + + t.test('throws error with wrong encoder', function (st) { + st.throws(function () { + qs.stringify({}, { + encoder: 'string' + }); + }, new TypeError('Encoder has to be a function.')); + st.end(); + }); + + t.test('can use custom encoder for a buffer object', { + skip: typeof Buffer === 'undefined' + }, function (st) { + st.equal(qs.stringify({ a: new Buffer([1]) }, { + encoder: function (buffer) { + if (typeof buffer === 'string') { + return buffer; + } + return String.fromCharCode(buffer.readUInt8(0) + 97); + } + }), 'a=b'); + st.end(); + }); +}); diff --git a/hm_sunwell/node_modules/express/node_modules/qs/test/utils.js b/hm_sunwell/node_modules/express/node_modules/qs/test/utils.js new file mode 100644 index 0000000..4a8d824 --- /dev/null +++ b/hm_sunwell/node_modules/express/node_modules/qs/test/utils.js @@ -0,0 +1,9 @@ +'use strict'; + +var test = require('tape'); +var utils = require('../lib/utils'); + +test('merge()', function (t) { + t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key'); + t.end(); +}); diff --git a/hm_sunwell/node_modules/express/package.json b/hm_sunwell/node_modules/express/package.json new file mode 100644 index 0000000..c3aad3a --- /dev/null +++ b/hm_sunwell/node_modules/express/package.json @@ -0,0 +1,185 @@ +{ + "_args": [ + [ + "express@^4.13.4", + "/home/xor/shared_vm/git/node-sunwell" + ] + ], + "_from": "express@>=4.13.4 <5.0.0", + "_id": "express@4.14.0", + "_inCache": true, + "_installable": true, + "_location": "/express", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/express-4.14.0.tgz_1466095407850_0.17484632693231106" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "express", + "raw": "express@^4.13.4", + "rawSpec": "^4.13.4", + "scope": null, + "spec": ">=4.13.4 <5.0.0", + "type": "range" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "_shasum": "c1ee3f42cdc891fb3dc650a8922d51ec847d0d66", + "_shrinkwrap": null, + "_spec": "express@^4.13.4", + "_where": "/home/xor/shared_vm/git/node-sunwell", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk" + }, + "bugs": { + "url": "https://github.com/expressjs/express/issues" + }, + "contributors": [ + { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + { + "name": "Ciaran Jessup", + "email": "ciaranj@gmail.com" + }, + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com" + }, + { + "name": "Roman Shtylman", + "email": "shtylman+expressjs@gmail.com" + }, + { + "name": "Young Jae Sim", + "email": "hanul@hanul.me" + } + ], + "dependencies": { + "accepts": "~1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.1", + "content-type": "~1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "~2.2.0", + "depd": "~1.1.0", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "finalhandler": "0.5.0", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "~1.1.2", + "qs": "6.2.0", + "range-parser": "~1.2.0", + "send": "0.14.1", + "serve-static": "~1.11.1", + "type-is": "~1.6.13", + "utils-merge": "1.0.0", + "vary": "~1.1.0" + }, + "description": "Fast, unopinionated, minimalist web framework", + "devDependencies": { + "after": "0.8.1", + "body-parser": "~1.15.1", + "connect-redis": "~2.4.1", + "cookie-parser": "~1.4.3", + "cookie-session": "~1.2.0", + "ejs": "2.4.2", + "express-session": "~1.13.0", + "istanbul": "0.4.3", + "jade": "~1.11.0", + "marked": "0.3.5", + "method-override": "~2.3.6", + "mocha": "2.5.3", + "morgan": "~1.7.0", + "multiparty": "~4.1.2", + "should": "9.0.2", + "supertest": "1.2.0", + "vhost": "~3.0.2" + }, + "directories": {}, + "dist": { + "shasum": "c1ee3f42cdc891fb3dc650a8922d51ec847d0d66", + "tarball": "https://registry.npmjs.org/express/-/express-4.14.0.tgz" + }, + "engines": { + "node": ">= 0.10.0" + }, + "files": [ + "History.md", + "LICENSE", + "Readme.md", + "index.js", + "lib/" + ], + "gitHead": "9375a9afa9d7baa814b454c7a6818a7471aaef00", + "homepage": "http://expressjs.com/", + "keywords": [ + "api", + "app", + "express", + "framework", + "rest", + "restful", + "router", + "sinatra", + "web" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "hacksparrow", + "email": "captain@hacksparrow.com" + }, + { + "name": "jasnell", + "email": "jasnell@gmail.com" + }, + { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + } + ], + "name": "express", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/express.git" + }, + "scripts": { + "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/", + "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/" + }, + "version": "4.14.0" +} diff --git a/hm_sunwell/node_modules/extend/.eslintrc b/hm_sunwell/node_modules/extend/.eslintrc new file mode 100644 index 0000000..d49f173 --- /dev/null +++ b/hm_sunwell/node_modules/extend/.eslintrc @@ -0,0 +1,192 @@ +{ + "env": { + "browser": false, + "node": true, + "amd": false, + "mocha": false, + "jasmine": false + }, + + "rules": { + "accessor-pairs": [2, { getWithoutSet: false, setWithoutGet: true }], + "array-bracket-spacing": [2, "never", { + "singleValue": false, + "objectsInArrays": false, + "arraysInArrays": false + }], + "block-scoped-var": [0], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "camelcase": [2], + "comma-dangle": [2, "never"], + "comma-spacing": [2], + "comma-style": [2, "last"], + "complexity": [2, 15], + "computed-property-spacing": [2, "never"], + "consistent-return": [2], + "consistent-this": [0, "that"], + "constructor-super": [2], + "curly": [2, "all"], + "default-case": [2], + "dot-notation": [2, { "allowKeywords": true }], + "eol-last": [2], + "eqeqeq": [2], + "func-names": [0], + "func-style": [2, "expression"], + "generator-star-spacing": [2, { "before": false, "after": true }], + "global-strict": [0, "never"], + "guard-for-in": [0], + "handle-callback-err": [0], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "linebreak-style": [2, "unix"], + "lines-around-comment": [2, { + "beforeBlockComment": false, + "afterBlockComment": false, + "beforeLineComment": false, + "beforeLineComment": false, + "allowBlockStart": true, + "allowBlockEnd": true + }], + "quotes": [2, "single", "avoid-escape"], + "max-depth": [1, 4], + "max-len": [0, 80, 4], + "max-nested-callbacks": [2, 2], + "max-params": [2, 2], + "max-statements": [2, 21], + "new-parens": [2], + "new-cap": [2], + "newline-after-var": [0], + "no-alert": [2], + "no-array-constructor": [2], + "no-bitwise": [0], + "no-caller": [2], + "no-catch-shadow": [2], + "no-cond-assign": [2], + "no-console": [2], + "no-constant-condition": [2], + "no-continue": [2], + "no-control-regex": [2], + "no-debugger": [2], + "no-delete-var": [2], + "no-div-regex": [0], + "no-dupe-args": [2], + "no-dupe-keys": [2], + "no-duplicate-case": [2], + "no-else-return": [0], + "no-empty": [2], + "no-empty-character-class": [2], + "no-empty-label": [2], + "no-eq-null": [0], + "no-eval": [2], + "no-ex-assign": [2], + "no-extend-native": [2], + "no-extra-bind": [2], + "no-extra-boolean-cast": [2], + "no-extra-parens": [0], + "no-extra-semi": [2], + "no-fallthrough": [2], + "no-floating-decimal": [2], + "no-func-assign": [2], + "no-implied-eval": [2], + "no-inline-comments": [0], + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": [2], + "no-irregular-whitespace": [2], + "no-iterator": [2], + "no-label-var": [2], + "no-labels": [2], + "no-lone-blocks": [2], + "no-lonely-if": [2], + "no-loop-func": [2], + "no-mixed-requires": [0, false], + "no-mixed-spaces-and-tabs": [2, false], + "no-multi-spaces": [2], + "no-multi-str": [2], + "no-multiple-empty-lines": [2, {"max": 1}], + "no-native-reassign": [2], + "no-negated-in-lhs": [2], + "no-nested-ternary": [0], + "no-new": [2], + "no-new-func": [2], + "no-new-object": [2], + "no-new-require": [0], + "no-new-wrappers": [2], + "no-obj-calls": [2], + "no-octal": [2], + "no-octal-escape": [2], + "no-param-reassign": [2], + "no-path-concat": [0], + "no-plusplus": [0], + "no-process-env": [0], + "no-process-exit": [2], + "no-proto": [2], + "no-redeclare": [2], + "no-regex-spaces": [2], + "no-reserved-keys": [2], + "no-restricted-modules": [0], + "no-return-assign": [2, "always"], + "no-script-url": [2], + "no-self-compare": [0], + "no-sequences": [2], + "no-shadow": [2], + "no-shadow-restricted-names": [2], + "no-space-before-semi": [2], + "no-spaced-func": [2], + "no-sparse-arrays": [2], + "no-sync": [0], + "no-ternary": [0], + "no-this-before-super": [2], + "no-throw-literal": [2], + "no-trailing-spaces": [2, { "skipBlankLines": false }], + "no-undef": [2], + "no-undef-init": [2], + "no-undefined": [0], + "no-underscore-dangle": [2], + "no-unexpected-multiline": [2], + "no-unneeded-ternary": [2], + "no-unreachable": [2], + "no-unused-expressions": [2], + "no-unused-vars": [2, { "vars": "all", "args": "after-used" }], + "no-use-before-define": [2], + "no-void": [0], + "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], + "no-with": [2], + "no-wrap-func": [2], + "object-curly-spacing": [2, "always"], + "object-shorthand": [2, "never"], + "one-var": [0], + "operator-assignment": [0, "always"], + "operator-linebreak": [2, "none"], + "padded-blocks": [0], + "prefer-const": [0], + "quote-props": [0], + "radix": [0], + "semi": [2], + "semi-spacing": [2, { "before": false, "after": true }], + "sort-vars": [0], + "space-after-keywords": [2, "always"], + "space-before-function-paren": [2, { "anonymous": "always", "named": "never" }], + "space-before-blocks": [0, "always"], + "space-in-brackets": [0, "never", { + "singleValue": true, + "arraysInArrays": false, + "arraysInObjects": false, + "objectsInArrays": true, + "objectsInObjects": true, + "propertyName": false + }], + "space-in-parens": [2, "never"], + "space-infix-ops": [2], + "space-return-throw-case": [2], + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [2, "always"], + "spaced-line-comment": [0, "always"], + "strict": [2, "global"], + "use-isnan": [2], + "valid-jsdoc": [0], + "valid-typeof": [2], + "vars-on-top": [0], + "wrap-iife": [2], + "wrap-regex": [2], + "yoda": [2, "never", { "exceptRange": true, "onlyEquality": false }] + } +} diff --git a/hm_sunwell/node_modules/extend/.jscs.json b/hm_sunwell/node_modules/extend/.jscs.json new file mode 100644 index 0000000..7e84b28 --- /dev/null +++ b/hm_sunwell/node_modules/extend/.jscs.json @@ -0,0 +1,104 @@ +{ + "additionalRules": [], + + "requireSemicolons": true, + + "disallowMultipleSpaces": true, + + "disallowIdentifierNames": [], + + "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"], + + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"], + + "disallowSpaceAfterKeywords": [], + + "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true }, + "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, + "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, + "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, + "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, + + "requireSpaceBetweenArguments": true, + + "disallowSpacesInsideParentheses": true, + + "disallowSpacesInsideArrayBrackets": true, + + "disallowQuotedKeysInObjects": "allButReserved", + + "disallowSpaceAfterObjectKeys": true, + + "requireCommaBeforeLineBreak": true, + + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], + "requireSpaceAfterPrefixUnaryOperators": [], + + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "requireSpaceBeforePostfixUnaryOperators": [], + + "disallowSpaceBeforeBinaryOperators": [], + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + "disallowSpaceAfterBinaryOperators": [], + + "disallowImplicitTypeConversion": ["binary", "string"], + + "disallowKeywords": ["with", "eval"], + + "requireKeywordsOnNewLine": [], + "disallowKeywordsOnNewLine": ["else"], + + "requireLineFeedAtFileEnd": true, + + "disallowTrailingWhitespace": true, + + "disallowTrailingComma": true, + + "excludeFiles": ["node_modules/**", "vendor/**"], + + "disallowMultipleLineStrings": true, + + "requireDotNotation": true, + + "requireParenthesesAroundIIFE": true, + + "validateLineBreaks": "LF", + + "validateQuoteMarks": { + "escape": true, + "mark": "'" + }, + + "disallowOperatorBeforeLineBreak": [], + + "requireSpaceBeforeKeywords": [ + "do", + "for", + "if", + "else", + "switch", + "case", + "try", + "catch", + "finally", + "while", + "with", + "return" + ], + + "validateAlignedFunctionParameters": { + "lineBreakAfterOpeningBraces": true, + "lineBreakBeforeClosingBraces": true + }, + + "requirePaddingNewLinesBeforeExport": true, + + "validateNewlineAfterArrayElements": { + "maximum": 6 + }, + + "requirePaddingNewLinesAfterUseStrict": true +} + diff --git a/hm_sunwell/node_modules/extend/.npmignore b/hm_sunwell/node_modules/extend/.npmignore new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/hm_sunwell/node_modules/extend/.npmignore @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/hm_sunwell/node_modules/extend/.travis.yml b/hm_sunwell/node_modules/extend/.travis.yml new file mode 100644 index 0000000..ebef644 --- /dev/null +++ b/hm_sunwell/node_modules/extend/.travis.yml @@ -0,0 +1,44 @@ +language: node_js +node_js: + - "iojs-v2.3" + - "iojs-v2.2" + - "iojs-v2.1" + - "iojs-v2.0" + - "iojs-v1.8" + - "iojs-v1.7" + - "iojs-v1.6" + - "iojs-v1.5" + - "iojs-v1.4" + - "iojs-v1.3" + - "iojs-v1.2" + - "iojs-v1.1" + - "iojs-v1.0" + - "0.12" + - "0.11" + - "0.10" + - "0.9" + - "0.8" + - "0.6" + - "0.4" +before_install: + - '[ "${TRAVIS_NODE_VERSION}" = "0.6" ] || npm install -g npm@1.4.28 && npm install -g npm' +sudo: false +matrix: + fast_finish: true + allow_failures: + - node_js: "iojs-v2.2" + - node_js: "iojs-v2.1" + - node_js: "iojs-v2.0" + - node_js: "iojs-v1.7" + - node_js: "iojs-v1.6" + - node_js: "iojs-v1.5" + - node_js: "iojs-v1.4" + - node_js: "iojs-v1.3" + - node_js: "iojs-v1.2" + - node_js: "iojs-v1.1" + - node_js: "iojs-v1.0" + - node_js: "0.11" + - node_js: "0.9" + - node_js: "0.8" + - node_js: "0.6" + - node_js: "0.4" diff --git a/hm_sunwell/node_modules/extend/CHANGELOG.md b/hm_sunwell/node_modules/extend/CHANGELOG.md new file mode 100644 index 0000000..ee0cfd6 --- /dev/null +++ b/hm_sunwell/node_modules/extend/CHANGELOG.md @@ -0,0 +1,69 @@ +3.0.0 / 2015-07-01 +================== + * [Possible breaking change] Use global "strict" directive (#32) + * [Tests] `int` is an ES3 reserved word + * [Tests] Test up to `io.js` `v2.3` + * [Tests] Add `npm run eslint` + * [Dev Deps] Update `covert`, `jscs` + +2.0.1 / 2015-04-25 +================== + * Use an inline `isArray` check, for ES3 browsers. (#27) + * Some old browsers fail when an identifier is `toString` + * Test latest `node` and `io.js` versions on `travis-ci`; speed up builds + * Add license info to package.json (#25) + * Update `tape`, `jscs` + * Adding a CHANGELOG + +2.0.0 / 2014-10-01 +================== + * Increase code coverage to 100%; run code coverage as part of tests + * Add `npm run lint`; Run linter as part of tests + * Remove nodeType and setInterval checks in isPlainObject + * Updating `tape`, `jscs`, `covert` + * General style and README cleanup + +1.3.0 / 2014-06-20 +================== + * Add component.json for browser support (#18) + * Use SVG for badges in README (#16) + * Updating `tape`, `covert` + * Updating travis-ci to work with multiple node versions + * Fix `deep === false` bug (returning target as {}) (#14) + * Fixing constructor checks in isPlainObject + * Adding additional test coverage + * Adding `npm run coverage` + * Add LICENSE (#13) + * Adding a warning about `false`, per #11 + * General style and whitespace cleanup + +1.2.1 / 2013-09-14 +================== + * Fixing hasOwnProperty bugs that would only have shown up in specific browsers. Fixes #8 + * Updating `tape` + +1.2.0 / 2013-09-02 +================== + * Updating the README: add badges + * Adding a missing variable reference. + * Using `tape` instead of `buster` for tests; add more tests (#7) + * Adding node 0.10 to Travis CI (#6) + * Enabling "npm test" and cleaning up package.json (#5) + * Add Travis CI. + +1.1.3 / 2012-12-06 +================== + * Added unit tests. + * Ensure extend function is named. (Looks nicer in a stack trace.) + * README cleanup. + +1.1.1 / 2012-11-07 +================== + * README cleanup. + * Added installation instructions. + * Added a missing semicolon + +1.0.0 / 2012-04-08 +================== + * Initial commit + diff --git a/hm_sunwell/node_modules/extend/LICENSE b/hm_sunwell/node_modules/extend/LICENSE new file mode 100644 index 0000000..e16d6a5 --- /dev/null +++ b/hm_sunwell/node_modules/extend/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2014 Stefan Thomas + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/hm_sunwell/node_modules/extend/README.md b/hm_sunwell/node_modules/extend/README.md new file mode 100644 index 0000000..632fb0f --- /dev/null +++ b/hm_sunwell/node_modules/extend/README.md @@ -0,0 +1,62 @@ +[![Build Status][travis-svg]][travis-url] +[![dependency status][deps-svg]][deps-url] +[![dev dependency status][dev-deps-svg]][dev-deps-url] + +# extend() for Node.js [![Version Badge][npm-version-png]][npm-url] + +`node-extend` is a port of the classic extend() method from jQuery. It behaves as you expect. It is simple, tried and true. + +## Installation + +This package is available on [npm][npm-url] as: `extend` + +``` sh +npm install extend +``` + +## Usage + +**Syntax:** extend **(** [`deep`], `target`, `object1`, [`objectN`] **)** + +*Extend one object with one or more others, returning the modified object.* + +Keep in mind that the target object will be modified, and will be returned from extend(). + +If a boolean true is specified as the first argument, extend performs a deep copy, recursively copying any objects it finds. Otherwise, the copy will share structure with the original object(s). +Undefined properties are not copied. However, properties inherited from the object's prototype will be copied over. +Warning: passing `false` as the first argument is not supported. + +### Arguments + +* `deep` *Boolean* (optional) +If set, the merge becomes recursive (i.e. deep copy). +* `target` *Object* +The object to extend. +* `object1` *Object* +The object that will be merged into the first. +* `objectN` *Object* (Optional) +More objects to merge into the first. + +## License + +`node-extend` is licensed under the [MIT License][mit-license-url]. + +## Acknowledgements + +All credit to the jQuery authors for perfecting this amazing utility. + +Ported to Node.js by [Stefan Thomas][github-justmoon] with contributions by [Jonathan Buchanan][github-insin] and [Jordan Harband][github-ljharb]. + +[travis-svg]: https://travis-ci.org/justmoon/node-extend.svg +[travis-url]: https://travis-ci.org/justmoon/node-extend +[npm-url]: https://npmjs.org/package/extend +[mit-license-url]: http://opensource.org/licenses/MIT +[github-justmoon]: https://github.com/justmoon +[github-insin]: https://github.com/insin +[github-ljharb]: https://github.com/ljharb +[npm-version-png]: http://vb.teelaun.ch/justmoon/node-extend.svg +[deps-svg]: https://david-dm.org/justmoon/node-extend.svg +[deps-url]: https://david-dm.org/justmoon/node-extend +[dev-deps-svg]: https://david-dm.org/justmoon/node-extend/dev-status.svg +[dev-deps-url]: https://david-dm.org/justmoon/node-extend#info=devDependencies + diff --git a/hm_sunwell/node_modules/extend/component.json b/hm_sunwell/node_modules/extend/component.json new file mode 100644 index 0000000..1500a2f --- /dev/null +++ b/hm_sunwell/node_modules/extend/component.json @@ -0,0 +1,32 @@ +{ + "name": "extend", + "author": "Stefan Thomas (http://www.justmoon.net)", + "version": "3.0.0", + "description": "Port of jQuery.extend for node.js and the browser.", + "scripts": [ + "index.js" + ], + "contributors": [ + { + "name": "Jordan Harband", + "url": "https://github.com/ljharb" + } + ], + "keywords": [ + "extend", + "clone", + "merge" + ], + "repository" : { + "type": "git", + "url": "https://github.com/justmoon/node-extend.git" + }, + "dependencies": { + }, + "devDependencies": { + "tape" : "~3.0.0", + "covert": "~0.4.0", + "jscs": "~1.6.2" + } +} + diff --git a/hm_sunwell/node_modules/extend/index.js b/hm_sunwell/node_modules/extend/index.js new file mode 100644 index 0000000..f5ec75d --- /dev/null +++ b/hm_sunwell/node_modules/extend/index.js @@ -0,0 +1,86 @@ +'use strict'; + +var hasOwn = Object.prototype.hasOwnProperty; +var toStr = Object.prototype.toString; + +var isArray = function isArray(arr) { + if (typeof Array.isArray === 'function') { + return Array.isArray(arr); + } + + return toStr.call(arr) === '[object Array]'; +}; + +var isPlainObject = function isPlainObject(obj) { + if (!obj || toStr.call(obj) !== '[object Object]') { + return false; + } + + var hasOwnConstructor = hasOwn.call(obj, 'constructor'); + var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); + // Not own constructor property must be Object + if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) {/**/} + + return typeof key === 'undefined' || hasOwn.call(obj, key); +}; + +module.exports = function extend() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0], + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if (typeof target === 'boolean') { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) { + target = {}; + } + + for (; i < length; ++i) { + options = arguments[i]; + // Only deal with non-null/undefined values + if (options != null) { + // Extend the base object + for (name in options) { + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target !== copy) { + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[name] = extend(deep, clone, copy); + + // Don't bring in undefined values + } else if (typeof copy !== 'undefined') { + target[name] = copy; + } + } + } + } + } + + // Return the modified object + return target; +}; + diff --git a/hm_sunwell/node_modules/extend/package.json b/hm_sunwell/node_modules/extend/package.json new file mode 100644 index 0000000..39805eb --- /dev/null +++ b/hm_sunwell/node_modules/extend/package.json @@ -0,0 +1,98 @@ +{ + "_args": [ + [ + "extend@~3.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/request" + ] + ], + "_from": "extend@>=3.0.0 <3.1.0", + "_id": "extend@3.0.0", + "_inCache": true, + "_installable": true, + "_location": "/extend", + "_nodeVersion": "2.3.1", + "_npmUser": { + "email": "ljharb@gmail.com", + "name": "ljharb" + }, + "_npmVersion": "2.11.3", + "_phantomChildren": {}, + "_requested": { + "name": "extend", + "raw": "extend@~3.0.0", + "rawSpec": "~3.0.0", + "scope": null, + "spec": ">=3.0.0 <3.1.0", + "type": "range" + }, + "_requiredBy": [ + "/request" + ], + "_resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "_shasum": "5a474353b9f3353ddd8176dfd37b91c83a46f1d4", + "_shrinkwrap": null, + "_spec": "extend@~3.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/request", + "author": { + "email": "justmoon@members.fsf.org", + "name": "Stefan Thomas", + "url": "http://www.justmoon.net" + }, + "bugs": { + "url": "https://github.com/justmoon/node-extend/issues" + }, + "contributors": [ + { + "name": "Jordan Harband", + "url": "https://github.com/ljharb" + } + ], + "dependencies": {}, + "description": "Port of jQuery.extend for node.js and the browser", + "devDependencies": { + "covert": "^1.1.0", + "eslint": "^0.24.0", + "jscs": "^1.13.1", + "tape": "^4.0.0" + }, + "directories": {}, + "dist": { + "shasum": "5a474353b9f3353ddd8176dfd37b91c83a46f1d4", + "tarball": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "gitHead": "148e7270cab2e9413af2cd0cab147070d755ed6d", + "homepage": "https://github.com/justmoon/node-extend#readme", + "keywords": [ + "clone", + "extend", + "merge" + ], + "license": "MIT", + "main": "index", + "maintainers": [ + { + "name": "justmoon", + "email": "justmoon@members.fsf.org" + }, + { + "name": "ljharb", + "email": "ljharb@gmail.com" + } + ], + "name": "extend", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/justmoon/node-extend.git" + }, + "scripts": { + "coverage": "covert test/index.js", + "coverage-quiet": "covert test/index.js --quiet", + "eslint": "eslint *.js */*.js", + "jscs": "jscs *.js */*.js", + "lint": "npm run jscs && npm run eslint", + "test": "npm run lint && node test/index.js && npm run coverage-quiet" + }, + "version": "3.0.0" +} diff --git a/hm_sunwell/node_modules/extsprintf/.gitmodules b/hm_sunwell/node_modules/extsprintf/.gitmodules new file mode 100644 index 0000000..4e0f5e2 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/.gitmodules @@ -0,0 +1,6 @@ +[submodule "deps/jsstyle"] + path = deps/jsstyle + url = git://github.com/davepacheco/jsstyle +[submodule "deps/javascriptlint"] + path = deps/javascriptlint + url = git://github.com/davepacheco/javascriptlint diff --git a/hm_sunwell/node_modules/extsprintf/LICENSE b/hm_sunwell/node_modules/extsprintf/LICENSE new file mode 100644 index 0000000..cbc0bb3 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012, Joyent, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE diff --git a/hm_sunwell/node_modules/extsprintf/Makefile b/hm_sunwell/node_modules/extsprintf/Makefile new file mode 100644 index 0000000..1deeb5f --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# +# Makefile: top-level Makefile +# +# This Makefile contains only repo-specific logic and uses included makefiles +# to supply common targets (javascriptlint, jsstyle, restdown, etc.), which are +# used by other repos as well. +# + +# +# Files +# +JS_FILES := $(shell find lib -name '*.js') +JSL_FILES_NODE = $(JS_FILES) +JSSTYLE_FILES = $(JS_FILES) +JSL_CONF_NODE = jsl.node.conf + +# Default target is "check" +check: + +include ./Makefile.deps +include ./Makefile.targ diff --git a/hm_sunwell/node_modules/extsprintf/Makefile.deps b/hm_sunwell/node_modules/extsprintf/Makefile.deps new file mode 100644 index 0000000..2811bde --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/Makefile.deps @@ -0,0 +1,39 @@ +# -*- mode: makefile -*- +# +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# +# Makefile.deps: Makefile for including common tools as dependencies +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +# This file is separate from Makefile.targ so that teams can choose +# independently whether to use the common targets in Makefile.targ and the +# common tools here. +# + +# +# javascriptlint +# +JSL_EXEC ?= deps/javascriptlint/build/install/jsl +JSL ?= python2.6 $(JSL_EXEC) + +$(JSL_EXEC): | deps/javascriptlint/.git + cd deps/javascriptlint && make install + +# +# jsstyle +# +JSSTYLE_EXEC ?= deps/jsstyle/jsstyle +JSSTYLE ?= $(JSSTYLE_EXEC) + +$(JSSTYLE_EXEC): | deps/jsstyle/.git + +# +# restdown +# +RESTDOWN_EXEC ?= deps/restdown/bin/restdown +RESTDOWN ?= python2.6 $(RESTDOWN_EXEC) +$(RESTDOWN_EXEC): | deps/restdown/.git diff --git a/hm_sunwell/node_modules/extsprintf/Makefile.targ b/hm_sunwell/node_modules/extsprintf/Makefile.targ new file mode 100644 index 0000000..2a64fe7 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/Makefile.targ @@ -0,0 +1,285 @@ +# -*- mode: makefile -*- +# +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# +# Makefile.targ: common targets. +# +# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped +# into other repos as-is without requiring any modifications. If you find +# yourself changing this file, you should instead update the original copy in +# eng.git and then update your repo to use the new version. +# +# This Makefile defines several useful targets and rules. You can use it by +# including it from a Makefile that specifies some of the variables below. +# +# Targets defined in this Makefile: +# +# check Checks JavaScript files for lint and style +# Checks bash scripts for syntax +# Checks SMF manifests for validity against the SMF DTD +# +# clean Removes built files +# +# docs Builds restdown documentation in docs/ +# +# prepush Depends on "check" and "test" +# +# test Does nothing (you should override this) +# +# xref Generates cscope (source cross-reference index) +# +# For details on what these targets are supposed to do, see the Joyent +# Engineering Guide. +# +# To make use of these targets, you'll need to set some of these variables. Any +# variables left unset will simply not be used. +# +# BASH_FILES Bash scripts to check for syntax +# (paths relative to top-level Makefile) +# +# CLEAN_FILES Files to remove as part of the "clean" target. Note +# that files generated by targets in this Makefile are +# automatically included in CLEAN_FILES. These include +# restdown-generated HTML and JSON files. +# +# DOC_FILES Restdown (documentation source) files. These are +# assumed to be contained in "docs/", and must NOT +# contain the "docs/" prefix. +# +# JSL_CONF_NODE Specify JavaScriptLint configuration files +# JSL_CONF_WEB (paths relative to top-level Makefile) +# +# Node.js and Web configuration files are separate +# because you'll usually want different global variable +# configurations. If no file is specified, none is given +# to jsl, which causes it to use a default configuration, +# which probably isn't what you want. +# +# JSL_FILES_NODE JavaScript files to check with Node config file. +# JSL_FILES_WEB JavaScript files to check with Web config file. +# +# You can also override these variables: +# +# BASH Path to bash (default: bash) +# +# CSCOPE_DIRS Directories to search for source files for the cscope +# index. (default: ".") +# +# JSL Path to JavaScriptLint (default: "jsl") +# +# JSL_FLAGS_NODE Additional flags to pass through to JSL +# JSL_FLAGS_WEB +# JSL_FLAGS +# +# JSSTYLE Path to jsstyle (default: jsstyle) +# +# JSSTYLE_FLAGS Additional flags to pass through to jsstyle +# + +# +# Defaults for the various tools we use. +# +BASH ?= bash +BASHSTYLE ?= tools/bashstyle +CP ?= cp +CSCOPE ?= cscope +CSCOPE_DIRS ?= . +JSL ?= jsl +JSSTYLE ?= jsstyle +MKDIR ?= mkdir -p +MV ?= mv +RESTDOWN_FLAGS ?= +RMTREE ?= rm -rf +JSL_FLAGS ?= --nologo --nosummary + +ifeq ($(shell uname -s),SunOS) + TAR ?= gtar +else + TAR ?= tar +endif + + +# +# Defaults for other fixed values. +# +BUILD = build +DISTCLEAN_FILES += $(BUILD) +DOC_BUILD = $(BUILD)/docs/public + +# +# Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}. +# +ifneq ($(origin JSL_CONF_NODE), undefined) + JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE) +endif + +ifneq ($(origin JSL_CONF_WEB), undefined) + JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB) +endif + +# +# Targets. For descriptions on what these are supposed to do, see the +# Joyent Engineering Guide. +# + +# +# Instruct make to keep around temporary files. We have rules below that +# automatically update git submodules as needed, but they employ a deps/*/.git +# temporary file. Without this directive, make tries to remove these .git +# directories after the build has completed. +# +.SECONDARY: $($(wildcard deps/*):%=%/.git) + +# +# This rule enables other rules that use files from a git submodule to have +# those files depend on deps/module/.git and have "make" automatically check +# out the submodule as needed. +# +deps/%/.git: + git submodule update --init deps/$* + +# +# These recipes make heavy use of dynamically-created phony targets. The parent +# Makefile defines a list of input files like BASH_FILES. We then say that each +# of these files depends on a fake target called filename.bashchk, and then we +# define a pattern rule for those targets that runs bash in check-syntax-only +# mode. This mechanism has the nice properties that if you specify zero files, +# the rule becomes a noop (unlike a single rule to check all bash files, which +# would invoke bash with zero files), and you can check individual files from +# the command line with "make filename.bashchk". +# +.PHONY: check-bash +check-bash: $(BASH_FILES:%=%.bashchk) $(BASH_FILES:%=%.bashstyle) + +%.bashchk: % + $(BASH) -n $^ + +%.bashstyle: % + $(BASHSTYLE) $^ + +.PHONY: check-jsl check-jsl-node check-jsl-web +check-jsl: check-jsl-node check-jsl-web + +check-jsl-node: $(JSL_FILES_NODE:%=%.jslnodechk) + +check-jsl-web: $(JSL_FILES_WEB:%=%.jslwebchk) + +%.jslnodechk: % $(JSL_EXEC) + $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $< + +%.jslwebchk: % $(JSL_EXEC) + $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $< + +.PHONY: check-jsstyle +check-jsstyle: $(JSSTYLE_FILES:%=%.jsstylechk) + +%.jsstylechk: % $(JSSTYLE_EXEC) + $(JSSTYLE) $(JSSTYLE_FLAGS) $< + +.PHONY: check +check: check-jsl check-jsstyle check-bash + @echo check ok + +.PHONY: clean +clean:: + -$(RMTREE) $(CLEAN_FILES) + +.PHONY: distclean +distclean:: clean + -$(RMTREE) $(DISTCLEAN_FILES) + +CSCOPE_FILES = cscope.in.out cscope.out cscope.po.out +CLEAN_FILES += $(CSCOPE_FILES) + +.PHONY: xref +xref: cscope.files + $(CSCOPE) -bqR + +.PHONY: cscope.files +cscope.files: + find $(CSCOPE_DIRS) -name '*.c' -o -name '*.h' -o -name '*.cc' \ + -o -name '*.js' -o -name '*.s' -o -name '*.cpp' > $@ + +# +# The "docs" target is complicated because we do several things here: +# +# (1) Use restdown to build HTML and JSON files from each of DOC_FILES. +# +# (2) Copy these files into $(DOC_BUILD) (build/docs/public), which +# functions as a complete copy of the documentation that could be +# mirrored or served over HTTP. +# +# (3) Then copy any directories and media from docs/media into +# $(DOC_BUILD)/media. This allows projects to include their own media, +# including files that will override same-named files provided by +# restdown. +# +# Step (3) is the surprisingly complex part: in order to do this, we need to +# identify the subdirectories in docs/media, recreate them in +# $(DOC_BUILD)/media, then do the same with the files. +# +DOC_MEDIA_DIRS := $(shell find docs/media -type d 2>/dev/null | grep -v "^docs/media$$") +DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/media/%=%) +DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%) + +DOC_MEDIA_FILES := $(shell find docs/media -type f 2>/dev/null) +DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%) +DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%) + +# +# Like the other targets, "docs" just depends on the final files we want to +# create in $(DOC_BUILD), leveraging other targets and recipes to define how +# to get there. +# +.PHONY: docs +docs: \ + $(DOC_FILES:%.restdown=$(DOC_BUILD)/%.html) \ + $(DOC_FILES:%.restdown=$(DOC_BUILD)/%.json) \ + $(DOC_MEDIA_FILES_BUILD) + +# +# We keep the intermediate files so that the next build can see whether the +# files in DOC_BUILD are up to date. +# +.PRECIOUS: \ + $(DOC_FILES:%.restdown=docs/%.html) \ + $(DOC_FILES:%.restdown=docs/%json) + +# +# We do clean those intermediate files, as well as all of DOC_BUILD. +# +CLEAN_FILES += \ + $(DOC_BUILD) \ + $(DOC_FILES:%.restdown=docs/%.html) \ + $(DOC_FILES:%.restdown=docs/%.json) + +# +# Before installing the files, we must make sure the directories exist. The | +# syntax tells make that the dependency need only exist, not be up to date. +# Otherwise, it might try to rebuild spuriously because the directory itself +# appears out of date. +# +$(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD) + +$(DOC_BUILD)/%: docs/% | $(DOC_BUILD) + $(CP) $< $@ + +docs/%.json docs/%.html: docs/%.restdown | $(DOC_BUILD) $(RESTDOWN_EXEC) + $(RESTDOWN) $(RESTDOWN_FLAGS) -m $(DOC_BUILD) $< + +$(DOC_BUILD): + $(MKDIR) $@ + +$(DOC_MEDIA_DIRS_BUILD): + $(MKDIR) $@ + +# +# The default "test" target does nothing. This should usually be overridden by +# the parent Makefile. It's included here so we can define "prepush" without +# requiring the repo to define "test". +# +.PHONY: test +test: + +.PHONY: prepush +prepush: check test diff --git a/hm_sunwell/node_modules/extsprintf/README.md b/hm_sunwell/node_modules/extsprintf/README.md new file mode 100644 index 0000000..702e4e2 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/README.md @@ -0,0 +1,39 @@ +# extsprintf: extended POSIX-style sprintf + +Stripped down version of s[n]printf(3c). We make a best effort to throw an +exception when given a format string we don't understand, rather than ignoring +it, so that we won't break existing programs if/when we go implement the rest +of this. + +This implementation currently supports specifying + +* field alignment ('-' flag), +* zero-pad ('0' flag) +* always show numeric sign ('+' flag), +* field width +* conversions for strings, decimal integers, and floats (numbers). +* argument size specifiers. These are all accepted but ignored, since + Javascript has no notion of the physical size of an argument. + +Everything else is currently unsupported, most notably: precision, unsigned +numbers, non-decimal numbers, and characters. + +Besides the usual POSIX conversions, this implementation supports: + +* `%j`: pretty-print a JSON object (using node's "inspect") +* `%r`: pretty-print an Error object + +# Example + +First, install it: + + # npm install extsprintf + +Now, use it: + + var mod_extsprintf = require('extsprintf'); + console.log(mod_extsprintf.sprintf('hello %25s', 'world')); + +outputs: + + hello world diff --git a/hm_sunwell/node_modules/extsprintf/examples/simple.js b/hm_sunwell/node_modules/extsprintf/examples/simple.js new file mode 100644 index 0000000..9f342f5 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/examples/simple.js @@ -0,0 +1,2 @@ +var mod_extsprintf = require('extsprintf'); +console.log(mod_extsprintf.sprintf('hello %25s', 'world')); diff --git a/hm_sunwell/node_modules/extsprintf/jsl.node.conf b/hm_sunwell/node_modules/extsprintf/jsl.node.conf new file mode 100644 index 0000000..03f787f --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/jsl.node.conf @@ -0,0 +1,137 @@ +# +# Configuration File for JavaScript Lint +# +# This configuration file can be used to lint a collection of scripts, or to enable +# or disable warnings for scripts that are linted via the command line. +# + +### Warnings +# Enable or disable warnings based on requirements. +# Use "+WarningName" to display or "-WarningName" to suppress. +# ++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent ++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity ++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement ++anon_no_return_value # anonymous function does not always return value ++assign_to_function_call # assignment to a function call +-block_without_braces # block statement without curly braces ++comma_separated_stmts # multiple statements separated by commas (use semicolons?) ++comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) ++default_not_at_end # the default case is not at the end of the switch statement ++dup_option_explicit # duplicate "option explicit" control comment ++duplicate_case_in_switch # duplicate case in switch statement ++duplicate_formal # duplicate formal argument {name} ++empty_statement # empty statement or extra semicolon ++identifier_hides_another # identifer {name} hides an identifier in a parent scope +-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement ++incorrect_version # Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version. ++invalid_fallthru # unexpected "fallthru" control comment ++invalid_pass # unexpected "pass" control comment ++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax ++leading_decimal_point # leading decimal point may indicate a number or an object member ++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax ++meaningless_block # meaningless block; curly braces have no impact ++mismatch_ctrl_comments # mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence ++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma ++missing_break # missing break statement ++missing_break_for_last_case # missing break statement for last case in switch ++missing_default_case # missing default case in switch statement ++missing_option_explicit # the "option explicit" control comment is missing ++missing_semicolon # missing semicolon ++missing_semicolon_for_lambda # missing semicolon for lambda assignment ++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs ++nested_comment # nested comment ++no_return_value # function {name} does not always return a value ++octal_number # leading zeros make an octal number ++parseint_missing_radix # parseInt missing radix parameter ++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag ++redeclared_var # redeclaration of {name} ++trailing_comma_in_array # extra comma is not recommended in array initializers ++trailing_decimal_point # trailing decimal point may indicate a number or an object member ++undeclared_identifier # undeclared identifier: {name} ++unreachable_code # unreachable code +-unreferenced_argument # argument declared but never referenced: {name} +-unreferenced_function # function is declared but never referenced: {name} ++unreferenced_variable # variable is declared but never referenced: {name} ++unsupported_version # JavaScript {version} is not supported ++use_of_label # use of label ++useless_assign # useless assignment ++useless_comparison # useless comparison; comparing identical expressions +-useless_quotes # the quotation marks are unnecessary ++useless_void # use of the void type may be unnecessary (void is always undefined) ++var_hides_arg # variable {name} hides argument ++want_assign_or_call # expected an assignment or function call ++with_statement # with statement hides undeclared variables; use temporary variable instead + + +### Output format +# Customize the format of the error message. +# __FILE__ indicates current file path +# __FILENAME__ indicates current file name +# __LINE__ indicates current line +# __COL__ indicates current column +# __ERROR__ indicates error message (__ERROR_PREFIX__: __ERROR_MSG__) +# __ERROR_NAME__ indicates error name (used in configuration file) +# __ERROR_PREFIX__ indicates error prefix +# __ERROR_MSG__ indicates error message +# +# For machine-friendly output, the output format can be prefixed with +# "encode:". If specified, all items will be encoded with C-slashes. +# +# Visual Studio syntax (default): ++output-format __FILE__(__LINE__): __ERROR__ +# Alternative syntax: +#+output-format __FILE__:__LINE__: __ERROR__ + + +### Context +# Show the in-line position of the error. +# Use "+context" to display or "-context" to suppress. +# ++context + + +### Control Comments +# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for +# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is +# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason, +# although legacy control comments are enabled by default for backward compatibility. +# +-legacy_control_comments + + +### Defining identifiers +# By default, "option explicit" is enabled on a per-file basis. +# To enable this for all files, use "+always_use_option_explicit" +-always_use_option_explicit + +# Define certain identifiers of which the lint is not aware. +# (Use this in conjunction with the "undeclared identifier" warning.) +# +# Common uses for webpages might be: ++define __dirname ++define clearInterval ++define clearTimeout ++define console ++define exports ++define global ++define process ++define require ++define setInterval ++define setTimeout ++define Buffer ++define JSON ++define Math + +### JavaScript Version +# To change the default JavaScript version: +#+default-type text/javascript;version=1.5 +#+default-type text/javascript;e4x=1 + +### Files +# Specify which files to lint +# Use "+recurse" to enable recursion (disabled by default). +# To add a set of files, use "+process FileName", "+process Folder\Path\*.js", +# or "+process Folder\Path\*.htm". +# + diff --git a/hm_sunwell/node_modules/extsprintf/lib/extsprintf.js b/hm_sunwell/node_modules/extsprintf/lib/extsprintf.js new file mode 100644 index 0000000..61ff891 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/lib/extsprintf.js @@ -0,0 +1,166 @@ +/* + * extsprintf.js: extended POSIX-style sprintf + */ + +var mod_assert = require('assert'); +var mod_util = require('util'); + +/* + * Public interface + */ +exports.sprintf = jsSprintf; + +/* + * Stripped down version of s[n]printf(3c). We make a best effort to throw an + * exception when given a format string we don't understand, rather than + * ignoring it, so that we won't break existing programs if/when we go implement + * the rest of this. + * + * This implementation currently supports specifying + * - field alignment ('-' flag), + * - zero-pad ('0' flag) + * - always show numeric sign ('+' flag), + * - field width + * - conversions for strings, decimal integers, and floats (numbers). + * - argument size specifiers. These are all accepted but ignored, since + * Javascript has no notion of the physical size of an argument. + * + * Everything else is currently unsupported, most notably precision, unsigned + * numbers, non-decimal numbers, and characters. + */ +function jsSprintf(fmt) +{ + var regex = [ + '([^%]*)', /* normal text */ + '%', /* start of format */ + '([\'\\-+ #0]*?)', /* flags (optional) */ + '([1-9]\\d*)?', /* width (optional) */ + '(\\.([1-9]\\d*))?', /* precision (optional) */ + '[lhjztL]*?', /* length mods (ignored) */ + '([diouxXfFeEgGaAcCsSp%jr])' /* conversion */ + ].join(''); + + var re = new RegExp(regex); + var args = Array.prototype.slice.call(arguments, 1); + var flags, width, precision, conversion; + var left, pad, sign, arg, match; + var ret = ''; + var argn = 1; + + mod_assert.equal('string', typeof (fmt)); + + while ((match = re.exec(fmt)) !== null) { + ret += match[1]; + fmt = fmt.substring(match[0].length); + + flags = match[2] || ''; + width = match[3] || 0; + precision = match[4] || ''; + conversion = match[6]; + left = false; + sign = false; + pad = ' '; + + if (conversion == '%') { + ret += '%'; + continue; + } + + if (args.length === 0) + throw (new Error('too few args to sprintf')); + + arg = args.shift(); + argn++; + + if (flags.match(/[\' #]/)) + throw (new Error( + 'unsupported flags: ' + flags)); + + if (precision.length > 0) + throw (new Error( + 'non-zero precision not supported')); + + if (flags.match(/-/)) + left = true; + + if (flags.match(/0/)) + pad = '0'; + + if (flags.match(/\+/)) + sign = true; + + switch (conversion) { + case 's': + if (arg === undefined || arg === null) + throw (new Error('argument ' + argn + + ': attempted to print undefined or null ' + + 'as a string')); + ret += doPad(pad, width, left, arg.toString()); + break; + + case 'd': + arg = Math.floor(arg); + /*jsl:fallthru*/ + case 'f': + sign = sign && arg > 0 ? '+' : ''; + ret += sign + doPad(pad, width, left, + arg.toString()); + break; + + case 'j': /* non-standard */ + if (width === 0) + width = 10; + ret += mod_util.inspect(arg, false, width); + break; + + case 'r': /* non-standard */ + ret += dumpException(arg); + break; + + default: + throw (new Error('unsupported conversion: ' + + conversion)); + } + } + + ret += fmt; + return (ret); +} + +function doPad(chr, width, left, str) +{ + var ret = str; + + while (ret.length < width) { + if (left) + ret += chr; + else + ret = chr + ret; + } + + return (ret); +} + +/* + * This function dumps long stack traces for exceptions having a cause() method. + * See node-verror for an example. + */ +function dumpException(ex) +{ + var ret; + + if (!(ex instanceof Error)) + throw (new Error(jsSprintf('invalid type for %%r: %j', ex))); + + /* Note that V8 prepends "ex.stack" with ex.toString(). */ + ret = 'EXCEPTION: ' + ex.constructor.name + ': ' + ex.stack; + + if (ex.cause && typeof (ex.cause) === 'function') { + var cex = ex.cause(); + if (cex) { + ret += '\nCaused by: ' + dumpException(cex); + } + } + + return (ret); +} diff --git a/hm_sunwell/node_modules/extsprintf/package.json b/hm_sunwell/node_modules/extsprintf/package.json new file mode 100644 index 0000000..af85874 --- /dev/null +++ b/hm_sunwell/node_modules/extsprintf/package.json @@ -0,0 +1,66 @@ +{ + "_args": [ + [ + "extsprintf@1.0.2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/jsprim" + ] + ], + "_from": "extsprintf@1.0.2", + "_id": "extsprintf@1.0.2", + "_inCache": true, + "_installable": true, + "_location": "/extsprintf", + "_npmUser": { + "email": "dap@cs.brown.edu", + "name": "dap" + }, + "_npmVersion": "1.1.65", + "_phantomChildren": {}, + "_requested": { + "name": "extsprintf", + "raw": "extsprintf@1.0.2", + "rawSpec": "1.0.2", + "scope": null, + "spec": "1.0.2", + "type": "version" + }, + "_requiredBy": [ + "/jsprim", + "/verror" + ], + "_resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "_shasum": "e1080e0658e300b06294990cc70e1502235fd550", + "_shrinkwrap": null, + "_spec": "extsprintf@1.0.2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/jsprim", + "bugs": { + "url": "https://github.com/davepacheco/node-extsprintf/issues" + }, + "dependencies": {}, + "description": "extended POSIX-style sprintf", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "e1080e0658e300b06294990cc70e1502235fd550", + "tarball": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + }, + "engines": [ + "node >=0.6.0" + ], + "homepage": "https://github.com/davepacheco/node-extsprintf#readme", + "main": "./lib/extsprintf.js", + "maintainers": [ + { + "name": "dap", + "email": "dap@cs.brown.edu" + } + ], + "name": "extsprintf", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/davepacheco/node-extsprintf.git" + }, + "version": "1.0.2" +} diff --git a/hm_sunwell/node_modules/fast-levenshtein/LICENSE.md b/hm_sunwell/node_modules/fast-levenshtein/LICENSE.md new file mode 100644 index 0000000..6212406 --- /dev/null +++ b/hm_sunwell/node_modules/fast-levenshtein/LICENSE.md @@ -0,0 +1,25 @@ +(MIT License) + +Copyright (c) 2013 [Ramesh Nair](http://www.hiddentao.com/) + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + diff --git a/hm_sunwell/node_modules/fast-levenshtein/README.md b/hm_sunwell/node_modules/fast-levenshtein/README.md new file mode 100644 index 0000000..a778995 --- /dev/null +++ b/hm_sunwell/node_modules/fast-levenshtein/README.md @@ -0,0 +1,104 @@ +# fast-levenshtein - Levenshtein algorithm in Javascript + +[![Build Status](https://secure.travis-ci.org/hiddentao/fast-levenshtein.png)](http://travis-ci.org/hiddentao/fast-levenshtein) +[![NPM module](https://badge.fury.io/js/fast-levenshtein.png)](https://badge.fury.io/js/fast-levenshtein) +[![NPM downloads](https://img.shields.io/npm/dm/fast-levenshtein.svg?maxAge=2592000)](https://www.npmjs.com/package/fast-levenshtein) +[![Follow on Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Follow&maxAge=2592000)](https://twitter.com/hiddentao) + +An efficient Javascript implementation of the [Levenshtein algorithm](http://en.wikipedia.org/wiki/Levenshtein_distance) with locale-specific collator support. + +## Features + +* Works in node.js and in the browser. +* Better performance than other implementations by not needing to store the whole matrix ([more info](http://www.codeproject.com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm)). +* Locale-sensitive string comparisions if needed. +* Comprehensive test suite and performance benchmark. +* Small: <1 KB minified and gzipped + +## Installation + +### node.js + +Install using [npm](http://npmjs.org/): + +```bash +$ npm install fast-levenshtein +``` + +### Browser + +Using bower: + +```bash +$ bower install fast-levenshtein +``` + +If you are not using any module loader system then the API will then be accessible via the `window.Levenshtein` object. + +## Examples + +**Default usage** + +```javascript +var levenshtein = require('fast-levenshtein'); + +var distance = levenshtein.get('back', 'book'); // 2 +var distance = levenshtein.get('我愛你', '我叫你'); // 1 +``` + +**Locale-sensitive string comparisons** + +It supports using [Intl.Collator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator) for locale-sensitive string comparisons: + +```javascript +var levenshtein = require('fast-levenshtein'); + +levenshtein.get('mikailovitch', 'Mikhaïlovitch', { useCollator: true}); +// 1 +``` + +## Building and Testing + +To build the code and run the tests: + +```bash +$ npm install -g grunt-cli +$ npm install +$ npm run build +``` + +## Performance + +_Thanks to [Titus Wormer](https://github.com/wooorm) for [encouraging me](https://github.com/hiddentao/fast-levenshtein/issues/1) to do this._ + +Benchmarked against other node.js levenshtein distance modules (on Macbook Air 2012, Core i7, 8GB RAM): + +```bash +Running suite Implementation comparison [benchmark/speed.js]... +>> levenshtein-edit-distance x 234 ops/sec ±3.02% (73 runs sampled) +>> levenshtein-component x 422 ops/sec ±4.38% (83 runs sampled) +>> levenshtein-deltas x 283 ops/sec ±3.83% (78 runs sampled) +>> natural x 255 ops/sec ±0.76% (88 runs sampled) +>> levenshtein x 180 ops/sec ±3.55% (86 runs sampled) +>> fast-levenshtein x 1,792 ops/sec ±2.72% (95 runs sampled) +Benchmark done. +Fastest test is fast-levenshtein at 4.2x faster than levenshtein-component +``` + +You can run this benchmark yourself by doing: + +```bash +$ npm install +$ npm run build +$ npm run benchmark +``` + +## Contributing + +If you wish to submit a pull request please update and/or create new tests for any changes you make and ensure the grunt build passes. + +See [CONTRIBUTING.md](https://github.com/hiddentao/fast-levenshtein/blob/master/CONTRIBUTING.md) for details. + +## License + +MIT - see [LICENSE.md](https://github.com/hiddentao/fast-levenshtein/blob/master/LICENSE.md) diff --git a/hm_sunwell/node_modules/fast-levenshtein/levenshtein.js b/hm_sunwell/node_modules/fast-levenshtein/levenshtein.js new file mode 100644 index 0000000..404a315 --- /dev/null +++ b/hm_sunwell/node_modules/fast-levenshtein/levenshtein.js @@ -0,0 +1,102 @@ +(function() { + 'use strict'; + + var collator; + try { + collator = (typeof Intl !== "undefined" && typeof Intl.Collator !== "undefined") ? Intl.Collator("generic", { sensitivity: "base" }) : null; + } catch (err){ + console.log("Collator could not be initialized and wouldn't be used"); + } + // arrays to re-use + var prevRow = [], + str2Char = []; + + /** + * Based on the algorithm at http://en.wikipedia.org/wiki/Levenshtein_distance. + */ + var Levenshtein = { + /** + * Calculate levenshtein distance of the two strings. + * + * @param str1 String the first string. + * @param str2 String the second string. + * @param [options] Additional options. + * @param [options.useCollator] Use `Intl.Collator` for locale-sensitive string comparison. + * @return Integer the levenshtein distance (0 and above). + */ + get: function(str1, str2, options) { + var useCollator = (options && collator && options.useCollator); + + var str1Len = str1.length, + str2Len = str2.length; + + // base cases + if (str1Len === 0) return str2Len; + if (str2Len === 0) return str1Len; + + // two rows + var curCol, nextCol, i, j, tmp; + + // initialise previous row + for (i=0; i tmp) { + nextCol = tmp; + } + // deletion + tmp = prevRow[j + 1] + 1; + if (nextCol > tmp) { + nextCol = tmp; + } + + // copy current col value into previous (in preparation for next iteration) + prevRow[j] = curCol; + } + + // copy last col value into previous (in preparation for next iteration) + prevRow[j] = nextCol; + } + + return nextCol; + } + + }; + + // amd + if (typeof define !== "undefined" && define !== null && define.amd) { + define(function() { + return Levenshtein; + }); + } + // commonjs + else if (typeof module !== "undefined" && module !== null && typeof exports !== "undefined" && module.exports === exports) { + module.exports = Levenshtein; + } + // web worker + else if (typeof self !== "undefined" && typeof self.postMessage === 'function' && typeof self.importScripts === 'function') { + self.Levenshtein = Levenshtein; + } + // browser main thread + else if (typeof window !== "undefined" && window !== null) { + window.Levenshtein = Levenshtein; + } +}()); + diff --git a/hm_sunwell/node_modules/fast-levenshtein/package.json b/hm_sunwell/node_modules/fast-levenshtein/package.json new file mode 100644 index 0000000..b7a8998 --- /dev/null +++ b/hm_sunwell/node_modules/fast-levenshtein/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + "fast-levenshtein@~2.0.4", + "/home/xor/shared_vm/git/node-sunwell/node_modules/optionator" + ] + ], + "_from": "fast-levenshtein@>=2.0.4 <2.1.0", + "_id": "fast-levenshtein@2.0.5", + "_inCache": true, + "_installable": true, + "_location": "/fast-levenshtein", + "_nodeVersion": "4.4.5", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/fast-levenshtein-2.0.5.tgz_1475102215149_0.23410583310760558" + }, + "_npmUser": { + "email": "ram@hiddentao.com", + "name": "hiddentao" + }, + "_npmVersion": "3.9.3", + "_phantomChildren": {}, + "_requested": { + "name": "fast-levenshtein", + "raw": "fast-levenshtein@~2.0.4", + "rawSpec": "~2.0.4", + "scope": null, + "spec": ">=2.0.4 <2.1.0", + "type": "range" + }, + "_requiredBy": [ + "/optionator" + ], + "_resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.5.tgz", + "_shasum": "bd33145744519ab1c36c3ee9f31f08e9079b67f2", + "_shrinkwrap": null, + "_spec": "fast-levenshtein@~2.0.4", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/optionator", + "author": { + "email": "ram@hiddentao.com", + "name": "Ramesh Nair", + "url": "http://www.hiddentao.com/" + }, + "bugs": { + "url": "https://github.com/hiddentao/fast-levenshtein/issues" + }, + "dependencies": {}, + "description": "Efficient implementation of Levenshtein algorithm with locale-specific collator support.", + "devDependencies": { + "chai": "~1.5.0", + "grunt": "~0.4.1", + "grunt-benchmark": "~0.2.0", + "grunt-cli": "^1.2.0", + "grunt-contrib-jshint": "~0.4.3", + "grunt-contrib-uglify": "~0.2.0", + "grunt-mocha-test": "~0.2.2", + "grunt-npm-install": "~0.1.0", + "load-grunt-tasks": "~0.6.0", + "lodash": "^4.0.1", + "mocha": "~1.9.0" + }, + "directories": {}, + "dist": { + "shasum": "bd33145744519ab1c36c3ee9f31f08e9079b67f2", + "tarball": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.5.tgz" + }, + "files": [ + "levenshtein.js" + ], + "gitHead": "7c41122f8725a63587ec34bb19b12dd91f12465f", + "homepage": "https://github.com/hiddentao/fast-levenshtein#readme", + "keywords": [ + "distance", + "levenshtein", + "string" + ], + "license": "MIT", + "main": "levenshtein.js", + "maintainers": [ + { + "name": "hiddentao", + "email": "ram@hiddentao.com" + } + ], + "name": "fast-levenshtein", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/hiddentao/fast-levenshtein.git" + }, + "scripts": { + "benchmark": "grunt benchmark", + "build": "grunt build", + "prepublish": "npm run build", + "test": "mocha" + }, + "version": "2.0.5" +} diff --git a/hm_sunwell/node_modules/finalhandler/HISTORY.md b/hm_sunwell/node_modules/finalhandler/HISTORY.md new file mode 100644 index 0000000..e7e144c --- /dev/null +++ b/hm_sunwell/node_modules/finalhandler/HISTORY.md @@ -0,0 +1,108 @@ +0.5.0 / 2016-06-15 +================== + + * Change invalid or non-numeric status code to 500 + * Overwrite status message to match set status code + * Prefer `err.statusCode` if `err.status` is invalid + * Set response headers from `err.headers` object + * Use `statuses` instead of `http` module for status messages + - Includes all defined status messages + +0.4.1 / 2015-12-02 +================== + + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + +0.4.0 / 2015-06-14 +================== + + * Fix a false-positive when unpiping in Node.js 0.8 + * Support `statusCode` property on `Error` objects + * Use `unpipe` module for unpiping requests + * deps: escape-html@1.0.2 + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * perf: enable strict mode + * perf: remove argument reassignment + +0.3.6 / 2015-05-11 +================== + + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + +0.3.5 / 2015-04-22 +================== + + * deps: on-finished@~2.2.1 + - Fix `isFinished(req)` when data buffered + +0.3.4 / 2015-03-15 +================== + + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +0.3.3 / 2015-01-01 +================== + + * deps: debug@~2.1.1 + * deps: on-finished@~2.2.0 + +0.3.2 / 2014-10-22 +================== + + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + +0.3.1 / 2014-10-16 +================== + + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + +0.3.0 / 2014-09-17 +================== + + * Terminate in progress response only on error + * Use `on-finished` to determine request status + +0.2.0 / 2014-09-03 +================== + + * Set `X-Content-Type-Options: nosniff` header + * deps: debug@~2.0.0 + +0.1.0 / 2014-07-16 +================== + + * Respond after request fully read + - prevents hung responses and socket hang ups + * deps: debug@1.0.4 + +0.0.3 / 2014-07-11 +================== + + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + +0.0.2 / 2014-06-19 +================== + + * Handle invalid status codes + +0.0.1 / 2014-06-05 +================== + + * deps: debug@1.0.2 + +0.0.0 / 2014-06-05 +================== + + * Extracted from connect/express diff --git a/hm_sunwell/node_modules/finalhandler/LICENSE b/hm_sunwell/node_modules/finalhandler/LICENSE new file mode 100644 index 0000000..b60a5ad --- /dev/null +++ b/hm_sunwell/node_modules/finalhandler/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/finalhandler/README.md b/hm_sunwell/node_modules/finalhandler/README.md new file mode 100644 index 0000000..58bf720 --- /dev/null +++ b/hm_sunwell/node_modules/finalhandler/README.md @@ -0,0 +1,142 @@ +# finalhandler + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Node.js function to invoke as the final step to respond to HTTP request. + +## Installation + +```sh +$ npm install finalhandler +``` + +## API + +```js +var finalhandler = require('finalhandler') +``` + +### finalhandler(req, res, [options]) + +Returns function to be invoked as the final step for the given `req` and `res`. +This function is to be invoked as `fn(err)`. If `err` is falsy, the handler will +write out a 404 response to the `res`. If it is truthy, an error response will +be written out to the `res`. + +When an error is written, the following information is added to the response: + + * The `res.statusCode` is set from `err.status` (or `err.statusCode`). If + this value is outside the 4xx or 5xx range, it will be set to 500. + * The `res.statusMessage` is set according to the status code. + * The body will be the HTML of the status code message if `env` is + `'production'`, otherwise will be `err.stack`. + * Any headers specified in an `err.headers` object. + +The final handler will also unpipe anything from `req` when it is invoked. + +#### options.env + +By default, the environment is determined by `NODE_ENV` variable, but it can be +overridden by this option. + +#### options.onerror + +Provide a function to be called with the `err` when it exists. Can be used for +writing errors to a central location without excessive function generation. Called +as `onerror(err, req, res)`. + +## Examples + +### always 404 + +```js +var finalhandler = require('finalhandler') +var http = require('http') + +var server = http.createServer(function (req, res) { + var done = finalhandler(req, res) + done() +}) + +server.listen(3000) +``` + +### perform simple action + +```js +var finalhandler = require('finalhandler') +var fs = require('fs') +var http = require('http') + +var server = http.createServer(function (req, res) { + var done = finalhandler(req, res) + + fs.readFile('index.html', function (err, buf) { + if (err) return done(err) + res.setHeader('Content-Type', 'text/html') + res.end(buf) + }) +}) + +server.listen(3000) +``` + +### use with middleware-style functions + +```js +var finalhandler = require('finalhandler') +var http = require('http') +var serveStatic = require('serve-static') + +var serve = serveStatic('public') + +var server = http.createServer(function (req, res) { + var done = finalhandler(req, res) + serve(req, res, done) +}) + +server.listen(3000) +``` + +### keep log of all errors + +```js +var finalhandler = require('finalhandler') +var fs = require('fs') +var http = require('http') + +var server = http.createServer(function (req, res) { + var done = finalhandler(req, res, {onerror: logerror}) + + fs.readFile('index.html', function (err, buf) { + if (err) return done(err) + res.setHeader('Content-Type', 'text/html') + res.end(buf) + }) +}) + +server.listen(3000) + +function logerror(err) { + console.error(err.stack || err.toString()) +} +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/finalhandler.svg +[npm-url]: https://npmjs.org/package/finalhandler +[node-image]: https://img.shields.io/node/v/finalhandler.svg +[node-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/pillarjs/finalhandler.svg +[travis-url]: https://travis-ci.org/pillarjs/finalhandler +[coveralls-image]: https://img.shields.io/coveralls/pillarjs/finalhandler.svg +[coveralls-url]: https://coveralls.io/r/pillarjs/finalhandler?branch=master +[downloads-image]: https://img.shields.io/npm/dm/finalhandler.svg +[downloads-url]: https://npmjs.org/package/finalhandler diff --git a/hm_sunwell/node_modules/finalhandler/index.js b/hm_sunwell/node_modules/finalhandler/index.js new file mode 100644 index 0000000..884d802 --- /dev/null +++ b/hm_sunwell/node_modules/finalhandler/index.js @@ -0,0 +1,189 @@ +/*! + * finalhandler + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var debug = require('debug')('finalhandler') +var escapeHtml = require('escape-html') +var onFinished = require('on-finished') +var statuses = require('statuses') +var unpipe = require('unpipe') + +/** + * Module variables. + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function (fn) { process.nextTick(fn.bind.apply(fn, arguments)) } +var isFinished = onFinished.isFinished + +/** + * Module exports. + * @public + */ + +module.exports = finalhandler + +/** + * Create a function to handle the final response. + * + * @param {Request} req + * @param {Response} res + * @param {Object} [options] + * @return {Function} + * @public + */ + +function finalhandler (req, res, options) { + var opts = options || {} + + // get environment + var env = opts.env || process.env.NODE_ENV || 'development' + + // get error callback + var onerror = opts.onerror + + return function (err) { + var headers = Object.create(null) + var status + + // ignore 404 on in-flight response + if (!err && res._header) { + debug('cannot 404 after headers sent') + return + } + + // unhandled error + if (err) { + // respect status code from error + status = getErrorStatusCode(err) || res.statusCode + + // default status code to 500 if outside valid range + if (typeof status !== 'number' || status < 400 || status > 599) { + status = 500 + } + + // respect err.headers + if (err.headers && (err.status === status || err.statusCode === status)) { + var keys = Object.keys(err.headers) + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + headers[key] = err.headers[key] + } + } + + // production gets a basic error message + var msg = env === 'production' + ? statuses[status] + : err.stack || err.toString() + msg = escapeHtml(msg) + .replace(/\n/g, '
') + .replace(/\x20{2}/g, '  ') + '\n' + } else { + status = 404 + msg = 'Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl || req.url) + '\n' + } + + debug('default %s', status) + + // schedule onerror callback + if (err && onerror) { + defer(onerror, err, req, res) + } + + // cannot actually respond + if (res._header) { + debug('cannot %d after headers sent', status) + req.socket.destroy() + return + } + + // send response + send(req, res, status, headers, msg) + } +} + +/** + * Get status code from Error object. + * + * @param {Error} err + * @return {number} + * @private + */ + +function getErrorStatusCode (err) { + // check err.status + if (typeof err.status === 'number' && err.status >= 400 && err.status < 600) { + return err.status + } + + // check err.statusCode + if (typeof err.statusCode === 'number' && err.statusCode >= 400 && err.statusCode < 600) { + return err.statusCode + } + + return undefined +} + +/** + * Send response. + * + * @param {IncomingMessage} req + * @param {OutgoingMessage} res + * @param {number} status + * @param {object} headers + * @param {string} body + * @private + */ + +function send (req, res, status, headers, body) { + function write () { + // response status + res.statusCode = status + res.statusMessage = statuses[status] + + // response headers + var keys = Object.keys(headers) + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + res.setHeader(key, headers[key]) + } + + // security header for content sniffing + res.setHeader('X-Content-Type-Options', 'nosniff') + + // standard headers + res.setHeader('Content-Type', 'text/html; charset=utf-8') + res.setHeader('Content-Length', Buffer.byteLength(body, 'utf8')) + + if (req.method === 'HEAD') { + res.end() + return + } + + res.end(body, 'utf8') + } + + if (isFinished(req)) { + write() + return + } + + // unpipe everything from the request + unpipe(req) + + // flush the request + onFinished(req, write) + req.resume() +} diff --git a/hm_sunwell/node_modules/finalhandler/package.json b/hm_sunwell/node_modules/finalhandler/package.json new file mode 100644 index 0000000..dcfbcb6 --- /dev/null +++ b/hm_sunwell/node_modules/finalhandler/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + "finalhandler@0.5.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "finalhandler@0.5.0", + "_id": "finalhandler@0.5.0", + "_inCache": true, + "_installable": true, + "_location": "/finalhandler", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/finalhandler-0.5.0.tgz_1466028655505_0.19758180482313037" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "finalhandler", + "raw": "finalhandler@0.5.0", + "rawSpec": "0.5.0", + "scope": null, + "spec": "0.5.0", + "type": "version" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "_shasum": "e9508abece9b6dba871a6942a1d7911b91911ac7", + "_shrinkwrap": null, + "_spec": "finalhandler@0.5.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "author": { + "email": "doug@somethingdoug.com", + "name": "Douglas Christopher Wilson" + }, + "bugs": { + "url": "https://github.com/pillarjs/finalhandler/issues" + }, + "dependencies": { + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "statuses": "~1.3.0", + "unpipe": "~1.0.0" + }, + "description": "Node.js final http responder", + "devDependencies": { + "eslint": "2.12.0", + "eslint-config-standard": "5.3.1", + "eslint-plugin-promise": "1.3.2", + "eslint-plugin-standard": "1.3.2", + "istanbul": "0.4.3", + "mocha": "2.5.3", + "readable-stream": "2.1.2", + "supertest": "1.1.0" + }, + "directories": {}, + "dist": { + "shasum": "e9508abece9b6dba871a6942a1d7911b91911ac7", + "tarball": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "gitHead": "15cc543eb87dd0e2f29e931d86816a6eb348c573", + "homepage": "https://github.com/pillarjs/finalhandler", + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "finalhandler", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/pillarjs/finalhandler.git" + }, + "scripts": { + "lint": "eslint **/*.js", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "0.5.0" +} diff --git a/hm_sunwell/node_modules/forever-agent/LICENSE b/hm_sunwell/node_modules/forever-agent/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/hm_sunwell/node_modules/forever-agent/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/hm_sunwell/node_modules/forever-agent/README.md b/hm_sunwell/node_modules/forever-agent/README.md new file mode 100644 index 0000000..9d5b663 --- /dev/null +++ b/hm_sunwell/node_modules/forever-agent/README.md @@ -0,0 +1,4 @@ +forever-agent +============= + +HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module. diff --git a/hm_sunwell/node_modules/forever-agent/index.js b/hm_sunwell/node_modules/forever-agent/index.js new file mode 100644 index 0000000..416c7ab --- /dev/null +++ b/hm_sunwell/node_modules/forever-agent/index.js @@ -0,0 +1,138 @@ +module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL + +var util = require('util') + , Agent = require('http').Agent + , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent + +function getConnectionName(host, port) { + var name = '' + if (typeof host === 'string') { + name = host + ':' + port + } else { + // For node.js v012.0 and iojs-v1.5.1, host is an object. And any existing localAddress is part of the connection name. + name = host.host + ':' + host.port + ':' + (host.localAddress ? (host.localAddress + ':') : ':') + } + return name +} + +function ForeverAgent(options) { + var self = this + self.options = options || {} + self.requests = {} + self.sockets = {} + self.freeSockets = {} + self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets + self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets + self.on('free', function(socket, host, port) { + var name = getConnectionName(host, port) + + if (self.requests[name] && self.requests[name].length) { + self.requests[name].shift().onSocket(socket) + } else if (self.sockets[name].length < self.minSockets) { + if (!self.freeSockets[name]) self.freeSockets[name] = [] + self.freeSockets[name].push(socket) + + // if an error happens while we don't use the socket anyway, meh, throw the socket away + var onIdleError = function() { + socket.destroy() + } + socket._onIdleError = onIdleError + socket.on('error', onIdleError) + } else { + // If there are no pending requests just destroy the + // socket and it will get removed from the pool. This + // gets us out of timeout issues and allows us to + // default to Connection:keep-alive. + socket.destroy() + } + }) + +} +util.inherits(ForeverAgent, Agent) + +ForeverAgent.defaultMinSockets = 5 + + +ForeverAgent.prototype.createConnection = net.createConnection +ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest +ForeverAgent.prototype.addRequest = function(req, host, port) { + var name = getConnectionName(host, port) + + if (typeof host !== 'string') { + var options = host + port = options.port + host = options.host + } + + if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { + var idleSocket = this.freeSockets[name].pop() + idleSocket.removeListener('error', idleSocket._onIdleError) + delete idleSocket._onIdleError + req._reusedSocket = true + req.onSocket(idleSocket) + } else { + this.addRequestNoreuse(req, host, port) + } +} + +ForeverAgent.prototype.removeSocket = function(s, name, host, port) { + if (this.sockets[name]) { + var index = this.sockets[name].indexOf(s) + if (index !== -1) { + this.sockets[name].splice(index, 1) + } + } else if (this.sockets[name] && this.sockets[name].length === 0) { + // don't leak + delete this.sockets[name] + delete this.requests[name] + } + + if (this.freeSockets[name]) { + var index = this.freeSockets[name].indexOf(s) + if (index !== -1) { + this.freeSockets[name].splice(index, 1) + if (this.freeSockets[name].length === 0) { + delete this.freeSockets[name] + } + } + } + + if (this.requests[name] && this.requests[name].length) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(name, host, port).emit('free') + } +} + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + if (typeof port === 'object') { + options = port; + } else if (typeof host === 'object') { + options = host; + } else if (typeof options === 'object') { + options = options; + } else { + options = {}; + } + + if (typeof port === 'number') { + options.port = port; + } + + if (typeof host === 'string') { + options.host = host; + } + + return tls.connect(options); +} diff --git a/hm_sunwell/node_modules/forever-agent/package.json b/hm_sunwell/node_modules/forever-agent/package.json new file mode 100644 index 0000000..2d9fa69 --- /dev/null +++ b/hm_sunwell/node_modules/forever-agent/package.json @@ -0,0 +1,80 @@ +{ + "_args": [ + [ + "forever-agent@~0.6.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/request" + ] + ], + "_from": "forever-agent@>=0.6.1 <0.7.0", + "_id": "forever-agent@0.6.1", + "_inCache": true, + "_installable": true, + "_location": "/forever-agent", + "_npmUser": { + "email": "simeonvelichkov@gmail.com", + "name": "simov" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "forever-agent", + "raw": "forever-agent@~0.6.1", + "rawSpec": "~0.6.1", + "scope": null, + "spec": ">=0.6.1 <0.7.0", + "type": "range" + }, + "_requiredBy": [ + "/request" + ], + "_resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "_shasum": "fbc71f0c41adeb37f96c577ad1ed42d8fdacca91", + "_shrinkwrap": null, + "_spec": "forever-agent@~0.6.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/request", + "author": { + "email": "mikeal.rogers@gmail.com", + "name": "Mikeal Rogers", + "url": "http://www.futurealoof.com" + }, + "bugs": { + "url": "https://github.com/mikeal/forever-agent/issues" + }, + "dependencies": {}, + "description": "HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "fbc71f0c41adeb37f96c577ad1ed42d8fdacca91", + "tarball": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + }, + "engines": { + "node": "*" + }, + "gitHead": "1b3b6163f2b3c2c4122bbfa288c1325c0df9871d", + "homepage": "https://github.com/mikeal/forever-agent", + "license": "Apache-2.0", + "main": "index.js", + "maintainers": [ + { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + { + "name": "nylen", + "email": "jnylen@gmail.com" + }, + { + "name": "simov", + "email": "simeonvelichkov@gmail.com" + } + ], + "name": "forever-agent", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "url": "git+https://github.com/mikeal/forever-agent.git" + }, + "scripts": {}, + "version": "0.6.1" +} diff --git a/hm_sunwell/node_modules/form-data/License b/hm_sunwell/node_modules/form-data/License new file mode 100644 index 0000000..c7ff12a --- /dev/null +++ b/hm_sunwell/node_modules/form-data/License @@ -0,0 +1,19 @@ +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/hm_sunwell/node_modules/form-data/README.md b/hm_sunwell/node_modules/form-data/README.md new file mode 100644 index 0000000..5864d82 --- /dev/null +++ b/hm_sunwell/node_modules/form-data/README.md @@ -0,0 +1,217 @@ +# Form-Data [![NPM Module](https://img.shields.io/npm/v/form-data.svg)](https://www.npmjs.com/package/form-data) [![Join the chat at https://gitter.im/form-data/form-data](http://form-data.github.io/images/gitterbadge.svg)](https://gitter.im/form-data/form-data) + +A library to create readable ```"multipart/form-data"``` streams. Can be used to submit forms and file uploads to other web applications. + +The API of this library is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd]. + +[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface + +[![Linux Build](https://img.shields.io/travis/form-data/form-data/v2.0.0.svg?label=linux:0.12-6.x)](https://travis-ci.org/form-data/form-data) +[![MacOS Build](https://img.shields.io/travis/form-data/form-data/v2.0.0.svg?label=macos:0.12-6.x)](https://travis-ci.org/form-data/form-data) +[![Windows Build](https://img.shields.io/appveyor/ci/alexindigo/form-data/v2.0.0.svg?label=windows:0.12-6.x)](https://ci.appveyor.com/project/alexindigo/form-data) + +[![Coverage Status](https://img.shields.io/coveralls/form-data/form-data/v2.0.0.svg?label=code+coverage)](https://coveralls.io/github/form-data/form-data?branch=master) +[![Dependency Status](https://img.shields.io/david/form-data/form-data.svg)](https://david-dm.org/form-data/form-data) +[![bitHound Overall Score](https://www.bithound.io/github/form-data/form-data/badges/score.svg)](https://www.bithound.io/github/form-data/form-data) + +## Install + +``` +npm install --save form-data +``` + +## Usage + +In this example we are constructing a form with 3 fields that contain a string, +a buffer and a file stream. + +``` javascript +var FormData = require('form-data'); +var fs = require('fs'); + +var form = new FormData(); +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_file', fs.createReadStream('/foo/bar.jpg')); +``` + +Also you can use http-response stream: + +``` javascript +var FormData = require('form-data'); +var http = require('http'); + +var form = new FormData(); + +http.request('http://nodejs.org/images/logo.png', function(response) { + form.append('my_field', 'my value'); + form.append('my_buffer', new Buffer(10)); + form.append('my_logo', response); +}); +``` + +Or @mikeal's [request](https://github.com/request/request) stream: + +``` javascript +var FormData = require('form-data'); +var request = require('request'); + +var form = new FormData(); + +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_logo', request('http://nodejs.org/images/logo.png')); +``` + +In order to submit this form to a web application, call ```submit(url, [callback])``` method: + +``` javascript +form.submit('http://example.org/', function(err, res) { + // res – response object (http.IncomingMessage) // + res.resume(); +}); + +``` + +For more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods. + +### Alternative submission methods + +You can use node's http client interface: + +``` javascript +var http = require('http'); + +var request = http.request({ + method: 'post', + host: 'example.org', + path: '/upload', + headers: form.getHeaders() +}); + +form.pipe(request); + +request.on('response', function(res) { + console.log(res.statusCode); +}); +``` + +Or if you would prefer the `'Content-Length'` header to be set for you: + +``` javascript +form.submit('example.org/upload', function(err, res) { + console.log(res.statusCode); +}); +``` + +To use custom headers and pre-known length in parts: + +``` javascript +var CRLF = '\r\n'; +var form = new FormData(); + +var options = { + header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF, + knownLength: 1 +}; + +form.append('my_buffer', buffer, options); + +form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); +}); +``` + +Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually: + +``` javascript +someModule.stream(function(err, stdout, stderr) { + if (err) throw err; + + var form = new FormData(); + + form.append('file', stdout, { + filename: 'unicycle.jpg', + contentType: 'image/jpg', + knownLength: 19806 + }); + + form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); + }); +}); +``` + +For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter: + +``` javascript +form.submit({ + host: 'example.com', + path: '/probably.php?extra=params', + auth: 'username:password' +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +In case you need to also send custom HTTP headers with the POST request, you can use the `headers` key in first parameter of `form.submit()`: + +``` javascript +form.submit({ + host: 'example.com', + path: '/surelynot.php', + headers: {'x-test-header': 'test-header-value'} +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +### Integration with other libraries + +#### Request + +Form submission using [request](https://github.com/request/request): + +```javascript +var formData = { + my_field: 'my_value', + my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), +}; + +request.post({url:'http://service.com/upload', formData: formData}, function(err, httpResponse, body) { + if (err) { + return console.error('upload failed:', err); + } + console.log('Upload successful! Server responded with:', body); +}); +``` + +For more details see [request readme](https://github.com/request/request#multipartform-data-multipart-form-uploads). + +#### node-fetch + +You can also submit a form using [node-fetch](https://github.com/bitinn/node-fetch): + +```javascript +var form = new FormData(); + +form.append('a', 1); + +fetch('http://example.com', { method: 'POST', body: form }) + .then(function(res) { + return res.json(); + }).then(function(json) { + console.log(json); + }); +``` + +## Notes + +- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround. +- Starting version `2.x` FormData has dropped support for `node@0.10.x`. + +## License + +Form-Data is released under the [MIT](License) license. diff --git a/hm_sunwell/node_modules/form-data/lib/browser.js b/hm_sunwell/node_modules/form-data/lib/browser.js new file mode 100644 index 0000000..f42221c --- /dev/null +++ b/hm_sunwell/node_modules/form-data/lib/browser.js @@ -0,0 +1,2 @@ +/* eslint-env browser */ +module.exports = window.FormData; diff --git a/hm_sunwell/node_modules/form-data/lib/form_data.js b/hm_sunwell/node_modules/form-data/lib/form_data.js new file mode 100644 index 0000000..8252e65 --- /dev/null +++ b/hm_sunwell/node_modules/form-data/lib/form_data.js @@ -0,0 +1,427 @@ +var CombinedStream = require('combined-stream'); +var util = require('util'); +var path = require('path'); +var http = require('http'); +var https = require('https'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var mime = require('mime-types'); +var asynckit = require('asynckit'); +var populate = require('./populate.js'); + +// Public API +module.exports = FormData; + +// make it a Stream +util.inherits(FormData, CombinedStream); + +/** + * Create readable "multipart/form-data" streams. + * Can be used to submit forms + * and file uploads to other web applications. + * + * @constructor + */ +function FormData() { + if (!(this instanceof FormData)) { + return new FormData(); + } + + this._overheadLength = 0; + this._valueLength = 0; + this._valuesToMeasure = []; + + CombinedStream.call(this); +} + +FormData.LINE_BREAK = '\r\n'; +FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream'; + +FormData.prototype.append = function(field, value, options) { + + options = options || {}; + + // allow filename as single option + if (typeof options == 'string') { + options = {filename: options}; + } + + var append = CombinedStream.prototype.append.bind(this); + + // all that streamy business can't handle numbers + if (typeof value == 'number') { + value = '' + value; + } + + // https://github.com/felixge/node-form-data/issues/38 + if (util.isArray(value)) { + // Please convert your array into string + // the way web server expects it + this._error(new Error('Arrays are not supported.')); + return; + } + + var header = this._multiPartHeader(field, value, options); + var footer = this._multiPartFooter(); + + append(header); + append(value); + append(footer); + + // pass along options.knownLength + this._trackLength(header, value, options); +}; + +FormData.prototype._trackLength = function(header, value, options) { + var valueLength = 0; + + // used w/ getLengthSync(), when length is known. + // e.g. for streaming directly from a remote server, + // w/ a known file a size, and not wanting to wait for + // incoming file to finish to get its size. + if (options.knownLength != null) { + valueLength += +options.knownLength; + } else if (Buffer.isBuffer(value)) { + valueLength = value.length; + } else if (typeof value === 'string') { + valueLength = Buffer.byteLength(value); + } + + this._valueLength += valueLength; + + // @check why add CRLF? does this account for custom/multiple CRLFs? + this._overheadLength += + Buffer.byteLength(header) + + FormData.LINE_BREAK.length; + + // empty or either doesn't have path or not an http response + if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) { + return; + } + + // no need to bother with the length + if (!options.knownLength) { + this._valuesToMeasure.push(value); + } +}; + +FormData.prototype._lengthRetriever = function(value, callback) { + + if (value.hasOwnProperty('fd')) { + + // take read range into a account + // `end` = Infinity –> read file till the end + // + // TODO: Looks like there is bug in Node fs.createReadStream + // it doesn't respect `end` options without `start` options + // Fix it when node fixes it. + // https://github.com/joyent/node/issues/7819 + if (value.end != undefined && value.end != Infinity && value.start != undefined) { + + // when end specified + // no need to calculate range + // inclusive, starts with 0 + callback(null, value.end + 1 - (value.start ? value.start : 0)); + + // not that fast snoopy + } else { + // still need to fetch file size from fs + fs.stat(value.path, function(err, stat) { + + var fileSize; + + if (err) { + callback(err); + return; + } + + // update final size based on the range options + fileSize = stat.size - (value.start ? value.start : 0); + callback(null, fileSize); + }); + } + + // or http response + } else if (value.hasOwnProperty('httpVersion')) { + callback(null, +value.headers['content-length']); + + // or request stream http://github.com/mikeal/request + } else if (value.hasOwnProperty('httpModule')) { + // wait till response come back + value.on('response', function(response) { + value.pause(); + callback(null, +response.headers['content-length']); + }); + value.resume(); + + // something else + } else { + callback('Unknown stream'); + } +}; + +FormData.prototype._multiPartHeader = function(field, value, options) { + // custom header specified (as string)? + // it becomes responsible for boundary + // (e.g. to handle extra CRLFs on .NET servers) + if (typeof options.header == 'string') { + return options.header; + } + + var contentDisposition = this._getContentDisposition(value, options); + var contentType = this._getContentType(value, options); + + var contents = ''; + var headers = { + // add custom disposition as third element or keep it two elements if not + 'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []), + // if no content type. allow it to be empty array + 'Content-Type': [].concat(contentType || []) + }; + + // allow custom headers. + if (typeof options.header == 'object') { + populate(headers, options.header); + } + + var header; + for (var prop in headers) { + header = headers[prop]; + + // skip nullish headers. + if (header == null) { + continue; + } + + // convert all headers to arrays. + if (!Array.isArray(header)) { + header = [header]; + } + + // add non-empty headers. + if (header.length) { + contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK; + } + } + + return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK; +}; + +FormData.prototype._getContentDisposition = function(value, options) { + + var contentDisposition; + + // custom filename takes precedence + // fs- and request- streams have path property + // formidable and the browser add a name property. + var filename = options.filename || value.name || value.path; + + // or try http response + if (!filename && value.readable && value.hasOwnProperty('httpVersion')) { + filename = value.client._httpMessage.path; + } + + if (filename) { + contentDisposition = 'filename="' + path.basename(filename) + '"'; + } + + return contentDisposition; +}; + +FormData.prototype._getContentType = function(value, options) { + + // use custom content-type above all + var contentType = options.contentType; + + // or try `name` from formidable, browser + if (!contentType && value.name) { + contentType = mime.lookup(value.name); + } + + // or try `path` from fs-, request- streams + if (!contentType && value.path) { + contentType = mime.lookup(value.path); + } + + // or if it's http-reponse + if (!contentType && value.readable && value.hasOwnProperty('httpVersion')) { + contentType = value.headers['content-type']; + } + + // or guess it from the filename + if (!contentType && options.filename) { + contentType = mime.lookup(options.filename); + } + + // fallback to the default content type if `value` is not simple value + if (!contentType && typeof value == 'object') { + contentType = FormData.DEFAULT_CONTENT_TYPE; + } + + return contentType; +}; + +FormData.prototype._multiPartFooter = function() { + return function(next) { + var footer = FormData.LINE_BREAK; + + var lastPart = (this._streams.length === 0); + if (lastPart) { + footer += this._lastBoundary(); + } + + next(footer); + }.bind(this); +}; + +FormData.prototype._lastBoundary = function() { + return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK; +}; + +FormData.prototype.getHeaders = function(userHeaders) { + var header; + var formHeaders = { + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + }; + + for (header in userHeaders) { + if (userHeaders.hasOwnProperty(header)) { + formHeaders[header.toLowerCase()] = userHeaders[header]; + } + } + + return formHeaders; +}; + +FormData.prototype.getBoundary = function() { + if (!this._boundary) { + this._generateBoundary(); + } + + return this._boundary; +}; + +FormData.prototype._generateBoundary = function() { + // This generates a 50 character boundary similar to those used by Firefox. + // They are optimized for boyer-moore parsing. + var boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + boundary += Math.floor(Math.random() * 10).toString(16); + } + + this._boundary = boundary; +}; + +// Note: getLengthSync DOESN'T calculate streams length +// As workaround one can calculate file size manually +// and add it as knownLength option +FormData.prototype.getLengthSync = function() { + var knownLength = this._overheadLength + this._valueLength; + + // Don't get confused, there are 3 "internal" streams for each keyval pair + // so it basically checks if there is any value added to the form + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + // https://github.com/form-data/form-data/issues/40 + if (this._valuesToMeasure.length) { + // Some async length retrievers are present + // therefore synchronous length calculation is false. + // Please use getLength(callback) to get proper length + this._error(new Error('Cannot calculate proper length in synchronous way.')); + } + + return knownLength; +}; + +FormData.prototype.getLength = function(cb) { + var knownLength = this._overheadLength + this._valueLength; + + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + if (!this._valuesToMeasure.length) { + process.nextTick(cb.bind(this, null, knownLength)); + return; + } + + asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function(err, values) { + if (err) { + cb(err); + return; + } + + values.forEach(function(length) { + knownLength += length; + }); + + cb(null, knownLength); + }); +}; + +FormData.prototype.submit = function(params, cb) { + var request + , options + , defaults = {method: 'post'} + ; + + // parse provided url if it's string + // or treat it as options object + if (typeof params == 'string') { + + params = parseUrl(params); + options = populate({ + port: params.port, + path: params.pathname, + host: params.hostname + }, defaults); + + // use custom params + } else { + + options = populate(params, defaults); + // if no port provided use default one + if (!options.port) { + options.port = options.protocol == 'https:' ? 443 : 80; + } + } + + // put that good code in getHeaders to some use + options.headers = this.getHeaders(params.headers); + + // https if specified, fallback to http in any other case + if (options.protocol == 'https:') { + request = https.request(options); + } else { + request = http.request(options); + } + + // get content length and fire away + this.getLength(function(err, length) { + if (err) { + this._error(err); + return; + } + + // add content length + request.setHeader('Content-Length', length); + + this.pipe(request); + if (cb) { + request.on('error', cb); + request.on('response', cb.bind(this, null)); + } + }.bind(this)); + + return request; +}; + +FormData.prototype._error = function(err) { + if (!this.error) { + this.error = err; + this.pause(); + this.emit('error', err); + } +}; diff --git a/hm_sunwell/node_modules/form-data/lib/populate.js b/hm_sunwell/node_modules/form-data/lib/populate.js new file mode 100644 index 0000000..4d35738 --- /dev/null +++ b/hm_sunwell/node_modules/form-data/lib/populate.js @@ -0,0 +1,10 @@ +// populates missing values +module.exports = function(dst, src) { + + Object.keys(src).forEach(function(prop) + { + dst[prop] = dst[prop] || src[prop]; + }); + + return dst; +}; diff --git a/hm_sunwell/node_modules/form-data/package.json b/hm_sunwell/node_modules/form-data/package.json new file mode 100644 index 0000000..2fbf05b --- /dev/null +++ b/hm_sunwell/node_modules/form-data/package.json @@ -0,0 +1,129 @@ +{ + "_args": [ + [ + "form-data@~2.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/request" + ] + ], + "_from": "form-data@>=2.0.0 <2.1.0", + "_id": "form-data@2.0.0", + "_inCache": true, + "_installable": true, + "_location": "/form-data", + "_nodeVersion": "4.5.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/form-data-2.0.0.tgz_1474092617403_0.5404838663525879" + }, + "_npmUser": { + "email": "iam@alexindigo.com", + "name": "alexindigo" + }, + "_npmVersion": "2.15.9", + "_phantomChildren": {}, + "_requested": { + "name": "form-data", + "raw": "form-data@~2.0.0", + "rawSpec": "~2.0.0", + "scope": null, + "spec": ">=2.0.0 <2.1.0", + "type": "range" + }, + "_requiredBy": [ + "/request" + ], + "_resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "_shasum": "6f0aebadcc5da16c13e1ecc11137d85f9b883b25", + "_shrinkwrap": null, + "_spec": "form-data@~2.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/request", + "author": { + "email": "felix@debuggable.com", + "name": "Felix Geisendörfer", + "url": "http://debuggable.com/" + }, + "browser": "./lib/browser", + "bugs": { + "url": "https://github.com/form-data/form-data/issues" + }, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + }, + "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", + "devDependencies": { + "coveralls": "^2.11.13", + "cross-spawn": "^4.0.0", + "eslint": "^3.5.0", + "fake": "^0.2.2", + "far": "^0.0.7", + "formidable": "^1.0.17", + "in-publish": "^2.0.0", + "is-node-modern": "^1.0.0", + "istanbul": "^0.4.5", + "pkgfiles": "^2.3.0", + "pre-commit": "^1.1.3", + "request": "^2.74.0", + "rimraf": "^2.5.4" + }, + "directories": {}, + "dist": { + "shasum": "6f0aebadcc5da16c13e1ecc11137d85f9b883b25", + "tarball": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz" + }, + "engines": { + "node": ">= 0.12" + }, + "gitHead": "652b16ff5b9077bdf65eb66b67286c823c2a1040", + "homepage": "https://github.com/form-data/form-data#readme", + "license": "MIT", + "main": "./lib/form_data", + "maintainers": [ + { + "name": "alexindigo", + "email": "iam@alexindigo.com" + }, + { + "name": "dylanpiercey", + "email": "pierceydylan@gmail.com" + }, + { + "name": "felixge", + "email": "felix@debuggable.com" + }, + { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + } + ], + "name": "form-data", + "optionalDependencies": {}, + "pre-commit": [ + "check", + "lint", + "test" + ], + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/form-data/form-data.git" + }, + "scripts": { + "check": "istanbul check-coverage coverage/coverage*.json", + "ci-lint": "is-node-modern && npm run lint || is-node-not-modern", + "debug": "verbose=1 ./test/run.js", + "files": "pkgfiles --sort=name", + "get-version": "node -e \"console.log(require('./package.json').version)\"", + "lint": "eslint lib/*.js test/*.js test/integration/*.js", + "postpublish": "npm run restore-readme", + "posttest": "istanbul report lcov text", + "predebug": "rimraf coverage test/tmp", + "prepublish": "in-publish && npm run update-readme || not-in-publish", + "pretest": "rimraf coverage test/tmp", + "restore-readme": "mv README.md.bak README.md", + "test": "istanbul cover test/run.js", + "update-readme": "sed -i.bak 's/\\/master\\.svg/\\/v'$(npm --silent run get-version)'.svg/g' README.md" + }, + "version": "2.0.0" +} diff --git a/hm_sunwell/node_modules/forwarded/HISTORY.md b/hm_sunwell/node_modules/forwarded/HISTORY.md new file mode 100644 index 0000000..97fa1d1 --- /dev/null +++ b/hm_sunwell/node_modules/forwarded/HISTORY.md @@ -0,0 +1,4 @@ +0.1.0 / 2014-09-21 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/forwarded/LICENSE b/hm_sunwell/node_modules/forwarded/LICENSE new file mode 100644 index 0000000..b7dce6c --- /dev/null +++ b/hm_sunwell/node_modules/forwarded/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/forwarded/README.md b/hm_sunwell/node_modules/forwarded/README.md new file mode 100644 index 0000000..2b4988f --- /dev/null +++ b/hm_sunwell/node_modules/forwarded/README.md @@ -0,0 +1,53 @@ +# forwarded + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Parse HTTP X-Forwarded-For header + +## Installation + +```sh +$ npm install forwarded +``` + +## API + +```js +var forwarded = require('forwarded') +``` + +### forwarded(req) + +```js +var addresses = forwarded(req) +``` + +Parse the `X-Forwarded-For` header from the request. Returns an array +of the addresses, including the socket address for the `req`. In reverse +order (i.e. index `0` is the socket address and the last index is the +furthest address, typically the end-user). + +## Testing + +```sh +$ npm test +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/forwarded.svg?style=flat +[npm-url]: https://npmjs.org/package/forwarded +[node-version-image]: https://img.shields.io/node/v/forwarded.svg?style=flat +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/forwarded.svg?style=flat +[travis-url]: https://travis-ci.org/jshttp/forwarded +[coveralls-image]: https://img.shields.io/coveralls/jshttp/forwarded.svg?style=flat +[coveralls-url]: https://coveralls.io/r/jshttp/forwarded?branch=master +[downloads-image]: https://img.shields.io/npm/dm/forwarded.svg?style=flat +[downloads-url]: https://npmjs.org/package/forwarded diff --git a/hm_sunwell/node_modules/forwarded/index.js b/hm_sunwell/node_modules/forwarded/index.js new file mode 100644 index 0000000..2f5c340 --- /dev/null +++ b/hm_sunwell/node_modules/forwarded/index.js @@ -0,0 +1,35 @@ +/*! + * forwarded + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +/** + * Module exports. + */ + +module.exports = forwarded + +/** + * Get all addresses in the request, using the `X-Forwarded-For` header. + * + * @param {Object} req + * @api public + */ + +function forwarded(req) { + if (!req) { + throw new TypeError('argument req is required') + } + + // simple header parsing + var proxyAddrs = (req.headers['x-forwarded-for'] || '') + .split(/ *, */) + .filter(Boolean) + .reverse() + var socketAddr = req.connection.remoteAddress + var addrs = [socketAddr].concat(proxyAddrs) + + // return all addresses + return addrs +} diff --git a/hm_sunwell/node_modules/forwarded/package.json b/hm_sunwell/node_modules/forwarded/package.json new file mode 100644 index 0000000..bf4f5e6 --- /dev/null +++ b/hm_sunwell/node_modules/forwarded/package.json @@ -0,0 +1,91 @@ +{ + "_args": [ + [ + "forwarded@~0.1.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/proxy-addr" + ] + ], + "_from": "forwarded@>=0.1.0 <0.2.0", + "_id": "forwarded@0.1.0", + "_inCache": true, + "_installable": true, + "_location": "/forwarded", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.21", + "_phantomChildren": {}, + "_requested": { + "name": "forwarded", + "raw": "forwarded@~0.1.0", + "rawSpec": "~0.1.0", + "scope": null, + "spec": ">=0.1.0 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/proxy-addr" + ], + "_resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "_shasum": "19ef9874c4ae1c297bcf078fde63a09b66a84363", + "_shrinkwrap": null, + "_spec": "forwarded@~0.1.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/proxy-addr", + "bugs": { + "url": "https://github.com/jshttp/forwarded/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "dependencies": {}, + "description": "Parse HTTP X-Forwarded-For header", + "devDependencies": { + "istanbul": "0.3.2", + "mocha": "~1.21.4" + }, + "directories": {}, + "dist": { + "shasum": "19ef9874c4ae1c297bcf078fde63a09b66a84363", + "tarball": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "gitHead": "e9a9faeb3cfaadf40eb57d144fff26bca9b818e8", + "homepage": "https://github.com/jshttp/forwarded", + "keywords": [ + "http", + "req", + "x-forwarded-for" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "forwarded", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/forwarded.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "0.1.0" +} diff --git a/hm_sunwell/node_modules/fresh/HISTORY.md b/hm_sunwell/node_modules/fresh/HISTORY.md new file mode 100644 index 0000000..3c95fbb --- /dev/null +++ b/hm_sunwell/node_modules/fresh/HISTORY.md @@ -0,0 +1,38 @@ +0.3.0 / 2015-05-12 +================== + + * Add weak `ETag` matching support + +0.2.4 / 2014-09-07 +================== + + * Support Node.js 0.6 + +0.2.3 / 2014-09-07 +================== + + * Move repository to jshttp + +0.2.2 / 2014-02-19 +================== + + * Revert "Fix for blank page on Safari reload" + +0.2.1 / 2014-01-29 +================== + + * Fix for blank page on Safari reload + +0.2.0 / 2013-08-11 +================== + + * Return stale for `Cache-Control: no-cache` + +0.1.0 / 2012-06-15 +================== + * Add `If-None-Match: *` support + +0.0.1 / 2012-06-10 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/fresh/LICENSE b/hm_sunwell/node_modules/fresh/LICENSE new file mode 100644 index 0000000..f527394 --- /dev/null +++ b/hm_sunwell/node_modules/fresh/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/fresh/README.md b/hm_sunwell/node_modules/fresh/README.md new file mode 100644 index 0000000..0813e30 --- /dev/null +++ b/hm_sunwell/node_modules/fresh/README.md @@ -0,0 +1,58 @@ +# fresh + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +HTTP response freshness testing + +## Installation + +``` +$ npm install fresh +``` + +## API + +```js +var fresh = require('fresh') +``` + +### fresh(req, res) + + Check freshness of `req` and `res` headers. + + When the cache is "fresh" __true__ is returned, + otherwise __false__ is returned to indicate that + the cache is now stale. + +## Example + +```js +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'luna' }; +fresh(req, res); +// => false + +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'tobi' }; +fresh(req, res); +// => true +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/fresh.svg +[npm-url]: https://npmjs.org/package/fresh +[node-version-image]: https://img.shields.io/node/v/fresh.svg +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/fresh/master.svg +[travis-url]: https://travis-ci.org/jshttp/fresh +[coveralls-image]: https://img.shields.io/coveralls/jshttp/fresh/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/fresh?branch=master +[downloads-image]: https://img.shields.io/npm/dm/fresh.svg +[downloads-url]: https://npmjs.org/package/fresh diff --git a/hm_sunwell/node_modules/fresh/index.js b/hm_sunwell/node_modules/fresh/index.js new file mode 100644 index 0000000..a900873 --- /dev/null +++ b/hm_sunwell/node_modules/fresh/index.js @@ -0,0 +1,57 @@ + +/** + * Expose `fresh()`. + */ + +module.exports = fresh; + +/** + * Check freshness of `req` and `res` headers. + * + * When the cache is "fresh" __true__ is returned, + * otherwise __false__ is returned to indicate that + * the cache is now stale. + * + * @param {Object} req + * @param {Object} res + * @return {Boolean} + * @api public + */ + +function fresh(req, res) { + // defaults + var etagMatches = true; + var notModified = true; + + // fields + var modifiedSince = req['if-modified-since']; + var noneMatch = req['if-none-match']; + var lastModified = res['last-modified']; + var etag = res['etag']; + var cc = req['cache-control']; + + // unconditional request + if (!modifiedSince && !noneMatch) return false; + + // check for no-cache cache request directive + if (cc && cc.indexOf('no-cache') !== -1) return false; + + // parse if-none-match + if (noneMatch) noneMatch = noneMatch.split(/ *, */); + + // if-none-match + if (noneMatch) { + etagMatches = noneMatch.some(function (match) { + return match === '*' || match === etag || match === 'W/' + etag; + }); + } + + // if-modified-since + if (modifiedSince) { + modifiedSince = new Date(modifiedSince); + lastModified = new Date(lastModified); + notModified = lastModified <= modifiedSince; + } + + return !! (etagMatches && notModified); +} diff --git a/hm_sunwell/node_modules/fresh/package.json b/hm_sunwell/node_modules/fresh/package.json new file mode 100644 index 0000000..94a4b48 --- /dev/null +++ b/hm_sunwell/node_modules/fresh/package.json @@ -0,0 +1,114 @@ +{ + "_args": [ + [ + "fresh@0.3.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "fresh@0.3.0", + "_id": "fresh@0.3.0", + "_inCache": true, + "_installable": true, + "_location": "/fresh", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "fresh", + "raw": "fresh@0.3.0", + "rawSpec": "0.3.0", + "scope": null, + "spec": "0.3.0", + "type": "version" + }, + "_requiredBy": [ + "/express", + "/send" + ], + "_resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "_shasum": "651f838e22424e7566de161d8358caa199f83d4f", + "_shrinkwrap": null, + "_spec": "fresh@0.3.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk", + "url": "http://tjholowaychuk.com" + }, + "bugs": { + "url": "https://github.com/jshttp/fresh/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": {}, + "description": "HTTP response freshness testing", + "devDependencies": { + "istanbul": "0.3.9", + "mocha": "1.21.5" + }, + "directories": {}, + "dist": { + "shasum": "651f838e22424e7566de161d8358caa199f83d4f", + "tarball": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "gitHead": "14616c9748368ca08cd6a955dd88ab659b778634", + "homepage": "https://github.com/jshttp/fresh", + "keywords": [ + "cache", + "conditional", + "fresh", + "http" + ], + "license": "MIT", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "jonathanong", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + } + ], + "name": "fresh", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/fresh.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "0.3.0" +} diff --git a/hm_sunwell/node_modules/generate-function/.npmignore b/hm_sunwell/node_modules/generate-function/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/hm_sunwell/node_modules/generate-function/.travis.yml b/hm_sunwell/node_modules/generate-function/.travis.yml new file mode 100644 index 0000000..6e5919d --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" diff --git a/hm_sunwell/node_modules/generate-function/README.md b/hm_sunwell/node_modules/generate-function/README.md new file mode 100644 index 0000000..693bff8 --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/README.md @@ -0,0 +1,72 @@ +# generate-function + +Module that helps you write generated functions in Node + +``` +npm install generate-function +``` + +[![build status](http://img.shields.io/travis/mafintosh/generate-function.svg?style=flat)](http://travis-ci.org/mafintosh/generate-function) + +## Disclamer + +Writing code that generates code is hard. +You should only use this if you really, really, really need this for performance reasons (like schema validators / parsers etc). + +## Usage + +``` js +var genfun = require('generate-function') + +var addNumber = function(val) { + var fn = genfun() + ('function add(n) {') + ('return n + %d', val) // supports format strings to insert values + ('}') + + return fn.toFunction() // will compile the function +} + +var add2 = addNumber(2) + +console.log('1+2=', add2(1)) +console.log(add2.toString()) // prints the generated function +``` + +If you need to close over variables in your generated function pass them to `toFunction(scope)` + +``` js +var multiply = function(a, b) { + return a * b +} + +var addAndMultiplyNumber = function(val) { + var fn = genfun() + ('function(n) {') + ('if (typeof n !== "number") {') // ending a line with { will indent the source + ('throw new Error("argument should be a number")') + ('}') + ('var result = multiply(%d, n+%d)', val, val) + ('return result') + ('}') + + // use fn.toString() if you want to see the generated source + + return fn.toFunction({ + multiply: multiply + }) +} + +var addAndMultiply2 = addAndMultiplyNumber(2) + +console.log('(3 + 2) * 2 =', addAndMultiply2(3)) +``` + +## Related + +See [generate-object-property](https://github.com/mafintosh/generate-object-property) if you need to safely generate code that +can be used to reference an object property + +## License + +MIT \ No newline at end of file diff --git a/hm_sunwell/node_modules/generate-function/example.js b/hm_sunwell/node_modules/generate-function/example.js new file mode 100644 index 0000000..8d1fee1 --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/example.js @@ -0,0 +1,27 @@ +var genfun = require('./') + +var multiply = function(a, b) { + return a * b +} + +var addAndMultiplyNumber = function(val) { + var fn = genfun() + ('function(n) {') + ('if (typeof n !== "number") {') // ending a line with { will indent the source + ('throw new Error("argument should be a number")') + ('}') + ('var result = multiply(%d, n+%d)', val, val) + ('return result') + ('}') + + // use fn.toString() if you want to see the generated source + + return fn.toFunction({ + multiply: multiply + }) +} + +var addAndMultiply2 = addAndMultiplyNumber(2) + +console.log(addAndMultiply2.toString()) +console.log('(3 + 2) * 2 =', addAndMultiply2(3)) \ No newline at end of file diff --git a/hm_sunwell/node_modules/generate-function/index.js b/hm_sunwell/node_modules/generate-function/index.js new file mode 100644 index 0000000..37e064b --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/index.js @@ -0,0 +1,61 @@ +var util = require('util') + +var INDENT_START = /[\{\[]/ +var INDENT_END = /[\}\]]/ + +module.exports = function() { + var lines = [] + var indent = 0 + + var push = function(str) { + var spaces = '' + while (spaces.length < indent*2) spaces += ' ' + lines.push(spaces+str) + } + + var line = function(fmt) { + if (!fmt) return line + + if (INDENT_END.test(fmt.trim()[0]) && INDENT_START.test(fmt[fmt.length-1])) { + indent-- + push(util.format.apply(util, arguments)) + indent++ + return line + } + if (INDENT_START.test(fmt[fmt.length-1])) { + push(util.format.apply(util, arguments)) + indent++ + return line + } + if (INDENT_END.test(fmt.trim()[0])) { + indent-- + push(util.format.apply(util, arguments)) + return line + } + + push(util.format.apply(util, arguments)) + return line + } + + line.toString = function() { + return lines.join('\n') + } + + line.toFunction = function(scope) { + var src = 'return ('+line.toString()+')' + + var keys = Object.keys(scope || {}).map(function(key) { + return key + }) + + var vals = keys.map(function(key) { + return scope[key] + }) + + return Function.apply(null, keys.concat(src)).apply(null, vals) + } + + if (arguments.length) line.apply(null, arguments) + + return line +} diff --git a/hm_sunwell/node_modules/generate-function/package.json b/hm_sunwell/node_modules/generate-function/package.json new file mode 100644 index 0000000..b87443b --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/package.json @@ -0,0 +1,79 @@ +{ + "_args": [ + [ + "generate-function@^2.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/is-my-json-valid" + ] + ], + "_from": "generate-function@>=2.0.0 <3.0.0", + "_id": "generate-function@2.0.0", + "_inCache": true, + "_installable": true, + "_location": "/generate-function", + "_npmUser": { + "email": "mathiasbuus@gmail.com", + "name": "mafintosh" + }, + "_npmVersion": "1.4.23", + "_phantomChildren": {}, + "_requested": { + "name": "generate-function", + "raw": "generate-function@^2.0.0", + "rawSpec": "^2.0.0", + "scope": null, + "spec": ">=2.0.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/is-my-json-valid" + ], + "_resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "_shasum": "6858fe7c0969b7d4e9093337647ac79f60dfbe74", + "_shrinkwrap": null, + "_spec": "generate-function@^2.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/is-my-json-valid", + "author": { + "name": "Mathias Buus" + }, + "bugs": { + "url": "https://github.com/mafintosh/generate-function/issues" + }, + "dependencies": {}, + "description": "Module that helps you write generated functions in Node", + "devDependencies": { + "tape": "^2.13.4" + }, + "directories": {}, + "dist": { + "shasum": "6858fe7c0969b7d4e9093337647ac79f60dfbe74", + "tarball": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + }, + "gitHead": "3d5fc8de5859be95f58e3af9bfb5f663edd95149", + "homepage": "https://github.com/mafintosh/generate-function", + "keywords": [ + "code", + "function", + "generate", + "generation", + "performance" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "mafintosh", + "email": "mathiasbuus@gmail.com" + } + ], + "name": "generate-function", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/mafintosh/generate-function.git" + }, + "scripts": { + "test": "tape test.js" + }, + "version": "2.0.0" +} diff --git a/hm_sunwell/node_modules/generate-function/test.js b/hm_sunwell/node_modules/generate-function/test.js new file mode 100644 index 0000000..2768893 --- /dev/null +++ b/hm_sunwell/node_modules/generate-function/test.js @@ -0,0 +1,33 @@ +var tape = require('tape') +var genfun = require('./') + +tape('generate add function', function(t) { + var fn = genfun() + ('function add(n) {') + ('return n + %d', 42) + ('}') + + t.same(fn.toString(), 'function add(n) {\n return n + 42\n}', 'code is indented') + t.same(fn.toFunction()(10), 52, 'function works') + t.end() +}) + +tape('generate function + closed variables', function(t) { + var fn = genfun() + ('function add(n) {') + ('return n + %d + number', 42) + ('}') + + var notGood = fn.toFunction() + var good = fn.toFunction({number:10}) + + try { + notGood(10) + t.ok(false, 'function should not work') + } catch (err) { + t.same(err.message, 'number is not defined', 'throws reference error') + } + + t.same(good(11), 63, 'function with closed var works') + t.end() +}) \ No newline at end of file diff --git a/hm_sunwell/node_modules/generate-object-property/.npmignore b/hm_sunwell/node_modules/generate-object-property/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/hm_sunwell/node_modules/generate-object-property/.travis.yml b/hm_sunwell/node_modules/generate-object-property/.travis.yml new file mode 100644 index 0000000..6e5919d --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" diff --git a/hm_sunwell/node_modules/generate-object-property/LICENSE b/hm_sunwell/node_modules/generate-object-property/LICENSE new file mode 100644 index 0000000..757562e --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/hm_sunwell/node_modules/generate-object-property/README.md b/hm_sunwell/node_modules/generate-object-property/README.md new file mode 100644 index 0000000..0ee0461 --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/README.md @@ -0,0 +1,19 @@ +# generate-object-property + +Generate safe JS code that can used to reference a object property + + npm install generate-object-property + +[![build status](http://img.shields.io/travis/mafintosh/generate-object-property.svg?style=flat)](http://travis-ci.org/mafintosh/generate-object-property) + +## Usage + +``` js +var gen = require('generate-object-property'); +console.log(gen('a','b')); // prints a.b +console.log(gen('a', 'foo-bar')); // prints a["foo-bar"] +``` + +## License + +MIT \ No newline at end of file diff --git a/hm_sunwell/node_modules/generate-object-property/index.js b/hm_sunwell/node_modules/generate-object-property/index.js new file mode 100644 index 0000000..5dc9f77 --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/index.js @@ -0,0 +1,12 @@ +var isProperty = require('is-property') + +var gen = function(obj, prop) { + return isProperty(prop) ? obj+'.'+prop : obj+'['+JSON.stringify(prop)+']' +} + +gen.valid = isProperty +gen.property = function (prop) { + return isProperty(prop) ? prop : JSON.stringify(prop) +} + +module.exports = gen diff --git a/hm_sunwell/node_modules/generate-object-property/package.json b/hm_sunwell/node_modules/generate-object-property/package.json new file mode 100644 index 0000000..922b6df --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/package.json @@ -0,0 +1,76 @@ +{ + "_args": [ + [ + "generate-object-property@^1.1.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/is-my-json-valid" + ] + ], + "_from": "generate-object-property@>=1.1.0 <2.0.0", + "_id": "generate-object-property@1.2.0", + "_inCache": true, + "_installable": true, + "_location": "/generate-object-property", + "_nodeVersion": "2.0.1", + "_npmUser": { + "email": "mathiasbuus@gmail.com", + "name": "mafintosh" + }, + "_npmVersion": "2.9.0", + "_phantomChildren": {}, + "_requested": { + "name": "generate-object-property", + "raw": "generate-object-property@^1.1.0", + "rawSpec": "^1.1.0", + "scope": null, + "spec": ">=1.1.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/is-my-json-valid" + ], + "_resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "_shasum": "9c0e1c40308ce804f4783618b937fa88f99d50d0", + "_shrinkwrap": null, + "_spec": "generate-object-property@^1.1.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/is-my-json-valid", + "author": { + "name": "Mathias Buus", + "url": "@mafintosh" + }, + "bugs": { + "url": "https://github.com/mafintosh/generate-object-property/issues" + }, + "dependencies": { + "is-property": "^1.0.0" + }, + "description": "Generate safe JS code that can used to reference a object property", + "devDependencies": { + "tape": "^2.13.0" + }, + "directories": {}, + "dist": { + "shasum": "9c0e1c40308ce804f4783618b937fa88f99d50d0", + "tarball": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + }, + "gitHead": "0dd7d411018de54b2eae63b424c15b3e50bd678c", + "homepage": "https://github.com/mafintosh/generate-object-property", + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "mafintosh", + "email": "mathiasbuus@gmail.com" + } + ], + "name": "generate-object-property", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/mafintosh/generate-object-property.git" + }, + "scripts": { + "test": "tape test.js" + }, + "version": "1.2.0" +} diff --git a/hm_sunwell/node_modules/generate-object-property/test.js b/hm_sunwell/node_modules/generate-object-property/test.js new file mode 100644 index 0000000..6c299c6 --- /dev/null +++ b/hm_sunwell/node_modules/generate-object-property/test.js @@ -0,0 +1,12 @@ +var tape = require('tape') +var gen = require('./') + +tape('valid', function(t) { + t.same(gen('a', 'b'), 'a.b') + t.end() +}) + +tape('invalid', function(t) { + t.same(gen('a', '-b'), 'a["-b"]') + t.end() +}) \ No newline at end of file diff --git a/hm_sunwell/node_modules/getpass/.npmignore b/hm_sunwell/node_modules/getpass/.npmignore new file mode 100644 index 0000000..a4261fc --- /dev/null +++ b/hm_sunwell/node_modules/getpass/.npmignore @@ -0,0 +1,8 @@ +.gitmodules +deps +docs +Makefile +node_modules +test +tools +coverage diff --git a/hm_sunwell/node_modules/getpass/.travis.yml b/hm_sunwell/node_modules/getpass/.travis.yml new file mode 100644 index 0000000..d8b5833 --- /dev/null +++ b/hm_sunwell/node_modules/getpass/.travis.yml @@ -0,0 +1,9 @@ +language: node_js +node_js: + - "5.10" + - "4.4" + - "4.1" + - "0.12" + - "0.10" +before_install: + - "make check" diff --git a/hm_sunwell/node_modules/getpass/LICENSE b/hm_sunwell/node_modules/getpass/LICENSE new file mode 100644 index 0000000..f6d947d --- /dev/null +++ b/hm_sunwell/node_modules/getpass/LICENSE @@ -0,0 +1,18 @@ +Copyright Joyent, Inc. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/getpass/README.md b/hm_sunwell/node_modules/getpass/README.md new file mode 100644 index 0000000..6e4a50f --- /dev/null +++ b/hm_sunwell/node_modules/getpass/README.md @@ -0,0 +1,32 @@ +## getpass + +Get a password from the terminal. Sounds simple? Sounds like the `readline` +module should be able to do it? NOPE. + +## Install and use it + +```bash +npm install --save getpass +``` + +```javascript +const mod_getpass = require('getpass'); +``` + +## API + +### `mod_getpass.getPass([options, ]callback)` + +Gets a password from the terminal. If available, this uses `/dev/tty` to avoid +interfering with any data being piped in or out of stdio. + +This function prints a prompt (by default `Password:`) and then accepts input +without echoing. + +Parameters: + + * `options`, an Object, with properties: + * `prompt`, an optional String + * `callback`, a `Func(error, password)`, with arguments: + * `error`, either `null` (no error) or an `Error` instance + * `password`, a String diff --git a/hm_sunwell/node_modules/getpass/lib/index.js b/hm_sunwell/node_modules/getpass/lib/index.js new file mode 100644 index 0000000..55a7718 --- /dev/null +++ b/hm_sunwell/node_modules/getpass/lib/index.js @@ -0,0 +1,123 @@ +/* + * Copyright 2016, Joyent, Inc. All rights reserved. + * Author: Alex Wilson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. +*/ + +module.exports = { + getPass: getPass +}; + +const mod_tty = require('tty'); +const mod_fs = require('fs'); +const mod_assert = require('assert-plus'); + +var BACKSPACE = String.fromCharCode(127); +var CTRLC = '\u0003'; +var CTRLD = '\u0004'; + +function getPass(opts, cb) { + if (typeof (opts) === 'function' && cb === undefined) { + cb = opts; + opts = {}; + } + mod_assert.object(opts, 'options'); + mod_assert.func(cb, 'callback'); + + mod_assert.optionalString(opts.prompt, 'options.prompt'); + if (opts.prompt === undefined) + opts.prompt = 'Password'; + + openTTY(function (err, rfd, wfd, rtty, wtty) { + if (err) { + cb(err); + return; + } + + wtty.write(opts.prompt + ':'); + rtty.resume(); + rtty.setRawMode(true); + rtty.resume(); + rtty.setEncoding('utf8'); + + var pw = ''; + rtty.on('data', onData); + + function onData(data) { + var str = data.toString('utf8'); + for (var i = 0; i < str.length; ++i) { + var ch = str[i]; + switch (ch) { + case '\r': + case '\n': + case CTRLD: + cleanup(); + cb(null, pw); + return; + case CTRLC: + cleanup(); + cb(new Error('Aborted')); + return; + case BACKSPACE: + pw = pw.slice(0, pw.length - 1); + break; + default: + pw += ch; + break; + } + } + } + + function cleanup() { + wtty.write('\r\n'); + rtty.setRawMode(false); + rtty.pause(); + rtty.removeListener('data', onData); + if (wfd !== undefined && wfd !== rfd) { + wtty.end(); + mod_fs.closeSync(wfd); + } + if (rfd !== undefined) { + rtty.end(); + mod_fs.closeSync(rfd); + } + } + }); +} + +function openTTY(cb) { + mod_fs.open('/dev/tty', 'r+', function (err, rttyfd) { + if ((err && (err.code === 'ENOENT' || err.code === 'EACCES')) || + (process.version.match(/^v0[.][0-8][.]/))) { + cb(null, undefined, undefined, process.stdin, + process.stdout); + return; + } + var rtty = new mod_tty.ReadStream(rttyfd); + mod_fs.open('/dev/tty', 'w+', function (err3, wttyfd) { + var wtty = new mod_tty.WriteStream(wttyfd); + if (err3) { + cb(err3); + return; + } + cb(null, rttyfd, wttyfd, rtty, wtty); + }); + }); +} diff --git a/hm_sunwell/node_modules/getpass/node_modules/assert-plus/AUTHORS b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/AUTHORS new file mode 100644 index 0000000..1923524 --- /dev/null +++ b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/AUTHORS @@ -0,0 +1,6 @@ +Dave Eddy +Fred Kuo +Lars-Magnus Skog +Mark Cavage +Patrick Mooney +Rob Gulewich diff --git a/hm_sunwell/node_modules/getpass/node_modules/assert-plus/CHANGES.md b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/CHANGES.md new file mode 100644 index 0000000..57d92bf --- /dev/null +++ b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/CHANGES.md @@ -0,0 +1,14 @@ +# assert-plus Changelog + +## 1.0.0 + +- *BREAKING* assert.number (and derivatives) now accept Infinity as valid input +- Add assert.finite check. Previous assert.number callers should use this if + they expect Infinity inputs to throw. + +## 0.2.0 + +- Fix `assert.object(null)` so it throws +- Fix optional/arrayOf exports for non-type-of asserts +- Add optiona/arrayOf exports for Stream/Date/Regex/uuid +- Add basic unit test coverage diff --git a/hm_sunwell/node_modules/getpass/node_modules/assert-plus/README.md b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/README.md new file mode 100644 index 0000000..ec200d1 --- /dev/null +++ b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/README.md @@ -0,0 +1,162 @@ +# assert-plus + +This library is a super small wrapper over node's assert module that has two +things: (1) the ability to disable assertions with the environment variable +NODE\_NDEBUG, and (2) some API wrappers for argument testing. Like +`assert.string(myArg, 'myArg')`. As a simple example, most of my code looks +like this: + +```javascript + var assert = require('assert-plus'); + + function fooAccount(options, callback) { + assert.object(options, 'options'); + assert.number(options.id, 'options.id'); + assert.bool(options.isManager, 'options.isManager'); + assert.string(options.name, 'options.name'); + assert.arrayOfString(options.email, 'options.email'); + assert.func(callback, 'callback'); + + // Do stuff + callback(null, {}); + } +``` + +# API + +All methods that *aren't* part of node's core assert API are simply assumed to +take an argument, and then a string 'name' that's not a message; `AssertionError` +will be thrown if the assertion fails with a message like: + + AssertionError: foo (string) is required + at test (/home/mark/work/foo/foo.js:3:9) + at Object. (/home/mark/work/foo/foo.js:15:1) + at Module._compile (module.js:446:26) + at Object..js (module.js:464:10) + at Module.load (module.js:353:31) + at Function._load (module.js:311:12) + at Array.0 (module.js:484:10) + at EventEmitter._tickCallback (node.js:190:38) + +from: + +```javascript + function test(foo) { + assert.string(foo, 'foo'); + } +``` + +There you go. You can check that arrays are of a homogeneous type with `Arrayof$Type`: + +```javascript + function test(foo) { + assert.arrayOfString(foo, 'foo'); + } +``` + +You can assert IFF an argument is not `undefined` (i.e., an optional arg): + +```javascript + assert.optionalString(foo, 'foo'); +``` + +Lastly, you can opt-out of assertion checking altogether by setting the +environment variable `NODE_NDEBUG=1`. This is pseudo-useful if you have +lots of assertions, and don't want to pay `typeof ()` taxes to v8 in +production. Be advised: The standard functions re-exported from `assert` are +also disabled in assert-plus if NDEBUG is specified. Using them directly from +the `assert` module avoids this behavior. + +The complete list of APIs is: + +* assert.array +* assert.bool +* assert.buffer +* assert.func +* assert.number +* assert.finite +* assert.object +* assert.string +* assert.stream +* assert.date +* assert.regexp +* assert.uuid +* assert.arrayOfArray +* assert.arrayOfBool +* assert.arrayOfBuffer +* assert.arrayOfFunc +* assert.arrayOfNumber +* assert.arrayOfFinite +* assert.arrayOfObject +* assert.arrayOfString +* assert.arrayOfStream +* assert.arrayOfDate +* assert.arrayOfRegexp +* assert.arrayOfUuid +* assert.optionalArray +* assert.optionalBool +* assert.optionalBuffer +* assert.optionalFunc +* assert.optionalNumber +* assert.optionalFinite +* assert.optionalObject +* assert.optionalString +* assert.optionalStream +* assert.optionalDate +* assert.optionalRegexp +* assert.optionalUuid +* assert.optionalArrayOfArray +* assert.optionalArrayOfBool +* assert.optionalArrayOfBuffer +* assert.optionalArrayOfFunc +* assert.optionalArrayOfNumber +* assert.optionalArrayOfFinite +* assert.optionalArrayOfObject +* assert.optionalArrayOfString +* assert.optionalArrayOfStream +* assert.optionalArrayOfDate +* assert.optionalArrayOfRegexp +* assert.optionalArrayOfUuid +* assert.AssertionError +* assert.fail +* assert.ok +* assert.equal +* assert.notEqual +* assert.deepEqual +* assert.notDeepEqual +* assert.strictEqual +* assert.notStrictEqual +* assert.throws +* assert.doesNotThrow +* assert.ifError + +# Installation + + npm install assert-plus + +## License + +The MIT License (MIT) +Copyright (c) 2012 Mark Cavage + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +## Bugs + +See . diff --git a/hm_sunwell/node_modules/getpass/node_modules/assert-plus/assert.js b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/assert.js new file mode 100644 index 0000000..26f944e --- /dev/null +++ b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/assert.js @@ -0,0 +1,211 @@ +// Copyright (c) 2012, Mark Cavage. All rights reserved. +// Copyright 2015 Joyent, Inc. + +var assert = require('assert'); +var Stream = require('stream').Stream; +var util = require('util'); + + +///--- Globals + +/* JSSTYLED */ +var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/; + + +///--- Internal + +function _capitalize(str) { + return (str.charAt(0).toUpperCase() + str.slice(1)); +} + +function _toss(name, expected, oper, arg, actual) { + throw new assert.AssertionError({ + message: util.format('%s (%s) is required', name, expected), + actual: (actual === undefined) ? typeof (arg) : actual(arg), + expected: expected, + operator: oper || '===', + stackStartFunction: _toss.caller + }); +} + +function _getClass(arg) { + return (Object.prototype.toString.call(arg).slice(8, -1)); +} + +function noop() { + // Why even bother with asserts? +} + + +///--- Exports + +var types = { + bool: { + check: function (arg) { return typeof (arg) === 'boolean'; } + }, + func: { + check: function (arg) { return typeof (arg) === 'function'; } + }, + string: { + check: function (arg) { return typeof (arg) === 'string'; } + }, + object: { + check: function (arg) { + return typeof (arg) === 'object' && arg !== null; + } + }, + number: { + check: function (arg) { + return typeof (arg) === 'number' && !isNaN(arg); + } + }, + finite: { + check: function (arg) { + return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg); + } + }, + buffer: { + check: function (arg) { return Buffer.isBuffer(arg); }, + operator: 'Buffer.isBuffer' + }, + array: { + check: function (arg) { return Array.isArray(arg); }, + operator: 'Array.isArray' + }, + stream: { + check: function (arg) { return arg instanceof Stream; }, + operator: 'instanceof', + actual: _getClass + }, + date: { + check: function (arg) { return arg instanceof Date; }, + operator: 'instanceof', + actual: _getClass + }, + regexp: { + check: function (arg) { return arg instanceof RegExp; }, + operator: 'instanceof', + actual: _getClass + }, + uuid: { + check: function (arg) { + return typeof (arg) === 'string' && UUID_REGEXP.test(arg); + }, + operator: 'isUUID' + } +}; + +function _setExports(ndebug) { + var keys = Object.keys(types); + var out; + + /* re-export standard assert */ + if (process.env.NODE_NDEBUG) { + out = noop; + } else { + out = function (arg, msg) { + if (!arg) { + _toss(msg, 'true', arg); + } + }; + } + + /* standard checks */ + keys.forEach(function (k) { + if (ndebug) { + out[k] = noop; + return; + } + var type = types[k]; + out[k] = function (arg, msg) { + if (!type.check(arg)) { + _toss(msg, k, type.operator, arg, type.actual); + } + }; + }); + + /* optional checks */ + keys.forEach(function (k) { + var name = 'optional' + _capitalize(k); + if (ndebug) { + out[name] = noop; + return; + } + var type = types[k]; + out[name] = function (arg, msg) { + if (arg === undefined || arg === null) { + return; + } + if (!type.check(arg)) { + _toss(msg, k, type.operator, arg, type.actual); + } + }; + }); + + /* arrayOf checks */ + keys.forEach(function (k) { + var name = 'arrayOf' + _capitalize(k); + if (ndebug) { + out[name] = noop; + return; + } + var type = types[k]; + var expected = '[' + k + ']'; + out[name] = function (arg, msg) { + if (!Array.isArray(arg)) { + _toss(msg, expected, type.operator, arg, type.actual); + } + var i; + for (i = 0; i < arg.length; i++) { + if (!type.check(arg[i])) { + _toss(msg, expected, type.operator, arg, type.actual); + } + } + }; + }); + + /* optionalArrayOf checks */ + keys.forEach(function (k) { + var name = 'optionalArrayOf' + _capitalize(k); + if (ndebug) { + out[name] = noop; + return; + } + var type = types[k]; + var expected = '[' + k + ']'; + out[name] = function (arg, msg) { + if (arg === undefined || arg === null) { + return; + } + if (!Array.isArray(arg)) { + _toss(msg, expected, type.operator, arg, type.actual); + } + var i; + for (i = 0; i < arg.length; i++) { + if (!type.check(arg[i])) { + _toss(msg, expected, type.operator, arg, type.actual); + } + } + }; + }); + + /* re-export built-in assertions */ + Object.keys(assert).forEach(function (k) { + if (k === 'AssertionError') { + out[k] = assert[k]; + return; + } + if (ndebug) { + out[k] = noop; + return; + } + out[k] = assert[k]; + }); + + /* export ourselves (for unit tests _only_) */ + out._setExports = _setExports; + + return out; +} + +module.exports = _setExports(process.env.NODE_NDEBUG); diff --git a/hm_sunwell/node_modules/getpass/node_modules/assert-plus/package.json b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/package.json new file mode 100644 index 0000000..3628f51 --- /dev/null +++ b/hm_sunwell/node_modules/getpass/node_modules/assert-plus/package.json @@ -0,0 +1,107 @@ +{ + "_args": [ + [ + "assert-plus@^1.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/getpass" + ] + ], + "_from": "assert-plus@>=1.0.0 <2.0.0", + "_id": "assert-plus@1.0.0", + "_inCache": true, + "_installable": true, + "_location": "/getpass/assert-plus", + "_nodeVersion": "0.10.40", + "_npmUser": { + "email": "patrick.f.mooney@gmail.com", + "name": "pfmooney" + }, + "_npmVersion": "3.3.9", + "_phantomChildren": {}, + "_requested": { + "name": "assert-plus", + "raw": "assert-plus@^1.0.0", + "rawSpec": "^1.0.0", + "scope": null, + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/getpass" + ], + "_resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "_shasum": "f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525", + "_shrinkwrap": null, + "_spec": "assert-plus@^1.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/getpass", + "author": { + "email": "mcavage@gmail.com", + "name": "Mark Cavage" + }, + "bugs": { + "url": "https://github.com/mcavage/node-assert-plus/issues" + }, + "contributors": [ + { + "name": "Dave Eddy", + "email": "dave@daveeddy.com" + }, + { + "name": "Fred Kuo", + "email": "fred.kuo@joyent.com" + }, + { + "name": "Lars-Magnus Skog", + "email": "ralphtheninja@riseup.net" + }, + { + "name": "Mark Cavage", + "email": "mcavage@gmail.com" + }, + { + "name": "Patrick Mooney", + "email": "pmooney@pfmooney.com" + }, + { + "name": "Rob Gulewich", + "email": "robert.gulewich@joyent.com" + } + ], + "dependencies": {}, + "description": "Extra assertions on top of node's assert module", + "devDependencies": { + "faucet": "0.0.1", + "tape": "4.2.2" + }, + "directories": {}, + "dist": { + "shasum": "f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525", + "tarball": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + }, + "engines": { + "node": ">=0.8" + }, + "homepage": "https://github.com/mcavage/node-assert-plus#readme", + "license": "MIT", + "main": "./assert.js", + "maintainers": [ + { + "name": "mcavage", + "email": "mcavage@gmail.com" + }, + { + "name": "pfmooney", + "email": "patrick.f.mooney@gmail.com" + } + ], + "name": "assert-plus", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/mcavage/node-assert-plus.git" + }, + "scripts": { + "test": "tape tests/*.js | ./node_modules/.bin/faucet" + }, + "version": "1.0.0" +} diff --git a/hm_sunwell/node_modules/getpass/package.json b/hm_sunwell/node_modules/getpass/package.json new file mode 100644 index 0000000..1bbd2e4 --- /dev/null +++ b/hm_sunwell/node_modules/getpass/package.json @@ -0,0 +1,82 @@ +{ + "_args": [ + [ + "getpass@^0.1.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk" + ] + ], + "_from": "getpass@>=0.1.1 <0.2.0", + "_id": "getpass@0.1.6", + "_inCache": true, + "_installable": true, + "_location": "/getpass", + "_nodeVersion": "0.12.9", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/getpass-0.1.6.tgz_1461907090215_0.6450737570412457" + }, + "_npmUser": { + "email": "alex@cooperi.net", + "name": "arekinath" + }, + "_npmVersion": "2.14.9", + "_phantomChildren": {}, + "_requested": { + "name": "getpass", + "raw": "getpass@^0.1.1", + "rawSpec": "^0.1.1", + "scope": null, + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/sshpk" + ], + "_resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "_shasum": "283ffd9fc1256840875311c1b60e8c40187110e6", + "_shrinkwrap": null, + "_spec": "getpass@^0.1.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk", + "author": { + "email": "alex.wilson@joyent.com", + "name": "Alex Wilson" + }, + "bugs": { + "url": "https://github.com/arekinath/node-getpass/issues" + }, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "description": "getpass for node.js", + "devDependencies": { + "json": "^9.0.3", + "pty.js": "^0.3.0", + "tape": "^4.4.0" + }, + "directories": {}, + "dist": { + "shasum": "283ffd9fc1256840875311c1b60e8c40187110e6", + "tarball": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz" + }, + "gitHead": "e7fdf43ad60aa520f894d41856852aa320f36646", + "homepage": "https://github.com/arekinath/node-getpass#readme", + "license": "MIT", + "main": "lib/index.js", + "maintainers": [ + { + "name": "arekinath", + "email": "alex@cooperi.net" + } + ], + "name": "getpass", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/arekinath/node-getpass.git" + }, + "scripts": { + "test": "tape test/*.test.js" + }, + "version": "0.1.6" +} diff --git a/hm_sunwell/node_modules/glob/LICENSE b/hm_sunwell/node_modules/glob/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/hm_sunwell/node_modules/glob/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/hm_sunwell/node_modules/glob/README.md b/hm_sunwell/node_modules/glob/README.md new file mode 100644 index 0000000..063cf95 --- /dev/null +++ b/hm_sunwell/node_modules/glob/README.md @@ -0,0 +1,377 @@ +[![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Dependency Status](https://david-dm.org/isaacs/node-glob.svg)](https://david-dm.org/isaacs/node-glob) [![devDependency Status](https://david-dm.org/isaacs/node-glob/dev-status.svg)](https://david-dm.org/isaacs/node-glob#info=devDependencies) [![optionalDependency Status](https://david-dm.org/isaacs/node-glob/optional-status.svg)](https://david-dm.org/isaacs/node-glob#info=optionalDependencies) + +# Glob + +Match files using the patterns the shell uses, like stars and stuff. + +This is a glob implementation in JavaScript. It uses the `minimatch` +library to do its matching. + +![](oh-my-glob.gif) + +## Usage + +```javascript +var glob = require("glob") + +// options is optional +glob("**/*.js", options, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. +}) +``` + +## Glob Primer + +"Globs" are the patterns you type when you do stuff like `ls *.js` on +the command line, or put `build/*` in a `.gitignore` file. + +Before parsing the path part patterns, braced sections are expanded +into a set. Braced sections start with `{` and end with `}`, with any +number of comma-delimited sections within. Braced sections may contain +slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`. + +The following characters have special magic meaning when used in a +path portion: + +* `*` Matches 0 or more characters in a single path portion +* `?` Matches 1 character +* `[...]` Matches a range of characters, similar to a RegExp range. + If the first character of the range is `!` or `^` then it matches + any character not in the range. +* `!(pattern|pattern|pattern)` Matches anything that does not match + any of the patterns provided. +* `?(pattern|pattern|pattern)` Matches zero or one occurrence of the + patterns provided. +* `+(pattern|pattern|pattern)` Matches one or more occurrences of the + patterns provided. +* `*(a|b|c)` Matches zero or more occurrences of the patterns provided +* `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns + provided +* `**` If a "globstar" is alone in a path portion, then it matches + zero or more directories and subdirectories searching for matches. + It does not crawl symlinked directories. + +### Dots + +If a file or directory path portion has a `.` as the first character, +then it will not match any glob pattern unless that pattern's +corresponding path part also has a `.` as its first character. + +For example, the pattern `a/.*/c` would match the file at `a/.b/c`. +However the pattern `a/*/c` would not, because `*` does not start with +a dot character. + +You can make glob treat dots as normal characters by setting +`dot:true` in the options. + +### Basename Matching + +If you set `matchBase:true` in the options, and the pattern has no +slashes in it, then it will seek for any file anywhere in the tree +with a matching basename. For example, `*.js` would match +`test/simple/basic.js`. + +### Negation + +The intent for negation would be for a pattern starting with `!` to +match everything that *doesn't* match the supplied pattern. However, +the implementation is weird, and for the time being, this should be +avoided. The behavior is deprecated in version 5, and will be removed +entirely in version 6. + +### Empty Sets + +If no matching files are found, then an empty array is returned. This +differs from the shell, where the pattern itself is returned. For +example: + + $ echo a*s*d*f + a*s*d*f + +To get the bash-style behavior, set the `nonull:true` in the options. + +### See Also: + +* `man sh` +* `man bash` (Search for "Pattern Matching") +* `man 3 fnmatch` +* `man 5 gitignore` +* [minimatch documentation](https://github.com/isaacs/minimatch) + +## glob.hasMagic(pattern, [options]) + +Returns `true` if there are any special characters in the pattern, and +`false` otherwise. + +Note that the options affect the results. If `noext:true` is set in +the options object, then `+(a|b)` will not be considered a magic +pattern. If the pattern has a brace expansion, like `a/{b/c,x/y}` +then that is considered magical, unless `nobrace:true` is set in the +options. + +## glob(pattern, [options], cb) + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* `cb` {Function} + * `err` {Error | null} + * `matches` {Array} filenames found matching the pattern + +Perform an asynchronous glob search. + +## glob.sync(pattern, [options]) + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* return: {Array} filenames found matching the pattern + +Perform a synchronous glob search. + +## Class: glob.Glob + +Create a Glob object by instantiating the `glob.Glob` class. + +```javascript +var Glob = require("glob").Glob +var mg = new Glob(pattern, options, cb) +``` + +It's an EventEmitter, and starts walking the filesystem to find matches +immediately. + +### new glob.Glob(pattern, [options], [cb]) + +* `pattern` {String} pattern to search for +* `options` {Object} +* `cb` {Function} Called when an error occurs, or matches are found + * `err` {Error | null} + * `matches` {Array} filenames found matching the pattern + +Note that if the `sync` flag is set in the options, then matches will +be immediately available on the `g.found` member. + +### Properties + +* `minimatch` The minimatch object that the glob uses. +* `options` The options object passed in. +* `aborted` Boolean which is set to true when calling `abort()`. There + is no way at this time to continue a glob search after aborting, but + you can re-use the statCache to avoid having to duplicate syscalls. +* `cache` Convenience object. Each field has the following possible + values: + * `false` - Path does not exist + * `true` - Path exists + * `'DIR'` - Path exists, and is not a directory + * `'FILE'` - Path exists, and is a directory + * `[file, entries, ...]` - Path exists, is a directory, and the + array value is the results of `fs.readdir` +* `statCache` Cache of `fs.stat` results, to prevent statting the same + path multiple times. +* `symlinks` A record of which paths are symbolic links, which is + relevant in resolving `**` patterns. +* `realpathCache` An optional object which is passed to `fs.realpath` + to minimize unnecessary syscalls. It is stored on the instantiated + Glob object, and may be re-used. + +### Events + +* `end` When the matching is finished, this is emitted with all the + matches found. If the `nonull` option is set, and no match was found, + then the `matches` list contains the original pattern. The matches + are sorted, unless the `nosort` flag is set. +* `match` Every time a match is found, this is emitted with the matched. +* `error` Emitted when an unexpected error is encountered, or whenever + any fs error occurs if `options.strict` is set. +* `abort` When `abort()` is called, this event is raised. + +### Methods + +* `pause` Temporarily stop the search +* `resume` Resume the search +* `abort` Stop the search forever + +### Options + +All the options that can be passed to Minimatch can also be passed to +Glob to change pattern matching behavior. Also, some have been added, +or have glob-specific ramifications. + +All options are false by default, unless otherwise noted. + +All options are added to the Glob object, as well. + +If you are running many `glob` operations, you can pass a Glob object +as the `options` argument to a subsequent operation to shortcut some +`stat` and `readdir` calls. At the very least, you may pass in shared +`symlinks`, `statCache`, `realpathCache`, and `cache` options, so that +parallel glob operations will be sped up by sharing information about +the filesystem. + +* `cwd` The current working directory in which to search. Defaults + to `process.cwd()`. +* `root` The place where patterns starting with `/` will be mounted + onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix + systems, and `C:\` or some such on Windows.) +* `dot` Include `.dot` files in normal matches and `globstar` matches. + Note that an explicit dot in a portion of the pattern will always + match dot files. +* `nomount` By default, a pattern starting with a forward-slash will be + "mounted" onto the root setting, so that a valid filesystem path is + returned. Set this flag to disable that behavior. +* `mark` Add a `/` character to directory matches. Note that this + requires additional stat calls. +* `nosort` Don't sort the results. +* `stat` Set to true to stat *all* results. This reduces performance + somewhat, and is completely unnecessary, unless `readdir` is presumed + to be an untrustworthy indicator of file existence. +* `silent` When an unusual error is encountered when attempting to + read a directory, a warning will be printed to stderr. Set the + `silent` option to true to suppress these warnings. +* `strict` When an unusual error is encountered when attempting to + read a directory, the process will just continue on in search of + other matches. Set the `strict` option to raise an error in these + cases. +* `cache` See `cache` property above. Pass in a previously generated + cache object to save some fs calls. +* `statCache` A cache of results of filesystem information, to prevent + unnecessary stat calls. While it should not normally be necessary + to set this, you may pass the statCache from one glob() call to the + options object of another, if you know that the filesystem will not + change between calls. (See "Race Conditions" below.) +* `symlinks` A cache of known symbolic links. You may pass in a + previously generated `symlinks` object to save `lstat` calls when + resolving `**` matches. +* `sync` DEPRECATED: use `glob.sync(pattern, opts)` instead. +* `nounique` In some cases, brace-expanded patterns can result in the + same file showing up multiple times in the result set. By default, + this implementation prevents duplicates in the result set. Set this + flag to disable that behavior. +* `nonull` Set to never return an empty set, instead returning a set + containing the pattern itself. This is the default in glob(3). +* `debug` Set to enable debug logging in minimatch and glob. +* `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets. +* `noglobstar` Do not match `**` against multiple filenames. (Ie, + treat it as a normal `*` instead.) +* `noext` Do not match `+(a|b)` "extglob" patterns. +* `nocase` Perform a case-insensitive match. Note: on + case-insensitive filesystems, non-magic patterns will match by + default, since `stat` and `readdir` will not raise errors. +* `matchBase` Perform a basename-only match if the pattern does not + contain any slash characters. That is, `*.js` would be treated as + equivalent to `**/*.js`, matching all js files in all directories. +* `nodir` Do not match directories, only files. (Note: to match + *only* directories, simply put a `/` at the end of the pattern.) +* `ignore` Add a pattern or an array of patterns to exclude matches. +* `follow` Follow symlinked directories when expanding `**` patterns. + Note that this can result in a lot of duplicate references in the + presence of cyclic links. +* `realpath` Set to true to call `fs.realpath` on all of the results. + In the case of a symlink that cannot be resolved, the full absolute + path to the matched entry is returned (though it will usually be a + broken symlink) +* `nonegate` Suppress deprecated `negate` behavior. (See below.) + Default=true +* `nocomment` Suppress deprecated `comment` behavior. (See below.) + Default=true + +## Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between node-glob and other +implementations, and are intentional. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.3, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. + +Note that symlinked directories are not crawled as part of a `**`, +though their contents may match against subsequent portions of the +pattern. This prevents infinite loops and duplicates and the like. + +If an escaped pattern has no matches, and the `nonull` flag is set, +then glob returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + +### Comments and Negation + +**Note**: In version 5 of this module, negation and comments are +**disabled** by default. You can explicitly set `nonegate:false` or +`nocomment:false` to re-enable them. They are going away entirely in +version 6. + +The intent for negation would be for a pattern starting with `!` to +match everything that *doesn't* match the supplied pattern. However, +the implementation is weird. It is better to use the `ignore` option +to set a pattern or set of patterns to exclude from matches. If you +want the "everything except *x*" type of behavior, you can use `**` as +the main pattern, and set an `ignore` for the things to exclude. + +The comments feature is added in minimatch, primarily to more easily +support use cases like ignore files, where a `#` at the start of a +line makes the pattern "empty". However, in the context of a +straightforward filesystem globber, "comments" don't make much sense. + +## Windows + +**Please only use forward-slashes in glob expressions.** + +Though windows uses either `/` or `\` as its path separator, only `/` +characters are used by this glob implementation. You must use +forward-slashes **only** in glob expressions. Back-slashes will always +be interpreted as escape characters, not path separators. + +Results from absolute patterns such as `/foo/*` are mounted onto the +root setting using `path.join`. On windows, this will by default result +in `/foo/*` matching `C:\foo\bar.txt`. + +## Race Conditions + +Glob searching, by its very nature, is susceptible to race conditions, +since it relies on directory walking and such. + +As a result, it is possible that a file that exists when glob looks for +it may have been deleted or modified by the time it returns the result. + +As part of its internal implementation, this program caches all stat +and readdir calls that it makes, in order to cut down on system +overhead. However, this also makes it even more susceptible to races, +especially if the cache or statCache objects are reused between glob +calls. + +Users are thus advised not to use a glob result as a guarantee of +filesystem state in the face of rapid changes. For the vast majority +of operations, this is never a problem. + +## Contributing + +Any change to behavior (including bugfixes) must come with a test. + +Patches that fail tests or reduce performance will be rejected. + +``` +# to run tests +npm test + +# to re-generate test fixtures +npm run test-regen + +# to benchmark against bash/zsh +npm run bench + +# to profile javascript +npm run prof +``` diff --git a/hm_sunwell/node_modules/glob/common.js b/hm_sunwell/node_modules/glob/common.js new file mode 100644 index 0000000..e36a631 --- /dev/null +++ b/hm_sunwell/node_modules/glob/common.js @@ -0,0 +1,245 @@ +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored + +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} + +var path = require("path") +var minimatch = require("minimatch") +var isAbsolute = require("path-is-absolute") +var Minimatch = minimatch.Minimatch + +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} + +function alphasort (a, b) { + return a.localeCompare(b) +} + +function setupIgnores (self, options) { + self.ignore = options.ignore || [] + + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] + + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } +} + +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern) + } + + return { + matcher: new Minimatch(pattern), + gmatcher: gmatcher + } +} + +function setopts (self, pattern, options) { + if (!options) + options = {} + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + + setupIgnores(self, options) + + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = options.cwd + self.changedCwd = path.resolve(options.cwd) !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + + self.nomount = !!options.nomount + + // disable comments and negation unless the user explicitly + // passes in false as the option. + options.nonegate = options.nonegate === false ? false : true + options.nocomment = options.nocomment === false ? false : true + deprecationWarning(options) + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} + +// TODO(isaacs): remove entirely in v6 +// exported to reset in tests +exports.deprecationWarned +function deprecationWarning(options) { + if (!options.nonegate || !options.nocomment) { + if (process.noDeprecation !== true && !exports.deprecationWarned) { + var msg = 'glob WARNING: comments and negation will be disabled in v6' + if (process.throwDeprecation) + throw new Error(msg) + else if (process.traceDeprecation) + console.trace(msg) + else + console.error(msg) + + exports.deprecationWarned = true + } + } +} + +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) + + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) + all = Object.keys(all) + + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) + + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + return !(/\/$/.test(e)) + }) + } + } + + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) + + self.found = all +} + +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } + + return m +} + +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + return abs +} + + +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} diff --git a/hm_sunwell/node_modules/glob/glob.js b/hm_sunwell/node_modules/glob/glob.js new file mode 100644 index 0000000..022d2ac --- /dev/null +++ b/hm_sunwell/node_modules/glob/glob.js @@ -0,0 +1,752 @@ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + +module.exports = glob + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var inherits = require('inherits') +var EE = require('events').EventEmitter +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var globSync = require('./sync.js') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = require('inflight') +var util = require('util') +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +var once = require('once') + +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) +} + +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +glob.hasMagic = function (pattern, options_) { + var options = util._extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } + + return false +} + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } + + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) + + setopts(this, pattern, options) + this._didRealPath = false + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } + + var self = this + var n = this.minimatch.set.length + this._processing = 0 + this.matches = new Array(n) + + this._emitQueue = [] + this._processQueue = [] + this.paused = false + + if (this.noprocess) + return this + + if (n === 0) + return done() + + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) + } + + function done () { + --self._processing + if (self._processing <= 0) + self._finish() + } +} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return + + if (this.realpath && !this._didRealpath) + return this._realpath() + + common.finish(this) + this.emit('end', this.found) +} + +Glob.prototype._realpath = function () { + if (this._didRealpath) + return + + this._didRealpath = true + + var n = this.matches.length + if (n === 0) + return this._finish() + + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) + + function next () { + if (--n === 0) + self._finish() + } +} + +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() + + var found = Object.keys(matchset) + var self = this + var n = found.length + + if (n === 0) + return cb() + + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + fs.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} + +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} + +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} + +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} + +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } + } + } +} + +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') + + if (this.aborted) + return + + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } + + //console.error('PROCESS %d', this._processing, pattern) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} + +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() +} + +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + + if (this.matches[index][e]) + return + + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + + var abs = this._makeAbs(e) + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + if (this.mark) + e = this._mark(e) + + this.matches[index][e] = true + + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) + + this.emit('match', e) +} + +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + fs.lstat(abs, lstatcb) + + function lstatcb_ (er, lstat) { + if (er) + return cb() + + var isSym = lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) + } + + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) +} + +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } +} + +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + return cb(null, entries) +} + +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return + + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } + + return cb() +} + +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + + +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + + var isSym = this.symlinks[abs] + var len = entries.length + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } + + cb() +} + +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { + + //console.error('ps2', prefix, exists) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} + +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return cb() + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } + + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) + + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} + +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er) { + this.statCache[abs] = false + return cb() + } + + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat + + if (abs.slice(-1) === '/' && !stat.isDirectory()) + return cb(null, false, stat) + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return cb() + + return cb(null, c, stat) +} diff --git a/hm_sunwell/node_modules/glob/package.json b/hm_sunwell/node_modules/glob/package.json new file mode 100644 index 0000000..f093355 --- /dev/null +++ b/hm_sunwell/node_modules/glob/package.json @@ -0,0 +1,98 @@ +{ + "_args": [ + [ + "glob@^5.0.15", + "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul" + ] + ], + "_from": "glob@>=5.0.15 <6.0.0", + "_id": "glob@5.0.15", + "_inCache": true, + "_installable": true, + "_location": "/glob", + "_nodeVersion": "4.0.0", + "_npmUser": { + "email": "isaacs@npmjs.com", + "name": "isaacs" + }, + "_npmVersion": "3.3.2", + "_phantomChildren": {}, + "_requested": { + "name": "glob", + "raw": "glob@^5.0.15", + "rawSpec": "^5.0.15", + "scope": null, + "spec": ">=5.0.15 <6.0.0", + "type": "range" + }, + "_requiredBy": [ + "/istanbul" + ], + "_resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "_shasum": "1bc936b9e02f4a603fcc222ecf7633d30b8b93b1", + "_shrinkwrap": null, + "_spec": "glob@^5.0.15", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul", + "author": { + "email": "i@izs.me", + "name": "Isaac Z. Schlueter", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/isaacs/node-glob/issues" + }, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "description": "a little globber", + "devDependencies": { + "mkdirp": "0", + "rimraf": "^2.2.8", + "tap": "^1.1.4", + "tick": "0.0.6" + }, + "directories": {}, + "dist": { + "shasum": "1bc936b9e02f4a603fcc222ecf7633d30b8b93b1", + "tarball": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" + }, + "engines": { + "node": "*" + }, + "files": [ + "common.js", + "glob.js", + "sync.js" + ], + "gitHead": "3a7e71d453dd80e75b196fd262dd23ed54beeceb", + "homepage": "https://github.com/isaacs/node-glob#readme", + "license": "ISC", + "main": "glob.js", + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "name": "glob", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-glob.git" + }, + "scripts": { + "bench": "bash benchmark.sh", + "benchclean": "node benchclean.js", + "prepublish": "npm run benchclean", + "prof": "bash prof.sh && cat profile.txt", + "profclean": "rm -f v8.log profile.txt", + "test": "tap test/*.js --cov", + "test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js" + }, + "version": "5.0.15" +} diff --git a/hm_sunwell/node_modules/glob/sync.js b/hm_sunwell/node_modules/glob/sync.js new file mode 100644 index 0000000..09883d2 --- /dev/null +++ b/hm_sunwell/node_modules/glob/sync.js @@ -0,0 +1,460 @@ +module.exports = globSync +globSync.GlobSync = GlobSync + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var Glob = require('./glob.js').Glob +var util = require('util') +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored + +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + return new GlobSync(pattern, options).found +} + +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') + + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) + + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = fs.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) +} + + +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip processing + if (childrenIgnored(this, read)) + return + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} + + +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this.matches[index][e] = true + } + // This was the last one, and no stats were needed + return + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) + } +} + + +GlobSync.prototype._emitMatch = function (index, e) { + var abs = this._makeAbs(e) + if (this.mark) + e = this._mark(e) + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[this._makeAbs(e)] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + if (this.stat) + this._stat(e) +} + + +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) + + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + // lstat failed, doesn't exist + return null + } + + var isSym = lstat.isSymbolicLink() + this.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + + return entries +} + +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries + + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null + + if (Array.isArray(c)) + return c + } + + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } +} + +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + + // mark and cache dir-ness + return entries +} + +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break + } +} + +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { + + var entries = this._readdir(abs, inGlobStar) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) + + var len = entries.length + var isSym = this.symlinks[abs] + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} + +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this.matches[index][prefix] = true +} + +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return false + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + + if (needDir && c === 'FILE') + return false + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + return false + } + + if (lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } + + this.statCache[abs] = stat + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return false + + return c +} + +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} + +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} diff --git a/hm_sunwell/node_modules/graceful-readlink/.npmignore b/hm_sunwell/node_modules/graceful-readlink/.npmignore new file mode 100644 index 0000000..3ac7d16 --- /dev/null +++ b/hm_sunwell/node_modules/graceful-readlink/.npmignore @@ -0,0 +1,3 @@ +.idea/ +.DS_Store +node_modules/ diff --git a/hm_sunwell/node_modules/graceful-readlink/.travis.yml b/hm_sunwell/node_modules/graceful-readlink/.travis.yml new file mode 100644 index 0000000..baf9be7 --- /dev/null +++ b/hm_sunwell/node_modules/graceful-readlink/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" + - "0.12" + - "io.js" diff --git a/hm_sunwell/node_modules/graceful-readlink/LICENSE b/hm_sunwell/node_modules/graceful-readlink/LICENSE new file mode 100644 index 0000000..d1f842f --- /dev/null +++ b/hm_sunwell/node_modules/graceful-readlink/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Zhiye Li + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/hm_sunwell/node_modules/graceful-readlink/README.md b/hm_sunwell/node_modules/graceful-readlink/README.md new file mode 100644 index 0000000..fc63b50 --- /dev/null +++ b/hm_sunwell/node_modules/graceful-readlink/README.md @@ -0,0 +1,17 @@ +# graceful-readlink +[![NPM Version](http://img.shields.io/npm/v/graceful-readlink.svg?style=flat)](https://www.npmjs.org/package/graceful-readlink) +[![NPM Downloads](https://img.shields.io/npm/dm/graceful-readlink.svg?style=flat)](https://www.npmjs.org/package/graceful-readlink) + + +## Usage + +```js +var readlinkSync = require('graceful-readlink').readlinkSync; +console.log(readlinkSync(f)); +// output +// the file pointed to when `f` is a symbolic link +// the `f` itself when `f` is not a symbolic link +``` +## Licence + +MIT License diff --git a/hm_sunwell/node_modules/graceful-readlink/index.js b/hm_sunwell/node_modules/graceful-readlink/index.js new file mode 100644 index 0000000..7e9fc70 --- /dev/null +++ b/hm_sunwell/node_modules/graceful-readlink/index.js @@ -0,0 +1,12 @@ +var fs = require('fs') + , lstat = fs.lstatSync; + +exports.readlinkSync = function (p) { + if (lstat(p).isSymbolicLink()) { + return fs.readlinkSync(p); + } else { + return p; + } +}; + + diff --git a/hm_sunwell/node_modules/graceful-readlink/package.json b/hm_sunwell/node_modules/graceful-readlink/package.json new file mode 100644 index 0000000..b021e14 --- /dev/null +++ b/hm_sunwell/node_modules/graceful-readlink/package.json @@ -0,0 +1,75 @@ +{ + "_args": [ + [ + "graceful-readlink@>= 1.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/commander" + ] + ], + "_from": "graceful-readlink@>=1.0.0", + "_id": "graceful-readlink@1.0.1", + "_inCache": true, + "_installable": true, + "_location": "/graceful-readlink", + "_nodeVersion": "0.11.14", + "_npmUser": { + "email": "zhiyelee@gmail.com", + "name": "zhiyelee" + }, + "_npmVersion": "2.1.17", + "_phantomChildren": {}, + "_requested": { + "name": "graceful-readlink", + "raw": "graceful-readlink@>= 1.0.0", + "rawSpec": ">= 1.0.0", + "scope": null, + "spec": ">=1.0.0", + "type": "range" + }, + "_requiredBy": [ + "/commander" + ], + "_resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "_shasum": "4cafad76bc62f02fa039b2f94e9a3dd3a391a725", + "_shrinkwrap": null, + "_spec": "graceful-readlink@>= 1.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/commander", + "author": { + "name": "zhiyelee" + }, + "bugs": { + "url": "https://github.com/zhiyelee/graceful-readlink/issues" + }, + "dependencies": {}, + "description": "graceful fs.readlink", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "4cafad76bc62f02fa039b2f94e9a3dd3a391a725", + "tarball": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + }, + "gitHead": "f6655275bebef706fb63fd01b5f062a7052419a5", + "homepage": "https://github.com/zhiyelee/graceful-readlink", + "keywords": [ + "fs.readlink", + "readlink" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "zhiyelee", + "email": "zhiyelee@gmail.com" + } + ], + "name": "graceful-readlink", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/zhiyelee/graceful-readlink.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.0.1" +} diff --git a/hm_sunwell/node_modules/growl/History.md b/hm_sunwell/node_modules/growl/History.md new file mode 100644 index 0000000..a4b7b49 --- /dev/null +++ b/hm_sunwell/node_modules/growl/History.md @@ -0,0 +1,63 @@ + +1.7.0 / 2012-12-30 +================== + + * support transient notifications in Gnome + +1.6.1 / 2012-09-25 +================== + + * restore compatibility with node < 0.8 [fgnass] + +1.6.0 / 2012-09-06 +================== + + * add notification center support [drudge] + +1.5.1 / 2012-04-08 +================== + + * Merge pull request #16 from KyleAMathews/patch-1 + * Fixes #15 + +1.5.0 / 2012-02-08 +================== + + * Added windows support [perfusorius] + +1.4.1 / 2011-12-28 +================== + + * Fixed: dont exit(). Closes #9 + +1.4.0 / 2011-12-17 +================== + + * Changed API: `growl.notify()` -> `growl()` + +1.3.0 / 2011-12-17 +================== + + * Added support for Ubuntu/Debian/Linux users [niftylettuce] + * Fixed: send notifications even if title not specified [alessioalex] + +1.2.0 / 2011-10-06 +================== + + * Add support for priority. + +1.1.0 / 2011-03-15 +================== + + * Added optional callbacks + * Added parsing of version + +1.0.1 / 2010-03-26 +================== + + * Fixed; sys.exec -> child_process.exec to support latest node + +1.0.0 / 2010-03-19 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/growl/Readme.md b/hm_sunwell/node_modules/growl/Readme.md new file mode 100644 index 0000000..785344e --- /dev/null +++ b/hm_sunwell/node_modules/growl/Readme.md @@ -0,0 +1,108 @@ +# Growl for nodejs + +Growl support for Nodejs. This is essentially a port of my [Ruby Growl Library](http://github.com/visionmedia/growl). Ubuntu/Linux support added thanks to [@niftylettuce](http://github.com/niftylettuce). + +## Installation + +### Install + +### Mac OS X (Darwin): + + Install [growlnotify(1)](http://growl.info/extras.php#growlnotify). On OS X 10.8, Notification Center is supported using [terminal-notifier](https://github.com/alloy/terminal-notifier). To install: + + $ sudo gem install terminal-notifier + + Install [npm](http://npmjs.org/) and run: + + $ npm install growl + +### Ubuntu (Linux): + + Install `notify-send` through the [libnotify-bin](http://packages.ubuntu.com/libnotify-bin) package: + + $ sudo apt-get install libnotify-bin + + Install [npm](http://npmjs.org/) and run: + + $ npm install growl + +### Windows: + + Download and install [Growl for Windows](http://www.growlforwindows.com/gfw/default.aspx) + + Download [growlnotify](http://www.growlforwindows.com/gfw/help/growlnotify.aspx) - **IMPORTANT :** Unpack growlnotify to a folder that is present in your path! + + Install [npm](http://npmjs.org/) and run: + + $ npm install growl + +## Examples + +Callback functions are optional + +```javascript +var growl = require('growl') +growl('You have mail!') +growl('5 new messages', { sticky: true }) +growl('5 new emails', { title: 'Email Client', image: 'Safari', sticky: true }) +growl('Message with title', { title: 'Title'}) +growl('Set priority', { priority: 2 }) +growl('Show Safari icon', { image: 'Safari' }) +growl('Show icon', { image: 'path/to/icon.icns' }) +growl('Show image', { image: 'path/to/my.image.png' }) +growl('Show png filesystem icon', { image: 'png' }) +growl('Show pdf filesystem icon', { image: 'article.pdf' }) +growl('Show pdf filesystem icon', { image: 'article.pdf' }, function(err){ + // ... notified +}) +``` + +## Options + + - title + - notification title + - name + - application name + - priority + - priority for the notification (default is 0) + - sticky + - weither or not the notification should remainin until closed + - image + - Auto-detects the context: + - path to an icon sets --iconpath + - path to an image sets --image + - capitalized word sets --appIcon + - filename uses extname as --icon + - otherwise treated as --icon + - exec + - manually specify a shell command instead + - appends message to end of shell command + - or, replaces `%s` with message + - optionally prepends title (example: `title: message`) + - examples: `{exec: 'tmux display-message'}`, `{exec: 'echo "%s" > messages.log}` + +## License + +(The MIT License) + +Copyright (c) 2009 TJ Holowaychuk +Copyright (c) 2016 Joshua Boy Nicolai Appelman + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/growl/lib/growl.js b/hm_sunwell/node_modules/growl/lib/growl.js new file mode 100644 index 0000000..719b5af --- /dev/null +++ b/hm_sunwell/node_modules/growl/lib/growl.js @@ -0,0 +1,290 @@ +// Growl - Copyright TJ Holowaychuk (MIT Licensed) + +/** + * Module dependencies. + */ + +var exec = require('child_process').exec + , fs = require('fs') + , path = require('path') + , exists = fs.existsSync || path.existsSync + , os = require('os') + , quote = JSON.stringify + , cmd; + +function which(name) { + var paths = process.env.PATH.split(':'); + var loc; + + for (var i = 0, len = paths.length; i < len; ++i) { + loc = path.join(paths[i], name); + if (exists(loc)) return loc; + } +} + +switch(os.type()) { + case 'Darwin': + if (which('terminal-notifier')) { + cmd = { + type: "Darwin-NotificationCenter" + , pkg: "terminal-notifier" + , msg: '-message' + , title: '-title' + , subtitle: '-subtitle' + , icon: '-appIcon' + , sound: '-sound' + , url: '-open' + , priority: { + cmd: '-execute' + , range: [] + } + }; + } else { + cmd = { + type: "Darwin-Growl" + , pkg: "growlnotify" + , msg: '-m' + , sticky: '--sticky' + , priority: { + cmd: '--priority' + , range: [ + -2 + , -1 + , 0 + , 1 + , 2 + , "Very Low" + , "Moderate" + , "Normal" + , "High" + , "Emergency" + ] + } + }; + } + break; + case 'Linux': + if (which('growl')) { + cmd = { + type: "Linux-Growl" + , pkg: "growl" + , msg: '-m' + , title: '-title' + , subtitle: '-subtitle' + , host: { + cmd: '-H' + , hostname: '192.168.33.1' + } + }; + } else { + cmd = { + type: "Linux" + , pkg: "notify-send" + , msg: '' + , sticky: '-t 0' + , icon: '-i' + , priority: { + cmd: '-u' + , range: [ + "low" + , "normal" + , "critical" + ] + } + }; + } + break; + case 'Windows_NT': + cmd = { + type: "Windows" + , pkg: "growlnotify" + , msg: '' + , sticky: '/s:true' + , title: '/t:' + , icon: '/i:' + , url: '/cu:' + , priority: { + cmd: '/p:' + , range: [ + -2 + , -1 + , 0 + , 1 + , 2 + ] + } + }; + break; +} + +/** + * Expose `growl`. + */ + +exports = module.exports = growl; + +/** + * Node-growl version. + */ + +exports.version = '1.4.1' + +/** + * Send growl notification _msg_ with _options_. + * + * Options: + * + * - title Notification title + * - sticky Make the notification stick (defaults to false) + * - priority Specify an int or named key (default is 0) + * - name Application name (defaults to growlnotify) + * - sound Sound efect ( in OSx defined in preferences -> sound -> effects) * works only in OSX > 10.8x + * - image + * - path to an icon sets --iconpath + * - path to an image sets --image + * - capitalized word sets --appIcon + * - filename uses extname as --icon + * - otherwise treated as --icon + * + * Examples: + * + * growl('New email') + * growl('5 new emails', { title: 'Thunderbird' }) + * growl('5 new emails', { title: 'Thunderbird', sound: 'Purr' }) + * growl('Email sent', function(){ + * // ... notification sent + * }) + * + * @param {string} msg + * @param {object} options + * @param {function} fn + * @api public + */ + +function growl(msg, options, fn) { + var image + , args + , options = options || {} + , fn = fn || function(){}; + + if (options.exec) { + cmd = { + type: "Custom" + , pkg: options.exec + , range: [] + }; + } + + // noop + if (!cmd) return fn(new Error('growl not supported on this platform')); + args = [cmd.pkg]; + + // image + if (image = options.image) { + switch(cmd.type) { + case 'Darwin-Growl': + var flag, ext = path.extname(image).substr(1) + flag = flag || ext == 'icns' && 'iconpath' + flag = flag || /^[A-Z]/.test(image) && 'appIcon' + flag = flag || /^png|gif|jpe?g$/.test(ext) && 'image' + flag = flag || ext && (image = ext) && 'icon' + flag = flag || 'icon' + args.push('--' + flag, quote(image)) + break; + case 'Darwin-NotificationCenter': + args.push(cmd.icon, quote(image)); + break; + case 'Linux': + args.push(cmd.icon, quote(image)); + // libnotify defaults to sticky, set a hint for transient notifications + if (!options.sticky) args.push('--hint=int:transient:1'); + break; + case 'Windows': + args.push(cmd.icon + quote(image)); + break; + } + } + + // sticky + if (options.sticky) args.push(cmd.sticky); + + // priority + if (options.priority) { + var priority = options.priority + ''; + var checkindexOf = cmd.priority.range.indexOf(priority); + if (~cmd.priority.range.indexOf(priority)) { + args.push(cmd.priority, options.priority); + } + } + + //sound + if(options.sound && cmd.type === 'Darwin-NotificationCenter'){ + args.push(cmd.sound, options.sound) + } + + // name + if (options.name && cmd.type === "Darwin-Growl") { + args.push('--name', options.name); + } + + switch(cmd.type) { + case 'Darwin-Growl': + args.push(cmd.msg); + args.push(quote(msg).replace(/\\n/g, '\n')); + if (options.title) args.push(quote(options.title)); + break; + case 'Darwin-NotificationCenter': + args.push(cmd.msg); + var stringifiedMsg = quote(msg); + var escapedMsg = stringifiedMsg.replace(/\\n/g, '\n'); + args.push(escapedMsg); + if (options.title) { + args.push(cmd.title); + args.push(quote(options.title)); + } + if (options.subtitle) { + args.push(cmd.subtitle); + args.push(quote(options.subtitle)); + } + if (options.url) { + args.push(cmd.url); + args.push(quote(options.url)); + } + break; + case 'Linux-Growl': + args.push(cmd.msg); + args.push(quote(msg).replace(/\\n/g, '\n')); + if (options.title) args.push(quote(options.title)); + if (cmd.host) { + args.push(cmd.host.cmd, cmd.host.hostname) + } + break; + case 'Linux': + if (options.title) { + args.push(quote(options.title)); + args.push(cmd.msg); + args.push(quote(msg).replace(/\\n/g, '\n')); + } else { + args.push(quote(msg).replace(/\\n/g, '\n')); + } + break; + case 'Windows': + args.push(quote(msg).replace(/\\n/g, '\n')); + if (options.title) args.push(cmd.title + quote(options.title)); + if (options.url) args.push(cmd.url + quote(options.url)); + break; + case 'Custom': + args[0] = (function(origCommand) { + var message = options.title + ? options.title + ': ' + msg + : msg; + var command = origCommand.replace(/(^|[^%])%s/g, '$1' + quote(message)); + if (command === origCommand) args.push(quote(message)); + return command; + })(args[0]); + break; + } + + // execute + exec(args.join(' '), fn); +}; diff --git a/hm_sunwell/node_modules/growl/package.json b/hm_sunwell/node_modules/growl/package.json new file mode 100644 index 0000000..acbd3b0 --- /dev/null +++ b/hm_sunwell/node_modules/growl/package.json @@ -0,0 +1,78 @@ +{ + "_args": [ + [ + "growl@1.9.2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha" + ] + ], + "_from": "growl@1.9.2", + "_id": "growl@1.9.2", + "_inCache": true, + "_installable": true, + "_location": "/growl", + "_nodeVersion": "0.12.7", + "_npmOperationalInternal": { + "host": "packages-6-west.internal.npmjs.com", + "tmp": "tmp/growl-1.9.2.tgz_1456056369289_0.9604133665561676" + }, + "_npmUser": { + "email": "jappelman@xebia.com", + "name": "jbnicolai" + }, + "_npmVersion": "2.11.3", + "_phantomChildren": {}, + "_requested": { + "name": "growl", + "raw": "growl@1.9.2", + "rawSpec": "1.9.2", + "scope": null, + "spec": "1.9.2", + "type": "version" + }, + "_requiredBy": [ + "/mocha" + ], + "_resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "_shasum": "0ea7743715db8d8de2c5ede1775e1b45ac85c02f", + "_shrinkwrap": null, + "_spec": "growl@1.9.2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk" + }, + "bugs": { + "url": "https://github.com/tj/node-growl/issues" + }, + "dependencies": {}, + "description": "Growl unobtrusive notifications", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "0ea7743715db8d8de2c5ede1775e1b45ac85c02f", + "tarball": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz" + }, + "gitHead": "dc8aae046df328edd32dd69f3cd2d6b114d7018e", + "homepage": "https://github.com/tj/node-growl", + "license": "MIT", + "main": "./lib/growl.js", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + } + ], + "name": "growl", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/tj/node-growl.git" + }, + "scripts": {}, + "version": "1.9.2" +} diff --git a/hm_sunwell/node_modules/growl/test.js b/hm_sunwell/node_modules/growl/test.js new file mode 100644 index 0000000..9bb09d9 --- /dev/null +++ b/hm_sunwell/node_modules/growl/test.js @@ -0,0 +1,31 @@ + +var growl = require('./lib/growl') + +growl('Support sound notifications', {title: 'Make a sound', sound: 'purr'}); +growl('You have mail!') +growl('5 new messages', { sticky: true }) +growl('5 new emails', { title: 'Email Client', image: 'Safari', sticky: true }) +growl('Message with title', { title: 'Title'}) +growl('Set priority', { priority: 2 }) +growl('Show Safari icon', { image: 'Safari' }) +growl('Show icon', { image: 'path/to/icon.icns' }) +growl('Show image', { image: 'path/to/my.image.png' }) +growl('Show png filesystem icon', { image: 'png' }) +growl('Show pdf filesystem icon', { image: 'article.pdf' }) +growl('Show pdf filesystem icon', { image: 'article.pdf' }, function(){ + console.log('callback'); +}) +growl('Show pdf filesystem icon', { title: 'Use show()', image: 'article.pdf' }) +growl('here \' are \n some \\ characters that " need escaping', {}, function(error, stdout, stderr) { + if (error !== null) throw new Error('escaping failed:\n' + stdout + stderr); +}) +growl('Allow custom notifiers', { exec: 'echo XXX %s' }, function(error, stdout, stderr) { + console.log(stdout); +}) +growl('Allow custom notifiers', { title: 'test', exec: 'echo YYY' }, function(error, stdout, stderr) { + console.log(stdout); +}) +growl('Allow custom notifiers', { title: 'test', exec: 'echo ZZZ %s' }, function(error, stdout, stderr) { + console.log(stdout); +}) +growl('Open a URL', { url: 'https://npmjs.org/package/growl' }); diff --git a/hm_sunwell/node_modules/handlebars/.gitmodules b/hm_sunwell/node_modules/handlebars/.gitmodules new file mode 100644 index 0000000..1739275 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/.gitmodules @@ -0,0 +1,3 @@ +[submodule "spec/mustache"] + path = spec/mustache + url = git://github.com/mustache/spec.git diff --git a/hm_sunwell/node_modules/handlebars/.istanbul.yml b/hm_sunwell/node_modules/handlebars/.istanbul.yml new file mode 100644 index 0000000..e6911f1 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/.istanbul.yml @@ -0,0 +1,2 @@ +instrumentation: + excludes: ['**/spec/**'] diff --git a/hm_sunwell/node_modules/handlebars/.npmignore b/hm_sunwell/node_modules/handlebars/.npmignore new file mode 100644 index 0000000..f10592c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/.npmignore @@ -0,0 +1,25 @@ +.DS_Store +.gitignore +.rvmrc +.eslintrc +.travis.yml +.rspec +Gemfile +Gemfile.lock +Rakefile +Gruntfile.js +*.gemspec +*.nuspec +*.log +bench/* +configurations/* +components/* +coverage/* +dist/cdnjs/* +dist/components/* +spec/* +src/* +tasks/* +tmp/* +publish/* +vendor/* diff --git a/hm_sunwell/node_modules/handlebars/CONTRIBUTING.md b/hm_sunwell/node_modules/handlebars/CONTRIBUTING.md new file mode 100644 index 0000000..1ea2466 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/CONTRIBUTING.md @@ -0,0 +1,99 @@ +# How to Contribute + +## Reporting Issues + +Please see our [FAQ](https://github.com/wycats/handlebars.js/blob/master/FAQ.md) for common issues that people run into. + +Should you run into other issues with the project, please don't hesitate to let us know by filing an [issue][issue]! In general we are going to ask for an example of the problem failing, which can be as simple as a jsfiddle/jsbin/etc. We've put together a jsfiddle [template][jsfiddle] to ease this. (We will keep this link up to date as new releases occur, so feel free to check back here) + +Pull requests containing only failing tests demonstrating the issue are welcomed and this also helps ensure that your issue won't regress in the future once it's fixed. + +Documentation issues on the handlebarsjs.com site should be reported on [handlebars-site](https://github.com/wycats/handlebars-site). + +## Pull Requests + +We also accept [pull requests][pull-request]! + +Generally we like to see pull requests that +- Maintain the existing code style +- Are focused on a single change (i.e. avoid large refactoring or style adjustments in untouched code if not the primary goal of the pull request) +- Have [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) +- Have tests +- Don't significantly decrease the current code coverage (see coverage/lcov-report/index.html) + +## Building + +To build Handlebars.js you'll need a few things installed. + +* Node.js +* [Grunt](http://gruntjs.com/getting-started) + +Before building, you need to make sure that the Git submodule `spec/mustache` is included (i.e. the directory `spec/mustache` should not be empty). To include it, if using Git version 1.6.5 or newer, use `git clone --recursive` rather than `git clone`. Or, if you already cloned without `--recursive`, use `git submodule update --init`. + +Project dependencies may be installed via `npm install`. + +To build Handlebars.js from scratch, you'll want to run `grunt` +in the root of the project. That will build Handlebars and output the +results to the dist/ folder. To re-run tests, run `grunt test` or `npm test`. +You can also run our set of benchmarks with `grunt bench`. + +The `grunt dev` implements watching for tests and allows for in browser testing at `http://localhost:9999/spec/`. + +If you notice any problems, please report them to the GitHub issue tracker at +[http://github.com/wycats/handlebars.js/issues](http://github.com/wycats/handlebars.js/issues). + +##Running Tests + +To run tests locally, first install all dependencies. +```sh +npm install +``` + +Clone the mustache specs into the spec/mustache folder. +```sh +cd spec +rm -r mustache +git clone https://github.com/mustache/spec.git mustache +``` + +From the root directory, run the tests. +```sh +npm test +``` + +## Ember testing + +The current ember distribution should be tested as part of the handlebars release process. This requires building the `handlebars-source` gem locally and then executing the ember test script. + +```sh +npm link +grunt build release +cp dist/*.js $emberRepoDir/bower_components/handlebars/ + +cd $emberRepoDir +npm link handlebars +npm test +``` + +## Releasing + +Handlebars utilizes the [release yeoman generator][generator-release] to perform most release tasks. + +A full release may be completed with the following: + +``` +yo release +npm publish +yo release:publish components handlebars.js dist/components/ + +cd dist/components/ +gem build handlebars-source.gemspec +gem push handlebars-source-*.gem +``` + +After this point the handlebars site needs to be updated to point to the new version numbers. The jsfiddle link should be updated to point to the most recent distribution for all instances in our documentation. + +[generator-release]: https://github.com/walmartlabs/generator-release +[pull-request]: https://github.com/wycats/handlebars.js/pull/new/master +[issue]: https://github.com/wycats/handlebars.js/issues/new +[jsfiddle]: https://jsfiddle.net/9D88g/47/ diff --git a/hm_sunwell/node_modules/handlebars/FAQ.md b/hm_sunwell/node_modules/handlebars/FAQ.md new file mode 100644 index 0000000..108e839 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/FAQ.md @@ -0,0 +1,60 @@ +# Frequently Asked Questions + +1. How can I file a bug report: + + See our guidelines on [reporting issues](https://github.com/wycats/handlebars.js/blob/master/CONTRIBUTING.md#reporting-issues). + +1. Why isn't my Mustache template working? + + Handlebars deviates from Mustache slightly on a few behaviors. These variations are documented in our [readme](https://github.com/wycats/handlebars.js#differences-between-handlebarsjs-and-mustache). + +1. Why is it slower when compiling? + + The Handlebars compiler must parse the template and construct a JavaScript program which can then be run. Under some environments such as older mobile devices this can have a performance impact which can be avoided by precompiling. Generally it's recommended that precompilation and the runtime library be used on all clients. + +1. Why doesn't this work with Content Security Policy restrictions? + + When not using the precompiler, Handlebars generates a dynamic function for each template which can cause issues with pages that have enabled Content Policy. It's recommended that templates are precompiled or the `unsafe-eval` policy is enabled for sites that must generate dynamic templates at runtime. + +1. How can I include script tags in my template? + + If loading the template via an inlined ` + ``` + + It's generally recommended that templates are served through external, precompiled, files, which do not suffer from this issue. + +1. Why are my precompiled scripts throwing exceptions? + + When using the precompiler, it's important that a supporting version of the Handlebars runtime be loaded on the target page. In version 1.x there were rudimentary checks to compare the version but these did not always work. This is fixed under 2.x but the version checking does not work between these two versions. If you see unexpected errors such as `undefined is not a function` or similar, please verify that the same version is being used for both the precompiler and the client. This can be checked via: + + ```sh + handlebars --version + ``` + If using the integrated precompiler and + + ```javascript + console.log(Handlebars.VERSION); + ``` + On the client side. + + We include the built client libraries in the npm package for those who want to be certain that they are using the same client libraries as the compiler. + + Should these match, please file an issue with us, per our [issue filing guidelines](https://github.com/wycats/handlebars.js/blob/master/CONTRIBUTING.md#reporting-issues). + +1. Why doesn't IE like the `default` name in the AMD module? + + Some browsers such as particular versions of IE treat `default` as a reserved word in JavaScript source files. To safely use this you need to reference this via the `Handlebars['default']` lookup method. This is an unfortunate side effect of the shims necessary to backport the Handlebars ES6 code to all current browsers. + +1. How do I load the runtime library when using AMD? + + There are two options for loading under AMD environments. The first is to use the `handlebars.runtime.amd.js` file. This may require a [path mapping](https://github.com/wycats/handlebars.js/blob/master/spec/amd-runtime.html#L31) as well as access via the `default` field. + + The other option is to load the `handlebars.runtime.js` UMD build, which might not require path configuration and exposes the library as both the module root and the `default` field for compatibility. + + If not using ES6 transpilers or accessing submodules in the build the former option should be sufficient for most use cases. diff --git a/hm_sunwell/node_modules/handlebars/LICENSE b/hm_sunwell/node_modules/handlebars/LICENSE new file mode 100644 index 0000000..307ebc1 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/handlebars/README.markdown b/hm_sunwell/node_modules/handlebars/README.markdown new file mode 100644 index 0000000..89e3fc5 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/README.markdown @@ -0,0 +1,167 @@ +[![Travis Build Status](https://img.shields.io/travis/wycats/handlebars.js/master.svg)](https://travis-ci.org/wycats/handlebars.js) +[![Selenium Test Status](https://saucelabs.com/buildstatus/handlebars)](https://saucelabs.com/u/handlebars) + +Handlebars.js +============= + +Handlebars.js is an extension to the [Mustache templating +language](http://mustache.github.com/) created by Chris Wanstrath. +Handlebars.js and Mustache are both logicless templating languages that +keep the view and the code separated like we all know they should be. + +Checkout the official Handlebars docs site at +[http://www.handlebarsjs.com](http://www.handlebarsjs.com) and the live demo at [http://tryhandlebarsjs.com/](http://tryhandlebarsjs.com/). + +Installing +---------- + +See our [installation documentation](http://handlebarsjs.com/installation.html). + +Usage +----- +In general, the syntax of Handlebars.js templates is a superset +of Mustache templates. For basic syntax, check out the [Mustache +manpage](http://mustache.github.com/mustache.5.html). + +Once you have a template, use the `Handlebars.compile` method to compile +the template into a function. The generated function takes a context +argument, which will be used to render the template. + +```js +var source = "

Hello, my name is {{name}}. I am from {{hometown}}. I have " + + "{{kids.length}} kids:

" + + "
    {{#kids}}
  • {{name}} is {{age}}
  • {{/kids}}
"; +var template = Handlebars.compile(source); + +var data = { "name": "Alan", "hometown": "Somewhere, TX", + "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]}; +var result = template(data); + +// Would render: +//

Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:

+//
    +//
  • Jimmy is 12
  • +//
  • Sally is 4
  • +//
+``` + +Full documentation and more examples are at [handlebarsjs.com](http://handlebarsjs.com/). + +Precompiling Templates +---------------------- + +Handlebars allows templates to be precompiled and included as javascript code rather than the handlebars template allowing for faster startup time. Full details are located [here](http://handlebarsjs.com/precompilation.html). + +Differences Between Handlebars.js and Mustache +---------------------------------------------- +Handlebars.js adds a couple of additional features to make writing +templates easier and also changes a tiny detail of how partials work. + +- [Nested Paths](http://handlebarsjs.com/#paths) +- [Helpers](http://handlebarsjs.com/#helpers) +- [Block Expressions](http://handlebarsjs.com/#block-expressions) +- [Literal Values](http://handlebarsjs.com/#literals) +- [Delimited Comments](http://handlebarsjs.com/#comments) + +Block expressions have the same syntax as mustache sections but should not be confused with one another. Sections are akin to an implicit `each` or `with` statement depending on the input data and helpers are explicit pieces of code that are free to implement whatever behavior they like. The [mustache spec](http://mustache.github.io/mustache.5.html) defines the exact behavior of sections. In the case of name conflicts, helpers are given priority. + +### Compatibility + +There are a few Mustache behaviors that Handlebars does not implement. +- Handlebars deviates from Mustache slightly in that it does not perform recursive lookup by default. The compile time `compat` flag must be set to enable this functionality. Users should note that there is a performance cost for enabling this flag. The exact cost varies by template, but it's recommended that performance sensitive operations should avoid this mode and instead opt for explicit path references. +- The optional Mustache-style lambdas are not supported. Instead Handlebars provides its own lambda resolution that follows the behaviors of helpers. +- Alternative delimiters are not supported. + + +Supported Environments +---------------------- + +Handlebars has been designed to work in any ECMAScript 3 environment. This includes + +- Node.js +- Chrome +- Firefox +- Safari 5+ +- Opera 11+ +- IE 6+ + +Older versions and other runtimes are likely to work but have not been formally +tested. The compiler requires `JSON.stringify` to be implemented natively or via a polyfill. If using the precompiler this is not necessary. + +[![Selenium Test Status](https://saucelabs.com/browser-matrix/handlebars.svg)](https://saucelabs.com/u/handlebars) + +Performance +----------- + +In a rough performance test, precompiled Handlebars.js templates (in +the original version of Handlebars.js) rendered in about half the +time of Mustache templates. It would be a shame if it were any other +way, since they were precompiled, but the difference in architecture +does have some big performance advantages. Justin Marney, a.k.a. +[gotascii](http://github.com/gotascii), confirmed that with an +[independent test](http://sorescode.com/2010/09/12/benchmarks.html). The +rewritten Handlebars (current version) is faster than the old version, +with many [performance tests](https://travis-ci.org/wycats/handlebars.js/builds/33392182#L538) being 5 to 7 times faster than the Mustache equivalent. + + +Upgrading +--------- + +See [release-notes.md](https://github.com/wycats/handlebars.js/blob/master/release-notes.md) for upgrade notes. + +Known Issues +------------ + +See [FAQ.md](https://github.com/wycats/handlebars.js/blob/master/FAQ.md) for known issues and common pitfalls. + + +Handlebars in the Wild +---------------------- + +* [Assemble](http://assemble.io), by [@jonschlinkert](https://github.com/jonschlinkert) + and [@doowb](https://github.com/doowb), is a static site generator that uses Handlebars.js + as its template engine. +* [Cory](https://github.com/leo/cory), by [@leo](https://github.com/leo), is another tiny static site generator +* [CoSchedule](http://coschedule.com) An editorial calendar for WordPress that uses Handlebars.js +* [dashbars](https://github.com/pismute/dashbars) A modern helper library for Handlebars.js. +* [Ember.js](http://www.emberjs.com) makes Handlebars.js the primary way to + structure your views, also with automatic data binding support. +* [Ghost](https://ghost.org/) Just a blogging platform. +* [handlebars_assets](http://github.com/leshill/handlebars_assets): A Rails Asset Pipeline gem + from Les Hill (@leshill). +* [handlebars-helpers](https://github.com/assemble/handlebars-helpers) is an extensive library + with 100+ handlebars helpers. +* [handlebars-layouts](https://github.com/shannonmoeller/handlebars-layouts) is a set of helpers which implement extendible and embeddable layout blocks as seen in other popular templating languages. +* [hbs](http://github.com/donpark/hbs): An Express.js view engine adapter for Handlebars.js, + from Don Park. +* [koa-hbs](https://github.com/jwilm/koa-hbs): [koa](https://github.com/koajs/koa) generator based + renderer for Handlebars.js. +* [jblotus](http://github.com/jblotus) created [http://tryhandlebarsjs.com](http://tryhandlebarsjs.com) + for anyone who would like to try out Handlebars.js in their browser. +* [jQuery plugin](http://71104.github.io/jquery-handlebars/): allows you to use + Handlebars.js with [jQuery](http://jquery.com/). +* [Lumbar](http://walmartlabs.github.io/lumbar) provides easy module-based template management for + handlebars projects. +* [Marionette.Handlebars](https://github.com/hashchange/marionette.handlebars) adds support for Handlebars and Mustache templates to Marionette. +* [sammy.js](http://github.com/quirkey/sammy) by Aaron Quint, a.k.a. quirkey, + supports Handlebars.js as one of its template plugins. +* [SproutCore](http://www.sproutcore.com) uses Handlebars.js as its main + templating engine, extending it with automatic data binding support. +* [YUI](http://yuilibrary.com/yui/docs/handlebars/) implements a port of handlebars +* [Swag](https://github.com/elving/swag) by [@elving](https://github.com/elving) is a growing collection of helpers for handlebars.js. Give your handlebars.js templates some swag son! +* [DOMBars](https://github.com/blakeembrey/dombars) is a DOM-based templating engine built on the Handlebars parser and runtime **DEPRECATED** +* [promised-handlebars](https://github.com/nknapp/promised-handlebars) is a wrapper for Handlebars that allows helpers to return Promises. +* [just-handlebars-helpers](https://github.com/leapfrogtechnology/just-handlebars-helpers) A fully tested lightweight package with common Handlebars helpers. + +External Resources +------------------ + +* [Gist about Synchronous and asynchronous loading of external handlebars templates](https://gist.github.com/2287070) + +Have a project using Handlebars? Send us a [pull request][pull-request]! + +License +------- +Handlebars.js is released under the MIT license. + +[pull-request]: https://github.com/wycats/handlebars.js/pull/new/master diff --git a/hm_sunwell/node_modules/handlebars/bin/handlebars b/hm_sunwell/node_modules/handlebars/bin/handlebars new file mode 100644 index 0000000..7645adf --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/bin/handlebars @@ -0,0 +1,128 @@ +#!/usr/bin/env node + +var optimist = require('optimist') + .usage('Precompile handlebar templates.\nUsage: $0 [template|directory]...', { + 'f': { + 'type': 'string', + 'description': 'Output File', + 'alias': 'output' + }, + 'map': { + 'type': 'string', + 'description': 'Source Map File' + }, + 'a': { + 'type': 'boolean', + 'description': 'Exports amd style (require.js)', + 'alias': 'amd' + }, + 'c': { + 'type': 'string', + 'description': 'Exports CommonJS style, path to Handlebars module', + 'alias': 'commonjs', + 'default': null + }, + 'h': { + 'type': 'string', + 'description': 'Path to handlebar.js (only valid for amd-style)', + 'alias': 'handlebarPath', + 'default': '' + }, + 'k': { + 'type': 'string', + 'description': 'Known helpers', + 'alias': 'known' + }, + 'o': { + 'type': 'boolean', + 'description': 'Known helpers only', + 'alias': 'knownOnly' + }, + 'm': { + 'type': 'boolean', + 'description': 'Minimize output', + 'alias': 'min' + }, + 'n': { + 'type': 'string', + 'description': 'Template namespace', + 'alias': 'namespace', + 'default': 'Handlebars.templates' + }, + 's': { + 'type': 'boolean', + 'description': 'Output template function only.', + 'alias': 'simple' + }, + 'N': { + 'type': 'string', + 'description': 'Name of passed string templates. Optional if running in a simple mode. Required when operating on multiple templates.', + 'alias': 'name' + }, + 'i': { + 'type': 'string', + 'description': 'Generates a template from the passed CLI argument.\n"-" is treated as a special value and causes stdin to be read for the template value.', + 'alias': 'string' + }, + 'r': { + 'type': 'string', + 'description': 'Template root. Base value that will be stripped from template names.', + 'alias': 'root' + }, + 'p': { + 'type': 'boolean', + 'description': 'Compiling a partial template', + 'alias': 'partial' + }, + 'd': { + 'type': 'boolean', + 'description': 'Include data when compiling', + 'alias': 'data' + }, + 'e': { + 'type': 'string', + 'description': 'Template extension.', + 'alias': 'extension', + 'default': 'handlebars' + }, + 'b': { + 'type': 'boolean', + 'description': 'Removes the BOM (Byte Order Mark) from the beginning of the templates.', + 'alias': 'bom' + }, + 'v': { + 'type': 'boolean', + 'description': 'Prints the current compiler version', + 'alias': 'version' + }, + + 'help': { + 'type': 'boolean', + 'description': 'Outputs this message' + } + }) + + .wrap(120) + .check(function(argv) { + if (argv.version) { + return; + } + }); + + +var argv = optimist.argv; +argv.files = argv._; +delete argv._; + +var Precompiler = require('../dist/cjs/precompiler'); +Precompiler.loadTemplates(argv, function(err, opts) { + if (err) { + throw err; + } + + if (opts.help || (!opts.templates.length && !opts.version)) { + optimist.showHelp(); + } else { + Precompiler.cli(opts); + } +}); diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars.js new file mode 100644 index 0000000..a9800bb --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars.js @@ -0,0 +1,51 @@ +define(['exports', 'module', './handlebars.runtime', './handlebars/compiler/ast', './handlebars/compiler/base', './handlebars/compiler/compiler', './handlebars/compiler/javascript-compiler', './handlebars/compiler/visitor', './handlebars/no-conflict'], function (exports, module, _handlebarsRuntime, _handlebarsCompilerAst, _handlebarsCompilerBase, _handlebarsCompilerCompiler, _handlebarsCompilerJavascriptCompiler, _handlebarsCompilerVisitor, _handlebarsNoConflict) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _runtime = _interopRequireDefault(_handlebarsRuntime); + + // Compiler imports + + var _AST = _interopRequireDefault(_handlebarsCompilerAst); + + var _JavaScriptCompiler = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler); + + var _Visitor = _interopRequireDefault(_handlebarsCompilerVisitor); + + var _noConflict = _interopRequireDefault(_handlebarsNoConflict); + + var _create = _runtime['default'].create; + function create() { + var hb = _create(); + + hb.compile = function (input, options) { + return _handlebarsCompilerCompiler.compile(input, options, hb); + }; + hb.precompile = function (input, options) { + return _handlebarsCompilerCompiler.precompile(input, options, hb); + }; + + hb.AST = _AST['default']; + hb.Compiler = _handlebarsCompilerCompiler.Compiler; + hb.JavaScriptCompiler = _JavaScriptCompiler['default']; + hb.Parser = _handlebarsCompilerBase.parser; + hb.parse = _handlebarsCompilerBase.parse; + + return hb; + } + + var inst = create(); + inst.create = create; + + _noConflict['default'](inst); + + inst.Visitor = _Visitor['default']; + + inst['default'] = inst; + + module.exports = inst; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFXQSxNQUFJLE9BQU8sR0FBRyxvQkFBUSxNQUFNLENBQUM7QUFDN0IsV0FBUyxNQUFNLEdBQUc7QUFDaEIsUUFBSSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7O0FBRW5CLE1BQUUsQ0FBQyxPQUFPLEdBQUcsVUFBUyxLQUFLLEVBQUUsT0FBTyxFQUFFO0FBQ3BDLGFBQU8sNEJBWFEsT0FBTyxDQVdQLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDcEMsQ0FBQztBQUNGLE1BQUUsQ0FBQyxVQUFVLEdBQUcsVUFBUyxLQUFLLEVBQUUsT0FBTyxFQUFFO0FBQ3ZDLGFBQU8sNEJBZGlCLFVBQVUsQ0FjaEIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztLQUN2QyxDQUFDOztBQUVGLE1BQUUsQ0FBQyxHQUFHLGtCQUFNLENBQUM7QUFDYixNQUFFLENBQUMsUUFBUSwrQkFsQkosUUFBUSxBQWtCTyxDQUFDO0FBQ3ZCLE1BQUUsQ0FBQyxrQkFBa0IsaUNBQXFCLENBQUM7QUFDM0MsTUFBRSxDQUFDLE1BQU0sMkJBckJGLE1BQU0sQUFxQkssQ0FBQztBQUNuQixNQUFFLENBQUMsS0FBSywyQkF0QmlCLEtBQUssQUFzQmQsQ0FBQzs7QUFFakIsV0FBTyxFQUFFLENBQUM7R0FDWDs7QUFFRCxNQUFJLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQztBQUNwQixNQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7QUFFckIseUJBQVcsSUFBSSxDQUFDLENBQUM7O0FBRWpCLE1BQUksQ0FBQyxPQUFPLHNCQUFVLENBQUM7O0FBRXZCLE1BQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7O21CQUVSLElBQUkiLCJmaWxlIjoiaGFuZGxlYmFycy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBydW50aW1lIGZyb20gJy4vaGFuZGxlYmFycy5ydW50aW1lJztcblxuLy8gQ29tcGlsZXIgaW1wb3J0c1xuaW1wb3J0IEFTVCBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvYXN0JztcbmltcG9ydCB7IHBhcnNlciBhcyBQYXJzZXIsIHBhcnNlIH0gZnJvbSAnLi9oYW5kbGViYXJzL2NvbXBpbGVyL2Jhc2UnO1xuaW1wb3J0IHsgQ29tcGlsZXIsIGNvbXBpbGUsIHByZWNvbXBpbGUgfSBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvY29tcGlsZXInO1xuaW1wb3J0IEphdmFTY3JpcHRDb21waWxlciBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvamF2YXNjcmlwdC1jb21waWxlcic7XG5pbXBvcnQgVmlzaXRvciBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvdmlzaXRvcic7XG5cbmltcG9ydCBub0NvbmZsaWN0IGZyb20gJy4vaGFuZGxlYmFycy9uby1jb25mbGljdCc7XG5cbmxldCBfY3JlYXRlID0gcnVudGltZS5jcmVhdGU7XG5mdW5jdGlvbiBjcmVhdGUoKSB7XG4gIGxldCBoYiA9IF9jcmVhdGUoKTtcblxuICBoYi5jb21waWxlID0gZnVuY3Rpb24oaW5wdXQsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gY29tcGlsZShpbnB1dCwgb3B0aW9ucywgaGIpO1xuICB9O1xuICBoYi5wcmVjb21waWxlID0gZnVuY3Rpb24oaW5wdXQsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gcHJlY29tcGlsZShpbnB1dCwgb3B0aW9ucywgaGIpO1xuICB9O1xuXG4gIGhiLkFTVCA9IEFTVDtcbiAgaGIuQ29tcGlsZXIgPSBDb21waWxlcjtcbiAgaGIuSmF2YVNjcmlwdENvbXBpbGVyID0gSmF2YVNjcmlwdENvbXBpbGVyO1xuICBoYi5QYXJzZXIgPSBQYXJzZXI7XG4gIGhiLnBhcnNlID0gcGFyc2U7XG5cbiAgcmV0dXJuIGhiO1xufVxuXG5sZXQgaW5zdCA9IGNyZWF0ZSgpO1xuaW5zdC5jcmVhdGUgPSBjcmVhdGU7XG5cbm5vQ29uZmxpY3QoaW5zdCk7XG5cbmluc3QuVmlzaXRvciA9IFZpc2l0b3I7XG5cbmluc3RbJ2RlZmF1bHQnXSA9IGluc3Q7XG5cbmV4cG9ydCBkZWZhdWx0IGluc3Q7XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars.runtime.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars.runtime.js new file mode 100644 index 0000000..62e563c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars.runtime.js @@ -0,0 +1,44 @@ +define(['exports', 'module', './handlebars/base', './handlebars/safe-string', './handlebars/exception', './handlebars/utils', './handlebars/runtime', './handlebars/no-conflict'], function (exports, module, _handlebarsBase, _handlebarsSafeString, _handlebarsException, _handlebarsUtils, _handlebarsRuntime, _handlebarsNoConflict) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + // Each of these augment the Handlebars object. No need to setup here. + // (This is done to easily share code between commonjs and browse envs) + + var _SafeString = _interopRequireDefault(_handlebarsSafeString); + + var _Exception = _interopRequireDefault(_handlebarsException); + + var _noConflict = _interopRequireDefault(_handlebarsNoConflict); + + // For compatibility and usage outside of module systems, make the Handlebars object a namespace + function create() { + var hb = new _handlebarsBase.HandlebarsEnvironment(); + + _handlebarsUtils.extend(hb, _handlebarsBase); + hb.SafeString = _SafeString['default']; + hb.Exception = _Exception['default']; + hb.Utils = _handlebarsUtils; + hb.escapeExpression = _handlebarsUtils.escapeExpression; + + hb.VM = _handlebarsRuntime; + hb.template = function (spec) { + return _handlebarsRuntime.template(spec, hb); + }; + + return hb; + } + + var inst = create(); + inst.create = create; + + _noConflict['default'](inst); + + inst['default'] = inst; + + module.exports = inst; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLnJ1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFZQSxXQUFTLE1BQU0sR0FBRztBQUNoQixRQUFJLEVBQUUsR0FBRyxJQUFJLGdCQUFLLHFCQUFxQixFQUFFLENBQUM7O0FBRTFDLHFCQUFNLE1BQU0sQ0FBQyxFQUFFLGtCQUFPLENBQUM7QUFDdkIsTUFBRSxDQUFDLFVBQVUseUJBQWEsQ0FBQztBQUMzQixNQUFFLENBQUMsU0FBUyx3QkFBWSxDQUFDO0FBQ3pCLE1BQUUsQ0FBQyxLQUFLLG1CQUFRLENBQUM7QUFDakIsTUFBRSxDQUFDLGdCQUFnQixHQUFHLGlCQUFNLGdCQUFnQixDQUFDOztBQUU3QyxNQUFFLENBQUMsRUFBRSxxQkFBVSxDQUFDO0FBQ2hCLE1BQUUsQ0FBQyxRQUFRLEdBQUcsVUFBUyxJQUFJLEVBQUU7QUFDM0IsYUFBTyxtQkFBUSxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ25DLENBQUM7O0FBRUYsV0FBTyxFQUFFLENBQUM7R0FDWDs7QUFFRCxNQUFJLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQztBQUNwQixNQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7QUFFckIseUJBQVcsSUFBSSxDQUFDLENBQUM7O0FBRWpCLE1BQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7O21CQUVSLElBQUkiLCJmaWxlIjoiaGFuZGxlYmFycy5ydW50aW1lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYmFzZSBmcm9tICcuL2hhbmRsZWJhcnMvYmFzZSc7XG5cbi8vIEVhY2ggb2YgdGhlc2UgYXVnbWVudCB0aGUgSGFuZGxlYmFycyBvYmplY3QuIE5vIG5lZWQgdG8gc2V0dXAgaGVyZS5cbi8vIChUaGlzIGlzIGRvbmUgdG8gZWFzaWx5IHNoYXJlIGNvZGUgYmV0d2VlbiBjb21tb25qcyBhbmQgYnJvd3NlIGVudnMpXG5pbXBvcnQgU2FmZVN0cmluZyBmcm9tICcuL2hhbmRsZWJhcnMvc2FmZS1zdHJpbmcnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuL2hhbmRsZWJhcnMvZXhjZXB0aW9uJztcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gJy4vaGFuZGxlYmFycy91dGlscyc7XG5pbXBvcnQgKiBhcyBydW50aW1lIGZyb20gJy4vaGFuZGxlYmFycy9ydW50aW1lJztcblxuaW1wb3J0IG5vQ29uZmxpY3QgZnJvbSAnLi9oYW5kbGViYXJzL25vLWNvbmZsaWN0JztcblxuLy8gRm9yIGNvbXBhdGliaWxpdHkgYW5kIHVzYWdlIG91dHNpZGUgb2YgbW9kdWxlIHN5c3RlbXMsIG1ha2UgdGhlIEhhbmRsZWJhcnMgb2JqZWN0IGEgbmFtZXNwYWNlXG5mdW5jdGlvbiBjcmVhdGUoKSB7XG4gIGxldCBoYiA9IG5ldyBiYXNlLkhhbmRsZWJhcnNFbnZpcm9ubWVudCgpO1xuXG4gIFV0aWxzLmV4dGVuZChoYiwgYmFzZSk7XG4gIGhiLlNhZmVTdHJpbmcgPSBTYWZlU3RyaW5nO1xuICBoYi5FeGNlcHRpb24gPSBFeGNlcHRpb247XG4gIGhiLlV0aWxzID0gVXRpbHM7XG4gIGhiLmVzY2FwZUV4cHJlc3Npb24gPSBVdGlscy5lc2NhcGVFeHByZXNzaW9uO1xuXG4gIGhiLlZNID0gcnVudGltZTtcbiAgaGIudGVtcGxhdGUgPSBmdW5jdGlvbihzcGVjKSB7XG4gICAgcmV0dXJuIHJ1bnRpbWUudGVtcGxhdGUoc3BlYywgaGIpO1xuICB9O1xuXG4gIHJldHVybiBoYjtcbn1cblxubGV0IGluc3QgPSBjcmVhdGUoKTtcbmluc3QuY3JlYXRlID0gY3JlYXRlO1xuXG5ub0NvbmZsaWN0KGluc3QpO1xuXG5pbnN0WydkZWZhdWx0J10gPSBpbnN0O1xuXG5leHBvcnQgZGVmYXVsdCBpbnN0O1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/base.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/base.js new file mode 100644 index 0000000..b3dcf46 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/base.js @@ -0,0 +1,96 @@ +define(['exports', './utils', './exception', './helpers', './decorators', './logger'], function (exports, _utils, _exception, _helpers, _decorators, _logger) { + 'use strict'; + + exports.__esModule = true; + exports.HandlebarsEnvironment = HandlebarsEnvironment; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _logger2 = _interopRequireDefault(_logger); + + var VERSION = '4.0.6'; + exports.VERSION = VERSION; + var COMPILER_REVISION = 7; + + exports.COMPILER_REVISION = COMPILER_REVISION; + var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '== 1.x.x', + 5: '== 2.0.0-alpha.x', + 6: '>= 2.0.0-beta.1', + 7: '>= 4.0.0' + }; + + exports.REVISION_CHANGES = REVISION_CHANGES; + var objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + _helpers.registerDefaultHelpers(this); + _decorators.registerDefaultDecorators(this); + } + + HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: _logger2['default'], + log: _logger2['default'].log, + + registerHelper: function registerHelper(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _Exception['default']('Arg not supported with multiple helpers'); + } + _utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function unregisterHelper(name) { + delete this.helpers[name]; + }, + + registerPartial: function registerPartial(name, partial) { + if (_utils.toString.call(name) === objectType) { + _utils.extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new _Exception['default']('Attempting to register a partial called "' + name + '" as undefined'); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function unregisterPartial(name) { + delete this.partials[name]; + }, + + registerDecorator: function registerDecorator(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _Exception['default']('Arg not supported with multiple decorators'); + } + _utils.extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function unregisterDecorator(name) { + delete this.decorators[name]; + } + }; + + var log = _logger2['default'].log; + + exports.log = log; + exports.createFrame = _utils.createFrame; + exports.logger = _logger2['default']; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQU1PLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQzs7QUFDeEIsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7OztBQUU1QixNQUFNLGdCQUFnQixHQUFHO0FBQzlCLEtBQUMsRUFBRSxhQUFhO0FBQ2hCLEtBQUMsRUFBRSxlQUFlO0FBQ2xCLEtBQUMsRUFBRSxlQUFlO0FBQ2xCLEtBQUMsRUFBRSxVQUFVO0FBQ2IsS0FBQyxFQUFFLGtCQUFrQjtBQUNyQixLQUFDLEVBQUUsaUJBQWlCO0FBQ3BCLEtBQUMsRUFBRSxVQUFVO0dBQ2QsQ0FBQzs7O0FBRUYsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUM7O0FBRTlCLFdBQVMscUJBQXFCLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUU7QUFDbkUsUUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO0FBQzdCLFFBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztBQUMvQixRQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsSUFBSSxFQUFFLENBQUM7O0FBRW5DLGFBeEJNLHNCQUFzQixDQXdCTCxJQUFJLENBQUMsQ0FBQztBQUM3QixnQkF4Qk0seUJBQXlCLENBd0JMLElBQUksQ0FBQyxDQUFDO0dBQ2pDOztBQUVELHVCQUFxQixDQUFDLFNBQVMsR0FBRztBQUNoQyxlQUFXLEVBQUUscUJBQXFCOztBQUVsQyxVQUFNLHFCQUFRO0FBQ2QsT0FBRyxFQUFFLG9CQUFPLEdBQUc7O0FBRWYsa0JBQWMsRUFBRSx3QkFBUyxJQUFJLEVBQUUsRUFBRSxFQUFFO0FBQ2pDLFVBQUksT0FyQ3FCLFFBQVEsQ0FxQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxVQUFVLEVBQUU7QUFDdEMsWUFBSSxFQUFFLEVBQUU7QUFBRSxnQkFBTSwwQkFBYyx5Q0FBeUMsQ0FBQyxDQUFDO1NBQUU7QUFDM0UsZUF2Q2UsTUFBTSxDQXVDZCxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO09BQzVCLE1BQU07QUFDTCxZQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztPQUN6QjtLQUNGO0FBQ0Qsb0JBQWdCLEVBQUUsMEJBQVMsSUFBSSxFQUFFO0FBQy9CLGFBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUMzQjs7QUFFRCxtQkFBZSxFQUFFLHlCQUFTLElBQUksRUFBRSxPQUFPLEVBQUU7QUFDdkMsVUFBSSxPQWpEcUIsUUFBUSxDQWlEcEIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLFVBQVUsRUFBRTtBQUN0QyxlQWxEZSxNQUFNLENBa0RkLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7T0FDN0IsTUFBTTtBQUNMLFlBQUksT0FBTyxPQUFPLEtBQUssV0FBVyxFQUFFO0FBQ2xDLGdCQUFNLHdFQUEwRCxJQUFJLG9CQUFpQixDQUFDO1NBQ3ZGO0FBQ0QsWUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUM7T0FDL0I7S0FDRjtBQUNELHFCQUFpQixFQUFFLDJCQUFTLElBQUksRUFBRTtBQUNoQyxhQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDNUI7O0FBRUQscUJBQWlCLEVBQUUsMkJBQVMsSUFBSSxFQUFFLEVBQUUsRUFBRTtBQUNwQyxVQUFJLE9BL0RxQixRQUFRLENBK0RwQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssVUFBVSxFQUFFO0FBQ3RDLFlBQUksRUFBRSxFQUFFO0FBQUUsZ0JBQU0sMEJBQWMsNENBQTRDLENBQUMsQ0FBQztTQUFFO0FBQzlFLGVBakVlLE1BQU0sQ0FpRWQsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztPQUMvQixNQUFNO0FBQ0wsWUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7T0FDNUI7S0FDRjtBQUNELHVCQUFtQixFQUFFLDZCQUFTLElBQUksRUFBRTtBQUNsQyxhQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDOUI7R0FDRixDQUFDOztBQUVLLE1BQUksR0FBRyxHQUFHLG9CQUFPLEdBQUcsQ0FBQzs7O1VBRXBCLFdBQVcsVUE3RVgsV0FBVztVQTZFRSxNQUFNIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2NyZWF0ZUZyYW1lLCBleHRlbmQsIHRvU3RyaW5nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi9leGNlcHRpb24nO1xuaW1wb3J0IHtyZWdpc3RlckRlZmF1bHRIZWxwZXJzfSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtyZWdpc3RlckRlZmF1bHREZWNvcmF0b3JzfSBmcm9tICcuL2RlY29yYXRvcnMnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuL2xvZ2dlcic7XG5cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gJzQuMC42JztcbmV4cG9ydCBjb25zdCBDT01QSUxFUl9SRVZJU0lPTiA9IDc7XG5cbmV4cG9ydCBjb25zdCBSRVZJU0lPTl9DSEFOR0VTID0ge1xuICAxOiAnPD0gMS4wLnJjLjInLCAvLyAxLjAucmMuMiBpcyBhY3R1YWxseSByZXYyIGJ1dCBkb2Vzbid0IHJlcG9ydCBpdFxuICAyOiAnPT0gMS4wLjAtcmMuMycsXG4gIDM6ICc9PSAxLjAuMC1yYy40JyxcbiAgNDogJz09IDEueC54JyxcbiAgNTogJz09IDIuMC4wLWFscGhhLngnLFxuICA2OiAnPj0gMi4wLjAtYmV0YS4xJyxcbiAgNzogJz49IDQuMC4wJ1xufTtcblxuY29uc3Qgb2JqZWN0VHlwZSA9ICdbb2JqZWN0IE9iamVjdF0nO1xuXG5leHBvcnQgZnVuY3Rpb24gSGFuZGxlYmFyc0Vudmlyb25tZW50KGhlbHBlcnMsIHBhcnRpYWxzLCBkZWNvcmF0b3JzKSB7XG4gIHRoaXMuaGVscGVycyA9IGhlbHBlcnMgfHwge307XG4gIHRoaXMucGFydGlhbHMgPSBwYXJ0aWFscyB8fCB7fTtcbiAgdGhpcy5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycyB8fCB7fTtcblxuICByZWdpc3RlckRlZmF1bHRIZWxwZXJzKHRoaXMpO1xuICByZWdpc3RlckRlZmF1bHREZWNvcmF0b3JzKHRoaXMpO1xufVxuXG5IYW5kbGViYXJzRW52aXJvbm1lbnQucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogSGFuZGxlYmFyc0Vudmlyb25tZW50LFxuXG4gIGxvZ2dlcjogbG9nZ2VyLFxuICBsb2c6IGxvZ2dlci5sb2csXG5cbiAgcmVnaXN0ZXJIZWxwZXI6IGZ1bmN0aW9uKG5hbWUsIGZuKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGlmIChmbikgeyB0aHJvdyBuZXcgRXhjZXB0aW9uKCdBcmcgbm90IHN1cHBvcnRlZCB3aXRoIG11bHRpcGxlIGhlbHBlcnMnKTsgfVxuICAgICAgZXh0ZW5kKHRoaXMuaGVscGVycywgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGVscGVyc1tuYW1lXSA9IGZuO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlckhlbHBlcjogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLmhlbHBlcnNbbmFtZV07XG4gIH0sXG5cbiAgcmVnaXN0ZXJQYXJ0aWFsOiBmdW5jdGlvbihuYW1lLCBwYXJ0aWFsKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGV4dGVuZCh0aGlzLnBhcnRpYWxzLCBuYW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGVvZiBwYXJ0aWFsID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKGBBdHRlbXB0aW5nIHRvIHJlZ2lzdGVyIGEgcGFydGlhbCBjYWxsZWQgXCIke25hbWV9XCIgYXMgdW5kZWZpbmVkYCk7XG4gICAgICB9XG4gICAgICB0aGlzLnBhcnRpYWxzW25hbWVdID0gcGFydGlhbDtcbiAgICB9XG4gIH0sXG4gIHVucmVnaXN0ZXJQYXJ0aWFsOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMucGFydGlhbHNbbmFtZV07XG4gIH0sXG5cbiAgcmVnaXN0ZXJEZWNvcmF0b3I6IGZ1bmN0aW9uKG5hbWUsIGZuKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGlmIChmbikgeyB0aHJvdyBuZXcgRXhjZXB0aW9uKCdBcmcgbm90IHN1cHBvcnRlZCB3aXRoIG11bHRpcGxlIGRlY29yYXRvcnMnKTsgfVxuICAgICAgZXh0ZW5kKHRoaXMuZGVjb3JhdG9ycywgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVjb3JhdG9yc1tuYW1lXSA9IGZuO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlckRlY29yYXRvcjogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLmRlY29yYXRvcnNbbmFtZV07XG4gIH1cbn07XG5cbmV4cG9ydCBsZXQgbG9nID0gbG9nZ2VyLmxvZztcblxuZXhwb3J0IHtjcmVhdGVGcmFtZSwgbG9nZ2VyfTtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/ast.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/ast.js new file mode 100644 index 0000000..c28ffeb --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/ast.js @@ -0,0 +1,31 @@ +define(['exports', 'module'], function (exports, module) { + 'use strict'; + + var AST = { + // Public API used to evaluate derived attributes regarding AST nodes + helpers: { + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + helperExpression: function helperExpression(node) { + return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash); + }, + + scopedId: function scopedId(path) { + return (/^\.|this\b/.test(path.original) + ); + }, + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + simpleId: function simpleId(path) { + return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; + } + } + }; + + // Must be exported as an object rather than the root of the module as the jison lexer + // must modify the object to operate properly. + module.exports = AST; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2FzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxNQUFJLEdBQUcsR0FBRzs7QUFFUixXQUFPLEVBQUU7Ozs7QUFJUCxzQkFBZ0IsRUFBRSwwQkFBUyxJQUFJLEVBQUU7QUFDL0IsZUFBTyxBQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssZUFBZSxJQUM3QixDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssbUJBQW1CLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxnQkFBZ0IsQ0FBQSxJQUNuRSxDQUFDLEVBQUUsQUFBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFLLElBQUksQ0FBQyxJQUFJLENBQUEsQUFBQyxBQUFDLENBQUM7T0FDaEU7O0FBRUQsY0FBUSxFQUFFLGtCQUFTLElBQUksRUFBRTtBQUN2QixlQUFPLEFBQUMsYUFBWSxDQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1VBQUM7T0FDM0M7Ozs7QUFJRCxjQUFRLEVBQUUsa0JBQVMsSUFBSSxFQUFFO0FBQ3ZCLGVBQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO09BQzlFO0tBQ0Y7R0FDRixDQUFDOzs7O21CQUthLEdBQUciLCJmaWxlIjoiYXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsibGV0IEFTVCA9IHtcbiAgLy8gUHVibGljIEFQSSB1c2VkIHRvIGV2YWx1YXRlIGRlcml2ZWQgYXR0cmlidXRlcyByZWdhcmRpbmcgQVNUIG5vZGVzXG4gIGhlbHBlcnM6IHtcbiAgICAvLyBhIG11c3RhY2hlIGlzIGRlZmluaXRlbHkgYSBoZWxwZXIgaWY6XG4gICAgLy8gKiBpdCBpcyBhbiBlbGlnaWJsZSBoZWxwZXIsIGFuZFxuICAgIC8vICogaXQgaGFzIGF0IGxlYXN0IG9uZSBwYXJhbWV0ZXIgb3IgaGFzaCBzZWdtZW50XG4gICAgaGVscGVyRXhwcmVzc2lvbjogZnVuY3Rpb24obm9kZSkge1xuICAgICAgcmV0dXJuIChub2RlLnR5cGUgPT09ICdTdWJFeHByZXNzaW9uJylcbiAgICAgICAgICB8fCAoKG5vZGUudHlwZSA9PT0gJ011c3RhY2hlU3RhdGVtZW50JyB8fCBub2RlLnR5cGUgPT09ICdCbG9ja1N0YXRlbWVudCcpXG4gICAgICAgICAgICAmJiAhISgobm9kZS5wYXJhbXMgJiYgbm9kZS5wYXJhbXMubGVuZ3RoKSB8fCBub2RlLmhhc2gpKTtcbiAgICB9LFxuXG4gICAgc2NvcGVkSWQ6IGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgIHJldHVybiAoL15cXC58dGhpc1xcYi8pLnRlc3QocGF0aC5vcmlnaW5hbCk7XG4gICAgfSxcblxuICAgIC8vIGFuIElEIGlzIHNpbXBsZSBpZiBpdCBvbmx5IGhhcyBvbmUgcGFydCwgYW5kIHRoYXQgcGFydCBpcyBub3RcbiAgICAvLyBgLi5gIG9yIGB0aGlzYC5cbiAgICBzaW1wbGVJZDogZnVuY3Rpb24ocGF0aCkge1xuICAgICAgcmV0dXJuIHBhdGgucGFydHMubGVuZ3RoID09PSAxICYmICFBU1QuaGVscGVycy5zY29wZWRJZChwYXRoKSAmJiAhcGF0aC5kZXB0aDtcbiAgICB9XG4gIH1cbn07XG5cblxuLy8gTXVzdCBiZSBleHBvcnRlZCBhcyBhbiBvYmplY3QgcmF0aGVyIHRoYW4gdGhlIHJvb3Qgb2YgdGhlIG1vZHVsZSBhcyB0aGUgamlzb24gbGV4ZXJcbi8vIG11c3QgbW9kaWZ5IHRoZSBvYmplY3QgdG8gb3BlcmF0ZSBwcm9wZXJseS5cbmV4cG9ydCBkZWZhdWx0IEFTVDtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/base.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/base.js new file mode 100644 index 0000000..b4c65cc --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/base.js @@ -0,0 +1,36 @@ +define(['exports', './parser', './whitespace-control', './helpers', '../utils'], function (exports, _parser, _whitespaceControl, _helpers, _utils) { + 'use strict'; + + exports.__esModule = true; + exports.parse = parse; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _parser2 = _interopRequireDefault(_parser); + + var _WhitespaceControl = _interopRequireDefault(_whitespaceControl); + + exports.parser = _parser2['default']; + + var yy = {}; + _utils.extend(yy, _helpers); + + function parse(input, options) { + // Just return if an already-compiled AST was passed in. + if (input.type === 'Program') { + return input; + } + + _parser2['default'].yy = yy; + + // Altering the shared object here, but this is ok as parser is a sync operation + yy.locInfo = function (locInfo) { + return new yy.SourceLocation(options && options.srcName, locInfo); + }; + + var strip = new _WhitespaceControl['default'](options); + return strip.accept(_parser2['default'].parse(input)); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztVQUtTLE1BQU07O0FBRWYsTUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBQ1osU0FMUyxNQUFNLENBS1IsRUFBRSxXQUFVLENBQUM7O0FBRWIsV0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRTs7QUFFcEMsUUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTtBQUFFLGFBQU8sS0FBSyxDQUFDO0tBQUU7O0FBRS9DLHdCQUFPLEVBQUUsR0FBRyxFQUFFLENBQUM7OztBQUdmLE1BQUUsQ0FBQyxPQUFPLEdBQUcsVUFBUyxPQUFPLEVBQUU7QUFDN0IsYUFBTyxJQUFJLEVBQUUsQ0FBQyxjQUFjLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDbkUsQ0FBQzs7QUFFRixRQUFJLEtBQUssR0FBRyxrQ0FBc0IsT0FBTyxDQUFDLENBQUM7QUFDM0MsV0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLG9CQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0dBQzFDIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGFyc2VyIGZyb20gJy4vcGFyc2VyJztcbmltcG9ydCBXaGl0ZXNwYWNlQ29udHJvbCBmcm9tICcuL3doaXRlc3BhY2UtY29udHJvbCc7XG5pbXBvcnQgKiBhcyBIZWxwZXJzIGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgeyBleHRlbmQgfSBmcm9tICcuLi91dGlscyc7XG5cbmV4cG9ydCB7IHBhcnNlciB9O1xuXG5sZXQgeXkgPSB7fTtcbmV4dGVuZCh5eSwgSGVscGVycyk7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZShpbnB1dCwgb3B0aW9ucykge1xuICAvLyBKdXN0IHJldHVybiBpZiBhbiBhbHJlYWR5LWNvbXBpbGVkIEFTVCB3YXMgcGFzc2VkIGluLlxuICBpZiAoaW5wdXQudHlwZSA9PT0gJ1Byb2dyYW0nKSB7IHJldHVybiBpbnB1dDsgfVxuXG4gIHBhcnNlci55eSA9IHl5O1xuXG4gIC8vIEFsdGVyaW5nIHRoZSBzaGFyZWQgb2JqZWN0IGhlcmUsIGJ1dCB0aGlzIGlzIG9rIGFzIHBhcnNlciBpcyBhIHN5bmMgb3BlcmF0aW9uXG4gIHl5LmxvY0luZm8gPSBmdW5jdGlvbihsb2NJbmZvKSB7XG4gICAgcmV0dXJuIG5ldyB5eS5Tb3VyY2VMb2NhdGlvbihvcHRpb25zICYmIG9wdGlvbnMuc3JjTmFtZSwgbG9jSW5mbyk7XG4gIH07XG5cbiAgbGV0IHN0cmlwID0gbmV3IFdoaXRlc3BhY2VDb250cm9sKG9wdGlvbnMpO1xuICByZXR1cm4gc3RyaXAuYWNjZXB0KHBhcnNlci5wYXJzZShpbnB1dCkpO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/code-gen.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/code-gen.js new file mode 100644 index 0000000..f3cc80c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/code-gen.js @@ -0,0 +1,163 @@ +define(['exports', 'module', '../utils'], function (exports, module, _utils) { + /* global define */ + 'use strict'; + + var SourceNode = undefined; + + try { + /* istanbul ignore next */ + if (typeof define !== 'function' || !define.amd) { + // We don't support this in AMD environments. For these environments, we asusme that + // they are running on the browser and thus have no need for the source-map library. + var SourceMap = require('source-map'); + SourceNode = SourceMap.SourceNode; + } + } catch (err) {} + /* NOP */ + + /* istanbul ignore if: tested but not covered in istanbul due to dist build */ + if (!SourceNode) { + SourceNode = function (line, column, srcFile, chunks) { + this.src = ''; + if (chunks) { + this.add(chunks); + } + }; + /* istanbul ignore next */ + SourceNode.prototype = { + add: function add(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src += chunks; + }, + prepend: function prepend(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src = chunks + this.src; + }, + toStringWithSourceMap: function toStringWithSourceMap() { + return { code: this.toString() }; + }, + toString: function toString() { + return this.src; + } + }; + } + + function castChunk(chunk, codeGen, loc) { + if (_utils.isArray(chunk)) { + var ret = []; + + for (var i = 0, len = chunk.length; i < len; i++) { + ret.push(codeGen.wrap(chunk[i], loc)); + } + return ret; + } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { + // Handle primitives that the SourceNode will throw up on + return chunk + ''; + } + return chunk; + } + + function CodeGen(srcFile) { + this.srcFile = srcFile; + this.source = []; + } + + CodeGen.prototype = { + isEmpty: function isEmpty() { + return !this.source.length; + }, + prepend: function prepend(source, loc) { + this.source.unshift(this.wrap(source, loc)); + }, + push: function push(source, loc) { + this.source.push(this.wrap(source, loc)); + }, + + merge: function merge() { + var source = this.empty(); + this.each(function (line) { + source.add([' ', line, '\n']); + }); + return source; + }, + + each: function each(iter) { + for (var i = 0, len = this.source.length; i < len; i++) { + iter(this.source[i]); + } + }, + + empty: function empty() { + var loc = this.currentLocation || { start: {} }; + return new SourceNode(loc.start.line, loc.start.column, this.srcFile); + }, + wrap: function wrap(chunk) { + var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1]; + + if (chunk instanceof SourceNode) { + return chunk; + } + + chunk = castChunk(chunk, this, loc); + + return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); + }, + + functionCall: function functionCall(fn, type, params) { + params = this.generateList(params); + return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); + }, + + quotedString: function quotedString(str) { + return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + objectLiteral: function objectLiteral(obj) { + var pairs = []; + + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var value = castChunk(obj[key], this); + if (value !== 'undefined') { + pairs.push([this.quotedString(key), ':', value]); + } + } + } + + var ret = this.generateList(pairs); + ret.prepend('{'); + ret.add('}'); + return ret; + }, + + generateList: function generateList(entries) { + var ret = this.empty(); + + for (var i = 0, len = entries.length; i < len; i++) { + if (i) { + ret.add(','); + } + + ret.add(castChunk(entries[i], this)); + } + + return ret; + }, + + generateArray: function generateArray(entries) { + var ret = this.generateList(entries); + ret.prepend('['); + ret.add(']'); + + return ret; + } + }; + + module.exports = CodeGen; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvZGUtZ2VuLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFHQSxNQUFJLFVBQVUsWUFBQSxDQUFDOztBQUVmLE1BQUk7O0FBRUYsUUFBSSxPQUFPLE1BQU0sS0FBSyxVQUFVLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFOzs7QUFHL0MsVUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3RDLGdCQUFVLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQztLQUNuQztHQUNGLENBQUMsT0FBTyxHQUFHLEVBQUUsRUFFYjs7OztBQUFBLEFBR0QsTUFBSSxDQUFDLFVBQVUsRUFBRTtBQUNmLGNBQVUsR0FBRyxVQUFTLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUNuRCxVQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNkLFVBQUksTUFBTSxFQUFFO0FBQ1YsWUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztPQUNsQjtLQUNGLENBQUM7O0FBRUYsY0FBVSxDQUFDLFNBQVMsR0FBRztBQUNyQixTQUFHLEVBQUUsYUFBUyxNQUFNLEVBQUU7QUFDcEIsWUFBSSxPQTNCRixPQUFPLENBMkJHLE1BQU0sQ0FBQyxFQUFFO0FBQ25CLGdCQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUMxQjtBQUNELFlBQUksQ0FBQyxHQUFHLElBQUksTUFBTSxDQUFDO09BQ3BCO0FBQ0QsYUFBTyxFQUFFLGlCQUFTLE1BQU0sRUFBRTtBQUN4QixZQUFJLE9BakNGLE9BQU8sQ0FpQ0csTUFBTSxDQUFDLEVBQUU7QUFDbkIsZ0JBQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQzFCO0FBQ0QsWUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFD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QUFZLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDckMsU0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqQixTQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztBQUViLGFBQU8sR0FBRyxDQUFDO0tBQ1o7R0FDRixDQUFDOzttQkFFYSxPQUFPIiwiZmlsZSI6ImNvZGUtZ2VuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZ2xvYmFsIGRlZmluZSAqL1xuaW1wb3J0IHtpc0FycmF5fSBmcm9tICcuLi91dGlscyc7XG5cbmxldCBTb3VyY2VOb2RlO1xuXG50cnkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAodHlwZW9mIGRlZmluZSAhPT0gJ2Z1bmN0aW9uJyB8fCAhZGVmaW5lLmFtZCkge1xuICAgIC8vIFdlIGRvbid0IHN1cHBvcnQgdGhpcyBpbiBBTUQgZW52aXJvbm1lbnRzLiBGb3IgdGhlc2UgZW52aXJvbm1lbnRzLCB3ZSBhc3VzbWUgdGhhdFxuICAgIC8vIHRoZXkgYXJlIHJ1bm5pbmcgb24gdGhlIGJyb3dzZXIgYW5kIHRodXMgaGF2ZSBubyBuZWVkIGZvciB0aGUgc291cmNlLW1hcCBsaWJyYXJ5LlxuICAgIGxldCBTb3VyY2VNYXAgPSByZXF1aXJlKCdzb3VyY2UtbWFwJyk7XG4gICAgU291cmNlTm9kZSA9IFNvdXJjZU1hcC5Tb3VyY2VOb2RlO1xuICB9XG59IGNhdGNoIChlcnIpIHtcbiAgLyogTk9QICovXG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBpZjogdGVzdGVkIGJ1dCBub3QgY292ZXJlZCBpbiBpc3RhbmJ1bCBkdWUgdG8gZGlzdCBidWlsZCAgKi9cbmlmICghU291cmNlTm9kZSkge1xuICBTb3VyY2VOb2RlID0gZnVuY3Rpb24obGluZSwgY29sdW1uLCBzcmNGaWxlLCBjaHVua3MpIHtcbiAgICB0aGlzLnNyYyA9ICcnO1xuICAgIGlmIChjaHVua3MpIHtcbiAgICAgIHRoaXMuYWRkKGNodW5rcyk7XG4gICAgfVxuICB9O1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBTb3VyY2VOb2RlLnByb3RvdHlwZSA9IHtcbiAgICBhZGQ6IGZ1bmN0aW9uKGNodW5rcykge1xuICAgICAgaWYgKGlzQXJyYXkoY2h1bmtzKSkge1xuICAgICAgICBjaHVua3MgPSBjaHVua3Muam9pbignJyk7XG4gICAgICB9XG4gICAgICB0aGlzLnNyYyArPSBjaHVua3M7XG4gICAgfSxcbiAgICBwcmVwZW5kOiBmdW5jdGlvbihjaHVua3MpIHtcbiAgICAgIGlmIChpc0FycmF5KGNodW5rcykpIHtcbiAgICAgICAgY2h1bmtzID0gY2h1bmtzLmpvaW4oJycpO1xuICAgICAgfVxuICAgICAgdGhpcy5zcmMgPSBjaHVua3MgKyB0aGlzLnNyYztcbiAgICB9LFxuICAgIHRvU3RyaW5nV2l0aFNvdXJjZU1hcDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4ge2NvZGU6IHRoaXMudG9TdHJpbmcoKX07XG4gICAgfSxcbiAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5zcmM7XG4gICAgfVxuICB9O1xufVxuXG5cbmZ1bmN0aW9uIGNhc3RDaHVuayhjaHVuaywgY29kZUdlbiwgbG9jKSB7XG4gIGlmIChpc0FycmF5KGNodW5rKSkge1xuICAgIGxldCByZXQgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBjaHVuay5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgcmV0LnB1c2goY29kZUdlbi53cmFwKGNodW5rW2ldLCBsb2MpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY2h1bmsgPT09ICdib29sZWFuJyB8fCB0eXBlb2YgY2h1bmsgPT09ICdudW1iZXInKSB7XG4gICAgLy8gSGFuZGxlIHByaW1pdGl2ZXMgdGhhdCB0aGUgU291cmNlTm9kZSB3aWxsIHRocm93IHVwIG9uXG4gICAgcmV0dXJuIGNodW5rICsgJyc7XG4gIH1cbiAgcmV0dXJuIGNodW5rO1xufVxuXG5cbmZ1bmN0aW9uIENvZGVHZW4oc3JjRmlsZSkge1xuICB0aGlzLnNyY0ZpbGUgPSBzcmNGaWxlO1xuICB0aGlzLnNvdXJjZSA9IFtdO1xufVxuXG5Db2RlR2VuLnByb3RvdHlwZSA9IHtcbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gIXRoaXMuc291cmNlLmxlbmd0aDtcbiAgfSxcbiAgcHJlcGVuZDogZnVuY3Rpb24oc291cmNlLCBsb2MpIHtcbiAgICB0aGlzLnNvdXJjZS51bnNoaWZ0KHRoaXMud3JhcChzb3VyY2UsIGxvYykpO1xuICB9LFxuICBwdXNoOiBmdW5jdGlvbihzb3VyY2UsIGxvYykge1xuICAgIHRoaXMuc291cmNlLnB1c2godGhpcy53cmFwKHNvdXJjZSwgbG9jKSk7XG4gIH0sXG5cbiAgbWVyZ2U6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBzb3VyY2UgPSB0aGlzLmVtcHR5KCk7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIHNvdXJjZS5hZGQoWycgICcsIGxpbmUsICdcXG4nXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHNvdXJjZTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbihpdGVyKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRoaXMuc291cmNlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpdGVyKHRoaXMuc291cmNlW2ldKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBsb2MgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbiB8fCB7c3RhcnQ6IHt9fTtcbiAgICByZXR1cm4gbmV3IFNvdXJjZU5vZGUobG9jLnN0YXJ0LmxpbmUsIGxvYy5zdGFydC5jb2x1bW4sIHRoaXMuc3JjRmlsZSk7XG4gIH0sXG4gIHdyYXA6IGZ1bmN0aW9uKGNodW5rLCBsb2MgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbiB8fCB7c3RhcnQ6IHt9fSkge1xuICAgIGlmIChjaHVuayBpbnN0YW5jZW9mIFNvdXJjZU5vZGUpIHtcbiAgICAgIHJldHVybiBjaHVuaztcbiAgICB9XG5cbiAgICBjaHVuayA9IGNhc3RDaHVuayhjaHVuaywgdGhpcywgbG9jKTtcblxuICAgIHJldHVybiBuZXcgU291cmNlTm9kZShsb2Muc3RhcnQubGluZSwgbG9jLnN0YXJ0LmNvbHVtbiwgdGhpcy5zcmNGaWxlLCBjaHVuayk7XG4gIH0sXG5cbiAgZnVuY3Rpb25DYWxsOiBmdW5jdGlvbihmbiwgdHlwZSwgcGFyYW1zKSB7XG4gICAgcGFyYW1zID0gdGhpcy5nZW5lcmF0ZUxpc3QocGFyYW1zKTtcbiAgICByZXR1cm4gdGhpcy53cmFwKFtmbiwgdHlwZSA/ICcuJyArIHR5cGUgKyAnKCcgOiAnKCcsIHBhcmFtcywgJyknXSk7XG4gIH0sXG5cbiAgcXVvdGVkU3RyaW5nOiBmdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gJ1wiJyArIChzdHIgKyAnJylcbiAgICAgIC5yZXBsYWNlKC9cXFxcL2csICdcXFxcXFxcXCcpXG4gICAgICAucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpXG4gICAgICAucmVwbGFjZSgvXFxuL2csICdcXFxcbicpXG4gICAgICAucmVwbGFjZSgvXFxyL2csICdcXFxccicpXG4gICAgICAucmVwbGFjZSgvXFx1MjAyOC9nLCAnXFxcXHUyMDI4JykgICAvLyBQZXIgRWNtYS0yNjIgNy4zICsgNy44LjRcbiAgICAgIC5yZXBsYWNlKC9cXHUyMDI5L2csICdcXFxcdTIwMjknKSArICdcIic7XG4gIH0sXG5cbiAgb2JqZWN0TGl0ZXJhbDogZnVuY3Rpb24ob2JqKSB7XG4gICAgbGV0IHBhaXJzID0gW107XG5cbiAgICBmb3IgKGxldCBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgbGV0IHZhbHVlID0gY2FzdENodW5rKG9ialtrZXldLCB0aGlzKTtcbiAgICAgICAgaWYgKHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHBhaXJzLnB1c2goW3RoaXMucXVvdGVkU3RyaW5nKGtleSksICc6JywgdmFsdWVdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGxldCByZXQgPSB0aGlzLmdlbmVyYXRlTGlzdChwYWlycyk7XG4gICAgcmV0LnByZXBlbmQoJ3snKTtcbiAgICByZXQuYWRkKCd9Jyk7XG4gICAgcmV0dXJuIHJldDtcbiAgfSxcblxuXG4gIGdlbmVyYXRlTGlzdDogZnVuY3Rpb24oZW50cmllcykge1xuICAgIGxldCByZXQgPSB0aGlzLmVtcHR5KCk7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gZW50cmllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgaWYgKGkpIHtcbiAgICAgICAgcmV0LmFkZCgnLCcpO1xuICAgICAgfVxuXG4gICAgICByZXQuYWRkKGNhc3RDaHVuayhlbnRyaWVzW2ldLCB0aGlzKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfSxcblxuICBnZW5lcmF0ZUFycmF5OiBmdW5jdGlvbihlbnRyaWVzKSB7XG4gICAgbGV0IHJldCA9IHRoaXMuZ2VuZXJhdGVMaXN0KGVudHJpZXMpO1xuICAgIHJldC5wcmVwZW5kKCdbJyk7XG4gICAgcmV0LmFkZCgnXScpO1xuXG4gICAgcmV0dXJuIHJldDtcbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgQ29kZUdlbjtcblxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/compiler.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/compiler.js new file mode 100644 index 0000000..71edc15 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/compiler.js @@ -0,0 +1,568 @@ +define(['exports', '../exception', '../utils', './ast'], function (exports, _exception, _utils, _ast) { + /* eslint-disable new-cap */ + + 'use strict'; + + exports.__esModule = true; + exports.Compiler = Compiler; + exports.precompile = precompile; + exports.compile = compile; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _AST = _interopRequireDefault(_ast); + + var slice = [].slice; + + function Compiler() {} + + // the foundHelper register will disambiguate helper lookup from finding a + // function in a context. This is necessary for mustache compatibility, which + // requires that context functions in blocks are evaluated by blockHelperMissing, + // and then proceed as if the resulting value was provided to blockHelperMissing. + + Compiler.prototype = { + compiler: Compiler, + + equals: function equals(other) { + var len = this.opcodes.length; + if (other.opcodes.length !== len) { + return false; + } + + for (var i = 0; i < len; i++) { + var opcode = this.opcodes[i], + otherOpcode = other.opcodes[i]; + if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { + return false; + } + } + + // We know that length is the same between the two arrays because they are directly tied + // to the opcode behavior above. + len = this.children.length; + for (var i = 0; i < len; i++) { + if (!this.children[i].equals(other.children[i])) { + return false; + } + } + + return true; + }, + + guid: 0, + + compile: function compile(program, options) { + this.sourceNode = []; + this.opcodes = []; + this.children = []; + this.options = options; + this.stringParams = options.stringParams; + this.trackIds = options.trackIds; + + options.blockParams = options.blockParams || []; + + // These changes will propagate to the other compiler components + var knownHelpers = options.knownHelpers; + options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true, + 'lookup': true + }; + if (knownHelpers) { + for (var _name in knownHelpers) { + /* istanbul ignore else */ + if (_name in knownHelpers) { + options.knownHelpers[_name] = knownHelpers[_name]; + } + } + } + + return this.accept(program); + }, + + compileProgram: function compileProgram(program) { + var childCompiler = new this.compiler(), + // eslint-disable-line new-cap + result = childCompiler.compile(program, this.options), + guid = this.guid++; + + this.usePartial = this.usePartial || result.usePartial; + + this.children[guid] = result; + this.useDepths = this.useDepths || result.useDepths; + + return guid; + }, + + accept: function accept(node) { + /* istanbul ignore next: Sanity code */ + if (!this[node.type]) { + throw new _Exception['default']('Unknown type: ' + node.type, node); + } + + this.sourceNode.unshift(node); + var ret = this[node.type](node); + this.sourceNode.shift(); + return ret; + }, + + Program: function Program(program) { + this.options.blockParams.unshift(program.blockParams); + + var body = program.body, + bodyLength = body.length; + for (var i = 0; i < bodyLength; i++) { + this.accept(body[i]); + } + + this.options.blockParams.shift(); + + this.isSimple = bodyLength === 1; + this.blockParams = program.blockParams ? program.blockParams.length : 0; + + return this; + }, + + BlockStatement: function BlockStatement(block) { + transformLiteralToPath(block); + + var program = block.program, + inverse = block.inverse; + + program = program && this.compileProgram(program); + inverse = inverse && this.compileProgram(inverse); + + var type = this.classifySexpr(block); + + if (type === 'helper') { + this.helperSexpr(block, program, inverse); + } else if (type === 'simple') { + this.simpleSexpr(block); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('blockValue', block.path.original); + } else { + this.ambiguousSexpr(block, program, inverse); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('ambiguousBlockValue'); + } + + this.opcode('append'); + }, + + DecoratorBlock: function DecoratorBlock(decorator) { + var program = decorator.program && this.compileProgram(decorator.program); + var params = this.setupFullMustacheParams(decorator, program, undefined), + path = decorator.path; + + this.useDecorators = true; + this.opcode('registerDecorator', params.length, path.original); + }, + + PartialStatement: function PartialStatement(partial) { + this.usePartial = true; + + var program = partial.program; + if (program) { + program = this.compileProgram(partial.program); + } + + var params = partial.params; + if (params.length > 1) { + throw new _Exception['default']('Unsupported number of partial arguments: ' + params.length, partial); + } else if (!params.length) { + if (this.options.explicitPartialContext) { + this.opcode('pushLiteral', 'undefined'); + } else { + params.push({ type: 'PathExpression', parts: [], depth: 0 }); + } + } + + var partialName = partial.name.original, + isDynamic = partial.name.type === 'SubExpression'; + if (isDynamic) { + this.accept(partial.name); + } + + this.setupFullMustacheParams(partial, program, undefined, true); + + var indent = partial.indent || ''; + if (this.options.preventIndent && indent) { + this.opcode('appendContent', indent); + indent = ''; + } + + this.opcode('invokePartial', isDynamic, partialName, indent); + this.opcode('append'); + }, + PartialBlockStatement: function PartialBlockStatement(partialBlock) { + this.PartialStatement(partialBlock); + }, + + MustacheStatement: function MustacheStatement(mustache) { + this.SubExpression(mustache); + + if (mustache.escaped && !this.options.noEscape) { + this.opcode('appendEscaped'); + } else { + this.opcode('append'); + } + }, + Decorator: function Decorator(decorator) { + this.DecoratorBlock(decorator); + }, + + ContentStatement: function ContentStatement(content) { + if (content.value) { + this.opcode('appendContent', content.value); + } + }, + + CommentStatement: function CommentStatement() {}, + + SubExpression: function SubExpression(sexpr) { + transformLiteralToPath(sexpr); + var type = this.classifySexpr(sexpr); + + if (type === 'simple') { + this.simpleSexpr(sexpr); + } else if (type === 'helper') { + this.helperSexpr(sexpr); + } else { + this.ambiguousSexpr(sexpr); + } + }, + ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) { + var path = sexpr.path, + name = path.parts[0], + isBlock = program != null || inverse != null; + + this.opcode('getContext', path.depth); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + path.strict = true; + this.accept(path); + + this.opcode('invokeAmbiguous', name, isBlock); + }, + + simpleSexpr: function simpleSexpr(sexpr) { + var path = sexpr.path; + path.strict = true; + this.accept(path); + this.opcode('resolvePossibleLambda'); + }, + + helperSexpr: function helperSexpr(sexpr, program, inverse) { + var params = this.setupFullMustacheParams(sexpr, program, inverse), + path = sexpr.path, + name = path.parts[0]; + + if (this.options.knownHelpers[name]) { + this.opcode('invokeKnownHelper', params.length, name); + } else if (this.options.knownHelpersOnly) { + throw new _Exception['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); + } else { + path.strict = true; + path.falsy = true; + + this.accept(path); + this.opcode('invokeHelper', params.length, path.original, _AST['default'].helpers.simpleId(path)); + } + }, + + PathExpression: function PathExpression(path) { + this.addDepth(path.depth); + this.opcode('getContext', path.depth); + + var name = path.parts[0], + scoped = _AST['default'].helpers.scopedId(path), + blockParamId = !path.depth && !scoped && this.blockParamIndex(name); + + if (blockParamId) { + this.opcode('lookupBlockParam', blockParamId, path.parts); + } else if (!name) { + // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` + this.opcode('pushContext'); + } else if (path.data) { + this.options.data = true; + this.opcode('lookupData', path.depth, path.parts, path.strict); + } else { + this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); + } + }, + + StringLiteral: function StringLiteral(string) { + this.opcode('pushString', string.value); + }, + + NumberLiteral: function NumberLiteral(number) { + this.opcode('pushLiteral', number.value); + }, + + BooleanLiteral: function BooleanLiteral(bool) { + this.opcode('pushLiteral', bool.value); + }, + + UndefinedLiteral: function UndefinedLiteral() { + this.opcode('pushLiteral', 'undefined'); + }, + + NullLiteral: function NullLiteral() { + this.opcode('pushLiteral', 'null'); + }, + + Hash: function Hash(hash) { + var pairs = hash.pairs, + i = 0, + l = pairs.length; + + this.opcode('pushHash'); + + for (; i < l; i++) { + this.pushParam(pairs[i].value); + } + while (i--) { + this.opcode('assignToHash', pairs[i].key); + } + this.opcode('popHash'); + }, + + // HELPERS + opcode: function opcode(name) { + this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc }); + }, + + addDepth: function addDepth(depth) { + if (!depth) { + return; + } + + this.useDepths = true; + }, + + classifySexpr: function classifySexpr(sexpr) { + var isSimple = _AST['default'].helpers.simpleId(sexpr.path); + + var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + var isHelper = !isBlockParam && _AST['default'].helpers.helperExpression(sexpr); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + var isEligible = !isBlockParam && (isHelper || isSimple); + + // if ambiguous, we can possibly resolve the ambiguity now + // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. + if (isEligible && !isHelper) { + var _name2 = sexpr.path.parts[0], + options = this.options; + + if (options.knownHelpers[_name2]) { + isHelper = true; + } else if (options.knownHelpersOnly) { + isEligible = false; + } + } + + if (isHelper) { + return 'helper'; + } else if (isEligible) { + return 'ambiguous'; + } else { + return 'simple'; + } + }, + + pushParams: function pushParams(params) { + for (var i = 0, l = params.length; i < l; i++) { + this.pushParam(params[i]); + } + }, + + pushParam: function pushParam(val) { + var value = val.value != null ? val.value : val.original || ''; + + if (this.stringParams) { + if (value.replace) { + value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.'); + } + + if (val.depth) { + this.addDepth(val.depth); + } + this.opcode('getContext', val.depth || 0); + this.opcode('pushStringParam', value, val.type); + + if (val.type === 'SubExpression') { + // SubExpressions get evaluated and passed in + // in string params mode. + this.accept(val); + } + } else { + if (this.trackIds) { + var blockParamIndex = undefined; + if (val.parts && !_AST['default'].helpers.scopedId(val) && !val.depth) { + blockParamIndex = this.blockParamIndex(val.parts[0]); + } + if (blockParamIndex) { + var blockParamChild = val.parts.slice(1).join('.'); + this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); + } else { + value = val.original || value; + if (value.replace) { + value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, ''); + } + + this.opcode('pushId', val.type, value); + } + } + this.accept(val); + } + }, + + setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) { + var params = sexpr.params; + this.pushParams(params); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + if (sexpr.hash) { + this.accept(sexpr.hash); + } else { + this.opcode('emptyHash', omitEmpty); + } + + return params; + }, + + blockParamIndex: function blockParamIndex(name) { + for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { + var blockParams = this.options.blockParams[depth], + param = blockParams && _utils.indexOf(blockParams, name); + if (blockParams && param >= 0) { + return [depth, param]; + } + } + } + }; + + function precompile(input, options, env) { + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _Exception['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); + } + + options = options || {}; + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options); + return new env.JavaScriptCompiler().compile(environment, options); + } + + function compile(input, options, env) { + if (options === undefined) options = {}; + + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _Exception['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); + } + + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var compiled = undefined; + + function compileInput() { + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options), + templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); + return env.template(templateSpec); + } + + // Template is only compiled on first use and cached after that point. + function ret(context, execOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled.call(this, context, execOptions); + } + ret._setup = function (setupOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._setup(setupOptions); + }; + ret._child = function (i, data, blockParams, depths) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._child(i, data, blockParams, depths); + }; + return ret; + } + + function argEquals(a, b) { + if (a === b) { + return true; + } + + if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) { + for (var i = 0; i < a.length; i++) { + if (!argEquals(a[i], b[i])) { + return false; + } + } + return true; + } + } + + function transformLiteralToPath(sexpr) { + if (!sexpr.path.parts) { + var literal = sexpr.path; + // Casting to string here to make false and 0 literal values play nicely with the rest + // of the system. + sexpr.path = { + type: 'PathExpression', + data: false, + depth: 0, + parts: [literal.original + ''], + original: literal.original + '', + loc: literal.loc + }; + } + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvbXBpbGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBTUEsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQzs7QUFFaEIsV0FBUyxRQUFRLEdBQUcsRUFBRTs7Ozs7OztBQU83QixVQUFRLENBQUMsU0FBUyxHQUFHO0FBQ25CLFlBQVEsRUFBRSxRQUFROztBQUVsQixVQUFNLEVBQUUsZ0JBQVMsS0FBSyxFQUFFO0FBQ3RCLFVBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO0FBQzlCLFVBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFO0FBQ2hDLGVBQU8sS0FBSyxDQUFDO09BQ2Q7O0FBRUQsV0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM1QixZQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN4QixXQUFXLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNuQyxZQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssV0FBVyxDQUFDLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRTtBQUNyRixpQkFBTyxLQUFLLENBQUM7U0FDZDtPQUNGOzs7O0FBSUQsU0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO0FBQzNCLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDNUIsWUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FB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S0FBSyxDQUFDLENBQUMsTUFBTSxFQUFFO0FBQ3JELFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQ2pDLFlBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0FBQzFCLGlCQUFPLEtBQUssQ0FBQztTQUNkO09BQ0Y7QUFDRCxhQUFPLElBQUksQ0FBQztLQUNiO0dBQ0Y7O0FBRUQsV0FBUyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUU7QUFDckMsUUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO0FBQ3JCLFVBQUksT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7OztBQUd6QixXQUFLLENBQUMsSUFBSSxHQUFHO0FBQ1gsWUFBSSxFQUFFLGdCQUFnQjtBQUN0QixZQUFJLEVBQUUsS0FBSztBQUNYLGFBQUssRUFBRSxDQUFDO0FBQ1IsYUFBSyxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7QUFDOUIsZ0JBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxHQUFHLEVBQUU7QUFDL0IsV0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO09BQ2pCLENBQUM7S0FDSDtHQUNGIiwiZmlsZSI6ImNvbXBpbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbmV3LWNhcCAqL1xuXG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5pbXBvcnQge2lzQXJyYXksIGluZGV4T2Z9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCBBU1QgZnJvbSAnLi9hc3QnO1xuXG5jb25zdCBzbGljZSA9IFtdLnNsaWNlO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcGlsZXIoKSB7fVxuXG4vLyB0aGUgZm91bmRIZWxwZXIgcmVnaXN0ZXIgd2lsbCBkaXNhbWJpZ3VhdGUgaGVscGVyIGxvb2t1cCBmcm9tIGZpbmRpbmcgYVxuLy8gZnVuY3Rpb24gaW4gYSBjb250ZXh0LiBUaGlzIGlzIG5lY2Vzc2FyeSBmb3IgbXVzdGFjaGUgY29tcGF0aWJpbGl0eSwgd2hpY2hcbi8vIHJlcXVpcmVzIHRoYXQgY29udGV4dCBmdW5jdGlvbnMgaW4gYmxvY2tzIGFyZSBldmFsdWF0ZWQgYnkgYmxvY2tIZWxwZXJNaXNzaW5nLFxuLy8gYW5kIHRoZW4gcHJvY2VlZCBhcyBpZiB0aGUgcmVzdWx0aW5nIHZhbHVlIHdhcyBwcm92aWRlZCB0byBibG9ja0hlbHBlck1pc3NpbmcuXG5cbkNvbXBpbGVyLnByb3RvdHlwZSA9IHtcbiAgY29tcGlsZXI6IENvbXBpbGVyLFxuXG4gIGVxdWFsczogZnVuY3Rpb24ob3RoZXIpIHtcbiAgICBsZXQgbGVuID0gdGhpcy5vcGNvZGVzLmxlbmd0aDtcbiAgICBpZiAob3RoZXIub3Bjb2Rlcy5sZW5ndGggIT09IGxlbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGxldCBvcGNvZGUgPSB0aGlzLm9wY29kZXNbaV0sXG4gICAgICAgICAgb3RoZXJPcGNvZGUgPSBvdGhlci5vcGNvZGVzW2ldO1xuICAgICAgaWYgKG9wY29kZS5vcGNvZGUgIT09IG90aGVyT3Bjb2RlLm9wY29kZSB8fCAhYXJnRXF1YWxzKG9wY29kZS5hcmdzLCBvdGhlck9wY29kZS5hcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gV2Uga25vdyB0aGF0IGxlbmd0aCBpcyB0aGUgc2FtZSBiZXR3ZWVuIHRoZSB0d28gYXJyYXlzIGJlY2F1c2UgdGhleSBhcmUgZGlyZWN0bHkgdGllZFxuICAgIC8vIHRvIHRoZSBvcGNvZGUgYmVoYXZpb3IgYWJvdmUuXG4gICAgbGVuID0gdGhpcy5jaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgaWYgKCF0aGlzLmNoaWxkcmVuW2ldLmVxdWFscyhvdGhlci5jaGlsZHJlbltpXSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGd1aWQ6IDAsXG5cbiAgY29tcGlsZTogZnVuY3Rpb24ocHJvZ3JhbSwgb3B0aW9ucykge1xuICAgIHRoaXMuc291cmNlTm9kZSA9IFtdO1xuICAgIHRoaXMub3Bjb2RlcyA9IFtdO1xuICAgIHRoaXMuY2hpbGRyZW4gPSBbXTtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMuc3RyaW5nUGFyYW1zID0gb3B0aW9ucy5zdHJpbmdQYXJhbXM7XG4gICAgdGhpcy50cmFja0lkcyA9IG9wdGlvbnMudHJhY2tJZHM7XG5cbiAgICBvcHRpb25zLmJsb2NrUGFyYW1zID0gb3B0aW9ucy5ibG9ja1BhcmFtcyB8fCBbXTtcblxuICAgIC8vIFRoZXNlIGNoYW5nZXMgd2lsbCBwcm9wYWdhdGUgdG8gdGhlIG90aGVyIGNvbXBpbGVyIGNvbXBvbmVudHNcbiAgICBsZXQga25vd25IZWxwZXJzID0gb3B0aW9ucy5rbm93bkhlbHBlcnM7XG4gICAgb3B0aW9ucy5rbm93bkhlbHBlcnMgPSB7XG4gICAgICAnaGVscGVyTWlzc2luZyc6IHRydWUsXG4gICAgICAnYmxvY2tIZWxwZXJNaXNzaW5nJzogdHJ1ZSxcbiAgICAgICdlYWNoJzogdHJ1ZSxcbiAgICAgICdpZic6IHRydWUsXG4gICAgICAndW5sZXNzJzogdHJ1ZSxcbiAgICAgICd3aXRoJzogdHJ1ZSxcbiAgICAgICdsb2cnOiB0cnVlLFxuICAgICAgJ2xvb2t1cCc6IHRydWVcbiAgICB9O1xuICAgIGlmIChrbm93bkhlbHBlcnMpIHtcbiAgICAgIGZvciAobGV0IG5hbWUgaW4ga25vd25IZWxwZXJzKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgIGlmIChuYW1lIGluIGtub3duSGVscGVycykge1xuICAgICAgICAgIG9wdGlvbnMua25vd25IZWxwZXJzW25hbWVdID0ga25vd25IZWxwZXJzW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYWNjZXB0KHByb2dyYW0pO1xuICB9LFxuXG4gIGNvbXBpbGVQcm9ncmFtOiBmdW5jdGlvbihwcm9ncmFtKSB7XG4gICAgbGV0IGNoaWxkQ29tcGlsZXIgPSBuZXcgdGhpcy5jb21waWxlcigpLCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5ldy1jYXBcbiAgICAgICAgcmVzdWx0ID0gY2hpbGRDb21waWxlci5jb21waWxlKHByb2dyYW0sIHRoaXMub3B0aW9ucyksXG4gICAgICAgIGd1aWQgPSB0aGlzLmd1aWQrKztcblxuICAgIHRoaXMudXNlUGFydGlhbCA9IHRoaXMudXNlUGFydGlhbCB8fCByZXN1bHQudXNlUGFydGlhbDtcblxuICAgIHRoaXMuY2hpbGRyZW5bZ3VpZF0gPSByZXN1bHQ7XG4gICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCByZXN1bHQudXNlRGVwdGhzO1xuXG4gICAgcmV0dXJuIGd1aWQ7XG4gIH0sXG5cbiAgYWNjZXB0OiBmdW5jdGlvbihub2RlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IFNhbml0eSBjb2RlICovXG4gICAgaWYgKCF0aGlzW25vZGUudHlwZV0pIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdHlwZTogJyArIG5vZGUudHlwZSwgbm9kZSk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VOb2RlLnVuc2hpZnQobm9kZSk7XG4gICAgbGV0IHJldCA9IHRoaXNbbm9kZS50eXBlXShub2RlKTtcbiAgICB0aGlzLnNvdXJjZU5vZGUuc2hpZnQoKTtcbiAgICByZXR1cm4gcmV0O1xuICB9LFxuXG4gIFByb2dyYW06IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgICB0aGlzLm9wdGlvbnMuYmxvY2tQYXJhbXMudW5zaGlmdChwcm9ncmFtLmJsb2NrUGFyYW1zKTtcblxuICAgIGxldCBib2R5ID0gcHJvZ3JhbS5ib2R5LFxuICAgICAgICBib2R5TGVuZ3RoID0gYm9keS5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBib2R5TGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuYWNjZXB0KGJvZHlbaV0pO1xuICAgIH1cblxuICAgIHRoaXMub3B0aW9ucy5ibG9ja1BhcmFtcy5zaGlmdCgpO1xuXG4gICAgdGhpcy5pc1NpbXBsZSA9IGJvZHlMZW5ndGggPT09IDE7XG4gICAgdGhpcy5ibG9ja1BhcmFtcyA9IHByb2dyYW0uYmxvY2tQYXJhbXMgPyBwcm9ncmFtLmJsb2NrUGFyYW1zLmxlbmd0aCA6IDA7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBCbG9ja1N0YXRlbWVudDogZnVuY3Rpb24oYmxvY2spIHtcbiAgICB0cmFuc2Zvcm1MaXRlcmFsVG9QYXRoKGJsb2NrKTtcblxuICAgIGxldCBwcm9ncmFtID0gYmxvY2sucHJvZ3JhbSxcbiAgICAgICAgaW52ZXJzZSA9IGJsb2NrLmludmVyc2U7XG5cbiAgICBwcm9ncmFtID0gcHJvZ3JhbSAmJiB0aGlzLmNvbXBpbGVQcm9ncmFtKHByb2dyYW0pO1xuICAgIGludmVyc2UgPSBpbnZlcnNlICYmIHRoaXMuY29tcGlsZVByb2dyYW0oaW52ZXJzZSk7XG5cbiAgICBsZXQgdHlwZSA9IHRoaXMuY2xhc3NpZnlTZXhwcihibG9jayk7XG5cbiAgICBpZiAodHlwZSA9PT0gJ2hlbHBlcicpIHtcbiAgICAgIHRoaXMuaGVscGVyU2V4cHIoYmxvY2ssIHByb2dyYW0sIGludmVyc2UpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3NpbXBsZScpIHtcbiAgICAgIHRoaXMuc2ltcGxlU2V4cHIoYmxvY2spO1xuXG4gICAgICAvLyBub3cgdGhhdCB0aGUgc2ltcGxlIG11c3RhY2hlIGlzIHJlc29sdmVkLCB3ZSBuZWVkIHRvXG4gICAgICAvLyBldmFsdWF0ZSBpdCBieSBleGVjdXRpbmcgYGJsb2NrSGVscGVyTWlzc2luZ2BcbiAgICAgIHRoaXMub3Bjb2RlKCdwdXNoUHJvZ3JhbScsIHByb2dyYW0pO1xuICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgaW52ZXJzZSk7XG4gICAgICB0aGlzLm9wY29kZSgnZW1wdHlIYXNoJyk7XG4gICAgICB0aGlzLm9wY29kZSgnYmxvY2tWYWx1ZScsIGJsb2NrLnBhdGgub3JpZ2luYWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFtYmlndW91c1NleHByKGJsb2NrLCBwcm9ncmFtLCBpbnZlcnNlKTtcblxuICAgICAgLy8gbm93IHRoYXQgdGhlIHNpbXBsZSBtdXN0YWNoZSBpcyByZXNvbHZlZCwgd2UgbmVlZCB0b1xuICAgICAgLy8gZXZhbHVhdGUgaXQgYnkgZXhlY3V0aW5nIGBibG9ja0hlbHBlck1pc3NpbmdgXG4gICAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBwcm9ncmFtKTtcbiAgICAgIHRoaXMub3Bjb2RlKCdwdXNoUHJvZ3JhbScsIGludmVyc2UpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2VtcHR5SGFzaCcpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2FtYmlndW91c0Jsb2NrVmFsdWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLm9wY29kZSgnYXBwZW5kJyk7XG4gIH0sXG5cbiAgRGVjb3JhdG9yQmxvY2soZGVjb3JhdG9yKSB7XG4gICAgbGV0IHByb2dyYW0gPSBkZWNvcmF0b3IucHJvZ3JhbSAmJiB0aGlzLmNvbXBpbGVQcm9ncmFtKGRlY29yYXRvci5wcm9ncmFtKTtcbiAgICBsZXQgcGFyYW1zID0gdGhpcy5zZXR1cEZ1bGxNdXN0YWNoZVBhcmFtcyhkZWNvcmF0b3IsIHByb2dyYW0sIHVuZGVmaW5lZCksXG4gICAgICAgIHBhdGggPSBkZWNvcmF0b3IucGF0aDtcblxuICAgIHRoaXMudXNlRGVjb3JhdG9ycyA9IHRydWU7XG4gICAgdGhpcy5vcGNvZGUoJ3JlZ2lzdGVyRGVjb3JhdG9yJywgcGFyYW1zLmxlbmd0aCwgcGF0aC5vcmlnaW5hbCk7XG4gIH0sXG5cbiAgUGFydGlhbFN0YXRlbWVudDogZnVuY3Rpb24ocGFydGlhbCkge1xuICAgIHRoaXMudXNlUGFydGlhbCA9IHRydWU7XG5cbiAgICBsZXQgcHJvZ3JhbSA9IHBhcnRpYWwucHJvZ3JhbTtcbiAgICBpZiAocHJvZ3JhbSkge1xuICAgICAgcHJvZ3JhbSA9IHRoaXMuY29tcGlsZVByb2dyYW0ocGFydGlhbC5wcm9ncmFtKTtcbiAgICB9XG5cbiAgICBsZXQgcGFyYW1zID0gcGFydGlhbC5wYXJhbXM7XG4gICAgaWYgKHBhcmFtcy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdVbnN1cHBvcnRlZCBudW1iZXIgb2YgcGFydGlhbCBhcmd1bWVudHM6ICcgKyBwYXJhbXMubGVuZ3RoLCBwYXJ0aWFsKTtcbiAgICB9IGVsc2UgaWYgKCFwYXJhbXMubGVuZ3RoKSB7XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmV4cGxpY2l0UGFydGlhbENvbnRleHQpIHtcbiAgICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgJ3VuZGVmaW5lZCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zLnB1c2goe3R5cGU6ICdQYXRoRXhwcmVzc2lvbicsIHBhcnRzOiBbXSwgZGVwdGg6IDB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgcGFydGlhbE5hbWUgPSBwYXJ0aWFsLm5hbWUub3JpZ2luYWwsXG4gICAgICAgIGlzRHluYW1pYyA9IHBhcnRpYWwubmFtZS50eXBlID09PSAnU3ViRXhwcmVzc2lvbic7XG4gICAgaWYgKGlzRHluYW1pYykge1xuICAgICAgdGhpcy5hY2NlcHQocGFydGlhbC5uYW1lKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldHVwRnVsbE11c3RhY2hlUGFyYW1zKHBhcnRpYWwsIHByb2dyYW0sIHVuZGVmaW5lZCwgdHJ1ZSk7XG5cbiAgICBsZXQgaW5kZW50ID0gcGFydGlhbC5pbmRlbnQgfHwgJyc7XG4gICAgaWYgKHRoaXMub3B0aW9ucy5wcmV2ZW50SW5kZW50ICYmIGluZGVudCkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZENvbnRlbnQnLCBpbmRlbnQpO1xuICAgICAgaW5kZW50ID0gJyc7XG4gICAgfVxuXG4gICAgdGhpcy5vcGNvZGUoJ2ludm9rZVBhcnRpYWwnLCBpc0R5bmFtaWMsIHBhcnRpYWxOYW1lLCBpbmRlbnQpO1xuICAgIHRoaXMub3Bjb2RlKCdhcHBlbmQnKTtcbiAgfSxcbiAgUGFydGlhbEJsb2NrU3RhdGVtZW50OiBmdW5jdGlvbihwYXJ0aWFsQmxvY2spIHtcbiAgICB0aGlzLlBhcnRpYWxTdGF0ZW1lbnQocGFydGlhbEJsb2NrKTtcbiAgfSxcblxuICBNdXN0YWNoZVN0YXRlbWVudDogZnVuY3Rpb24obXVzdGFjaGUpIHtcbiAgICB0aGlzLlN1YkV4cHJlc3Npb24obXVzdGFjaGUpO1xuXG4gICAgaWYgKG11c3RhY2hlLmVzY2FwZWQgJiYgIXRoaXMub3B0aW9ucy5ub0VzY2FwZSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZEVzY2FwZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZCcpO1xuICAgIH1cbiAgfSxcbiAgRGVjb3JhdG9yKGRlY29yYXRvcikge1xuICAgIHRoaXMuRGVjb3JhdG9yQmxvY2soZGVjb3JhdG9yKTtcbiAgfSxcblxuXG4gIENvbnRlbnRTdGF0ZW1lbnQ6IGZ1bmN0aW9uKGNvbnRlbnQpIHtcbiAgICBpZiAoY29udGVudC52YWx1ZSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZENvbnRlbnQnLCBjb250ZW50LnZhbHVlKTtcbiAgICB9XG4gIH0sXG5cbiAgQ29tbWVudFN0YXRlbWVudDogZnVuY3Rpb24oKSB7fSxcblxuICBTdWJFeHByZXNzaW9uOiBmdW5jdGlvbihzZXhwcikge1xuICAgIHRyYW5zZm9ybUxpdGVyYWxUb1BhdGgoc2V4cHIpO1xuICAgIGxldCB0eXBlID0gdGhpcy5jbGFzc2lmeVNleHByKHNleHByKTtcblxuICAgIGlmICh0eXBlID09PSAnc2ltcGxlJykge1xuICAgICAgdGhpcy5zaW1wbGVTZXhwcihzZXhwcik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnaGVscGVyJykge1xuICAgICAgdGhpcy5oZWxwZXJTZXhwcihzZXhwcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYW1iaWd1b3VzU2V4cHIoc2V4cHIpO1xuICAgIH1cbiAgfSxcbiAgYW1iaWd1b3VzU2V4cHI6IGZ1bmN0aW9uKHNleHByLCBwcm9ncmFtLCBpbnZlcnNlKSB7XG4gICAgbGV0IHBhdGggPSBzZXhwci5wYXRoLFxuICAgICAgICBuYW1lID0gcGF0aC5wYXJ0c1swXSxcbiAgICAgICAgaXNCbG9jayA9IHByb2dyYW0gIT0gbnVsbCB8fCBpbnZlcnNlICE9IG51bGw7XG5cbiAgICB0aGlzLm9wY29kZSgnZ2V0Q29udGV4dCcsIHBhdGguZGVwdGgpO1xuXG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgcHJvZ3JhbSk7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgaW52ZXJzZSk7XG5cbiAgICBwYXRoLnN0cmljdCA9IHRydWU7XG4gICAgdGhpcy5hY2NlcHQocGF0aCk7XG5cbiAgICB0aGlzLm9wY29kZSgnaW52b2tlQW1iaWd1b3VzJywgbmFtZSwgaXNCbG9jayk7XG4gIH0sXG5cbiAgc2ltcGxlU2V4cHI6IGZ1bmN0aW9uKHNleHByKSB7XG4gICAgbGV0IHBhdGggPSBzZXhwci5wYXRoO1xuICAgIHBhdGguc3RyaWN0ID0gdHJ1ZTtcbiAgICB0aGlzLmFjY2VwdChwYXRoKTtcbiAgICB0aGlzLm9wY29kZSgncmVzb2x2ZVBvc3NpYmxlTGFtYmRhJyk7XG4gIH0sXG5cbiAgaGVscGVyU2V4cHI6IGZ1bmN0aW9uKHNleHByLCBwcm9ncmFtLCBpbnZlcnNlKSB7XG4gICAgbGV0IHBhcmFtcyA9IHRoaXMuc2V0dXBGdWxsTXVzdGFjaGVQYXJhbXMoc2V4cHIsIHByb2dyYW0sIGludmVyc2UpLFxuICAgICAgICBwYXRoID0gc2V4cHIucGF0aCxcbiAgICAgICAgbmFtZSA9IHBhdGgucGFydHNbMF07XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmtub3duSGVscGVyc1tuYW1lXSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2ludm9rZUtub3duSGVscGVyJywgcGFyYW1zLmxlbmd0aCwgbmFtZSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMua25vd25IZWxwZXJzT25seSkge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignWW91IHNwZWNpZmllZCBrbm93bkhlbHBlcnNPbmx5LCBidXQgdXNlZCB0aGUgdW5rbm93biBoZWxwZXIgJyArIG5hbWUsIHNleHByKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0aC5zdHJpY3QgPSB0cnVlO1xuICAgICAgcGF0aC5mYWxzeSA9IHRydWU7XG5cbiAgICAgIHRoaXMuYWNjZXB0KHBhdGgpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2ludm9rZUhlbHBlcicsIHBhcmFtcy5sZW5ndGgsIHBhdGgub3JpZ2luYWwsIEFTVC5oZWxwZXJzLnNpbXBsZUlkKHBhdGgpKTtcbiAgICB9XG4gIH0sXG5cbiAgUGF0aEV4cHJlc3Npb246IGZ1bmN0aW9uKHBhdGgpIHtcbiAgICB0aGlzLmFkZERlcHRoKHBhdGguZGVwdGgpO1xuICAgIHRoaXMub3Bjb2RlKCdnZXRDb250ZXh0JywgcGF0aC5kZXB0aCk7XG5cbiAgICBsZXQgbmFtZSA9IHBhdGgucGFydHNbMF0sXG4gICAgICAgIHNjb3BlZCA9IEFTVC5oZWxwZXJzLnNjb3BlZElkKHBhdGgpLFxuICAgICAgICBibG9ja1BhcmFtSWQgPSAhcGF0aC5kZXB0aCAmJiAhc2NvcGVkICYmIHRoaXMuYmxvY2tQYXJhbUluZGV4KG5hbWUpO1xuXG4gICAgaWYgKGJsb2NrUGFyYW1JZCkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2xvb2t1cEJsb2NrUGFyYW0nLCBibG9ja1BhcmFtSWQsIHBhdGgucGFydHMpO1xuICAgIH0gZWxzZSBpZiAoIW5hbWUpIHtcbiAgICAgIC8vIENvbnRleHQgcmVmZXJlbmNlLCBpLmUuIGB7e2ZvbyAufX1gIG9yIGB7e2ZvbyAuLn19YFxuICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hDb250ZXh0Jyk7XG4gICAgfSBlbHNlIGlmIChwYXRoLmRhdGEpIHtcbiAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gdHJ1ZTtcbiAgICAgIHRoaXMub3Bjb2RlKCdsb29rdXBEYXRhJywgcGF0aC5kZXB0aCwgcGF0aC5wYXJ0cywgcGF0aC5zdHJpY3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm9wY29kZSgnbG9va3VwT25Db250ZXh0JywgcGF0aC5wYXJ0cywgcGF0aC5mYWxzeSwgcGF0aC5zdHJpY3QsIHNjb3BlZCk7XG4gICAgfVxuICB9LFxuXG4gIFN0cmluZ0xpdGVyYWw6IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHRoaXMub3Bjb2RlKCdwdXNoU3RyaW5nJywgc3RyaW5nLnZhbHVlKTtcbiAgfSxcblxuICBOdW1iZXJMaXRlcmFsOiBmdW5jdGlvbihudW1iZXIpIHtcbiAgICB0aGlzLm9wY29kZSgncHVzaExpdGVyYWwnLCBudW1iZXIudmFsdWUpO1xuICB9LFxuXG4gIEJvb2xlYW5MaXRlcmFsOiBmdW5jdGlvbihib29sKSB7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgYm9vbC52YWx1ZSk7XG4gIH0sXG5cbiAgVW5kZWZpbmVkTGl0ZXJhbDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgJ3VuZGVmaW5lZCcpO1xuICB9LFxuXG4gIE51bGxMaXRlcmFsOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLm9wY29kZSgncHVzaExpdGVyYWwnLCAnbnVsbCcpO1xuICB9LFxuXG4gIEhhc2g6IGZ1bmN0aW9uKGhhc2gpIHtcbiAgICBsZXQgcGFpcnMgPSBoYXNoLnBhaXJzLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbCA9IHBhaXJzLmxlbmd0aDtcblxuICAgIHRoaXMub3Bjb2RlKCdwdXNoSGFzaCcpO1xuXG4gICAgZm9yICg7IGkgPCBsOyBpKyspIHtcbiAgICAgIHRoaXMucHVzaFBhcmFtKHBhaXJzW2ldLnZhbHVlKTtcbiAgICB9XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2Fzc2lnblRvSGFzaCcsIHBhaXJzW2ldLmtleSk7XG4gICAgfVxuICAgIHRoaXMub3Bjb2RlKCdwb3BIYXNoJyk7XG4gIH0sXG5cbiAgLy8gSEVMUEVSU1xuICBvcGNvZGU6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB0aGlzLm9wY29kZXMucHVzaCh7IG9wY29kZTogbmFtZSwgYXJnczogc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLCBsb2M6IHRoaXMuc291cmNlTm9kZVswXS5sb2MgfSk7XG4gIH0sXG5cbiAgYWRkRGVwdGg6IGZ1bmN0aW9uKGRlcHRoKSB7XG4gICAgaWYgKCFkZXB0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudXNlRGVwdGhzID0gdHJ1ZTtcbiAgfSxcblxuICBjbGFzc2lmeVNleHByOiBmdW5jdGlvbihzZXhwcikge1xuICAgIGxldCBpc1NpbXBsZSA9IEFTVC5oZWxwZXJzLnNpbXBsZUlkKHNleHByLnBhdGgpO1xuXG4gICAgbGV0IGlzQmxvY2tQYXJhbSA9IGlzU2ltcGxlICYmICEhdGhpcy5ibG9ja1BhcmFtSW5kZXgoc2V4cHIucGF0aC5wYXJ0c1swXSk7XG5cbiAgICAvLyBhIG11c3RhY2hlIGlzIGFuIGVsaWdpYmxlIGhlbHBlciBpZjpcbiAgICAvLyAqIGl0cyBpZCBpcyBzaW1wbGUgKGEgc2luZ2xlIHBhcnQsIG5vdCBgdGhpc2Agb3IgYC4uYClcbiAgICBsZXQgaXNIZWxwZXIgPSAhaXNCbG9ja1BhcmFtICYmIEFTVC5oZWxwZXJzLmhlbHBlckV4cHJlc3Npb24oc2V4cHIpO1xuXG4gICAgLy8gaWYgYSBtdXN0YWNoZSBpcyBhbiBlbGlnaWJsZSBoZWxwZXIgYnV0IG5vdCBhIGRlZmluaXRlXG4gICAgLy8gaGVscGVyLCBpdCBpcyBhbWJpZ3VvdXMsIGFuZCB3aWxsIGJlIHJlc29sdmVkIGluIGEgbGF0ZXJcbiAgICAvLyBwYXNzIG9yIGF0IHJ1bnRpbWUuXG4gICAgbGV0IGlzRWxpZ2libGUgPSAhaXNCbG9ja1BhcmFtICYmIChpc0hlbHBlciB8fCBpc1NpbXBsZSk7XG5cbiAgICAvLyBpZiBhbWJpZ3VvdXMsIHdlIGNhbiBwb3NzaWJseSByZXNvbHZlIHRoZSBhbWJpZ3VpdHkgbm93XG4gICAgLy8gQW4gZWxpZ2libGUgaGVscGVyIGlzIG9uZSB0aGF0IGRvZXMgbm90IGhhdmUgYSBjb21wbGV4IHBhdGgsIGkuZS4gYHRoaXMuZm9vYCwgYC4uL2Zvb2AgZXRjLlxuICAgIGlmIChpc0VsaWdpYmxlICYmICFpc0hlbHBlcikge1xuICAgICAgbGV0IG5hbWUgPSBzZXhwci5wYXRoLnBhcnRzWzBdLFxuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgICAgIGlmIChvcHRpb25zLmtub3duSGVscGVyc1tuYW1lXSkge1xuICAgICAgICBpc0hlbHBlciA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnMua25vd25IZWxwZXJzT25seSkge1xuICAgICAgICBpc0VsaWdpYmxlID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzSGVscGVyKSB7XG4gICAgICByZXR1cm4gJ2hlbHBlcic7XG4gICAgfSBlbHNlIGlmIChpc0VsaWdpYmxlKSB7XG4gICAgICByZXR1cm4gJ2FtYmlndW91cyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnc2ltcGxlJztcbiAgICB9XG4gIH0sXG5cbiAgcHVzaFBhcmFtczogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBwYXJhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICB0aGlzLnB1c2hQYXJhbShwYXJhbXNbaV0pO1xuICAgIH1cbiAgfSxcblxuICBwdXNoUGFyYW06IGZ1bmN0aW9uKHZhbCkge1xuICAgIGxldCB2YWx1ZSA9IHZhbC52YWx1ZSAhPSBudWxsID8gdmFsLnZhbHVlIDogdmFsLm9yaWdpbmFsIHx8ICcnO1xuXG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICBpZiAodmFsdWUucmVwbGFjZSkge1xuICAgICAgICB2YWx1ZSA9IHZhbHVlXG4gICAgICAgICAgICAucmVwbGFjZSgvXihcXC4/XFwuXFwvKSovZywgJycpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFwvL2csICcuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh2YWwuZGVwdGgpIHtcbiAgICAgICAgdGhpcy5hZGREZXB0aCh2YWwuZGVwdGgpO1xuICAgICAgfVxuICAgICAgdGhpcy5vcGNvZGUoJ2dldENvbnRleHQnLCB2YWwuZGVwdGggfHwgMCk7XG4gICAgICB0aGlzLm9wY29kZSgncHVzaFN0cmluZ1BhcmFtJywgdmFsdWUsIHZhbC50eXBlKTtcblxuICAgICAgaWYgKHZhbC50eXBlID09PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgICAgLy8gU3ViRXhwcmVzc2lvbnMgZ2V0IGV2YWx1YXRlZCBhbmQgcGFzc2VkIGluXG4gICAgICAgIC8vIGluIHN0cmluZyBwYXJhbXMgbW9kZS5cbiAgICAgICAgdGhpcy5hY2NlcHQodmFsKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgICAgbGV0IGJsb2NrUGFyYW1JbmRleDtcbiAgICAgICAgaWYgKHZhbC5wYXJ0cyAmJiAhQVNULmhlbHBlcnMuc2NvcGVkSWQodmFsKSAmJiAhdmFsLmRlcHRoKSB7XG4gICAgICAgICAgIGJsb2NrUGFyYW1JbmRleCA9IHRoaXMuYmxvY2tQYXJhbUluZGV4KHZhbC5wYXJ0c1swXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJsb2NrUGFyYW1JbmRleCkge1xuICAgICAgICAgIGxldCBibG9ja1BhcmFtQ2hpbGQgPSB2YWwucGFydHMuc2xpY2UoMSkuam9pbignLicpO1xuICAgICAgICAgIHRoaXMub3Bjb2RlKCdwdXNoSWQnLCAnQmxvY2tQYXJhbScsIGJsb2NrUGFyYW1JbmRleCwgYmxvY2tQYXJhbUNoaWxkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWx1ZSA9IHZhbC5vcmlnaW5hbCB8fCB2YWx1ZTtcbiAgICAgICAgICBpZiAodmFsdWUucmVwbGFjZSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9edGhpcyg/OlxcLnwkKS8sICcnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9eXFwuXFwvLywgJycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL15cXC4kLywgJycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMub3Bjb2RlKCdwdXNoSWQnLCB2YWwudHlwZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmFjY2VwdCh2YWwpO1xuICAgIH1cbiAgfSxcblxuICBzZXR1cEZ1bGxNdXN0YWNoZVBhcmFtczogZnVuY3Rpb24oc2V4cHIsIHByb2dyYW0sIGludmVyc2UsIG9taXRFbXB0eSkge1xuICAgIGxldCBwYXJhbXMgPSBzZXhwci5wYXJhbXM7XG4gICAgdGhpcy5wdXNoUGFyYW1zKHBhcmFtcyk7XG5cbiAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBwcm9ncmFtKTtcbiAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBpbnZlcnNlKTtcblxuICAgIGlmIChzZXhwci5oYXNoKSB7XG4gICAgICB0aGlzLmFjY2VwdChzZXhwci5oYXNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGNvZGUoJ2VtcHR5SGFzaCcsIG9taXRFbXB0eSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmFtcztcbiAgfSxcblxuICBibG9ja1BhcmFtSW5kZXg6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBmb3IgKGxldCBkZXB0aCA9IDAsIGxlbiA9IHRoaXMub3B0aW9ucy5ibG9ja1BhcmFtcy5sZW5ndGg7IGRlcHRoIDwgbGVuOyBkZXB0aCsrKSB7XG4gICAgICBsZXQgYmxvY2tQYXJhbXMgPSB0aGlzLm9wdGlvbnMuYmxvY2tQYXJhbXNbZGVwdGhdLFxuICAgICAgICAgIHBhcmFtID0gYmxvY2tQYXJhbXMgJiYgaW5kZXhPZihibG9ja1BhcmFtcywgbmFtZSk7XG4gICAgICBpZiAoYmxvY2tQYXJhbXMgJiYgcGFyYW0gPj0gMCkge1xuICAgICAgICByZXR1cm4gW2RlcHRoLCBwYXJhbV07XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gcHJlY29tcGlsZShpbnB1dCwgb3B0aW9ucywgZW52KSB7XG4gIGlmIChpbnB1dCA9PSBudWxsIHx8ICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnICYmIGlucHV0LnR5cGUgIT09ICdQcm9ncmFtJykpIHtcbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdZb3UgbXVzdCBwYXNzIGEgc3RyaW5nIG9yIEhhbmRsZWJhcnMgQVNUIHRvIEhhbmRsZWJhcnMucHJlY29tcGlsZS4gWW91IHBhc3NlZCAnICsgaW5wdXQpO1xuICB9XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGlmICghKCdkYXRhJyBpbiBvcHRpb25zKSkge1xuICAgIG9wdGlvbnMuZGF0YSA9IHRydWU7XG4gIH1cbiAgaWYgKG9wdGlvbnMuY29tcGF0KSB7XG4gICAgb3B0aW9ucy51c2VEZXB0aHMgPSB0cnVlO1xuICB9XG5cbiAgbGV0IGFzdCA9IGVudi5wYXJzZShpbnB1dCwgb3B0aW9ucyksXG4gICAgICBlbnZpcm9ubWVudCA9IG5ldyBlbnYuQ29tcGlsZXIoKS5jb21waWxlKGFzdCwgb3B0aW9ucyk7XG4gIHJldHVybiBuZXcgZW52LkphdmFTY3JpcHRDb21waWxlcigpLmNvbXBpbGUoZW52aXJvbm1lbnQsIG9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZShpbnB1dCwgb3B0aW9ucyA9IHt9LCBlbnYpIHtcbiAgaWYgKGlucHV0ID09IG51bGwgfHwgKHR5cGVvZiBpbnB1dCAhPT0gJ3N0cmluZycgJiYgaW5wdXQudHlwZSAhPT0gJ1Byb2dyYW0nKSkge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1lvdSBtdXN0IHBhc3MgYSBzdHJpbmcgb3IgSGFuZGxlYmFycyBBU1QgdG8gSGFuZGxlYmFycy5jb21waWxlLiBZb3UgcGFzc2VkICcgKyBpbnB1dCk7XG4gIH1cblxuICBpZiAoISgnZGF0YScgaW4gb3B0aW9ucykpIHtcbiAgICBvcHRpb25zLmRhdGEgPSB0cnVlO1xuICB9XG4gIGlmIChvcHRpb25zLmNvbXBhdCkge1xuICAgIG9wdGlvbnMudXNlRGVwdGhzID0gdHJ1ZTtcbiAgfVxuXG4gIGxldCBjb21waWxlZDtcblxuICBmdW5jdGlvbiBjb21waWxlSW5wdXQoKSB7XG4gICAgbGV0IGFzdCA9IGVudi5wYXJzZShpbnB1dCwgb3B0aW9ucyksXG4gICAgICAgIGVudmlyb25tZW50ID0gbmV3IGVudi5Db21waWxlcigpLmNvbXBpbGUoYXN0LCBvcHRpb25zKSxcbiAgICAgICAgdGVtcGxhdGVTcGVjID0gbmV3IGVudi5KYXZhU2NyaXB0Q29tcGlsZXIoKS5jb21waWxlKGVudmlyb25tZW50LCBvcHRpb25zLCB1bmRlZmluZWQsIHRydWUpO1xuICAgIHJldHVybiBlbnYudGVtcGxhdGUodGVtcGxhdGVTcGVjKTtcbiAgfVxuXG4gIC8vIFRlbXBsYXRlIGlzIG9ubHkgY29tcGlsZWQgb24gZmlyc3QgdXNlIGFuZCBjYWNoZWQgYWZ0ZXIgdGhhdCBwb2ludC5cbiAgZnVuY3Rpb24gcmV0KGNvbnRleHQsIGV4ZWNPcHRpb25zKSB7XG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgY29tcGlsZWQgPSBjb21waWxlSW5wdXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBpbGVkLmNhbGwodGhpcywgY29udGV4dCwgZXhlY09wdGlvbnMpO1xuICB9XG4gIHJldC5fc2V0dXAgPSBmdW5jdGlvbihzZXR1cE9wdGlvbnMpIHtcbiAgICBpZiAoIWNvbXBpbGVkKSB7XG4gICAgICBjb21waWxlZCA9IGNvbXBpbGVJbnB1dCgpO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGlsZWQuX3NldHVwKHNldHVwT3B0aW9ucyk7XG4gIH07XG4gIHJldC5fY2hpbGQgPSBmdW5jdGlvbihpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgY29tcGlsZWQgPSBjb21waWxlSW5wdXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBpbGVkLl9jaGlsZChpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgfTtcbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gYXJnRXF1YWxzKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChpc0FycmF5KGEpICYmIGlzQXJyYXkoYikgJiYgYS5sZW5ndGggPT09IGIubGVuZ3RoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIWFyZ0VxdWFscyhhW2ldLCBiW2ldKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybUxpdGVyYWxUb1BhdGgoc2V4cHIpIHtcbiAgaWYgKCFzZXhwci5wYXRoLnBhcnRzKSB7XG4gICAgbGV0IGxpdGVyYWwgPSBzZXhwci5wYXRoO1xuICAgIC8vIENhc3RpbmcgdG8gc3RyaW5nIGhlcmUgdG8gbWFrZSBmYWxzZSBhbmQgMCBsaXRlcmFsIHZhbHVlcyBwbGF5IG5pY2VseSB3aXRoIHRoZSByZXN0XG4gICAgLy8gb2YgdGhlIHN5c3RlbS5cbiAgICBzZXhwci5wYXRoID0ge1xuICAgICAgdHlwZTogJ1BhdGhFeHByZXNzaW9uJyxcbiAgICAgIGRhdGE6IGZhbHNlLFxuICAgICAgZGVwdGg6IDAsXG4gICAgICBwYXJ0czogW2xpdGVyYWwub3JpZ2luYWwgKyAnJ10sXG4gICAgICBvcmlnaW5hbDogbGl0ZXJhbC5vcmlnaW5hbCArICcnLFxuICAgICAgbG9jOiBsaXRlcmFsLmxvY1xuICAgIH07XG4gIH1cbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/helpers.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/helpers.js new file mode 100644 index 0000000..60bc119 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/helpers.js @@ -0,0 +1,230 @@ +define(['exports', '../exception'], function (exports, _exception) { + 'use strict'; + + exports.__esModule = true; + exports.SourceLocation = SourceLocation; + exports.id = id; + exports.stripFlags = stripFlags; + exports.stripComment = stripComment; + exports.preparePath = preparePath; + exports.prepareMustache = prepareMustache; + exports.prepareRawBlock = prepareRawBlock; + exports.prepareBlock = prepareBlock; + exports.prepareProgram = prepareProgram; + exports.preparePartialBlock = preparePartialBlock; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function validateClose(open, close) { + close = close.path ? close.path.original : close; + + if (open.path.original !== close) { + var errorNode = { loc: open.path.loc }; + + throw new _Exception['default'](open.path.original + " doesn't match " + close, errorNode); + } + } + + function SourceLocation(source, locInfo) { + this.source = source; + this.start = { + line: locInfo.first_line, + column: locInfo.first_column + }; + this.end = { + line: locInfo.last_line, + column: locInfo.last_column + }; + } + + function id(token) { + if (/^\[.*\]$/.test(token)) { + return token.substr(1, token.length - 2); + } else { + return token; + } + } + + function stripFlags(open, close) { + return { + open: open.charAt(2) === '~', + close: close.charAt(close.length - 3) === '~' + }; + } + + function stripComment(comment) { + return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, ''); + } + + function preparePath(data, parts, loc) { + loc = this.locInfo(loc); + + var original = data ? '@' : '', + dig = [], + depth = 0, + depthString = ''; + + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i].part, + + // If we have [] syntax then we do not treat path references as operators, + // i.e. foo.[this] resolves to approximately context.foo['this'] + isLiteral = parts[i].original !== part; + original += (parts[i].separator || '') + part; + + if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { + if (dig.length > 0) { + throw new _Exception['default']('Invalid path: ' + original, { loc: loc }); + } else if (part === '..') { + depth++; + depthString += '../'; + } + } else { + dig.push(part); + } + } + + return { + type: 'PathExpression', + data: data, + depth: depth, + parts: dig, + original: original, + loc: loc + }; + } + + function prepareMustache(path, params, hash, open, strip, locInfo) { + // Must use charAt to support IE pre-10 + var escapeFlag = open.charAt(3) || open.charAt(2), + escaped = escapeFlag !== '{' && escapeFlag !== '&'; + + var decorator = /\*/.test(open); + return { + type: decorator ? 'Decorator' : 'MustacheStatement', + path: path, + params: params, + hash: hash, + escaped: escaped, + strip: strip, + loc: this.locInfo(locInfo) + }; + } + + function prepareRawBlock(openRawBlock, contents, close, locInfo) { + validateClose(openRawBlock, close); + + locInfo = this.locInfo(locInfo); + var program = { + type: 'Program', + body: contents, + strip: {}, + loc: locInfo + }; + + return { + type: 'BlockStatement', + path: openRawBlock.path, + params: openRawBlock.params, + hash: openRawBlock.hash, + program: program, + openStrip: {}, + inverseStrip: {}, + closeStrip: {}, + loc: locInfo + }; + } + + function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { + if (close && close.path) { + validateClose(openBlock, close); + } + + var decorator = /\*/.test(openBlock.open); + + program.blockParams = openBlock.blockParams; + + var inverse = undefined, + inverseStrip = undefined; + + if (inverseAndProgram) { + if (decorator) { + throw new _Exception['default']('Unexpected inverse block on decorator', inverseAndProgram); + } + + if (inverseAndProgram.chain) { + inverseAndProgram.program.body[0].closeStrip = close.strip; + } + + inverseStrip = inverseAndProgram.strip; + inverse = inverseAndProgram.program; + } + + if (inverted) { + inverted = inverse; + inverse = program; + program = inverted; + } + + return { + type: decorator ? 'DecoratorBlock' : 'BlockStatement', + path: openBlock.path, + params: openBlock.params, + hash: openBlock.hash, + program: program, + inverse: inverse, + openStrip: openBlock.strip, + inverseStrip: inverseStrip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; + } + + function prepareProgram(statements, loc) { + if (!loc && statements.length) { + var firstLoc = statements[0].loc, + lastLoc = statements[statements.length - 1].loc; + + /* istanbul ignore else */ + if (firstLoc && lastLoc) { + loc = { + source: firstLoc.source, + start: { + line: firstLoc.start.line, + column: firstLoc.start.column + }, + end: { + line: lastLoc.end.line, + column: lastLoc.end.column + } + }; + } + } + + return { + type: 'Program', + body: statements, + strip: {}, + loc: loc + }; + } + + function preparePartialBlock(open, program, close, locInfo) { + validateClose(open, close); + + return { + type: 'PartialBlockStatement', + name: open.path, + params: open.params, + hash: open.hash, + program: program, + openStrip: open.strip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxXQUFTLGFBQWEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO0FBQ2xDLFNBQUssR0FBRyxLQUFLLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQzs7QUFFakQsUUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsS0FBSyxLQUFLLEVBQUU7QUFDaEMsVUFBSSxTQUFTLEdBQUcsRUFBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUMsQ0FBQzs7QUFFckMsWUFBTSwwQkFBYyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7S0FDaEY7R0FDRjs7QUFFTSxXQUFTLGNBQWMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFO0FBQzlDLFFBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQ3JCLFFBQUksQ0FBQyxLQUFLLEdBQUc7QUFDWCxVQUFJLEVBQUUsT0FBTyxDQUFDLFVBQVU7QUFDeEIsWUFBTSxFQUFFLE9BQU8sQ0FBQyxZQUFZO0tBQzdCLENBQUM7QUFDRixRQUFJLENBQUMsR0FBRyxHQUFHO0FBQ1QsVUFBSSxFQUFFLE9BQU8sQ0FBQyxTQUFTO0FBQ3ZCLFlBQU0sRUFBRSxPQUFPLENBQUMsV0FBVztLQUM1QixDQUFDO0dBQ0g7O0FBRU0sV0FBUyxFQUFFLENBQUMsS0FBSyxFQUFFO0FBQ3hCLFFBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUMxQixhQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7S0FDMUMsTUFBTTtBQUNMLGFB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InNvdXJjZXNDb250ZW50IjpbImltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi4vZXhjZXB0aW9uJztcblxuZnVuY3Rpb24gdmFsaWRhdGVDbG9zZShvcGVuLCBjbG9zZSkge1xuICBjbG9zZSA9IGNsb3NlLnBhdGggPyBjbG9zZS5wYXRoLm9yaWdpbmFsIDogY2xvc2U7XG5cbiAgaWYgKG9wZW4ucGF0aC5vcmlnaW5hbCAhPT0gY2xvc2UpIHtcbiAgICBsZXQgZXJyb3JOb2RlID0ge2xvYzogb3Blbi5wYXRoLmxvY307XG5cbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKG9wZW4ucGF0aC5vcmlnaW5hbCArIFwiIGRvZXNuJ3QgbWF0Y2ggXCIgKyBjbG9zZSwgZXJyb3JOb2RlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gU291cmNlTG9jYXRpb24oc291cmNlLCBsb2NJbmZvKSB7XG4gIHRoaXMuc291cmNlID0gc291cmNlO1xuICB0aGlzLnN0YXJ0ID0ge1xuICAgIGxpbmU6IGxvY0luZm8uZmlyc3RfbGluZSxcbiAgICBjb2x1bW46IGxvY0luZm8uZmlyc3RfY29sdW1uXG4gIH07XG4gIHRoaXMuZW5kID0ge1xuICAgIGxpbmU6IGxvY0luZm8ubGFzdF9saW5lLFxuICAgIGNvbHVtbjogbG9jSW5mby5sYXN0X2NvbHVtblxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaWQodG9rZW4pIHtcbiAgaWYgKC9eXFxbLipcXF0kLy50ZXN0KHRva2VuKSkge1xuICAgIHJldHVybiB0b2tlbi5zdWJzdHIoMSwgdG9rZW4ubGVuZ3RoIC0gMik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcEZsYWdzKG9wZW4sIGNsb3NlKSB7XG4gIHJldHVybiB7XG4gICAgb3Blbjogb3Blbi5jaGFyQXQoMikgPT09ICd+JyxcbiAgICBjbG9zZTogY2xvc2UuY2hhckF0KGNsb3NlLmxlbmd0aCAtIDMpID09PSAnfidcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmlwQ29tbWVudChjb21tZW50KSB7XG4gIHJldHVybiBjb21tZW50LnJlcGxhY2UoL15cXHtcXHt+P1xcIS0/LT8vLCAnJylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvLT8tP34/XFx9XFx9JC8sICcnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVQYXRoKGRhdGEsIHBhcnRzLCBsb2MpIHtcbiAgbG9jID0gdGhpcy5sb2NJbmZvKGxvYyk7XG5cbiAgbGV0IG9yaWdpbmFsID0gZGF0YSA/ICdAJyA6ICcnLFxuICAgICAgZGlnID0gW10sXG4gICAgICBkZXB0aCA9IDAsXG4gICAgICBkZXB0aFN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwLCBsID0gcGFydHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgbGV0IHBhcnQgPSBwYXJ0c1tpXS5wYXJ0LFxuICAgICAgICAvLyBJZiB3ZSBoYXZlIFtdIHN5bnRheCB0aGVuIHdlIGRvIG5vdCB0cmVhdCBwYXRoIHJlZmVyZW5jZXMgYXMgb3BlcmF0b3JzLFxuICAgICAgICAvLyBpLmUuIGZvby5bdGhpc10gcmVzb2x2ZXMgdG8gYXBwcm94aW1hdGVseSBjb250ZXh0LmZvb1sndGhpcyddXG4gICAgICAgIGlzTGl0ZXJhbCA9IHBhcnRzW2ldLm9yaWdpbmFsICE9PSBwYXJ0O1xuICAgIG9yaWdpbmFsICs9IChwYXJ0c1tpXS5zZXBhcmF0b3IgfHwgJycpICsgcGFydDtcblxuICAgIGlmICghaXNMaXRlcmFsICYmIChwYXJ0ID09PSAnLi4nIHx8IHBhcnQgPT09ICcuJyB8fCBwYXJ0ID09PSAndGhpcycpKSB7XG4gICAgICBpZiAoZGlnLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignSW52YWxpZCBwYXRoOiAnICsgb3JpZ2luYWwsIHtsb2N9KTtcbiAgICAgIH0gZWxzZSBpZiAocGFydCA9PT0gJy4uJykge1xuICAgICAgICBkZXB0aCsrO1xuICAgICAgICBkZXB0aFN0cmluZyArPSAnLi4vJztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZGlnLnB1c2gocGFydCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnUGF0aEV4cHJlc3Npb24nLFxuICAgIGRhdGEsXG4gICAgZGVwdGgsXG4gICAgcGFydHM6IGRpZyxcbiAgICBvcmlnaW5hbCxcbiAgICBsb2NcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVNdXN0YWNoZShwYXRoLCBwYXJhbXMsIGhhc2gsIG9wZW4sIHN0cmlwLCBsb2NJbmZvKSB7XG4gIC8vIE11c3QgdXNlIGNoYXJBdCB0byBzdXBwb3J0IElFIHByZS0xMFxuICBsZXQgZXNjYXBlRmxhZyA9IG9wZW4uY2hhckF0KDMpIHx8IG9wZW4uY2hhckF0KDIpLFxuICAgICAgZXNjYXBlZCA9IGVzY2FwZUZsYWcgIT09ICd7JyAmJiBlc2NhcGVGbGFnICE9PSAnJic7XG5cbiAgbGV0IGRlY29yYXRvciA9ICgvXFwqLy50ZXN0KG9wZW4pKTtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBkZWNvcmF0b3IgPyAnRGVjb3JhdG9yJyA6ICdNdXN0YWNoZVN0YXRlbWVudCcsXG4gICAgcGF0aCxcbiAgICBwYXJhbXMsXG4gICAgaGFzaCxcbiAgICBlc2NhcGVkLFxuICAgIHN0cmlwLFxuICAgIGxvYzogdGhpcy5sb2NJbmZvKGxvY0luZm8pXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmVwYXJlUmF3QmxvY2sob3BlblJhd0Jsb2NrLCBjb250ZW50cywgY2xvc2UsIGxvY0luZm8pIHtcbiAgdmFsaWRhdGVDbG9zZShvcGVuUmF3QmxvY2ssIGNsb3NlKTtcblxuICBsb2NJbmZvID0gdGhpcy5sb2NJbmZvKGxvY0luZm8pO1xuICBsZXQgcHJvZ3JhbSA9IHtcbiAgICB0eXBlOiAnUHJvZ3JhbScsXG4gICAgYm9keTogY29udGVudHMsXG4gICAgc3RyaXA6IHt9LFxuICAgIGxvYzogbG9jSW5mb1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0Jsb2NrU3RhdGVtZW50JyxcbiAgICBwYXRoOiBvcGVuUmF3QmxvY2sucGF0aCxcbiAgICBwYXJhbXM6IG9wZW5SYXdCbG9jay5wYXJhbXMsXG4gICAgaGFzaDogb3BlblJhd0Jsb2NrLmhhc2gsXG4gICAgcHJvZ3JhbSxcbiAgICBvcGVuU3RyaXA6IHt9LFxuICAgIGludmVyc2VTdHJpcDoge30sXG4gICAgY2xvc2VTdHJpcDoge30sXG4gICAgbG9jOiBsb2NJbmZvXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmVwYXJlQmxvY2sob3BlbkJsb2NrLCBwcm9ncmFtLCBpbnZlcnNlQW5kUHJvZ3JhbSwgY2xvc2UsIGludmVydGVkLCBsb2NJbmZvKSB7XG4gIGlmIChjbG9zZSAmJiBjbG9zZS5wYXRoKSB7XG4gICAgdmFsaWRhdGVDbG9zZShvcGVuQmxvY2ssIGNsb3NlKTtcbiAgfVxuXG4gIGxldCBkZWNvcmF0b3IgPSAoL1xcKi8udGVzdChvcGVuQmxvY2sub3BlbikpO1xuXG4gIHByb2dyYW0uYmxvY2tQYXJhbXMgPSBvcGVuQmxvY2suYmxvY2tQYXJhbXM7XG5cbiAgbGV0IGludmVyc2UsXG4gICAgICBpbnZlcnNlU3RyaXA7XG5cbiAgaWYgKGludmVyc2VBbmRQcm9ncmFtKSB7XG4gICAgaWYgKGRlY29yYXRvcikge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVW5leHBlY3RlZCBpbnZlcnNlIGJsb2NrIG9uIGRlY29yYXRvcicsIGludmVyc2VBbmRQcm9ncmFtKTtcbiAgICB9XG5cbiAgICBpZiAoaW52ZXJzZUFuZFByb2dyYW0uY2hhaW4pIHtcbiAgICAgIGludmVyc2VBbmRQcm9ncmFtLnByb2dyYW0uYm9keVswXS5jbG9zZVN0cmlwID0gY2xvc2Uuc3RyaXA7XG4gICAgfVxuXG4gICAgaW52ZXJzZVN0cmlwID0gaW52ZXJzZUFuZFByb2dyYW0uc3RyaXA7XG4gICAgaW52ZXJzZSA9IGludmVyc2VBbmRQcm9ncmFtLnByb2dyYW07XG4gIH1cblxuICBpZiAoaW52ZXJ0ZWQpIHtcbiAgICBpbnZlcnRlZCA9IGludmVyc2U7XG4gICAgaW52ZXJzZSA9IHByb2dyYW07XG4gICAgcHJvZ3JhbSA9IGludmVydGVkO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBkZWNvcmF0b3IgPyAnRGVjb3JhdG9yQmxvY2snIDogJ0Jsb2NrU3RhdGVtZW50JyxcbiAgICBwYXRoOiBvcGVuQmxvY2sucGF0aCxcbiAgICBwYXJhbXM6IG9wZW5CbG9jay5wYXJhbXMsXG4gICAgaGFzaDogb3BlbkJsb2NrLmhhc2gsXG4gICAgcHJvZ3JhbSxcbiAgICBpbnZlcnNlLFxuICAgIG9wZW5TdHJpcDogb3BlbkJsb2NrLnN0cmlwLFxuICAgIGludmVyc2VTdHJpcCxcbiAgICBjbG9zZVN0cmlwOiBjbG9zZSAmJiBjbG9zZS5zdHJpcCxcbiAgICBsb2M6IHRoaXMubG9jSW5mbyhsb2NJbmZvKVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZVByb2dyYW0oc3RhdGVtZW50cywgbG9jKSB7XG4gIGlmICghbG9jICYmIHN0YXRlbWVudHMubGVuZ3RoKSB7XG4gICAgY29uc3QgZmlyc3RMb2MgPSBzdGF0ZW1lbnRzWzBdLmxvYyxcbiAgICAgICAgICBsYXN0TG9jID0gc3RhdGVtZW50c1tzdGF0ZW1lbnRzLmxlbmd0aCAtIDFdLmxvYztcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKGZpcnN0TG9jICYmIGxhc3RMb2MpIHtcbiAgICAgIGxvYyA9IHtcbiAgICAgICAgc291cmNlOiBmaXJzdExvYy5zb3VyY2UsXG4gICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgbGluZTogZmlyc3RMb2Muc3RhcnQubGluZSxcbiAgICAgICAgICBjb2x1bW46IGZpcnN0TG9jLnN0YXJ0LmNvbHVtblxuICAgICAgICB9LFxuICAgICAgICBlbmQ6IHtcbiAgICAgICAgICBsaW5lOiBsYXN0TG9jLmVuZC5saW5lLFxuICAgICAgICAgIGNvbHVtbjogbGFzdExvYy5lbmQuY29sdW1uXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnUHJvZ3JhbScsXG4gICAgYm9keTogc3RhdGVtZW50cyxcbiAgICBzdHJpcDoge30sXG4gICAgbG9jOiBsb2NcbiAgfTtcbn1cblxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZVBhcnRpYWxCbG9jayhvcGVuLCBwcm9ncmFtLCBjbG9zZSwgbG9jSW5mbykge1xuICB2YWxpZGF0ZUNsb3NlKG9wZW4sIGNsb3NlKTtcblxuICByZXR1cm4ge1xuICAgIHR5cGU6ICdQYXJ0aWFsQmxvY2tTdGF0ZW1lbnQnLFxuICAgIG5hbWU6IG9wZW4ucGF0aCxcbiAgICBwYXJhbXM6IG9wZW4ucGFyYW1zLFxuICAgIGhhc2g6IG9wZW4uaGFzaCxcbiAgICBwcm9ncmFtLFxuICAgIG9wZW5TdHJpcDogb3Blbi5zdHJpcCxcbiAgICBjbG9zZVN0cmlwOiBjbG9zZSAmJiBjbG9zZS5zdHJpcCxcbiAgICBsb2M6IHRoaXMubG9jSW5mbyhsb2NJbmZvKVxuICB9O1xufVxuXG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/javascript-compiler.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/javascript-compiler.js new file mode 100644 index 0000000..8d6165e --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/javascript-compiler.js @@ -0,0 +1,1120 @@ +define(['exports', 'module', '../base', '../exception', '../utils', './code-gen'], function (exports, module, _base, _exception, _utils, _codeGen) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _CodeGen = _interopRequireDefault(_codeGen); + + function Literal(value) { + this.value = value; + } + + function JavaScriptCompiler() {} + + JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function nameLookup(parent, name /* , type*/) { + if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + return [parent, '.', name]; + } else { + return [parent, '[', JSON.stringify(name), ']']; + } + }, + depthedLookup: function depthedLookup(name) { + return [this.aliasable('container.lookup'), '(depths, "', name, '")']; + }, + + compilerInfo: function compilerInfo() { + var revision = _base.COMPILER_REVISION, + versions = _base.REVISION_CHANGES[revision]; + return [revision, versions]; + }, + + appendToBuffer: function appendToBuffer(source, location, explicit) { + // Force a source as this simplifies the merge logic. + if (!_utils.isArray(source)) { + source = [source]; + } + source = this.source.wrap(source, location); + + if (this.environment.isSimple) { + return ['return ', source, ';']; + } else if (explicit) { + // This is a case where the buffer operation occurs as a child of another + // construct, generally braces. We have to explicitly output these buffer + // operations to ensure that the emitted code goes in the correct location. + return ['buffer += ', source, ';']; + } else { + source.appendToBuffer = true; + return source; + } + }, + + initializeBuffer: function initializeBuffer() { + return this.quotedString(''); + }, + // END PUBLIC API + + compile: function compile(environment, options, context, asObject) { + this.environment = environment; + this.options = options; + this.stringParams = this.options.stringParams; + this.trackIds = this.options.trackIds; + this.precompile = !asObject; + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + decorators: [], + programs: [], + environments: [] + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.aliases = {}; + this.registers = { list: [] }; + this.hashes = []; + this.compileStack = []; + this.inlineStack = []; + this.blockParams = []; + + this.compileChildren(environment, options); + + this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; + this.useBlockParams = this.useBlockParams || environment.useBlockParams; + + var opcodes = environment.opcodes, + opcode = undefined, + firstLoc = undefined, + i = undefined, + l = undefined; + + for (i = 0, l = opcodes.length; i < l; i++) { + opcode = opcodes[i]; + + this.source.currentLocation = opcode.loc; + firstLoc = firstLoc || opcode.loc; + this[opcode.opcode].apply(this, opcode.args); + } + + // Flush any trailing content that might be pending. + this.source.currentLocation = firstLoc; + this.pushSource(''); + + /* istanbul ignore next */ + if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { + throw new _Exception['default']('Compile completed with content left on stack'); + } + + if (!this.decorators.isEmpty()) { + this.useDecorators = true; + + this.decorators.prepend('var decorators = container.decorators;\n'); + this.decorators.push('return fn;'); + + if (asObject) { + this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); + } else { + this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); + this.decorators.push('}\n'); + this.decorators = this.decorators.merge(); + } + } else { + this.decorators = undefined; + } + + var fn = this.createFunctionContext(asObject); + if (!this.isChild) { + var ret = { + compiler: this.compilerInfo(), + main: fn + }; + + if (this.decorators) { + ret.main_d = this.decorators; // eslint-disable-line camelcase + ret.useDecorators = true; + } + + var _context = this.context; + var programs = _context.programs; + var decorators = _context.decorators; + + for (i = 0, l = programs.length; i < l; i++) { + if (programs[i]) { + ret[i] = programs[i]; + if (decorators[i]) { + ret[i + '_d'] = decorators[i]; + ret.useDecorators = true; + } + } + } + + if (this.environment.usePartial) { + ret.usePartial = true; + } + if (this.options.data) { + ret.useData = true; + } + if (this.useDepths) { + ret.useDepths = true; + } + if (this.useBlockParams) { + ret.useBlockParams = true; + } + if (this.options.compat) { + ret.compat = true; + } + + if (!asObject) { + ret.compiler = JSON.stringify(ret.compiler); + + this.source.currentLocation = { start: { line: 1, column: 0 } }; + ret = this.objectLiteral(ret); + + if (options.srcName) { + ret = ret.toStringWithSourceMap({ file: options.destName }); + ret.map = ret.map && ret.map.toString(); + } else { + ret = ret.toString(); + } + } else { + ret.compilerOptions = this.options; + } + + return ret; + } else { + return fn; + } + }, + + preamble: function preamble() { + // track the last context pushed into place to allow skipping the + // getContext opcode when it would be a noop + this.lastContext = 0; + this.source = new _CodeGen['default'](this.options.srcName); + this.decorators = new _CodeGen['default'](this.options.srcName); + }, + + createFunctionContext: function createFunctionContext(asObject) { + var varDeclarations = ''; + + var locals = this.stackVars.concat(this.registers.list); + if (locals.length > 0) { + varDeclarations += ', ' + locals.join(', '); + } + + // Generate minimizer alias mappings + // + // When using true SourceNodes, this will update all references to the given alias + // as the source nodes are reused in situ. For the non-source node compilation mode, + // aliases will not be used, but this case is already being run on the client and + // we aren't concern about minimizing the template size. + var aliasCount = 0; + for (var alias in this.aliases) { + // eslint-disable-line guard-for-in + var node = this.aliases[alias]; + + if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { + varDeclarations += ', alias' + ++aliasCount + '=' + alias; + node.children[0] = 'alias' + aliasCount; + } + } + + var params = ['container', 'depth0', 'helpers', 'partials', 'data']; + + if (this.useBlockParams || this.useDepths) { + params.push('blockParams'); + } + if (this.useDepths) { + params.push('depths'); + } + + // Perform a second pass over the output to merge content when possible + var source = this.mergeSource(varDeclarations); + + if (asObject) { + params.push(source); + + return Function.apply(this, params); + } else { + return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); + } + }, + mergeSource: function mergeSource(varDeclarations) { + var isSimple = this.environment.isSimple, + appendOnly = !this.forceBuffer, + appendFirst = undefined, + sourceSeen = undefined, + bufferStart = undefined, + bufferEnd = undefined; + this.source.each(function (line) { + if (line.appendToBuffer) { + if (bufferStart) { + line.prepend(' + '); + } else { + bufferStart = line; + } + bufferEnd = line; + } else { + if (bufferStart) { + if (!sourceSeen) { + appendFirst = true; + } else { + bufferStart.prepend('buffer += '); + } + bufferEnd.add(';'); + bufferStart = bufferEnd = undefined; + } + + sourceSeen = true; + if (!isSimple) { + appendOnly = false; + } + } + }); + + if (appendOnly) { + if (bufferStart) { + bufferStart.prepend('return '); + bufferEnd.add(';'); + } else if (!sourceSeen) { + this.source.push('return "";'); + } + } else { + varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); + + if (bufferStart) { + bufferStart.prepend('return buffer + '); + bufferEnd.add(';'); + } else { + this.source.push('return buffer;'); + } + } + + if (varDeclarations) { + this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); + } + + return this.source.merge(); + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function blockValue(name) { + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs(name, 0, params); + + var blockName = this.popStack(); + params.splice(1, 0, blockName); + + this.push(this.source.functionCall(blockHelperMissing, 'call', params)); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function ambiguousBlockValue() { + // We're being a bit cheeky and reusing the options value from the prior exec + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs('', 0, params, true); + + this.flushInline(); + + var current = this.topStack(); + params.splice(1, 0, current); + + this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function appendContent(content) { + if (this.pendingContent) { + content = this.pendingContent + content; + } else { + this.pendingLocation = this.source.currentLocation; + } + + this.pendingContent = content; + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function append() { + if (this.isInline()) { + this.replaceStack(function (current) { + return [' != null ? ', current, ' : ""']; + }); + + this.pushSource(this.appendToBuffer(this.popStack())); + } else { + var local = this.popStack(); + this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); + if (this.environment.isSimple) { + this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); + } + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function appendEscaped() { + this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function getContext(depth) { + this.lastContext = depth; + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function pushContext() { + this.pushStackLiteral(this.contextName(this.lastContext)); + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) { + var i = 0; + + if (!scoped && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.push(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); + } + + this.resolvePath('context', parts, i, falsy, strict); + }, + + // [lookupBlockParam] + // + // On stack, before: ... + // On stack, after: blockParam[name], ... + // + // Looks up the value of `parts` on the given block param and pushes + // it onto the stack. + lookupBlockParam: function lookupBlockParam(blockParamId, parts) { + this.useBlockParams = true; + + this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); + this.resolvePath('context', parts, 1); + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data, ... + // + // Push the data lookup operator + lookupData: function lookupData(depth, parts, strict) { + if (!depth) { + this.pushStackLiteral('data'); + } else { + this.pushStackLiteral('container.data(data, ' + depth + ')'); + } + + this.resolvePath('data', parts, 0, true, strict); + }, + + resolvePath: function resolvePath(type, parts, i, falsy, strict) { + // istanbul ignore next + + var _this = this; + + if (this.options.strict || this.options.assumeObjects) { + this.push(strictLookup(this.options.strict && strict, this, parts, type)); + return; + } + + var len = parts.length; + for (; i < len; i++) { + /* eslint-disable no-loop-func */ + this.replaceStack(function (current) { + var lookup = _this.nameLookup(current, parts[i], type); + // We want to ensure that zero and false are handled properly if the context (falsy flag) + // needs to have the special handling for these values. + if (!falsy) { + return [' != null ? ', lookup, ' : ', current]; + } else { + // Otherwise we can use generic falsy handling + return [' && ', lookup]; + } + }); + /* eslint-enable no-loop-func */ + } + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function resolvePossibleLambda() { + this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function pushStringParam(string, type) { + this.pushContext(); + this.pushString(type); + + // If it's a subexpression, the string result + // will be pushed after this opcode. + if (type !== 'SubExpression') { + if (typeof string === 'string') { + this.pushString(string); + } else { + this.pushStackLiteral(string); + } + } + }, + + emptyHash: function emptyHash(omitEmpty) { + if (this.trackIds) { + this.push('{}'); // hashIds + } + if (this.stringParams) { + this.push('{}'); // hashContexts + this.push('{}'); // hashTypes + } + this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); + }, + pushHash: function pushHash() { + if (this.hash) { + this.hashes.push(this.hash); + } + this.hash = { values: [], types: [], contexts: [], ids: [] }; + }, + popHash: function popHash() { + var hash = this.hash; + this.hash = this.hashes.pop(); + + if (this.trackIds) { + this.push(this.objectLiteral(hash.ids)); + } + if (this.stringParams) { + this.push(this.objectLiteral(hash.contexts)); + this.push(this.objectLiteral(hash.types)); + } + + this.push(this.objectLiteral(hash.values)); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function pushString(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function pushLiteral(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function pushProgram(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [registerDecorator] + // + // On stack, before: hash, program, params..., ... + // On stack, after: ... + // + // Pops off the decorator's parameters, invokes the decorator, + // and inserts the decorator into the decorators list. + registerDecorator: function registerDecorator(paramSize, name) { + var foundDecorator = this.nameLookup('decorators', name, 'decorator'), + options = this.setupHelperArgs(name, paramSize); + + this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']); + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function invokeHelper(paramSize, name, isSimple) { + var nonHelper = this.popStack(), + helper = this.setupHelper(paramSize, name), + simple = isSimple ? [helper.name, ' || '] : ''; + + var lookup = ['('].concat(simple, nonHelper); + if (!this.options.strict) { + lookup.push(' || ', this.aliasable('helpers.helperMissing')); + } + lookup.push(')'); + + this.push(this.source.functionCall(lookup, 'call', helper.callParams)); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function invokeKnownHelper(paramSize, name) { + var helper = this.setupHelper(paramSize, name); + this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function invokeAmbiguous(name, helperCall) { + this.useRegister('helper'); + + var nonHelper = this.popStack(); + + this.emptyHash(); + var helper = this.setupHelper(0, name, helperCall); + + var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + + var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; + if (!this.options.strict) { + lookup[0] = '(helper = '; + lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing')); + } + + this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function invokePartial(isDynamic, name, indent) { + var params = [], + options = this.setupParams(name, 1, params); + + if (isDynamic) { + name = this.popStack(); + delete options.name; + } + + if (indent) { + options.indent = JSON.stringify(indent); + } + options.helpers = 'helpers'; + options.partials = 'partials'; + options.decorators = 'container.decorators'; + + if (!isDynamic) { + params.unshift(this.nameLookup('partials', name, 'partial')); + } else { + params.unshift(name); + } + + if (this.options.compat) { + options.depths = 'depths'; + } + options = this.objectLiteral(options); + params.push(options); + + this.push(this.source.functionCall('container.invokePartial', '', params)); + }, + + // [assignToHash] + // + // On stack, before: value, ..., hash, ... + // On stack, after: ..., hash, ... + // + // Pops a value off the stack and assigns it to the current hash + assignToHash: function assignToHash(key) { + var value = this.popStack(), + context = undefined, + type = undefined, + id = undefined; + + if (this.trackIds) { + id = this.popStack(); + } + if (this.stringParams) { + type = this.popStack(); + context = this.popStack(); + } + + var hash = this.hash; + if (context) { + hash.contexts[key] = context; + } + if (type) { + hash.types[key] = type; + } + if (id) { + hash.ids[key] = id; + } + hash.values[key] = value; + }, + + pushId: function pushId(type, name, child) { + if (type === 'BlockParam') { + this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : '')); + } else if (type === 'PathExpression') { + this.pushString(name); + } else if (type === 'SubExpression') { + this.pushStackLiteral('true'); + } else { + this.pushStackLiteral('null'); + } + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function compileChildren(environment, options) { + var children = environment.children, + child = undefined, + compiler = undefined; + + for (var i = 0, l = children.length; i < l; i++) { + child = children[i]; + compiler = new this.compiler(); // eslint-disable-line new-cap + + var existing = this.matchExistingProgram(child); + + if (existing == null) { + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + var index = this.context.programs.length; + child.index = index; + child.name = 'program' + index; + this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); + this.context.decorators[index] = compiler.decorators; + this.context.environments[index] = child; + + this.useDepths = this.useDepths || compiler.useDepths; + this.useBlockParams = this.useBlockParams || compiler.useBlockParams; + child.useDepths = this.useDepths; + child.useBlockParams = this.useBlockParams; + } else { + child.index = existing.index; + child.name = 'program' + existing.index; + + this.useDepths = this.useDepths || existing.useDepths; + this.useBlockParams = this.useBlockParams || existing.useBlockParams; + } + } + }, + matchExistingProgram: function matchExistingProgram(child) { + for (var i = 0, len = this.context.environments.length; i < len; i++) { + var environment = this.context.environments[i]; + if (environment && environment.equals(child)) { + return environment; + } + } + }, + + programExpression: function programExpression(guid) { + var child = this.environment.children[guid], + programParams = [child.index, 'data', child.blockParams]; + + if (this.useBlockParams || this.useDepths) { + programParams.push('blockParams'); + } + if (this.useDepths) { + programParams.push('depths'); + } + + return 'container.program(' + programParams.join(', ') + ')'; + }, + + useRegister: function useRegister(name) { + if (!this.registers[name]) { + this.registers[name] = true; + this.registers.list.push(name); + } + }, + + push: function push(expr) { + if (!(expr instanceof Literal)) { + expr = this.source.wrap(expr); + } + + this.inlineStack.push(expr); + return expr; + }, + + pushStackLiteral: function pushStackLiteral(item) { + this.push(new Literal(item)); + }, + + pushSource: function pushSource(source) { + if (this.pendingContent) { + this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); + this.pendingContent = undefined; + } + + if (source) { + this.source.push(source); + } + }, + + replaceStack: function replaceStack(callback) { + var prefix = ['('], + stack = undefined, + createdStack = undefined, + usedLiteral = undefined; + + /* istanbul ignore next */ + if (!this.isInline()) { + throw new _Exception['default']('replaceStack on non-inline'); + } + + // We want to merge the inline statement into the replacement statement via ',' + var top = this.popStack(true); + + if (top instanceof Literal) { + // Literals do not need to be inlined + stack = [top.value]; + prefix = ['(', stack]; + usedLiteral = true; + } else { + // Get or create the current stack name for use by the inline + createdStack = true; + var _name = this.incrStack(); + + prefix = ['((', this.push(_name), ' = ', top, ')']; + stack = this.topStack(); + } + + var item = callback.call(this, stack); + + if (!usedLiteral) { + this.popStack(); + } + if (createdStack) { + this.stackSlot--; + } + this.push(prefix.concat(item, ')')); + }, + + incrStack: function incrStack() { + this.stackSlot++; + if (this.stackSlot > this.stackVars.length) { + this.stackVars.push('stack' + this.stackSlot); + } + return this.topStackName(); + }, + topStackName: function topStackName() { + return 'stack' + this.stackSlot; + }, + flushInline: function flushInline() { + var inlineStack = this.inlineStack; + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + /* istanbul ignore if */ + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + var stack = this.incrStack(); + this.pushSource([stack, ' = ', entry, ';']); + this.compileStack.push(stack); + } + } + }, + isInline: function isInline() { + return this.inlineStack.length; + }, + + popStack: function popStack(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && item instanceof Literal) { + return item.value; + } else { + if (!inline) { + /* istanbul ignore next */ + if (!this.stackSlot) { + throw new _Exception['default']('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function topStack() { + var stack = this.isInline() ? this.inlineStack : this.compileStack, + item = stack[stack.length - 1]; + + /* istanbul ignore if */ + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + contextName: function contextName(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + + quotedString: function quotedString(str) { + return this.source.quotedString(str); + }, + + objectLiteral: function objectLiteral(obj) { + return this.source.objectLiteral(obj); + }, + + aliasable: function aliasable(name) { + var ret = this.aliases[name]; + if (ret) { + ret.referenceCount++; + return ret; + } + + ret = this.aliases[name] = this.source.wrap(name); + ret.aliasable = true; + ret.referenceCount = 1; + + return ret; + }, + + setupHelper: function setupHelper(paramSize, name, blockHelper) { + var params = [], + paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); + var foundHelper = this.nameLookup('helpers', name, 'helper'), + callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : {}'); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: [callContext].concat(params) + }; + }, + + setupParams: function setupParams(helper, paramSize, params) { + var options = {}, + contexts = [], + types = [], + ids = [], + objectArgs = !params, + param = undefined; + + if (objectArgs) { + params = []; + } + + options.name = this.quotedString(helper); + options.hash = this.popStack(); + + if (this.trackIds) { + options.hashIds = this.popStack(); + } + if (this.stringParams) { + options.hashTypes = this.popStack(); + options.hashContexts = this.popStack(); + } + + var inverse = this.popStack(), + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + options.fn = program || 'container.noop'; + options.inverse = inverse || 'container.noop'; + } + + // The parameters go on to the stack in order (making sure that they are evaluated in order) + // so we need to pop them off the stack in reverse order + var i = paramSize; + while (i--) { + param = this.popStack(); + params[i] = param; + + if (this.trackIds) { + ids[i] = this.popStack(); + } + if (this.stringParams) { + types[i] = this.popStack(); + contexts[i] = this.popStack(); + } + } + + if (objectArgs) { + options.args = this.source.generateArray(params); + } + + if (this.trackIds) { + options.ids = this.source.generateArray(ids); + } + if (this.stringParams) { + options.types = this.source.generateArray(types); + options.contexts = this.source.generateArray(contexts); + } + + if (this.options.data) { + options.data = 'data'; + } + if (this.useBlockParams) { + options.blockParams = 'blockParams'; + } + return options; + }, + + setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) { + var options = this.setupParams(helper, paramSize, params); + options = this.objectLiteral(options); + if (useRegister) { + this.useRegister('options'); + params.push('options'); + return ['options=', options]; + } else if (params) { + params.push(options); + return ''; + } else { + return options; + } + } + }; + + (function () { + var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' '); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for (var i = 0, l = reservedWords.length; i < l; i++) { + compilerWords[reservedWords[i]] = true; + } + })(); + + JavaScriptCompiler.isValidJavaScriptVariableName = function (name) { + return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); + }; + + function strictLookup(requireTerminal, compiler, parts, type) { + var stack = compiler.popStack(), + i = 0, + len = parts.length; + if (requireTerminal) { + len--; + } + + for (; i < len; i++) { + stack = compiler.nameLookup(stack, parts[i], type); + } + + if (requireTerminal) { + return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')']; + } else { + return stack; + } + } + + module.exports = JavaScriptCompiler; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2phdmFzY3JpcHQtY29tcGlsZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFLQSxXQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUU7QUFDdEIsUUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7R0FDcEI7O0FBRUQsV0FBUyxrQkFBa0IsR0FBRyxFQUFFOztBQUVoQyxvQkFBa0IsQ0FBQyxTQUFTLEdBQUc7OztBQUc3QixjQUFVLEVBQUUsb0JBQVMsTUFBTSxFQUFFLElBQUksY0FBYTtBQUM1QyxVQUFJLGtCQUFrQixDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxFQUFFO0FBQzFELGVBQU8sQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO09BQzVCLE1BQU07QUFDTCxlQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO09BQ2pEO0tBQ0Y7QUFDRCxpQkFBYSxFQUFFLHVCQUFTLElBQUksRUFBRTtBQUM1QixhQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdkU7O0FBRUQsZ0JBQVksRUFBRSx3QkFBVztBQUN2QixVQUFNLFFBQVEsU0ExQlQsaUJBQWlCLEFBMEJZO1VBQzVCLFFBQVEsR0FBRyxNQTNCTyxnQkFBZ0IsQ0EyQk4sUUFBUSxDQUFDLENBQUM7QUFDNUMsYUFBTyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztLQUM3Qjs7QUFFRCxrQkFBYyxFQUFFLHdCQUFTLE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFOztBQUVuRCxVQUFJLENBQUMsT0EvQkQsT0FBTyxDQStCRSxNQUFNLENBQUMsRUFBRTtBQUNwQixjQUFNLEdBQUcs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LENBQUM7UUFDTCxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztBQUN2QixRQUFJLGVBQWUsRUFBRTtBQUNuQixTQUFHLEVBQUUsQ0FBQztLQUNQOztBQUVELFdBQU8sQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUNuQixXQUFLLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3BEOztBQUVELFFBQUksZUFBZSxFQUFFO0FBQ25CLGFBQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztLQUN6RyxNQUFNO0FBQ0wsYUFBTyxLQUFLLENBQUM7S0FDZDtHQUNGOzttQkFFYyxrQkFBa0IiLCJmaWxlIjoiamF2YXNjcmlwdC1jb21waWxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENPTVBJTEVSX1JFVklTSU9OLCBSRVZJU0lPTl9DSEFOR0VTIH0gZnJvbSAnLi4vYmFzZSc7XG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5pbXBvcnQge2lzQXJyYXl9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCBDb2RlR2VuIGZyb20gJy4vY29kZS1nZW4nO1xuXG5mdW5jdGlvbiBMaXRlcmFsKHZhbHVlKSB7XG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gSmF2YVNjcmlwdENvbXBpbGVyKCkge31cblxuSmF2YVNjcmlwdENvbXBpbGVyLnByb3RvdHlwZSA9IHtcbiAgLy8gUFVCTElDIEFQSTogWW91IGNhbiBvdmVycmlkZSB0aGVzZSBtZXRob2RzIGluIGEgc3ViY2xhc3MgdG8gcHJvdmlkZVxuICAvLyBhbHRlcm5hdGl2ZSBjb21waWxlZCBmb3JtcyBmb3IgbmFtZSBsb29rdXAgYW5kIGJ1ZmZlcmluZyBzZW1hbnRpY3NcbiAgbmFtZUxvb2t1cDogZnVuY3Rpb24ocGFyZW50LCBuYW1lLyogLCB0eXBlKi8pIHtcbiAgICBpZiAoSmF2YVNjcmlwdENvbXBpbGVyLmlzVmFsaWRKYXZhU2NyaXB0VmFyaWFibGVOYW1lKG5hbWUpKSB7XG4gICAgICByZXR1cm4gW3BhcmVudCwgJy4nLCBuYW1lXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtwYXJlbnQsICdbJywgSlNPTi5zdHJpbmdpZnkobmFtZSksICddJ107XG4gICAgfVxuICB9LFxuICBkZXB0aGVkTG9va3VwOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIFt0aGlzLmFsaWFzYWJsZSgnY29udGFpbmVyLmxvb2t1cCcpLCAnKGRlcHRocywgXCInLCBuYW1lLCAnXCIpJ107XG4gIH0sXG5cbiAgY29tcGlsZXJJbmZvOiBmdW5jdGlvbigpIHtcbiAgICBjb25zdCByZXZpc2lvbiA9IENPTVBJTEVSX1JFVklTSU9OLFxuICAgICAgICAgIHZlcnNpb25zID0gUkVWSVNJT05fQ0hBTkdFU1tyZXZpc2lvbl07XG4gICAgcmV0dXJuIFtyZXZpc2lvbiwgdmVyc2lvbnNdO1xuICB9LFxuXG4gIGFwcGVuZFRvQnVmZmVyOiBmdW5jdGlvbihzb3VyY2UsIGxvY2F0aW9uLCBleHBsaWNpdCkge1xuICAgIC8vIEZvcmNlIGEgc291cmNlIGFzIHRoaXMgc2ltcGxpZmllcyB0aGUgbWVyZ2UgbG9naWMuXG4gICAgaWYgKCFpc0FycmF5KHNvdXJjZSkpIHtcbiAgICAgIHNvdXJjZSA9IFtzb3VyY2VdO1xuICAgIH1cbiAgICBzb3VyY2UgPSB0aGlzLnNvdXJjZS53cmFwKHNvdXJjZSwgbG9jYXRpb24pO1xuXG4gICAgaWYgKHRoaXMuZW52aXJvbm1lbnQuaXNTaW1wbGUpIHtcbiAgICAgIHJldHVybiBbJ3JldHVybiAnLCBzb3VyY2UsICc7J107XG4gICAgfSBlbHNlIGlmIChleHBsaWNpdCkge1xuICAgICAgLy8gVGhpcyBpcyBhIGNhc2Ugd2hlcmUgdGhlIGJ1ZmZlciBvcGVyYXRpb24gb2NjdXJzIGFzIGEgY2hpbGQgb2YgYW5vdGhlclxuICAgICAgLy8gY29uc3RydWN0LCBnZW5lcmFsbHkgYnJhY2VzLiBXZSBoYXZlIHRvIGV4cGxpY2l0bHkgb3V0cHV0IHRoZXNlIGJ1ZmZlclxuICAgICAgLy8gb3BlcmF0aW9ucyB0byBlbnN1cmUgdGhhdCB0aGUgZW1pdHRlZCBjb2RlIGdvZXMgaW4gdGhlIGNvcnJlY3QgbG9jYXRpb24uXG4gICAgICByZXR1cm4gWydidWZmZXIgKz0gJywgc291cmNlLCAnOyddO1xuICAgIH0gZWxzZSB7XG4gICAgICBzb3VyY2UuYXBwZW5kVG9CdWZmZXIgPSB0cnVlO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG4gIH0sXG5cbiAgaW5pdGlhbGl6ZUJ1ZmZlcjogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucXVvdGVkU3RyaW5nKCcnKTtcbiAgfSxcbiAgLy8gRU5EIFBVQkxJQyBBUElcblxuICBjb21waWxlOiBmdW5jdGlvbihlbnZpcm9ubWVudCwgb3B0aW9ucywgY29udGV4dCwgYXNPYmplY3QpIHtcbiAgICB0aGlzLmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLnN0cmluZ1BhcmFtcyA9IHRoaXMub3B0aW9ucy5zdHJpbmdQYXJhbXM7XG4gICAgdGhpcy50cmFja0lkcyA9IHRoaXMub3B0aW9ucy50cmFja0lkcztcbiAgICB0aGlzLnByZWNvbXBpbGUgPSAhYXNPYmplY3Q7XG5cbiAgICB0aGlzLm5hbWUgPSB0aGlzLmVudmlyb25tZW50Lm5hbWU7XG4gICAgdGhpcy5pc0NoaWxkID0gISFjb250ZXh0O1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQgfHwge1xuICAgICAgZGVjb3JhdG9yczogW10sXG4gICAgICBwcm9ncmFtczogW10sXG4gICAgICBlbnZpcm9ubWVudHM6IFtdXG4gICAgfTtcblxuICAgIHRoaXMucHJlYW1ibGUoKTtcblxuICAgIHRoaXMuc3RhY2tTbG90ID0gMDtcbiAgICB0aGlzLnN0YWNrVmFycyA9IFtdO1xuICAgIHRoaXMuYWxpYXNlcyA9IHt9O1xuICAgIHRoaXMucmVnaXN0ZXJzID0geyBsaXN0OiBbXSB9O1xuICAgIHRoaXMuaGFzaGVzID0gW107XG4gICAgdGhpcy5jb21waWxlU3RhY2sgPSBbXTtcbiAgICB0aGlzLmlubGluZVN0YWNrID0gW107XG4gICAgdGhpcy5ibG9ja1BhcmFtcyA9IFtdO1xuXG4gICAgdGhpcy5jb21waWxlQ2hpbGRyZW4oZW52aXJvbm1lbnQsIG9wdGlvbnMpO1xuXG4gICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCBlbnZpcm9ubWVudC51c2VEZXB0aHMgfHwgZW52aXJvbm1lbnQudXNlRGVjb3JhdG9ycyB8fCB0aGlzLm9wdGlvbnMuY29tcGF0O1xuICAgIHRoaXMudXNlQmxvY2tQYXJhbXMgPSB0aGlzLnVzZUJsb2NrUGFyYW1zIHx8IGVudmlyb25tZW50LnVzZUJsb2NrUGFyYW1zO1xuXG4gICAgbGV0IG9wY29kZXMgPSBlbnZpcm9ubWVudC5vcGNvZGVzLFxuICAgICAgICBvcGNvZGUsXG4gICAgICAgIGZpcnN0TG9jLFxuICAgICAgICBpLFxuICAgICAgICBsO1xuXG4gICAgZm9yIChpID0gMCwgbCA9IG9wY29kZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICBvcGNvZGUgPSBvcGNvZGVzW2ldO1xuXG4gICAgICB0aGlzLnNvdXJjZS5jdXJyZW50TG9jYXRpb24gPSBvcGNvZGUubG9jO1xuICAgICAgZmlyc3RMb2MgPSBmaXJzdExvYyB8fCBvcGNvZGUubG9jO1xuICAgICAgdGhpc1tvcGNvZGUub3Bjb2RlXS5hcHBseSh0aGlzLCBvcGNvZGUuYXJncyk7XG4gICAgfVxuXG4gICAgLy8gRmx1c2ggYW55IHRyYWlsaW5nIGNvbnRlbnQgdGhhdCBtaWdodCBiZSBwZW5kaW5nLlxuICAgIHRoaXMuc291cmNlLmN1cnJlbnRMb2NhdGlvbiA9IGZpcnN0TG9jO1xuICAgIHRoaXMucHVzaFNvdXJjZSgnJyk7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICh0aGlzLnN0YWNrU2xvdCB8fCB0aGlzLmlubGluZVN0YWNrLmxlbmd0aCB8fCB0aGlzLmNvbXBpbGVTdGFjay5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0NvbXBpbGUgY29tcGxldGVkIHdpdGggY29udGVudCBsZWZ0IG9uIHN0YWNrJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmRlY29yYXRvcnMuaXNFbXB0eSgpKSB7XG4gICAgICB0aGlzLnVzZURlY29yYXRvcnMgPSB0cnVlO1xuXG4gICAgICB0aGlzLmRlY29yYXRvcnMucHJlcGVuZCgndmFyIGRlY29yYXRvcnMgPSBjb250YWluZXIuZGVjb3JhdG9ycztcXG4nKTtcbiAgICAgIHRoaXMuZGVjb3JhdG9ycy5wdXNoKCdyZXR1cm4gZm47Jyk7XG5cbiAgICAgIGlmIChhc09iamVjdCkge1xuICAgICAgICB0aGlzLmRlY29yYXRvcnMgPSBGdW5jdGlvbi5hcHBseSh0aGlzLCBbJ2ZuJywgJ3Byb3BzJywgJ2NvbnRhaW5lcicsICdkZXB0aDAnLCAnZGF0YScsICdibG9ja1BhcmFtcycsICdkZXB0aHMnLCB0aGlzLmRlY29yYXRvcnMubWVyZ2UoKV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzLnByZXBlbmQoJ2Z1bmN0aW9uKGZuLCBwcm9wcywgY29udGFpbmVyLCBkZXB0aDAsIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcXG4nKTtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzLnB1c2goJ31cXG4nKTtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzID0gdGhpcy5kZWNvcmF0b3JzLm1lcmdlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVjb3JhdG9ycyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBsZXQgZm4gPSB0aGlzLmNyZWF0ZUZ1bmN0aW9uQ29udGV4dChhc09iamVjdCk7XG4gICAgaWYgKCF0aGlzLmlzQ2hpbGQpIHtcbiAgICAgIGxldCByZXQgPSB7XG4gICAgICAgIGNvbXBpbGVyOiB0aGlzLmNvbXBpbGVySW5mbygpLFxuICAgICAgICBtYWluOiBmblxuICAgICAgfTtcblxuICAgICAgaWYgKHRoaXMuZGVjb3JhdG9ycykge1xuICAgICAgICByZXQubWFpbl9kID0gdGhpcy5kZWNvcmF0b3JzOyAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY2FtZWxjYXNlXG4gICAgICAgIHJldC51c2VEZWNvcmF0b3JzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgbGV0IHtwcm9ncmFtcywgZGVjb3JhdG9yc30gPSB0aGlzLmNvbnRleHQ7XG4gICAgICBmb3IgKGkgPSAwLCBsID0gcHJvZ3JhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIGlmIChwcm9ncmFtc1tpXSkge1xuICAgICAgICAgIHJldFtpXSA9IHByb2dyYW1zW2ldO1xuICAgICAgICAgIGlmIChkZWNvcmF0b3JzW2ldKSB7XG4gICAgICAgICAgICByZXRbaSArICdfZCddID0gZGVjb3JhdG9yc1tpXTtcbiAgICAgICAgICAgIHJldC51c2VEZWNvcmF0b3JzID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQudXNlUGFydGlhbCkge1xuICAgICAgICByZXQudXNlUGFydGlhbCA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmRhdGEpIHtcbiAgICAgICAgcmV0LnVzZURhdGEgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudXNlRGVwdGhzKSB7XG4gICAgICAgIHJldC51c2VEZXB0aHMgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudXNlQmxvY2tQYXJhbXMpIHtcbiAgICAgICAgcmV0LnVzZUJsb2NrUGFyYW1zID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuY29tcGF0KSB7XG4gICAgICAgIHJldC5jb21wYXQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWFzT2JqZWN0KSB7XG4gICAgICAgIHJldC5jb21waWxlciA9IEpTT04uc3RyaW5naWZ5KHJldC5jb21waWxlcik7XG5cbiAgICAgICAgdGhpcy5zb3VyY2UuY3VycmVudExvY2F0aW9uID0ge3N0YXJ0OiB7bGluZTogMSwgY29sdW1uOiAwfX07XG4gICAgICAgIHJldCA9IHRoaXMub2JqZWN0TGl0ZXJhbChyZXQpO1xuXG4gICAgICAgIGlmIChvcHRpb25zLnNyY05hbWUpIHtcbiAgICAgICAgICByZXQgPSByZXQudG9TdHJpbmdXaXRoU291cmNlTWFwKHtmaWxlOiBvcHRpb25zLmRlc3ROYW1lfSk7XG4gICAgICAgICAgcmV0Lm1hcCA9IHJldC5tYXAgJiYgcmV0Lm1hcC50b1N0cmluZygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldCA9IHJldC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXQuY29tcGlsZXJPcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZm47XG4gICAgfVxuICB9LFxuXG4gIHByZWFtYmxlOiBmdW5jdGlvbigpIHtcbiAgICAvLyB0cmFjayB0aGUgbGFzdCBjb250ZXh0IHB1c2hlZCBpbnRvIHBsYWNlIHRvIGFsbG93IHNraXBwaW5nIHRoZVxuICAgIC8vIGdldENvbnRleHQgb3Bjb2RlIHdoZW4gaXQgd291bGQgYmUgYSBub29wXG4gICAgdGhpcy5sYXN0Q29udGV4dCA9IDA7XG4gICAgdGhpcy5zb3VyY2UgPSBuZXcgQ29kZUdlbih0aGlzLm9wdGlvbnMuc3JjTmFtZSk7XG4gICAgdGhpcy5kZWNvcmF0b3JzID0gbmV3IENvZGVHZW4odGhpcy5vcHRpb25zLnNyY05hbWUpO1xuICB9LFxuXG4gIGNyZWF0ZUZ1bmN0aW9uQ29udGV4dDogZnVuY3Rpb24oYXNPYmplY3QpIHtcbiAgICBsZXQgdmFyRGVjbGFyYXRpb25zID0gJyc7XG5cbiAgICBsZXQgbG9jYWxzID0gdGhpcy5zdGFja1ZhcnMuY29uY2F0KHRoaXMucmVnaXN0ZXJzLmxpc3QpO1xuICAgIGlmIChsb2NhbHMubGVuZ3RoID4gMCkge1xuICAgICAgdmFyRGVjbGFyYXRpb25zICs9ICcsICcgKyBsb2NhbHMuam9pbignLCAnKTtcbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZSBtaW5pbWl6ZXIgYWxpYXMgbWFwcGluZ3NcbiAgICAvL1xuICAgIC8vIFdoZW4gdXNpbmcgdHJ1ZSBTb3VyY2VOb2RlcywgdGhpcyB3aWxsIHVwZGF0ZSBhbGwgcmVmZXJlbmNlcyB0byB0aGUgZ2l2ZW4gYWxpYXNcbiAgICAvLyBhcyB0aGUgc291cmNlIG5vZGVzIGFyZSByZXVzZWQgaW4gc2l0dS4gRm9yIHRoZSBub24tc291cmNlIG5vZGUgY29tcGlsYXRpb24gbW9kZSxcbiAgICAvLyBhbGlhc2VzIHdpbGwgbm90IGJlIHVzZWQsIGJ1dCB0aGlzIGNhc2UgaXMgYWxyZWFkeSBiZWluZyBydW4gb24gdGhlIGNsaWVudCBhbmRcbiAgICAvLyB3ZSBhcmVuJ3QgY29uY2VybiBhYm91dCBtaW5pbWl6aW5nIHRoZSB0ZW1wbGF0ZSBzaXplLlxuICAgIGxldCBhbGlhc0NvdW50ID0gMDtcbiAgICBmb3IgKGxldCBhbGlhcyBpbiB0aGlzLmFsaWFzZXMpIHsgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBndWFyZC1mb3ItaW5cbiAgICAgIGxldCBub2RlID0gdGhpcy5hbGlhc2VzW2FsaWFzXTtcblxuICAgICAgaWYgKHRoaXMuYWxpYXNlcy5oYXNPd25Qcm9wZXJ0eShhbGlhcykgJiYgbm9kZS5jaGlsZHJlbiAmJiBub2RlLnJlZmVyZW5jZUNvdW50ID4gMSkge1xuICAgICAgICB2YXJEZWNsYXJhdGlvbnMgKz0gJywgYWxpYXMnICsgKCsrYWxpYXNDb3VudCkgKyAnPScgKyBhbGlhcztcbiAgICAgICAgbm9kZS5jaGlsZHJlblswXSA9ICdhbGlhcycgKyBhbGlhc0NvdW50O1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBwYXJhbXMgPSBbJ2NvbnRhaW5lcicsICdkZXB0aDAnLCAnaGVscGVycycsICdwYXJ0aWFscycsICdkYXRhJ107XG5cbiAgICBpZiAodGhpcy51c2VCbG9ja1BhcmFtcyB8fCB0aGlzLnVzZURlcHRocykge1xuICAgICAgcGFyYW1zLnB1c2goJ2Jsb2NrUGFyYW1zJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnVzZURlcHRocykge1xuICAgICAgcGFyYW1zLnB1c2goJ2RlcHRocycpO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gYSBzZWNvbmQgcGFzcyBvdmVyIHRoZSBvdXRwdXQgdG8gbWVyZ2UgY29udGVudCB3aGVuIHBvc3NpYmxlXG4gICAgbGV0IHNvdXJjZSA9IHRoaXMubWVyZ2VTb3VyY2UodmFyRGVjbGFyYXRpb25zKTtcblxuICAgIGlmIChhc09iamVjdCkge1xuICAgICAgcGFyYW1zLnB1c2goc291cmNlKTtcblxuICAgICAgcmV0dXJuIEZ1bmN0aW9uLmFwcGx5KHRoaXMsIHBhcmFtcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnNvdXJjZS53cmFwKFsnZnVuY3Rpb24oJywgcGFyYW1zLmpvaW4oJywnKSwgJykge1xcbiAgJywgc291cmNlLCAnfSddKTtcbiAgICB9XG4gIH0sXG4gIG1lcmdlU291cmNlOiBmdW5jdGlvbih2YXJEZWNsYXJhdGlvbnMpIHtcbiAgICBsZXQgaXNTaW1wbGUgPSB0aGlzLmVudmlyb25tZW50LmlzU2ltcGxlLFxuICAgICAgICBhcHBlbmRPbmx5ID0gIXRoaXMuZm9yY2VCdWZmZXIsXG4gICAgICAgIGFwcGVuZEZpcnN0LFxuXG4gICAgICAgIHNvdXJjZVNlZW4sXG4gICAgICAgIGJ1ZmZlclN0YXJ0LFxuICAgICAgICBidWZmZXJFbmQ7XG4gICAgdGhpcy5zb3VyY2UuZWFjaCgobGluZSkgPT4ge1xuICAgICAgaWYgKGxpbmUuYXBwZW5kVG9CdWZmZXIpIHtcbiAgICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgICAgbGluZS5wcmVwZW5kKCcgICsgJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVmZmVyU3RhcnQgPSBsaW5lO1xuICAgICAgICB9XG4gICAgICAgIGJ1ZmZlckVuZCA9IGxpbmU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoYnVmZmVyU3RhcnQpIHtcbiAgICAgICAgICBpZiAoIXNvdXJjZVNlZW4pIHtcbiAgICAgICAgICAgIGFwcGVuZEZpcnN0ID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZmVyU3RhcnQucHJlcGVuZCgnYnVmZmVyICs9ICcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBidWZmZXJFbmQuYWRkKCc7Jyk7XG4gICAgICAgICAgYnVmZmVyU3RhcnQgPSBidWZmZXJFbmQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBzb3VyY2VTZWVuID0gdHJ1ZTtcbiAgICAgICAgaWYgKCFpc1NpbXBsZSkge1xuICAgICAgICAgIGFwcGVuZE9ubHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG5cbiAgICBpZiAoYXBwZW5kT25seSkge1xuICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgIGJ1ZmZlclN0YXJ0LnByZXBlbmQoJ3JldHVybiAnKTtcbiAgICAgICAgYnVmZmVyRW5kLmFkZCgnOycpO1xuICAgICAgfSBlbHNlIGlmICghc291cmNlU2Vlbikge1xuICAgICAgICB0aGlzLnNvdXJjZS5wdXNoKCdyZXR1cm4gXCJcIjsnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyRGVjbGFyYXRpb25zICs9ICcsIGJ1ZmZlciA9ICcgKyAoYXBwZW5kRmlyc3QgPyAnJyA6IHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcigpKTtcblxuICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgIGJ1ZmZlclN0YXJ0LnByZXBlbmQoJ3JldHVybiBidWZmZXIgKyAnKTtcbiAgICAgICAgYnVmZmVyRW5kLmFkZCgnOycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zb3VyY2UucHVzaCgncmV0dXJuIGJ1ZmZlcjsnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodmFyRGVjbGFyYXRpb25zKSB7XG4gICAgICB0aGlzLnNvdXJjZS5wcmVwZW5kKCd2YXIgJyArIHZhckRlY2xhcmF0aW9ucy5zdWJzdHJpbmcoMikgKyAoYXBwZW5kRmlyc3QgPyAnJyA6ICc7XFxuJykpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNvdXJjZS5tZXJnZSgpO1xuICB9LFxuXG4gIC8vIFtibG9ja1ZhbHVlXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCB2YWx1ZVxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJldHVybiB2YWx1ZSBvZiBibG9ja0hlbHBlck1pc3NpbmdcbiAgLy9cbiAgLy8gVGhlIHB1cnBvc2Ugb2YgdGhpcyBvcGNvZGUgaXMgdG8gdGFrZSBhIGJsb2NrIG9mIHRoZSBmb3JtXG4gIC8vIGB7eyN0aGlzLmZvb319Li4ue3svdGhpcy5mb299fWAsIHJlc29sdmUgdGhlIHZhbHVlIG9mIGBmb29gLCBhbmRcbiAgLy8gcmVwbGFjZSBpdCBvbiB0aGUgc3RhY2sgd2l0aCB0aGUgcmVzdWx0IG9mIHByb3Blcmx5XG4gIC8vIGludm9raW5nIGJsb2NrSGVscGVyTWlzc2luZy5cbiAgYmxvY2tWYWx1ZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGxldCBibG9ja0hlbHBlck1pc3NpbmcgPSB0aGlzLmFsaWFzYWJsZSgnaGVscGVycy5ibG9ja0hlbHBlck1pc3NpbmcnKSxcbiAgICAgICAgcGFyYW1zID0gW3RoaXMuY29udGV4dE5hbWUoMCldO1xuICAgIHRoaXMuc2V0dXBIZWxwZXJBcmdzKG5hbWUsIDAsIHBhcmFtcyk7XG5cbiAgICBsZXQgYmxvY2tOYW1lID0gdGhpcy5wb3BTdGFjaygpO1xuICAgIHBhcmFtcy5zcGxpY2UoMSwgMCwgYmxvY2tOYW1lKTtcblxuICAgIHRoaXMucHVzaCh0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwoYmxvY2tIZWxwZXJNaXNzaW5nLCAnY2FsbCcsIHBhcmFtcykpO1xuICB9LFxuXG4gIC8vIFthbWJpZ3VvdXNCbG9ja1ZhbHVlXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCB2YWx1ZVxuICAvLyBDb21waWxlciB2YWx1ZSwgYmVmb3JlOiBsYXN0SGVscGVyPXZhbHVlIG9mIGxhc3QgZm91bmQgaGVscGVyLCBpZiBhbnlcbiAgLy8gT24gc3RhY2ssIGFmdGVyLCBpZiBubyBsYXN0SGVscGVyOiBzYW1lIGFzIFtibG9ja1ZhbHVlXVxuICAvLyBPbiBzdGFjaywgYWZ0ZXIsIGlmIGxhc3RIZWxwZXI6IHZhbHVlXG4gIGFtYmlndW91c0Jsb2NrVmFsdWU6IGZ1bmN0aW9uKCkge1xuICAgIC8vIFdlJ3JlIGJlaW5nIGEgYml0IGNoZWVreSBhbmQgcmV1c2luZyB0aGUgb3B0aW9ucyB2YWx1ZSBmcm9tIHRoZSBwcmlvciBleGVjXG4gICAgbGV0IGJsb2NrSGVscGVyTWlzc2luZyA9IHRoaXMuYWxpYXNhYmxlKCdoZWxwZXJzLmJsb2NrSGVscGVyTWlzc2luZycpLFxuICAgICAgICBwYXJhbXMgPSBbdGhpcy5jb250ZXh0TmFtZSgwKV07XG4gICAgdGhpcy5zZXR1cEhlbHBlckFyZ3MoJycsIDAsIHBhcmFtcywgdHJ1ZSk7XG5cbiAgICB0aGlzLmZsdXNoSW5saW5lKCk7XG5cbiAgICBsZXQgY3VycmVudCA9IHRoaXMudG9wU3RhY2soKTtcbiAgICBwYXJhbXMuc3BsaWNlKDEsIDAsIGN1cnJlbnQpO1xuXG4gICAgdGhpcy5wdXNoU291cmNlKFtcbiAgICAgICAgJ2lmICghJywgdGhpcy5sYXN0SGVscGVyLCAnKSB7ICcsXG4gICAgICAgICAgY3VycmVudCwgJyA9ICcsIHRoaXMuc291cmNlLmZ1bmN0aW9uQ2FsbChibG9ja0hlbHBlck1pc3NpbmcsICdjYWxsJywgcGFyYW1zKSxcbiAgICAgICAgJ30nXSk7XG4gIH0sXG5cbiAgLy8gW2FwcGVuZENvbnRlbnRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBBcHBlbmRzIHRoZSBzdHJpbmcgdmFsdWUgb2YgYGNvbnRlbnRgIHRvIHRoZSBjdXJyZW50IGJ1ZmZlclxuICBhcHBlbmRDb250ZW50OiBmdW5jdGlvbihjb250ZW50KSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIGNvbnRlbnQgPSB0aGlzLnBlbmRpbmdDb250ZW50ICsgY29udGVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wZW5kaW5nTG9jYXRpb24gPSB0aGlzLnNvdXJjZS5jdXJyZW50TG9jYXRpb247XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nQ29udGVudCA9IGNvbnRlbnQ7XG4gIH0sXG5cbiAgLy8gW2FwcGVuZF1cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogdmFsdWUsIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBDb2VyY2VzIGB2YWx1ZWAgdG8gYSBTdHJpbmcgYW5kIGFwcGVuZHMgaXQgdG8gdGhlIGN1cnJlbnQgYnVmZmVyLlxuICAvL1xuICAvLyBJZiBgdmFsdWVgIGlzIHRydXRoeSwgb3IgMCwgaXQgaXMgY29lcmNlZCBpbnRvIGEgc3RyaW5nIGFuZCBhcHBlbmRlZFxuICAvLyBPdGhlcndpc2UsIHRoZSBlbXB0eSBzdHJpbmcgaXMgYXBwZW5kZWRcbiAgYXBwZW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5pc0lubGluZSgpKSB7XG4gICAgICB0aGlzLnJlcGxhY2VTdGFjaygoY3VycmVudCkgPT4gWycgIT0gbnVsbCA/ICcsIGN1cnJlbnQsICcgOiBcIlwiJ10pO1xuXG4gICAgICB0aGlzLnB1c2hTb3VyY2UodGhpcy5hcHBlbmRUb0J1ZmZlcih0aGlzLnBvcFN0YWNrKCkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGxvY2FsID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgdGhpcy5wdXNoU291cmNlKFsnaWYgKCcsIGxvY2FsLCAnICE9IG51bGwpIHsgJywgdGhpcy5hcHBlbmRUb0J1ZmZlcihsb2NhbCwgdW5kZWZpbmVkLCB0cnVlKSwgJyB9J10pO1xuICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQuaXNTaW1wbGUpIHtcbiAgICAgICAgdGhpcy5wdXNoU291cmNlKFsnZWxzZSB7ICcsIHRoaXMuYXBwZW5kVG9CdWZmZXIoXCInJ1wiLCB1bmRlZmluZWQsIHRydWUpLCAnIH0nXSk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8vIFthcHBlbmRFc2NhcGVkXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiB2YWx1ZSwgLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogLi4uXG4gIC8vXG4gIC8vIEVzY2FwZSBgdmFsdWVgIGFuZCBhcHBlbmQgaXQgdG8gdGhlIGJ1ZmZlclxuICBhcHBlbmRFc2NhcGVkOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2hTb3VyY2UodGhpcy5hcHBlbmRUb0J1ZmZlcihcbiAgICAgICAgW3RoaXMuYWxpYXNhYmxlKCdjb250YWluZXIuZXNjYXBlRXhwcmVzc2lvbicpLCAnKCcsIHRoaXMucG9wU3RhY2soKSwgJyknXSkpO1xuICB9LFxuXG4gIC8vIFtnZXRDb250ZXh0XVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiAuLi5cbiAgLy8gQ29tcGlsZXIgdmFsdWUsIGFmdGVyOiBsYXN0Q29udGV4dD1kZXB0aFxuICAvL1xuICAvLyBTZXQgdGhlIHZhbHVlIG9mIHRoZSBgbGFzdENvbnRleHRgIGNvbXBpbGVyIHZhbHVlIHRvIHRoZSBkZXB0aFxuICBnZXRDb250ZXh0OiBmdW5jdGlvbihkZXB0aCkge1xuICAgIHRoaXMubGFzdENvbnRleHQgPSBkZXB0aDtcbiAgfSxcblxuICAvLyBbcHVzaENvbnRleHRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IGN1cnJlbnRDb250ZXh0LCAuLi5cbiAgLy9cbiAgLy8gUHVzaGVzIHRoZSB2YWx1ZSBvZiB0aGUgY3VycmVudCBjb250ZXh0IG9udG8gdGhlIHN0YWNrLlxuICBwdXNoQ29udGV4dDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHRoaXMuY29udGV4dE5hbWUodGhpcy5sYXN0Q29udGV4dCkpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBPbkNvbnRleHRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IGN1cnJlbnRDb250ZXh0W25hbWVdLCAuLi5cbiAgLy9cbiAgLy8gTG9va3MgdXAgdGhlIHZhbHVlIG9mIGBuYW1lYCBvbiB0aGUgY3VycmVudCBjb250ZXh0IGFuZCBwdXNoZXNcbiAgLy8gaXQgb250byB0aGUgc3RhY2suXG4gIGxvb2t1cE9uQ29udGV4dDogZnVuY3Rpb24ocGFydHMsIGZhbHN5LCBzdHJpY3QsIHNjb3BlZCkge1xuICAgIGxldCBpID0gMDtcblxuICAgIGlmICghc2NvcGVkICYmIHRoaXMub3B0aW9ucy5jb21wYXQgJiYgIXRoaXMubGFzdENvbnRleHQpIHtcbiAgICAgIC8vIFRoZSBkZXB0aGVkIHF1ZXJ5IGlzIGV4cGVjdGVkIHRvIGhhbmRsZSB0aGUgdW5kZWZpbmVkIGxvZ2ljIGZvciB0aGUgcm9vdCBsZXZlbCB0aGF0XG4gICAgICAvLyBpcyBpbXBsZW1lbnRlZCBiZWxvdywgc28gd2UgZXZhbHVhdGUgdGhhdCBkaXJlY3RseSBpbiBjb21wYXQgbW9kZVxuICAgICAgdGhpcy5wdXNoKHRoaXMuZGVwdGhlZExvb2t1cChwYXJ0c1tpKytdKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaENvbnRleHQoKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlc29sdmVQYXRoKCdjb250ZXh0JywgcGFydHMsIGksIGZhbHN5LCBzdHJpY3QpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBCbG9ja1BhcmFtXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBibG9ja1BhcmFtW25hbWVdLCAuLi5cbiAgLy9cbiAgLy8gTG9va3MgdXAgdGhlIHZhbHVlIG9mIGBwYXJ0c2Agb24gdGhlIGdpdmVuIGJsb2NrIHBhcmFtIGFuZCBwdXNoZXNcbiAgLy8gaXQgb250byB0aGUgc3RhY2suXG4gIGxvb2t1cEJsb2NrUGFyYW06IGZ1bmN0aW9uKGJsb2NrUGFyYW1JZCwgcGFydHMpIHtcbiAgICB0aGlzLnVzZUJsb2NrUGFyYW1zID0gdHJ1ZTtcblxuICAgIHRoaXMucHVzaChbJ2Jsb2NrUGFyYW1zWycsIGJsb2NrUGFyYW1JZFswXSwgJ11bJywgYmxvY2tQYXJhbUlkWzFdLCAnXSddKTtcbiAgICB0aGlzLnJlc29sdmVQYXRoKCdjb250ZXh0JywgcGFydHMsIDEpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBEYXRhXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBkYXRhLCAuLi5cbiAgLy9cbiAgLy8gUHVzaCB0aGUgZGF0YSBsb29rdXAgb3BlcmF0b3JcbiAgbG9va3VwRGF0YTogZnVuY3Rpb24oZGVwdGgsIHBhcnRzLCBzdHJpY3QpIHtcbiAgICBpZiAoIWRlcHRoKSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwoJ2RhdGEnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKCdjb250YWluZXIuZGF0YShkYXRhLCAnICsgZGVwdGggKyAnKScpO1xuICAgIH1cblxuICAgIHRoaXMucmVzb2x2ZVBhdGgoJ2RhdGEnLCBwYXJ0cywgMCwgdHJ1ZSwgc3RyaWN0KTtcbiAgfSxcblxuICByZXNvbHZlUGF0aDogZnVuY3Rpb24odHlwZSwgcGFydHMsIGksIGZhbHN5LCBzdHJpY3QpIHtcbiAgICBpZiAodGhpcy5vcHRpb25zLnN0cmljdCB8fCB0aGlzLm9wdGlvbnMuYXNzdW1lT2JqZWN0cykge1xuICAgICAgdGhpcy5wdXNoKHN0cmljdExvb2t1cCh0aGlzLm9wdGlvbnMuc3RyaWN0ICYmIHN0cmljdCwgdGhpcywgcGFydHMsIHR5cGUpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgbGVuID0gcGFydHMubGVuZ3RoO1xuICAgIGZvciAoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWxvb3AtZnVuYyAqL1xuICAgICAgdGhpcy5yZXBsYWNlU3RhY2soKGN1cnJlbnQpID0+IHtcbiAgICAgICAgbGV0IGxvb2t1cCA9IHRoaXMubmFtZUxvb2t1cChjdXJyZW50LCBwYXJ0c1tpXSwgdHlwZSk7XG4gICAgICAgIC8vIFdlIHdhbnQgdG8gZW5zdXJlIHRoYXQgemVybyBhbmQgZmFsc2UgYXJlIGhhbmRsZWQgcHJvcGVybHkgaWYgdGhlIGNvbnRleHQgKGZhbHN5IGZsYWcpXG4gICAgICAgIC8vIG5lZWRzIHRvIGhhdmUgdGhlIHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRoZXNlIHZhbHVlcy5cbiAgICAgICAgaWYgKCFmYWxzeSkge1xuICAgICAgICAgIHJldHVybiBbJyAhPSBudWxsID8gJywgbG9va3VwLCAnIDogJywgY3VycmVudF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlIHdlIGNhbiB1c2UgZ2VuZXJpYyBmYWxzeSBoYW5kbGluZ1xuICAgICAgICAgIHJldHVybiBbJyAmJiAnLCBsb29rdXBdO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG4gICAgfVxuICB9LFxuXG4gIC8vIFtyZXNvbHZlUG9zc2libGVMYW1iZGFdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IHZhbHVlLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiByZXNvbHZlZCB2YWx1ZSwgLi4uXG4gIC8vXG4gIC8vIElmIHRoZSBgdmFsdWVgIGlzIGEgbGFtYmRhLCByZXBsYWNlIGl0IG9uIHRoZSBzdGFjayBieVxuICAvLyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBsYW1iZGFcbiAgcmVzb2x2ZVBvc3NpYmxlTGFtYmRhOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2goW3RoaXMuYWxpYXNhYmxlKCdjb250YWluZXIubGFtYmRhJyksICcoJywgdGhpcy5wb3BTdGFjaygpLCAnLCAnLCB0aGlzLmNvbnRleHROYW1lKDApLCAnKSddKTtcbiAgfSxcblxuICAvLyBbcHVzaFN0cmluZ1BhcmFtXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBzdHJpbmcsIGN1cnJlbnRDb250ZXh0LCAuLi5cbiAgLy9cbiAgLy8gVGhpcyBvcGNvZGUgaXMgZGVzaWduZWQgZm9yIHVzZSBpbiBzdHJpbmcgbW9kZSwgd2hpY2hcbiAgLy8gcHJvdmlkZXMgdGhlIHN0cmluZyB2YWx1ZSBvZiBhIHBhcmFtZXRlciBhbG9uZyB3aXRoIGl0c1xuICAvLyBkZXB0aCByYXRoZXIgdGhhbiByZXNvbHZpbmcgaXQgaW1tZWRpYXRlbHkuXG4gIHB1c2hTdHJpbmdQYXJhbTogZnVuY3Rpb24oc3RyaW5nLCB0eXBlKSB7XG4gICAgdGhpcy5wdXNoQ29udGV4dCgpO1xuICAgIHRoaXMucHVzaFN0cmluZyh0eXBlKTtcblxuICAgIC8vIElmIGl0J3MgYSBzdWJleHByZXNzaW9uLCB0aGUgc3RyaW5nIHJlc3VsdFxuICAgIC8vIHdpbGwgYmUgcHVzaGVkIGFmdGVyIHRoaXMgb3Bjb2RlLlxuICAgIGlmICh0eXBlICE9PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgIGlmICh0eXBlb2Ygc3RyaW5nID09PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLnB1c2hTdHJpbmcoc3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChzdHJpbmcpO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBlbXB0eUhhc2g6IGZ1bmN0aW9uKG9taXRFbXB0eSkge1xuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICB0aGlzLnB1c2goJ3t9Jyk7IC8vIGhhc2hJZHNcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0aGlzLnB1c2goJ3t9Jyk7IC8vIGhhc2hDb250ZXh0c1xuICAgICAgdGhpcy5wdXNoKCd7fScpOyAvLyBoYXNoVHlwZXNcbiAgICB9XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKG9taXRFbXB0eSA/ICd1bmRlZmluZWQnIDogJ3t9Jyk7XG4gIH0sXG4gIHB1c2hIYXNoOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5oYXNoKSB7XG4gICAgICB0aGlzLmhhc2hlcy5wdXNoKHRoaXMuaGFzaCk7XG4gICAgfVxuICAgIHRoaXMuaGFzaCA9IHt2YWx1ZXM6IFtdLCB0eXBlczogW10sIGNvbnRleHRzOiBbXSwgaWRzOiBbXX07XG4gIH0sXG4gIHBvcEhhc2g6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBoYXNoID0gdGhpcy5oYXNoO1xuICAgIHRoaXMuaGFzaCA9IHRoaXMuaGFzaGVzLnBvcCgpO1xuXG4gICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC5pZHMpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0aGlzLnB1c2godGhpcy5vYmplY3RMaXRlcmFsKGhhc2guY29udGV4dHMpKTtcbiAgICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC50eXBlcykpO1xuICAgIH1cblxuICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC52YWx1ZXMpKTtcbiAgfSxcblxuICAvLyBbcHVzaFN0cmluZ11cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogcXVvdGVkU3RyaW5nKHN0cmluZyksIC4uLlxuICAvL1xuICAvLyBQdXNoIGEgcXVvdGVkIHZlcnNpb24gb2YgYHN0cmluZ2Agb250byB0aGUgc3RhY2tcbiAgcHVzaFN0cmluZzogZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHRoaXMucXVvdGVkU3RyaW5nKHN0cmluZykpO1xuICB9LFxuXG4gIC8vIFtwdXNoTGl0ZXJhbF1cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogdmFsdWUsIC4uLlxuICAvL1xuICAvLyBQdXNoZXMgYSB2YWx1ZSBvbnRvIHRoZSBzdGFjay4gVGhpcyBvcGVyYXRpb24gcHJldmVudHNcbiAgLy8gdGhlIGNvbXBpbGVyIGZyb20gY3JlYXRpbmcgYSB0ZW1wb3JhcnkgdmFyaWFibGUgdG8gaG9sZFxuICAvLyBpdC5cbiAgcHVzaExpdGVyYWw6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHZhbHVlKTtcbiAgfSxcblxuICAvLyBbcHVzaFByb2dyYW1dXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHByb2dyYW0oZ3VpZCksIC4uLlxuICAvL1xuICAvLyBQdXNoIGEgcHJvZ3JhbSBleHByZXNzaW9uIG9udG8gdGhlIHN0YWNrLiBUaGlzIHRha2VzXG4gIC8vIGEgY29tcGlsZS10aW1lIGd1aWQgYW5kIGNvbnZlcnRzIGl0IGludG8gYSBydW50aW1lLWFjY2Vzc2libGVcbiAgLy8gZXhwcmVzc2lvbi5cbiAgcHVzaFByb2dyYW06IGZ1bmN0aW9uKGd1aWQpIHtcbiAgICBpZiAoZ3VpZCAhPSBudWxsKSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwodGhpcy5wcm9ncmFtRXhwcmVzc2lvbihndWlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChudWxsKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gW3JlZ2lzdGVyRGVjb3JhdG9yXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBQb3BzIG9mZiB0aGUgZGVjb3JhdG9yJ3MgcGFyYW1ldGVycywgaW52b2tlcyB0aGUgZGVjb3JhdG9yLFxuICAvLyBhbmQgaW5zZXJ0cyB0aGUgZGVjb3JhdG9yIGludG8gdGhlIGRlY29yYXRvcnMgbGlzdC5cbiAgcmVnaXN0ZXJEZWNvcmF0b3IocGFyYW1TaXplLCBuYW1lKSB7XG4gICAgbGV0IGZvdW5kRGVjb3JhdG9yID0gdGhpcy5uYW1lTG9va3VwKCdkZWNvcmF0b3JzJywgbmFtZSwgJ2RlY29yYXRvcicpLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5zZXR1cEhlbHBlckFyZ3MobmFtZSwgcGFyYW1TaXplKTtcblxuICAgIHRoaXMuZGVjb3JhdG9ycy5wdXNoKFtcbiAgICAgICdmbiA9ICcsXG4gICAgICB0aGlzLmRlY29yYXRvcnMuZnVuY3Rpb25DYWxsKGZvdW5kRGVjb3JhdG9yLCAnJywgWydmbicsICdwcm9wcycsICdjb250YWluZXInLCBvcHRpb25zXSksXG4gICAgICAnIHx8IGZuOydcbiAgICBdKTtcbiAgfSxcblxuICAvLyBbaW52b2tlSGVscGVyXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJlc3VsdCBvZiBoZWxwZXIgaW52b2NhdGlvblxuICAvL1xuICAvLyBQb3BzIG9mZiB0aGUgaGVscGVyJ3MgcGFyYW1ldGVycywgaW52b2tlcyB0aGUgaGVscGVyLFxuICAvLyBhbmQgcHVzaGVzIHRoZSBoZWxwZXIncyByZXR1cm4gdmFsdWUgb250byB0aGUgc3RhY2suXG4gIC8vXG4gIC8vIElmIHRoZSBoZWxwZXIgaXMgbm90IGZvdW5kLCBgaGVscGVyTWlzc2luZ2AgaXMgY2FsbGVkLlxuICBpbnZva2VIZWxwZXI6IGZ1bmN0aW9uKHBhcmFtU2l6ZSwgbmFtZSwgaXNTaW1wbGUpIHtcbiAgICBsZXQgbm9uSGVscGVyID0gdGhpcy5wb3BTdGFjaygpLFxuICAgICAgICBoZWxwZXIgPSB0aGlzLnNldHVwSGVscGVyKHBhcmFtU2l6ZSwgbmFtZSksXG4gICAgICAgIHNpbXBsZSA9IGlzU2ltcGxlID8gW2hlbHBlci5uYW1lLCAnIHx8ICddIDogJyc7XG5cbiAgICBsZXQgbG9va3VwID0gWycoJ10uY29uY2F0KHNpbXBsZSwgbm9uSGVscGVyKTtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5zdHJpY3QpIHtcbiAgICAgIGxvb2t1cC5wdXNoKCcgfHwgJywgdGhpcy5hbGlhc2FibGUoJ2hlbHBlcnMuaGVscGVyTWlzc2luZycpKTtcbiAgICB9XG4gICAgbG9va3VwLnB1c2goJyknKTtcblxuICAgIHRoaXMucHVzaCh0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwobG9va3VwLCAnY2FsbCcsIGhlbHBlci5jYWxsUGFyYW1zKSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZUtub3duSGVscGVyXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJlc3VsdCBvZiBoZWxwZXIgaW52b2NhdGlvblxuICAvL1xuICAvLyBUaGlzIG9wZXJhdGlvbiBpcyB1c2VkIHdoZW4gdGhlIGhlbHBlciBpcyBrbm93biB0byBleGlzdCxcbiAgLy8gc28gYSBgaGVscGVyTWlzc2luZ2AgZmFsbGJhY2sgaXMgbm90IHJlcXVpcmVkLlxuICBpbnZva2VLbm93bkhlbHBlcjogZnVuY3Rpb24ocGFyYW1TaXplLCBuYW1lKSB7XG4gICAgbGV0IGhlbHBlciA9IHRoaXMuc2V0dXBIZWxwZXIocGFyYW1TaXplLCBuYW1lKTtcbiAgICB0aGlzLnB1c2godGhpcy5zb3VyY2UuZnVuY3Rpb25DYWxsKGhlbHBlci5uYW1lLCAnY2FsbCcsIGhlbHBlci5jYWxsUGFyYW1zKSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZUFtYmlndW91c11cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogaGFzaCwgaW52ZXJzZSwgcHJvZ3JhbSwgcGFyYW1zLi4uLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiByZXN1bHQgb2YgZGlzYW1iaWd1YXRpb25cbiAgLy9cbiAgLy8gVGhpcyBvcGVyYXRpb24gaXMgdXNlZCB3aGVuIGFuIGV4cHJlc3Npb24gbGlrZSBge3tmb299fWBcbiAgLy8gaXMgcHJvdmlkZWQsIGJ1dCB3ZSBkb24ndCBrbm93IGF0IGNvbXBpbGUtdGltZSB3aGV0aGVyIGl0XG4gIC8vIGlzIGEgaGVscGVyIG9yIGEgcGF0aC5cbiAgLy9cbiAgLy8gVGhpcyBvcGVyYXRpb24gZW1pdHMgbW9yZSBjb2RlIHRoYW4gdGhlIG90aGVyIG9wdGlvbnMsXG4gIC8vIGFuZCBjYW4gYmUgYXZvaWRlZCBieSBwYXNzaW5nIHRoZSBga25vd25IZWxwZXJzYCBhbmRcbiAgLy8gYGtub3duSGVscGVyc09ubHlgIGZsYWdzIGF0IGNvbXBpbGUtdGltZS5cbiAgaW52b2tlQW1iaWd1b3VzOiBmdW5jdGlvbihuYW1lLCBoZWxwZXJDYWxsKSB7XG4gICAgdGhpcy51c2VSZWdpc3RlcignaGVscGVyJyk7XG5cbiAgICBsZXQgbm9uSGVscGVyID0gdGhpcy5wb3BTdGFjaygpO1xuXG4gICAgdGhpcy5lbXB0eUhhc2goKTtcbiAgICBsZXQgaGVscGVyID0gdGhpcy5zZXR1cEhlbHBlcigwLCBuYW1lLCBoZWxwZXJDYWxsKTtcblxuICAgIGxldCBoZWxwZXJOYW1lID0gdGhpcy5sYXN0SGVscGVyID0gdGhpcy5uYW1lTG9va3VwKCdoZWxwZXJzJywgbmFtZSwgJ2hlbHBlcicpO1xuXG4gICAgbGV0IGxvb2t1cCA9IFsnKCcsICcoaGVscGVyID0gJywgaGVscGVyTmFtZSwgJyB8fCAnLCBub25IZWxwZXIsICcpJ107XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICBsb29rdXBbMF0gPSAnKGhlbHBlciA9ICc7XG4gICAgICBsb29rdXAucHVzaChcbiAgICAgICAgJyAhPSBudWxsID8gaGVscGVyIDogJyxcbiAgICAgICAgdGhpcy5hbGlhc2FibGUoJ2hlbHBlcnMuaGVscGVyTWlzc2luZycpXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMucHVzaChbXG4gICAgICAgICcoJywgbG9va3VwLFxuICAgICAgICAoaGVscGVyLnBhcmFtc0luaXQgPyBbJyksKCcsIGhlbHBlci5wYXJhbXNJbml0XSA6IFtdKSwgJyksJyxcbiAgICAgICAgJyh0eXBlb2YgaGVscGVyID09PSAnLCB0aGlzLmFsaWFzYWJsZSgnXCJmdW5jdGlvblwiJyksICcgPyAnLFxuICAgICAgICB0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwoJ2hlbHBlcicsICdjYWxsJywgaGVscGVyLmNhbGxQYXJhbXMpLCAnIDogaGVscGVyKSknXG4gICAgXSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZVBhcnRpYWxdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IGNvbnRleHQsIC4uLlxuICAvLyBPbiBzdGFjayBhZnRlcjogcmVzdWx0IG9mIHBhcnRpYWwgaW52b2NhdGlvblxuICAvL1xuICAvLyBUaGlzIG9wZXJhdGlvbiBwb3BzIG9mZiBhIGNvbnRleHQsIGludm9rZXMgYSBwYXJ0aWFsIHdpdGggdGhhdCBjb250ZXh0LFxuICAvLyBhbmQgcHVzaGVzIHRoZSByZXN1bHQgb2YgdGhlIGludm9jYXRpb24gYmFjay5cbiAgaW52b2tlUGFydGlhbDogZnVuY3Rpb24oaXNEeW5hbWljLCBuYW1lLCBpbmRlbnQpIHtcbiAgICBsZXQgcGFyYW1zID0gW10sXG4gICAgICAgIG9wdGlvbnMgPSB0aGlzLnNldHVwUGFyYW1zKG5hbWUsIDEsIHBhcmFtcyk7XG5cbiAgICBpZiAoaXNEeW5hbWljKSB7XG4gICAgICBuYW1lID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgZGVsZXRlIG9wdGlvbnMubmFtZTtcbiAgICB9XG5cbiAgICBpZiAoaW5kZW50KSB7XG4gICAgICBvcHRpb25zLmluZGVudCA9IEpTT04uc3RyaW5naWZ5KGluZGVudCk7XG4gICAgfVxuICAgIG9wdGlvbnMuaGVscGVycyA9ICdoZWxwZXJzJztcbiAgICBvcHRpb25zLnBhcnRpYWxzID0gJ3BhcnRpYWxzJztcbiAgICBvcHRpb25zLmRlY29yYXRvcnMgPSAnY29udGFpbmVyLmRlY29yYXRvcnMnO1xuXG4gICAgaWYgKCFpc0R5bmFtaWMpIHtcbiAgICAgIHBhcmFtcy51bnNoaWZ0KHRoaXMubmFtZUxvb2t1cCgncGFydGlhbHMnLCBuYW1lLCAncGFydGlhbCcpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFyYW1zLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5jb21wYXQpIHtcbiAgICAgIG9wdGlvbnMuZGVwdGhzID0gJ2RlcHRocyc7XG4gICAgfVxuICAgIG9wdGlvbnMgPSB0aGlzLm9iamVjdExpdGVyYWwob3B0aW9ucyk7XG4gICAgcGFyYW1zLnB1c2gob3B0aW9ucyk7XG5cbiAgICB0aGlzLnB1c2godGhpcy5zb3VyY2UuZnVuY3Rpb25DYWxsKCdjb250YWluZXIuaW52b2tlUGFydGlhbCcsICcnLCBwYXJhbXMpKTtcbiAgfSxcblxuICAvLyBbYXNzaWduVG9IYXNoXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiB2YWx1ZSwgLi4uLCBoYXNoLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiAuLi4sIGhhc2gsIC4uLlxuICAvL1xuICAvLyBQb3BzIGEgdmFsdWUgb2ZmIHRoZSBzdGFjayBhbmQgYXNzaWducyBpdCB0byB0aGUgY3VycmVudCBoYXNoXG4gIGFzc2lnblRvSGFzaDogZnVuY3Rpb24oa2V5KSB7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5wb3BTdGFjaygpLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICB0eXBlLFxuICAgICAgICBpZDtcblxuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICBpZCA9IHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0eXBlID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgY29udGV4dCA9IHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG5cbiAgICBsZXQgaGFzaCA9IHRoaXMuaGFzaDtcbiAgICBpZiAoY29udGV4dCkge1xuICAgICAgaGFzaC5jb250ZXh0c1trZXldID0gY29udGV4dDtcbiAgICB9XG4gICAgaWYgKHR5cGUpIHtcbiAgICAgIGhhc2gudHlwZXNba2V5XSA9IHR5cGU7XG4gICAgfVxuICAgIGlmIChpZCkge1xuICAgICAgaGFzaC5pZHNba2V5XSA9IGlkO1xuICAgIH1cbiAgICBoYXNoLnZhbHVlc1trZXldID0gdmFsdWU7XG4gIH0sXG5cbiAgcHVzaElkOiBmdW5jdGlvbih0eXBlLCBuYW1lLCBjaGlsZCkge1xuICAgIGlmICh0eXBlID09PSAnQmxvY2tQYXJhbScpIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChcbiAgICAgICAgICAnYmxvY2tQYXJhbXNbJyArIG5hbWVbMF0gKyAnXS5wYXRoWycgKyBuYW1lWzFdICsgJ10nXG4gICAgICAgICAgKyAoY2hpbGQgPyAnICsgJyArIEpTT04uc3RyaW5naWZ5KCcuJyArIGNoaWxkKSA6ICcnKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnUGF0aEV4cHJlc3Npb24nKSB7XG4gICAgICB0aGlzLnB1c2hTdHJpbmcobmFtZSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbCgndHJ1ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwoJ251bGwnKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gSEVMUEVSU1xuXG4gIGNvbXBpbGVyOiBKYXZhU2NyaXB0Q29tcGlsZXIsXG5cbiAgY29tcGlsZUNoaWxkcmVuOiBmdW5jdGlvbihlbnZpcm9ubWVudCwgb3B0aW9ucykge1xuICAgIGxldCBjaGlsZHJlbiA9IGVudmlyb25tZW50LmNoaWxkcmVuLCBjaGlsZCwgY29tcGlsZXI7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IGNoaWxkcmVuLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgIGNvbXBpbGVyID0gbmV3IHRoaXMuY29tcGlsZXIoKTsgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuZXctY2FwXG5cbiAgICAgIGxldCBleGlzdGluZyA9IHRoaXMubWF0Y2hFeGlzdGluZ1Byb2dyYW0oY2hpbGQpO1xuXG4gICAgICBpZiAoZXhpc3RpbmcgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmNvbnRleHQucHJvZ3JhbXMucHVzaCgnJyk7ICAgICAvLyBQbGFjZWhvbGRlciB0byBwcmV2ZW50IG5hbWUgY29uZmxpY3RzIGZvciBuZXN0ZWQgY2hpbGRyZW5cbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5jb250ZXh0LnByb2dyYW1zLmxlbmd0aDtcbiAgICAgICAgY2hpbGQuaW5kZXggPSBpbmRleDtcbiAgICAgICAgY2hpbGQubmFtZSA9ICdwcm9ncmFtJyArIGluZGV4O1xuICAgICAgICB0aGlzLmNvbnRleHQucHJvZ3JhbXNbaW5kZXhdID0gY29tcGlsZXIuY29tcGlsZShjaGlsZCwgb3B0aW9ucywgdGhpcy5jb250ZXh0LCAhdGhpcy5wcmVjb21waWxlKTtcbiAgICAgICAgdGhpcy5jb250ZXh0LmRlY29yYXRvcnNbaW5kZXhdID0gY29tcGlsZXIuZGVjb3JhdG9ycztcbiAgICAgICAgdGhpcy5jb250ZXh0LmVudmlyb25tZW50c1tpbmRleF0gPSBjaGlsZDtcblxuICAgICAgICB0aGlzLnVzZURlcHRocyA9IHRoaXMudXNlRGVwdGhzIHx8IGNvbXBpbGVyLnVzZURlcHRocztcbiAgICAgICAgdGhpcy51c2VCbG9ja1BhcmFtcyA9IHRoaXMudXNlQmxvY2tQYXJhbXMgfHwgY29tcGlsZXIudXNlQmxvY2tQYXJhbXM7XG4gICAgICAgIGNoaWxkLnVzZURlcHRocyA9IHRoaXMudXNlRGVwdGhzO1xuICAgICAgICBjaGlsZC51c2VCbG9ja1BhcmFtcyA9IHRoaXMudXNlQmxvY2tQYXJhbXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGlsZC5pbmRleCA9IGV4aXN0aW5nLmluZGV4O1xuICAgICAgICBjaGlsZC5uYW1lID0gJ3Byb2dyYW0nICsgZXhpc3RpbmcuaW5kZXg7XG5cbiAgICAgICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCBleGlzdGluZy51c2VEZXB0aHM7XG4gICAgICAgIHRoaXMudXNlQmxvY2tQYXJhbXMgPSB0aGlzLnVzZUJsb2NrUGFyYW1zIHx8IGV4aXN0aW5nLnVzZUJsb2NrUGFyYW1zO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgbWF0Y2hFeGlzdGluZ1Byb2dyYW06IGZ1bmN0aW9uKGNoaWxkKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRoaXMuY29udGV4dC5lbnZpcm9ubWVudHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGxldCBlbnZpcm9ubWVudCA9IHRoaXMuY29udGV4dC5lbnZpcm9ubWVudHNbaV07XG4gICAgICBpZiAoZW52aXJvbm1lbnQgJiYgZW52aXJvbm1lbnQuZXF1YWxzKGNoaWxkKSkge1xuICAgICAgICByZXR1cm4gZW52aXJvbm1lbnQ7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIHByb2dyYW1FeHByZXNzaW9uOiBmdW5jdGlvbihndWlkKSB7XG4gICAgbGV0IGNoaWxkID0gdGhpcy5lbnZpcm9ubWVudC5jaGlsZHJlbltndWlkXSxcbiAgICAgICAgcHJvZ3JhbVBhcmFtcyA9IFtjaGlsZC5pbmRleCwgJ2RhdGEnLCBjaGlsZC5ibG9ja1BhcmFtc107XG5cbiAgICBpZiAodGhpcy51c2VCbG9ja1BhcmFtcyB8fCB0aGlzLnVzZURlcHRocykge1xuICAgICAgcHJvZ3JhbVBhcmFtcy5wdXNoKCdibG9ja1BhcmFtcycpO1xuICAgIH1cbiAgICBpZiAodGhpcy51c2VEZXB0aHMpIHtcbiAgICAgIHByb2dyYW1QYXJhbXMucHVzaCgnZGVwdGhzJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICdjb250YWluZXIucHJvZ3JhbSgnICsgcHJvZ3JhbVBhcmFtcy5qb2luKCcsICcpICsgJyknO1xuICB9LFxuXG4gIHVzZVJlZ2lzdGVyOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLnJlZ2lzdGVyc1tuYW1lXSkge1xuICAgICAgdGhpcy5yZWdpc3RlcnNbbmFtZV0gPSB0cnVlO1xuICAgICAgdGhpcy5yZWdpc3RlcnMubGlzdC5wdXNoKG5hbWUpO1xuICAgIH1cbiAgfSxcblxuICBwdXNoOiBmdW5jdGlvbihleHByKSB7XG4gICAgaWYgKCEoZXhwciBpbnN0YW5jZW9mIExpdGVyYWwpKSB7XG4gICAgICBleHByID0gdGhpcy5zb3VyY2Uud3JhcChleHByKTtcbiAgICB9XG5cbiAgICB0aGlzLmlubGluZVN0YWNrLnB1c2goZXhwcik7XG4gICAgcmV0dXJuIGV4cHI7XG4gIH0sXG5cbiAgcHVzaFN0YWNrTGl0ZXJhbDogZnVuY3Rpb24oaXRlbSkge1xuICAgIHRoaXMucHVzaChuZXcgTGl0ZXJhbChpdGVtKSk7XG4gIH0sXG5cbiAgcHVzaFNvdXJjZTogZnVuY3Rpb24oc291cmNlKSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIHRoaXMuc291cmNlLnB1c2goXG4gICAgICAgICAgdGhpcy5hcHBlbmRUb0J1ZmZlcih0aGlzLnNvdXJjZS5xdW90ZWRTdHJpbmcodGhpcy5wZW5kaW5nQ29udGVudCksIHRoaXMucGVuZGluZ0xvY2F0aW9uKSk7XG4gICAgICB0aGlzLnBlbmRpbmdDb250ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgIHRoaXMuc291cmNlLnB1c2goc291cmNlKTtcbiAgICB9XG4gIH0sXG5cbiAgcmVwbGFjZVN0YWNrOiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIGxldCBwcmVmaXggPSBbJygnXSxcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIGNyZWF0ZWRTdGFjayxcbiAgICAgICAgdXNlZExpdGVyYWw7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICghdGhpcy5pc0lubGluZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdyZXBsYWNlU3RhY2sgb24gbm9uLWlubGluZScpO1xuICAgIH1cblxuICAgIC8vIFdlIHdhbnQgdG8gbWVyZ2UgdGhlIGlubGluZSBzdGF0ZW1lbnQgaW50byB0aGUgcmVwbGFjZW1lbnQgc3RhdGVtZW50IHZpYSAnLCdcbiAgICBsZXQgdG9wID0gdGhpcy5wb3BTdGFjayh0cnVlKTtcblxuICAgIGlmICh0b3AgaW5zdGFuY2VvZiBMaXRlcmFsKSB7XG4gICAgICAvLyBMaXRlcmFscyBkbyBub3QgbmVlZCB0byBiZSBpbmxpbmVkXG4gICAgICBzdGFjayA9IFt0b3AudmFsdWVdO1xuICAgICAgcHJlZml4ID0gWycoJywgc3RhY2tdO1xuICAgICAgdXNlZExpdGVyYWwgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBHZXQgb3IgY3JlYXRlIHRoZSBjdXJyZW50IHN0YWNrIG5hbWUgZm9yIHVzZSBieSB0aGUgaW5saW5lXG4gICAgICBjcmVhdGVkU3RhY2sgPSB0cnVlO1xuICAgICAgbGV0IG5hbWUgPSB0aGlzLmluY3JTdGFjaygpO1xuXG4gICAgICBwcmVmaXggPSBbJygoJywgdGhpcy5wdXNoKG5hbWUpLCAnID0gJywgdG9wLCAnKSddO1xuICAgICAgc3RhY2sgPSB0aGlzLnRvcFN0YWNrKCk7XG4gICAgfVxuXG4gICAgbGV0IGl0ZW0gPSBjYWxsYmFjay5jYWxsKHRoaXMsIHN0YWNrKTtcblxuICAgIGlmICghdXNlZExpdGVyYWwpIHtcbiAgICAgIHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG4gICAgaWYgKGNyZWF0ZWRTdGFjaykge1xuICAgICAgdGhpcy5zdGFja1Nsb3QtLTtcbiAgICB9XG4gICAgdGhpcy5wdXNoKHByZWZpeC5jb25jYXQoaXRlbSwgJyknKSk7XG4gIH0sXG5cbiAgaW5jclN0YWNrOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnN0YWNrU2xvdCsrO1xuICAgIGlmICh0aGlzLnN0YWNrU2xvdCA+IHRoaXMuc3RhY2tWYXJzLmxlbmd0aCkgeyB0aGlzLnN0YWNrVmFycy5wdXNoKCdzdGFjaycgKyB0aGlzLnN0YWNrU2xvdCk7IH1cbiAgICByZXR1cm4gdGhpcy50b3BTdGFja05hbWUoKTtcbiAgfSxcbiAgdG9wU3RhY2tOYW1lOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gJ3N0YWNrJyArIHRoaXMuc3RhY2tTbG90O1xuICB9LFxuICBmbHVzaElubGluZTogZnVuY3Rpb24oKSB7XG4gICAgbGV0IGlubGluZVN0YWNrID0gdGhpcy5pbmxpbmVTdGFjaztcbiAgICB0aGlzLmlubGluZVN0YWNrID0gW107XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGlubGluZVN0YWNrLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBsZXQgZW50cnkgPSBpbmxpbmVTdGFja1tpXTtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgTGl0ZXJhbCkge1xuICAgICAgICB0aGlzLmNvbXBpbGVTdGFjay5wdXNoKGVudHJ5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBzdGFjayA9IHRoaXMuaW5jclN0YWNrKCk7XG4gICAgICAgIHRoaXMucHVzaFNvdXJjZShbc3RhY2ssICcgPSAnLCBlbnRyeSwgJzsnXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVN0YWNrLnB1c2goc3RhY2spO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgaXNJbmxpbmU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmlubGluZVN0YWNrLmxlbmd0aDtcbiAgfSxcblxuICBwb3BTdGFjazogZnVuY3Rpb24od3JhcHBlZCkge1xuICAgIGxldCBpbmxpbmUgPSB0aGlzLmlzSW5saW5lKCksXG4gICAgICAgIGl0ZW0gPSAoaW5saW5lID8gdGhpcy5pbmxpbmVTdGFjayA6IHRoaXMuY29tcGlsZVN0YWNrKS5wb3AoKTtcblxuICAgIGlmICghd3JhcHBlZCAmJiAoaXRlbSBpbnN0YW5jZW9mIExpdGVyYWwpKSB7XG4gICAgICByZXR1cm4gaXRlbS52YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFpbmxpbmUpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgaWYgKCF0aGlzLnN0YWNrU2xvdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0ludmFsaWQgc3RhY2sgcG9wJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGFja1Nsb3QtLTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgfSxcblxuICB0b3BTdGFjazogZnVuY3Rpb24oKSB7XG4gICAgbGV0IHN0YWNrID0gKHRoaXMuaXNJbmxpbmUoKSA/IHRoaXMuaW5saW5lU3RhY2sgOiB0aGlzLmNvbXBpbGVTdGFjayksXG4gICAgICAgIGl0ZW0gPSBzdGFja1tzdGFjay5sZW5ndGggLSAxXTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChpdGVtIGluc3RhbmNlb2YgTGl0ZXJhbCkge1xuICAgICAgcmV0dXJuIGl0ZW0udmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgfSxcblxuICBjb250ZXh0TmFtZTogZnVuY3Rpb24oY29udGV4dCkge1xuICAgIGlmICh0aGlzLnVzZURlcHRocyAmJiBjb250ZXh0KSB7XG4gICAgICByZXR1cm4gJ2RlcHRoc1snICsgY29udGV4dCArICddJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICdkZXB0aCcgKyBjb250ZXh0O1xuICAgIH1cbiAgfSxcblxuICBxdW90ZWRTdHJpbmc6IGZ1bmN0aW9uKHN0cikge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZS5xdW90ZWRTdHJpbmcoc3RyKTtcbiAgfSxcblxuICBvYmplY3RMaXRlcmFsOiBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdGhpcy5zb3VyY2Uub2JqZWN0TGl0ZXJhbChvYmopO1xuICB9LFxuXG4gIGFsaWFzYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGxldCByZXQgPSB0aGlzLmFsaWFzZXNbbmFtZV07XG4gICAgaWYgKHJldCkge1xuICAgICAgcmV0LnJlZmVyZW5jZUNvdW50Kys7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIHJldCA9IHRoaXMuYWxpYXNlc1tuYW1lXSA9IHRoaXMuc291cmNlLndyYXAobmFtZSk7XG4gICAgcmV0LmFsaWFzYWJsZSA9IHRydWU7XG4gICAgcmV0LnJlZmVyZW5jZUNvdW50ID0gMTtcblxuICAgIHJldHVybiByZXQ7XG4gIH0sXG5cbiAgc2V0dXBIZWxwZXI6IGZ1bmN0aW9uKHBhcmFtU2l6ZSwgbmFtZSwgYmxvY2tIZWxwZXIpIHtcbiAgICBsZXQgcGFyYW1zID0gW10sXG4gICAgICAgIHBhcmFtc0luaXQgPSB0aGlzLnNldHVwSGVscGVyQXJncyhuYW1lLCBwYXJhbVNpemUsIHBhcmFtcywgYmxvY2tIZWxwZXIpO1xuICAgIGxldCBmb3VuZEhlbHBlciA9IHRoaXMubmFtZUxvb2t1cCgnaGVscGVycycsIG5hbWUsICdoZWxwZXInKSxcbiAgICAgICAgY2FsbENvbnRleHQgPSB0aGlzLmFsaWFzYWJsZShgJHt0aGlzLmNvbnRleHROYW1lKDApfSAhPSBudWxsID8gJHt0aGlzLmNvbnRleHROYW1lKDApfSA6IHt9YCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFyYW1zOiBwYXJhbXMsXG4gICAgICBwYXJhbXNJbml0OiBwYXJhbXNJbml0LFxuICAgICAgbmFtZTogZm91bmRIZWxwZXIsXG4gICAgICBjYWxsUGFyYW1zOiBbY2FsbENvbnRleHRdLmNvbmNhdChwYXJhbXMpXG4gICAgfTtcbiAgfSxcblxuICBzZXR1cFBhcmFtczogZnVuY3Rpb24oaGVscGVyLCBwYXJhbVNpemUsIHBhcmFtcykge1xuICAgIGxldCBvcHRpb25zID0ge30sXG4gICAgICAgIGNvbnRleHRzID0gW10sXG4gICAgICAgIHR5cGVzID0gW10sXG4gICAgICAgIGlkcyA9IFtdLFxuICAgICAgICBvYmplY3RBcmdzID0gIXBhcmFtcyxcbiAgICAgICAgcGFyYW07XG5cbiAgICBpZiAob2JqZWN0QXJncykge1xuICAgICAgcGFyYW1zID0gW107XG4gICAgfVxuXG4gICAgb3B0aW9ucy5uYW1lID0gdGhpcy5xdW90ZWRTdHJpbmcoaGVscGVyKTtcbiAgICBvcHRpb25zLmhhc2ggPSB0aGlzLnBvcFN0YWNrKCk7XG5cbiAgICBpZiAodGhpcy50cmFja0lkcykge1xuICAgICAgb3B0aW9ucy5oYXNoSWRzID0gdGhpcy5wb3BTdGFjaygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdHJpbmdQYXJhbXMpIHtcbiAgICAgIG9wdGlvbnMuaGFzaFR5cGVzID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgb3B0aW9ucy5oYXNoQ29udGV4dHMgPSB0aGlzLnBvcFN0YWNrKCk7XG4gICAgfVxuXG4gICAgbGV0IGludmVyc2UgPSB0aGlzLnBvcFN0YWNrKCksXG4gICAgICAgIHByb2dyYW0gPSB0aGlzLnBvcFN0YWNrKCk7XG5cbiAgICAvLyBBdm9pZCBzZXR0aW5nIGZuIGFuZCBpbnZlcnNlIGlmIG5laXRoZXIgYXJlIHNldC4gVGhpcyBhbGxvd3NcbiAgICAvLyBoZWxwZXJzIHRvIGRvIGEgY2hlY2sgZm9yIGBpZiAob3B0aW9ucy5mbilgXG4gICAgaWYgKHByb2dyYW0gfHwgaW52ZXJzZSkge1xuICAgICAgb3B0aW9ucy5mbiA9IHByb2dyYW0gfHwgJ2NvbnRhaW5lci5ub29wJztcbiAgICAgIG9wdGlvbnMuaW52ZXJzZSA9IGludmVyc2UgfHwgJ2NvbnRhaW5lci5ub29wJztcbiAgICB9XG5cbiAgICAvLyBUaGUgcGFyYW1ldGVycyBnbyBvbiB0byB0aGUgc3RhY2sgaW4gb3JkZXIgKG1ha2luZyBzdXJlIHRoYXQgdGhleSBhcmUgZXZhbHVhdGVkIGluIG9yZGVyKVxuICAgIC8vIHNvIHdlIG5lZWQgdG8gcG9wIHRoZW0gb2ZmIHRoZSBzdGFjayBpbiByZXZlcnNlIG9yZGVyXG4gICAgbGV0IGkgPSBwYXJhbVNpemU7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgcGFyYW0gPSB0aGlzLnBvcFN0YWNrKCk7XG4gICAgICBwYXJhbXNbaV0gPSBwYXJhbTtcblxuICAgICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgICAgaWRzW2ldID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICAgIHR5cGVzW2ldID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgICBjb250ZXh0c1tpXSA9IHRoaXMucG9wU3RhY2soKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob2JqZWN0QXJncykge1xuICAgICAgb3B0aW9ucy5hcmdzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheShwYXJhbXMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICBvcHRpb25zLmlkcyA9IHRoaXMuc291cmNlLmdlbmVyYXRlQXJyYXkoaWRzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICBvcHRpb25zLnR5cGVzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheSh0eXBlcyk7XG4gICAgICBvcHRpb25zLmNvbnRleHRzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheShjb250ZXh0cyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kYXRhKSB7XG4gICAgICBvcHRpb25zLmRhdGEgPSAnZGF0YSc7XG4gICAgfVxuICAgIGlmICh0aGlzLnVzZUJsb2NrUGFyYW1zKSB7XG4gICAgICBvcHRpb25zLmJsb2NrUGFyYW1zID0gJ2Jsb2NrUGFyYW1zJztcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH0sXG5cbiAgc2V0dXBIZWxwZXJBcmdzOiBmdW5jdGlvbihoZWxwZXIsIHBhcmFtU2l6ZSwgcGFyYW1zLCB1c2VSZWdpc3Rlcikge1xuICAgIGxldCBvcHRpb25zID0gdGhpcy5zZXR1cFBhcmFtcyhoZWxwZXIsIHBhcmFtU2l6ZSwgcGFyYW1zKTtcbiAgICBvcHRpb25zID0gdGhpcy5vYmplY3RMaXRlcmFsKG9wdGlvbnMpO1xuICAgIGlmICh1c2VSZWdpc3Rlcikge1xuICAgICAgdGhpcy51c2VSZWdpc3Rlcignb3B0aW9ucycpO1xuICAgICAgcGFyYW1zLnB1c2goJ29wdGlvbnMnKTtcbiAgICAgIHJldHVybiBbJ29wdGlvbnM9Jywgb3B0aW9uc107XG4gICAgfSBlbHNlIGlmIChwYXJhbXMpIHtcbiAgICAgIHBhcmFtcy5wdXNoKG9wdGlvbnMpO1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9XG4gIH1cbn07XG5cblxuKGZ1bmN0aW9uKCkge1xuICBjb25zdCByZXNlcnZlZFdvcmRzID0gKFxuICAgICdicmVhayBlbHNlIG5ldyB2YXInICtcbiAgICAnIGNhc2UgZmluYWxseSByZXR1cm4gdm9pZCcgK1xuICAgICcgY2F0Y2ggZm9yIHN3aXRjaCB3aGlsZScgK1xuICAgICcgY29udGludWUgZnVuY3Rpb24gdGhpcyB3aXRoJyArXG4gICAgJyBkZWZhdWx0IGlmIHRocm93JyArXG4gICAgJyBkZWxldGUgaW4gdHJ5JyArXG4gICAgJyBkbyBpbnN0YW5jZW9mIHR5cGVvZicgK1xuICAgICcgYWJzdHJhY3QgZW51bSBpbnQgc2hvcnQnICtcbiAgICAnIGJvb2xlYW4gZXhwb3J0IGludGVyZmFjZSBzdGF0aWMnICtcbiAgICAnIGJ5dGUgZXh0ZW5kcyBsb25nIHN1cGVyJyArXG4gICAgJyBjaGFyIGZpbmFsIG5hdGl2ZSBzeW5jaHJvbml6ZWQnICtcbiAgICAnIGNsYXNzIGZsb2F0IHBhY2thZ2UgdGhyb3dzJyArXG4gICAgJyBjb25zdCBnb3RvIHByaXZhdGUgdHJhbnNpZW50JyArXG4gICAgJyBkZWJ1Z2dlciBpbXBsZW1lbnRzIHByb3RlY3RlZCB2b2xhdGlsZScgK1xuICAgICcgZG91YmxlIGltcG9ydCBwdWJsaWMgbGV0IHlpZWxkIGF3YWl0JyArXG4gICAgJyBudWxsIHRydWUgZmFsc2UnXG4gICkuc3BsaXQoJyAnKTtcblxuICBjb25zdCBjb21waWxlcldvcmRzID0gSmF2YVNjcmlwdENvbXBpbGVyLlJFU0VSVkVEX1dPUkRTID0ge307XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSByZXNlcnZlZFdvcmRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGNvbXBpbGVyV29yZHNbcmVzZXJ2ZWRXb3Jkc1tpXV0gPSB0cnVlO1xuICB9XG59KCkpO1xuXG5KYXZhU2NyaXB0Q29tcGlsZXIuaXNWYWxpZEphdmFTY3JpcHRWYXJpYWJsZU5hbWUgPSBmdW5jdGlvbihuYW1lKSB7XG4gIHJldHVybiAhSmF2YVNjcmlwdENvbXBpbGVyLlJFU0VSVkVEX1dPUkRTW25hbWVdICYmICgvXlthLXpBLVpfJF1bMC05YS16QS1aXyRdKiQvKS50ZXN0KG5hbWUpO1xufTtcblxuZnVuY3Rpb24gc3RyaWN0TG9va3VwKHJlcXVpcmVUZXJtaW5hbCwgY29tcGlsZXIsIHBhcnRzLCB0eXBlKSB7XG4gIGxldCBzdGFjayA9IGNvbXBpbGVyLnBvcFN0YWNrKCksXG4gICAgICBpID0gMCxcbiAgICAgIGxlbiA9IHBhcnRzLmxlbmd0aDtcbiAgaWYgKHJlcXVpcmVUZXJtaW5hbCkge1xuICAgIGxlbi0tO1xuICB9XG5cbiAgZm9yICg7IGkgPCBsZW47IGkrKykge1xuICAgIHN0YWNrID0gY29tcGlsZXIubmFtZUxvb2t1cChzdGFjaywgcGFydHNbaV0sIHR5cGUpO1xuICB9XG5cbiAgaWYgKHJlcXVpcmVUZXJtaW5hbCkge1xuICAgIHJldHVybiBbY29tcGlsZXIuYWxpYXNhYmxlKCdjb250YWluZXIuc3RyaWN0JyksICcoJywgc3RhY2ssICcsICcsIGNvbXBpbGVyLnF1b3RlZFN0cmluZyhwYXJ0c1tpXSksICcpJ107XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0YWNrO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEphdmFTY3JpcHRDb21waWxlcjtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/parser.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/parser.js new file mode 100644 index 0000000..58748e0 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/parser.js @@ -0,0 +1,740 @@ +define(["exports"], function (exports) { + /* istanbul ignore next */ + /* Jison generated parser */ + "use strict"; + + var handlebars = (function () { + var parser = { trace: function trace() {}, + yy: {}, + symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 }, + terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" }, + productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$ + /**/) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: + return $$[$0 - 1]; + break; + case 2: + this.$ = yy.prepareProgram($$[$0]); + break; + case 3: + this.$ = $$[$0]; + break; + case 4: + this.$ = $$[$0]; + break; + case 5: + this.$ = $$[$0]; + break; + case 6: + this.$ = $$[$0]; + break; + case 7: + this.$ = $$[$0]; + break; + case 8: + this.$ = $$[$0]; + break; + case 9: + this.$ = { + type: 'CommentStatement', + value: yy.stripComment($$[$0]), + strip: yy.stripFlags($$[$0], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 10: + this.$ = { + type: 'ContentStatement', + original: $$[$0], + value: $$[$0], + loc: yy.locInfo(this._$) + }; + + break; + case 11: + this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 12: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] }; + break; + case 13: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$); + break; + case 14: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$); + break; + case 15: + this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 16: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 17: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 18: + this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] }; + break; + case 19: + var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$), + program = yy.prepareProgram([inverse], $$[$0 - 1].loc); + program.chained = true; + + this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true }; + + break; + case 20: + this.$ = $$[$0]; + break; + case 21: + this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) }; + break; + case 22: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 23: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 24: + this.$ = { + type: 'PartialStatement', + name: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + indent: '', + strip: yy.stripFlags($$[$0 - 4], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 25: + this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 26: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) }; + break; + case 27: + this.$ = $$[$0]; + break; + case 28: + this.$ = $$[$0]; + break; + case 29: + this.$ = { + type: 'SubExpression', + path: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + loc: yy.locInfo(this._$) + }; + + break; + case 30: + this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 31: + this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 32: + this.$ = yy.id($$[$0 - 1]); + break; + case 33: + this.$ = $$[$0]; + break; + case 34: + this.$ = $$[$0]; + break; + case 35: + this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 36: + this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) }; + break; + case 37: + this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) }; + break; + case 38: + this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) }; + break; + case 39: + this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) }; + break; + case 40: + this.$ = $$[$0]; + break; + case 41: + this.$ = $$[$0]; + break; + case 42: + this.$ = yy.preparePath(true, $$[$0], this._$); + break; + case 43: + this.$ = yy.preparePath(false, $$[$0], this._$); + break; + case 44: + $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2]; + break; + case 45: + this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }]; + break; + case 46: + this.$ = []; + break; + case 47: + $$[$0 - 1].push($$[$0]); + break; + case 48: + this.$ = [$$[$0]]; + break; + case 49: + $$[$0 - 1].push($$[$0]); + break; + case 50: + this.$ = []; + break; + case 51: + $$[$0 - 1].push($$[$0]); + break; + case 58: + this.$ = []; + break; + case 59: + $$[$0 - 1].push($$[$0]); + break; + case 64: + this.$ = []; + break; + case 65: + $$[$0 - 1].push($$[$0]); + break; + case 70: + this.$ = []; + break; + case 71: + $$[$0 - 1].push($$[$0]); + break; + case 78: + this.$ = []; + break; + case 79: + $$[$0 - 1].push($$[$0]); + break; + case 82: + this.$ = []; + break; + case 83: + $$[$0 - 1].push($$[$0]); + break; + case 86: + this.$ = []; + break; + case 87: + $$[$0 - 1].push($$[$0]); + break; + case 90: + this.$ = []; + break; + case 91: + $$[$0 - 1].push($$[$0]); + break; + case 94: + this.$ = []; + break; + case 95: + $$[$0 - 1].push($$[$0]); + break; + case 98: + this.$ = [$$[$0]]; + break; + case 99: + $$[$0 - 1].push($$[$0]); + break; + case 100: + this.$ = [$$[$0]]; + break; + case 101: + $$[$0 - 1].push($$[$0]); + break; + } + }, + table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }], + defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137: [2, 32] }, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], + lstack = [], + table = this.table, + yytext = "", + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, + preErrorSymbol, + state, + action, + a, + r, + yyval = {}, + p, + len, + newState, + expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected }); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; + } + }; + /* Jison generated lexer */ + var lexer = (function () { + var lexer = { EOF: 1, + parseError: function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput: function setInput(input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; + if (this.options.ranges) this.yylloc.range = [0, 0]; + this.offset = 0; + return this; + }, + input: function input() { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, + unput: function unput(ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); + + if (lines.length - 1) this.yylineno -= lines.length - 1; + var r = this.yylloc.range; + + this.yylloc = { first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, + more: function more() { + this._more = true; + return this; + }, + less: function less(n) { + this.unput(this.match.slice(n)); + }, + pastInput: function pastInput() { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput: function upcomingInput() { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20 - next.length); + } + return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, + showPosition: function showPosition() { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, + next: function next() { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, match, tempMatch, index, col, lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = { first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) this.done = false; + if (token) return token;else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); + } + }, + lex: function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin: function begin(condition) { + this.conditionStack.push(condition); + }, + popState: function popState() { + return this.conditionStack.pop(); + }, + _currentRules: function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + }, + topState: function topState() { + return this.conditionStack[this.conditionStack.length - 2]; + }, + pushState: function begin(condition) { + this.begin(condition); + } }; + lexer.options = {}; + lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START + /**/) { + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end); + } + + var YYSTATE = YY_START; + switch ($avoiding_name_collisions) { + case 0: + if (yy_.yytext.slice(-2) === "\\\\") { + strip(0, 1); + this.begin("mu"); + } else if (yy_.yytext.slice(-1) === "\\") { + strip(0, 1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if (yy_.yytext) return 15; + + break; + case 1: + return 15; + break; + case 2: + this.popState(); + return 15; + + break; + case 3: + this.begin('raw');return 15; + break; + case 4: + this.popState(); + // Should be using `this.topState()` below, but it currently + // returns the second top instead of the first top. Opened an + // issue about it at https://github.com/zaach/jison/issues/291 + if (this.conditionStack[this.conditionStack.length - 1] === 'raw') { + return 15; + } else { + yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9); + return 'END_RAW_BLOCK'; + } + + break; + case 5: + return 15; + break; + case 6: + this.popState(); + return 14; + + break; + case 7: + return 65; + break; + case 8: + return 68; + break; + case 9: + return 19; + break; + case 10: + this.popState(); + this.begin('raw'); + return 23; + + break; + case 11: + return 55; + break; + case 12: + return 60; + break; + case 13: + return 29; + break; + case 14: + return 47; + break; + case 15: + this.popState();return 44; + break; + case 16: + this.popState();return 44; + break; + case 17: + return 34; + break; + case 18: + return 39; + break; + case 19: + return 51; + break; + case 20: + return 48; + break; + case 21: + this.unput(yy_.yytext); + this.popState(); + this.begin('com'); + + break; + case 22: + this.popState(); + return 14; + + break; + case 23: + return 48; + break; + case 24: + return 73; + break; + case 25: + return 72; + break; + case 26: + return 72; + break; + case 27: + return 87; + break; + case 28: + // ignore whitespace + break; + case 29: + this.popState();return 54; + break; + case 30: + this.popState();return 33; + break; + case 31: + yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80; + break; + case 32: + yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80; + break; + case 33: + return 85; + break; + case 34: + return 82; + break; + case 35: + return 82; + break; + case 36: + return 83; + break; + case 37: + return 84; + break; + case 38: + return 81; + break; + case 39: + return 75; + break; + case 40: + return 77; + break; + case 41: + return 72; + break; + case 42: + yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72; + break; + case 43: + return 'INVALID'; + break; + case 44: + return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/]; + lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } }; + return lexer; + })(); + parser.lexer = lexer; + function Parser() { + this.yy = {}; + }Parser.prototype = parser;parser.Parser = Parser; + return new Parser(); + })();exports.__esModule = true; + exports['default'] = handlebars; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3BhcnNlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLFFBQUksVUFBVSxHQUFHLENBQUMsWUFBVTtBQUM1QixZQUFJLE1BQU0sR0FBRyxFQUFDLEtBQUssRUFBRSxTQUFTLEtBQUssR0FBRyxFQUFHO0FBQ3pDLGNBQUUsRUFBRSxFQUFFO0FBQ04sb0JBQVEsRUFBRSxFQUFDLE9BQU8sRUFBQyxDQUFDLEVBQUMsTUFBTSxFQUFDLENBQUMsRUFBQyxTQUFTLEVBQUMsQ0FBQyxFQUFDLEtBQUssRUFBQyxDQUFDLEVBQUMscUJBQXFCLEVBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxDQUFDLEVBQUMsVUFBVSxFQUFDLENBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxFQUFDLFVBQVUsRUFBQyxFQUFFLEVBQUMsU0FBUyxFQUFDLEVBQUUsRUFBQyxjQUFjLEVBQUMsRUFBRSxFQUFDLFNBQVMsRUFBQyxFQUFFLEVBQUMsU0FBUyxFQUFDLEVBQUUsRUFBQyxTQUFTLEVBQUMsRUFBRSxFQUFDLGNBQWMsRUFBQyxFQUFFLEVBQUMsMkJBQTJCLEVBQUMsRUFBRSxFQUFDLGVBQWUsRUFBQyxFQUFFLEVBQUMsZ0JBQWdCLEVBQUMsRUFBRSxFQUFDLFlBQVksRUFBQyxFQUFFLEVBQUMsMEJBQTBCLEVBQUMsRUFBRSxFQUFDLHNCQUFzQixFQUFDLEVBQUUsRUFBQyxpQkFBaUIsRUFBQyxFQUFFLEVBQUMsV0FBVyxFQUFDLEVBQUUsRUFBQyxlQUFlLEVBQUMsRUFBRSxFQUFDLFlBQVksRUFBQyxFQUFFLEVBQUMsYUFBYSxFQUFDLEVBQUUsRUFBQyxlQUFlLEVBQUMsRUFBRSxFQUFDLFlBQVksRUFBQyxFQUFFLEVBQUMsdUJBQXVCLEVBQUMsRUFBRSxFQUFDLG1CQUFtQixFQUFDLEVBQUUsRUFBQyxtQkFBbUIsRUFBQyxFQUFFLEVBQUMsT0FBTyxFQUFDLEVBQUUsRUFBQyxjQUFjLEVBQUMsRUFB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RUFBRSxFQUFDLEtBQUssRUFBQztBQUM1ZSx3QkFBWSxFQUFFLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFB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QUFDLENBQUMsR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3pFLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ3RFLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN2Riw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdEYsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNySiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ3JJLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDckksOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztBQUMvRSw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUNILDRCQUFJLE9BQU8sR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDOzRCQUM3RSxPQUFPLEdBQUcsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDekQsK0JBQU8sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDOztBQUV2Qiw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQzs7QUFFdEUsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDeEIsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUMsQ0FBQztBQUMxRSw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RILDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdEgsOEJBQU07QUFB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SyxFQUFFO0FBQUUsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQUFBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEcsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUM7QUFDM0QsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDcEIsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQywwQkFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUIsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzFCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMxQiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDBCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5Qiw4QkFBTTtBQUFBLEFBQ04seUJBQUssR0FBRztBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDM0IsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEdBQUc7QUFBQywwQkFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDL0IsOEJBQU07QUFBQSxpQkFDTDthQUNBO0FBQ0QsaUJBQUssRUFBRSxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztBQUN4Z1csMEJBQWMsRUFBRSxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVB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QUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLCtCQUFPLEVBQUUsQ0FBQztBQUNsQiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUNMLDRCQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN2Qiw0QkFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ2hCLDRCQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDOztBQUVwQiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUNMLDRCQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDaEIsK0JBQU8sRUFBRSxDQUFDOztBQUVaLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFOztBQUNQLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxBQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ25DLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxBQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ25DLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMkJBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFDLEdBQUcsQ0FBQyxDQUFDLEFBQUMsT0FBTyxFQUFF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RUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLENBQUMsRUFBQyxXQUFXLEVBQUMsS0FBSyxFQUFDLEVBQUMsS0FBSyxFQUFDLEVBQUMsT0FBTyxFQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUMsV0FBVyxFQUFDLEtBQUssRUFBQyxFQUFDLEtBQUssRUFBQyxFQUFDLE9BQU8sRUFBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxLQUFLLEVBQUMsRUFBQyxLQUFLLEVBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxLQUFLLEVBQUMsRUFBQyxTQUFTLEVBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLFdBQVcsRUFBQyxJQUFJLEVBQUMsRUFBQyxDQUFDO0FBQzNVLG1CQUFPLEtBQUssQ0FBQztTQUFDLENBQUEsRUFBRyxDQUFBO0FBQ2pCLGNBQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0FBQ3JCLGlCQUFTLE1BQU0sR0FBSTtBQUFFLGdCQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztTQUFFLE1BQU0sQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQ3JGLGVBQU8sSUFBSSxNQUFNLEVBQUEsQ0FBQztLQUNqQixDQUFBLEVBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztBQUMvQixXQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsVUFBVSxDQUFDIiwiZmlsZSI6InBhcnNlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4vKiBKaXNvbiBnZW5lcmF0ZWQgcGFyc2VyICovXG52YXIgaGFuZGxlYmFycyA9IChmdW5jdGlvbigpe1xudmFyIHBhcnNlciA9IHt0cmFjZTogZnVuY3Rpb24gdHJhY2UoKSB7IH0sXG55eToge30sXG5zeW1ib2xzXzoge1wiZXJyb3JcIjoyLFwicm9vdFwiOjMsXCJwcm9ncmFtXCI6NCxcIkVPRlwiOjUsXCJwcm9ncmFtX3JlcGV0aXRpb24wXCI6NixcInN0YXRlbWVudFwiOjcsXCJtdXN0YWNoZVwiOjgsXCJibG9ja1wiOjksXCJyYXdCbG9ja1wiOjEwLFwicGFydGlhbFwiOjExLFwicGFydGlhbEJsb2NrXCI6MTIsXCJjb250ZW50XCI6MTMsXCJDT01NRU5UXCI6MTQsXCJDT05URU5UXCI6MTUsXCJvcGVuUmF3QmxvY2tcIjoxNixcInJhd0Jsb2NrX3JlcGV0aXRpb25fcGx1czBcIjoxNyxcIkVORF9SQVdfQkxPQ0tcIjoxOCxcIk9QRU5fUkFXX0JMT0NLXCI6MTksXCJoZWxwZXJOYW1lXCI6MjAsXCJvcGVuUmF3QmxvY2tfcmVwZXRpdGlvbjBcIjoyMSxcIm9wZW5SYXdCbG9ja19vcHRpb24wXCI6MjIsXCJDTE9TRV9SQVdfQkxPQ0tcIjoyMyxcIm9wZW5CbG9ja1wiOjI0LFwiYmxvY2tfb3B0aW9uMFwiOjI1LFwiY2xvc2VCbG9ja1wiOjI2LFwib3BlbkludmVyc2VcIjoyNyxcImJsb2NrX29wdGlvbjFcIjoyOCxcIk9QRU5fQkxPQ0tcIjoyOSxcIm9wZW5CbG9ja19yZXBldGl0aW9uMFwiOjMwLFwib3BlbkJsb2NrX29wdGlvbjBcIjozMSxcIm9wZW5CbG9ja19vcHRpb24xXCI6MzIsXCJDTE9TRVwiOjMzLFwiT1BFTl9JTlZFUlNFXCI6MzQsXCJvcGVuSW52ZXJzZV9yZXBldGl0aW9uMFwiOjM1LFwib3BlbkludmVyc2Vfb3B0aW9uMFwiOjM2LFwib3BlbkludmVyc2Vfb3B0aW9uMVwiOjM3LFwib3BlbkludmVyc2VDaGFpblwiOjM4LFwiT1BFTl9JTlZFUlNFX0NIQUlOXCI6MzksXCJvcGVuSW52ZXJzZUNoYWluX3JlcGV0aXRpb24wXCI6NDAsXCJvcGVuSW52ZXJzZUNoYWluX29wdGlvbjBcIjo0MSxcIm9wZW5JbnZlcnNlQ2hhaW5fb3B0aW9uMVwiOjQyLFwiaW52ZXJzZUFuZFByb2dyYW1cIjo0MyxcIklOVkVSU0VcIjo0NCxcImludmVyc2VDaGFpblwiOjQ1LFwiaW52ZXJzZUNoYWluX29wdGlvbjBcIjo0NixcIk9QRU5fRU5EQkxPQ0tcIjo0NyxcIk9QRU5cIjo0OCxcIm11c3RhY2hlX3JlcGV0aXRpb24wXCI6NDksXCJtdXN0YWNoZV9vcHRpb24wXCI6NTAsXCJPUEVOX1VORVNDQVBFRFwiOjUxLFwibXVzdGFjaGVfcmVwZXRpdGlvbjFcIjo1MixcIm11c3RhY2hlX29wdGlvbjFcIjo1MyxcIkNMT1NFX1VORVNDQVBFRFwiOjU0LFwiT1BFTl9QQVJUSUFMXCI6NTUsXCJwYXJ0aWFsTmFtZVwiOjU2LFwicGFydGlhbF9yZXBldGl0aW9uMFwiOjU3LFwicGFydGlhbF9vcHRpb24wXCI6NTgsXCJvcGVuUGFydGlhbEJsb2NrXCI6NTksXCJPUEVOX1BBUlRJQUxfQkxPQ0tcIjo2MCxcIm9wZW5QYXJ0aWFsQmxvY2tfcmVwZXRpdGlvbjBcIjo2MSxcIm9wZW5QYXJ0aWFsQmxvY2tfb3B0aW9uMFwiOjYyLFwicGFyYW1cIjo2MyxcInNleHByXCI6NjQsXCJPUEVOX1NFWFBSXCI6NjUsXCJzZXhwcl9yZXBldGl0aW9uMFwiOjY2LFwic2V4cHJfb3B0aW9uMFwiOjY3LFwiQ0xPU0VfU0VYUFJcIjo2OCxcImhhc2hcIjo2OSxcImhhc2hfcmVwZXRpdGlvbl9wbHVzMFwiOjcwLFwiaGFzaFNlZ21lbnRcIjo3MSxcIklEXCI6NzIsXCJFUVVBTFNcIjo3MyxcImJsb2NrUGFyYW1zXCI6NzQsXCJPUEVOX0JMT0NLX1BBUkFNU1wiOjc1LFwiYmxvY2tQYXJhbXNfcmVwZXRpdGlvbl9wbHVzMFwiOjc2LFwiQ0xPU0VfQkxPQ0tfUEFSQU1TXCI6NzcsXCJwYXRoXCI6NzgsXCJkYXRhTmFtZVwiOjc5LFwiU1RSSU5HXCI6ODAsXCJOVU1CRVJcIjo4MSxcIkJPT0xFQU5cIjo4MixcIlVOREVGSU5FRFwiOjgzLFwiTlVMTFwiOjg0LFwiREFUQVwiOjg1LFwicGF0aFNlZ21lbnRzXCI6ODYsXCJTRVBcIjo4NyxcIiRhY2NlcHRcIjowLFwiJGVuZFwiOjF9LFxudGVybWluYWxzXzogezI6XCJlcnJvclwiLDU6XCJFT0ZcIiwxNDpcIkNPTU1FTlRcIiwxNTpcIkNPTlRFTlRcIiwxODpcIkVORF9SQVdfQkxPQ0tcIiwxOTpcIk9QRU5fUkFXX0JMT0NLXCIsMjM6XCJDTE9TRV9SQVdfQkxPQ0tcIiwyOTpcIk9QRU5fQkxPQ0tcIiwzMzpcIkNMT1NFXCIsMzQ6XCJPUEVOX0lOVkVSU0VcIiwzOTpcIk9QRU5fSU5WRVJTRV9DSEFJTlwiLDQ0OlwiSU5WRVJTRVwiLDQ3OlwiT1BFTl9FTkRCTE9DS1wiLDQ4OlwiT1BFTlwiLDUxOlwiT1BFTl9VTkVTQ0FQRURcIiw1NDpcIkNMT1NFX1VORVNDQVBFRFwiLDU1OlwiT1BFTl9QQVJUSUFMXCIsNjA6XCJPUEVOX1BBUlRJQUxfQkxPQ0tcIiw2NTpcIk9QRU5fU0VYUFJcIiw2ODpcIkNMT1NFX1NFWFBSXCIsNzI6XCJJRFwiLDczOlwiRVFVQUxTXCIsNzU6XCJPUEVOX0JMT0NLX1BBUkFNU1wiLDc3OlwiQ0xPU0VfQkxPQ0tfUEFSQU1TXCIsODA6XCJTVFJJTkdcIiw4MTpcIk5VTUJFUlwiLDgyOlwiQk9PTEVBTlwiLDgzOlwiVU5ERUZJTkVEXCIsODQ6XCJOVUxMXCIsODU6XCJEQVRBXCIsODc6XCJTRVBcIn0sXG5wcm9kdWN0aW9uc186IFswLFszLDJdLFs0LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFsxMywxXSxbMTAsM10sWzE2LDVdLFs5LDRdLFs5LDRdLFsyNCw2XSxbMjcsNl0sWzM4LDZdLFs0MywyXSxbNDUsM10sWzQ1LDFdLFsyNiwzXSxbOCw1XSxbOCw1XSxbMTEsNV0sWzEyLDNdLFs1OSw1XSxbNjMsMV0sWzYzLDFdLFs2NCw1XSxbNjksMV0sWzcxLDNdLFs3NCwzXSxbMjAsMV0sWzIwLDFdLFsyMCwxXSxbMjAsMV0sWzIwLDFdLFsyMCwxXSxbMjAsMV0sWzU2LDFdLFs1NiwxXSxbNzksMl0sWzc4LDFdLFs4NiwzXSxbODYsMV0sWzYsMF0sWzYsMl0sWzE3LDFdLFsxNywyXSxbMjEsMF0sWzIxLDJdLFsyMiwwXSxbMjIsMV0sWzI1LDBdLFsyNSwxXSxbMjgsMF0sWzI4LDFdLFszMCwwXSxbMzAsMl0sWzMxLDBdLFszMSwxXSxbMzIsMF0sWzMyLDFdLFszNSwwXSxbMzUsMl0sWzM2LDBdLFszNiwxXSxbMzcsMF0sWzM3LDFdLFs0MCwwXSxbNDAsMl0sWzQxLDBdLFs0MSwxXSxbNDIsMF0sWzQyLDFdLFs0NiwwXSxbNDYsMV0sWzQ5LDBdLFs0OSwyXSxbNTAsMF0sWzUwLDFdLFs1MiwwXSxbNTIsMl0sWzUzLDBdLFs1MywxXSxbNTcsMF0sWzU3LDJdLFs1OCwwXSxbNTgsMV0sWzYxLDBdLFs2MSwyXSxbNjIsMF0sWzYyLDFdLFs2NiwwXSxbNjYsMl0sWzY3LDBdLFs2NywxXSxbNzAsMV0sWzcwLDJdLFs3NiwxXSxbNzYsMl1dLFxucGVyZm9ybUFjdGlvbjogZnVuY3Rpb24gYW5vbnltb3VzKHl5dGV4dCx5eWxlbmcseXlsaW5lbm8seXkseXlzdGF0ZSwkJCxfJFxuLyoqLykge1xuXG52YXIgJDAgPSAkJC5sZW5ndGggLSAxO1xuc3dpdGNoICh5eXN0YXRlKSB7XG5jYXNlIDE6IHJldHVybiAkJFskMC0xXTsgXG5icmVhaztcbmNhc2UgMjp0aGlzLiQgPSB5eS5wcmVwYXJlUHJvZ3JhbSgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDM6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDQ6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDU6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDY6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDc6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDg6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDk6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ0NvbW1lbnRTdGF0ZW1lbnQnLFxuICAgICAgdmFsdWU6IHl5LnN0cmlwQ29tbWVudCgkJFskMF0pLFxuICAgICAgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDBdLCAkJFskMF0pLFxuICAgICAgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpXG4gICAgfTtcbiAgXG5icmVhaztcbmNhc2UgMTA6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ0NvbnRlbnRTdGF0ZW1lbnQnLFxuICAgICAgb3JpZ2luYWw6ICQkWyQwXSxcbiAgICAgIHZhbHVlOiAkJFskMF0sXG4gICAgICBsb2M6IHl5LmxvY0luZm8odGhpcy5fJClcbiAgICB9O1xuICBcbmJyZWFrO1xuY2FzZSAxMTp0aGlzLiQgPSB5eS5wcmVwYXJlUmF3QmxvY2soJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMF0sIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDEyOnRoaXMuJCA9IHsgcGF0aDogJCRbJDAtM10sIHBhcmFtczogJCRbJDAtMl0sIGhhc2g6ICQkWyQwLTFdIH07XG5icmVhaztcbmNhc2UgMTM6dGhpcy4kID0geXkucHJlcGFyZUJsb2NrKCQkWyQwLTNdLCAkJFskMC0yXSwgJCRbJDAtMV0sICQkWyQwXSwgZmFsc2UsIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDE0OnRoaXMuJCA9IHl5LnByZXBhcmVCbG9jaygkJFskMC0zXSwgJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMF0sIHRydWUsIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDE1OnRoaXMuJCA9IHsgb3BlbjogJCRbJDAtNV0sIHBhdGg6ICQkWyQwLTRdLCBwYXJhbXM6ICQkWyQwLTNdLCBoYXNoOiAkJFskMC0yXSwgYmxvY2tQYXJhbXM6ICQkWyQwLTFdLCBzdHJpcDogeXkuc3RyaXBGbGFncygkJFskMC01XSwgJCRbJDBdKSB9O1xuYnJlYWs7XG5jYXNlIDE2OnRoaXMuJCA9IHsgcGF0aDogJCRbJDAtNF0sIHBhcmFtczogJCRbJDAtM10sIGhhc2g6ICQkWyQwLTJdLCBibG9ja1BhcmFtczogJCRbJDAtMV0sIHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTVdLCAkJFskMF0pIH07XG5icmVhaztcbmNhc2UgMTc6dGhpcy4kID0geyBwYXRoOiAkJFskMC00XSwgcGFyYW1zOiAkJFskMC0zXSwgaGFzaDogJCRbJDAtMl0sIGJsb2NrUGFyYW1zOiAkJFskMC0xXSwgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNV0sICQkWyQwXSkgfTtcbmJyZWFrO1xuY2FzZSAxODp0aGlzLiQgPSB7IHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTFdLCAkJFskMC0xXSksIHByb2dyYW06ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDE5OlxuICAgIHZhciBpbnZlcnNlID0geXkucHJlcGFyZUJsb2NrKCQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDBdLCAkJFskMF0sIGZhbHNlLCB0aGlzLl8kKSxcbiAgICAgICAgcHJvZ3JhbSA9IHl5LnByZXBhcmVQcm9ncmFtKFtpbnZlcnNlXSwgJCRbJDAtMV0ubG9jKTtcbiAgICBwcm9ncmFtLmNoYWluZWQgPSB0cnVlO1xuXG4gICAgdGhpcy4kID0geyBzdHJpcDogJCRbJDAtMl0uc3RyaXAsIHByb2dyYW06IHByb2dyYW0sIGNoYWluOiB0cnVlIH07XG4gIFxuYnJlYWs7XG5jYXNlIDIwOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSAyMTp0aGlzLiQgPSB7cGF0aDogJCRbJDAtMV0sIHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTJdLCAkJFskMF0pfTtcbmJyZWFrO1xuY2FzZSAyMjp0aGlzLiQgPSB5eS5wcmVwYXJlTXVzdGFjaGUoJCRbJDAtM10sICQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDAtNF0sIHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSksIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDIzOnRoaXMuJCA9IHl5LnByZXBhcmVNdXN0YWNoZSgkJFskMC0zXSwgJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMC00XSwgeXkuc3RyaXBGbGFncygkJFskMC00XSwgJCRbJDBdKSwgdGhpcy5fJCk7XG5icmVhaztcbmNhc2UgMjQ6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ1BhcnRpYWxTdGF0ZW1lbnQnLFxuICAgICAgbmFtZTogJCRbJDAtM10sXG4gICAgICBwYXJhbXM6ICQkWyQwLTJdLFxuICAgICAgaGFzaDogJCRbJDAtMV0sXG4gICAgICBpbmRlbnQ6ICcnLFxuICAgICAgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSksXG4gICAgICBsb2M6IHl5LmxvY0luZm8odGhpcy5fJClcbiAgICB9O1xuICBcbmJyZWFrO1xuY2FzZSAyNTp0aGlzLiQgPSB5eS5wcmVwYXJlUGFydGlhbEJsb2NrKCQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSAyNjp0aGlzLiQgPSB7IHBhdGg6ICQkWyQwLTNdLCBwYXJhbXM6ICQkWyQwLTJdLCBoYXNoOiAkJFskMC0xXSwgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSkgfTtcbmJyZWFrO1xuY2FzZSAyNzp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgMjg6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDI5OlxuICAgIHRoaXMuJCA9IHtcbiAgICAgIHR5cGU6ICdTdWJFeHByZXNzaW9uJyxcbiAgICAgIHBhdGg6ICQkWyQwLTNdLFxuICAgICAgcGFyYW1zOiAkJFskMC0yXSxcbiAgICAgIGhhc2g6ICQkWyQwLTFdLFxuICAgICAgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpXG4gICAgfTtcbiAgXG5icmVhaztcbmNhc2UgMzA6dGhpcy4kID0ge3R5cGU6ICdIYXNoJywgcGFpcnM6ICQkWyQwXSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzMTp0aGlzLiQgPSB7dHlwZTogJ0hhc2hQYWlyJywga2V5OiB5eS5pZCgkJFskMC0yXSksIHZhbHVlOiAkJFskMF0sIGxvYzogeXkubG9jSW5mbyh0aGlzLl8kKX07XG5icmVhaztcbmNhc2UgMzI6dGhpcy4kID0geXkuaWQoJCRbJDAtMV0pO1xuYnJlYWs7XG5jYXNlIDMzOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSAzNDp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgMzU6dGhpcy4kID0ge3R5cGU6ICdTdHJpbmdMaXRlcmFsJywgdmFsdWU6ICQkWyQwXSwgb3JpZ2luYWw6ICQkWyQwXSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzNjp0aGlzLiQgPSB7dHlwZTogJ051bWJlckxpdGVyYWwnLCB2YWx1ZTogTnVtYmVyKCQkWyQwXSksIG9yaWdpbmFsOiBOdW1iZXIoJCRbJDBdKSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzNzp0aGlzLiQgPSB7dHlwZTogJ0Jvb2xlYW5MaXRlcmFsJywgdmFsdWU6ICQkWyQwXSA9PT0gJ3RydWUnLCBvcmlnaW5hbDogJCRbJDBdID09PSAndHJ1ZScsIGxvYzogeXkubG9jSW5mbyh0aGlzLl8kKX07XG5icmVhaztcbmNhc2UgMzg6dGhpcy4kID0ge3R5cGU6ICdVbmRlZmluZWRMaXRlcmFsJywgb3JpZ2luYWw6IHVuZGVmaW5lZCwgdmFsdWU6IHVuZGVmaW5lZCwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzOTp0aGlzLiQgPSB7dHlwZTogJ051bGxMaXRlcmFsJywgb3JpZ2luYWw6IG51bGwsIHZhbHVlOiBudWxsLCBsb2M6IHl5LmxvY0luZm8odGhpcy5fJCl9O1xuYnJlYWs7XG5jYXNlIDQwOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSA0MTp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgNDI6dGhpcy4kID0geXkucHJlcGFyZVBhdGgodHJ1ZSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSA0Mzp0aGlzLiQgPSB5eS5wcmVwYXJlUGF0aChmYWxzZSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSA0NDogJCRbJDAtMl0ucHVzaCh7cGFydDogeXkuaWQoJCRbJDBdKSwgb3JpZ2luYWw6ICQkWyQwXSwgc2VwYXJhdG9yOiAkJFskMC0xXX0pOyB0aGlzLiQgPSAkJFskMC0yXTsgXG5icmVhaztcbmNhc2UgNDU6dGhpcy4kID0gW3twYXJ0OiB5eS5pZCgkJFskMF0pLCBvcmlnaW5hbDogJCRbJDBdfV07XG5icmVhaztcbmNhc2UgNDY6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNDc6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDQ4OnRoaXMuJCA9IFskJFskMF1dO1xuYnJlYWs7XG5jYXNlIDQ5OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA1MDp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA1MTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgNTg6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNTk6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDY0OnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDY1OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA3MDp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA3MTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgNzg6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNzk6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDgyOnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDgzOiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA4Njp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA4NzokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgOTA6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgOTE6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDk0OnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDk1OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA5ODp0aGlzLiQgPSBbJCRbJDBdXTtcbmJyZWFrO1xuY2FzZSA5OTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgMTAwOnRoaXMuJCA9IFskJFskMF1dO1xuYnJlYWs7XG5jYXNlIDEwMTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbn1cbn0sXG50YWJsZTogW3szOjEsNDoyLDU6WzIsNDZdLDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezE6WzNdfSx7NTpbMSw0XX0sezU6WzIsMl0sNzo1LDg6Niw5OjcsMTA6OCwxMTo5LDEyOjEwLDEzOjExLDE0OlsxLDEyXSwxNTpbMSwyMF0sMTY6MTcsMTk6WzEsMjNdLDI0OjE1LDI3OjE2LDI5OlsxLDIxXSwzNDpbMSwyMl0sMzk6WzIsMl0sNDQ6WzIsMl0sNDc6WzIsMl0sNDg6WzEsMTNdLDUxOlsxLDE0XSw1NTpbMSwxOF0sNTk6MTksNjA6WzEsMjRdfSx7MTpbMiwxXX0sezU6WzIsNDddLDE0OlsyLDQ3XSwxNTpbMiw0N10sMTk6WzIsNDddLDI5OlsyLDQ3XSwzNDpbMiw0N10sMzk6WzIsNDddLDQ0OlsyLDQ3XSw0NzpbMiw0N10sNDg6WzIsNDddLDUxOlsyLDQ3XSw1NTpbMiw0N10sNjA6WzIsNDddfSx7NTpbMiwzXSwxNDpbMiwzXSwxNTpbMiwzXSwxOTpbMiwzXSwyOTpbMiwzXSwzNDpbMiwzXSwzOTpbMiwzXSw0NDpbMiwzXSw0NzpbMiwzXSw0ODpbMiwzXSw1MTpbMiwzXSw1NTpbMiwzXSw2MDpbMiwzXX0sezU6WzIsNF0sMTQ6WzIsNF0sMTU6WzIsNF0sMTk6WzIsNF0sMjk6WzIsNF0sMzQ6WzIsNF0sMzk6WzIsNF0sNDQ6WzIsNF0sNDc6WzIsNF0sNDg6WzIsNF0sNTE6WzIsNF0sNTU6WzIsNF0sNjA6WzIsNF19LHs1OlsyLDVdLDE0OlsyLDVdLDE1OlsyLDVdLDE5OlsyLDVdLDI5OlsyLDVdLDM0OlsyLDVdLDM5OlsyLDVdLDQ0OlsyLDVdLDQ3OlsyLDVdLDQ4OlsyLDVdLDUxOlsyLDVdLDU1OlsyLDVdLDYwOlsyLDVdfSx7NTpbMiw2XSwxNDpbMiw2XSwxNTpbMiw2XSwxOTpbMiw2XSwyOTpbMiw2XSwzNDpbMiw2XSwzOTpbMiw2XSw0NDpbMiw2XSw0NzpbMiw2XSw0ODpbMiw2XSw1MTpbMiw2XSw1NTpbMiw2XSw2MDpbMiw2XX0sezU6WzIsN10sMTQ6WzIsN10sMTU6WzIsN10sMTk6WzIsN10sMjk6WzIsN10sMzQ6WzIsN10sMzk6WzIsN10sNDQ6WzIsN10sNDc6WzIsN10sNDg6WzIsN10sNTE6WzIsN10sNTU6WzIsN10sNjA6WzIsN119LHs1OlsyLDhdLDE0OlsyLDhdLDE1OlsyLDhdLDE5OlsyLDhdLDI5OlsyLDhdLDM0OlsyLDhdLDM5OlsyLDhdLDQ0OlsyLDhdLDQ3OlsyLDhdLDQ4OlsyLDhdLDUxOlsyLDhdLDU1OlsyLDhdLDYwOlsyLDhdfSx7NTpbMiw5XSwxNDpbMiw5XSwxNTpbMiw5XSwxOTpbMiw5XSwyOTpbMiw5XSwzNDpbMiw5XSwzOTpbMiw5XSw0NDpbMiw5XSw0NzpbMiw5XSw0ODpbMiw5XSw1MTpbMiw5XSw1NTpbMiw5XSw2MDpbMiw5XX0sezIwOjI1LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjM2LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezQ6MzcsNjozLDE0OlsyLDQ2XSwxNTpbMiw0Nl0sMTk6WzIsNDZdLDI5OlsyLDQ2XSwzNDpbMiw0Nl0sMzk6WzIsNDZdLDQ0OlsyLDQ2XSw0NzpbMiw0Nl0sNDg6WzIsNDZdLDUxOlsyLDQ2XSw1NTpbMiw0Nl0sNjA6WzIsNDZdfSx7NDozOCw2OjMsMTQ6WzIsNDZdLDE1OlsyLDQ2XSwxOTpbMiw0Nl0sMjk6WzIsNDZdLDM0OlsyLDQ2XSw0NDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezEzOjQwLDE1OlsxLDIwXSwxNzozOX0sezIwOjQyLDU2OjQxLDY0OjQzLDY1OlsxLDQ0XSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs0OjQ1LDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDQ3OlsyLDQ2XSw0ODpbMiw0Nl0sNTE6WzIsNDZdLDU1OlsyLDQ2XSw2MDpbMiw0Nl19LHs1OlsyLDEwXSwxNDpbMiwxMF0sMTU6WzIsMTBdLDE4OlsyLDEwXSwxOTpbMiwxMF0sMjk6WzIsMTBdLDM0OlsyLDEwXSwzOTpbMiwxMF0sNDQ6WzIsMTBdLDQ3OlsyLDEwXSw0ODpbMiwxMF0sNTE6WzIsMTBdLDU1OlsyLDEwXSw2MDpbMiwxMF19LHsyMDo0Niw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0Nyw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0OCw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0Miw1Njo0OSw2NDo0Myw2NTpbMSw0NF0sNzI6WzEsMzVdLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7MzM6WzIsNzhdLDQ5OjUwLDY1OlsyLDc4XSw3MjpbMiw3OF0sODA6WzIsNzhdLDgxOlsyLDc4XSw4MjpbMiw3OF0sODM6WzIsNzhdLDg0OlsyLDc4XSw4NTpbMiw3OF19LHsyMzpbMiwzM10sMzM6WzIsMzNdLDU0OlsyLDMzXSw2NTpbMiwzM10sNjg6WzIsMzNdLDcyOlsyLDMzXSw3NTpbMiwzM10sODA6WzIsMzNdLDgxOlsyLDMzXSw4MjpbMiwzM10sODM6WzIsMzNdLDg0OlsyLDMzXSw4NTpbMiwzM119LHsyMzpbMiwzNF0sMzM6WzIsMzRdLDU0OlsyLDM0XSw2NTpbMiwzNF0sNjg6WzIsMzRdLDcyOlsyLDM0XSw3NTpbMiwzNF0sODA6WzIsMzRdLDgxOlsyLDM0XSw4MjpbMiwzNF0sODM6WzIsMzRdLDg0OlsyLDM0XSw4NTpbMiwzNF19LHsyMzpbMiwzNV0sMzM6WzIsMzVdLDU0OlsyLDM1XSw2NTpbMiwzNV0sNjg6WzIsMzVdLDcyOlsyLDM1XSw3NTpbMiwzNV0sODA6WzIsMzVdLDgxOlsyLDM1XSw4MjpbMiwzNV0sODM6WzIsMzVdLDg0OlsyLDM1XSw4NTpbMiwzNV19LHsyMzpbMiwzNl0sMzM6WzIsMzZdLDU0OlsyLDM2XSw2NTpbMiwzNl0sNjg6WzIsMzZdLDcyOlsyLDM2XSw3NTpbMiwzNl0sODA6WzIsMzZdLDgxOlsyLDM2XSw4MjpbMiwzNl0sODM6WzIsMzZdLDg0OlsyLDM2XSw4NTpbMiwzNl19LHsyMzpbMiwzN10sMzM6WzIsMzddLDU0OlsyLDM3XSw2NTpbMiwzN10sNjg6WzIsMzddLDcyOlsyLDM3XSw3NTpbMiwzN10sODA6WzIsMzddLDgxOlsyLDM3XSw4MjpbMiwzN10sODM6WzIsMzddLDg0OlsyLDM3XSw4NTpbMiwzN119LHsyMzpbMiwzOF0sMzM6WzIsMzhdLDU0OlsyLDM4XSw2NTpbMiwzOF0sNjg6WzIsMzhdLDcyOlsyLDM4XSw3NTpbMiwzOF0sODA6WzIsMzhdLDgxOlsyLDM4XSw4MjpbMiwzOF0sODM6WzIsMzhdLDg0OlsyLDM4XSw4NTpbMiwzOF19LHsyMzpbMiwzOV0sMzM6WzIsMzldLDU0OlsyLDM5XSw2NTpbMiwzOV0sNjg6WzIsMzldLDcyOlsyLDM5XSw3NTpbMiwzOV0sODA6WzIsMzldLDgxOlsyLDM5XSw4MjpbMiwzOV0sODM6WzIsMzldLDg0OlsyLDM5XSw4NTpbMiwzOV19LHsyMzpbMiw0M10sMzM6WzIsNDNdLDU0OlsyLDQzXSw2NTpbMiw0M10sNjg6WzIsNDNdLDcyOlsyLDQzXSw3NTpbMiw0M10sODA6WzIsNDNdLDgxOlsyLDQzXSw4MjpbMiw0M10sODM6WzIsNDNdLDg0OlsyLDQzXSw4NTpbMiw0M10sODc6WzEsNTFdfSx7NzI6WzEsMzVdLDg2OjUyfSx7MjM6WzIsNDVdLDMzOlsyLDQ1XSw1NDpbMiw0NV0sNjU6WzIsNDVdLDY4OlsyLDQ1XSw3MjpbMiw0NV0sNzU6WzIsNDVdLDgwOlsyLDQ1XSw4MTpbMiw0NV0sODI6WzIsNDVdLDgzOlsyLDQ1XSw4NDpbMiw0NV0sODU6WzIsNDVdLDg3OlsyLDQ1XX0sezUyOjUzLDU0OlsyLDgyXSw2NTpbMiw4Ml0sNzI6WzIsODJdLDgwOlsyLDgyXSw4MTpbMiw4Ml0sODI6WzIsODJdLDgzOlsyLDgyXSw4NDpbMiw4Ml0sODU6WzIsODJdfSx7MjU6NTQsMzg6NTYsMzk6WzEsNThdLDQzOjU3LDQ0OlsxLDU5XSw0NTo1NSw0NzpbMiw1NF19LHsyODo2MCw0Mzo2MSw0NDpbMSw1OV0sNDc6WzIsNTZdfSx7MTM6NjMsMTU6WzEsMjBdLDE4OlsxLDYyXX0sezE1OlsyLDQ4XSwxODpbMiw0OF19LHszMzpbMiw4Nl0sNTc6NjQsNjU6WzIsODZdLDcyOlsyLDg2XSw4MDpbMiw4Nl0sODE6WzIsODZdLDgyOlsyLDg2XSw4MzpbMiw4Nl0sODQ6WzIsODZdLDg1OlsyLDg2XX0sezMzOlsyLDQwXSw2NTpbMiw0MF0sNzI6WzIsNDBdLDgwOlsyLDQwXSw4MTpbMiw0MF0sODI6WzIsNDBdLDgzOlsyLDQwXSw4NDpbMiw0MF0sODU6WzIsNDBdfSx7MzM6WzIsNDFdLDY1OlsyLDQxXSw3MjpbMiw0MV0sODA6WzIsNDFdLDgxOlsyLDQxXSw4MjpbMiw0MV0sODM6WzIsNDFdLDg0OlsyLDQxXSw4NTpbMiw0MV19LHsyMDo2NSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyNjo2Niw0NzpbMSw2N119LHszMDo2OCwzMzpbMiw1OF0sNjU6WzIsNThdLDcyOlsyLDU4XSw3NTpbMiw1OF0sODA6WzIsNThdLDgxOlsyLDU4XSw4MjpbMiw1OF0sODM6WzIsNThdLDg0OlsyLDU4XSw4NTpbMiw1OF19LHszMzpbMiw2NF0sMzU6NjksNjU6WzIsNjRdLDcyOlsyLDY0XSw3NTpbMiw2NF0sODA6WzIsNjRdLDgxOlsyLDY0XSw4MjpbMiw2NF0sODM6WzIsNjRdLDg0OlsyLDY0XSw4NTpbMiw2NF19LHsyMTo3MCwyMzpbMiw1MF0sNjU6WzIsNTBdLDcyOlsyLDUwXSw4MDpbMiw1MF0sODE6WzIsNTBdLDgyOlsyLDUwXSw4MzpbMiw1MF0sODQ6WzIsNTBdLDg1OlsyLDUwXX0sezMzOlsyLDkwXSw2MTo3MSw2NTpbMiw5MF0sNzI6WzIsOTBdLDgwOlsyLDkwXSw4MTpbMiw5MF0sODI6WzIsOTBdLDgzOlsyLDkwXSw4NDpbMiw5MF0sODU6WzIsOTBdfSx7MjA6NzUsMzM6WzIsODBdLDUwOjcyLDYzOjczLDY0Ojc2LDY1OlsxLDQ0XSw2OTo3NCw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs3MjpbMSw4MF19LHsyMzpbMiw0Ml0sMzM6WzIsNDJdLDU0OlsyLDQyXSw2NTpbMiw0Ml0sNjg6WzIsNDJdLDcyOlsyLDQyXSw3NTpbMiw0Ml0sODA6WzIsNDJdLDgxOlsyLDQyXSw4MjpbMiw0Ml0sODM6WzIsNDJdLDg0OlsyLDQyXSw4NTpbMiw0Ml0sODc6WzEsNTFdfSx7MjA6NzUsNTM6ODEsNTQ6WzIsODRdLDYzOjgyLDY0Ojc2LDY1OlsxLDQ0XSw2OTo4Myw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyNjo4NCw0NzpbMSw2N119LHs0NzpbMiw1NV19LHs0Ojg1LDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDM5OlsyLDQ2XSw0NDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezQ3OlsyLDIwXX0sezIwOjg2LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezQ6ODcsNjozLDE0OlsyLDQ2XSwxNTpbMiw0Nl0sMTk6WzIsNDZdLDI5OlsyLDQ2XSwzNDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezI2Ojg4LDQ3OlsxLDY3XX0sezQ3OlsyLDU3XX0sezU6WzIsMTFdLDE0OlsyLDExXSwxNTpbMiwxMV0sMTk6WzIsMTFdLDI5OlsyLDExXSwzNDpbMiwxMV0sMzk6WzIsMTFdLDQ0OlsyLDExXSw0NzpbMiwxMV0sNDg6WzIsMTFdLDUxOlsyLDExXSw1NTpbMiwxMV0sNjA6WzIsMTFdfSx7MTU6WzIsNDldLDE4OlsyLDQ5XX0sezIwOjc1LDMzOlsyLDg4XSw1ODo4OSw2Mzo5MCw2NDo3Niw2NTpbMSw0NF0sNjk6OTEsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7NjU6WzIsOTRdLDY2OjkyLDY4OlsyLDk0XSw3MjpbMiw5NF0sODA6WzIsOTRdLDgxOlsyLDk0XSw4MjpbMiw5NF0sODM6WzIsOTRdLDg0OlsyLDk0XSw4NTpbMiw5NF19LHs1OlsyLDI1XSwxNDpbMiwyNV0sMTU6WzIsMjVdLDE5OlsyLDI1XSwyOTpbMiwyNV0sMzQ6WzIsMjVdLDM5OlsyLDI1XSw0NDpbMiwyNV0sNDc6WzIsMjVdLDQ4OlsyLDI1XSw1MTpbMiwyNV0sNTU6WzIsMjVdLDYwOlsyLDI1XX0sezIwOjkzLDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDMxOjk0LDMzOlsyLDYwXSw2Mzo5NSw2NDo3Niw2NTpbMSw0NF0sNjk6OTYsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDYwXSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDMzOlsyLDY2XSwzNjo5Nyw2Mzo5OCw2NDo3Niw2NTpbMSw0NF0sNjk6OTksNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDY2XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDIyOjEwMCwyMzpbMiw1Ml0sNjM6MTAxLDY0Ojc2LDY1OlsxLDQ0XSw2OToxMDIsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7MjA6NzUsMzM6WzIsOTJdLDYyOjEwMyw2MzoxMDQsNjQ6NzYsNjU6WzEsNDRdLDY5OjEwNSw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHszMzpbMSwxMDZdfSx7MzM6WzIsNzldLDY1OlsyLDc5XSw3MjpbMiw3OV0sODA6WzIsNzldLDgxOlsyLDc5XSw4MjpbMiw3OV0sODM6WzIsNzldLDg0OlsyLDc5XSw4NTpbMiw3OV19LHszMzpbMiw4MV19LHsyMzpbMiwyN10sMzM6WzIsMjddLDU0OlsyLDI3XSw2NTpbMiwyN10sNjg6WzIsMjddLDcyOlsyLDI3XSw3NTpbMiwyN10sODA6WzIsMjddLDgxOlsyLDI3XSw4MjpbMiwyN10sODM6WzIsMjddLDg0OlsyLDI3XSw4NTpbMiwyN119LHsyMzpbMiwyOF0sMzM6WzIsMjhdLDU0OlsyLDI4XSw2NTpbMiwyOF0sNjg6WzIsMjhdLDcyOlsyLDI4XSw3NTpbMiwyOF0sODA6WzIsMjhdLDgxOlsyLDI4XSw4MjpbMiwyOF0sODM6WzIsMjhdLDg0OlsyLDI4XSw4NTpbMiwyOF19LHsyMzpbMiwzMF0sMzM6WzIsMzBdLDU0OlsyLDMwXSw2ODpbMiwzMF0sNzE6MTA3LDcyOlsxLDEwOF0sNzU6WzIsMzBdfSx7MjM6WzIsOThdLDMzOlsyLDk4XSw1NDpbMiw5OF0sNjg6WzIsOThdLDcyOlsyLDk4XSw3NTpbMiw5OF19LHsyMzpbMiw0NV0sMzM6WzIsNDVdLDU0OlsyLDQ1XSw2NTpbMiw0NV0sNjg6WzIsNDVdLDcyOlsyLDQ1XSw3MzpbMSwxMDldLDc1OlsyLDQ1XSw4MDpbMiw0NV0sODE6WzIsNDVdLDgyOlsyLDQ1XSw4MzpbMiw0NV0sODQ6WzIsNDVdLDg1OlsyLDQ1XSw4NzpbMiw0NV19LHsyMzpbMiw0NF0sMzM6WzIsNDRdLDU0OlsyLDQ0XSw2NTpbMiw0NF0sNjg6WzIsNDRdLDcyOlsyLDQ0XSw3NTpbMiw0NF0sODA6WzIsNDRdLDgxOlsyLDQ0XSw4MjpbMiw0NF0sODM6WzIsNDRdLDg0OlsyLDQ0XSw4NTpbMiw0NF0sODc6WzIsNDRdfSx7NTQ6WzEsMTEwXX0sezU0OlsyLDgzXSw2NTpbMiw4M10sNzI6WzIsODNdLDgwOlsyLDgzXSw4MTpbMiw4M10sODI6WzIsODNdLDgzOlsyLDgzXSw4NDpbMiw4M10sODU6WzIsODNdfSx7NTQ6WzIsODVdfSx7NTpbMiwxM10sMTQ6WzIsMTNdLDE1OlsyLDEzXSwxOTpbMiwxM10sMjk6WzIsMTNdLDM0OlsyLDEzXSwzOTpbMiwxM10sNDQ6WzIsMTNdLDQ3OlsyLDEzXSw0ODpbMiwxM10sNTE6WzIsMTNdLDU1OlsyLDEzXSw2MDpbMiwxM119LHszODo1NiwzOTpbMSw1OF0sNDM6NTcsNDQ6WzEsNTldLDQ1OjExMiw0NjoxMTEsNDc6WzIsNzZdfSx7MzM6WzIsNzBdLDQwOjExMyw2NTpbMiw3MF0sNzI6WzIsNzBdLDc1OlsyLDcwXSw4MDpbMiw3MF0sODE6WzIsNzBdLDgyOlsyLDcwXSw4MzpbMiw3MF0sODQ6WzIsNzBdLDg1OlsyLDcwXX0sezQ3OlsyLDE4XX0sezU6WzIsMTRdLDE0OlsyLDE0XSwxNTpbMiwxNF0sMTk6WzIsMTRdLDI5OlsyLDE0XSwzNDpbMiwxNF0sMzk6WzIsMTRdLDQ0OlsyLDE0XSw0NzpbMiwxNF0sNDg6WzIsMTRdLDUxOlsyLDE0XSw1NTpbMiwxNF0sNjA6WzIsMTRdfSx7MzM6WzEsMTE0XX0sezMzOlsyLDg3XSw2NTpbMiw4N10sNzI6WzIsODddLDgwOlsyLDg3XSw4MTpbMiw4N10sODI6WzIsODddLDgzOlsyLDg3XSw4NDpbMiw4N10sODU6WzIsODddfSx7MzM6WzIsODldfSx7MjA6NzUsNjM6MTE2LDY0Ojc2LDY1OlsxLDQ0XSw2NzoxMTUsNjg6WzIsOTZdLDY5OjExNyw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHszMzpbMSwxMThdfSx7MzI6MTE5LDMzOlsyLDYyXSw3NDoxMjAsNzU6WzEsMTIxXX0sezMzOlsyLDU5XSw2NTpbMiw1OV0sNzI6WzIsNTldLDc1OlsyLDU5XSw4MDpbMiw1OV0sODE6WzIsNTldLDgyOlsyLDU5XSw4MzpbMiw1OV0sODQ6WzIsNTldLDg1OlsyLDU5XX0sezMzOlsyLDYxXSw3NTpbMiw2MV19LHszMzpbMiw2OF0sMzc6MTIyLDc0OjEyMyw3NTpbMSwxMjFdfSx7MzM6WzIsNjVdLDY1OlsyLDY1XSw3MjpbMiw2NV0sNzU6WzIsNjVdLDgwOlsyLDY1XSw4MTpbMiw2NV0sODI6WzIsNjVdLDgzOlsyLDY1XSw4NDpbMiw2NV0sODU6WzIsNjVdfSx7MzM6WzIsNjddLDc1OlsyLDY3XX0sezIzOlsxLDEyNF19LHsyMzpbMiw1MV0sNjU6WzIsNTFdLDcyOlsyLDUxXSw4MDpbMiw1MV0sODE6WzIsNTFdLDgyOlsyLDUxXSw4MzpbMiw1MV0sODQ6WzIsNTFdLDg1OlsyLDUxXX0sezIzOlsyLDUzXX0sezMzOlsxLDEyNV19LHszMzpbMiw5MV0sNjU6WzIsOTFdLDcyOlsyLDkxXSw4MDpbMiw5MV0sODE6WzIsOTFdLDgyOlsyLDkxXSw4MzpbMiw5MV0sODQ6WzIsOTFdLDg1OlsyLDkxXX0sezMzOlsyLDkzXX0sezU6WzIsMjJdLDE0OlsyLDIyXSwxNTpbMiwyMl0sMTk6WzIsMjJdLDI5OlsyLDIyXSwzNDpbMiwyMl0sMzk6WzIsMjJdLDQ0OlsyLDIyXSw0NzpbMiwyMl0sNDg6WzIsMjJdLDUxOlsyLDIyXSw1NTpbMiwyMl0sNjA6WzIsMjJdfSx7MjM6WzIsOTldLDMzOlsyLDk5XSw1NDpbMiw5OV0sNjg6WzIsOTldLDcyOlsyLDk5XSw3NTpbMiw5OV19LHs3MzpbMSwxMDldfSx7MjA6NzUsNjM6MTI2LDY0Ojc2LDY1OlsxLDQ0XSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs1OlsyLDIzXSwxNDpbMiwyM10sMTU6WzIsMjNdLDE5OlsyLDIzXSwyOTpbMiwyM10sMzQ6WzIsMjNdLDM5OlsyLDIzXSw0NDpbMiwyM10sNDc6WzIsMjNdLDQ4OlsyLDIzXSw1MTpbMiwyM10sNTU6WzIsMjNdLDYwOlsyLDIzXX0sezQ3OlsyLDE5XX0sezQ3OlsyLDc3XX0sezIwOjc1LDMzOlsyLDcyXSw0MToxMjcsNjM6MTI4LDY0Ojc2LDY1OlsxLDQ0XSw2OToxMjksNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDcyXSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezU6WzIsMjRdLDE0OlsyLDI0XSwxNTpbMiwyNF0sMTk6WzIsMjRdLDI5OlsyLDI0XSwzNDpbMiwyNF0sMzk6WzIsMjRdLDQ0OlsyLDI0XSw0NzpbMiwyNF0sNDg6WzIsMjRdLDUxOlsyLDI0XSw1NTpbMiwyNF0sNjA6WzIsMjRdfSx7Njg6WzEsMTMwXX0sezY1OlsyLDk1XSw2ODpbMiw5NV0sNzI6WzIsOTVdLDgwOlsyLDk1XSw4MTpbMiw5NV0sODI6WzIsOTVdLDgzOlsyLDk1XSw4NDpbMiw5NV0sODU6WzIsOTVdfSx7Njg6WzIsOTddfSx7NTpbMiwyMV0sMTQ6WzIsMjFdLDE1OlsyLDIxXSwxOTpbMiwyMV0sMjk6WzIsMjFdLDM0OlsyLDIxXSwzOTpbMiwyMV0sNDQ6WzIsMjFdLDQ3OlsyLDIxXSw0ODpbMiwyMV0sNTE6WzIsMjFdLDU1OlsyLDIxXSw2MDpbMiwyMV19LHszMzpbMSwxMzFdfSx7MzM6WzIsNjNdfSx7NzI6WzEsMTMzXSw3NjoxMzJ9LHszMzpbMSwxMzRdfSx7MzM6WzIsNjldfSx7MTU6WzIsMTJdfSx7MTQ6WzIsMjZdLDE1OlsyLDI2XSwxOTpbMiwyNl0sMjk6WzIsMjZdLDM0OlsyLDI2XSw0NzpbMiwyNl0sNDg6WzIsMjZdLDUxOlsyLDI2XSw1NTpbMiwyNl0sNjA6WzIsMjZdfSx7MjM6WzIsMzFdLDMzOlsyLDMxXSw1NDpbMiwzMV0sNjg6WzIsMzFdLDcyOlsyLDMxXSw3NTpbMiwzMV19LHszMzpbMiw3NF0sNDI6MTM1LDc0OjEzNiw3NTpbMSwxMjFdfSx7MzM6WzIsNzFdLDY1OlsyLDcxXSw3MjpbMiw3MV0sNzU6WzIsNzFdLDgwOlsyLDcxXSw4MTpbMiw3MV0sODI6WzIsNzFdLDgzOlsyLDcxXSw4NDpbMiw3MV0sODU6WzIsNzFdfSx7MzM6WzIsNzNdLDc1OlsyLDczXX0sezIzOlsyLDI5XSwzMzpbMiwyOV0sNTQ6WzIsMjldLDY1OlsyLDI5XSw2ODpbMiwyOV0sNzI6WzIsMjldLDc1OlsyLDI5XSw4MDpbMiwyOV0sODE6WzIsMjldLDgyOlsyLDI5XSw4MzpbMiwyOV0sODQ6WzIsMjldLDg1OlsyLDI5XX0sezE0OlsyLDE1XSwxNTpbMiwxNV0sMTk6WzIsMTVdLDI5OlsyLDE1XSwzNDpbMiwxNV0sMzk6WzIsMTVdLDQ0OlsyLDE1XSw0NzpbMiwxNV0sNDg6WzIsMTVdLDUxOlsyLDE1XSw1NTpbMiwxNV0sNjA6WzIsMTVdfSx7NzI6WzEsMTM4XSw3NzpbMSwxMzddfSx7NzI6WzIsMTAwXSw3NzpbMiwxMDBdfSx7MTQ6WzIsMTZdLDE1OlsyLDE2XSwxOTpbMiwxNl0sMjk6WzIsMTZdLDM0OlsyLDE2XSw0NDpbMiwxNl0sNDc6WzIsMTZdLDQ4OlsyLDE2XSw1MTpbMiwxNl0sNTU6WzIsMTZdLDYwOlsyLDE2XX0sezMzOlsxLDEzOV19LHszMzpbMiw3NV19LHszMzpbMiwzMl19LHs3MjpbMiwxMDFdLDc3OlsyLDEwMV19LHsxNDpbMiwxN10sMTU6WzIsMTddLDE5OlsyLDE3XSwyOTpbMiwxN10sMzQ6WzIsMTddLDM5OlsyLDE3XSw0NDpbMiwxN10sNDc6WzIsMTddLDQ4OlsyLDE3XSw1MTpbMiwxN10sNTU6WzIsMTddLDYwOlsyLDE3XX1dLFxuZGVmYXVsdEFjdGlvbnM6IHs0OlsyLDFdLDU1OlsyLDU1XSw1NzpbMiwyMF0sNjE6WzIsNTddLDc0OlsyLDgxXSw4MzpbMiw4NV0sODc6WzIsMThdLDkxOlsyLDg5XSwxMDI6WzIsNTNdLDEwNTpbMiw5M10sMTExOlsyLDE5XSwxMTI6WzIsNzddLDExNzpbMiw5N10sMTIwOlsyLDYzXSwxMjM6WzIsNjldLDEyNDpbMiwxMl0sMTM2OlsyLDc1XSwxMzc6WzIsMzJdfSxcbnBhcnNlRXJyb3I6IGZ1bmN0aW9uIHBhcnNlRXJyb3Ioc3RyLCBoYXNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHN0cik7XG59LFxucGFyc2U6IGZ1bmN0aW9uIHBhcnNlKGlucHV0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzLCBzdGFjayA9IFswXSwgdnN0YWNrID0gW251bGxdLCBsc3RhY2sgPSBbXSwgdGFibGUgPSB0aGlzLnRhYmxlLCB5eXRleHQgPSBcIlwiLCB5eWxpbmVubyA9IDAsIHl5bGVuZyA9IDAsIHJlY292ZXJpbmcgPSAwLCBURVJST1IgPSAyLCBFT0YgPSAxO1xuICAgIHRoaXMubGV4ZXIuc2V0SW5wdXQoaW5wdXQpO1xuICAgIHRoaXMubGV4ZXIueXkgPSB0aGlzLnl5O1xuICAgIHRoaXMueXkubGV4ZXIgPSB0aGlzLmxleGVyO1xuICAgIHRoaXMueXkucGFyc2VyID0gdGhpcztcbiAgICBpZiAodHlwZW9mIHRoaXMubGV4ZXIueXlsbG9jID09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgIHRoaXMubGV4ZXIueXlsbG9jID0ge307XG4gICAgdmFyIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgbHN0YWNrLnB1c2goeXlsb2MpO1xuICAgIHZhciByYW5nZXMgPSB0aGlzLmxleGVyLm9wdGlvbnMgJiYgdGhpcy5sZXhlci5vcHRpb25zLnJhbmdlcztcbiAgICBpZiAodHlwZW9mIHRoaXMueXkucGFyc2VFcnJvciA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSB0aGlzLnl5LnBhcnNlRXJyb3I7XG4gICAgZnVuY3Rpb24gcG9wU3RhY2sobikge1xuICAgICAgICBzdGFjay5sZW5ndGggPSBzdGFjay5sZW5ndGggLSAyICogbjtcbiAgICAgICAgdnN0YWNrLmxlbmd0aCA9IHZzdGFjay5sZW5ndGggLSBuO1xuICAgICAgICBsc3RhY2subGVuZ3RoID0gbHN0YWNrLmxlbmd0aCAtIG47XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxleCgpIHtcbiAgICAgICAgdmFyIHRva2VuO1xuICAgICAgICB0b2tlbiA9IHNlbGYubGV4ZXIubGV4KCkgfHwgMTtcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdG9rZW4gPSBzZWxmLnN5bWJvbHNfW3Rva2VuXSB8fCB0b2tlbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9rZW47XG4gICAgfVxuICAgIHZhciBzeW1ib2wsIHByZUVycm9yU3ltYm9sLCBzdGF0ZSwgYWN0aW9uLCBhLCByLCB5eXZhbCA9IHt9LCBwLCBsZW4sIG5ld1N0YXRlLCBleHBlY3RlZDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBzdGF0ZSA9IHN0YWNrW3N0YWNrLmxlbmd0aCAtIDFdO1xuICAgICAgICBpZiAodGhpcy5kZWZhdWx0QWN0aW9uc1tzdGF0ZV0pIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IHRoaXMuZGVmYXVsdEFjdGlvbnNbc3RhdGVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHN5bWJvbCA9PT0gbnVsbCB8fCB0eXBlb2Ygc3ltYm9sID09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICBzeW1ib2wgPSBsZXgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjdGlvbiA9IHRhYmxlW3N0YXRlXSAmJiB0YWJsZVtzdGF0ZV1bc3ltYm9sXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGFjdGlvbiA9PT0gXCJ1bmRlZmluZWRcIiB8fCAhYWN0aW9uLmxlbmd0aCB8fCAhYWN0aW9uWzBdKSB7XG4gICAgICAgICAgICB2YXIgZXJyU3RyID0gXCJcIjtcbiAgICAgICAgICAgIGlmICghcmVjb3ZlcmluZykge1xuICAgICAgICAgICAgICAgIGV4cGVjdGVkID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChwIGluIHRhYmxlW3N0YXRlXSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudGVybWluYWxzX1twXSAmJiBwID4gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQucHVzaChcIidcIiArIHRoaXMudGVybWluYWxzX1twXSArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxleGVyLnNob3dQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBlcnJTdHIgPSBcIlBhcnNlIGVycm9yIG9uIGxpbmUgXCIgKyAoeXlsaW5lbm8gKyAxKSArIFwiOlxcblwiICsgdGhpcy5sZXhlci5zaG93UG9zaXRpb24oKSArIFwiXFxuRXhwZWN0aW5nIFwiICsgZXhwZWN0ZWQuam9pbihcIiwgXCIpICsgXCIsIGdvdCAnXCIgKyAodGhpcy50ZXJtaW5hbHNfW3N5bWJvbF0gfHwgc3ltYm9sKSArIFwiJ1wiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVyclN0ciA9IFwiUGFyc2UgZXJyb3Igb24gbGluZSBcIiArICh5eWxpbmVubyArIDEpICsgXCI6IFVuZXhwZWN0ZWQgXCIgKyAoc3ltYm9sID09IDE/XCJlbmQgb2YgaW5wdXRcIjpcIidcIiArICh0aGlzLnRlcm1pbmFsc19bc3ltYm9sXSB8fCBzeW1ib2wpICsgXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IoZXJyU3RyLCB7dGV4dDogdGhpcy5sZXhlci5tYXRjaCwgdG9rZW46IHRoaXMudGVybWluYWxzX1tzeW1ib2xdIHx8IHN5bWJvbCwgbGluZTogdGhpcy5sZXhlci55eWxpbmVubywgbG9jOiB5eWxvYywgZXhwZWN0ZWQ6IGV4cGVjdGVkfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGlvblswXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFjdGlvbi5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQYXJzZSBFcnJvcjogbXVsdGlwbGUgYWN0aW9ucyBwb3NzaWJsZSBhdCBzdGF0ZTogXCIgKyBzdGF0ZSArIFwiLCB0b2tlbjogXCIgKyBzeW1ib2wpO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uWzBdKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHN0YWNrLnB1c2goc3ltYm9sKTtcbiAgICAgICAgICAgIHZzdGFjay5wdXNoKHRoaXMubGV4ZXIueXl0ZXh0KTtcbiAgICAgICAgICAgIGxzdGFjay5wdXNoKHRoaXMubGV4ZXIueXlsbG9jKTtcbiAgICAgICAgICAgIHN0YWNrLnB1c2goYWN0aW9uWzFdKTtcbiAgICAgICAgICAgIHN5bWJvbCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIXByZUVycm9yU3ltYm9sKSB7XG4gICAgICAgICAgICAgICAgeXlsZW5nID0gdGhpcy5sZXhlci55eWxlbmc7XG4gICAgICAgICAgICAgICAgeXl0ZXh0ID0gdGhpcy5sZXhlci55eXRleHQ7XG4gICAgICAgICAgICAgICAgeXlsaW5lbm8gPSB0aGlzLmxleGVyLnl5bGluZW5vO1xuICAgICAgICAgICAgICAgIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgICAgICAgICAgICAgaWYgKHJlY292ZXJpbmcgPiAwKVxuICAgICAgICAgICAgICAgICAgICByZWNvdmVyaW5nLS07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN5bWJvbCA9IHByZUVycm9yU3ltYm9sO1xuICAgICAgICAgICAgICAgIHByZUVycm9yU3ltYm9sID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICBsZW4gPSB0aGlzLnByb2R1Y3Rpb25zX1thY3Rpb25bMV1dWzFdO1xuICAgICAgICAgICAgeXl2YWwuJCA9IHZzdGFja1t2c3RhY2subGVuZ3RoIC0gbGVuXTtcbiAgICAgICAgICAgIHl5dmFsLl8kID0ge2ZpcnN0X2xpbmU6IGxzdGFja1tsc3RhY2subGVuZ3RoIC0gKGxlbiB8fCAxKV0uZmlyc3RfbGluZSwgbGFzdF9saW5lOiBsc3RhY2tbbHN0YWNrLmxlbmd0aCAtIDFdLmxhc3RfbGluZSwgZmlyc3RfY29sdW1uOiBsc3RhY2tbbHN0YWNrLmxlbmd0aCAtIChsZW4gfHwgMSldLmZpcnN0X2NvbHVtbiwgbGFzdF9jb2x1bW46IGxzdGFja1tsc3RhY2subGVuZ3RoIC0gMV0ubGFzdF9jb2x1bW59O1xuICAgICAgICAgICAgaWYgKHJhbmdlcykge1xuICAgICAgICAgICAgICAgIHl5dmFsLl8kLnJhbmdlID0gW2xzdGFja1tsc3RhY2subGVuZ3RoIC0gKGxlbiB8fCAxKV0ucmFuZ2VbMF0sIGxzdGFja1tsc3RhY2subGVuZ3RoIC0gMV0ucmFuZ2VbMV1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgciA9IHRoaXMucGVyZm9ybUFjdGlvbi5jYWxsKHl5dmFsLCB5eXRleHQsIHl5bGVuZywgeXlsaW5lbm8sIHRoaXMueXksIGFjdGlvblsxXSwgdnN0YWNrLCBsc3RhY2spO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGVuKSB7XG4gICAgICAgICAgICAgICAgc3RhY2sgPSBzdGFjay5zbGljZSgwLCAtMSAqIGxlbiAqIDIpO1xuICAgICAgICAgICAgICAgIHZzdGFjayA9IHZzdGFjay5zbGljZSgwLCAtMSAqIGxlbik7XG4gICAgICAgICAgICAgICAgbHN0YWNrID0gbHN0YWNrLnNsaWNlKDAsIC0xICogbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YWNrLnB1c2godGhpcy5wcm9kdWN0aW9uc19bYWN0aW9uWzFdXVswXSk7XG4gICAgICAgICAgICB2c3RhY2sucHVzaCh5eXZhbC4kKTtcbiAgICAgICAgICAgIGxzdGFjay5wdXNoKHl5dmFsLl8kKTtcbiAgICAgICAgICAgIG5ld1N0YXRlID0gdGFibGVbc3RhY2tbc3RhY2subGVuZ3RoIC0gMl1dW3N0YWNrW3N0YWNrLmxlbmd0aCAtIDFdXTtcbiAgICAgICAgICAgIHN0YWNrLnB1c2gobmV3U3RhdGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxufTtcbi8qIEppc29uIGdlbmVyYXRlZCBsZXhlciAqL1xudmFyIGxleGVyID0gKGZ1bmN0aW9uKCl7XG52YXIgbGV4ZXIgPSAoe0VPRjoxLFxucGFyc2VFcnJvcjpmdW5jdGlvbiBwYXJzZUVycm9yKHN0ciwgaGFzaCkge1xuICAgICAgICBpZiAodGhpcy55eS5wYXJzZXIpIHtcbiAgICAgICAgICAgIHRoaXMueXkucGFyc2VyLnBhcnNlRXJyb3Ioc3RyLCBoYXNoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihzdHIpO1xuICAgICAgICB9XG4gICAgfSxcbnNldElucHV0OmZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICB0aGlzLl9pbnB1dCA9IGlucHV0O1xuICAgICAgICB0aGlzLl9tb3JlID0gdGhpcy5fbGVzcyA9IHRoaXMuZG9uZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnl5bGluZW5vID0gdGhpcy55eWxlbmcgPSAwO1xuICAgICAgICB0aGlzLnl5dGV4dCA9IHRoaXMubWF0Y2hlZCA9IHRoaXMubWF0Y2ggPSAnJztcbiAgICAgICAgdGhpcy5jb25kaXRpb25TdGFjayA9IFsnSU5JVElBTCddO1xuICAgICAgICB0aGlzLnl5bGxvYyA9IHtmaXJzdF9saW5lOjEsZmlyc3RfY29sdW1uOjAsbGFzdF9saW5lOjEsbGFzdF9jb2x1bW46MH07XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB0aGlzLnl5bGxvYy5yYW5nZSA9IFswLDBdO1xuICAgICAgICB0aGlzLm9mZnNldCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5pbnB1dDpmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjaCA9IHRoaXMuX2lucHV0WzBdO1xuICAgICAgICB0aGlzLnl5dGV4dCArPSBjaDtcbiAgICAgICAgdGhpcy55eWxlbmcrKztcbiAgICAgICAgdGhpcy5vZmZzZXQrKztcbiAgICAgICAgdGhpcy5tYXRjaCArPSBjaDtcbiAgICAgICAgdGhpcy5tYXRjaGVkICs9IGNoO1xuICAgICAgICB2YXIgbGluZXMgPSBjaC5tYXRjaCgvKD86XFxyXFxuP3xcXG4pLiovZyk7XG4gICAgICAgIGlmIChsaW5lcykge1xuICAgICAgICAgICAgdGhpcy55eWxpbmVubysrO1xuICAgICAgICAgICAgdGhpcy55eWxsb2MubGFzdF9saW5lKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnl5bGxvYy5sYXN0X2NvbHVtbisrO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB0aGlzLnl5bGxvYy5yYW5nZVsxXSsrO1xuXG4gICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiBjaDtcbiAgICB9LFxudW5wdXQ6ZnVuY3Rpb24gKGNoKSB7XG4gICAgICAgIHZhciBsZW4gPSBjaC5sZW5ndGg7XG4gICAgICAgIHZhciBsaW5lcyA9IGNoLnNwbGl0KC8oPzpcXHJcXG4/fFxcbikvZyk7XG5cbiAgICAgICAgdGhpcy5faW5wdXQgPSBjaCArIHRoaXMuX2lucHV0O1xuICAgICAgICB0aGlzLnl5dGV4dCA9IHRoaXMueXl0ZXh0LnN1YnN0cigwLCB0aGlzLnl5dGV4dC5sZW5ndGgtbGVuLTEpO1xuICAgICAgICAvL3RoaXMueXlsZW5nIC09IGxlbjtcbiAgICAgICAgdGhpcy5vZmZzZXQgLT0gbGVuO1xuICAgICAgICB2YXIgb2xkTGluZXMgPSB0aGlzLm1hdGNoLnNwbGl0KC8oPzpcXHJcXG4/fFxcbikvZyk7XG4gICAgICAgIHRoaXMubWF0Y2ggPSB0aGlzLm1hdGNoLnN1YnN0cigwLCB0aGlzLm1hdGNoLmxlbmd0aC0xKTtcbiAgICAgICAgdGhpcy5tYXRjaGVkID0gdGhpcy5tYXRjaGVkLnN1YnN0cigwLCB0aGlzLm1hdGNoZWQubGVuZ3RoLTEpO1xuXG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGgtMSkgdGhpcy55eWxpbmVubyAtPSBsaW5lcy5sZW5ndGgtMTtcbiAgICAgICAgdmFyIHIgPSB0aGlzLnl5bGxvYy5yYW5nZTtcblxuICAgICAgICB0aGlzLnl5bGxvYyA9IHtmaXJzdF9saW5lOiB0aGlzLnl5bGxvYy5maXJzdF9saW5lLFxuICAgICAgICAgIGxhc3RfbGluZTogdGhpcy55eWxpbmVubysxLFxuICAgICAgICAgIGZpcnN0X2NvbHVtbjogdGhpcy55eWxsb2MuZmlyc3RfY29sdW1uLFxuICAgICAgICAgIGxhc3RfY29sdW1uOiBsaW5lcyA/XG4gICAgICAgICAgICAgIChsaW5lcy5sZW5ndGggPT09IG9sZExpbmVzLmxlbmd0aCA/IHRoaXMueXlsbG9jLmZpcnN0X2NvbHVtbiA6IDApICsgb2xkTGluZXNbb2xkTGluZXMubGVuZ3RoIC0gbGluZXMubGVuZ3RoXS5sZW5ndGggLSBsaW5lc1swXS5sZW5ndGg6XG4gICAgICAgICAgICAgIHRoaXMueXlsbG9jLmZpcnN0X2NvbHVtbiAtIGxlblxuICAgICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5yYW5nZXMpIHtcbiAgICAgICAgICAgIHRoaXMueXlsbG9jLnJhbmdlID0gW3JbMF0sIHJbMF0gKyB0aGlzLnl5bGVuZyAtIGxlbl07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbm1vcmU6ZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9tb3JlID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbmxlc3M6ZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgdGhpcy51bnB1dCh0aGlzLm1hdGNoLnNsaWNlKG4pKTtcbiAgICB9LFxucGFzdElucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHBhc3QgPSB0aGlzLm1hdGNoZWQuc3Vic3RyKDAsIHRoaXMubWF0Y2hlZC5sZW5ndGggLSB0aGlzLm1hdGNoLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiAocGFzdC5sZW5ndGggPiAyMCA/ICcuLi4nOicnKSArIHBhc3Quc3Vic3RyKC0yMCkucmVwbGFjZSgvXFxuL2csIFwiXCIpO1xuICAgIH0sXG51cGNvbWluZ0lucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5leHQgPSB0aGlzLm1hdGNoO1xuICAgICAgICBpZiAobmV4dC5sZW5ndGggPCAyMCkge1xuICAgICAgICAgICAgbmV4dCArPSB0aGlzLl9pbnB1dC5zdWJzdHIoMCwgMjAtbmV4dC5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAobmV4dC5zdWJzdHIoMCwyMCkrKG5leHQubGVuZ3RoID4gMjAgPyAnLi4uJzonJykpLnJlcGxhY2UoL1xcbi9nLCBcIlwiKTtcbiAgICB9LFxuc2hvd1Bvc2l0aW9uOmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByZSA9IHRoaXMucGFzdElucHV0KCk7XG4gICAgICAgIHZhciBjID0gbmV3IEFycmF5KHByZS5sZW5ndGggKyAxKS5qb2luKFwiLVwiKTtcbiAgICAgICAgcmV0dXJuIHByZSArIHRoaXMudXBjb21pbmdJbnB1dCgpICsgXCJcXG5cIiArIGMrXCJeXCI7XG4gICAgfSxcbm5leHQ6ZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kb25lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5FT0Y7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9pbnB1dCkgdGhpcy5kb25lID0gdHJ1ZTtcblxuICAgICAgICB2YXIgdG9rZW4sXG4gICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgIHRlbXBNYXRjaCxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgY29sLFxuICAgICAgICAgICAgbGluZXM7XG4gICAgICAgIGlmICghdGhpcy5fbW9yZSkge1xuICAgICAgICAgICAgdGhpcy55eXRleHQgPSAnJztcbiAgICAgICAgICAgIHRoaXMubWF0Y2ggPSAnJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcnVsZXMgPSB0aGlzLl9jdXJyZW50UnVsZXMoKTtcbiAgICAgICAgZm9yICh2YXIgaT0wO2kgPCBydWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGVtcE1hdGNoID0gdGhpcy5faW5wdXQubWF0Y2godGhpcy5ydWxlc1tydWxlc1tpXV0pO1xuICAgICAgICAgICAgaWYgKHRlbXBNYXRjaCAmJiAoIW1hdGNoIHx8IHRlbXBNYXRjaFswXS5sZW5ndGggPiBtYXRjaFswXS5sZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2ggPSB0ZW1wTWF0Y2g7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5vcHRpb25zLmZsZXgpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgbGluZXMgPSBtYXRjaFswXS5tYXRjaCgvKD86XFxyXFxuP3xcXG4pLiovZyk7XG4gICAgICAgICAgICBpZiAobGluZXMpIHRoaXMueXlsaW5lbm8gKz0gbGluZXMubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy55eWxsb2MgPSB7Zmlyc3RfbGluZTogdGhpcy55eWxsb2MubGFzdF9saW5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9saW5lOiB0aGlzLnl5bGluZW5vKzEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBmaXJzdF9jb2x1bW46IHRoaXMueXlsbG9jLmxhc3RfY29sdW1uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9jb2x1bW46IGxpbmVzID8gbGluZXNbbGluZXMubGVuZ3RoLTFdLmxlbmd0aC1saW5lc1tsaW5lcy5sZW5ndGgtMV0ubWF0Y2goL1xccj9cXG4/LylbMF0ubGVuZ3RoIDogdGhpcy55eWxsb2MubGFzdF9jb2x1bW4gKyBtYXRjaFswXS5sZW5ndGh9O1xuICAgICAgICAgICAgdGhpcy55eXRleHQgKz0gbWF0Y2hbMF07XG4gICAgICAgICAgICB0aGlzLm1hdGNoICs9IG1hdGNoWzBdO1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzID0gbWF0Y2g7XG4gICAgICAgICAgICB0aGlzLnl5bGVuZyA9IHRoaXMueXl0ZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy55eWxsb2MucmFuZ2UgPSBbdGhpcy5vZmZzZXQsIHRoaXMub2Zmc2V0ICs9IHRoaXMueXlsZW5nXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX21vcmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UobWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMubWF0Y2hlZCArPSBtYXRjaFswXTtcbiAgICAgICAgICAgIHRva2VuID0gdGhpcy5wZXJmb3JtQWN0aW9uLmNhbGwodGhpcywgdGhpcy55eSwgdGhpcywgcnVsZXNbaW5kZXhdLHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMV0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuZG9uZSAmJiB0aGlzLl9pbnB1dCkgdGhpcy5kb25lID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodG9rZW4pIHJldHVybiB0b2tlbjtcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnB1dCA9PT0gXCJcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuRU9GO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VFcnJvcignTGV4aWNhbCBlcnJvciBvbiBsaW5lICcrKHRoaXMueXlsaW5lbm8rMSkrJy4gVW5yZWNvZ25pemVkIHRleHQuXFxuJyt0aGlzLnNob3dQb3NpdGlvbigpLFxuICAgICAgICAgICAgICAgICAgICB7dGV4dDogXCJcIiwgdG9rZW46IG51bGwsIGxpbmU6IHRoaXMueXlsaW5lbm99KTtcbiAgICAgICAgfVxuICAgIH0sXG5sZXg6ZnVuY3Rpb24gbGV4KCkge1xuICAgICAgICB2YXIgciA9IHRoaXMubmV4dCgpO1xuICAgICAgICBpZiAodHlwZW9mIHIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxleCgpO1xuICAgICAgICB9XG4gICAgfSxcbmJlZ2luOmZ1bmN0aW9uIGJlZ2luKGNvbmRpdGlvbikge1xuICAgICAgICB0aGlzLmNvbmRpdGlvblN0YWNrLnB1c2goY29uZGl0aW9uKTtcbiAgICB9LFxucG9wU3RhdGU6ZnVuY3Rpb24gcG9wU3RhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRpdGlvblN0YWNrLnBvcCgpO1xuICAgIH0sXG5fY3VycmVudFJ1bGVzOmZ1bmN0aW9uIF9jdXJyZW50UnVsZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRpdGlvbnNbdGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0xXV0ucnVsZXM7XG4gICAgfSxcbnRvcFN0YXRlOmZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMl07XG4gICAgfSxcbnB1c2hTdGF0ZTpmdW5jdGlvbiBiZWdpbihjb25kaXRpb24pIHtcbiAgICAgICAgdGhpcy5iZWdpbihjb25kaXRpb24pO1xuICAgIH19KTtcbmxleGVyLm9wdGlvbnMgPSB7fTtcbmxleGVyLnBlcmZvcm1BY3Rpb24gPSBmdW5jdGlvbiBhbm9ueW1vdXMoeXkseXlfLCRhdm9pZGluZ19uYW1lX2NvbGxpc2lvbnMsWVlfU1RBUlRcbi8qKi8pIHtcblxuXG5mdW5jdGlvbiBzdHJpcChzdGFydCwgZW5kKSB7XG4gIHJldHVybiB5eV8ueXl0ZXh0ID0geXlfLnl5dGV4dC5zdWJzdHIoc3RhcnQsIHl5Xy55eWxlbmctZW5kKTtcbn1cblxuXG52YXIgWVlTVEFURT1ZWV9TVEFSVFxuc3dpdGNoKCRhdm9pZGluZ19uYW1lX2NvbGxpc2lvbnMpIHtcbmNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoeXlfLnl5dGV4dC5zbGljZSgtMikgPT09IFwiXFxcXFxcXFxcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmlwKDAsMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iZWdpbihcIm11XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeXlfLnl5dGV4dC5zbGljZSgtMSkgPT09IFwiXFxcXFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaXAoMCwxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luKFwiZW11XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmVnaW4oXCJtdVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZih5eV8ueXl0ZXh0KSByZXR1cm4gMTU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmJyZWFrO1xuY2FzZSAxOnJldHVybiAxNTtcbmJyZWFrO1xuY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvcFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxNTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuYnJlYWs7XG5jYXNlIDM6dGhpcy5iZWdpbigncmF3Jyk7IHJldHVybiAxNTtcbmJyZWFrO1xuY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9wU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgYmUgdXNpbmcgYHRoaXMudG9wU3RhdGUoKWAgYmVsb3csIGJ1dCBpdCBjdXJyZW50bHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm5zIHRoZSBzZWNvbmQgdG9wIGluc3RlYWQgb2YgdGhlIGZpcnN0IHRvcC4gT3BlbmVkIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXNzdWUgYWJvdXQgaXQgYXQgaHR0cHM6Ly9naXRodWIuY29tL3phYWNoL2ppc29uL2lzc3Vlcy8yOTFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0xXSA9PT0gJ3JhdycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxNTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeXlfLnl5dGV4dCA9IHl5Xy55eXRleHQuc3Vic3RyKDUsIHl5Xy55eWxlbmctOSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ0VORF9SQVdfQkxPQ0snO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuYnJlYWs7XG5jYXNlIDU6IHJldHVybiAxNTsgXG5icmVhaztcbmNhc2UgNjpcbiAgdGhpcy5wb3BTdGF0ZSgpO1xuICByZXR1cm4gMTQ7XG5cbmJyZWFrO1xuY2FzZSA3OnJldHVybiA2NTtcbmJyZWFrO1xuY2FzZSA4OnJldHVybiA2ODtcbmJyZWFrO1xuY2FzZSA5OiByZXR1cm4gMTk7IFxuYnJlYWs7XG5jYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9wU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luKCdyYXcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMjM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmJyZWFrO1xuY2FzZSAxMTpyZXR1cm4gNTU7XG5icmVhaztcbmNhc2UgMTI6cmV0dXJuIDYwO1xuYnJlYWs7XG5jYXNlIDEzOnJldHVybiAyOTtcbmJyZWFrO1xuY2FzZSAxNDpyZXR1cm4gNDc7XG5icmVhaztcbmNhc2UgMTU6dGhpcy5wb3BTdGF0ZSgpOyByZXR1cm4gNDQ7XG5icmVhaztcbmNhc2UgMTY6dGhpcy5wb3BTdGF0ZSgpOyByZXR1cm4gNDQ7XG5icmVhaztcbmNhc2UgMTc6cmV0dXJuIDM0O1xuYnJlYWs7XG5jYXNlIDE4OnJldHVybiAzOTtcbmJyZWFrO1xuY2FzZSAxOTpyZXR1cm4gNTE7XG5icmVhaztcbmNhc2UgMjA6cmV0dXJuIDQ4O1xuYnJlYWs7XG5jYXNlIDIxOlxuICB0aGlzLnVucHV0KHl5Xy55eXRleHQpO1xuICB0aGlzLnBvcFN0YXRlKCk7XG4gIHRoaXMuYmVnaW4oJ2NvbScpO1xuXG5icmVhaztcbmNhc2UgMjI6XG4gIHRoaXMucG9wU3RhdGUoKTtcbiAgcmV0dXJuIDE0O1xuXG5icmVhaztcbmNhc2UgMjM6cmV0dXJuIDQ4O1xuYnJlYWs7XG5jYXNlIDI0OnJldHVybiA3MztcbmJyZWFrO1xuY2FzZSAyNTpyZXR1cm4gNzI7XG5icmVhaztcbmNhc2UgMjY6cmV0dXJuIDcyO1xuYnJlYWs7XG5jYXNlIDI3OnJldHVybiA4NztcbmJyZWFrO1xuY2FzZSAyODovLyBpZ25vcmUgd2hpdGVzcGFjZVxuYnJlYWs7XG5jYXNlIDI5OnRoaXMucG9wU3RhdGUoKTsgcmV0dXJuIDU0O1xuYnJlYWs7XG5jYXNlIDMwOnRoaXMucG9wU3RhdGUoKTsgcmV0dXJuIDMzO1xuYnJlYWs7XG5jYXNlIDMxOnl5Xy55eXRleHQgPSBzdHJpcCgxLDIpLnJlcGxhY2UoL1xcXFxcIi9nLCdcIicpOyByZXR1cm4gODA7XG5icmVhaztcbmNhc2UgMzI6eXlfLnl5dGV4dCA9IHN0cmlwKDEsMikucmVwbGFjZSgvXFxcXCcvZyxcIidcIik7IHJldHVybiA4MDtcbmJyZWFrO1xuY2FzZSAzMzpyZXR1cm4gODU7XG5icmVhaztcbmNhc2UgMzQ6cmV0dXJuIDgyO1xuYnJlYWs7XG5jYXNlIDM1OnJldHVybiA4MjtcbmJyZWFrO1xuY2FzZSAzNjpyZXR1cm4gODM7XG5icmVhaztcbmNhc2UgMzc6cmV0dXJuIDg0O1xuYnJlYWs7XG5jYXNlIDM4OnJldHVybiA4MTtcbmJyZWFrO1xuY2FzZSAzOTpyZXR1cm4gNzU7XG5icmVhaztcbmNhc2UgNDA6cmV0dXJuIDc3O1xuYnJlYWs7XG5jYXNlIDQxOnJldHVybiA3MjtcbmJyZWFrO1xuY2FzZSA0Mjp5eV8ueXl0ZXh0ID0geXlfLnl5dGV4dC5yZXBsYWNlKC9cXFxcKFtcXFxcXFxdXSkvZywnJDEnKTsgcmV0dXJuIDcyO1xuYnJlYWs7XG5jYXNlIDQzOnJldHVybiAnSU5WQUxJRCc7XG5icmVhaztcbmNhc2UgNDQ6cmV0dXJuIDU7XG5icmVhaztcbn1cbn07XG5sZXhlci5ydWxlcyA9IFsvXig/OlteXFx4MDBdKj8oPz0oXFx7XFx7KSkpLywvXig/OlteXFx4MDBdKykvLC9eKD86W15cXHgwMF17Mix9Pyg/PShcXHtcXHt8XFxcXFxce1xce3xcXFxcXFxcXFxce1xce3wkKSkpLywvXig/Olxce1xce1xce1xceyg/PVteXFwvXSkpLywvXig/Olxce1xce1xce1xce1xcL1teXFxzIVwiIyUtLFxcLlxcLzstPkBcXFstXFxeYFxcey1+XSsoPz1bPX1cXHNcXC8uXSlcXH1cXH1cXH1cXH0pLywvXig/OlteXFx4MDBdKj8oPz0oXFx7XFx7XFx7XFx7KSkpLywvXig/OltcXHNcXFNdKj8tLSh+KT9cXH1cXH0pLywvXig/OlxcKCkvLC9eKD86XFwpKS8sL14oPzpcXHtcXHtcXHtcXHspLywvXig/OlxcfVxcfVxcfVxcfSkvLC9eKD86XFx7XFx7KH4pPz4pLywvXig/Olxce1xceyh+KT8jPikvLC9eKD86XFx7XFx7KH4pPyNcXCo/KS8sL14oPzpcXHtcXHsofik/XFwvKS8sL14oPzpcXHtcXHsofik/XFxeXFxzKih+KT9cXH1cXH0pLywvXig/Olxce1xceyh+KT9cXHMqZWxzZVxccyoofik/XFx9XFx9KS8sL14oPzpcXHtcXHsofik/XFxeKS8sL14oPzpcXHtcXHsofik/XFxzKmVsc2VcXGIpLywvXig/Olxce1xceyh+KT9cXHspLywvXig/Olxce1xceyh+KT8mKS8sL14oPzpcXHtcXHsofik/IS0tKS8sL14oPzpcXHtcXHsofik/IVtcXHNcXFNdKj9cXH1cXH0pLywvXig/Olxce1xceyh+KT9cXCo/KS8sL14oPzo9KS8sL14oPzpcXC5cXC4pLywvXig/OlxcLig/PShbPX59XFxzXFwvLil8XSkpKS8sL14oPzpbXFwvLl0pLywvXig/OlxccyspLywvXig/OlxcfSh+KT9cXH1cXH0pLywvXig/Oih+KT9cXH1cXH0pLywvXig/OlwiKFxcXFxbXCJdfFteXCJdKSpcIikvLC9eKD86JyhcXFxcWyddfFteJ10pKicpLywvXig/OkApLywvXig/OnRydWUoPz0oW359XFxzKV0pKSkvLC9eKD86ZmFsc2UoPz0oW359XFxzKV0pKSkvLC9eKD86dW5kZWZpbmVkKD89KFt+fVxccyldKSkpLywvXig/Om51bGwoPz0oW359XFxzKV0pKSkvLC9eKD86LT9bMC05XSsoPzpcXC5bMC05XSspPyg/PShbfn1cXHMpXSkpKS8sL14oPzphc1xccytcXHwpLywvXig/OlxcfCkvLC9eKD86KFteXFxzIVwiIyUtLFxcLlxcLzstPkBcXFstXFxeYFxcey1+XSsoPz0oWz1+fVxcc1xcLy4pfF0pKSkpLywvXig/OlxcWyhcXFxcXFxdfFteXFxdXSkqXFxdKS8sL14oPzouKS8sL14oPzokKS9dO1xubGV4ZXIuY29uZGl0aW9ucyA9IHtcIm11XCI6e1wicnVsZXNcIjpbNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDRdLFwiaW5jbHVzaXZlXCI6ZmFsc2V9LFwiZW11XCI6e1wicnVsZXNcIjpbMl0sXCJpbmNsdXNpdmVcIjpmYWxzZX0sXCJjb21cIjp7XCJydWxlc1wiOls2XSxcImluY2x1c2l2ZVwiOmZhbHNlfSxcInJhd1wiOntcInJ1bGVzXCI6WzMsNCw1XSxcImluY2x1c2l2ZVwiOmZhbHNlfSxcIklOSVRJQUxcIjp7XCJydWxlc1wiOlswLDEsNDRdLFwiaW5jbHVzaXZlXCI6dHJ1ZX19O1xucmV0dXJuIGxleGVyO30pKClcbnBhcnNlci5sZXhlciA9IGxleGVyO1xuZnVuY3Rpb24gUGFyc2VyICgpIHsgdGhpcy55eSA9IHt9OyB9UGFyc2VyLnByb3RvdHlwZSA9IHBhcnNlcjtwYXJzZXIuUGFyc2VyID0gUGFyc2VyO1xucmV0dXJuIG5ldyBQYXJzZXI7XG59KSgpO2V4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5leHBvcnRzWydkZWZhdWx0J10gPSBoYW5kbGViYXJzO1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/printer.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/printer.js new file mode 100644 index 0000000..4f9f9c3 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/printer.js @@ -0,0 +1,186 @@ +define(['exports', './visitor'], function (exports, _visitor) { + /* eslint-disable new-cap */ + 'use strict'; + + exports.__esModule = true; + exports.print = print; + exports.PrintVisitor = PrintVisitor; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Visitor = _interopRequireDefault(_visitor); + + function print(ast) { + return new PrintVisitor().accept(ast); + } + + function PrintVisitor() { + this.padding = 0; + } + + PrintVisitor.prototype = new _Visitor['default'](); + + PrintVisitor.prototype.pad = function (string) { + var out = ''; + + for (var i = 0, l = this.padding; i < l; i++) { + out += ' '; + } + + out += string + '\n'; + return out; + }; + + PrintVisitor.prototype.Program = function (program) { + var out = '', + body = program.body, + i = undefined, + l = undefined; + + if (program.blockParams) { + var blockParams = 'BLOCK PARAMS: ['; + for (i = 0, l = program.blockParams.length; i < l; i++) { + blockParams += ' ' + program.blockParams[i]; + } + blockParams += ' ]'; + out += this.pad(blockParams); + } + + for (i = 0, l = body.length; i < l; i++) { + out += this.accept(body[i]); + } + + this.padding--; + + return out; + }; + + PrintVisitor.prototype.MustacheStatement = function (mustache) { + return this.pad('{{ ' + this.SubExpression(mustache) + ' }}'); + }; + PrintVisitor.prototype.Decorator = function (mustache) { + return this.pad('{{ DIRECTIVE ' + this.SubExpression(mustache) + ' }}'); + }; + + PrintVisitor.prototype.BlockStatement = PrintVisitor.prototype.DecoratorBlock = function (block) { + var out = ''; + + out += this.pad((block.type === 'DecoratorBlock' ? 'DIRECTIVE ' : '') + 'BLOCK:'); + this.padding++; + out += this.pad(this.SubExpression(block)); + if (block.program) { + out += this.pad('PROGRAM:'); + this.padding++; + out += this.accept(block.program); + this.padding--; + } + if (block.inverse) { + if (block.program) { + this.padding++; + } + out += this.pad('{{^}}'); + this.padding++; + out += this.accept(block.inverse); + this.padding--; + if (block.program) { + this.padding--; + } + } + this.padding--; + + return out; + }; + + PrintVisitor.prototype.PartialStatement = function (partial) { + var content = 'PARTIAL:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + return this.pad('{{> ' + content + ' }}'); + }; + PrintVisitor.prototype.PartialBlockStatement = function (partial) { + var content = 'PARTIAL BLOCK:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + + content += ' ' + this.pad('PROGRAM:'); + this.padding++; + content += this.accept(partial.program); + this.padding--; + + return this.pad('{{> ' + content + ' }}'); + }; + + PrintVisitor.prototype.ContentStatement = function (content) { + return this.pad("CONTENT[ '" + content.value + "' ]"); + }; + + PrintVisitor.prototype.CommentStatement = function (comment) { + return this.pad("{{! '" + comment.value + "' }}"); + }; + + PrintVisitor.prototype.SubExpression = function (sexpr) { + var params = sexpr.params, + paramStrings = [], + hash = undefined; + + for (var i = 0, l = params.length; i < l; i++) { + paramStrings.push(this.accept(params[i])); + } + + params = '[' + paramStrings.join(', ') + ']'; + + hash = sexpr.hash ? ' ' + this.accept(sexpr.hash) : ''; + + return this.accept(sexpr.path) + ' ' + params + hash; + }; + + PrintVisitor.prototype.PathExpression = function (id) { + var path = id.parts.join('/'); + return (id.data ? '@' : '') + 'PATH:' + path; + }; + + PrintVisitor.prototype.StringLiteral = function (string) { + return '"' + string.value + '"'; + }; + + PrintVisitor.prototype.NumberLiteral = function (number) { + return 'NUMBER{' + number.value + '}'; + }; + + PrintVisitor.prototype.BooleanLiteral = function (bool) { + return 'BOOLEAN{' + bool.value + '}'; + }; + + PrintVisitor.prototype.UndefinedLiteral = function () { + return 'UNDEFINED'; + }; + + PrintVisitor.prototype.NullLiteral = function () { + return 'NULL'; + }; + + PrintVisitor.prototype.Hash = function (hash) { + var pairs = hash.pairs, + joinedPairs = []; + + for (var i = 0, l = pairs.length; i < l; i++) { + joinedPairs.push(this.accept(pairs[i])); + } + + return 'HASH{' + joinedPairs.join(', ') + '}'; + }; + PrintVisitor.prototype.HashPair = function (pair) { + return pair.key + '=' + this.accept(pair.value); + }; + /* eslint-enable new-cap */ +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3ByaW50ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQUdPLFdBQVMsS0FBSyxDQUFDLEdBQUcsRUFBRTtBQUN6QixXQUFPLElBQUksWUFBWSxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0dBQ3ZDOztBQUVNLFdBQVMsWUFBWSxHQUFHO0FBQzdCLFFBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO0dBQ2xCOztBQUVELGNBQVksQ0FBQyxTQUFTLEdBQUcseUJBQWEsQ0FBQzs7QUFFdkMsY0FBWSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsVUFBUyxNQUFNLEVBQUU7QUFDNUMsUUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDOztBQUViLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDNUMsU0FBRyxJQUFJLElBQUksQ0FBQztLQUNiOztBQUVELE9BQUcsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDO0FBQ3JCLFdBQU8sR0FBRyxDQUFDO0dBQ1osQ0FBQzs7QUFFRixjQUFZLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRyxVQUFTLE9BQU8sRUFBRTtBQUNqRCxRQUFJLEdBQUcsR0FBRyxFQUFFO1FBQ1IsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJO1FBQ25CLENBQUMsWUFBQTtRQUFFLENBQUMsWUFBQSxDQUFDOztBQUVULFFBQUksT0FBTyxDQUFDLFdBQVcsRUFBRTtBQUN2QixVQUFJLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQztBQUNwQyxXQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFD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QUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN6Qzs7QUFFRCxXQUFPLE9BQU8sR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQztHQUMvQyxDQUFDO0FBQ0YsY0FBWSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsVUFBUyxJQUFJLEVBQUU7QUFDL0MsV0FBTyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUNqRCxDQUFDIiwiZmlsZSI6InByaW50ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuZXctY2FwICovXG5pbXBvcnQgVmlzaXRvciBmcm9tICcuL3Zpc2l0b3InO1xuXG5leHBvcnQgZnVuY3Rpb24gcHJpbnQoYXN0KSB7XG4gIHJldHVybiBuZXcgUHJpbnRWaXNpdG9yKCkuYWNjZXB0KGFzdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBQcmludFZpc2l0b3IoKSB7XG4gIHRoaXMucGFkZGluZyA9IDA7XG59XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUgPSBuZXcgVmlzaXRvcigpO1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLnBhZCA9IGZ1bmN0aW9uKHN0cmluZykge1xuICBsZXQgb3V0ID0gJyc7XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSB0aGlzLnBhZGRpbmc7IGkgPCBsOyBpKyspIHtcbiAgICBvdXQgKz0gJyAgJztcbiAgfVxuXG4gIG91dCArPSBzdHJpbmcgKyAnXFxuJztcbiAgcmV0dXJuIG91dDtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuUHJvZ3JhbSA9IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgbGV0IG91dCA9ICcnLFxuICAgICAgYm9keSA9IHByb2dyYW0uYm9keSxcbiAgICAgIGksIGw7XG5cbiAgaWYgKHByb2dyYW0uYmxvY2tQYXJhbXMpIHtcbiAgICBsZXQgYmxvY2tQYXJhbXMgPSAnQkxPQ0sgUEFSQU1TOiBbJztcbiAgICBmb3IgKGkgPSAwLCBsID0gcHJvZ3JhbS5ibG9ja1BhcmFtcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICBibG9ja1BhcmFtcyArPSAnICcgKyBwcm9ncmFtLmJsb2NrUGFyYW1zW2ldO1xuICAgIH1cbiAgICBibG9ja1BhcmFtcyArPSAnIF0nO1xuICAgIG91dCArPSB0aGlzLnBhZChibG9ja1BhcmFtcyk7XG4gIH1cblxuICBmb3IgKGkgPSAwLCBsID0gYm9keS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICBvdXQgKz0gdGhpcy5hY2NlcHQoYm9keVtpXSk7XG4gIH1cblxuICB0aGlzLnBhZGRpbmctLTtcblxuICByZXR1cm4gb3V0O1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5NdXN0YWNoZVN0YXRlbWVudCA9IGZ1bmN0aW9uKG11c3RhY2hlKSB7XG4gIHJldHVybiB0aGlzLnBhZCgne3sgJyArIHRoaXMuU3ViRXhwcmVzc2lvbihtdXN0YWNoZSkgKyAnIH19Jyk7XG59O1xuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5EZWNvcmF0b3IgPSBmdW5jdGlvbihtdXN0YWNoZSkge1xuICByZXR1cm4gdGhpcy5wYWQoJ3t7IERJUkVDVElWRSAnICsgdGhpcy5TdWJFeHByZXNzaW9uKG11c3RhY2hlKSArICcgfX0nKTtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuQmxvY2tTdGF0ZW1lbnQgPVxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5EZWNvcmF0b3JCbG9jayA9IGZ1bmN0aW9uKGJsb2NrKSB7XG4gIGxldCBvdXQgPSAnJztcblxuICBvdXQgKz0gdGhpcy5wYWQoKGJsb2NrLnR5cGUgPT09ICdEZWNvcmF0b3JCbG9jaycgPyAnRElSRUNUSVZFICcgOiAnJykgKyAnQkxPQ0s6Jyk7XG4gIHRoaXMucGFkZGluZysrO1xuICBvdXQgKz0gdGhpcy5wYWQodGhpcy5TdWJFeHByZXNzaW9uKGJsb2NrKSk7XG4gIGlmIChibG9jay5wcm9ncmFtKSB7XG4gICAgb3V0ICs9IHRoaXMucGFkKCdQUk9HUkFNOicpO1xuICAgIHRoaXMucGFkZGluZysrO1xuICAgIG91dCArPSB0aGlzLmFjY2VwdChibG9jay5wcm9ncmFtKTtcbiAgICB0aGlzLnBhZGRpbmctLTtcbiAgfVxuICBpZiAoYmxvY2suaW52ZXJzZSkge1xuICAgIGlmIChibG9jay5wcm9ncmFtKSB7IHRoaXMucGFkZGluZysrOyB9XG4gICAgb3V0ICs9IHRoaXMucGFkKCd7e159fScpO1xuICAgIHRoaXMucGFkZGluZysrO1xuICAgIG91dCArPSB0aGlzLmFjY2VwdChibG9jay5pbnZlcnNlKTtcbiAgICB0aGlzLnBhZGRpbmctLTtcbiAgICBpZiAoYmxvY2sucHJvZ3JhbSkgeyB0aGlzLnBhZGRpbmctLTsgfVxuICB9XG4gIHRoaXMucGFkZGluZy0tO1xuXG4gIHJldHVybiBvdXQ7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLlBhcnRpYWxTdGF0ZW1lbnQgPSBmdW5jdGlvbihwYXJ0aWFsKSB7XG4gIGxldCBjb250ZW50ID0gJ1BBUlRJQUw6JyArIHBhcnRpYWwubmFtZS5vcmlnaW5hbDtcbiAgaWYgKHBhcnRpYWwucGFyYW1zWzBdKSB7XG4gICAgY29udGVudCArPSAnICcgKyB0aGlzLmFjY2VwdChwYXJ0aWFsLnBhcmFtc1swXSk7XG4gIH1cbiAgaWYgKHBhcnRpYWwuaGFzaCkge1xuICAgIGNvbnRlbnQgKz0gJyAnICsgdGhpcy5hY2NlcHQocGFydGlhbC5oYXNoKTtcbiAgfVxuICByZXR1cm4gdGhpcy5wYWQoJ3t7PiAnICsgY29udGVudCArICcgfX0nKTtcbn07XG5QcmludFZpc2l0b3IucHJvdG90eXBlLlBhcnRpYWxCbG9ja1N0YXRlbWVudCA9IGZ1bmN0aW9uKHBhcnRpYWwpIHtcbiAgbGV0IGNvbnRlbnQgPSAnUEFSVElBTCBCTE9DSzonICsgcGFydGlhbC5uYW1lLm9yaWdpbmFsO1xuICBpZiAocGFydGlhbC5wYXJhbXNbMF0pIHtcbiAgICBjb250ZW50ICs9ICcgJyArIHRoaXMuYWNjZXB0KHBhcnRpYWwucGFyYW1zWzBdKTtcbiAgfVxuICBpZiAocGFydGlhbC5oYXNoKSB7XG4gICAgY29udGVudCArPSAnICcgKyB0aGlzLmFjY2VwdChwYXJ0aWFsLmhhc2gpO1xuICB9XG5cbiAgY29udGVudCArPSAnICcgKyB0aGlzLnBhZCgnUFJPR1JBTTonKTtcbiAgdGhpcy5wYWRkaW5nKys7XG4gIGNvbnRlbnQgKz0gdGhpcy5hY2NlcHQocGFydGlhbC5wcm9ncmFtKTtcbiAgdGhpcy5wYWRkaW5nLS07XG5cbiAgcmV0dXJuIHRoaXMucGFkKCd7ez4gJyArIGNvbnRlbnQgKyAnIH19Jyk7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLkNvbnRlbnRTdGF0ZW1lbnQgPSBmdW5jdGlvbihjb250ZW50KSB7XG4gIHJldHVybiB0aGlzLnBhZChcIkNPTlRFTlRbICdcIiArIGNvbnRlbnQudmFsdWUgKyBcIicgXVwiKTtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuQ29tbWVudFN0YXRlbWVudCA9IGZ1bmN0aW9uKGNvbW1lbnQpIHtcbiAgcmV0dXJuIHRoaXMucGFkKFwie3shICdcIiArIGNvbW1lbnQudmFsdWUgKyBcIicgfX1cIik7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLlN1YkV4cHJlc3Npb24gPSBmdW5jdGlvbihzZXhwcikge1xuICBsZXQgcGFyYW1zID0gc2V4cHIucGFyYW1zLFxuICAgICAgcGFyYW1TdHJpbmdzID0gW10sXG4gICAgICBoYXNoO1xuXG4gIGZvciAobGV0IGkgPSAwLCBsID0gcGFyYW1zLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIHBhcmFtU3RyaW5ncy5wdXNoKHRoaXMuYWNjZXB0KHBhcmFtc1tpXSkpO1xuICB9XG5cbiAgcGFyYW1zID0gJ1snICsgcGFyYW1TdHJpbmdzLmpvaW4oJywgJykgKyAnXSc7XG5cbiAgaGFzaCA9IHNleHByLmhhc2ggPyAnICcgKyB0aGlzLmFjY2VwdChzZXhwci5oYXNoKSA6ICcnO1xuXG4gIHJldHVybiB0aGlzLmFjY2VwdChzZXhwci5wYXRoKSArICcgJyArIHBhcmFtcyArIGhhc2g7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLlBhdGhFeHByZXNzaW9uID0gZnVuY3Rpb24oaWQpIHtcbiAgbGV0IHBhdGggPSBpZC5wYXJ0cy5qb2luKCcvJyk7XG4gIHJldHVybiAoaWQuZGF0YSA/ICdAJyA6ICcnKSArICdQQVRIOicgKyBwYXRoO1xufTtcblxuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLlN0cmluZ0xpdGVyYWwgPSBmdW5jdGlvbihzdHJpbmcpIHtcbiAgcmV0dXJuICdcIicgKyBzdHJpbmcudmFsdWUgKyAnXCInO1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5OdW1iZXJMaXRlcmFsID0gZnVuY3Rpb24obnVtYmVyKSB7XG4gIHJldHVybiAnTlVNQkVSeycgKyBudW1iZXIudmFsdWUgKyAnfSc7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLkJvb2xlYW5MaXRlcmFsID0gZnVuY3Rpb24oYm9vbCkge1xuICByZXR1cm4gJ0JPT0xFQU57JyArIGJvb2wudmFsdWUgKyAnfSc7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLlVuZGVmaW5lZExpdGVyYWwgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuICdVTkRFRklORUQnO1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5OdWxsTGl0ZXJhbCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gJ05VTEwnO1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5IYXNoID0gZnVuY3Rpb24oaGFzaCkge1xuICBsZXQgcGFpcnMgPSBoYXNoLnBhaXJzLFxuICAgICAgam9pbmVkUGFpcnMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMCwgbCA9IHBhaXJzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGpvaW5lZFBhaXJzLnB1c2godGhpcy5hY2NlcHQocGFpcnNbaV0pKTtcbiAgfVxuXG4gIHJldHVybiAnSEFTSHsnICsgam9pbmVkUGFpcnMuam9pbignLCAnKSArICd9Jztcbn07XG5QcmludFZpc2l0b3IucHJvdG90eXBlLkhhc2hQYWlyID0gZnVuY3Rpb24ocGFpcikge1xuICByZXR1cm4gcGFpci5rZXkgKyAnPScgKyB0aGlzLmFjY2VwdChwYWlyLnZhbHVlKTtcbn07XG4vKiBlc2xpbnQtZW5hYmxlIG5ldy1jYXAgKi9cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/visitor.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/visitor.js new file mode 100644 index 0000000..b74d987 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/visitor.js @@ -0,0 +1,138 @@ +define(['exports', 'module', '../exception'], function (exports, module, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function Visitor() { + this.parents = []; + } + + Visitor.prototype = { + constructor: Visitor, + mutating: false, + + // Visits a given value. If mutating, will replace the value if necessary. + acceptKey: function acceptKey(node, name) { + var value = this.accept(node[name]); + if (this.mutating) { + // Hacky sanity check: This may have a few false positives for type for the helper + // methods but will generally do the right thing without a lot of overhead. + if (value && !Visitor.prototype[value.type]) { + throw new _Exception['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); + } + node[name] = value; + } + }, + + // Performs an accept operation with added sanity check to ensure + // required keys are not removed. + acceptRequired: function acceptRequired(node, name) { + this.acceptKey(node, name); + + if (!node[name]) { + throw new _Exception['default'](node.type + ' requires ' + name); + } + }, + + // Traverses a given array. If mutating, empty respnses will be removed + // for child elements. + acceptArray: function acceptArray(array) { + for (var i = 0, l = array.length; i < l; i++) { + this.acceptKey(array, i); + + if (!array[i]) { + array.splice(i, 1); + i--; + l--; + } + } + }, + + accept: function accept(object) { + if (!object) { + return; + } + + /* istanbul ignore next: Sanity code */ + if (!this[object.type]) { + throw new _Exception['default']('Unknown type: ' + object.type, object); + } + + if (this.current) { + this.parents.unshift(this.current); + } + this.current = object; + + var ret = this[object.type](object); + + this.current = this.parents.shift(); + + if (!this.mutating || ret) { + return ret; + } else if (ret !== false) { + return object; + } + }, + + Program: function Program(program) { + this.acceptArray(program.body); + }, + + MustacheStatement: visitSubExpression, + Decorator: visitSubExpression, + + BlockStatement: visitBlock, + DecoratorBlock: visitBlock, + + PartialStatement: visitPartial, + PartialBlockStatement: function PartialBlockStatement(partial) { + visitPartial.call(this, partial); + + this.acceptKey(partial, 'program'); + }, + + ContentStatement: function ContentStatement() /* content */{}, + CommentStatement: function CommentStatement() /* comment */{}, + + SubExpression: visitSubExpression, + + PathExpression: function PathExpression() /* path */{}, + + StringLiteral: function StringLiteral() /* string */{}, + NumberLiteral: function NumberLiteral() /* number */{}, + BooleanLiteral: function BooleanLiteral() /* bool */{}, + UndefinedLiteral: function UndefinedLiteral() /* literal */{}, + NullLiteral: function NullLiteral() /* literal */{}, + + Hash: function Hash(hash) { + this.acceptArray(hash.pairs); + }, + HashPair: function HashPair(pair) { + this.acceptRequired(pair, 'value'); + } + }; + + function visitSubExpression(mustache) { + this.acceptRequired(mustache, 'path'); + this.acceptArray(mustache.params); + this.acceptKey(mustache, 'hash'); + } + function visitBlock(block) { + visitSubExpression.call(this, block); + + this.acceptKey(block, 'program'); + this.acceptKey(block, 'inverse'); + } + function visitPartial(partial) { + this.acceptRequired(partial, 'name'); + this.acceptArray(partial.params); + this.acceptKey(partial, 'hash'); + } + + module.exports = Visitor; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3Zpc2l0b3IuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBRUEsV0FBUyxPQUFPLEdBQUc7QUFDakIsUUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7R0FDbkI7O0FBRUQsU0FBTyxDQUFDLFNBQVMsR0FBRztBQUNsQixlQUFXLEVBQUUsT0FBTztBQUNwQixZQUFRLEVBQUUsS0FBSzs7O0FBR2YsYUFBUyxFQUFFLG1CQUFTLElBQUksRUFBRSxJQUFJLEVBQUU7QUFDOUIsVUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUNwQyxVQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7OztBQUdqQixZQUFJLEtBQUssSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFO0FBQzNDLGdCQUFNLDBCQUFjLHdCQUF3QixHQUFHLEtBQUssQ0FBQyxJQUFJLEdBQUcseUJBQXlCLEdBQUcsSUFBSSxHQUFHLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDcEg7QUFDRCxZQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO09BQ3BCO0tBQ0Y7Ozs7QUFJRCxrQkFBYyxFQUFFLHdCQUFTLElBQUksRUFBRSxJQUFJLEVBQUU7QUFDbkMsVUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7O0FBRTNCLFVBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7QUFDZixjQUFNLDBCQUFjLElBQUksQ0FBQyxJQUFJLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQyxDQUFDO09BQ3REO0tBQ0Y7Ozs7QUFJRCxlQUFXLEVBQUUscUJBQVMsS0FBSyxFQUFFO0FBQzNCLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENB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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7R0FDbEM7QUFDRCxXQUFTLFVBQVUsQ0FBQyxLQUFLLEVBQUU7QUFDekIsc0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQzs7QUFFckMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDakMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7R0FDbEM7QUFDRCxXQUFTLFlBQVksQ0FBQyxPQUFPLEVBQUU7QUFDN0IsUUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDckMsUUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDakMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7R0FDakM7O21CQUVjLE9BQU8iLCJmaWxlIjoidmlzaXRvci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi4vZXhjZXB0aW9uJztcblxuZnVuY3Rpb24gVmlzaXRvcigpIHtcbiAgdGhpcy5wYXJlbnRzID0gW107XG59XG5cblZpc2l0b3IucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogVmlzaXRvcixcbiAgbXV0YXRpbmc6IGZhbHNlLFxuXG4gIC8vIFZpc2l0cyBhIGdpdmVuIHZhbHVlLiBJZiBtdXRhdGluZywgd2lsbCByZXBsYWNlIHRoZSB2YWx1ZSBpZiBuZWNlc3NhcnkuXG4gIGFjY2VwdEtleTogZnVuY3Rpb24obm9kZSwgbmFtZSkge1xuICAgIGxldCB2YWx1ZSA9IHRoaXMuYWNjZXB0KG5vZGVbbmFtZV0pO1xuICAgIGlmICh0aGlzLm11dGF0aW5nKSB7XG4gICAgICAvLyBIYWNreSBzYW5pdHkgY2hlY2s6IFRoaXMgbWF5IGhhdmUgYSBmZXcgZmFsc2UgcG9zaXRpdmVzIGZvciB0eXBlIGZvciB0aGUgaGVscGVyXG4gICAgICAvLyBtZXRob2RzIGJ1dCB3aWxsIGdlbmVyYWxseSBkbyB0aGUgcmlnaHQgdGhpbmcgd2l0aG91dCBhIGxvdCBvZiBvdmVyaGVhZC5cbiAgICAgIGlmICh2YWx1ZSAmJiAhVmlzaXRvci5wcm90b3R5cGVbdmFsdWUudHlwZV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVW5leHBlY3RlZCBub2RlIHR5cGUgXCInICsgdmFsdWUudHlwZSArICdcIiBmb3VuZCB3aGVuIGFjY2VwdGluZyAnICsgbmFtZSArICcgb24gJyArIG5vZGUudHlwZSk7XG4gICAgICB9XG4gICAgICBub2RlW25hbWVdID0gdmFsdWU7XG4gICAgfVxuICB9LFxuXG4gIC8vIFBlcmZvcm1zIGFuIGFjY2VwdCBvcGVyYXRpb24gd2l0aCBhZGRlZCBzYW5pdHkgY2hlY2sgdG8gZW5zdXJlXG4gIC8vIHJlcXVpcmVkIGtleXMgYXJlIG5vdCByZW1vdmVkLlxuICBhY2NlcHRSZXF1aXJlZDogZnVuY3Rpb24obm9kZSwgbmFtZSkge1xuICAgIHRoaXMuYWNjZXB0S2V5KG5vZGUsIG5hbWUpO1xuXG4gICAgaWYgKCFub2RlW25hbWVdKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKG5vZGUudHlwZSArICcgcmVxdWlyZXMgJyArIG5hbWUpO1xuICAgIH1cbiAgfSxcblxuICAvLyBUcmF2ZXJzZXMgYSBnaXZlbiBhcnJheS4gSWYgbXV0YXRpbmcsIGVtcHR5IHJlc3Buc2VzIHdpbGwgYmUgcmVtb3ZlZFxuICAvLyBmb3IgY2hpbGQgZWxlbWVudHMuXG4gIGFjY2VwdEFycmF5OiBmdW5jdGlvbihhcnJheSkge1xuICAgIGZvciAobGV0IGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICB0aGlzLmFjY2VwdEtleShhcnJheSwgaSk7XG5cbiAgICAgIGlmICghYXJyYXlbaV0pIHtcbiAgICAgICAgYXJyYXkuc3BsaWNlKGksIDEpO1xuICAgICAgICBpLS07XG4gICAgICAgIGwtLTtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgYWNjZXB0OiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBpZiAoIW9iamVjdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBTYW5pdHkgY29kZSAqL1xuICAgIGlmICghdGhpc1tvYmplY3QudHlwZV0pIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdHlwZTogJyArIG9iamVjdC50eXBlLCBvYmplY3QpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmN1cnJlbnQpIHtcbiAgICAgIHRoaXMucGFyZW50cy51bnNoaWZ0KHRoaXMuY3VycmVudCk7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudCA9IG9iamVjdDtcblxuICAgIGxldCByZXQgPSB0aGlzW29iamVjdC50eXBlXShvYmplY3QpO1xuXG4gICAgdGhpcy5jdXJyZW50ID0gdGhpcy5wYXJlbnRzLnNoaWZ0KCk7XG5cbiAgICBpZiAoIXRoaXMubXV0YXRpbmcgfHwgcmV0KSB7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0gZWxzZSBpZiAocmV0ICE9PSBmYWxzZSkge1xuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG4gIH0sXG5cbiAgUHJvZ3JhbTogZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgIHRoaXMuYWNjZXB0QXJyYXkocHJvZ3JhbS5ib2R5KTtcbiAgfSxcblxuICBNdXN0YWNoZVN0YXRlbWVudDogdmlzaXRTdWJFeHByZXNzaW9uLFxuICBEZWNvcmF0b3I6IHZpc2l0U3ViRXhwcmVzc2lvbixcblxuICBCbG9ja1N0YXRlbWVudDogdmlzaXRCbG9jayxcbiAgRGVjb3JhdG9yQmxvY2s6IHZpc2l0QmxvY2ssXG5cbiAgUGFydGlhbFN0YXRlbWVudDogdmlzaXRQYXJ0aWFsLFxuICBQYXJ0aWFsQmxvY2tTdGF0ZW1lbnQ6IGZ1bmN0aW9uKHBhcnRpYWwpIHtcbiAgICB2aXNpdFBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsKTtcblxuICAgIHRoaXMuYWNjZXB0S2V5KHBhcnRpYWwsICdwcm9ncmFtJyk7XG4gIH0sXG5cbiAgQ29udGVudFN0YXRlbWVudDogZnVuY3Rpb24oLyogY29udGVudCAqLykge30sXG4gIENvbW1lbnRTdGF0ZW1lbnQ6IGZ1bmN0aW9uKC8qIGNvbW1lbnQgKi8pIHt9LFxuXG4gIFN1YkV4cHJlc3Npb246IHZpc2l0U3ViRXhwcmVzc2lvbixcblxuICBQYXRoRXhwcmVzc2lvbjogZnVuY3Rpb24oLyogcGF0aCAqLykge30sXG5cbiAgU3RyaW5nTGl0ZXJhbDogZnVuY3Rpb24oLyogc3RyaW5nICovKSB7fSxcbiAgTnVtYmVyTGl0ZXJhbDogZnVuY3Rpb24oLyogbnVtYmVyICovKSB7fSxcbiAgQm9vbGVhbkxpdGVyYWw6IGZ1bmN0aW9uKC8qIGJvb2wgKi8pIHt9LFxuICBVbmRlZmluZWRMaXRlcmFsOiBmdW5jdGlvbigvKiBsaXRlcmFsICovKSB7fSxcbiAgTnVsbExpdGVyYWw6IGZ1bmN0aW9uKC8qIGxpdGVyYWwgKi8pIHt9LFxuXG4gIEhhc2g6IGZ1bmN0aW9uKGhhc2gpIHtcbiAgICB0aGlzLmFjY2VwdEFycmF5KGhhc2gucGFpcnMpO1xuICB9LFxuICBIYXNoUGFpcjogZnVuY3Rpb24ocGFpcikge1xuICAgIHRoaXMuYWNjZXB0UmVxdWlyZWQocGFpciwgJ3ZhbHVlJyk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHZpc2l0U3ViRXhwcmVzc2lvbihtdXN0YWNoZSkge1xuICB0aGlzLmFjY2VwdFJlcXVpcmVkKG11c3RhY2hlLCAncGF0aCcpO1xuICB0aGlzLmFjY2VwdEFycmF5KG11c3RhY2hlLnBhcmFtcyk7XG4gIHRoaXMuYWNjZXB0S2V5KG11c3RhY2hlLCAnaGFzaCcpO1xufVxuZnVuY3Rpb24gdmlzaXRCbG9jayhibG9jaykge1xuICB2aXNpdFN1YkV4cHJlc3Npb24uY2FsbCh0aGlzLCBibG9jayk7XG5cbiAgdGhpcy5hY2NlcHRLZXkoYmxvY2ssICdwcm9ncmFtJyk7XG4gIHRoaXMuYWNjZXB0S2V5KGJsb2NrLCAnaW52ZXJzZScpO1xufVxuZnVuY3Rpb24gdmlzaXRQYXJ0aWFsKHBhcnRpYWwpIHtcbiAgdGhpcy5hY2NlcHRSZXF1aXJlZChwYXJ0aWFsLCAnbmFtZScpO1xuICB0aGlzLmFjY2VwdEFycmF5KHBhcnRpYWwucGFyYW1zKTtcbiAgdGhpcy5hY2NlcHRLZXkocGFydGlhbCwgJ2hhc2gnKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgVmlzaXRvcjtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/whitespace-control.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/whitespace-control.js new file mode 100644 index 0000000..47c365a --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/compiler/whitespace-control.js @@ -0,0 +1,219 @@ +define(['exports', 'module', './visitor'], function (exports, module, _visitor) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Visitor = _interopRequireDefault(_visitor); + + function WhitespaceControl() { + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + this.options = options; + } + WhitespaceControl.prototype = new _Visitor['default'](); + + WhitespaceControl.prototype.Program = function (program) { + var doStandalone = !this.options.ignoreStandalone; + + var isRoot = !this.isRootSeen; + this.isRootSeen = true; + + var body = program.body; + for (var i = 0, l = body.length; i < l; i++) { + var current = body[i], + strip = this.accept(current); + + if (!strip) { + continue; + } + + var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), + _isNextWhitespace = isNextWhitespace(body, i, isRoot), + openStandalone = strip.openStandalone && _isPrevWhitespace, + closeStandalone = strip.closeStandalone && _isNextWhitespace, + inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; + + if (strip.close) { + omitRight(body, i, true); + } + if (strip.open) { + omitLeft(body, i, true); + } + + if (doStandalone && inlineStandalone) { + omitRight(body, i); + + if (omitLeft(body, i)) { + // If we are on a standalone node, save the indent info for partials + if (current.type === 'PartialStatement') { + // Pull out the whitespace from the final line + current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1]; + } + } + } + if (doStandalone && openStandalone) { + omitRight((current.program || current.inverse).body); + + // Strip out the previous content node if it's whitespace only + omitLeft(body, i); + } + if (doStandalone && closeStandalone) { + // Always strip the next node + omitRight(body, i); + + omitLeft((current.inverse || current.program).body); + } + } + + return program; + }; + + WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) { + this.accept(block.program); + this.accept(block.inverse); + + // Find the inverse program that is involed with whitespace stripping. + var program = block.program || block.inverse, + inverse = block.program && block.inverse, + firstInverse = inverse, + lastInverse = inverse; + + if (inverse && inverse.chained) { + firstInverse = inverse.body[0].program; + + // Walk the inverse chain to find the last inverse that is actually in the chain. + while (lastInverse.chained) { + lastInverse = lastInverse.body[lastInverse.body.length - 1].program; + } + } + + var strip = { + open: block.openStrip.open, + close: block.closeStrip.close, + + // Determine the standalone candiacy. Basically flag our content as being possibly standalone + // so our parent can determine if we actually are standalone + openStandalone: isNextWhitespace(program.body), + closeStandalone: isPrevWhitespace((firstInverse || program).body) + }; + + if (block.openStrip.close) { + omitRight(program.body, null, true); + } + + if (inverse) { + var inverseStrip = block.inverseStrip; + + if (inverseStrip.open) { + omitLeft(program.body, null, true); + } + + if (inverseStrip.close) { + omitRight(firstInverse.body, null, true); + } + if (block.closeStrip.open) { + omitLeft(lastInverse.body, null, true); + } + + // Find standalone else statments + if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) { + omitLeft(program.body); + omitRight(firstInverse.body); + } + } else if (block.closeStrip.open) { + omitLeft(program.body, null, true); + } + + return strip; + }; + + WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) { + return mustache.strip; + }; + + WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) { + /* istanbul ignore next */ + var strip = node.strip || {}; + return { + inlineStandalone: true, + open: strip.open, + close: strip.close + }; + }; + + function isPrevWhitespace(body, i, isRoot) { + if (i === undefined) { + i = body.length; + } + + // Nodes that end with newlines are considered whitespace (but are special + // cased for strip operations) + var prev = body[i - 1], + sibling = body[i - 2]; + if (!prev) { + return isRoot; + } + + if (prev.type === 'ContentStatement') { + return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original); + } + } + function isNextWhitespace(body, i, isRoot) { + if (i === undefined) { + i = -1; + } + + var next = body[i + 1], + sibling = body[i + 2]; + if (!next) { + return isRoot; + } + + if (next.type === 'ContentStatement') { + return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original); + } + } + + // Marks the node to the right of the position as omitted. + // I.e. {{foo}}' ' will mark the ' ' node as omitted. + // + // If i is undefined, then the first child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitRight(body, i, multiple) { + var current = body[i == null ? 0 : i + 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) { + return; + } + + var original = current.value; + current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, ''); + current.rightStripped = current.value !== original; + } + + // Marks the node to the left of the position as omitted. + // I.e. ' '{{foo}} will mark the ' ' node as omitted. + // + // If i is undefined then the last child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitLeft(body, i, multiple) { + var current = body[i == null ? body.length - 1 : i - 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) { + return; + } + + // We omit the last node if it's whitespace only and not preceeded by a non-content node. + var original = current.value; + current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, ''); + current.leftStripped = current.value !== original; + return current.leftStripped; + } + + module.exports = WhitespaceControl; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3doaXRlc3BhY2UtY29udHJvbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFFQSxXQUFTLGlCQUFpQixHQUFlO1FBQWQsT0FBTyx5REFBRyxFQUFFOztBQUNyQyxRQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztHQUN4QjtBQUNELG1CQUFpQixDQUFDLFNBQVMsR0FBRyx5QkFBYSxDQUFDOztBQUU1QyxtQkFBaUIsQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLFVBQVMsT0FBTyxFQUFFO0FBQ3RELFFBQU0sWUFBWSxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQzs7QUFFcEQsUUFBSSxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO0FBQzlCLFFBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDOztBQUV2QixRQUFJLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO0FBQ3hCLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDM0MsVUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztVQUNqQixLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQzs7QUFFakMsVUFBSSxDQUFDLEtBQUssRUFBRTtBQUNWLGlCQUFTO09BQ1Y7O0FBRUQsVUFBSSxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztVQUNyRCxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztVQUVyRCxjQUFjLEdBQUcsS0FBSyxDQUFDLGNBQWMsSUFBSSxpQkFBaUI7VUFDMUQsZUFBZSxHQUFHLEtB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QUN4RCxRQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssa0JBQWtCLElBQUssQ0FBQyxRQUFRLElBQUksT0FBTyxDQUFDLFlBQVksQUFBQyxFQUFFO0FBQzFGLGFBQU87S0FDUjs7O0FBR0QsUUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztBQUM3QixXQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsR0FBSSxNQUFNLEdBQUssU0FBUyxBQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDN0UsV0FBTyxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQztBQUNsRCxXQUFPLE9BQU8sQ0FBQyxZQUFZLENBQUM7R0FDN0I7O21CQUVjLGlCQUFpQiIsImZpbGUiOiJ3aGl0ZXNwYWNlLWNvbnRyb2wuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgVmlzaXRvciBmcm9tICcuL3Zpc2l0b3InO1xuXG5mdW5jdGlvbiBXaGl0ZXNwYWNlQ29udHJvbChvcHRpb25zID0ge30pIHtcbiAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbn1cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZSA9IG5ldyBWaXNpdG9yKCk7XG5cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5Qcm9ncmFtID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICBjb25zdCBkb1N0YW5kYWxvbmUgPSAhdGhpcy5vcHRpb25zLmlnbm9yZVN0YW5kYWxvbmU7XG5cbiAgbGV0IGlzUm9vdCA9ICF0aGlzLmlzUm9vdFNlZW47XG4gIHRoaXMuaXNSb290U2VlbiA9IHRydWU7XG5cbiAgbGV0IGJvZHkgPSBwcm9ncmFtLmJvZHk7XG4gIGZvciAobGV0IGkgPSAwLCBsID0gYm9keS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICBsZXQgY3VycmVudCA9IGJvZHlbaV0sXG4gICAgICAgIHN0cmlwID0gdGhpcy5hY2NlcHQoY3VycmVudCk7XG5cbiAgICBpZiAoIXN0cmlwKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBsZXQgX2lzUHJldldoaXRlc3BhY2UgPSBpc1ByZXZXaGl0ZXNwYWNlKGJvZHksIGksIGlzUm9vdCksXG4gICAgICAgIF9pc05leHRXaGl0ZXNwYWNlID0gaXNOZXh0V2hpdGVzcGFjZShib2R5LCBpLCBpc1Jvb3QpLFxuXG4gICAgICAgIG9wZW5TdGFuZGFsb25lID0gc3RyaXAub3BlblN0YW5kYWxvbmUgJiYgX2lzUHJldldoaXRlc3BhY2UsXG4gICAgICAgIGNsb3NlU3RhbmRhbG9uZSA9IHN0cmlwLmNsb3NlU3RhbmRhbG9uZSAmJiBfaXNOZXh0V2hpdGVzcGFjZSxcbiAgICAgICAgaW5saW5lU3RhbmRhbG9uZSA9IHN0cmlwLmlubGluZVN0YW5kYWxvbmUgJiYgX2lzUHJldldoaXRlc3BhY2UgJiYgX2lzTmV4dFdoaXRlc3BhY2U7XG5cbiAgICBpZiAoc3RyaXAuY2xvc2UpIHtcbiAgICAgIG9taXRSaWdodChib2R5LCBpLCB0cnVlKTtcbiAgICB9XG4gICAgaWYgKHN0cmlwLm9wZW4pIHtcbiAgICAgIG9taXRMZWZ0KGJvZHksIGksIHRydWUpO1xuICAgIH1cblxuICAgIGlmIChkb1N0YW5kYWxvbmUgJiYgaW5saW5lU3RhbmRhbG9uZSkge1xuICAgICAgb21pdFJpZ2h0KGJvZHksIGkpO1xuXG4gICAgICBpZiAob21pdExlZnQoYm9keSwgaSkpIHtcbiAgICAgICAgLy8gSWYgd2UgYXJlIG9uIGEgc3RhbmRhbG9uZSBub2RlLCBzYXZlIHRoZSBpbmRlbnQgaW5mbyBmb3IgcGFydGlhbHNcbiAgICAgICAgaWYgKGN1cnJlbnQudHlwZSA9PT0gJ1BhcnRpYWxTdGF0ZW1lbnQnKSB7XG4gICAgICAgICAgLy8gUHVsbCBvdXQgdGhlIHdoaXRlc3BhY2UgZnJvbSB0aGUgZmluYWwgbGluZVxuICAgICAgICAgIGN1cnJlbnQuaW5kZW50ID0gKC8oWyBcXHRdKyQpLykuZXhlYyhib2R5W2kgLSAxXS5vcmlnaW5hbClbMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGRvU3RhbmRhbG9uZSAmJiBvcGVuU3RhbmRhbG9uZSkge1xuICAgICAgb21pdFJpZ2h0KChjdXJyZW50LnByb2dyYW0gfHwgY3VycmVudC5pbnZlcnNlKS5ib2R5KTtcblxuICAgICAgLy8gU3RyaXAgb3V0IHRoZSBwcmV2aW91cyBjb250ZW50IG5vZGUgaWYgaXQncyB3aGl0ZXNwYWNlIG9ubHlcbiAgICAgIG9taXRMZWZ0KGJvZHksIGkpO1xuICAgIH1cbiAgICBpZiAoZG9TdGFuZGFsb25lICYmIGNsb3NlU3RhbmRhbG9uZSkge1xuICAgICAgLy8gQWx3YXlzIHN0cmlwIHRoZSBuZXh0IG5vZGVcbiAgICAgIG9taXRSaWdodChib2R5LCBpKTtcblxuICAgICAgb21pdExlZnQoKGN1cnJlbnQuaW52ZXJzZSB8fCBjdXJyZW50LnByb2dyYW0pLmJvZHkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwcm9ncmFtO1xufTtcblxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLkJsb2NrU3RhdGVtZW50ID1cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5EZWNvcmF0b3JCbG9jayA9XG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuUGFydGlhbEJsb2NrU3RhdGVtZW50ID0gZnVuY3Rpb24oYmxvY2spIHtcbiAgdGhpcy5hY2NlcHQoYmxvY2sucHJvZ3JhbSk7XG4gIHRoaXMuYWNjZXB0KGJsb2NrLmludmVyc2UpO1xuXG4gIC8vIEZpbmQgdGhlIGludmVyc2UgcHJvZ3JhbSB0aGF0IGlzIGludm9sZWQgd2l0aCB3aGl0ZXNwYWNlIHN0cmlwcGluZy5cbiAgbGV0IHByb2dyYW0gPSBibG9jay5wcm9ncmFtIHx8IGJsb2NrLmludmVyc2UsXG4gICAgICBpbnZlcnNlID0gYmxvY2sucHJvZ3JhbSAmJiBibG9jay5pbnZlcnNlLFxuICAgICAgZmlyc3RJbnZlcnNlID0gaW52ZXJzZSxcbiAgICAgIGxhc3RJbnZlcnNlID0gaW52ZXJzZTtcblxuICBpZiAoaW52ZXJzZSAmJiBpbnZlcnNlLmNoYWluZWQpIHtcbiAgICBmaXJzdEludmVyc2UgPSBpbnZlcnNlLmJvZHlbMF0ucHJvZ3JhbTtcblxuICAgIC8vIFdhbGsgdGhlIGludmVyc2UgY2hhaW4gdG8gZmluZCB0aGUgbGFzdCBpbnZlcnNlIHRoYXQgaXMgYWN0dWFsbHkgaW4gdGhlIGNoYWluLlxuICAgIHdoaWxlIChsYXN0SW52ZXJzZS5jaGFpbmVkKSB7XG4gICAgICBsYXN0SW52ZXJzZSA9IGxhc3RJbnZlcnNlLmJvZHlbbGFzdEludmVyc2UuYm9keS5sZW5ndGggLSAxXS5wcm9ncmFtO1xuICAgIH1cbiAgfVxuXG4gIGxldCBzdHJpcCA9IHtcbiAgICBvcGVuOiBibG9jay5vcGVuU3RyaXAub3BlbixcbiAgICBjbG9zZTogYmxvY2suY2xvc2VTdHJpcC5jbG9zZSxcblxuICAgIC8vIERldGVybWluZSB0aGUgc3RhbmRhbG9uZSBjYW5kaWFjeS4gQmFzaWNhbGx5IGZsYWcgb3VyIGNvbnRlbnQgYXMgYmVpbmcgcG9zc2libHkgc3RhbmRhbG9uZVxuICAgIC8vIHNvIG91ciBwYXJlbnQgY2FuIGRldGVybWluZSBpZiB3ZSBhY3R1YWxseSBhcmUgc3RhbmRhbG9uZVxuICAgIG9wZW5TdGFuZGFsb25lOiBpc05leHRXaGl0ZXNwYWNlKHByb2dyYW0uYm9keSksXG4gICAgY2xvc2VTdGFuZGFsb25lOiBpc1ByZXZXaGl0ZXNwYWNlKChmaXJzdEludmVyc2UgfHwgcHJvZ3JhbSkuYm9keSlcbiAgfTtcblxuICBpZiAoYmxvY2sub3BlblN0cmlwLmNsb3NlKSB7XG4gICAgb21pdFJpZ2h0KHByb2dyYW0uYm9keSwgbnVsbCwgdHJ1ZSk7XG4gIH1cblxuICBpZiAoaW52ZXJzZSkge1xuICAgIGxldCBpbnZlcnNlU3RyaXAgPSBibG9jay5pbnZlcnNlU3RyaXA7XG5cbiAgICBpZiAoaW52ZXJzZVN0cmlwLm9wZW4pIHtcbiAgICAgIG9taXRMZWZ0KHByb2dyYW0uYm9keSwgbnVsbCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgaWYgKGludmVyc2VTdHJpcC5jbG9zZSkge1xuICAgICAgb21pdFJpZ2h0KGZpcnN0SW52ZXJzZS5ib2R5LCBudWxsLCB0cnVlKTtcbiAgICB9XG4gICAgaWYgKGJsb2NrLmNsb3NlU3RyaXAub3Blbikge1xuICAgICAgb21pdExlZnQobGFzdEludmVyc2UuYm9keSwgbnVsbCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLy8gRmluZCBzdGFuZGFsb25lIGVsc2Ugc3RhdG1lbnRzXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuaWdub3JlU3RhbmRhbG9uZVxuICAgICAgICAmJiBpc1ByZXZXaGl0ZXNwYWNlKHByb2dyYW0uYm9keSlcbiAgICAgICAgJiYgaXNOZXh0V2hpdGVzcGFjZShmaXJzdEludmVyc2UuYm9keSkpIHtcbiAgICAgIG9taXRMZWZ0KHByb2dyYW0uYm9keSk7XG4gICAgICBvbWl0UmlnaHQoZmlyc3RJbnZlcnNlLmJvZHkpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChibG9jay5jbG9zZVN0cmlwLm9wZW4pIHtcbiAgICBvbWl0TGVmdChwcm9ncmFtLmJvZHksIG51bGwsIHRydWUpO1xuICB9XG5cbiAgcmV0dXJuIHN0cmlwO1xufTtcblxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLkRlY29yYXRvciA9XG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuTXVzdGFjaGVTdGF0ZW1lbnQgPSBmdW5jdGlvbihtdXN0YWNoZSkge1xuICByZXR1cm4gbXVzdGFjaGUuc3RyaXA7XG59O1xuXG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuUGFydGlhbFN0YXRlbWVudCA9XG4gICAgV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLkNvbW1lbnRTdGF0ZW1lbnQgPSBmdW5jdGlvbihub2RlKSB7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGxldCBzdHJpcCA9IG5vZGUuc3RyaXAgfHwge307XG4gIHJldHVybiB7XG4gICAgaW5saW5lU3RhbmRhbG9uZTogdHJ1ZSxcbiAgICBvcGVuOiBzdHJpcC5vcGVuLFxuICAgIGNsb3NlOiBzdHJpcC5jbG9zZVxuICB9O1xufTtcblxuXG5mdW5jdGlvbiBpc1ByZXZXaGl0ZXNwYWNlKGJvZHksIGksIGlzUm9vdCkge1xuICBpZiAoaSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgaSA9IGJvZHkubGVuZ3RoO1xuICB9XG5cbiAgLy8gTm9kZXMgdGhhdCBlbmQgd2l0aCBuZXdsaW5lcyBhcmUgY29uc2lkZXJlZCB3aGl0ZXNwYWNlIChidXQgYXJlIHNwZWNpYWxcbiAgLy8gY2FzZWQgZm9yIHN0cmlwIG9wZXJhdGlvbnMpXG4gIGxldCBwcmV2ID0gYm9keVtpIC0gMV0sXG4gICAgICBzaWJsaW5nID0gYm9keVtpIC0gMl07XG4gIGlmICghcHJldikge1xuICAgIHJldHVybiBpc1Jvb3Q7XG4gIH1cblxuICBpZiAocHJldi50eXBlID09PSAnQ29udGVudFN0YXRlbWVudCcpIHtcbiAgICByZXR1cm4gKHNpYmxpbmcgfHwgIWlzUm9vdCA/ICgvXFxyP1xcblxccyo/JC8pIDogKC8oXnxcXHI/XFxuKVxccyo/JC8pKS50ZXN0KHByZXYub3JpZ2luYWwpO1xuICB9XG59XG5mdW5jdGlvbiBpc05leHRXaGl0ZXNwYWNlKGJvZHksIGksIGlzUm9vdCkge1xuICBpZiAoaSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgaSA9IC0xO1xuICB9XG5cbiAgbGV0IG5leHQgPSBib2R5W2kgKyAxXSxcbiAgICAgIHNpYmxpbmcgPSBib2R5W2kgKyAyXTtcbiAgaWYgKCFuZXh0KSB7XG4gICAgcmV0dXJuIGlzUm9vdDtcbiAgfVxuXG4gIGlmIChuZXh0LnR5cGUgPT09ICdDb250ZW50U3RhdGVtZW50Jykge1xuICAgIHJldHVybiAoc2libGluZyB8fCAhaXNSb290ID8gKC9eXFxzKj9cXHI/XFxuLykgOiAoL15cXHMqPyhcXHI/XFxufCQpLykpLnRlc3QobmV4dC5vcmlnaW5hbCk7XG4gIH1cbn1cblxuLy8gTWFya3MgdGhlIG5vZGUgdG8gdGhlIHJpZ2h0IG9mIHRoZSBwb3NpdGlvbiBhcyBvbWl0dGVkLlxuLy8gSS5lLiB7e2Zvb319JyAnIHdpbGwgbWFyayB0aGUgJyAnIG5vZGUgYXMgb21pdHRlZC5cbi8vXG4vLyBJZiBpIGlzIHVuZGVmaW5lZCwgdGhlbiB0aGUgZmlyc3QgY2hpbGQgd2lsbCBiZSBtYXJrZWQgYXMgc3VjaC5cbi8vXG4vLyBJZiBtdWxpdHBsZSBpcyB0cnV0aHkgdGhlbiBhbGwgd2hpdGVzcGFjZSB3aWxsIGJlIHN0cmlwcGVkIG91dCB1bnRpbCBub24td2hpdGVzcGFjZVxuLy8gY29udGVudCBpcyBtZXQuXG5mdW5jdGlvbiBvbWl0UmlnaHQoYm9keSwgaSwgbXVsdGlwbGUpIHtcbiAgbGV0IGN1cnJlbnQgPSBib2R5W2kgPT0gbnVsbCA/IDAgOiBpICsgMV07XG4gIGlmICghY3VycmVudCB8fCBjdXJyZW50LnR5cGUgIT09ICdDb250ZW50U3RhdGVtZW50JyB8fCAoIW11bHRpcGxlICYmIGN1cnJlbnQucmlnaHRTdHJpcHBlZCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgb3JpZ2luYWwgPSBjdXJyZW50LnZhbHVlO1xuICBjdXJyZW50LnZhbHVlID0gY3VycmVudC52YWx1ZS5yZXBsYWNlKG11bHRpcGxlID8gKC9eXFxzKy8pIDogKC9eWyBcXHRdKlxccj9cXG4/LyksICcnKTtcbiAgY3VycmVudC5yaWdodFN0cmlwcGVkID0gY3VycmVudC52YWx1ZSAhPT0gb3JpZ2luYWw7XG59XG5cbi8vIE1hcmtzIHRoZSBub2RlIHRvIHRoZSBsZWZ0IG9mIHRoZSBwb3NpdGlvbiBhcyBvbWl0dGVkLlxuLy8gSS5lLiAnICd7e2Zvb319IHdpbGwgbWFyayB0aGUgJyAnIG5vZGUgYXMgb21pdHRlZC5cbi8vXG4vLyBJZiBpIGlzIHVuZGVmaW5lZCB0aGVuIHRoZSBsYXN0IGNoaWxkIHdpbGwgYmUgbWFya2VkIGFzIHN1Y2guXG4vL1xuLy8gSWYgbXVsaXRwbGUgaXMgdHJ1dGh5IHRoZW4gYWxsIHdoaXRlc3BhY2Ugd2lsbCBiZSBzdHJpcHBlZCBvdXQgdW50aWwgbm9uLXdoaXRlc3BhY2Vcbi8vIGNvbnRlbnQgaXMgbWV0LlxuZnVuY3Rpb24gb21pdExlZnQoYm9keSwgaSwgbXVsdGlwbGUpIHtcbiAgbGV0IGN1cnJlbnQgPSBib2R5W2kgPT0gbnVsbCA/IGJvZHkubGVuZ3RoIC0gMSA6IGkgLSAxXTtcbiAgaWYgKCFjdXJyZW50IHx8IGN1cnJlbnQudHlwZSAhPT0gJ0NvbnRlbnRTdGF0ZW1lbnQnIHx8ICghbXVsdGlwbGUgJiYgY3VycmVudC5sZWZ0U3RyaXBwZWQpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gV2Ugb21pdCB0aGUgbGFzdCBub2RlIGlmIGl0J3Mgd2hpdGVzcGFjZSBvbmx5IGFuZCBub3QgcHJlY2VlZGVkIGJ5IGEgbm9uLWNvbnRlbnQgbm9kZS5cbiAgbGV0IG9yaWdpbmFsID0gY3VycmVudC52YWx1ZTtcbiAgY3VycmVudC52YWx1ZSA9IGN1cnJlbnQudmFsdWUucmVwbGFjZShtdWx0aXBsZSA/ICgvXFxzKyQvKSA6ICgvWyBcXHRdKyQvKSwgJycpO1xuICBjdXJyZW50LmxlZnRTdHJpcHBlZCA9IGN1cnJlbnQudmFsdWUgIT09IG9yaWdpbmFsO1xuICByZXR1cm4gY3VycmVudC5sZWZ0U3RyaXBwZWQ7XG59XG5cbmV4cG9ydCBkZWZhdWx0IFdoaXRlc3BhY2VDb250cm9sO1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/decorators.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/decorators.js new file mode 100644 index 0000000..7c23cab --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/decorators.js @@ -0,0 +1,16 @@ +define(['exports', './decorators/inline'], function (exports, _decoratorsInline) { + 'use strict'; + + exports.__esModule = true; + exports.registerDefaultDecorators = registerDefaultDecorators; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _registerInline = _interopRequireDefault(_decoratorsInline); + + function registerDefaultDecorators(instance) { + _registerInline['default'](instance); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFFTyxXQUFTLHlCQUF5QixDQUFDLFFBQVEsRUFBRTtBQUNsRCwrQkFBZSxRQUFRLENBQUMsQ0FBQztHQUMxQiIsImZpbGUiOiJkZWNvcmF0b3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZ2lzdGVySW5saW5lIGZyb20gJy4vZGVjb3JhdG9ycy9pbmxpbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0RGVjb3JhdG9ycyhpbnN0YW5jZSkge1xuICByZWdpc3RlcklubGluZShpbnN0YW5jZSk7XG59XG5cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/decorators/inline.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/decorators/inline.js new file mode 100644 index 0000000..125e396 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/decorators/inline.js @@ -0,0 +1,25 @@ +define(['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerDecorator('inline', function (fn, props, container, options) { + var ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function (context, options) { + // Create a new partials stack frame prior to exec. + var original = container.partials; + container.partials = _utils.extend({}, original, props.partials); + var ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMvaW5saW5lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFFZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFVBQVMsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFO0FBQzNFLFVBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNiLFVBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFO0FBQ25CLGFBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLFdBQUcsR0FBRyxVQUFTLE9BQU8sRUFBRSxPQUFPLEVBQUU7O0FBRS9CLGNBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUM7QUFDbEMsbUJBQVMsQ0FBQyxRQUFRLEdBQUcsT0FWckIsTUFBTSxDQVVzQixFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMxRCxjQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9CLG1CQUFTLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUM5QixpQkFBTyxHQUFHLENBQUM7U0FDWixDQUFDO09BQ0g7O0FBRUQsV0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsQ0FBQzs7QUFFN0MsYUFBTyxHQUFHLENBQUM7S0FDWixDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJpbmxpbmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2V4dGVuZH0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckRlY29yYXRvcignaW5saW5lJywgZnVuY3Rpb24oZm4sIHByb3BzLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICBsZXQgcmV0ID0gZm47XG4gICAgaWYgKCFwcm9wcy5wYXJ0aWFscykge1xuICAgICAgcHJvcHMucGFydGlhbHMgPSB7fTtcbiAgICAgIHJldCA9IGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHBhcnRpYWxzIHN0YWNrIGZyYW1lIHByaW9yIHRvIGV4ZWMuXG4gICAgICAgIGxldCBvcmlnaW5hbCA9IGNvbnRhaW5lci5wYXJ0aWFscztcbiAgICAgICAgY29udGFpbmVyLnBhcnRpYWxzID0gZXh0ZW5kKHt9LCBvcmlnaW5hbCwgcHJvcHMucGFydGlhbHMpO1xuICAgICAgICBsZXQgcmV0ID0gZm4oY29udGV4dCwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IG9yaWdpbmFsO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBwcm9wcy5wYXJ0aWFsc1tvcHRpb25zLmFyZ3NbMF1dID0gb3B0aW9ucy5mbjtcblxuICAgIHJldHVybiByZXQ7XG4gIH0pO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/exception.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/exception.js new file mode 100644 index 0000000..52cf4b8 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/exception.js @@ -0,0 +1,50 @@ +define(['exports', 'module'], function (exports, module) { + 'use strict'; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var loc = node && node.loc, + line = undefined, + column = undefined; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (Object.defineProperty) { + Object.defineProperty(this, 'column', { value: column }); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } + } + + Exception.prototype = new Error(); + + module.exports = Exception; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2V4Y2VwdGlvbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxNQUFNLFVBQVUsR0FBRyxDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDOztBQUVuRyxXQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQ2hDLFFBQUksR0FBRyxHQUFHLElBQUksSUFBSSxJQUFJLENBQUMsR0FBRztRQUN0QixJQUFJLFlBQUE7UUFDSixNQUFNLFlBQUEsQ0FBQztBQUNYLFFBQUksR0FBRyxFQUFFO0FBQ1AsVUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO0FBQ3RCLFlBQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQzs7QUFFMUIsYUFBTyxJQUFJLEtBQUssR0FBRyxJQUFJLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztLQUN4Qzs7QUFFRCxRQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDOzs7QUFHMUQsU0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUU7QUFDaEQsVUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztLQUM5Qzs7O0FBR0QsUUFBSSxLQUFLLENBQUMsaUJBQWlCLEVBQUU7QUFDM0IsV0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztLQUMxQzs7QUFFRCxRQUFJO0FBQ0YsVUFBSSxHQUFHLEVBQUU7QUFDUCxZQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQzs7OztBQUl2QixZQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUU7QUFDekIsZ0JBQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFDO1NBQ3hELE1BQU07QUFDTCxjQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztTQUN0QjtPQUNGO0tBQ0YsQ0FBQyxPQUFPLEdBQUcsRUFBRTs7S0FFYjtHQUNGOztBQUVELFdBQVMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQzs7bUJBRW5CLFNBQVMiLCJmaWxlIjoiZXhjZXB0aW9uLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5jb25zdCBlcnJvclByb3BzID0gWydkZXNjcmlwdGlvbicsICdmaWxlTmFtZScsICdsaW5lTnVtYmVyJywgJ21lc3NhZ2UnLCAnbmFtZScsICdudW1iZXInLCAnc3RhY2snXTtcblxuZnVuY3Rpb24gRXhjZXB0aW9uKG1lc3NhZ2UsIG5vZGUpIHtcbiAgbGV0IGxvYyA9IG5vZGUgJiYgbm9kZS5sb2MsXG4gICAgICBsaW5lLFxuICAgICAgY29sdW1uO1xuICBpZiAobG9jKSB7XG4gICAgbGluZSA9IGxvYy5zdGFydC5saW5lO1xuICAgIGNvbHVtbiA9IGxvYy5zdGFydC5jb2x1bW47XG5cbiAgICBtZXNzYWdlICs9ICcgLSAnICsgbGluZSArICc6JyArIGNvbHVtbjtcbiAgfVxuXG4gIGxldCB0bXAgPSBFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IuY2FsbCh0aGlzLCBtZXNzYWdlKTtcblxuICAvLyBVbmZvcnR1bmF0ZWx5IGVycm9ycyBhcmUgbm90IGVudW1lcmFibGUgaW4gQ2hyb21lIChhdCBsZWFzdCksIHNvIGBmb3IgcHJvcCBpbiB0bXBgIGRvZXNuJ3Qgd29yay5cbiAgZm9yIChsZXQgaWR4ID0gMDsgaWR4IDwgZXJyb3JQcm9wcy5sZW5ndGg7IGlkeCsrKSB7XG4gICAgdGhpc1tlcnJvclByb3BzW2lkeF1dID0gdG1wW2Vycm9yUHJvcHNbaWR4XV07XG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBFeGNlcHRpb24pO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAobG9jKSB7XG4gICAgICB0aGlzLmxpbmVOdW1iZXIgPSBsaW5lO1xuXG4gICAgICAvLyBXb3JrIGFyb3VuZCBpc3N1ZSB1bmRlciBzYWZhcmkgd2hlcmUgd2UgY2FuJ3QgZGlyZWN0bHkgc2V0IHRoZSBjb2x1bW4gdmFsdWVcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnY29sdW1uJywge3ZhbHVlOiBjb2x1bW59KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY29sdW1uID0gY29sdW1uO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAobm9wKSB7XG4gICAgLyogSWdub3JlIGlmIHRoZSBicm93c2VyIGlzIHZlcnkgcGFydGljdWxhciAqL1xuICB9XG59XG5cbkV4Y2VwdGlvbi5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTtcblxuZXhwb3J0IGRlZmF1bHQgRXhjZXB0aW9uO1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers.js new file mode 100644 index 0000000..38cb506 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers.js @@ -0,0 +1,34 @@ +define(['exports', './helpers/block-helper-missing', './helpers/each', './helpers/helper-missing', './helpers/if', './helpers/log', './helpers/lookup', './helpers/with'], function (exports, _helpersBlockHelperMissing, _helpersEach, _helpersHelperMissing, _helpersIf, _helpersLog, _helpersLookup, _helpersWith) { + 'use strict'; + + exports.__esModule = true; + exports.registerDefaultHelpers = registerDefaultHelpers; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _registerBlockHelperMissing = _interopRequireDefault(_helpersBlockHelperMissing); + + var _registerEach = _interopRequireDefault(_helpersEach); + + var _registerHelperMissing = _interopRequireDefault(_helpersHelperMissing); + + var _registerIf = _interopRequireDefault(_helpersIf); + + var _registerLog = _interopRequireDefault(_helpersLog); + + var _registerLookup = _interopRequireDefault(_helpersLookup); + + var _registerWith = _interopRequireDefault(_helpersWith); + + function registerDefaultHelpers(instance) { + _registerBlockHelperMissing['default'](instance); + _registerEach['default'](instance); + _registerHelperMissing['default'](instance); + _registerIf['default'](instance); + _registerLog['default'](instance); + _registerLookup['default'](instance); + _registerWith['default'](instance); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRTyxXQUFTLHNCQUFzQixDQUFDLFFBQVEsRUFBRTtBQUMvQywyQ0FBMkIsUUFBUSxDQUFDLENBQUM7QUFDckMsNkJBQWEsUUFBUSxDQUFDLENBQUM7QUFDdkIsc0NBQXNCLFFBQVEsQ0FBQyxDQUFDO0FBQ2hDLDJCQUFXLFFBQVEsQ0FBQyxDQUFDO0FBQ3JCLDRCQUFZLFFBQVEsQ0FBQyxDQUFDO0FBQ3RCLCtCQUFlLFFBQVEsQ0FBQyxDQUFDO0FBQ3pCLDZCQUFhLFFBQVEsQ0FBQyxDQUFDO0dBQ3hCIiwiZmlsZSI6ImhlbHBlcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcmVnaXN0ZXJCbG9ja0hlbHBlck1pc3NpbmcgZnJvbSAnLi9oZWxwZXJzL2Jsb2NrLWhlbHBlci1taXNzaW5nJztcbmltcG9ydCByZWdpc3RlckVhY2ggZnJvbSAnLi9oZWxwZXJzL2VhY2gnO1xuaW1wb3J0IHJlZ2lzdGVySGVscGVyTWlzc2luZyBmcm9tICcuL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcnO1xuaW1wb3J0IHJlZ2lzdGVySWYgZnJvbSAnLi9oZWxwZXJzL2lmJztcbmltcG9ydCByZWdpc3RlckxvZyBmcm9tICcuL2hlbHBlcnMvbG9nJztcbmltcG9ydCByZWdpc3Rlckxvb2t1cCBmcm9tICcuL2hlbHBlcnMvbG9va3VwJztcbmltcG9ydCByZWdpc3RlcldpdGggZnJvbSAnLi9oZWxwZXJzL3dpdGgnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0SGVscGVycyhpbnN0YW5jZSkge1xuICByZWdpc3RlckJsb2NrSGVscGVyTWlzc2luZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyRWFjaChpbnN0YW5jZSk7XG4gIHJlZ2lzdGVySGVscGVyTWlzc2luZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVySWYoaW5zdGFuY2UpO1xuICByZWdpc3RlckxvZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyTG9va3VwKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJXaXRoKGluc3RhbmNlKTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/block-helper-missing.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/block-helper-missing.js new file mode 100644 index 0000000..1469897 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/block-helper-missing.js @@ -0,0 +1,35 @@ +define(['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('blockHelperMissing', function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvYmxvY2staGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3ZFLFVBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPO1VBQ3pCLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDOztBQUVwQixVQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUU7QUFDcEIsZUFBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDakIsTUFBTSxJQUFJLE9BQU8sS0FBSyxLQUFLLElBQUksT0FBTyxJQUFJLElBQUksRUFBRTtBQUMvQyxlQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUN0QixNQUFNLElBQUksT0FYeUIsT0FBTyxDQVd4QixPQUFPLENBQUMsRUFBRTtBQUMzQixZQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0FBQ3RCLGNBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUNmLG1CQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1dBQzlCOztBQUVELGlCQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztTQUNoRCxNQUFNO0FBQ0wsaUJBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3RCO09BQ0YsTUFBTTtBQUNMLFlBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO0FBQy9CLGNBQUksSUFBSSxHQUFHLE9BdkJRLFdBQVcsQ0F1QlAsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JDLGNBQUksQ0FBQyxXQUFXLEdBQUcsT0F4Qm5CLGlCQUFpQixDQXdCb0IsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzdFLGlCQUFPLEdBQUcsRUFBQyxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUM7U0FDeEI7O0FBRUQsZUFBTyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO09BQzdCO0tBQ0YsQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiYmxvY2staGVscGVyLW1pc3NpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBjcmVhdGVGcmFtZSwgaXNBcnJheX0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignYmxvY2tIZWxwZXJNaXNzaW5nJywgZnVuY3Rpb24oY29udGV4dCwgb3B0aW9ucykge1xuICAgIGxldCBpbnZlcnNlID0gb3B0aW9ucy5pbnZlcnNlLFxuICAgICAgICBmbiA9IG9wdGlvbnMuZm47XG5cbiAgICBpZiAoY29udGV4dCA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIGZuKHRoaXMpO1xuICAgIH0gZWxzZSBpZiAoY29udGV4dCA9PT0gZmFsc2UgfHwgY29udGV4dCA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gaW52ZXJzZSh0aGlzKTtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkoY29udGV4dCkpIHtcbiAgICAgIGlmIChjb250ZXh0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgICAgICAgb3B0aW9ucy5pZHMgPSBbb3B0aW9ucy5uYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbnN0YW5jZS5oZWxwZXJzLmVhY2goY29udGV4dCwgb3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gaW52ZXJzZSh0aGlzKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLmlkcykge1xuICAgICAgICBsZXQgZGF0YSA9IGNyZWF0ZUZyYW1lKG9wdGlvbnMuZGF0YSk7XG4gICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBhcHBlbmRDb250ZXh0UGF0aChvcHRpb25zLmRhdGEuY29udGV4dFBhdGgsIG9wdGlvbnMubmFtZSk7XG4gICAgICAgIG9wdGlvbnMgPSB7ZGF0YTogZGF0YX07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCBvcHRpb25zKTtcbiAgICB9XG4gIH0pO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/each.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/each.js new file mode 100644 index 0000000..48ecf2a --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/each.js @@ -0,0 +1,89 @@ +define(['exports', 'module', '../utils', '../exception'], function (exports, module, _utils, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + module.exports = function (instance) { + instance.registerHelper('each', function (context, options) { + if (!options) { + throw new _Exception['default']('Must pass iterator to #each'); + } + + var fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data = undefined, + contextPath = undefined; + + if (options.data && options.ids) { + contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (_utils.isFunction(context)) { + context = context.call(this); + } + + if (options.data) { + data = _utils.createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (_utils.isArray(context)) { + for (var j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + var priorKey = undefined; + + for (var key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvZWFjaC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7bUJBR2UsVUFBUyxRQUFRLEVBQUU7QUFDaEMsWUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFVBQUksQ0FBQyxPQUFPLEVBQUU7QUFDWixjQUFNLDBCQUFjLDZCQUE2QixDQUFDLENBQUM7T0FDcEQ7O0FBRUQsVUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUU7VUFDZixPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU87VUFDekIsQ0FBQyxHQUFHLENBQUM7VUFDTCxHQUFHLEdBQUcsRUFBRTtVQUNSLElBQUksWUFBQTtVQUNKLFdBQVcsWUFBQSxDQUFDOztBQUVoQixVQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUMvQixtQkFBVyxHQUFHLE9BakJaLGlCQUFpQixDQWlCYSxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO09BQ2pGOztBQUVELFVBQUksT0FwQnNELFVBQVUsQ0FvQnJELE9BQU8sQ0FBQyxFQUFFO0FBQUUsZUFBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7T0FBRTs7QUFFMUQsVUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFO0FBQ2hCLFlBQUksR0FBRyxPQXZCMkIsV0FBVyxDQXVCMUIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ2xDOztBQUVELGVBQVMsYUFBYSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO0FBQ3pDLFlBQUksSUFBSSxFQUFFO0FBQ1IsY0FBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFDakIsY0FBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7QUFDbkIsY0FBSSxDQUFDLEtBQUssR0FBRyxLQUFLLEtBQUssQ0FBQyxDQUFDO0FBQ3pCLGNBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQzs7QUFFbkIsY0FBSSxXQUFXLEVBQUU7QUFDZixnQkFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLEdBQUcsS0FBSyxDQUFDO1dBQ3hDO1NBQ0Y7O0FBRUQsV0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO0FBQzdCLGNBQUksRUFBRSxJQUFJO0FBQ1YscUJBQVcsRUFBRSxPQXhDTSxXQUFXLENBd0NMLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxHQUFHLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUMvRSxDQUFDLENBQUM7T0FDSjs7QUFFRCxVQUFJLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7QUFDMUMsWUFBSSxPQTdDMkMsT0FBTyxDQTZDMUMsT0FBTyxDQUFDLEVBQUU7QUFDcEIsZUFBSyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDdkMsZ0JBQUksQ0FBQyxJQUFJLE9BQU8sRUFBRTtBQUNoQiwyQkFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7YUFDL0M7V0FDRjtTQUNGLE1BQU07QUFDTCxjQUFJLFFBQVEsWUFBQSxDQUFDOztBQUViLGVBQUssSUFBSSxHQUFHLElBQUksT0FBTyxFQUFFO0FBQ3ZCLGdCQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUU7Ozs7QUFJL0Isa0JBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQiw2QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7ZUFDaEM7QUFDRCxzQkFBUSxHQUFHLEdBQUcsQ0FBQztBQUNmLGVBQUMsRUFBRSxDQUFDO2FBQ0w7V0FDRjtBQUNELGNBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQix5QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1dBQ3RDO1NBQ0Y7T0FDRjs7QUFFRCxVQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7QUFDWCxXQUFHLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ3JCOztBQUVELGFBQU8sR0FBRyxDQUFDO0tBQ1osQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiZWFjaC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXBwZW5kQ29udGV4dFBhdGgsIGJsb2NrUGFyYW1zLCBjcmVhdGVGcmFtZSwgaXNBcnJheSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuLi9leGNlcHRpb24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignZWFjaCcsIGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ011c3QgcGFzcyBpdGVyYXRvciB0byAjZWFjaCcpO1xuICAgIH1cblxuICAgIGxldCBmbiA9IG9wdGlvbnMuZm4sXG4gICAgICAgIGludmVyc2UgPSBvcHRpb25zLmludmVyc2UsXG4gICAgICAgIGkgPSAwLFxuICAgICAgICByZXQgPSAnJyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29udGV4dFBhdGg7XG5cbiAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICBjb250ZXh0UGF0aCA9IGFwcGVuZENvbnRleHRQYXRoKG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aCwgb3B0aW9ucy5pZHNbMF0pICsgJy4nO1xuICAgIH1cblxuICAgIGlmIChpc0Z1bmN0aW9uKGNvbnRleHQpKSB7IGNvbnRleHQgPSBjb250ZXh0LmNhbGwodGhpcyk7IH1cblxuICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4ZWNJdGVyYXRpb24oZmllbGQsIGluZGV4LCBsYXN0KSB7XG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICBkYXRhLmtleSA9IGZpZWxkO1xuICAgICAgICBkYXRhLmluZGV4ID0gaW5kZXg7XG4gICAgICAgIGRhdGEuZmlyc3QgPSBpbmRleCA9PT0gMDtcbiAgICAgICAgZGF0YS5sYXN0ID0gISFsYXN0O1xuXG4gICAgICAgIGlmIChjb250ZXh0UGF0aCkge1xuICAgICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBjb250ZXh0UGF0aCArIGZpZWxkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldCA9IHJldCArIGZuKGNvbnRleHRbZmllbGRdLCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dFtmaWVsZF0sIGZpZWxkXSwgW2NvbnRleHRQYXRoICsgZmllbGQsIG51bGxdKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoaXNBcnJheShjb250ZXh0KSkge1xuICAgICAgICBmb3IgKGxldCBqID0gY29udGV4dC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcbiAgICAgICAgICBpZiAoaSBpbiBjb250ZXh0KSB7XG4gICAgICAgICAgICBleGVjSXRlcmF0aW9uKGksIGksIGkgPT09IGNvbnRleHQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcHJpb3JLZXk7XG5cbiAgICAgICAgZm9yIChsZXQga2V5IGluIGNvbnRleHQpIHtcbiAgICAgICAgICBpZiAoY29udGV4dC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBydW5uaW5nIHRoZSBpdGVyYXRpb25zIG9uZSBzdGVwIG91dCBvZiBzeW5jIHNvIHdlIGNhbiBkZXRlY3RcbiAgICAgICAgICAgIC8vIHRoZSBsYXN0IGl0ZXJhdGlvbiB3aXRob3V0IGhhdmUgdG8gc2NhbiB0aGUgb2JqZWN0IHR3aWNlIGFuZCBjcmVhdGVcbiAgICAgICAgICAgIC8vIGFuIGl0ZXJtZWRpYXRlIGtleXMgYXJyYXkuXG4gICAgICAgICAgICBpZiAocHJpb3JLZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmlvcktleSA9IGtleTtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByaW9yS2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgcmV0ID0gaW52ZXJzZSh0aGlzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/helper-missing.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/helper-missing.js new file mode 100644 index 0000000..75d43f6 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/helper-missing.js @@ -0,0 +1,22 @@ +define(['exports', 'module', '../exception'], function (exports, module, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + module.exports = function (instance) { + instance.registerHelper('helperMissing', function () /* [args, ]options */{ + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new _Exception['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsZUFBZSxFQUFFLGlDQUFnQztBQUN2RSxVQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFOztBQUUxQixlQUFPLFNBQVMsQ0FBQztPQUNsQixNQUFNOztBQUVMLGNBQU0sMEJBQWMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO09BQ3ZGO0tBQ0YsQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiaGVscGVyLW1pc3NpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdoZWxwZXJNaXNzaW5nJywgZnVuY3Rpb24oLyogW2FyZ3MsIF1vcHRpb25zICovKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIC8vIEEgbWlzc2luZyBmaWVsZCBpbiBhIHt7Zm9vfX0gY29uc3RydWN0LlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU29tZW9uZSBpcyBhY3R1YWxseSB0cnlpbmcgdG8gY2FsbCBzb21ldGhpbmcsIGJsb3cgdXAuXG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdNaXNzaW5nIGhlbHBlcjogXCInICsgYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXS5uYW1lICsgJ1wiJyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/if.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/if.js new file mode 100644 index 0000000..d1aa021 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/if.js @@ -0,0 +1,25 @@ +define(['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('if', function (conditional, options) { + if (_utils.isFunction(conditional)) { + conditional = conditional.call(this); + } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function (conditional, options) { + return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaWYuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVMsV0FBVyxFQUFFLE9BQU8sRUFBRTtBQUMzRCxVQUFJLE9BSlMsVUFBVSxDQUlSLFdBQVcsQ0FBQyxFQUFFO0FBQUUsbUJBQVcsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQUU7Ozs7O0FBS3RFLFVBQUksQUFBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxJQUFLLE9BVC9DLE9BQU8sQ0FTZ0QsV0FBVyxDQUFDLEVBQUU7QUFDdkUsZUFBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQzlCLE1BQU07QUFDTCxlQUFPLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDekI7S0FDRixDQUFDLENBQUM7O0FBRUgsWUFBUSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsVUFBUyxXQUFXLEVBQUUsT0FBTyxFQUFFO0FBQy9ELGFBQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQztLQUN2SCxDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJpZi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aXNFbXB0eSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignaWYnLCBmdW5jdGlvbihjb25kaXRpb25hbCwgb3B0aW9ucykge1xuICAgIGlmIChpc0Z1bmN0aW9uKGNvbmRpdGlvbmFsKSkgeyBjb25kaXRpb25hbCA9IGNvbmRpdGlvbmFsLmNhbGwodGhpcyk7IH1cblxuICAgIC8vIERlZmF1bHQgYmVoYXZpb3IgaXMgdG8gcmVuZGVyIHRoZSBwb3NpdGl2ZSBwYXRoIGlmIHRoZSB2YWx1ZSBpcyB0cnV0aHkgYW5kIG5vdCBlbXB0eS5cbiAgICAvLyBUaGUgYGluY2x1ZGVaZXJvYCBvcHRpb24gbWF5IGJlIHNldCB0byB0cmVhdCB0aGUgY29uZHRpb25hbCBhcyBwdXJlbHkgbm90IGVtcHR5IGJhc2VkIG9uIHRoZVxuICAgIC8vIGJlaGF2aW9yIG9mIGlzRW1wdHkuIEVmZmVjdGl2ZWx5IHRoaXMgZGV0ZXJtaW5lcyBpZiAwIGlzIGhhbmRsZWQgYnkgdGhlIHBvc2l0aXZlIHBhdGggb3IgbmVnYXRpdmUuXG4gICAgaWYgKCghb3B0aW9ucy5oYXNoLmluY2x1ZGVaZXJvICYmICFjb25kaXRpb25hbCkgfHwgaXNFbXB0eShjb25kaXRpb25hbCkpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmZuKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3VubGVzcycsIGZ1bmN0aW9uKGNvbmRpdGlvbmFsLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGluc3RhbmNlLmhlbHBlcnNbJ2lmJ10uY2FsbCh0aGlzLCBjb25kaXRpb25hbCwge2ZuOiBvcHRpb25zLmludmVyc2UsIGludmVyc2U6IG9wdGlvbnMuZm4sIGhhc2g6IG9wdGlvbnMuaGFzaH0pO1xuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/log.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/log.js new file mode 100644 index 0000000..7ea9080 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/log.js @@ -0,0 +1,24 @@ +define(['exports', 'module'], function (exports, module) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('log', function () /* message, options */{ + var args = [undefined], + options = arguments[arguments.length - 1]; + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + var level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log.apply(instance, args); + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFBZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxrQ0FBaUM7QUFDOUQsVUFBSSxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUM7VUFDbEIsT0FBTyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQzlDLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM3QyxZQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO09BQ3pCOztBQUVELFVBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztBQUNkLFVBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFO0FBQzlCLGFBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztPQUM1QixNQUFNLElBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUU7QUFDckQsYUFBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO09BQzVCO0FBQ0QsVUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQzs7QUFFaEIsY0FBUSxDQUFDLEdBQUcsTUFBQSxDQUFaLFFBQVEsRUFBUyxJQUFJLENBQUMsQ0FBQztLQUN4QixDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJsb2cuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignbG9nJywgZnVuY3Rpb24oLyogbWVzc2FnZSwgb3B0aW9ucyAqLykge1xuICAgIGxldCBhcmdzID0gW3VuZGVmaW5lZF0sXG4gICAgICAgIG9wdGlvbnMgPSBhcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aCAtIDFdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgYXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gICAgfVxuXG4gICAgbGV0IGxldmVsID0gMTtcbiAgICBpZiAob3B0aW9ucy5oYXNoLmxldmVsICE9IG51bGwpIHtcbiAgICAgIGxldmVsID0gb3B0aW9ucy5oYXNoLmxldmVsO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuZGF0YS5sZXZlbCAhPSBudWxsKSB7XG4gICAgICBsZXZlbCA9IG9wdGlvbnMuZGF0YS5sZXZlbDtcbiAgICB9XG4gICAgYXJnc1swXSA9IGxldmVsO1xuXG4gICAgaW5zdGFuY2UubG9nKC4uLiBhcmdzKTtcbiAgfSk7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/lookup.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/lookup.js new file mode 100644 index 0000000..8ed79c6 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/lookup.js @@ -0,0 +1,10 @@ +define(['exports', 'module'], function (exports, module) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('lookup', function (obj, field) { + return obj && obj[field]; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9va3VwLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFBZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxVQUFTLEdBQUcsRUFBRSxLQUFLLEVBQUU7QUFDckQsYUFBTyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQzFCLENBQUMsQ0FBQztHQUNKIiwiZmlsZSI6Imxvb2t1cC5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdsb29rdXAnLCBmdW5jdGlvbihvYmosIGZpZWxkKSB7XG4gICAgcmV0dXJuIG9iaiAmJiBvYmpbZmllbGRdO1xuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/with.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/with.js new file mode 100644 index 0000000..1428bac --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/helpers/with.js @@ -0,0 +1,29 @@ +define(['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('with', function (context, options) { + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvd2l0aC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7bUJBRWUsVUFBUyxRQUFRLEVBQUU7QUFDaEMsWUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFVBQUksT0FKc0QsVUFBVSxDQUlyRCxPQUFPLENBQUMsRUFBRTtBQUFFLGVBQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQUU7O0FBRTFELFVBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUM7O0FBRXBCLFVBQUksQ0FBQyxPQVI0QyxPQUFPLENBUTNDLE9BQU8sQ0FBQyxFQUFFO0FBQ3JCLFlBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUFDeEIsWUFBSSxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7QUFDL0IsY0FBSSxHQUFHLE9BWHlCLFdBQVcsQ0FXeEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2pDLGNBQUksQ0FBQyxXQUFXLEdBQUcsT0FabkIsaUJBQWlCLENBWW9CLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoRjs7QUFFRCxlQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUU7QUFDakIsY0FBSSxFQUFFLElBQUk7QUFDVixxQkFBVyxFQUFFLE9BakJNLFdBQVcsQ0FpQkwsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDaEUsQ0FBQyxDQUFDO09BQ0osTUFBTTtBQUNMLGVBQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUM5QjtLQUNGLENBQUMsQ0FBQztHQUNKIiwiZmlsZSI6IndpdGguanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBibG9ja1BhcmFtcywgY3JlYXRlRnJhbWUsIGlzRW1wdHksIGlzRnVuY3Rpb259IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oaW5zdGFuY2UpIHtcbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3dpdGgnLCBmdW5jdGlvbihjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24oY29udGV4dCkpIHsgY29udGV4dCA9IGNvbnRleHQuY2FsbCh0aGlzKTsgfVxuXG4gICAgbGV0IGZuID0gb3B0aW9ucy5mbjtcblxuICAgIGlmICghaXNFbXB0eShjb250ZXh0KSkge1xuICAgICAgbGV0IGRhdGEgPSBvcHRpb25zLmRhdGE7XG4gICAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgICAgICBkYXRhLmNvbnRleHRQYXRoID0gYXBwZW5kQ29udGV4dFBhdGgob3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoLCBvcHRpb25zLmlkc1swXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dF0sIFtkYXRhICYmIGRhdGEuY29udGV4dFBhdGhdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/logger.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/logger.js new file mode 100644 index 0000000..7786eda --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/logger.js @@ -0,0 +1,44 @@ +define(['exports', 'module', './utils'], function (exports, module, _utils) { + 'use strict'; + + var logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function lookupLevel(level) { + if (typeof level === 'string') { + var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function log(level) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + var method = logger.methodMap[level]; + if (!console[method]) { + // eslint-disable-line no-console + method = 'log'; + } + + for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + message[_key - 1] = arguments[_key]; + } + + console[method].apply(console, message); // eslint-disable-line no-console + } + } + }; + + module.exports = logger; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2xvZ2dlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxNQUFJLE1BQU0sR0FBRztBQUNYLGFBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQztBQUM3QyxTQUFLLEVBQUUsTUFBTTs7O0FBR2IsZUFBVyxFQUFFLHFCQUFTLEtBQUssRUFBRTtBQUMzQixVQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtBQUM3QixZQUFJLFFBQVEsR0FBRyxPQVRiLE9BQU8sQ0FTYyxNQUFNLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzlELFlBQUksUUFBUSxJQUFJLENBQUMsRUFBRTtBQUNqQixlQUFLLEdBQUcsUUFBUSxDQUFDO1NBQ2xCLE1BQU07QUFDTCxlQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztTQUM3QjtPQUNGOztBQUVELGFBQU8sS0FBSyxDQUFDO0tBQ2Q7OztBQUdELE9BQUcsRUFBRSxhQUFTLEtBQUssRUFBYztBQUMvQixXQUFLLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQzs7QUFFbEMsVUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxFQUFFO0FBQy9FLFlBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDckMsWUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTs7QUFDcEIsZ0JBQU0sR0FBRyxLQUFLLENBQUM7U0FDaEI7OzBDQVBtQixPQUFPO0FBQVAsaUJBQU87OztBQVEzQixlQUFPLENBQUMsTUFBTSxPQUFDLENBQWYsT0FBTyxFQUFZLE9BQU8sQ0FBQyxDQUFDO09BQzdCO0tBQ0Y7R0FDRixDQUFDOzttQkFFYSxNQUFNIiwiZmlsZSI6ImxvZ2dlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aW5kZXhPZn0gZnJvbSAnLi91dGlscyc7XG5cbmxldCBsb2dnZXIgPSB7XG4gIG1ldGhvZE1hcDogWydkZWJ1ZycsICdpbmZvJywgJ3dhcm4nLCAnZXJyb3InXSxcbiAgbGV2ZWw6ICdpbmZvJyxcblxuICAvLyBNYXBzIGEgZ2l2ZW4gbGV2ZWwgdmFsdWUgdG8gdGhlIGBtZXRob2RNYXBgIGluZGV4ZXMgYWJvdmUuXG4gIGxvb2t1cExldmVsOiBmdW5jdGlvbihsZXZlbCkge1xuICAgIGlmICh0eXBlb2YgbGV2ZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBsZXQgbGV2ZWxNYXAgPSBpbmRleE9mKGxvZ2dlci5tZXRob2RNYXAsIGxldmVsLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgaWYgKGxldmVsTWFwID49IDApIHtcbiAgICAgICAgbGV2ZWwgPSBsZXZlbE1hcDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldmVsID0gcGFyc2VJbnQobGV2ZWwsIDEwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGV2ZWw7XG4gIH0sXG5cbiAgLy8gQ2FuIGJlIG92ZXJyaWRkZW4gaW4gdGhlIGhvc3QgZW52aXJvbm1lbnRcbiAgbG9nOiBmdW5jdGlvbihsZXZlbCwgLi4ubWVzc2FnZSkge1xuICAgIGxldmVsID0gbG9nZ2VyLmxvb2t1cExldmVsKGxldmVsKTtcblxuICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbG9nZ2VyLmxvb2t1cExldmVsKGxvZ2dlci5sZXZlbCkgPD0gbGV2ZWwpIHtcbiAgICAgIGxldCBtZXRob2QgPSBsb2dnZXIubWV0aG9kTWFwW2xldmVsXTtcbiAgICAgIGlmICghY29uc29sZVttZXRob2RdKSB7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG4gICAgICAgIG1ldGhvZCA9ICdsb2cnO1xuICAgICAgfVxuICAgICAgY29uc29sZVttZXRob2RdKC4uLm1lc3NhZ2UpOyAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IGxvZ2dlcjtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/no-conflict.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/no-conflict.js new file mode 100644 index 0000000..567ff2b --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/no-conflict.js @@ -0,0 +1,18 @@ +define(['exports', 'module'], function (exports, module) { + /* global window */ + 'use strict'; + + module.exports = function (Handlebars) { + /* istanbul ignore next */ + var root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function () { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL25vLWNvbmZsaWN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7bUJBQ2UsVUFBUyxVQUFVLEVBQUU7O0FBRWxDLFFBQUksSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsR0FBRyxNQUFNLEdBQUcsTUFBTTtRQUN0RCxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQzs7QUFFbEMsY0FBVSxDQUFDLFVBQVUsR0FBRyxZQUFXO0FBQ2pDLFVBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUU7QUFDbEMsWUFBSSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUM7T0FDL0I7QUFDRCxhQUFPLFVBQVUsQ0FBQztLQUNuQixDQUFDO0dBQ0giLCJmaWxlIjoibm8tY29uZmxpY3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBnbG9iYWwgd2luZG93ICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihIYW5kbGViYXJzKSB7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGxldCByb290ID0gdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3csXG4gICAgICAkSGFuZGxlYmFycyA9IHJvb3QuSGFuZGxlYmFycztcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgSGFuZGxlYmFycy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHJvb3QuSGFuZGxlYmFycyA9PT0gSGFuZGxlYmFycykge1xuICAgICAgcm9vdC5IYW5kbGViYXJzID0gJEhhbmRsZWJhcnM7XG4gICAgfVxuICAgIHJldHVybiBIYW5kbGViYXJzO1xuICB9O1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/runtime.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/runtime.js new file mode 100644 index 0000000..1d5d667 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/runtime.js @@ -0,0 +1,287 @@ +define(['exports', './utils', './exception', './base'], function (exports, _utils, _exception, _base) { + 'use strict'; + + exports.__esModule = true; + exports.checkRevision = checkRevision; + exports.template = template; + exports.wrapProgram = wrapProgram; + exports.resolvePartial = resolvePartial; + exports.invokePartial = invokePartial; + exports.noop = noop; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function checkRevision(compilerInfo) { + var compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = _base.COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = _base.REVISION_CHANGES[currentRevision], + compilerVersions = _base.REVISION_CHANGES[compilerRevision]; + throw new _Exception['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new _Exception['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } + } + + function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new _Exception['default']('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new _Exception['default']('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = _utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + var result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + var lines = result.split('\n'); + for (var i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new _Exception['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + var container = { + strict: function strict(obj, name) { + if (!(name in obj)) { + throw new _Exception['default']('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function lookup(depths, name) { + var len = depths.length; + for (var i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function lambda(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: _utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function fn(i) { + var ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function program(i, data, declaredBlockParams, blockParams, depths) { + var programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function data(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function merge(param, common) { + var obj = param || common; + + if (param && common && param !== common) { + obj = _utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function (options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function (i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new _Exception['default']('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new _Exception['default']('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; + } + + function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; + } + + function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + var data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; + } + + function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + var partialBlock = undefined; + if (options.fn && options.fn !== noop) { + options.data = _base.createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = _utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new _Exception['default']('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } + } + + function noop() { + return ''; + } + + function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? _base.createFrame(data) : {}; + data.root = context; + } + return data; + } + + function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + var props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + _utils.extend(prog, props); + } + return prog; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3J1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUlPLFdBQVMsYUFBYSxDQUFDLFlBQVksRUFBRTtBQUMxQyxRQUFNLGdCQUFnQixHQUFHLFlBQVksSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUN2RCxlQUFlLFNBSmQsaUJBQWlCLEFBSWlCLENBQUM7O0FBRTFDLFFBQUksZ0JBQWdCLEtBQUssZUFBZSxFQUFFO0FBQ3hDLFVBQUksZ0JBQWdCLEdBQUcsZUFBZSxFQUFFO0FBQ3RDLFlBQU0sZUFBZSxHQUFHLE1BUkYsZ0JBQWdCLENBUUcsZUFBZSxDQUFDO1lBQ25ELGdCQUFnQixHQUFHLE1BVEgsZ0JBQWdCLENBU0ksZ0JBQWdCLENBQUMsQ0FBQztBQUM1RCxjQUFNLDBCQUFjLHlGQUF5RixHQUN2RyxxREFBcUQsR0FBRyxlQUFlLEdBQUcsbURBQW1ELEdBQUcsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDaEssTUFBTTs7QUFFTCxjQUFNLDBCQUFjLHdGQUF3RixHQUN0RyxpREFBaUQsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDbkY7S0FDRjtHQUNGOztBQUVNLFdBQVMsUUFBUSxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7O0FBRTFDLFFBQUksQ0FBQyxHQUFHLEVBQUU7QUFDUixZQUFNLDBCQUFjLG1DQUFtQyxDQUFDLENBQUM7S0FDMUQ7QUFDRCxRQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRTtBQUN2QyxZQUFNLDBCQUFjLDJCQUEyQixHQUFHLE9BQU8sWUFBWSxDQUFDLENBQUM7S0FDeEU7O0FBRUQsZ0JBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUM7Ozs7QUFJbEQsT0FBRyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENB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R0FBRyxPQUFPLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDLENBQUM7S0FDNUUsTUFBTSxJQUFJLE9BQU8sWUFBWSxRQUFRLEVBQUU7QUFDdEMsYUFBTyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0tBQ2xDO0dBQ0Y7O0FBRU0sV0FBUyxJQUFJLEdBQUc7QUFBRSxXQUFPLEVBQUUsQ0FBQztHQUFFOztBQUVyQyxXQUFTLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQy9CLFFBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxNQUFNLElBQUksSUFBSSxDQUFBLEFBQUMsRUFBRTtBQUM5QixVQUFJLEdBQUcsSUFBSSxHQUFHLE1BbFE0QixXQUFXLENBa1EzQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDckMsVUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7S0FDckI7QUFDRCxXQUFPLElBQUksQ0FBQztHQUNiOztBQUVELFdBQVMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7QUFDekUsUUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFO0FBQ2hCLFVBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztBQUNmLFVBQUksR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUM1RixhQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDM0I7QUFDRCxXQUFPLElBQUksQ0FBQztHQUNiIiwiZmlsZSI6InJ1bnRpbWUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBVdGlscyBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi9leGNlcHRpb24nO1xuaW1wb3J0IHsgQ09NUElMRVJfUkVWSVNJT04sIFJFVklTSU9OX0NIQU5HRVMsIGNyZWF0ZUZyYW1lIH0gZnJvbSAnLi9iYXNlJztcblxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrUmV2aXNpb24oY29tcGlsZXJJbmZvKSB7XG4gIGNvbnN0IGNvbXBpbGVyUmV2aXNpb24gPSBjb21waWxlckluZm8gJiYgY29tcGlsZXJJbmZvWzBdIHx8IDEsXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbiA9IENPTVBJTEVSX1JFVklTSU9OO1xuXG4gIGlmIChjb21waWxlclJldmlzaW9uICE9PSBjdXJyZW50UmV2aXNpb24pIHtcbiAgICBpZiAoY29tcGlsZXJSZXZpc2lvbiA8IGN1cnJlbnRSZXZpc2lvbikge1xuICAgICAgY29uc3QgcnVudGltZVZlcnNpb25zID0gUkVWSVNJT05fQ0hBTkdFU1tjdXJyZW50UmV2aXNpb25dLFxuICAgICAgICAgICAgY29tcGlsZXJWZXJzaW9ucyA9IFJFVklTSU9OX0NIQU5HRVNbY29tcGlsZXJSZXZpc2lvbl07XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUZW1wbGF0ZSB3YXMgcHJlY29tcGlsZWQgd2l0aCBhbiBvbGRlciB2ZXJzaW9uIG9mIEhhbmRsZWJhcnMgdGhhbiB0aGUgY3VycmVudCBydW50aW1lLiAnICtcbiAgICAgICAgICAgICdQbGVhc2UgdXBkYXRlIHlvdXIgcHJlY29tcGlsZXIgdG8gYSBuZXdlciB2ZXJzaW9uICgnICsgcnVudGltZVZlcnNpb25zICsgJykgb3IgZG93bmdyYWRlIHlvdXIgcnVudGltZSB0byBhbiBvbGRlciB2ZXJzaW9uICgnICsgY29tcGlsZXJWZXJzaW9ucyArICcpLicpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBVc2UgdGhlIGVtYmVkZGVkIHZlcnNpb24gaW5mbyBzaW5jZSB0aGUgcnVudGltZSBkb2Vzbid0IGtub3cgYWJvdXQgdGhpcyByZXZpc2lvbiB5ZXRcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1RlbXBsYXRlIHdhcyBwcmVjb21waWxlZCB3aXRoIGEgbmV3ZXIgdmVyc2lvbiBvZiBIYW5kbGViYXJzIHRoYW4gdGhlIGN1cnJlbnQgcnVudGltZS4gJyArXG4gICAgICAgICAgICAnUGxlYXNlIHVwZGF0ZSB5b3VyIHJ1bnRpbWUgdG8gYSBuZXdlciB2ZXJzaW9uICgnICsgY29tcGlsZXJJbmZvWzFdICsgJykuJyk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0ZW1wbGF0ZSh0ZW1wbGF0ZVNwZWMsIGVudikge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAoIWVudikge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ05vIGVudmlyb25tZW50IHBhc3NlZCB0byB0ZW1wbGF0ZScpO1xuICB9XG4gIGlmICghdGVtcGxhdGVTcGVjIHx8ICF0ZW1wbGF0ZVNwZWMubWFpbikge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdGVtcGxhdGUgb2JqZWN0OiAnICsgdHlwZW9mIHRlbXBsYXRlU3BlYyk7XG4gIH1cblxuICB0ZW1wbGF0ZVNwZWMubWFpbi5kZWNvcmF0b3IgPSB0ZW1wbGF0ZVNwZWMubWFpbl9kO1xuXG4gIC8vIE5vdGU6IFVzaW5nIGVudi5WTSByZWZlcmVuY2VzIHJhdGhlciB0aGFuIGxvY2FsIHZhciByZWZlcmVuY2VzIHRocm91Z2hvdXQgdGhpcyBzZWN0aW9uIHRvIGFsbG93XG4gIC8vIGZvciBleHRlcm5hbCB1c2VycyB0byBvdmVycmlkZSB0aGVzZSBhcyBwc3VlZG8tc3VwcG9ydGVkIEFQSXMuXG4gIGVudi5WTS5jaGVja1JldmlzaW9uKHRlbXBsYXRlU3BlYy5jb21waWxlcik7XG5cbiAgZnVuY3Rpb24gaW52b2tlUGFydGlhbFdyYXBwZXIocGFydGlhbCwgY29udGV4dCwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmhhc2gpIHtcbiAgICAgIGNvbnRleHQgPSBVdGlscy5leHRlbmQoe30sIGNvbnRleHQsIG9wdGlvbnMuaGFzaCk7XG4gICAgICBpZiAob3B0aW9ucy5pZHMpIHtcbiAgICAgICAgb3B0aW9ucy5pZHNbMF0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHBhcnRpYWwgPSBlbnYuVk0ucmVzb2x2ZVBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKTtcbiAgICBsZXQgcmVzdWx0ID0gZW52LlZNLmludm9rZVBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKTtcblxuICAgIGlmIChyZXN1bHQgPT0gbnVsbCAmJiBlbnYuY29tcGlsZSkge1xuICAgICAgb3B0aW9ucy5wYXJ0aWFsc1tvcHRpb25zLm5hbWVdID0gZW52LmNvbXBpbGUocGFydGlhbCwgdGVtcGxhdGVTcGVjLmNvbXBpbGVyT3B0aW9ucywgZW52KTtcbiAgICAgIHJlc3VsdCA9IG9wdGlvbnMucGFydGlhbHNbb3B0aW9ucy5uYW1lXShjb250ZXh0LCBvcHRpb25zKTtcbiAgICB9XG4gICAgaWYgKHJlc3VsdCAhPSBudWxsKSB7XG4gICAgICBpZiAob3B0aW9ucy5pbmRlbnQpIHtcbiAgICAgICAgbGV0IGxpbmVzID0gcmVzdWx0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBsaW5lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICBpZiAoIWxpbmVzW2ldICYmIGkgKyAxID09PSBsKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsaW5lc1tpXSA9IG9wdGlvbnMuaW5kZW50ICsgbGluZXNbaV07XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0ID0gbGluZXMuam9pbignXFxuJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUaGUgcGFydGlhbCAnICsgb3B0aW9ucy5uYW1lICsgJyBjb3VsZCBub3QgYmUgY29tcGlsZWQgd2hlbiBydW5uaW5nIGluIHJ1bnRpbWUtb25seSBtb2RlJyk7XG4gICAgfVxuICB9XG5cbiAgLy8gSnVzdCBhZGQgd2F0ZXJcbiAgbGV0IGNvbnRhaW5lciA9IHtcbiAgICBzdHJpY3Q6IGZ1bmN0aW9uKG9iaiwgbmFtZSkge1xuICAgICAgaWYgKCEobmFtZSBpbiBvYmopKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1wiJyArIG5hbWUgKyAnXCIgbm90IGRlZmluZWQgaW4gJyArIG9iaik7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqW25hbWVdO1xuICAgIH0sXG4gICAgbG9va3VwOiBmdW5jdGlvbihkZXB0aHMsIG5hbWUpIHtcbiAgICAgIGNvbnN0IGxlbiA9IGRlcHRocy5sZW5ndGg7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmIChkZXB0aHNbaV0gJiYgZGVwdGhzW2ldW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gZGVwdGhzW2ldW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBsYW1iZGE6IGZ1bmN0aW9uKGN1cnJlbnQsIGNvbnRleHQpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgY3VycmVudCA9PT0gJ2Z1bmN0aW9uJyA/IGN1cnJlbnQuY2FsbChjb250ZXh0KSA6IGN1cnJlbnQ7XG4gICAgfSxcblxuICAgIGVzY2FwZUV4cHJlc3Npb246IFV0aWxzLmVzY2FwZUV4cHJlc3Npb24sXG4gICAgaW52b2tlUGFydGlhbDogaW52b2tlUGFydGlhbFdyYXBwZXIsXG5cbiAgICBmbjogZnVuY3Rpb24oaSkge1xuICAgICAgbGV0IHJldCA9IHRlbXBsYXRlU3BlY1tpXTtcbiAgICAgIHJldC5kZWNvcmF0b3IgPSB0ZW1wbGF0ZVNwZWNbaSArICdfZCddO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9LFxuXG4gICAgcHJvZ3JhbXM6IFtdLFxuICAgIHByb2dyYW06IGZ1bmN0aW9uKGksIGRhdGEsIGRlY2xhcmVkQmxvY2tQYXJhbXMsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcbiAgICAgIGxldCBwcm9ncmFtV3JhcHBlciA9IHRoaXMucHJvZ3JhbXNbaV0sXG4gICAgICAgICAgZm4gPSB0aGlzLmZuKGkpO1xuICAgICAgaWYgKGRhdGEgfHwgZGVwdGhzIHx8IGJsb2NrUGFyYW1zIHx8IGRlY2xhcmVkQmxvY2tQYXJhbXMpIHtcbiAgICAgICAgcHJvZ3JhbVdyYXBwZXIgPSB3cmFwUHJvZ3JhbSh0aGlzLCBpLCBmbiwgZGF0YSwgZGVjbGFyZWRCbG9ja1BhcmFtcywgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gICAgICB9IGVsc2UgaWYgKCFwcm9ncmFtV3JhcHBlcikge1xuICAgICAgICBwcm9ncmFtV3JhcHBlciA9IHRoaXMucHJvZ3JhbXNbaV0gPSB3cmFwUHJvZ3JhbSh0aGlzLCBpLCBmbik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvZ3JhbVdyYXBwZXI7XG4gICAgfSxcblxuICAgIGRhdGE6IGZ1bmN0aW9uKHZhbHVlLCBkZXB0aCkge1xuICAgICAgd2hpbGUgKHZhbHVlICYmIGRlcHRoLS0pIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5fcGFyZW50O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sXG4gICAgbWVyZ2U6IGZ1bmN0aW9uKHBhcmFtLCBjb21tb24pIHtcbiAgICAgIGxldCBvYmogPSBwYXJhbSB8fCBjb21tb247XG5cbiAgICAgIGlmIChwYXJhbSAmJiBjb21tb24gJiYgKHBhcmFtICE9PSBjb21tb24pKSB7XG4gICAgICAgIG9iaiA9IFV0aWxzLmV4dGVuZCh7fSwgY29tbW9uLCBwYXJhbSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmo7XG4gICAgfSxcblxuICAgIG5vb3A6IGVudi5WTS5ub29wLFxuICAgIGNvbXBpbGVySW5mbzogdGVtcGxhdGVTcGVjLmNvbXBpbGVyXG4gIH07XG5cbiAgZnVuY3Rpb24gcmV0KGNvbnRleHQsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBkYXRhID0gb3B0aW9ucy5kYXRhO1xuXG4gICAgcmV0Ll9zZXR1cChvcHRpb25zKTtcbiAgICBpZiAoIW9wdGlvbnMucGFydGlhbCAmJiB0ZW1wbGF0ZVNwZWMudXNlRGF0YSkge1xuICAgICAgZGF0YSA9IGluaXREYXRhKGNvbnRleHQsIGRhdGEpO1xuICAgIH1cbiAgICBsZXQgZGVwdGhzLFxuICAgICAgICBibG9ja1BhcmFtcyA9IHRlbXBsYXRlU3BlYy51c2VCbG9ja1BhcmFtcyA/IFtdIDogdW5kZWZpbmVkO1xuICAgIGlmICh0ZW1wbGF0ZVNwZWMudXNlRGVwdGhzKSB7XG4gICAgICBpZiAob3B0aW9ucy5kZXB0aHMpIHtcbiAgICAgICAgZGVwdGhzID0gY29udGV4dCAhPSBvcHRpb25zLmRlcHRoc1swXSA/IFtjb250ZXh0XS5jb25jYXQob3B0aW9ucy5kZXB0aHMpIDogb3B0aW9ucy5kZXB0aHM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZXB0aHMgPSBbY29udGV4dF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFpbihjb250ZXh0LyosIG9wdGlvbnMqLykge1xuICAgICAgcmV0dXJuICcnICsgdGVtcGxhdGVTcGVjLm1haW4oY29udGFpbmVyLCBjb250ZXh0LCBjb250YWluZXIuaGVscGVycywgY29udGFpbmVyLnBhcnRpYWxzLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgICB9XG4gICAgbWFpbiA9IGV4ZWN1dGVEZWNvcmF0b3JzKHRlbXBsYXRlU3BlYy5tYWluLCBtYWluLCBjb250YWluZXIsIG9wdGlvbnMuZGVwdGhzIHx8IFtdLCBkYXRhLCBibG9ja1BhcmFtcyk7XG4gICAgcmV0dXJuIG1haW4oY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cbiAgcmV0LmlzVG9wID0gdHJ1ZTtcblxuICByZXQuX3NldHVwID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucy5wYXJ0aWFsKSB7XG4gICAgICBjb250YWluZXIuaGVscGVycyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLmhlbHBlcnMsIGVudi5oZWxwZXJzKTtcblxuICAgICAgaWYgKHRlbXBsYXRlU3BlYy51c2VQYXJ0aWFsKSB7XG4gICAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLnBhcnRpYWxzLCBlbnYucGFydGlhbHMpO1xuICAgICAgfVxuICAgICAgaWYgKHRlbXBsYXRlU3BlYy51c2VQYXJ0aWFsIHx8IHRlbXBsYXRlU3BlYy51c2VEZWNvcmF0b3JzKSB7XG4gICAgICAgIGNvbnRhaW5lci5kZWNvcmF0b3JzID0gY29udGFpbmVyLm1lcmdlKG9wdGlvbnMuZGVjb3JhdG9ycywgZW52LmRlY29yYXRvcnMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb250YWluZXIuaGVscGVycyA9IG9wdGlvbnMuaGVscGVycztcbiAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IG9wdGlvbnMucGFydGlhbHM7XG4gICAgICBjb250YWluZXIuZGVjb3JhdG9ycyA9IG9wdGlvbnMuZGVjb3JhdG9ycztcbiAgICB9XG4gIH07XG5cbiAgcmV0Ll9jaGlsZCA9IGZ1bmN0aW9uKGksIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZUJsb2NrUGFyYW1zICYmICFibG9ja1BhcmFtcykge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignbXVzdCBwYXNzIGJsb2NrIHBhcmFtcycpO1xuICAgIH1cbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZURlcHRocyAmJiAhZGVwdGhzKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdtdXN0IHBhc3MgcGFyZW50IGRlcHRocycpO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwUHJvZ3JhbShjb250YWluZXIsIGksIHRlbXBsYXRlU3BlY1tpXSwgZGF0YSwgMCwgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gIH07XG4gIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cmFwUHJvZ3JhbShjb250YWluZXIsIGksIGZuLCBkYXRhLCBkZWNsYXJlZEJsb2NrUGFyYW1zLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gIGZ1bmN0aW9uIHByb2coY29udGV4dCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgbGV0IGN1cnJlbnREZXB0aHMgPSBkZXB0aHM7XG4gICAgaWYgKGRlcHRocyAmJiBjb250ZXh0ICE9IGRlcHRoc1swXSkge1xuICAgICAgY3VycmVudERlcHRocyA9IFtjb250ZXh0XS5jb25jYXQoZGVwdGhzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZm4oY29udGFpbmVyLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICBjb250YWluZXIuaGVscGVycywgY29udGFpbmVyLnBhcnRpYWxzLFxuICAgICAgICBvcHRpb25zLmRhdGEgfHwgZGF0YSxcbiAgICAgICAgYmxvY2tQYXJhbXMgJiYgW29wdGlvbnMuYmxvY2tQYXJhbXNdLmNvbmNhdChibG9ja1BhcmFtcyksXG4gICAgICAgIGN1cnJlbnREZXB0aHMpO1xuICB9XG5cbiAgcHJvZyA9IGV4ZWN1dGVEZWNvcmF0b3JzKGZuLCBwcm9nLCBjb250YWluZXIsIGRlcHRocywgZGF0YSwgYmxvY2tQYXJhbXMpO1xuXG4gIHByb2cucHJvZ3JhbSA9IGk7XG4gIHByb2cuZGVwdGggPSBkZXB0aHMgPyBkZXB0aHMubGVuZ3RoIDogMDtcbiAgcHJvZy5ibG9ja1BhcmFtcyA9IGRlY2xhcmVkQmxvY2tQYXJhbXMgfHwgMDtcbiAgcmV0dXJuIHByb2c7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUGFydGlhbChwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKSB7XG4gIGlmICghcGFydGlhbCkge1xuICAgIGlmIChvcHRpb25zLm5hbWUgPT09ICdAcGFydGlhbC1ibG9jaycpIHtcbiAgICAgIGxldCBkYXRhID0gb3B0aW9ucy5kYXRhO1xuICAgICAgd2hpbGUgKGRhdGFbJ3BhcnRpYWwtYmxvY2snXSA9PT0gbm9vcCkge1xuICAgICAgICBkYXRhID0gZGF0YS5fcGFyZW50O1xuICAgICAgfVxuICAgICAgcGFydGlhbCA9IGRhdGFbJ3BhcnRpYWwtYmxvY2snXTtcbiAgICAgIGRhdGFbJ3BhcnRpYWwtYmxvY2snXSA9IG5vb3A7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcnRpYWwgPSBvcHRpb25zLnBhcnRpYWxzW29wdGlvbnMubmFtZV07XG4gICAgfVxuICB9IGVsc2UgaWYgKCFwYXJ0aWFsLmNhbGwgJiYgIW9wdGlvbnMubmFtZSkge1xuICAgIC8vIFRoaXMgaXMgYSBkeW5hbWljIHBhcnRpYWwgdGhhdCByZXR1cm5lZCBhIHN0cmluZ1xuICAgIG9wdGlvbnMubmFtZSA9IHBhcnRpYWw7XG4gICAgcGFydGlhbCA9IG9wdGlvbnMucGFydGlhbHNbcGFydGlhbF07XG4gIH1cbiAgcmV0dXJuIHBhcnRpYWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZva2VQYXJ0aWFsKHBhcnRpYWwsIGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucy5wYXJ0aWFsID0gdHJ1ZTtcbiAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgb3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoID0gb3B0aW9ucy5pZHNbMF0gfHwgb3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoO1xuICB9XG5cbiAgbGV0IHBhcnRpYWxCbG9jaztcbiAgaWYgKG9wdGlvbnMuZm4gJiYgb3B0aW9ucy5mbiAhPT0gbm9vcCkge1xuICAgIG9wdGlvbnMuZGF0YSA9IGNyZWF0ZUZyYW1lKG9wdGlvbnMuZGF0YSk7XG4gICAgcGFydGlhbEJsb2NrID0gb3B0aW9ucy5kYXRhWydwYXJ0aWFsLWJsb2NrJ10gPSBvcHRpb25zLmZuO1xuXG4gICAgaWYgKHBhcnRpYWxCbG9jay5wYXJ0aWFscykge1xuICAgICAgb3B0aW9ucy5wYXJ0aWFscyA9IFV0aWxzLmV4dGVuZCh7fSwgb3B0aW9ucy5wYXJ0aWFscywgcGFydGlhbEJsb2NrLnBhcnRpYWxzKTtcbiAgICB9XG4gIH1cblxuICBpZiAocGFydGlhbCA9PT0gdW5kZWZpbmVkICYmIHBhcnRpYWxCbG9jaykge1xuICAgIHBhcnRpYWwgPSBwYXJ0aWFsQmxvY2s7XG4gIH1cblxuICBpZiAocGFydGlhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVGhlIHBhcnRpYWwgJyArIG9wdGlvbnMubmFtZSArICcgY291bGQgbm90IGJlIGZvdW5kJyk7XG4gIH0gZWxzZSBpZiAocGFydGlhbCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIHBhcnRpYWwoY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5vb3AoKSB7IHJldHVybiAnJzsgfVxuXG5mdW5jdGlvbiBpbml0RGF0YShjb250ZXh0LCBkYXRhKSB7XG4gIGlmICghZGF0YSB8fCAhKCdyb290JyBpbiBkYXRhKSkge1xuICAgIGRhdGEgPSBkYXRhID8gY3JlYXRlRnJhbWUoZGF0YSkgOiB7fTtcbiAgICBkYXRhLnJvb3QgPSBjb250ZXh0O1xuICB9XG4gIHJldHVybiBkYXRhO1xufVxuXG5mdW5jdGlvbiBleGVjdXRlRGVjb3JhdG9ycyhmbiwgcHJvZywgY29udGFpbmVyLCBkZXB0aHMsIGRhdGEsIGJsb2NrUGFyYW1zKSB7XG4gIGlmIChmbi5kZWNvcmF0b3IpIHtcbiAgICBsZXQgcHJvcHMgPSB7fTtcbiAgICBwcm9nID0gZm4uZGVjb3JhdG9yKHByb2csIHByb3BzLCBjb250YWluZXIsIGRlcHRocyAmJiBkZXB0aHNbMF0sIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpO1xuICAgIFV0aWxzLmV4dGVuZChwcm9nLCBwcm9wcyk7XG4gIH1cbiAgcmV0dXJuIHByb2c7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/safe-string.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/safe-string.js new file mode 100644 index 0000000..1118c12 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/safe-string.js @@ -0,0 +1,15 @@ +define(['exports', 'module'], function (exports, module) { + // Build out our basic SafeString type + 'use strict'; + + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = SafeString.prototype.toHTML = function () { + return '' + this.string; + }; + + module.exports = SafeString; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3NhZmUtc3RyaW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFDQSxXQUFTLFVBQVUsQ0FBQyxNQUFNLEVBQUU7QUFDMUIsUUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7R0FDdEI7O0FBRUQsWUFBVSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsWUFBVztBQUN2RSxXQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0dBQ3pCLENBQUM7O21CQUVhLFVBQVUiLCJmaWxlIjoic2FmZS1zdHJpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBCdWlsZCBvdXQgb3VyIGJhc2ljIFNhZmVTdHJpbmcgdHlwZVxuZnVuY3Rpb24gU2FmZVN0cmluZyhzdHJpbmcpIHtcbiAgdGhpcy5zdHJpbmcgPSBzdHJpbmc7XG59XG5cblNhZmVTdHJpbmcucHJvdG90eXBlLnRvU3RyaW5nID0gU2FmZVN0cmluZy5wcm90b3R5cGUudG9IVE1MID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAnJyArIHRoaXMuc3RyaW5nO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgU2FmZVN0cmluZztcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/utils.js b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/utils.js new file mode 100644 index 0000000..a6d5692 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/handlebars/utils.js @@ -0,0 +1,126 @@ +define(['exports'], function (exports) { + 'use strict'; + + exports.__esModule = true; + exports.extend = extend; + exports.indexOf = indexOf; + exports.escapeExpression = escapeExpression; + exports.isEmpty = isEmpty; + exports.createFrame = createFrame; + exports.blockParams = blockParams; + exports.appendContextPath = appendContextPath; + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' + }; + + var badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + + function escapeChar(chr) { + return escape[chr]; + } + + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; + } + + var toString = Object.prototype.toString; + + exports.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + /* eslint-disable func-style */ + var isFunction = function isFunction(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + exports.isFunction = isFunction = function (value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + exports.isFunction = isFunction; + + /* eslint-enable func-style */ + + /* istanbul ignore next */ + var isArray = Array.isArray || function (value) { + return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; + }; + + exports.isArray = isArray; + // Older IE versions do not directly support indexOf so we must implement our own, sadly. + + function indexOf(array, value) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; + } + + function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); + } + + function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + function createFrame(object) { + var frame = extend({}, object); + frame._parent = object; + return frame; + } + + function blockParams(params, ids) { + params.path = ids; + return params; + } + + function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3V0aWxzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQUEsTUFBTSxNQUFNLEdBQUc7QUFDYixPQUFHLEVBQUUsT0FBTztBQUNaLE9BQUcsRUFBRSxNQUFNO0FBQ1gsT0FBRyxFQUFFLE1BQU07QUFDWCxPQUFHLEVBQUUsUUFBUTtBQUNiLE9BQUcsRUFBRSxRQUFRO0FBQ2IsT0FBRyxFQUFFLFFBQVE7QUFDYixPQUFHLEVBQUUsUUFBUTtHQUNkLENBQUM7O0FBRUYsTUFBTSxRQUFRLEdBQUcsWUFBWTtNQUN2QixRQUFRLEdBQUcsV0FBVyxDQUFDOztBQUU3QixXQUFTLFVBQVUsQ0FBQyxHQUFHLEVBQUU7QUFDdkIsV0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7R0FDcEI7O0FBRU0sV0FBUyxNQUFNLENBQUMsR0FBRyxvQkFBbUI7QUFDM0MsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDekMsV0FBSyxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7QUFDNUIsWUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFO0FBQzNELGFBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDOUI7T0FDRjtLQUNGOztBQUVELFdBQU8sR0FBRyxDQUFDO0dBQ1o7O0FBRU0sTUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7Ozs7OztBQUtoRCxNQUFJLFVBQVUsR0FBRyxvQkFBUyxLQUFLLEVBQUU7QUFDL0IsV0FBTyxPQUFPLEtBQUssS0FBSyxVQUFVLENBQUM7R0FDcEMsQ0FBQzs7O0FBR0YsTUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7QUFDbkIsWUFJTSxVQUFVLEdBSmhCLFVBQVUsR0FBRyxVQUFTLEtBQUssRUFBRTtBQUMzQixhQUFPLE9BQU8sS0FBSyxLQUFLLFVBQVUsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLG1CQUFtQixDQUFDO0tBQ3BGLENBQUM7R0FDSDtVQUNPLFVBQVUsR0FBVixVQUFVOzs7OztBQUlYLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLElBQUksVUFBUyxLQUFLLEVBQUU7QUFDdEQsV0FBTyxBQUFDLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEdBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7R0FDakcsQ0FBQzs7Ozs7QUFHSyxXQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQ3BDLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDaEQsVUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxFQUFFO0FBQ3RCLGVBQU8sQ0FBQyxDQUFDO09BQ1Y7S0FDRjtBQUNELFdBQU8sQ0FBQyxDQUFDLENBQUM7R0FDWDs7QUFHTSxXQUFTLGdCQUFnQixDQUFDLE1BQU0sRUFBRTtBQUN2QyxRQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsRUFBRTs7QUFFOUIsVUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtBQUMzQixlQUFPLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztPQUN4QixNQUFNLElBQUksTUFBTSxJQUFJLElBQUksRUFBRTtBQUN6QixlQUFPLEVBQUUsQ0FBQztPQUNYLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRTtBQUNsQixlQUFPLE1BQU0sR0FBRyxFQUFFLENBQUM7T0FDcEI7Ozs7O0FBS0QsWUFBTSxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUM7S0FDdEI7O0FBRUQsUUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7QUFBRSxhQUFPLE1BQU0sQ0FBQztLQUFFO0FBQzlDLFdBQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7R0FDN0M7O0FBRU0sV0FBUyxPQUFPLENBQUMsS0FBSyxFQUFFO0FBQzdCLFFBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxLQUFLLENBQUMsRUFBRTtBQUN6QixhQUFPLElBQUksQ0FBQztLQUNiLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7QUFDL0MsYUFBTyxJQUFJLENBQUM7S0FDYixNQUFNO0FBQ0wsYUFBTyxLQUFLLENBQUM7S0FDZDtHQUNGOztBQUVNLFdBQVMsV0FBVyxDQUFDLE1BQU0sRUFBRTtBQUNsQyxRQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQy9CLFNBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO0FBQ3ZCLFdBQU8sS0FBSyxDQUFDO0dBQ2Q7O0FBRU0sV0FBUyxXQUFXLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtBQUN2QyxVQUFNLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztBQUNsQixXQUFPLE1BQU0sQ0FBQztHQUNmOztBQUVNLFdBQVMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEVBQUUsRUFBRTtBQUNqRCxXQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFBLEdBQUksRUFBRSxDQUFDO0dBQ3BEIiwiZmlsZSI6InV0aWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgZXNjYXBlID0ge1xuICAnJic6ICcmYW1wOycsXG4gICc8JzogJyZsdDsnLFxuICAnPic6ICcmZ3Q7JyxcbiAgJ1wiJzogJyZxdW90OycsXG4gIFwiJ1wiOiAnJiN4Mjc7JyxcbiAgJ2AnOiAnJiN4NjA7JyxcbiAgJz0nOiAnJiN4M0Q7J1xufTtcblxuY29uc3QgYmFkQ2hhcnMgPSAvWyY8PlwiJ2A9XS9nLFxuICAgICAgcG9zc2libGUgPSAvWyY8PlwiJ2A9XS87XG5cbmZ1bmN0aW9uIGVzY2FwZUNoYXIoY2hyKSB7XG4gIHJldHVybiBlc2NhcGVbY2hyXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZChvYmovKiAsIC4uLnNvdXJjZSAqLykge1xuICBmb3IgKGxldCBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIGZvciAobGV0IGtleSBpbiBhcmd1bWVudHNbaV0pIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYXJndW1lbnRzW2ldLCBrZXkpKSB7XG4gICAgICAgIG9ialtrZXldID0gYXJndW1lbnRzW2ldW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZXhwb3J0IGxldCB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8vIFNvdXJjZWQgZnJvbSBsb2Rhc2hcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iZXN0aWVqcy9sb2Rhc2gvYmxvYi9tYXN0ZXIvTElDRU5TRS50eHRcbi8qIGVzbGludC1kaXNhYmxlIGZ1bmMtc3R5bGUgKi9cbmxldCBpc0Z1bmN0aW9uID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcbn07XG4vLyBmYWxsYmFjayBmb3Igb2xkZXIgdmVyc2lvbnMgb2YgQ2hyb21lIGFuZCBTYWZhcmlcbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5pZiAoaXNGdW5jdGlvbigveC8pKSB7XG4gIGlzRnVuY3Rpb24gPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicgJiYgdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG4gIH07XG59XG5leHBvcnQge2lzRnVuY3Rpb259O1xuLyogZXNsaW50LWVuYWJsZSBmdW5jLXN0eWxlICovXG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5leHBvcnQgY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSA/IHRvU3RyaW5nLmNhbGwodmFsdWUpID09PSAnW29iamVjdCBBcnJheV0nIDogZmFsc2U7XG59O1xuXG4vLyBPbGRlciBJRSB2ZXJzaW9ucyBkbyBub3QgZGlyZWN0bHkgc3VwcG9ydCBpbmRleE9mIHNvIHdlIG11c3QgaW1wbGVtZW50IG91ciBvd24sIHNhZGx5LlxuZXhwb3J0IGZ1bmN0aW9uIGluZGV4T2YoYXJyYXksIHZhbHVlKSB7XG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBhcnJheS5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGlmIChhcnJheVtpXSA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gLTE7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZUV4cHJlc3Npb24oc3RyaW5nKSB7XG4gIGlmICh0eXBlb2Ygc3RyaW5nICE9PSAnc3RyaW5nJykge1xuICAgIC8vIGRvbid0IGVzY2FwZSBTYWZlU3RyaW5ncywgc2luY2UgdGhleSdyZSBhbHJlYWR5IHNhZmVcbiAgICBpZiAoc3RyaW5nICYmIHN0cmluZy50b0hUTUwpIHtcbiAgICAgIHJldHVybiBzdHJpbmcudG9IVE1MKCk7XG4gICAgfSBlbHNlIGlmIChzdHJpbmcgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSBpZiAoIXN0cmluZykge1xuICAgICAgcmV0dXJuIHN0cmluZyArICcnO1xuICAgIH1cblxuICAgIC8vIEZvcmNlIGEgc3RyaW5nIGNvbnZlcnNpb24gYXMgdGhpcyB3aWxsIGJlIGRvbmUgYnkgdGhlIGFwcGVuZCByZWdhcmRsZXNzIGFuZFxuICAgIC8vIHRoZSByZWdleCB0ZXN0IHdpbGwgZG8gdGhpcyB0cmFuc3BhcmVudGx5IGJlaGluZCB0aGUgc2NlbmVzLCBjYXVzaW5nIGlzc3VlcyBpZlxuICAgIC8vIGFuIG9iamVjdCdzIHRvIHN0cmluZyBoYXMgZXNjYXBlZCBjaGFyYWN0ZXJzIGluIGl0LlxuICAgIHN0cmluZyA9ICcnICsgc3RyaW5nO1xuICB9XG5cbiAgaWYgKCFwb3NzaWJsZS50ZXN0KHN0cmluZykpIHsgcmV0dXJuIHN0cmluZzsgfVxuICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoYmFkQ2hhcnMsIGVzY2FwZUNoYXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSkge1xuICBpZiAoIXZhbHVlICYmIHZhbHVlICE9PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAoaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVGcmFtZShvYmplY3QpIHtcbiAgbGV0IGZyYW1lID0gZXh0ZW5kKHt9LCBvYmplY3QpO1xuICBmcmFtZS5fcGFyZW50ID0gb2JqZWN0O1xuICByZXR1cm4gZnJhbWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBibG9ja1BhcmFtcyhwYXJhbXMsIGlkcykge1xuICBwYXJhbXMucGF0aCA9IGlkcztcbiAgcmV0dXJuIHBhcmFtcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZENvbnRleHRQYXRoKGNvbnRleHRQYXRoLCBpZCkge1xuICByZXR1cm4gKGNvbnRleHRQYXRoID8gY29udGV4dFBhdGggKyAnLicgOiAnJykgKyBpZDtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/amd/precompiler.js b/hm_sunwell/node_modules/handlebars/dist/amd/precompiler.js new file mode 100644 index 0000000..70a80f9 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/amd/precompiler.js @@ -0,0 +1,292 @@ +define(['exports', 'async', 'fs', './handlebars', 'path', 'source-map', 'uglify-js'], function (exports, _async, _fs, _handlebars, _path, _sourceMap, _uglifyJs) { + /* eslint-disable no-console */ + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Async = _interopRequireDefault(_async); + + var _fs2 = _interopRequireDefault(_fs); + + var _uglify = _interopRequireDefault(_uglifyJs); + + module.exports.loadTemplates = function (opts, callback) { + loadStrings(opts, function (err, strings) { + if (err) { + callback(err); + } else { + loadFiles(opts, function (err, files) { + if (err) { + callback(err); + } else { + opts.templates = strings.concat(files); + callback(undefined, opts); + } + }); + } + }); + }; + + function loadStrings(opts, callback) { + var strings = arrayCast(opts.string), + names = arrayCast(opts.name); + + if (names.length !== strings.length && strings.length > 1) { + return callback(new _handlebars.Exception('Number of names did not match the number of string inputs')); + } + + _Async['default'].map(strings, function (string, callback) { + if (string !== '-') { + callback(undefined, string); + } else { + (function () { + // Load from stdin + var buffer = ''; + process.stdin.setEncoding('utf8'); + + process.stdin.on('data', function (chunk) { + buffer += chunk; + }); + process.stdin.on('end', function () { + callback(undefined, buffer); + }); + })(); + } + }, function (err, strings) { + strings = strings.map(function (string, index) { + return { + name: names[index], + path: names[index], + source: string + }; + }); + callback(err, strings); + }); + } + + function loadFiles(opts, callback) { + // Build file extension pattern + var extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function (arg) { + return '\\' + arg; + }); + extension = new RegExp('\\.' + extension + '$'); + + var ret = [], + queue = (opts.files || []).map(function (template) { + return { template: template, root: opts.root }; + }); + _Async['default'].whilst(function () { + return queue.length; + }, function (callback) { + var _queue$shift = queue.shift(); + + var path = _queue$shift.template; + var root = _queue$shift.root; + + _fs2['default'].stat(path, function (err, stat) { + if (err) { + return callback(new _handlebars.Exception('Unable to open template file "' + path + '"')); + } + + if (stat.isDirectory()) { + opts.hasDirectory = true; + + _fs2['default'].readdir(path, function (err, children) { + /* istanbul ignore next : Race condition that being too lazy to test */ + if (err) { + return callback(err); + } + children.forEach(function (file) { + var childPath = path + '/' + file; + + if (extension.test(childPath) || _fs2['default'].statSync(childPath).isDirectory()) { + queue.push({ template: childPath, root: root || path }); + } + }); + + callback(); + }); + } else { + _fs2['default'].readFile(path, 'utf8', function (err, data) { + /* istanbul ignore next : Race condition that being too lazy to test */ + if (err) { + return callback(err); + } + + if (opts.bom && data.indexOf('') === 0) { + data = data.substring(1); + } + + // Clean the template name + var name = path; + if (!root) { + name = _path.basename(name); + } else if (name.indexOf(root) === 0) { + name = name.substring(root.length + 1); + } + name = name.replace(extension, ''); + + ret.push({ + path: path, + name: name, + source: data + }); + + callback(); + }); + } + }); + }, function (err) { + if (err) { + callback(err); + } else { + callback(undefined, ret); + } + }); + } + + module.exports.cli = function (opts) { + if (opts.version) { + console.log(_handlebars.VERSION); + return; + } + + if (!opts.templates.length && !opts.hasDirectory) { + throw new _handlebars.Exception('Must define at least one template or directory.'); + } + + if (opts.simple && opts.min) { + throw new _handlebars.Exception('Unable to minimize simple output'); + } + + var multiple = opts.templates.length !== 1 || opts.hasDirectory; + if (opts.simple && multiple) { + throw new _handlebars.Exception('Unable to output multiple templates in simple mode'); + } + + // Force simple mode if we have only one template and it's unnamed. + if (!opts.amd && !opts.commonjs && opts.templates.length === 1 && !opts.templates[0].name) { + opts.simple = true; + } + + // Convert the known list into a hash + var known = {}; + if (opts.known && !Array.isArray(opts.known)) { + opts.known = [opts.known]; + } + if (opts.known) { + for (var i = 0, len = opts.known.length; i < len; i++) { + known[opts.known[i]] = true; + } + } + + var objectName = opts.partial ? 'Handlebars.partials' : 'templates'; + + var output = new _sourceMap.SourceNode(); + if (!opts.simple) { + if (opts.amd) { + output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];'); + } else if (opts.commonjs) { + output.add('var Handlebars = require("' + opts.commonjs + '");'); + } else { + output.add('(function() {\n'); + } + output.add(' var template = Handlebars.template, templates = '); + if (opts.namespace) { + output.add(opts.namespace); + output.add(' = '); + output.add(opts.namespace); + output.add(' || '); + } + output.add('{};\n'); + } + + opts.templates.forEach(function (template) { + var options = { + knownHelpers: known, + knownHelpersOnly: opts.o + }; + + if (opts.map) { + options.srcName = template.path; + } + if (opts.data) { + options.data = true; + } + + var precompiled = _handlebars.precompile(template.source, options); + + // If we are generating a source map, we have to reconstruct the SourceNode object + if (opts.map) { + var consumer = new _sourceMap.SourceMapConsumer(precompiled.map); + precompiled = _sourceMap.SourceNode.fromStringWithSourceMap(precompiled.code, consumer); + } + + if (opts.simple) { + output.add([precompiled, '\n']); + } else { + if (!template.name) { + throw new _handlebars.Exception('Name missing for template'); + } + + if (opts.amd && !multiple) { + output.add('return '); + } + output.add([objectName, '[\'', template.name, '\'] = template(', precompiled, ');\n']); + } + }); + + // Output the content + if (!opts.simple) { + if (opts.amd) { + if (multiple) { + output.add(['return ', objectName, ';\n']); + } + output.add('});'); + } else if (!opts.commonjs) { + output.add('})();'); + } + } + + if (opts.map) { + output.add('\n//# sourceMappingURL=' + opts.map + '\n'); + } + + output = output.toStringWithSourceMap(); + output.map = output.map + ''; + + if (opts.min) { + output = _uglify['default'].minify(output.code, { + fromString: true, + + outSourceMap: opts.map, + inSourceMap: JSON.parse(output.map) + }); + if (opts.map) { + output.code += '\n//# sourceMappingURL=' + opts.map + '\n'; + } + } + + if (opts.map) { + _fs2['default'].writeFileSync(opts.map, output.map, 'utf8'); + } + output = output.code; + + if (opts.output) { + _fs2['default'].writeFileSync(opts.output, output, 'utf8'); + } else { + console.log(output); + } + }; + + function arrayCast(value) { + value = value != null ? value : []; + if (!Array.isArray(value)) { + value = [value]; + } + return value; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9wcmVjb21waWxlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQVFBLFFBQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxHQUFHLFVBQVMsSUFBSSxFQUFFLFFBQVEsRUFBRTtBQUN0RCxlQUFXLENBQUMsSUFBSSxFQUFFLFVBQVMsR0FBRyxFQUFFLE9BQU8sRUFBRTtBQUN2QyxVQUFJLEdBQUcsRUFBRTtBQUNQLGdCQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7T0FDZixNQUFNO0FBQ0wsaUJBQVMsQ0FBQyxJQUFJLEVBQUUsVUFBUyxHQUFHLEVBQUUsS0FBSyxFQUFFO0FBQ25DLGNBQUksR0FBRyxFQUFFO0FBQ1Asb0JBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztXQUNmLE1BQU07QUFDTCxnQkFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3ZDLG9CQUFRLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO1dBQzNCO1NBQ0YsQ0FBQyxDQUFDO09BQ0o7S0FDRixDQUFDLENBQUM7R0FDSixDQUFDOztBQUVGLFdBQVMsV0FBVyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUU7QUFDbkMsUUFBSSxPQUFPLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDaEMsS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7O0FBRWpDLFFBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxJQUM1QixPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtBQUN6QixhQUFPLFFBQVEsQ0FBQyxJQUFJLFlBQVcsU0FBUyxDQUFDLDJEQUEyRCxDQUFDLENBQUMsQ0FBQztLQUN4Rzs7QUFFRCxzQkFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLFVBQVMsTUFBTSxFQUFFLFFBQVEsRUFBRTtBQUMxQyxVQUFJLE1BQU0sS0FB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LEdBQUcsQ0FBQztPQUNwQyxDQUFDLENBQUM7QUFDSCxVQUFJLElBQUksQ0FBQyxHQUFHLEVBQUU7QUFDWixjQUFNLENBQUMsSUFBSSxJQUFJLHlCQUF5QixHQUFHLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDO09BQzVEO0tBQ0Y7O0FBRUQsUUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO0FBQ1osc0JBQUcsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztLQUNoRDtBQUNELFVBQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDOztBQUVyQixRQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7QUFDZixzQkFBRyxhQUFhLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7S0FDL0MsTUFBTTtBQUNMLGFBQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7S0FDckI7R0FDRixDQUFDOztBQUVGLFdBQVMsU0FBUyxDQUFDLEtBQUssRUFBRTtBQUN4QixTQUFLLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLEdBQUcsRUFBRSxDQUFDO0FBQ25DLFFBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO0FBQ3pCLFdBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQ2pCO0FBQ0QsV0FBTyxLQUFLLENBQUM7R0FDZCIsImZpbGUiOiJwcmVjb21waWxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbmltcG9ydCBBc3luYyBmcm9tICdhc3luYyc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgSGFuZGxlYmFycyBmcm9tICcuL2hhbmRsZWJhcnMnO1xuaW1wb3J0IHtiYXNlbmFtZX0gZnJvbSAncGF0aCc7XG5pbXBvcnQge1NvdXJjZU1hcENvbnN1bWVyLCBTb3VyY2VOb2RlfSBmcm9tICdzb3VyY2UtbWFwJztcbmltcG9ydCB1Z2xpZnkgZnJvbSAndWdsaWZ5LWpzJztcblxubW9kdWxlLmV4cG9ydHMubG9hZFRlbXBsYXRlcyA9IGZ1bmN0aW9uKG9wdHMsIGNhbGxiYWNrKSB7XG4gIGxvYWRTdHJpbmdzKG9wdHMsIGZ1bmN0aW9uKGVyciwgc3RyaW5ncykge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvYWRGaWxlcyhvcHRzLCBmdW5jdGlvbihlcnIsIGZpbGVzKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9wdHMudGVtcGxhdGVzID0gc3RyaW5ncy5jb25jYXQoZmlsZXMpO1xuICAgICAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCwgb3B0cyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkU3RyaW5ncyhvcHRzLCBjYWxsYmFjaykge1xuICBsZXQgc3RyaW5ncyA9IGFycmF5Q2FzdChvcHRzLnN0cmluZyksXG4gICAgICBuYW1lcyA9IGFycmF5Q2FzdChvcHRzLm5hbWUpO1xuXG4gIGlmIChuYW1lcy5sZW5ndGggIT09IHN0cmluZ3MubGVuZ3RoXG4gICAgICAmJiBzdHJpbmdzLmxlbmd0aCA+IDEpIHtcbiAgICByZXR1cm4gY2FsbGJhY2sobmV3IEhhbmRsZWJhcnMuRXhjZXB0aW9uKCdOdW1iZXIgb2YgbmFtZXMgZGlkIG5vdCBtYXRjaCB0aGUgbnVtYmVyIG9mIHN0cmluZyBpbnB1dHMnKSk7XG4gIH1cblxuICBBc3luYy5tYXAoc3RyaW5ncywgZnVuY3Rpb24oc3RyaW5nLCBjYWxsYmFjaykge1xuICAgICAgaWYgKHN0cmluZyAhPT0gJy0nKSB7XG4gICAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCwgc3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIExvYWQgZnJvbSBzdGRpblxuICAgICAgICBsZXQgYnVmZmVyID0gJyc7XG4gICAgICAgIHByb2Nlc3Muc3RkaW4uc2V0RW5jb2RpbmcoJ3V0ZjgnKTtcblxuICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgICBidWZmZXIgKz0gY2h1bms7XG4gICAgICAgIH0pO1xuICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBjYWxsYmFjayh1bmRlZmluZWQsIGJ1ZmZlcik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sXG4gICAgZnVuY3Rpb24oZXJyLCBzdHJpbmdzKSB7XG4gICAgICBzdHJpbmdzID0gc3RyaW5ncy5tYXAoKHN0cmluZywgaW5kZXgpID0+ICh7XG4gICAgICAgIG5hbWU6IG5hbWVzW2luZGV4XSxcbiAgICAgICAgcGF0aDogbmFtZXNbaW5kZXhdLFxuICAgICAgICBzb3VyY2U6IHN0cmluZ1xuICAgICAgfSkpO1xuICAgICAgY2FsbGJhY2soZXJyLCBzdHJpbmdzKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gbG9hZEZpbGVzKG9wdHMsIGNhbGxiYWNrKSB7XG4gIC8vIEJ1aWxkIGZpbGUgZXh0ZW5zaW9uIHBhdHRlcm5cbiAgbGV0IGV4dGVuc2lvbiA9IChvcHRzLmV4dGVuc2lvbiB8fCAnaGFuZGxlYmFycycpLnJlcGxhY2UoL1tcXFxcXiQqKz8uKCk6PSF8e31cXC1cXFtcXF1dL2csIGZ1bmN0aW9uKGFyZykgeyByZXR1cm4gJ1xcXFwnICsgYXJnOyB9KTtcbiAgZXh0ZW5zaW9uID0gbmV3IFJlZ0V4cCgnXFxcXC4nICsgZXh0ZW5zaW9uICsgJyQnKTtcblxuICBsZXQgcmV0ID0gW10sXG4gICAgICBxdWV1ZSA9IChvcHRzLmZpbGVzIHx8IFtdKS5tYXAoKHRlbXBsYXRlKSA9PiAoe3RlbXBsYXRlLCByb290OiBvcHRzLnJvb3R9KSk7XG4gIEFzeW5jLndoaWxzdCgoKSA9PiBxdWV1ZS5sZW5ndGgsIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgbGV0IHt0ZW1wbGF0ZTogcGF0aCwgcm9vdH0gPSBxdWV1ZS5zaGlmdCgpO1xuXG4gICAgZnMuc3RhdChwYXRoLCBmdW5jdGlvbihlcnIsIHN0YXQpIHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBIYW5kbGViYXJzLkV4Y2VwdGlvbihgVW5hYmxlIHRvIG9wZW4gdGVtcGxhdGUgZmlsZSBcIiR7cGF0aH1cImApKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBvcHRzLmhhc0RpcmVjdG9yeSA9IHRydWU7XG5cbiAgICAgICAgZnMucmVhZGRpcihwYXRoLCBmdW5jdGlvbihlcnIsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgOiBSYWNlIGNvbmRpdGlvbiB0aGF0IGJlaW5nIHRvbyBsYXp5IHRvIHRlc3QgKi9cbiAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbihmaWxlKSB7XG4gICAgICAgICAgICBsZXQgY2hpbGRQYXRoID0gcGF0aCArICcvJyArIGZpbGU7XG5cbiAgICAgICAgICAgIGlmIChleHRlbnNpb24udGVzdChjaGlsZFBhdGgpIHx8IGZzLnN0YXRTeW5jKGNoaWxkUGF0aCkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgICBxdWV1ZS5wdXNoKHt0ZW1wbGF0ZTogY2hpbGRQYXRoLCByb290OiByb290IHx8IHBhdGh9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZnMucmVhZEZpbGUocGF0aCwgJ3V0ZjgnLCBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCA6IFJhY2UgY29uZGl0aW9uIHRoYXQgYmVpbmcgdG9vIGxhenkgdG8gdGVzdCAqL1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChvcHRzLmJvbSAmJiBkYXRhLmluZGV4T2YoJ1xcdUZFRkYnKSA9PT0gMCkge1xuICAgICAgICAgICAgZGF0YSA9IGRhdGEuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIENsZWFuIHRoZSB0ZW1wbGF0ZSBuYW1lXG4gICAgICAgICAgbGV0IG5hbWUgPSBwYXRoO1xuICAgICAgICAgIGlmICghcm9vdCkge1xuICAgICAgICAgICAgbmFtZSA9IGJhc2VuYW1lKG5hbWUpO1xuICAgICAgICAgIH0gZWxzZSBpZiAobmFtZS5pbmRleE9mKHJvb3QpID09PSAwKSB7XG4gICAgICAgICAgICBuYW1lID0gbmFtZS5zdWJzdHJpbmcocm9vdC5sZW5ndGggKyAxKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZShleHRlbnNpb24sICcnKTtcblxuICAgICAgICAgIHJldC5wdXNoKHtcbiAgICAgICAgICAgIHBhdGg6IHBhdGgsXG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgc291cmNlOiBkYXRhXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSxcbiAgZnVuY3Rpb24oZXJyKSB7XG4gICAgaWYgKGVycikge1xuICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FsbGJhY2sodW5kZWZpbmVkLCByZXQpO1xuICAgIH1cbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzLmNsaSA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgaWYgKG9wdHMudmVyc2lvbikge1xuICAgIGNvbnNvbGUubG9nKEhhbmRsZWJhcnMuVkVSU0lPTik7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFvcHRzLnRlbXBsYXRlcy5sZW5ndGggJiYgIW9wdHMuaGFzRGlyZWN0b3J5KSB7XG4gICAgdGhyb3cgbmV3IEhhbmRsZWJhcnMuRXhjZXB0aW9uKCdNdXN0IGRlZmluZSBhdCBsZWFzdCBvbmUgdGVtcGxhdGUgb3IgZGlyZWN0b3J5LicpO1xuICB9XG5cbiAgaWYgKG9wdHMuc2ltcGxlICYmIG9wdHMubWluKSB7XG4gICAgdGhyb3cgbmV3IEhhbmRsZWJhcnMuRXhjZXB0aW9uKCdVbmFibGUgdG8gbWluaW1pemUgc2ltcGxlIG91dHB1dCcpO1xuICB9XG5cbiAgY29uc3QgbXVsdGlwbGUgPSBvcHRzLnRlbXBsYXRlcy5sZW5ndGggIT09IDEgfHwgb3B0cy5oYXNEaXJlY3Rvcnk7XG4gIGlmIChvcHRzLnNpbXBsZSAmJiBtdWx0aXBsZSkge1xuICAgIHRocm93IG5ldyBIYW5kbGViYXJzLkV4Y2VwdGlvbignVW5hYmxlIHRvIG91dHB1dCBtdWx0aXBsZSB0ZW1wbGF0ZXMgaW4gc2ltcGxlIG1vZGUnKTtcbiAgfVxuXG4gIC8vIEZvcmNlIHNpbXBsZSBtb2RlIGlmIHdlIGhhdmUgb25seSBvbmUgdGVtcGxhdGUgYW5kIGl0J3MgdW5uYW1lZC5cbiAgaWYgKCFvcHRzLmFtZCAmJiAhb3B0cy5jb21tb25qcyAmJiBvcHRzLnRlbXBsYXRlcy5sZW5ndGggPT09IDFcbiAgICAgICYmICFvcHRzLnRlbXBsYXRlc1swXS5uYW1lKSB7XG4gICAgb3B0cy5zaW1wbGUgPSB0cnVlO1xuICB9XG5cbiAgLy8gQ29udmVydCB0aGUga25vd24gbGlzdCBpbnRvIGEgaGFzaFxuICBsZXQga25vd24gPSB7fTtcbiAgaWYgKG9wdHMua25vd24gJiYgIUFycmF5LmlzQXJyYXkob3B0cy5rbm93bikpIHtcbiAgICBvcHRzLmtub3duID0gW29wdHMua25vd25dO1xuICB9XG4gIGlmIChvcHRzLmtub3duKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IG9wdHMua25vd24ubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGtub3duW29wdHMua25vd25baV1dID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBvYmplY3ROYW1lID0gb3B0cy5wYXJ0aWFsID8gJ0hhbmRsZWJhcnMucGFydGlhbHMnIDogJ3RlbXBsYXRlcyc7XG5cbiAgbGV0IG91dHB1dCA9IG5ldyBTb3VyY2VOb2RlKCk7XG4gIGlmICghb3B0cy5zaW1wbGUpIHtcbiAgICBpZiAob3B0cy5hbWQpIHtcbiAgICAgIG91dHB1dC5hZGQoJ2RlZmluZShbXFwnJyArIG9wdHMuaGFuZGxlYmFyUGF0aCArICdoYW5kbGViYXJzLnJ1bnRpbWVcXCddLCBmdW5jdGlvbihIYW5kbGViYXJzKSB7XFxuICBIYW5kbGViYXJzID0gSGFuZGxlYmFyc1tcImRlZmF1bHRcIl07Jyk7XG4gICAgfSBlbHNlIGlmIChvcHRzLmNvbW1vbmpzKSB7XG4gICAgICBvdXRwdXQuYWRkKCd2YXIgSGFuZGxlYmFycyA9IHJlcXVpcmUoXCInICsgb3B0cy5jb21tb25qcyArICdcIik7Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5hZGQoJyhmdW5jdGlvbigpIHtcXG4nKTtcbiAgICB9XG4gICAgb3V0cHV0LmFkZCgnICB2YXIgdGVtcGxhdGUgPSBIYW5kbGViYXJzLnRlbXBsYXRlLCB0ZW1wbGF0ZXMgPSAnKTtcbiAgICBpZiAob3B0cy5uYW1lc3BhY2UpIHtcbiAgICAgIG91dHB1dC5hZGQob3B0cy5uYW1lc3BhY2UpO1xuICAgICAgb3V0cHV0LmFkZCgnID0gJyk7XG4gICAgICBvdXRwdXQuYWRkKG9wdHMubmFtZXNwYWNlKTtcbiAgICAgIG91dHB1dC5hZGQoJyB8fCAnKTtcbiAgICB9XG4gICAgb3V0cHV0LmFkZCgne307XFxuJyk7XG4gIH1cblxuICBvcHRzLnRlbXBsYXRlcy5mb3JFYWNoKGZ1bmN0aW9uKHRlbXBsYXRlKSB7XG4gICAgbGV0IG9wdGlvbnMgPSB7XG4gICAgICBrbm93bkhlbHBlcnM6IGtub3duLFxuICAgICAga25vd25IZWxwZXJzT25seTogb3B0cy5vXG4gICAgfTtcblxuICAgIGlmIChvcHRzLm1hcCkge1xuICAgICAgb3B0aW9ucy5zcmNOYW1lID0gdGVtcGxhdGUucGF0aDtcbiAgICB9XG4gICAgaWYgKG9wdHMuZGF0YSkge1xuICAgICAgb3B0aW9ucy5kYXRhID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBsZXQgcHJlY29tcGlsZWQgPSBIYW5kbGViYXJzLnByZWNvbXBpbGUodGVtcGxhdGUuc291cmNlLCBvcHRpb25zKTtcblxuICAgIC8vIElmIHdlIGFyZSBnZW5lcmF0aW5nIGEgc291cmNlIG1hcCwgd2UgaGF2ZSB0byByZWNvbnN0cnVjdCB0aGUgU291cmNlTm9kZSBvYmplY3RcbiAgICBpZiAob3B0cy5tYXApIHtcbiAgICAgIGxldCBjb25zdW1lciA9IG5ldyBTb3VyY2VNYXBDb25zdW1lcihwcmVjb21waWxlZC5tYXApO1xuICAgICAgcHJlY29tcGlsZWQgPSBTb3VyY2VOb2RlLmZyb21TdHJpbmdXaXRoU291cmNlTWFwKHByZWNvbXBpbGVkLmNvZGUsIGNvbnN1bWVyKTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5zaW1wbGUpIHtcbiAgICAgIG91dHB1dC5hZGQoW3ByZWNvbXBpbGVkLCAnXFxuJ10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIXRlbXBsYXRlLm5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEhhbmRsZWJhcnMuRXhjZXB0aW9uKCdOYW1lIG1pc3NpbmcgZm9yIHRlbXBsYXRlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRzLmFtZCAmJiAhbXVsdGlwbGUpIHtcbiAgICAgICAgb3V0cHV0LmFkZCgncmV0dXJuICcpO1xuICAgICAgfVxuICAgICAgb3V0cHV0LmFkZChbb2JqZWN0TmFtZSwgJ1tcXCcnLCB0ZW1wbGF0ZS5uYW1lLCAnXFwnXSA9IHRlbXBsYXRlKCcsIHByZWNvbXBpbGVkLCAnKTtcXG4nXSk7XG4gICAgfVxuICB9KTtcblxuICAvLyBPdXRwdXQgdGhlIGNvbnRlbnRcbiAgaWYgKCFvcHRzLnNpbXBsZSkge1xuICAgIGlmIChvcHRzLmFtZCkge1xuICAgICAgaWYgKG11bHRpcGxlKSB7XG4gICAgICAgIG91dHB1dC5hZGQoWydyZXR1cm4gJywgb2JqZWN0TmFtZSwgJztcXG4nXSk7XG4gICAgICB9XG4gICAgICBvdXRwdXQuYWRkKCd9KTsnKTtcbiAgICB9IGVsc2UgaWYgKCFvcHRzLmNvbW1vbmpzKSB7XG4gICAgICBvdXRwdXQuYWRkKCd9KSgpOycpO1xuICAgIH1cbiAgfVxuXG5cbiAgaWYgKG9wdHMubWFwKSB7XG4gICAgb3V0cHV0LmFkZCgnXFxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9JyArIG9wdHMubWFwICsgJ1xcbicpO1xuICB9XG5cbiAgb3V0cHV0ID0gb3V0cHV0LnRvU3RyaW5nV2l0aFNvdXJjZU1hcCgpO1xuICBvdXRwdXQubWFwID0gb3V0cHV0Lm1hcCArICcnO1xuXG4gIGlmIChvcHRzLm1pbikge1xuICAgIG91dHB1dCA9IHVnbGlmeS5taW5pZnkob3V0cHV0LmNvZGUsIHtcbiAgICAgIGZyb21TdHJpbmc6IHRydWUsXG5cbiAgICAgIG91dFNvdXJjZU1hcDogb3B0cy5tYXAsXG4gICAgICBpblNvdXJjZU1hcDogSlNPTi5wYXJzZShvdXRwdXQubWFwKVxuICAgIH0pO1xuICAgIGlmIChvcHRzLm1hcCkge1xuICAgICAgb3V0cHV0LmNvZGUgKz0gJ1xcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPScgKyBvcHRzLm1hcCArICdcXG4nO1xuICAgIH1cbiAgfVxuXG4gIGlmIChvcHRzLm1hcCkge1xuICAgIGZzLndyaXRlRmlsZVN5bmMob3B0cy5tYXAsIG91dHB1dC5tYXAsICd1dGY4Jyk7XG4gIH1cbiAgb3V0cHV0ID0gb3V0cHV0LmNvZGU7XG5cbiAgaWYgKG9wdHMub3V0cHV0KSB7XG4gICAgZnMud3JpdGVGaWxlU3luYyhvcHRzLm91dHB1dCwgb3V0cHV0LCAndXRmOCcpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUubG9nKG91dHB1dCk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGFycmF5Q2FzdCh2YWx1ZSkge1xuICB2YWx1ZSA9IHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6IFtdO1xuICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgdmFsdWUgPSBbdmFsdWVdO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars.js new file mode 100644 index 0000000..6bb5415 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars.js @@ -0,0 +1,65 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _handlebarsRuntime = require('./handlebars.runtime'); + +var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime); + +// Compiler imports + +var _handlebarsCompilerAst = require('./handlebars/compiler/ast'); + +var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst); + +var _handlebarsCompilerBase = require('./handlebars/compiler/base'); + +var _handlebarsCompilerCompiler = require('./handlebars/compiler/compiler'); + +var _handlebarsCompilerJavascriptCompiler = require('./handlebars/compiler/javascript-compiler'); + +var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler); + +var _handlebarsCompilerVisitor = require('./handlebars/compiler/visitor'); + +var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor); + +var _handlebarsNoConflict = require('./handlebars/no-conflict'); + +var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict); + +var _create = _handlebarsRuntime2['default'].create; +function create() { + var hb = _create(); + + hb.compile = function (input, options) { + return _handlebarsCompilerCompiler.compile(input, options, hb); + }; + hb.precompile = function (input, options) { + return _handlebarsCompilerCompiler.precompile(input, options, hb); + }; + + hb.AST = _handlebarsCompilerAst2['default']; + hb.Compiler = _handlebarsCompilerCompiler.Compiler; + hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default']; + hb.Parser = _handlebarsCompilerBase.parser; + hb.parse = _handlebarsCompilerBase.parse; + + return hb; +} + +var inst = create(); +inst.create = create; + +_handlebarsNoConflict2['default'](inst); + +inst.Visitor = _handlebarsCompilerVisitor2['default']; + +inst['default'] = inst; + +exports['default'] = inst; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7aUNBQW9CLHNCQUFzQjs7Ozs7O3FDQUcxQiwyQkFBMkI7Ozs7c0NBQ0gsNEJBQTRCOzswQ0FDdEIsZ0NBQWdDOztvREFDL0MsMkNBQTJDOzs7O3lDQUN0RCwrQkFBK0I7Ozs7b0NBRTVCLDBCQUEwQjs7OztBQUVqRCxJQUFJLE9BQU8sR0FBRywrQkFBUSxNQUFNLENBQUM7QUFDN0IsU0FBUyxNQUFNLEdBQUc7QUFDaEIsTUFBSSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7O0FBRW5CLElBQUUsQ0FBQyxPQUFPLEdBQUcsVUFBUyxLQUFLLEVBQUUsT0FBTyxFQUFFO0FBQ3BDLFdBQU8sb0NBQVEsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztHQUNwQyxDQUFDO0FBQ0YsSUFBRSxDQUFDLFVBQVUsR0FBRyxVQUFTLEtBQUssRUFBRSxPQUFPLEVBQUU7QUFDdkMsV0FBTyx1Q0FBVyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0dBQ3ZDLENBQUM7O0FBRUYsSUFBRSxDQUFDLEdBQUcscUNBQU0sQ0FBQztBQUNiLElBQUUsQ0FBQyxRQUFRLHVDQUFXLENBQUM7QUFDdkIsSUFBRSxDQUFDLGtCQUFrQixvREFBcUIsQ0FBQztBQUMzQyxJQUFFLENBQUMsTUFBTSxpQ0FBUyxDQUFDO0FBQ25CLElBQUUsQ0FBQyxLQUFLLGdDQUFRLENBQUM7O0FBRWpCLFNBQU8sRUFBRSxDQUFDO0NBQ1g7O0FBRUQsSUFBSSxJQUFJLEdBQUcsTUFBTSxFQUFFLENBQUM7QUFDcEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7O0FBRXJCLGtDQUFXLElBQUksQ0FBQyxDQUFDOztBQUVqQixJQUFJLENBQUMsT0FBTyx5Q0FBVSxDQUFDOztBQUV2QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFDOztxQkFFUixJQUFJIiwiZmlsZSI6ImhhbmRsZWJhcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcnVudGltZSBmcm9tICcuL2hhbmRsZWJhcnMucnVudGltZSc7XG5cbi8vIENvbXBpbGVyIGltcG9ydHNcbmltcG9ydCBBU1QgZnJvbSAnLi9oYW5kbGViYXJzL2NvbXBpbGVyL2FzdCc7XG5pbXBvcnQgeyBwYXJzZXIgYXMgUGFyc2VyLCBwYXJzZSB9IGZyb20gJy4vaGFuZGxlYmFycy9jb21waWxlci9iYXNlJztcbmltcG9ydCB7IENvbXBpbGVyLCBjb21waWxlLCBwcmVjb21waWxlIH0gZnJvbSAnLi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvbXBpbGVyJztcbmltcG9ydCBKYXZhU2NyaXB0Q29tcGlsZXIgZnJvbSAnLi9oYW5kbGViYXJzL2NvbXBpbGVyL2phdmFzY3JpcHQtY29tcGlsZXInO1xuaW1wb3J0IFZpc2l0b3IgZnJvbSAnLi9oYW5kbGViYXJzL2NvbXBpbGVyL3Zpc2l0b3InO1xuXG5pbXBvcnQgbm9Db25mbGljdCBmcm9tICcuL2hhbmRsZWJhcnMvbm8tY29uZmxpY3QnO1xuXG5sZXQgX2NyZWF0ZSA9IHJ1bnRpbWUuY3JlYXRlO1xuZnVuY3Rpb24gY3JlYXRlKCkge1xuICBsZXQgaGIgPSBfY3JlYXRlKCk7XG5cbiAgaGIuY29tcGlsZSA9IGZ1bmN0aW9uKGlucHV0LCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGNvbXBpbGUoaW5wdXQsIG9wdGlvbnMsIGhiKTtcbiAgfTtcbiAgaGIucHJlY29tcGlsZSA9IGZ1bmN0aW9uKGlucHV0LCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIHByZWNvbXBpbGUoaW5wdXQsIG9wdGlvbnMsIGhiKTtcbiAgfTtcblxuICBoYi5BU1QgPSBBU1Q7XG4gIGhiLkNvbXBpbGVyID0gQ29tcGlsZXI7XG4gIGhiLkphdmFTY3JpcHRDb21waWxlciA9IEphdmFTY3JpcHRDb21waWxlcjtcbiAgaGIuUGFyc2VyID0gUGFyc2VyO1xuICBoYi5wYXJzZSA9IHBhcnNlO1xuXG4gIHJldHVybiBoYjtcbn1cblxubGV0IGluc3QgPSBjcmVhdGUoKTtcbmluc3QuY3JlYXRlID0gY3JlYXRlO1xuXG5ub0NvbmZsaWN0KGluc3QpO1xuXG5pbnN0LlZpc2l0b3IgPSBWaXNpdG9yO1xuXG5pbnN0WydkZWZhdWx0J10gPSBpbnN0O1xuXG5leHBvcnQgZGVmYXVsdCBpbnN0O1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars.runtime.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars.runtime.js new file mode 100644 index 0000000..37550bc --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars.runtime.js @@ -0,0 +1,66 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +// istanbul ignore next + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } + +var _handlebarsBase = require('./handlebars/base'); + +var base = _interopRequireWildcard(_handlebarsBase); + +// Each of these augment the Handlebars object. No need to setup here. +// (This is done to easily share code between commonjs and browse envs) + +var _handlebarsSafeString = require('./handlebars/safe-string'); + +var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString); + +var _handlebarsException = require('./handlebars/exception'); + +var _handlebarsException2 = _interopRequireDefault(_handlebarsException); + +var _handlebarsUtils = require('./handlebars/utils'); + +var Utils = _interopRequireWildcard(_handlebarsUtils); + +var _handlebarsRuntime = require('./handlebars/runtime'); + +var runtime = _interopRequireWildcard(_handlebarsRuntime); + +var _handlebarsNoConflict = require('./handlebars/no-conflict'); + +var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict); + +// For compatibility and usage outside of module systems, make the Handlebars object a namespace +function create() { + var hb = new base.HandlebarsEnvironment(); + + Utils.extend(hb, base); + hb.SafeString = _handlebarsSafeString2['default']; + hb.Exception = _handlebarsException2['default']; + hb.Utils = Utils; + hb.escapeExpression = Utils.escapeExpression; + + hb.VM = runtime; + hb.template = function (spec) { + return runtime.template(spec, hb); + }; + + return hb; +} + +var inst = create(); +inst.create = create; + +_handlebarsNoConflict2['default'](inst); + +inst['default'] = inst; + +exports['default'] = inst; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLnJ1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OEJBQXNCLG1CQUFtQjs7SUFBN0IsSUFBSTs7Ozs7b0NBSU8sMEJBQTBCOzs7O21DQUMzQix3QkFBd0I7Ozs7K0JBQ3ZCLG9CQUFvQjs7SUFBL0IsS0FBSzs7aUNBQ1Esc0JBQXNCOztJQUFuQyxPQUFPOztvQ0FFSSwwQkFBMEI7Ozs7O0FBR2pELFNBQVMsTUFBTSxHQUFHO0FBQ2hCLE1BQUksRUFBRSxHQUFHLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7O0FBRTFDLE9BQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ3ZCLElBQUUsQ0FBQyxVQUFVLG9DQUFhLENBQUM7QUFDM0IsSUFBRSxDQUFDLFNBQVMsbUNBQVksQ0FBQztBQUN6QixJQUFFLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztBQUNqQixJQUFFLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixDQUFDOztBQUU3QyxJQUFFLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQztBQUNoQixJQUFFLENBQUMsUUFBUSxHQUFHLFVBQVMsSUFBSSxFQUFFO0FBQzNCLFdBQU8sT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7R0FDbkMsQ0FBQzs7QUFFRixTQUFPLEVBQUUsQ0FBQztDQUNYOztBQUVELElBQUksSUFBSSxHQUFHLE1BQU0sRUFBRSxDQUFDO0FBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDOztBQUVyQixrQ0FBVyxJQUFJLENBQUMsQ0FBQzs7QUFFakIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQzs7cUJBRVIsSUFBSSIsImZpbGUiOiJoYW5kbGViYXJzLnJ1bnRpbWUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBiYXNlIGZyb20gJy4vaGFuZGxlYmFycy9iYXNlJztcblxuLy8gRWFjaCBvZiB0aGVzZSBhdWdtZW50IHRoZSBIYW5kbGViYXJzIG9iamVjdC4gTm8gbmVlZCB0byBzZXR1cCBoZXJlLlxuLy8gKFRoaXMgaXMgZG9uZSB0byBlYXNpbHkgc2hhcmUgY29kZSBiZXR3ZWVuIGNvbW1vbmpzIGFuZCBicm93c2UgZW52cylcbmltcG9ydCBTYWZlU3RyaW5nIGZyb20gJy4vaGFuZGxlYmFycy9zYWZlLXN0cmluZyc7XG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4vaGFuZGxlYmFycy9leGNlcHRpb24nO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSAnLi9oYW5kbGViYXJzL3V0aWxzJztcbmltcG9ydCAqIGFzIHJ1bnRpbWUgZnJvbSAnLi9oYW5kbGViYXJzL3J1bnRpbWUnO1xuXG5pbXBvcnQgbm9Db25mbGljdCBmcm9tICcuL2hhbmRsZWJhcnMvbm8tY29uZmxpY3QnO1xuXG4vLyBGb3IgY29tcGF0aWJpbGl0eSBhbmQgdXNhZ2Ugb3V0c2lkZSBvZiBtb2R1bGUgc3lzdGVtcywgbWFrZSB0aGUgSGFuZGxlYmFycyBvYmplY3QgYSBuYW1lc3BhY2VcbmZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgbGV0IGhiID0gbmV3IGJhc2UuSGFuZGxlYmFyc0Vudmlyb25tZW50KCk7XG5cbiAgVXRpbHMuZXh0ZW5kKGhiLCBiYXNlKTtcbiAgaGIuU2FmZVN0cmluZyA9IFNhZmVTdHJpbmc7XG4gIGhiLkV4Y2VwdGlvbiA9IEV4Y2VwdGlvbjtcbiAgaGIuVXRpbHMgPSBVdGlscztcbiAgaGIuZXNjYXBlRXhwcmVzc2lvbiA9IFV0aWxzLmVzY2FwZUV4cHJlc3Npb247XG5cbiAgaGIuVk0gPSBydW50aW1lO1xuICBoYi50ZW1wbGF0ZSA9IGZ1bmN0aW9uKHNwZWMpIHtcbiAgICByZXR1cm4gcnVudGltZS50ZW1wbGF0ZShzcGVjLCBoYik7XG4gIH07XG5cbiAgcmV0dXJuIGhiO1xufVxuXG5sZXQgaW5zdCA9IGNyZWF0ZSgpO1xuaW5zdC5jcmVhdGUgPSBjcmVhdGU7XG5cbm5vQ29uZmxpY3QoaW5zdCk7XG5cbmluc3RbJ2RlZmF1bHQnXSA9IGluc3Q7XG5cbmV4cG9ydCBkZWZhdWx0IGluc3Q7XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/base.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/base.js new file mode 100644 index 0000000..d1cfc56 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/base.js @@ -0,0 +1,104 @@ +'use strict'; + +exports.__esModule = true; +exports.HandlebarsEnvironment = HandlebarsEnvironment; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _utils = require('./utils'); + +var _exception = require('./exception'); + +var _exception2 = _interopRequireDefault(_exception); + +var _helpers = require('./helpers'); + +var _decorators = require('./decorators'); + +var _logger = require('./logger'); + +var _logger2 = _interopRequireDefault(_logger); + +var VERSION = '4.0.5'; +exports.VERSION = VERSION; +var COMPILER_REVISION = 7; + +exports.COMPILER_REVISION = COMPILER_REVISION; +var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '== 1.x.x', + 5: '== 2.0.0-alpha.x', + 6: '>= 2.0.0-beta.1', + 7: '>= 4.0.0' +}; + +exports.REVISION_CHANGES = REVISION_CHANGES; +var objectType = '[object Object]'; + +function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + _helpers.registerDefaultHelpers(this); + _decorators.registerDefaultDecorators(this); +} + +HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: _logger2['default'], + log: _logger2['default'].log, + + registerHelper: function registerHelper(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _exception2['default']('Arg not supported with multiple helpers'); + } + _utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function unregisterHelper(name) { + delete this.helpers[name]; + }, + + registerPartial: function registerPartial(name, partial) { + if (_utils.toString.call(name) === objectType) { + _utils.extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined'); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function unregisterPartial(name) { + delete this.partials[name]; + }, + + registerDecorator: function registerDecorator(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _exception2['default']('Arg not supported with multiple decorators'); + } + _utils.extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function unregisterDecorator(name) { + delete this.decorators[name]; + } +}; + +var log = _logger2['default'].log; + +exports.log = log; +exports.createFrame = _utils.createFrame; +exports.logger = _logger2['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7cUJBQTRDLFNBQVM7O3lCQUMvQixhQUFhOzs7O3VCQUNFLFdBQVc7OzBCQUNSLGNBQWM7O3NCQUNuQyxVQUFVOzs7O0FBRXRCLElBQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQzs7QUFDeEIsSUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7OztBQUU1QixJQUFNLGdCQUFnQixHQUFHO0FBQzlCLEdBQUMsRUFBRSxhQUFhO0FBQ2hCLEdBQUMsRUFBRSxlQUFlO0FBQ2xCLEdBQUMsRUFBRSxlQUFlO0FBQ2xCLEdBQUMsRUFBRSxVQUFVO0FBQ2IsR0FBQyxFQUFFLGtCQUFrQjtBQUNyQixHQUFDLEVBQUUsaUJBQWlCO0FBQ3BCLEdBQUMsRUFBRSxVQUFVO0NBQ2QsQ0FBQzs7O0FBRUYsSUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUM7O0FBRTlCLFNBQVMscUJBQXFCLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUU7QUFDbkUsTUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO0FBQzdCLE1BQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztBQUMvQixNQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsSUFBSSxFQUFFLENBQUM7O0FBRW5DLGtDQUF1QixJQUFJLENBQUMsQ0FBQztBQUM3Qix3Q0FBMEIsSUFBSSxDQUFDLENBQUM7Q0FDakM7O0FBRUQscUJBQXFCLENBQUMsU0FBUyxHQUFHO0FBQ2hDLGFBQVcsRUFBRSxxQkFBcUI7O0FBRWxDLFFBQU0scUJBQVE7QUFDZCxLQUFHLEVBQUUsb0JBQU8sR0FBRzs7QUFFZixnQkFBYyxFQUFFLHdCQUFTLElBQUksRUFBRSxFQUFFLEVBQUU7QUFDakMsUUFBSSxnQkFBUyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssVUFBVSxFQUFFO0FBQ3RDLFVBQUksRUFBRSxFQUFFO0FBQUUsY0FBTSwyQkFBYyx5Q0FBeUMsQ0FBQyxDQUFDO09BQUU7QUFDM0Usb0JBQU8sSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztLQUM1QixNQUFNO0FBQ0wsVUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDekI7R0FDRjtBQUNELGtCQUFnQixFQUFFLDBCQUFTLElBQUksRUFBRTtBQUMvQixXQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7R0FDM0I7O0FBRUQsaUJBQWUsRUFBRSx5QkFBUyxJQUFJLEVBQUUsT0FBTyxFQUFFO0FBQ3ZDLFFBQUksZ0JBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLFVBQVUsRUFBRTtBQUN0QyxvQkFBTyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQzdCLE1BQU07QUFDTCxVQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVcsRUFBRTtBQUNsQyxjQUFNLHlFQUEwRCxJQUFJLG9CQUFpQixDQUFDO09BQ3ZGO0FBQ0QsVUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUM7S0FDL0I7R0FDRjtBQUNELG1CQUFpQixFQUFFLDJCQUFTLElBQUksRUFBRTtBQUNoQyxXQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7R0FDNUI7O0FBRUQsbUJBQWlCLEVBQUUsMkJBQVMsSUFBSSxFQUFFLEVBQUUsRUFBRTtBQUNwQyxRQUFJLGdCQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxVQUFVLEVBQUU7QUFDdEMsVUFBSSxFQUFFLEVBQUU7QUFBRSxjQUFNLDJCQUFjLDRDQUE0QyxDQUFDLENBQUM7T0FBRTtBQUM5RSxvQkFBTyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQy9CLE1BQU07QUFDTCxVQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUM1QjtHQUNGO0FBQ0QscUJBQW1CLEVBQUUsNkJBQVMsSUFBSSxFQUFFO0FBQ2xDLFdBQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztHQUM5QjtDQUNGLENBQUM7O0FBRUssSUFBSSxHQUFHLEdBQUcsb0JBQU8sR0FBRyxDQUFDOzs7UUFFcEIsV0FBVztRQUFFLE1BQU0iLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Y3JlYXRlRnJhbWUsIGV4dGVuZCwgdG9TdHJpbmd9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuL2V4Y2VwdGlvbic7XG5pbXBvcnQge3JlZ2lzdGVyRGVmYXVsdEhlbHBlcnN9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3JlZ2lzdGVyRGVmYXVsdERlY29yYXRvcnN9IGZyb20gJy4vZGVjb3JhdG9ycyc7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4vbG9nZ2VyJztcblxuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSAnNC4wLjUnO1xuZXhwb3J0IGNvbnN0IENPTVBJTEVSX1JFVklTSU9OID0gNztcblxuZXhwb3J0IGNvbnN0IFJFVklTSU9OX0NIQU5HRVMgPSB7XG4gIDE6ICc8PSAxLjAucmMuMicsIC8vIDEuMC5yYy4yIGlzIGFjdHVhbGx5IHJldjIgYnV0IGRvZXNuJ3QgcmVwb3J0IGl0XG4gIDI6ICc9PSAxLjAuMC1yYy4zJyxcbiAgMzogJz09IDEuMC4wLXJjLjQnLFxuICA0OiAnPT0gMS54LngnLFxuICA1OiAnPT0gMi4wLjAtYWxwaGEueCcsXG4gIDY6ICc+PSAyLjAuMC1iZXRhLjEnLFxuICA3OiAnPj0gNC4wLjAnXG59O1xuXG5jb25zdCBvYmplY3RUeXBlID0gJ1tvYmplY3QgT2JqZWN0XSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBIYW5kbGViYXJzRW52aXJvbm1lbnQoaGVscGVycywgcGFydGlhbHMsIGRlY29yYXRvcnMpIHtcbiAgdGhpcy5oZWxwZXJzID0gaGVscGVycyB8fCB7fTtcbiAgdGhpcy5wYXJ0aWFscyA9IHBhcnRpYWxzIHx8IHt9O1xuICB0aGlzLmRlY29yYXRvcnMgPSBkZWNvcmF0b3JzIHx8IHt9O1xuXG4gIHJlZ2lzdGVyRGVmYXVsdEhlbHBlcnModGhpcyk7XG4gIHJlZ2lzdGVyRGVmYXVsdERlY29yYXRvcnModGhpcyk7XG59XG5cbkhhbmRsZWJhcnNFbnZpcm9ubWVudC5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBIYW5kbGViYXJzRW52aXJvbm1lbnQsXG5cbiAgbG9nZ2VyOiBsb2dnZXIsXG4gIGxvZzogbG9nZ2VyLmxvZyxcblxuICByZWdpc3RlckhlbHBlcjogZnVuY3Rpb24obmFtZSwgZm4pIHtcbiAgICBpZiAodG9TdHJpbmcuY2FsbChuYW1lKSA9PT0gb2JqZWN0VHlwZSkge1xuICAgICAgaWYgKGZuKSB7IHRocm93IG5ldyBFeGNlcHRpb24oJ0FyZyBub3Qgc3VwcG9ydGVkIHdpdGggbXVsdGlwbGUgaGVscGVycycpOyB9XG4gICAgICBleHRlbmQodGhpcy5oZWxwZXJzLCBuYW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5oZWxwZXJzW25hbWVdID0gZm47XG4gICAgfVxuICB9LFxuICB1bnJlZ2lzdGVySGVscGVyOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMuaGVscGVyc1tuYW1lXTtcbiAgfSxcblxuICByZWdpc3RlclBhcnRpYWw6IGZ1bmN0aW9uKG5hbWUsIHBhcnRpYWwpIHtcbiAgICBpZiAodG9TdHJpbmcuY2FsbChuYW1lKSA9PT0gb2JqZWN0VHlwZSkge1xuICAgICAgZXh0ZW5kKHRoaXMucGFydGlhbHMsIG5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIHBhcnRpYWwgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oYEF0dGVtcHRpbmcgdG8gcmVnaXN0ZXIgYSBwYXJ0aWFsIGNhbGxlZCBcIiR7bmFtZX1cIiBhcyB1bmRlZmluZWRgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMucGFydGlhbHNbbmFtZV0gPSBwYXJ0aWFsO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlclBhcnRpYWw6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBkZWxldGUgdGhpcy5wYXJ0aWFsc1tuYW1lXTtcbiAgfSxcblxuICByZWdpc3RlckRlY29yYXRvcjogZnVuY3Rpb24obmFtZSwgZm4pIHtcbiAgICBpZiAodG9TdHJpbmcuY2FsbChuYW1lKSA9PT0gb2JqZWN0VHlwZSkge1xuICAgICAgaWYgKGZuKSB7IHRocm93IG5ldyBFeGNlcHRpb24oJ0FyZyBub3Qgc3VwcG9ydGVkIHdpdGggbXVsdGlwbGUgZGVjb3JhdG9ycycpOyB9XG4gICAgICBleHRlbmQodGhpcy5kZWNvcmF0b3JzLCBuYW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kZWNvcmF0b3JzW25hbWVdID0gZm47XG4gICAgfVxuICB9LFxuICB1bnJlZ2lzdGVyRGVjb3JhdG9yOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMuZGVjb3JhdG9yc1tuYW1lXTtcbiAgfVxufTtcblxuZXhwb3J0IGxldCBsb2cgPSBsb2dnZXIubG9nO1xuXG5leHBvcnQge2NyZWF0ZUZyYW1lLCBsb2dnZXJ9O1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/ast.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/ast.js new file mode 100644 index 0000000..33c65fe --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/ast.js @@ -0,0 +1,31 @@ +'use strict'; + +exports.__esModule = true; +var AST = { + // Public API used to evaluate derived attributes regarding AST nodes + helpers: { + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + helperExpression: function helperExpression(node) { + return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash); + }, + + scopedId: function scopedId(path) { + return (/^\.|this\b/.test(path.original) + ); + }, + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + simpleId: function simpleId(path) { + return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; + } + } +}; + +// Must be exported as an object rather than the root of the module as the jison lexer +// must modify the object to operate properly. +exports['default'] = AST; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2FzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxJQUFJLEdBQUcsR0FBRzs7QUFFUixTQUFPLEVBQUU7Ozs7QUFJUCxvQkFBZ0IsRUFBRSwwQkFBUyxJQUFJLEVBQUU7QUFDL0IsYUFBTyxBQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssZUFBZSxJQUM3QixDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssbUJBQW1CLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxnQkFBZ0IsQ0FBQSxJQUNuRSxDQUFDLEVBQUUsQUFBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFLLElBQUksQ0FBQyxJQUFJLENBQUEsQUFBQyxBQUFDLENBQUM7S0FDaEU7O0FBRUQsWUFBUSxFQUFFLGtCQUFTLElBQUksRUFBRTtBQUN2QixhQUFPLEFBQUMsYUFBWSxDQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQUM7S0FDM0M7Ozs7QUFJRCxZQUFRLEVBQUUsa0JBQVMsSUFBSSxFQUFFO0FBQ3ZCLGFBQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0tBQzlFO0dBQ0Y7Q0FDRixDQUFDOzs7O3FCQUthLEdBQUciLCJmaWxlIjoiYXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsibGV0IEFTVCA9IHtcbiAgLy8gUHVibGljIEFQSSB1c2VkIHRvIGV2YWx1YXRlIGRlcml2ZWQgYXR0cmlidXRlcyByZWdhcmRpbmcgQVNUIG5vZGVzXG4gIGhlbHBlcnM6IHtcbiAgICAvLyBhIG11c3RhY2hlIGlzIGRlZmluaXRlbHkgYSBoZWxwZXIgaWY6XG4gICAgLy8gKiBpdCBpcyBhbiBlbGlnaWJsZSBoZWxwZXIsIGFuZFxuICAgIC8vICogaXQgaGFzIGF0IGxlYXN0IG9uZSBwYXJhbWV0ZXIgb3IgaGFzaCBzZWdtZW50XG4gICAgaGVscGVyRXhwcmVzc2lvbjogZnVuY3Rpb24obm9kZSkge1xuICAgICAgcmV0dXJuIChub2RlLnR5cGUgPT09ICdTdWJFeHByZXNzaW9uJylcbiAgICAgICAgICB8fCAoKG5vZGUudHlwZSA9PT0gJ011c3RhY2hlU3RhdGVtZW50JyB8fCBub2RlLnR5cGUgPT09ICdCbG9ja1N0YXRlbWVudCcpXG4gICAgICAgICAgICAmJiAhISgobm9kZS5wYXJhbXMgJiYgbm9kZS5wYXJhbXMubGVuZ3RoKSB8fCBub2RlLmhhc2gpKTtcbiAgICB9LFxuXG4gICAgc2NvcGVkSWQ6IGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgIHJldHVybiAoL15cXC58dGhpc1xcYi8pLnRlc3QocGF0aC5vcmlnaW5hbCk7XG4gICAgfSxcblxuICAgIC8vIGFuIElEIGlzIHNpbXBsZSBpZiBpdCBvbmx5IGhhcyBvbmUgcGFydCwgYW5kIHRoYXQgcGFydCBpcyBub3RcbiAgICAvLyBgLi5gIG9yIGB0aGlzYC5cbiAgICBzaW1wbGVJZDogZnVuY3Rpb24ocGF0aCkge1xuICAgICAgcmV0dXJuIHBhdGgucGFydHMubGVuZ3RoID09PSAxICYmICFBU1QuaGVscGVycy5zY29wZWRJZChwYXRoKSAmJiAhcGF0aC5kZXB0aDtcbiAgICB9XG4gIH1cbn07XG5cblxuLy8gTXVzdCBiZSBleHBvcnRlZCBhcyBhbiBvYmplY3QgcmF0aGVyIHRoYW4gdGhlIHJvb3Qgb2YgdGhlIG1vZHVsZSBhcyB0aGUgamlzb24gbGV4ZXJcbi8vIG11c3QgbW9kaWZ5IHRoZSBvYmplY3QgdG8gb3BlcmF0ZSBwcm9wZXJseS5cbmV4cG9ydCBkZWZhdWx0IEFTVDtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/base.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/base.js new file mode 100644 index 0000000..1aef63c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/base.js @@ -0,0 +1,48 @@ +'use strict'; + +exports.__esModule = true; +exports.parse = parse; +// istanbul ignore next + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } + +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _parser = require('./parser'); + +var _parser2 = _interopRequireDefault(_parser); + +var _whitespaceControl = require('./whitespace-control'); + +var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl); + +var _helpers = require('./helpers'); + +var Helpers = _interopRequireWildcard(_helpers); + +var _utils = require('../utils'); + +exports.parser = _parser2['default']; + +var yy = {}; +_utils.extend(yy, Helpers); + +function parse(input, options) { + // Just return if an already-compiled AST was passed in. + if (input.type === 'Program') { + return input; + } + + _parser2['default'].yy = yy; + + // Altering the shared object here, but this is ok as parser is a sync operation + yy.locInfo = function (locInfo) { + return new yy.SourceLocation(options && options.srcName, locInfo); + }; + + var strip = new _whitespaceControl2['default'](options); + return strip.accept(_parser2['default'].parse(input)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O3NCQUFtQixVQUFVOzs7O2lDQUNDLHNCQUFzQjs7Ozt1QkFDM0IsV0FBVzs7SUFBeEIsT0FBTzs7cUJBQ0ksVUFBVTs7UUFFeEIsTUFBTTs7QUFFZixJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDWixjQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQzs7QUFFYixTQUFTLEtBQUssQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFOztBQUVwQyxNQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFO0FBQUUsV0FBTyxLQUFLLENBQUM7R0FBRTs7QUFFL0Msc0JBQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQzs7O0FBR2YsSUFBRSxDQUFDLE9BQU8sR0FBRyxVQUFTLE9BQU8sRUFBRTtBQUM3QixXQUFPLElBQUksRUFBRSxDQUFDLGNBQWMsQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztHQUNuRSxDQUFDOztBQUVGLE1BQUksS0FBSyxHQUFHLG1DQUFzQixPQUFPLENBQUMsQ0FBQztBQUMzQyxTQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsb0JBQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Q0FDMUMiLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXJzZXIgZnJvbSAnLi9wYXJzZXInO1xuaW1wb3J0IFdoaXRlc3BhY2VDb250cm9sIGZyb20gJy4vd2hpdGVzcGFjZS1jb250cm9sJztcbmltcG9ydCAqIGFzIEhlbHBlcnMgZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7IGV4dGVuZCB9IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IHsgcGFyc2VyIH07XG5cbmxldCB5eSA9IHt9O1xuZXh0ZW5kKHl5LCBIZWxwZXJzKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlKGlucHV0LCBvcHRpb25zKSB7XG4gIC8vIEp1c3QgcmV0dXJuIGlmIGFuIGFscmVhZHktY29tcGlsZWQgQVNUIHdhcyBwYXNzZWQgaW4uXG4gIGlmIChpbnB1dC50eXBlID09PSAnUHJvZ3JhbScpIHsgcmV0dXJuIGlucHV0OyB9XG5cbiAgcGFyc2VyLnl5ID0geXk7XG5cbiAgLy8gQWx0ZXJpbmcgdGhlIHNoYXJlZCBvYmplY3QgaGVyZSwgYnV0IHRoaXMgaXMgb2sgYXMgcGFyc2VyIGlzIGEgc3luYyBvcGVyYXRpb25cbiAgeXkubG9jSW5mbyA9IGZ1bmN0aW9uKGxvY0luZm8pIHtcbiAgICByZXR1cm4gbmV3IHl5LlNvdXJjZUxvY2F0aW9uKG9wdGlvbnMgJiYgb3B0aW9ucy5zcmNOYW1lLCBsb2NJbmZvKTtcbiAgfTtcblxuICBsZXQgc3RyaXAgPSBuZXcgV2hpdGVzcGFjZUNvbnRyb2wob3B0aW9ucyk7XG4gIHJldHVybiBzdHJpcC5hY2NlcHQocGFyc2VyLnBhcnNlKGlucHV0KSk7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/code-gen.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/code-gen.js new file mode 100644 index 0000000..b5b3615 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/code-gen.js @@ -0,0 +1,166 @@ +/* global define */ +'use strict'; + +exports.__esModule = true; + +var _utils = require('../utils'); + +var SourceNode = undefined; + +try { + /* istanbul ignore next */ + if (typeof define !== 'function' || !define.amd) { + // We don't support this in AMD environments. For these environments, we asusme that + // they are running on the browser and thus have no need for the source-map library. + var SourceMap = require('source-map'); + SourceNode = SourceMap.SourceNode; + } +} catch (err) {} +/* NOP */ + +/* istanbul ignore if: tested but not covered in istanbul due to dist build */ +if (!SourceNode) { + SourceNode = function (line, column, srcFile, chunks) { + this.src = ''; + if (chunks) { + this.add(chunks); + } + }; + /* istanbul ignore next */ + SourceNode.prototype = { + add: function add(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src += chunks; + }, + prepend: function prepend(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src = chunks + this.src; + }, + toStringWithSourceMap: function toStringWithSourceMap() { + return { code: this.toString() }; + }, + toString: function toString() { + return this.src; + } + }; +} + +function castChunk(chunk, codeGen, loc) { + if (_utils.isArray(chunk)) { + var ret = []; + + for (var i = 0, len = chunk.length; i < len; i++) { + ret.push(codeGen.wrap(chunk[i], loc)); + } + return ret; + } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { + // Handle primitives that the SourceNode will throw up on + return chunk + ''; + } + return chunk; +} + +function CodeGen(srcFile) { + this.srcFile = srcFile; + this.source = []; +} + +CodeGen.prototype = { + isEmpty: function isEmpty() { + return !this.source.length; + }, + prepend: function prepend(source, loc) { + this.source.unshift(this.wrap(source, loc)); + }, + push: function push(source, loc) { + this.source.push(this.wrap(source, loc)); + }, + + merge: function merge() { + var source = this.empty(); + this.each(function (line) { + source.add([' ', line, '\n']); + }); + return source; + }, + + each: function each(iter) { + for (var i = 0, len = this.source.length; i < len; i++) { + iter(this.source[i]); + } + }, + + empty: function empty() { + var loc = this.currentLocation || { start: {} }; + return new SourceNode(loc.start.line, loc.start.column, this.srcFile); + }, + wrap: function wrap(chunk) { + var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1]; + + if (chunk instanceof SourceNode) { + return chunk; + } + + chunk = castChunk(chunk, this, loc); + + return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); + }, + + functionCall: function functionCall(fn, type, params) { + params = this.generateList(params); + return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); + }, + + quotedString: function quotedString(str) { + return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + objectLiteral: function objectLiteral(obj) { + var pairs = []; + + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var value = castChunk(obj[key], this); + if (value !== 'undefined') { + pairs.push([this.quotedString(key), ':', value]); + } + } + } + + var ret = this.generateList(pairs); + ret.prepend('{'); + ret.add('}'); + return ret; + }, + + generateList: function generateList(entries) { + var ret = this.empty(); + + for (var i = 0, len = entries.length; i < len; i++) { + if (i) { + ret.add(','); + } + + ret.add(castChunk(entries[i], this)); + } + + return ret; + }, + + generateArray: function generateArray(entries) { + var ret = this.generateList(entries); + ret.prepend('['); + ret.add(']'); + + return ret; + } +}; + +exports['default'] = CodeGen; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvZGUtZ2VuLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O3FCQUNzQixVQUFVOztBQUVoQyxJQUFJLFVBQVUsWUFBQSxDQUFDOztBQUVmLElBQUk7O0FBRUYsTUFBSSxPQUFPLE1BQU0sS0FBSyxVQUFVLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFOzs7QUFHL0MsUUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3RDLGNBQVUsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDO0dBQ25DO0NBQ0YsQ0FBQyxPQUFPLEdBQUcsRUFBRSxFQUViOzs7O0FBQUEsQUFHRCxJQUFJLENBQUMsVUFBVSxFQUFFO0FBQ2YsWUFBVSxHQUFHLFVBQVMsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQ25ELFFBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDO0FBQ2QsUUFBSSxNQUFNLEVBQUU7QUFDVixVQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQ2xCO0dBQ0YsQ0FBQzs7QUFFRixZQUFVLENBQUMsU0FBUyxHQUFHO0FBQ3JCLE9BQUcsRUFBRSxhQUFTLE1BQU0sRUFBRTtBQUNwQixVQUFJLGVBQVEsTUFBTSxDQUFDLEVBQUU7QUFDbkIsY0FBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7T0FDMUI7QUFDRCxVQUFJLENBQUMsR0FBRyxJQUFJLE1BQU0sQ0FBQztLQUNwQjtBQUNELFdBQU8sRUFBRSxpQkFBUyxNQUFNLEVBQUU7QUFDeEIsVUFBSSxlQUFRLE1BQU0sQ0FBQyxFQUFFO0FBQ25CLGNBQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO09BQzFCO0FBQ0QsVUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztLQUM5QjtBQUNELHlCQUFxQixFQUFFLGlDQUFXO0FBQ2hDLGFBQU8sRUFBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFDLENBQUM7S0FDaEM7QUFDRCxZQUFRLEVBQUUsb0JBQVc7QUFDbkIsYUFBTyxJQUFJLENBQUMsR0FBRyxDQUFDO0tBQ2pCO0dBQ0YsQ0FBQztDQUNIOztBQUdELFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFO0FBQ3RDLE1BQUksZUFBUSxLQUFLLENBQUMsRUFBRTtBQUNsQixRQUFJLEdBQUcsR0FBRyxFQUFFLENBQUM7O0FBRWIsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUNoRCxTQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7S0FDdkM7QUFDRCxXQUFPLEdBQUcsQ0FBQztHQUNaLE1BQU0sSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFOztBQUVsRSxXQUFPLEtBQUssR0FBRyxFQUFFLENBQUM7R0FDbkI7QUFDRCxTQUFPLEtBQUssQ0FBQztDQUNkOztBQUdELFNBQVMsT0FBTyxDQUFDLE9BQU8sRUFBRTtBQUN4QixNQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztBQUN2QixNQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztDQUNsQjs7QUFFRCxPQUFPLENBQUMsU0FBUyxHQUFHO0FBQ2xCLFNBQU8sRUFBQSxtQkFBRztBQUNSLFdBQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztHQUM1QjtBQUNELFNBQU8sRUFBRSxpQkFBUyxNQUFNLEVBQUUsR0FBRyxFQUFFO0FBQzdCLFFBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7R0FDN0M7QUFDRCxNQUFJLEVBQUUsY0FBUyxNQUFNLEVBQUUsR0FBRyxFQUFFO0FBQzFCLFFBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7R0FDMUM7O0FBRUQsT0FBSyxFQUFFLGlCQUFXO0FBQ2hCLFFBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUMxQixRQUFJLENBQUMsSUFBSSxDQUFDLFVBQVMsSUFBSSxFQUFFO0FBQ3ZCLFlBQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDaEMsQ0FBQyxDQUFDO0FBQ0gsV0FBTyxNQUFNLENBQUM7R0FDZjs7QUFFRCxNQUFJLEVBQUUsY0FBUyxJQUFJLEVBQUU7QUFDbkIsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDdEQsVUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN0QjtHQUNGOztBQUVELE9BQUssRUFBRSxpQkFBVztBQUNoQixRQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsZUFBZSxJQUFJLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBQyxDQUFDO0FBQzlDLFdBQU8sSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQ3ZFO0FBQ0QsTUFBSSxFQUFFLGNBQVMsS0FBSyxFQUE2QztRQUEzQyxHQUFHLHlEQUFHLElBQUksQ0FBQyxlQUFlLElBQUksRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFDOztBQUM3RCxRQUFJLEtBQUssWUFBWSxVQUFVLEVBQUU7QUFDL0IsYUFBTyxLQUFLLENBQUM7S0FDZDs7QUFFRCxTQUFLLEdBQUcsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7O0FBRXBDLFdBQU8sSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztHQUM5RTs7QUFFRCxjQUFZLEVBQUUsc0JBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUU7QUFDdkMsVUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbkMsV0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7R0FDcEU7O0FBRUQsY0FBWSxFQUFFLHNCQUFTLEdBQUcsRUFBRTtBQUMxQixXQUFPLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUEsQ0FDbkIsT0FBTyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FDdEIsT0FBTyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FDcEIsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FDckIsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FDckIsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUM7S0FDN0IsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsR0FBRyxHQUFHLENBQUM7R0FDeEM7O0FBRUQsZUFBYSxFQUFFLHVCQUFTLEdBQUcsRUFBRTtBQUMzQixRQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7O0FBRWYsU0FBSyxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQUU7QUFDbkIsVUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxFQUFFO0FBQzNCLFlBQUksS0FBSyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDdEMsWUFBSSxLQUFLLEtBQUssV0FBVyxFQUFFO0FBQ3pCLGVBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQ2xEO09BQ0Y7S0FDRjs7QUFFRCxRQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ25DLE9BQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDakIsT0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNiLFdBQU8sR0FBRyxDQUFDO0dBQ1o7O0FBR0QsY0FBWSxFQUFFLHNCQUFTLE9BQU8sRUFBRTtBQUM5QixRQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7O0FBRXZCLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDbEQsVUFBSSxDQUFDLEVBQUU7QUFDTCxXQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO09BQ2Q7O0FBRUQsU0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDdEM7O0FBRUQsV0FBTyxHQUFHLENBQUM7R0FDWjs7QUFFRCxlQUFhLEVBQUUsdUJBQVMsT0FBTyxFQUFFO0FBQy9CLFFBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDckMsT0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqQixPQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztBQUViLFdBQU8sR0FBRyxDQUFDO0dBQ1o7Q0FDRixDQUFDOztxQkFFYSxPQUFPIiwiZmlsZSI6ImNvZGUtZ2VuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZ2xvYmFsIGRlZmluZSAqL1xuaW1wb3J0IHtpc0FycmF5fSBmcm9tICcuLi91dGlscyc7XG5cbmxldCBTb3VyY2VOb2RlO1xuXG50cnkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAodHlwZW9mIGRlZmluZSAhPT0gJ2Z1bmN0aW9uJyB8fCAhZGVmaW5lLmFtZCkge1xuICAgIC8vIFdlIGRvbid0IHN1cHBvcnQgdGhpcyBpbiBBTUQgZW52aXJvbm1lbnRzLiBGb3IgdGhlc2UgZW52aXJvbm1lbnRzLCB3ZSBhc3VzbWUgdGhhdFxuICAgIC8vIHRoZXkgYXJlIHJ1bm5pbmcgb24gdGhlIGJyb3dzZXIgYW5kIHRodXMgaGF2ZSBubyBuZWVkIGZvciB0aGUgc291cmNlLW1hcCBsaWJyYXJ5LlxuICAgIGxldCBTb3VyY2VNYXAgPSByZXF1aXJlKCdzb3VyY2UtbWFwJyk7XG4gICAgU291cmNlTm9kZSA9IFNvdXJjZU1hcC5Tb3VyY2VOb2RlO1xuICB9XG59IGNhdGNoIChlcnIpIHtcbiAgLyogTk9QICovXG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBpZjogdGVzdGVkIGJ1dCBub3QgY292ZXJlZCBpbiBpc3RhbmJ1bCBkdWUgdG8gZGlzdCBidWlsZCAgKi9cbmlmICghU291cmNlTm9kZSkge1xuICBTb3VyY2VOb2RlID0gZnVuY3Rpb24obGluZSwgY29sdW1uLCBzcmNGaWxlLCBjaHVua3MpIHtcbiAgICB0aGlzLnNyYyA9ICcnO1xuICAgIGlmIChjaHVua3MpIHtcbiAgICAgIHRoaXMuYWRkKGNodW5rcyk7XG4gICAgfVxuICB9O1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBTb3VyY2VOb2RlLnByb3RvdHlwZSA9IHtcbiAgICBhZGQ6IGZ1bmN0aW9uKGNodW5rcykge1xuICAgICAgaWYgKGlzQXJyYXkoY2h1bmtzKSkge1xuICAgICAgICBjaHVua3MgPSBjaHVua3Muam9pbignJyk7XG4gICAgICB9XG4gICAgICB0aGlzLnNyYyArPSBjaHVua3M7XG4gICAgfSxcbiAgICBwcmVwZW5kOiBmdW5jdGlvbihjaHVua3MpIHtcbiAgICAgIGlmIChpc0FycmF5KGNodW5rcykpIHtcbiAgICAgICAgY2h1bmtzID0gY2h1bmtzLmpvaW4oJycpO1xuICAgICAgfVxuICAgICAgdGhpcy5zcmMgPSBjaHVua3MgKyB0aGlzLnNyYztcbiAgICB9LFxuICAgIHRvU3RyaW5nV2l0aFNvdXJjZU1hcDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4ge2NvZGU6IHRoaXMudG9TdHJpbmcoKX07XG4gICAgfSxcbiAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5zcmM7XG4gICAgfVxuICB9O1xufVxuXG5cbmZ1bmN0aW9uIGNhc3RDaHVuayhjaHVuaywgY29kZUdlbiwgbG9jKSB7XG4gIGlmIChpc0FycmF5KGNodW5rKSkge1xuICAgIGxldCByZXQgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBjaHVuay5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgcmV0LnB1c2goY29kZUdlbi53cmFwKGNodW5rW2ldLCBsb2MpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY2h1bmsgPT09ICdib29sZWFuJyB8fCB0eXBlb2YgY2h1bmsgPT09ICdudW1iZXInKSB7XG4gICAgLy8gSGFuZGxlIHByaW1pdGl2ZXMgdGhhdCB0aGUgU291cmNlTm9kZSB3aWxsIHRocm93IHVwIG9uXG4gICAgcmV0dXJuIGNodW5rICsgJyc7XG4gIH1cbiAgcmV0dXJuIGNodW5rO1xufVxuXG5cbmZ1bmN0aW9uIENvZGVHZW4oc3JjRmlsZSkge1xuICB0aGlzLnNyY0ZpbGUgPSBzcmNGaWxlO1xuICB0aGlzLnNvdXJjZSA9IFtdO1xufVxuXG5Db2RlR2VuLnByb3RvdHlwZSA9IHtcbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gIXRoaXMuc291cmNlLmxlbmd0aDtcbiAgfSxcbiAgcHJlcGVuZDogZnVuY3Rpb24oc291cmNlLCBsb2MpIHtcbiAgICB0aGlzLnNvdXJjZS51bnNoaWZ0KHRoaXMud3JhcChzb3VyY2UsIGxvYykpO1xuICB9LFxuICBwdXNoOiBmdW5jdGlvbihzb3VyY2UsIGxvYykge1xuICAgIHRoaXMuc291cmNlLnB1c2godGhpcy53cmFwKHNvdXJjZSwgbG9jKSk7XG4gIH0sXG5cbiAgbWVyZ2U6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBzb3VyY2UgPSB0aGlzLmVtcHR5KCk7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIHNvdXJjZS5hZGQoWycgICcsIGxpbmUsICdcXG4nXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHNvdXJjZTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbihpdGVyKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRoaXMuc291cmNlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpdGVyKHRoaXMuc291cmNlW2ldKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBsb2MgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbiB8fCB7c3RhcnQ6IHt9fTtcbiAgICByZXR1cm4gbmV3IFNvdXJjZU5vZGUobG9jLnN0YXJ0LmxpbmUsIGxvYy5zdGFydC5jb2x1bW4sIHRoaXMuc3JjRmlsZSk7XG4gIH0sXG4gIHdyYXA6IGZ1bmN0aW9uKGNodW5rLCBsb2MgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbiB8fCB7c3RhcnQ6IHt9fSkge1xuICAgIGlmIChjaHVuayBpbnN0YW5jZW9mIFNvdXJjZU5vZGUpIHtcbiAgICAgIHJldHVybiBjaHVuaztcbiAgICB9XG5cbiAgICBjaHVuayA9IGNhc3RDaHVuayhjaHVuaywgdGhpcywgbG9jKTtcblxuICAgIHJldHVybiBuZXcgU291cmNlTm9kZShsb2Muc3RhcnQubGluZSwgbG9jLnN0YXJ0LmNvbHVtbiwgdGhpcy5zcmNGaWxlLCBjaHVuayk7XG4gIH0sXG5cbiAgZnVuY3Rpb25DYWxsOiBmdW5jdGlvbihmbiwgdHlwZSwgcGFyYW1zKSB7XG4gICAgcGFyYW1zID0gdGhpcy5nZW5lcmF0ZUxpc3QocGFyYW1zKTtcbiAgICByZXR1cm4gdGhpcy53cmFwKFtmbiwgdHlwZSA/ICcuJyArIHR5cGUgKyAnKCcgOiAnKCcsIHBhcmFtcywgJyknXSk7XG4gIH0sXG5cbiAgcXVvdGVkU3RyaW5nOiBmdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gJ1wiJyArIChzdHIgKyAnJylcbiAgICAgIC5yZXBsYWNlKC9cXFxcL2csICdcXFxcXFxcXCcpXG4gICAgICAucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpXG4gICAgICAucmVwbGFjZSgvXFxuL2csICdcXFxcbicpXG4gICAgICAucmVwbGFjZSgvXFxyL2csICdcXFxccicpXG4gICAgICAucmVwbGFjZSgvXFx1MjAyOC9nLCAnXFxcXHUyMDI4JykgICAvLyBQZXIgRWNtYS0yNjIgNy4zICsgNy44LjRcbiAgICAgIC5yZXBsYWNlKC9cXHUyMDI5L2csICdcXFxcdTIwMjknKSArICdcIic7XG4gIH0sXG5cbiAgb2JqZWN0TGl0ZXJhbDogZnVuY3Rpb24ob2JqKSB7XG4gICAgbGV0IHBhaXJzID0gW107XG5cbiAgICBmb3IgKGxldCBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgbGV0IHZhbHVlID0gY2FzdENodW5rKG9ialtrZXldLCB0aGlzKTtcbiAgICAgICAgaWYgKHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHBhaXJzLnB1c2goW3RoaXMucXVvdGVkU3RyaW5nKGtleSksICc6JywgdmFsdWVdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGxldCByZXQgPSB0aGlzLmdlbmVyYXRlTGlzdChwYWlycyk7XG4gICAgcmV0LnByZXBlbmQoJ3snKTtcbiAgICByZXQuYWRkKCd9Jyk7XG4gICAgcmV0dXJuIHJldDtcbiAgfSxcblxuXG4gIGdlbmVyYXRlTGlzdDogZnVuY3Rpb24oZW50cmllcykge1xuICAgIGxldCByZXQgPSB0aGlzLmVtcHR5KCk7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gZW50cmllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgaWYgKGkpIHtcbiAgICAgICAgcmV0LmFkZCgnLCcpO1xuICAgICAgfVxuXG4gICAgICByZXQuYWRkKGNhc3RDaHVuayhlbnRyaWVzW2ldLCB0aGlzKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfSxcblxuICBnZW5lcmF0ZUFycmF5OiBmdW5jdGlvbihlbnRyaWVzKSB7XG4gICAgbGV0IHJldCA9IHRoaXMuZ2VuZXJhdGVMaXN0KGVudHJpZXMpO1xuICAgIHJldC5wcmVwZW5kKCdbJyk7XG4gICAgcmV0LmFkZCgnXScpO1xuXG4gICAgcmV0dXJuIHJldDtcbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgQ29kZUdlbjtcblxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js new file mode 100644 index 0000000..65b4585 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js @@ -0,0 +1,572 @@ +/* eslint-disable new-cap */ + +'use strict'; + +exports.__esModule = true; +exports.Compiler = Compiler; +exports.precompile = precompile; +exports.compile = compile; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _exception = require('../exception'); + +var _exception2 = _interopRequireDefault(_exception); + +var _utils = require('../utils'); + +var _ast = require('./ast'); + +var _ast2 = _interopRequireDefault(_ast); + +var slice = [].slice; + +function Compiler() {} + +// the foundHelper register will disambiguate helper lookup from finding a +// function in a context. This is necessary for mustache compatibility, which +// requires that context functions in blocks are evaluated by blockHelperMissing, +// and then proceed as if the resulting value was provided to blockHelperMissing. + +Compiler.prototype = { + compiler: Compiler, + + equals: function equals(other) { + var len = this.opcodes.length; + if (other.opcodes.length !== len) { + return false; + } + + for (var i = 0; i < len; i++) { + var opcode = this.opcodes[i], + otherOpcode = other.opcodes[i]; + if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { + return false; + } + } + + // We know that length is the same between the two arrays because they are directly tied + // to the opcode behavior above. + len = this.children.length; + for (var i = 0; i < len; i++) { + if (!this.children[i].equals(other.children[i])) { + return false; + } + } + + return true; + }, + + guid: 0, + + compile: function compile(program, options) { + this.sourceNode = []; + this.opcodes = []; + this.children = []; + this.options = options; + this.stringParams = options.stringParams; + this.trackIds = options.trackIds; + + options.blockParams = options.blockParams || []; + + // These changes will propagate to the other compiler components + var knownHelpers = options.knownHelpers; + options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true, + 'lookup': true + }; + if (knownHelpers) { + for (var _name in knownHelpers) { + /* istanbul ignore else */ + if (_name in knownHelpers) { + options.knownHelpers[_name] = knownHelpers[_name]; + } + } + } + + return this.accept(program); + }, + + compileProgram: function compileProgram(program) { + var childCompiler = new this.compiler(), + // eslint-disable-line new-cap + result = childCompiler.compile(program, this.options), + guid = this.guid++; + + this.usePartial = this.usePartial || result.usePartial; + + this.children[guid] = result; + this.useDepths = this.useDepths || result.useDepths; + + return guid; + }, + + accept: function accept(node) { + /* istanbul ignore next: Sanity code */ + if (!this[node.type]) { + throw new _exception2['default']('Unknown type: ' + node.type, node); + } + + this.sourceNode.unshift(node); + var ret = this[node.type](node); + this.sourceNode.shift(); + return ret; + }, + + Program: function Program(program) { + this.options.blockParams.unshift(program.blockParams); + + var body = program.body, + bodyLength = body.length; + for (var i = 0; i < bodyLength; i++) { + this.accept(body[i]); + } + + this.options.blockParams.shift(); + + this.isSimple = bodyLength === 1; + this.blockParams = program.blockParams ? program.blockParams.length : 0; + + return this; + }, + + BlockStatement: function BlockStatement(block) { + transformLiteralToPath(block); + + var program = block.program, + inverse = block.inverse; + + program = program && this.compileProgram(program); + inverse = inverse && this.compileProgram(inverse); + + var type = this.classifySexpr(block); + + if (type === 'helper') { + this.helperSexpr(block, program, inverse); + } else if (type === 'simple') { + this.simpleSexpr(block); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('blockValue', block.path.original); + } else { + this.ambiguousSexpr(block, program, inverse); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('ambiguousBlockValue'); + } + + this.opcode('append'); + }, + + DecoratorBlock: function DecoratorBlock(decorator) { + var program = decorator.program && this.compileProgram(decorator.program); + var params = this.setupFullMustacheParams(decorator, program, undefined), + path = decorator.path; + + this.useDecorators = true; + this.opcode('registerDecorator', params.length, path.original); + }, + + PartialStatement: function PartialStatement(partial) { + this.usePartial = true; + + var program = partial.program; + if (program) { + program = this.compileProgram(partial.program); + } + + var params = partial.params; + if (params.length > 1) { + throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial); + } else if (!params.length) { + if (this.options.explicitPartialContext) { + this.opcode('pushLiteral', 'undefined'); + } else { + params.push({ type: 'PathExpression', parts: [], depth: 0 }); + } + } + + var partialName = partial.name.original, + isDynamic = partial.name.type === 'SubExpression'; + if (isDynamic) { + this.accept(partial.name); + } + + this.setupFullMustacheParams(partial, program, undefined, true); + + var indent = partial.indent || ''; + if (this.options.preventIndent && indent) { + this.opcode('appendContent', indent); + indent = ''; + } + + this.opcode('invokePartial', isDynamic, partialName, indent); + this.opcode('append'); + }, + PartialBlockStatement: function PartialBlockStatement(partialBlock) { + this.PartialStatement(partialBlock); + }, + + MustacheStatement: function MustacheStatement(mustache) { + this.SubExpression(mustache); + + if (mustache.escaped && !this.options.noEscape) { + this.opcode('appendEscaped'); + } else { + this.opcode('append'); + } + }, + Decorator: function Decorator(decorator) { + this.DecoratorBlock(decorator); + }, + + ContentStatement: function ContentStatement(content) { + if (content.value) { + this.opcode('appendContent', content.value); + } + }, + + CommentStatement: function CommentStatement() {}, + + SubExpression: function SubExpression(sexpr) { + transformLiteralToPath(sexpr); + var type = this.classifySexpr(sexpr); + + if (type === 'simple') { + this.simpleSexpr(sexpr); + } else if (type === 'helper') { + this.helperSexpr(sexpr); + } else { + this.ambiguousSexpr(sexpr); + } + }, + ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) { + var path = sexpr.path, + name = path.parts[0], + isBlock = program != null || inverse != null; + + this.opcode('getContext', path.depth); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + path.strict = true; + this.accept(path); + + this.opcode('invokeAmbiguous', name, isBlock); + }, + + simpleSexpr: function simpleSexpr(sexpr) { + var path = sexpr.path; + path.strict = true; + this.accept(path); + this.opcode('resolvePossibleLambda'); + }, + + helperSexpr: function helperSexpr(sexpr, program, inverse) { + var params = this.setupFullMustacheParams(sexpr, program, inverse), + path = sexpr.path, + name = path.parts[0]; + + if (this.options.knownHelpers[name]) { + this.opcode('invokeKnownHelper', params.length, name); + } else if (this.options.knownHelpersOnly) { + throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); + } else { + path.strict = true; + path.falsy = true; + + this.accept(path); + this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path)); + } + }, + + PathExpression: function PathExpression(path) { + this.addDepth(path.depth); + this.opcode('getContext', path.depth); + + var name = path.parts[0], + scoped = _ast2['default'].helpers.scopedId(path), + blockParamId = !path.depth && !scoped && this.blockParamIndex(name); + + if (blockParamId) { + this.opcode('lookupBlockParam', blockParamId, path.parts); + } else if (!name) { + // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` + this.opcode('pushContext'); + } else if (path.data) { + this.options.data = true; + this.opcode('lookupData', path.depth, path.parts, path.strict); + } else { + this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); + } + }, + + StringLiteral: function StringLiteral(string) { + this.opcode('pushString', string.value); + }, + + NumberLiteral: function NumberLiteral(number) { + this.opcode('pushLiteral', number.value); + }, + + BooleanLiteral: function BooleanLiteral(bool) { + this.opcode('pushLiteral', bool.value); + }, + + UndefinedLiteral: function UndefinedLiteral() { + this.opcode('pushLiteral', 'undefined'); + }, + + NullLiteral: function NullLiteral() { + this.opcode('pushLiteral', 'null'); + }, + + Hash: function Hash(hash) { + var pairs = hash.pairs, + i = 0, + l = pairs.length; + + this.opcode('pushHash'); + + for (; i < l; i++) { + this.pushParam(pairs[i].value); + } + while (i--) { + this.opcode('assignToHash', pairs[i].key); + } + this.opcode('popHash'); + }, + + // HELPERS + opcode: function opcode(name) { + this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc }); + }, + + addDepth: function addDepth(depth) { + if (!depth) { + return; + } + + this.useDepths = true; + }, + + classifySexpr: function classifySexpr(sexpr) { + var isSimple = _ast2['default'].helpers.simpleId(sexpr.path); + + var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + var isEligible = !isBlockParam && (isHelper || isSimple); + + // if ambiguous, we can possibly resolve the ambiguity now + // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. + if (isEligible && !isHelper) { + var _name2 = sexpr.path.parts[0], + options = this.options; + + if (options.knownHelpers[_name2]) { + isHelper = true; + } else if (options.knownHelpersOnly) { + isEligible = false; + } + } + + if (isHelper) { + return 'helper'; + } else if (isEligible) { + return 'ambiguous'; + } else { + return 'simple'; + } + }, + + pushParams: function pushParams(params) { + for (var i = 0, l = params.length; i < l; i++) { + this.pushParam(params[i]); + } + }, + + pushParam: function pushParam(val) { + var value = val.value != null ? val.value : val.original || ''; + + if (this.stringParams) { + if (value.replace) { + value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.'); + } + + if (val.depth) { + this.addDepth(val.depth); + } + this.opcode('getContext', val.depth || 0); + this.opcode('pushStringParam', value, val.type); + + if (val.type === 'SubExpression') { + // SubExpressions get evaluated and passed in + // in string params mode. + this.accept(val); + } + } else { + if (this.trackIds) { + var blockParamIndex = undefined; + if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) { + blockParamIndex = this.blockParamIndex(val.parts[0]); + } + if (blockParamIndex) { + var blockParamChild = val.parts.slice(1).join('.'); + this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); + } else { + value = val.original || value; + if (value.replace) { + value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, ''); + } + + this.opcode('pushId', val.type, value); + } + } + this.accept(val); + } + }, + + setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) { + var params = sexpr.params; + this.pushParams(params); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + if (sexpr.hash) { + this.accept(sexpr.hash); + } else { + this.opcode('emptyHash', omitEmpty); + } + + return params; + }, + + blockParamIndex: function blockParamIndex(name) { + for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { + var blockParams = this.options.blockParams[depth], + param = blockParams && _utils.indexOf(blockParams, name); + if (blockParams && param >= 0) { + return [depth, param]; + } + } + } +}; + +function precompile(input, options, env) { + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); + } + + options = options || {}; + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options); + return new env.JavaScriptCompiler().compile(environment, options); +} + +function compile(input, options, env) { + if (options === undefined) options = {}; + + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); + } + + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var compiled = undefined; + + function compileInput() { + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options), + templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); + return env.template(templateSpec); + } + + // Template is only compiled on first use and cached after that point. + function ret(context, execOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled.call(this, context, execOptions); + } + ret._setup = function (setupOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._setup(setupOptions); + }; + ret._child = function (i, data, blockParams, depths) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._child(i, data, blockParams, depths); + }; + return ret; +} + +function argEquals(a, b) { + if (a === b) { + return true; + } + + if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) { + for (var i = 0; i < a.length; i++) { + if (!argEquals(a[i], b[i])) { + return false; + } + } + return true; + } +} + +function transformLiteralToPath(sexpr) { + if (!sexpr.path.parts) { + var literal = sexpr.path; + // Casting to string here to make false and 0 literal values play nicely with the rest + // of the system. + sexpr.path = { + type: 'PathExpression', + data: false, + depth: 0, + parts: [literal.original + ''], + original: literal.original + '', + loc: literal.loc + }; + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvbXBpbGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozt5QkFFc0IsY0FBYzs7OztxQkFDTCxVQUFVOzttQkFDekIsT0FBTzs7OztBQUV2QixJQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDOztBQUVoQixTQUFTLFFBQVEsR0FBRyxFQUFFOzs7Ozs7O0FBTzdCLFFBQVEsQ0FBQyxTQUFTLEdBQUc7QUFDbkIsVUFBUSxFQUFFLFFBQVE7O0FBRWxCLFFBQU0sRUFBRSxnQkFBUyxLQUFLLEVBQUU7QUFDdEIsUUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7QUFDOUIsUUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sS0FBSyxHQUFHLEVBQUU7QUFDaEMsYUFBTyxLQUFLLENBQUM7S0FDZDs7QUFFRCxTQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQzVCLFVBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1VBQ3hCLFdBQVcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ25DLFVBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxXQUFXLENBQUMsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxFQUFFO0FBQ3JGLGVBQU8sS0FBSyxDQUFDO09BQ2Q7S0FDRjs7OztBQUlELE9BQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztBQUMzQixTQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQzVCLFVBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxD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QUU7QUFDckQsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDakMsVUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7QUFDMUIsZUFBTyxLQUFLLENBQUM7T0FDZDtLQUNGO0FBQ0QsV0FBTyxJQUFJLENBQUM7R0FDYjtDQUNGOztBQUVELFNBQVMsc0JBQXNCLENBQUMsS0FBSyxFQUFFO0FBQ3JDLE1BQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRTtBQUNyQixRQUFJLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDOzs7QUFHekIsU0FBSyxDQUFDLElBQUksR0FBRztBQUNYLFVBQUksRUFBRSxnQkFBZ0I7QUFDdEIsVUFBSSxFQUFFLEtBQUs7QUFDWCxXQUFLLEVBQUUsQ0FBQztBQUNSLFdBQUssRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQzlCLGNBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxHQUFHLEVBQUU7QUFDL0IsU0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO0tBQ2pCLENBQUM7R0FDSDtDQUNGIiwiZmlsZSI6ImNvbXBpbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbmV3LWNhcCAqL1xuXG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5pbXBvcnQge2lzQXJyYXksIGluZGV4T2Z9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCBBU1QgZnJvbSAnLi9hc3QnO1xuXG5jb25zdCBzbGljZSA9IFtdLnNsaWNlO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcGlsZXIoKSB7fVxuXG4vLyB0aGUgZm91bmRIZWxwZXIgcmVnaXN0ZXIgd2lsbCBkaXNhbWJpZ3VhdGUgaGVscGVyIGxvb2t1cCBmcm9tIGZpbmRpbmcgYVxuLy8gZnVuY3Rpb24gaW4gYSBjb250ZXh0LiBUaGlzIGlzIG5lY2Vzc2FyeSBmb3IgbXVzdGFjaGUgY29tcGF0aWJpbGl0eSwgd2hpY2hcbi8vIHJlcXVpcmVzIHRoYXQgY29udGV4dCBmdW5jdGlvbnMgaW4gYmxvY2tzIGFyZSBldmFsdWF0ZWQgYnkgYmxvY2tIZWxwZXJNaXNzaW5nLFxuLy8gYW5kIHRoZW4gcHJvY2VlZCBhcyBpZiB0aGUgcmVzdWx0aW5nIHZhbHVlIHdhcyBwcm92aWRlZCB0byBibG9ja0hlbHBlck1pc3NpbmcuXG5cbkNvbXBpbGVyLnByb3RvdHlwZSA9IHtcbiAgY29tcGlsZXI6IENvbXBpbGVyLFxuXG4gIGVxdWFsczogZnVuY3Rpb24ob3RoZXIpIHtcbiAgICBsZXQgbGVuID0gdGhpcy5vcGNvZGVzLmxlbmd0aDtcbiAgICBpZiAob3RoZXIub3Bjb2Rlcy5sZW5ndGggIT09IGxlbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGxldCBvcGNvZGUgPSB0aGlzLm9wY29kZXNbaV0sXG4gICAgICAgICAgb3RoZXJPcGNvZGUgPSBvdGhlci5vcGNvZGVzW2ldO1xuICAgICAgaWYgKG9wY29kZS5vcGNvZGUgIT09IG90aGVyT3Bjb2RlLm9wY29kZSB8fCAhYXJnRXF1YWxzKG9wY29kZS5hcmdzLCBvdGhlck9wY29kZS5hcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gV2Uga25vdyB0aGF0IGxlbmd0aCBpcyB0aGUgc2FtZSBiZXR3ZWVuIHRoZSB0d28gYXJyYXlzIGJlY2F1c2UgdGhleSBhcmUgZGlyZWN0bHkgdGllZFxuICAgIC8vIHRvIHRoZSBvcGNvZGUgYmVoYXZpb3IgYWJvdmUuXG4gICAgbGVuID0gdGhpcy5jaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgaWYgKCF0aGlzLmNoaWxkcmVuW2ldLmVxdWFscyhvdGhlci5jaGlsZHJlbltpXSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGd1aWQ6IDAsXG5cbiAgY29tcGlsZTogZnVuY3Rpb24ocHJvZ3JhbSwgb3B0aW9ucykge1xuICAgIHRoaXMuc291cmNlTm9kZSA9IFtdO1xuICAgIHRoaXMub3Bjb2RlcyA9IFtdO1xuICAgIHRoaXMuY2hpbGRyZW4gPSBbXTtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMuc3RyaW5nUGFyYW1zID0gb3B0aW9ucy5zdHJpbmdQYXJhbXM7XG4gICAgdGhpcy50cmFja0lkcyA9IG9wdGlvbnMudHJhY2tJZHM7XG5cbiAgICBvcHRpb25zLmJsb2NrUGFyYW1zID0gb3B0aW9ucy5ibG9ja1BhcmFtcyB8fCBbXTtcblxuICAgIC8vIFRoZXNlIGNoYW5nZXMgd2lsbCBwcm9wYWdhdGUgdG8gdGhlIG90aGVyIGNvbXBpbGVyIGNvbXBvbmVudHNcbiAgICBsZXQga25vd25IZWxwZXJzID0gb3B0aW9ucy5rbm93bkhlbHBlcnM7XG4gICAgb3B0aW9ucy5rbm93bkhlbHBlcnMgPSB7XG4gICAgICAnaGVscGVyTWlzc2luZyc6IHRydWUsXG4gICAgICAnYmxvY2tIZWxwZXJNaXNzaW5nJzogdHJ1ZSxcbiAgICAgICdlYWNoJzogdHJ1ZSxcbiAgICAgICdpZic6IHRydWUsXG4gICAgICAndW5sZXNzJzogdHJ1ZSxcbiAgICAgICd3aXRoJzogdHJ1ZSxcbiAgICAgICdsb2cnOiB0cnVlLFxuICAgICAgJ2xvb2t1cCc6IHRydWVcbiAgICB9O1xuICAgIGlmIChrbm93bkhlbHBlcnMpIHtcbiAgICAgIGZvciAobGV0IG5hbWUgaW4ga25vd25IZWxwZXJzKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgIGlmIChuYW1lIGluIGtub3duSGVscGVycykge1xuICAgICAgICAgIG9wdGlvbnMua25vd25IZWxwZXJzW25hbWVdID0ga25vd25IZWxwZXJzW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYWNjZXB0KHByb2dyYW0pO1xuICB9LFxuXG4gIGNvbXBpbGVQcm9ncmFtOiBmdW5jdGlvbihwcm9ncmFtKSB7XG4gICAgbGV0IGNoaWxkQ29tcGlsZXIgPSBuZXcgdGhpcy5jb21waWxlcigpLCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5ldy1jYXBcbiAgICAgICAgcmVzdWx0ID0gY2hpbGRDb21waWxlci5jb21waWxlKHByb2dyYW0sIHRoaXMub3B0aW9ucyksXG4gICAgICAgIGd1aWQgPSB0aGlzLmd1aWQrKztcblxuICAgIHRoaXMudXNlUGFydGlhbCA9IHRoaXMudXNlUGFydGlhbCB8fCByZXN1bHQudXNlUGFydGlhbDtcblxuICAgIHRoaXMuY2hpbGRyZW5bZ3VpZF0gPSByZXN1bHQ7XG4gICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCByZXN1bHQudXNlRGVwdGhzO1xuXG4gICAgcmV0dXJuIGd1aWQ7XG4gIH0sXG5cbiAgYWNjZXB0OiBmdW5jdGlvbihub2RlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IFNhbml0eSBjb2RlICovXG4gICAgaWYgKCF0aGlzW25vZGUudHlwZV0pIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdHlwZTogJyArIG5vZGUudHlwZSwgbm9kZSk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VOb2RlLnVuc2hpZnQobm9kZSk7XG4gICAgbGV0IHJldCA9IHRoaXNbbm9kZS50eXBlXShub2RlKTtcbiAgICB0aGlzLnNvdXJjZU5vZGUuc2hpZnQoKTtcbiAgICByZXR1cm4gcmV0O1xuICB9LFxuXG4gIFByb2dyYW06IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgICB0aGlzLm9wdGlvbnMuYmxvY2tQYXJhbXMudW5zaGlmdChwcm9ncmFtLmJsb2NrUGFyYW1zKTtcblxuICAgIGxldCBib2R5ID0gcHJvZ3JhbS5ib2R5LFxuICAgICAgICBib2R5TGVuZ3RoID0gYm9keS5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBib2R5TGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuYWNjZXB0KGJvZHlbaV0pO1xuICAgIH1cblxuICAgIHRoaXMub3B0aW9ucy5ibG9ja1BhcmFtcy5zaGlmdCgpO1xuXG4gICAgdGhpcy5pc1NpbXBsZSA9IGJvZHlMZW5ndGggPT09IDE7XG4gICAgdGhpcy5ibG9ja1BhcmFtcyA9IHByb2dyYW0uYmxvY2tQYXJhbXMgPyBwcm9ncmFtLmJsb2NrUGFyYW1zLmxlbmd0aCA6IDA7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBCbG9ja1N0YXRlbWVudDogZnVuY3Rpb24oYmxvY2spIHtcbiAgICB0cmFuc2Zvcm1MaXRlcmFsVG9QYXRoKGJsb2NrKTtcblxuICAgIGxldCBwcm9ncmFtID0gYmxvY2sucHJvZ3JhbSxcbiAgICAgICAgaW52ZXJzZSA9IGJsb2NrLmludmVyc2U7XG5cbiAgICBwcm9ncmFtID0gcHJvZ3JhbSAmJiB0aGlzLmNvbXBpbGVQcm9ncmFtKHByb2dyYW0pO1xuICAgIGludmVyc2UgPSBpbnZlcnNlICYmIHRoaXMuY29tcGlsZVByb2dyYW0oaW52ZXJzZSk7XG5cbiAgICBsZXQgdHlwZSA9IHRoaXMuY2xhc3NpZnlTZXhwcihibG9jayk7XG5cbiAgICBpZiAodHlwZSA9PT0gJ2hlbHBlcicpIHtcbiAgICAgIHRoaXMuaGVscGVyU2V4cHIoYmxvY2ssIHByb2dyYW0sIGludmVyc2UpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3NpbXBsZScpIHtcbiAgICAgIHRoaXMuc2ltcGxlU2V4cHIoYmxvY2spO1xuXG4gICAgICAvLyBub3cgdGhhdCB0aGUgc2ltcGxlIG11c3RhY2hlIGlzIHJlc29sdmVkLCB3ZSBuZWVkIHRvXG4gICAgICAvLyBldmFsdWF0ZSBpdCBieSBleGVjdXRpbmcgYGJsb2NrSGVscGVyTWlzc2luZ2BcbiAgICAgIHRoaXMub3Bjb2RlKCdwdXNoUHJvZ3JhbScsIHByb2dyYW0pO1xuICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgaW52ZXJzZSk7XG4gICAgICB0aGlzLm9wY29kZSgnZW1wdHlIYXNoJyk7XG4gICAgICB0aGlzLm9wY29kZSgnYmxvY2tWYWx1ZScsIGJsb2NrLnBhdGgub3JpZ2luYWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFtYmlndW91c1NleHByKGJsb2NrLCBwcm9ncmFtLCBpbnZlcnNlKTtcblxuICAgICAgLy8gbm93IHRoYXQgdGhlIHNpbXBsZSBtdXN0YWNoZSBpcyByZXNvbHZlZCwgd2UgbmVlZCB0b1xuICAgICAgLy8gZXZhbHVhdGUgaXQgYnkgZXhlY3V0aW5nIGBibG9ja0hlbHBlck1pc3NpbmdgXG4gICAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBwcm9ncmFtKTtcbiAgICAgIHRoaXMub3Bjb2RlKCdwdXNoUHJvZ3JhbScsIGludmVyc2UpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2VtcHR5SGFzaCcpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2FtYmlndW91c0Jsb2NrVmFsdWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLm9wY29kZSgnYXBwZW5kJyk7XG4gIH0sXG5cbiAgRGVjb3JhdG9yQmxvY2soZGVjb3JhdG9yKSB7XG4gICAgbGV0IHByb2dyYW0gPSBkZWNvcmF0b3IucHJvZ3JhbSAmJiB0aGlzLmNvbXBpbGVQcm9ncmFtKGRlY29yYXRvci5wcm9ncmFtKTtcbiAgICBsZXQgcGFyYW1zID0gdGhpcy5zZXR1cEZ1bGxNdXN0YWNoZVBhcmFtcyhkZWNvcmF0b3IsIHByb2dyYW0sIHVuZGVmaW5lZCksXG4gICAgICAgIHBhdGggPSBkZWNvcmF0b3IucGF0aDtcblxuICAgIHRoaXMudXNlRGVjb3JhdG9ycyA9IHRydWU7XG4gICAgdGhpcy5vcGNvZGUoJ3JlZ2lzdGVyRGVjb3JhdG9yJywgcGFyYW1zLmxlbmd0aCwgcGF0aC5vcmlnaW5hbCk7XG4gIH0sXG5cbiAgUGFydGlhbFN0YXRlbWVudDogZnVuY3Rpb24ocGFydGlhbCkge1xuICAgIHRoaXMudXNlUGFydGlhbCA9IHRydWU7XG5cbiAgICBsZXQgcHJvZ3JhbSA9IHBhcnRpYWwucHJvZ3JhbTtcbiAgICBpZiAocHJvZ3JhbSkge1xuICAgICAgcHJvZ3JhbSA9IHRoaXMuY29tcGlsZVByb2dyYW0ocGFydGlhbC5wcm9ncmFtKTtcbiAgICB9XG5cbiAgICBsZXQgcGFyYW1zID0gcGFydGlhbC5wYXJhbXM7XG4gICAgaWYgKHBhcmFtcy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdVbnN1cHBvcnRlZCBudW1iZXIgb2YgcGFydGlhbCBhcmd1bWVudHM6ICcgKyBwYXJhbXMubGVuZ3RoLCBwYXJ0aWFsKTtcbiAgICB9IGVsc2UgaWYgKCFwYXJhbXMubGVuZ3RoKSB7XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmV4cGxpY2l0UGFydGlhbENvbnRleHQpIHtcbiAgICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgJ3VuZGVmaW5lZCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zLnB1c2goe3R5cGU6ICdQYXRoRXhwcmVzc2lvbicsIHBhcnRzOiBbXSwgZGVwdGg6IDB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgcGFydGlhbE5hbWUgPSBwYXJ0aWFsLm5hbWUub3JpZ2luYWwsXG4gICAgICAgIGlzRHluYW1pYyA9IHBhcnRpYWwubmFtZS50eXBlID09PSAnU3ViRXhwcmVzc2lvbic7XG4gICAgaWYgKGlzRHluYW1pYykge1xuICAgICAgdGhpcy5hY2NlcHQocGFydGlhbC5uYW1lKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldHVwRnVsbE11c3RhY2hlUGFyYW1zKHBhcnRpYWwsIHByb2dyYW0sIHVuZGVmaW5lZCwgdHJ1ZSk7XG5cbiAgICBsZXQgaW5kZW50ID0gcGFydGlhbC5pbmRlbnQgfHwgJyc7XG4gICAgaWYgKHRoaXMub3B0aW9ucy5wcmV2ZW50SW5kZW50ICYmIGluZGVudCkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZENvbnRlbnQnLCBpbmRlbnQpO1xuICAgICAgaW5kZW50ID0gJyc7XG4gICAgfVxuXG4gICAgdGhpcy5vcGNvZGUoJ2ludm9rZVBhcnRpYWwnLCBpc0R5bmFtaWMsIHBhcnRpYWxOYW1lLCBpbmRlbnQpO1xuICAgIHRoaXMub3Bjb2RlKCdhcHBlbmQnKTtcbiAgfSxcbiAgUGFydGlhbEJsb2NrU3RhdGVtZW50OiBmdW5jdGlvbihwYXJ0aWFsQmxvY2spIHtcbiAgICB0aGlzLlBhcnRpYWxTdGF0ZW1lbnQocGFydGlhbEJsb2NrKTtcbiAgfSxcblxuICBNdXN0YWNoZVN0YXRlbWVudDogZnVuY3Rpb24obXVzdGFjaGUpIHtcbiAgICB0aGlzLlN1YkV4cHJlc3Npb24obXVzdGFjaGUpO1xuXG4gICAgaWYgKG11c3RhY2hlLmVzY2FwZWQgJiYgIXRoaXMub3B0aW9ucy5ub0VzY2FwZSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZEVzY2FwZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZCcpO1xuICAgIH1cbiAgfSxcbiAgRGVjb3JhdG9yKGRlY29yYXRvcikge1xuICAgIHRoaXMuRGVjb3JhdG9yQmxvY2soZGVjb3JhdG9yKTtcbiAgfSxcblxuXG4gIENvbnRlbnRTdGF0ZW1lbnQ6IGZ1bmN0aW9uKGNvbnRlbnQpIHtcbiAgICBpZiAoY29udGVudC52YWx1ZSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZENvbnRlbnQnLCBjb250ZW50LnZhbHVlKTtcbiAgICB9XG4gIH0sXG5cbiAgQ29tbWVudFN0YXRlbWVudDogZnVuY3Rpb24oKSB7fSxcblxuICBTdWJFeHByZXNzaW9uOiBmdW5jdGlvbihzZXhwcikge1xuICAgIHRyYW5zZm9ybUxpdGVyYWxUb1BhdGgoc2V4cHIpO1xuICAgIGxldCB0eXBlID0gdGhpcy5jbGFzc2lmeVNleHByKHNleHByKTtcblxuICAgIGlmICh0eXBlID09PSAnc2ltcGxlJykge1xuICAgICAgdGhpcy5zaW1wbGVTZXhwcihzZXhwcik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnaGVscGVyJykge1xuICAgICAgdGhpcy5oZWxwZXJTZXhwcihzZXhwcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYW1iaWd1b3VzU2V4cHIoc2V4cHIpO1xuICAgIH1cbiAgfSxcbiAgYW1iaWd1b3VzU2V4cHI6IGZ1bmN0aW9uKHNleHByLCBwcm9ncmFtLCBpbnZlcnNlKSB7XG4gICAgbGV0IHBhdGggPSBzZXhwci5wYXRoLFxuICAgICAgICBuYW1lID0gcGF0aC5wYXJ0c1swXSxcbiAgICAgICAgaXNCbG9jayA9IHByb2dyYW0gIT0gbnVsbCB8fCBpbnZlcnNlICE9IG51bGw7XG5cbiAgICB0aGlzLm9wY29kZSgnZ2V0Q29udGV4dCcsIHBhdGguZGVwdGgpO1xuXG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgcHJvZ3JhbSk7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgaW52ZXJzZSk7XG5cbiAgICBwYXRoLnN0cmljdCA9IHRydWU7XG4gICAgdGhpcy5hY2NlcHQocGF0aCk7XG5cbiAgICB0aGlzLm9wY29kZSgnaW52b2tlQW1iaWd1b3VzJywgbmFtZSwgaXNCbG9jayk7XG4gIH0sXG5cbiAgc2ltcGxlU2V4cHI6IGZ1bmN0aW9uKHNleHByKSB7XG4gICAgbGV0IHBhdGggPSBzZXhwci5wYXRoO1xuICAgIHBhdGguc3RyaWN0ID0gdHJ1ZTtcbiAgICB0aGlzLmFjY2VwdChwYXRoKTtcbiAgICB0aGlzLm9wY29kZSgncmVzb2x2ZVBvc3NpYmxlTGFtYmRhJyk7XG4gIH0sXG5cbiAgaGVscGVyU2V4cHI6IGZ1bmN0aW9uKHNleHByLCBwcm9ncmFtLCBpbnZlcnNlKSB7XG4gICAgbGV0IHBhcmFtcyA9IHRoaXMuc2V0dXBGdWxsTXVzdGFjaGVQYXJhbXMoc2V4cHIsIHByb2dyYW0sIGludmVyc2UpLFxuICAgICAgICBwYXRoID0gc2V4cHIucGF0aCxcbiAgICAgICAgbmFtZSA9IHBhdGgucGFydHNbMF07XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmtub3duSGVscGVyc1tuYW1lXSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2ludm9rZUtub3duSGVscGVyJywgcGFyYW1zLmxlbmd0aCwgbmFtZSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMua25vd25IZWxwZXJzT25seSkge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignWW91IHNwZWNpZmllZCBrbm93bkhlbHBlcnNPbmx5LCBidXQgdXNlZCB0aGUgdW5rbm93biBoZWxwZXIgJyArIG5hbWUsIHNleHByKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0aC5zdHJpY3QgPSB0cnVlO1xuICAgICAgcGF0aC5mYWxzeSA9IHRydWU7XG5cbiAgICAgIHRoaXMuYWNjZXB0KHBhdGgpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2ludm9rZUhlbHBlcicsIHBhcmFtcy5sZW5ndGgsIHBhdGgub3JpZ2luYWwsIEFTVC5oZWxwZXJzLnNpbXBsZUlkKHBhdGgpKTtcbiAgICB9XG4gIH0sXG5cbiAgUGF0aEV4cHJlc3Npb246IGZ1bmN0aW9uKHBhdGgpIHtcbiAgICB0aGlzLmFkZERlcHRoKHBhdGguZGVwdGgpO1xuICAgIHRoaXMub3Bjb2RlKCdnZXRDb250ZXh0JywgcGF0aC5kZXB0aCk7XG5cbiAgICBsZXQgbmFtZSA9IHBhdGgucGFydHNbMF0sXG4gICAgICAgIHNjb3BlZCA9IEFTVC5oZWxwZXJzLnNjb3BlZElkKHBhdGgpLFxuICAgICAgICBibG9ja1BhcmFtSWQgPSAhcGF0aC5kZXB0aCAmJiAhc2NvcGVkICYmIHRoaXMuYmxvY2tQYXJhbUluZGV4KG5hbWUpO1xuXG4gICAgaWYgKGJsb2NrUGFyYW1JZCkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2xvb2t1cEJsb2NrUGFyYW0nLCBibG9ja1BhcmFtSWQsIHBhdGgucGFydHMpO1xuICAgIH0gZWxzZSBpZiAoIW5hbWUpIHtcbiAgICAgIC8vIENvbnRleHQgcmVmZXJlbmNlLCBpLmUuIGB7e2ZvbyAufX1gIG9yIGB7e2ZvbyAuLn19YFxuICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hDb250ZXh0Jyk7XG4gICAgfSBlbHNlIGlmIChwYXRoLmRhdGEpIHtcbiAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gdHJ1ZTtcbiAgICAgIHRoaXMub3Bjb2RlKCdsb29rdXBEYXRhJywgcGF0aC5kZXB0aCwgcGF0aC5wYXJ0cywgcGF0aC5zdHJpY3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm9wY29kZSgnbG9va3VwT25Db250ZXh0JywgcGF0aC5wYXJ0cywgcGF0aC5mYWxzeSwgcGF0aC5zdHJpY3QsIHNjb3BlZCk7XG4gICAgfVxuICB9LFxuXG4gIFN0cmluZ0xpdGVyYWw6IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHRoaXMub3Bjb2RlKCdwdXNoU3RyaW5nJywgc3RyaW5nLnZhbHVlKTtcbiAgfSxcblxuICBOdW1iZXJMaXRlcmFsOiBmdW5jdGlvbihudW1iZXIpIHtcbiAgICB0aGlzLm9wY29kZSgncHVzaExpdGVyYWwnLCBudW1iZXIudmFsdWUpO1xuICB9LFxuXG4gIEJvb2xlYW5MaXRlcmFsOiBmdW5jdGlvbihib29sKSB7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgYm9vbC52YWx1ZSk7XG4gIH0sXG5cbiAgVW5kZWZpbmVkTGl0ZXJhbDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgJ3VuZGVmaW5lZCcpO1xuICB9LFxuXG4gIE51bGxMaXRlcmFsOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLm9wY29kZSgncHVzaExpdGVyYWwnLCAnbnVsbCcpO1xuICB9LFxuXG4gIEhhc2g6IGZ1bmN0aW9uKGhhc2gpIHtcbiAgICBsZXQgcGFpcnMgPSBoYXNoLnBhaXJzLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbCA9IHBhaXJzLmxlbmd0aDtcblxuICAgIHRoaXMub3Bjb2RlKCdwdXNoSGFzaCcpO1xuXG4gICAgZm9yICg7IGkgPCBsOyBpKyspIHtcbiAgICAgIHRoaXMucHVzaFBhcmFtKHBhaXJzW2ldLnZhbHVlKTtcbiAgICB9XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2Fzc2lnblRvSGFzaCcsIHBhaXJzW2ldLmtleSk7XG4gICAgfVxuICAgIHRoaXMub3Bjb2RlKCdwb3BIYXNoJyk7XG4gIH0sXG5cbiAgLy8gSEVMUEVSU1xuICBvcGNvZGU6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB0aGlzLm9wY29kZXMucHVzaCh7IG9wY29kZTogbmFtZSwgYXJnczogc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLCBsb2M6IHRoaXMuc291cmNlTm9kZVswXS5sb2MgfSk7XG4gIH0sXG5cbiAgYWRkRGVwdGg6IGZ1bmN0aW9uKGRlcHRoKSB7XG4gICAgaWYgKCFkZXB0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudXNlRGVwdGhzID0gdHJ1ZTtcbiAgfSxcblxuICBjbGFzc2lmeVNleHByOiBmdW5jdGlvbihzZXhwcikge1xuICAgIGxldCBpc1NpbXBsZSA9IEFTVC5oZWxwZXJzLnNpbXBsZUlkKHNleHByLnBhdGgpO1xuXG4gICAgbGV0IGlzQmxvY2tQYXJhbSA9IGlzU2ltcGxlICYmICEhdGhpcy5ibG9ja1BhcmFtSW5kZXgoc2V4cHIucGF0aC5wYXJ0c1swXSk7XG5cbiAgICAvLyBhIG11c3RhY2hlIGlzIGFuIGVsaWdpYmxlIGhlbHBlciBpZjpcbiAgICAvLyAqIGl0cyBpZCBpcyBzaW1wbGUgKGEgc2luZ2xlIHBhcnQsIG5vdCBgdGhpc2Agb3IgYC4uYClcbiAgICBsZXQgaXNIZWxwZXIgPSAhaXNCbG9ja1BhcmFtICYmIEFTVC5oZWxwZXJzLmhlbHBlckV4cHJlc3Npb24oc2V4cHIpO1xuXG4gICAgLy8gaWYgYSBtdXN0YWNoZSBpcyBhbiBlbGlnaWJsZSBoZWxwZXIgYnV0IG5vdCBhIGRlZmluaXRlXG4gICAgLy8gaGVscGVyLCBpdCBpcyBhbWJpZ3VvdXMsIGFuZCB3aWxsIGJlIHJlc29sdmVkIGluIGEgbGF0ZXJcbiAgICAvLyBwYXNzIG9yIGF0IHJ1bnRpbWUuXG4gICAgbGV0IGlzRWxpZ2libGUgPSAhaXNCbG9ja1BhcmFtICYmIChpc0hlbHBlciB8fCBpc1NpbXBsZSk7XG5cbiAgICAvLyBpZiBhbWJpZ3VvdXMsIHdlIGNhbiBwb3NzaWJseSByZXNvbHZlIHRoZSBhbWJpZ3VpdHkgbm93XG4gICAgLy8gQW4gZWxpZ2libGUgaGVscGVyIGlzIG9uZSB0aGF0IGRvZXMgbm90IGhhdmUgYSBjb21wbGV4IHBhdGgsIGkuZS4gYHRoaXMuZm9vYCwgYC4uL2Zvb2AgZXRjLlxuICAgIGlmIChpc0VsaWdpYmxlICYmICFpc0hlbHBlcikge1xuICAgICAgbGV0IG5hbWUgPSBzZXhwci5wYXRoLnBhcnRzWzBdLFxuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgICAgIGlmIChvcHRpb25zLmtub3duSGVscGVyc1tuYW1lXSkge1xuICAgICAgICBpc0hlbHBlciA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnMua25vd25IZWxwZXJzT25seSkge1xuICAgICAgICBpc0VsaWdpYmxlID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzSGVscGVyKSB7XG4gICAgICByZXR1cm4gJ2hlbHBlcic7XG4gICAgfSBlbHNlIGlmIChpc0VsaWdpYmxlKSB7XG4gICAgICByZXR1cm4gJ2FtYmlndW91cyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnc2ltcGxlJztcbiAgICB9XG4gIH0sXG5cbiAgcHVzaFBhcmFtczogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBwYXJhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICB0aGlzLnB1c2hQYXJhbShwYXJhbXNbaV0pO1xuICAgIH1cbiAgfSxcblxuICBwdXNoUGFyYW06IGZ1bmN0aW9uKHZhbCkge1xuICAgIGxldCB2YWx1ZSA9IHZhbC52YWx1ZSAhPSBudWxsID8gdmFsLnZhbHVlIDogdmFsLm9yaWdpbmFsIHx8ICcnO1xuXG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICBpZiAodmFsdWUucmVwbGFjZSkge1xuICAgICAgICB2YWx1ZSA9IHZhbHVlXG4gICAgICAgICAgICAucmVwbGFjZSgvXihcXC4/XFwuXFwvKSovZywgJycpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFwvL2csICcuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh2YWwuZGVwdGgpIHtcbiAgICAgICAgdGhpcy5hZGREZXB0aCh2YWwuZGVwdGgpO1xuICAgICAgfVxuICAgICAgdGhpcy5vcGNvZGUoJ2dldENvbnRleHQnLCB2YWwuZGVwdGggfHwgMCk7XG4gICAgICB0aGlzLm9wY29kZSgncHVzaFN0cmluZ1BhcmFtJywgdmFsdWUsIHZhbC50eXBlKTtcblxuICAgICAgaWYgKHZhbC50eXBlID09PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgICAgLy8gU3ViRXhwcmVzc2lvbnMgZ2V0IGV2YWx1YXRlZCBhbmQgcGFzc2VkIGluXG4gICAgICAgIC8vIGluIHN0cmluZyBwYXJhbXMgbW9kZS5cbiAgICAgICAgdGhpcy5hY2NlcHQodmFsKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgICAgbGV0IGJsb2NrUGFyYW1JbmRleDtcbiAgICAgICAgaWYgKHZhbC5wYXJ0cyAmJiAhQVNULmhlbHBlcnMuc2NvcGVkSWQodmFsKSAmJiAhdmFsLmRlcHRoKSB7XG4gICAgICAgICAgIGJsb2NrUGFyYW1JbmRleCA9IHRoaXMuYmxvY2tQYXJhbUluZGV4KHZhbC5wYXJ0c1swXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJsb2NrUGFyYW1JbmRleCkge1xuICAgICAgICAgIGxldCBibG9ja1BhcmFtQ2hpbGQgPSB2YWwucGFydHMuc2xpY2UoMSkuam9pbignLicpO1xuICAgICAgICAgIHRoaXMub3Bjb2RlKCdwdXNoSWQnLCAnQmxvY2tQYXJhbScsIGJsb2NrUGFyYW1JbmRleCwgYmxvY2tQYXJhbUNoaWxkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWx1ZSA9IHZhbC5vcmlnaW5hbCB8fCB2YWx1ZTtcbiAgICAgICAgICBpZiAodmFsdWUucmVwbGFjZSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9edGhpcyg/OlxcLnwkKS8sICcnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9eXFwuXFwvLywgJycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL15cXC4kLywgJycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMub3Bjb2RlKCdwdXNoSWQnLCB2YWwudHlwZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmFjY2VwdCh2YWwpO1xuICAgIH1cbiAgfSxcblxuICBzZXR1cEZ1bGxNdXN0YWNoZVBhcmFtczogZnVuY3Rpb24oc2V4cHIsIHByb2dyYW0sIGludmVyc2UsIG9taXRFbXB0eSkge1xuICAgIGxldCBwYXJhbXMgPSBzZXhwci5wYXJhbXM7XG4gICAgdGhpcy5wdXNoUGFyYW1zKHBhcmFtcyk7XG5cbiAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBwcm9ncmFtKTtcbiAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBpbnZlcnNlKTtcblxuICAgIGlmIChzZXhwci5oYXNoKSB7XG4gICAgICB0aGlzLmFjY2VwdChzZXhwci5oYXNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGNvZGUoJ2VtcHR5SGFzaCcsIG9taXRFbXB0eSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmFtcztcbiAgfSxcblxuICBibG9ja1BhcmFtSW5kZXg6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBmb3IgKGxldCBkZXB0aCA9IDAsIGxlbiA9IHRoaXMub3B0aW9ucy5ibG9ja1BhcmFtcy5sZW5ndGg7IGRlcHRoIDwgbGVuOyBkZXB0aCsrKSB7XG4gICAgICBsZXQgYmxvY2tQYXJhbXMgPSB0aGlzLm9wdGlvbnMuYmxvY2tQYXJhbXNbZGVwdGhdLFxuICAgICAgICAgIHBhcmFtID0gYmxvY2tQYXJhbXMgJiYgaW5kZXhPZihibG9ja1BhcmFtcywgbmFtZSk7XG4gICAgICBpZiAoYmxvY2tQYXJhbXMgJiYgcGFyYW0gPj0gMCkge1xuICAgICAgICByZXR1cm4gW2RlcHRoLCBwYXJhbV07XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gcHJlY29tcGlsZShpbnB1dCwgb3B0aW9ucywgZW52KSB7XG4gIGlmIChpbnB1dCA9PSBudWxsIHx8ICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnICYmIGlucHV0LnR5cGUgIT09ICdQcm9ncmFtJykpIHtcbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdZb3UgbXVzdCBwYXNzIGEgc3RyaW5nIG9yIEhhbmRsZWJhcnMgQVNUIHRvIEhhbmRsZWJhcnMucHJlY29tcGlsZS4gWW91IHBhc3NlZCAnICsgaW5wdXQpO1xuICB9XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGlmICghKCdkYXRhJyBpbiBvcHRpb25zKSkge1xuICAgIG9wdGlvbnMuZGF0YSA9IHRydWU7XG4gIH1cbiAgaWYgKG9wdGlvbnMuY29tcGF0KSB7XG4gICAgb3B0aW9ucy51c2VEZXB0aHMgPSB0cnVlO1xuICB9XG5cbiAgbGV0IGFzdCA9IGVudi5wYXJzZShpbnB1dCwgb3B0aW9ucyksXG4gICAgICBlbnZpcm9ubWVudCA9IG5ldyBlbnYuQ29tcGlsZXIoKS5jb21waWxlKGFzdCwgb3B0aW9ucyk7XG4gIHJldHVybiBuZXcgZW52LkphdmFTY3JpcHRDb21waWxlcigpLmNvbXBpbGUoZW52aXJvbm1lbnQsIG9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZShpbnB1dCwgb3B0aW9ucyA9IHt9LCBlbnYpIHtcbiAgaWYgKGlucHV0ID09IG51bGwgfHwgKHR5cGVvZiBpbnB1dCAhPT0gJ3N0cmluZycgJiYgaW5wdXQudHlwZSAhPT0gJ1Byb2dyYW0nKSkge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1lvdSBtdXN0IHBhc3MgYSBzdHJpbmcgb3IgSGFuZGxlYmFycyBBU1QgdG8gSGFuZGxlYmFycy5jb21waWxlLiBZb3UgcGFzc2VkICcgKyBpbnB1dCk7XG4gIH1cblxuICBpZiAoISgnZGF0YScgaW4gb3B0aW9ucykpIHtcbiAgICBvcHRpb25zLmRhdGEgPSB0cnVlO1xuICB9XG4gIGlmIChvcHRpb25zLmNvbXBhdCkge1xuICAgIG9wdGlvbnMudXNlRGVwdGhzID0gdHJ1ZTtcbiAgfVxuXG4gIGxldCBjb21waWxlZDtcblxuICBmdW5jdGlvbiBjb21waWxlSW5wdXQoKSB7XG4gICAgbGV0IGFzdCA9IGVudi5wYXJzZShpbnB1dCwgb3B0aW9ucyksXG4gICAgICAgIGVudmlyb25tZW50ID0gbmV3IGVudi5Db21waWxlcigpLmNvbXBpbGUoYXN0LCBvcHRpb25zKSxcbiAgICAgICAgdGVtcGxhdGVTcGVjID0gbmV3IGVudi5KYXZhU2NyaXB0Q29tcGlsZXIoKS5jb21waWxlKGVudmlyb25tZW50LCBvcHRpb25zLCB1bmRlZmluZWQsIHRydWUpO1xuICAgIHJldHVybiBlbnYudGVtcGxhdGUodGVtcGxhdGVTcGVjKTtcbiAgfVxuXG4gIC8vIFRlbXBsYXRlIGlzIG9ubHkgY29tcGlsZWQgb24gZmlyc3QgdXNlIGFuZCBjYWNoZWQgYWZ0ZXIgdGhhdCBwb2ludC5cbiAgZnVuY3Rpb24gcmV0KGNvbnRleHQsIGV4ZWNPcHRpb25zKSB7XG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgY29tcGlsZWQgPSBjb21waWxlSW5wdXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBpbGVkLmNhbGwodGhpcywgY29udGV4dCwgZXhlY09wdGlvbnMpO1xuICB9XG4gIHJldC5fc2V0dXAgPSBmdW5jdGlvbihzZXR1cE9wdGlvbnMpIHtcbiAgICBpZiAoIWNvbXBpbGVkKSB7XG4gICAgICBjb21waWxlZCA9IGNvbXBpbGVJbnB1dCgpO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGlsZWQuX3NldHVwKHNldHVwT3B0aW9ucyk7XG4gIH07XG4gIHJldC5fY2hpbGQgPSBmdW5jdGlvbihpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgY29tcGlsZWQgPSBjb21waWxlSW5wdXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBpbGVkLl9jaGlsZChpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgfTtcbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gYXJnRXF1YWxzKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChpc0FycmF5KGEpICYmIGlzQXJyYXkoYikgJiYgYS5sZW5ndGggPT09IGIubGVuZ3RoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIWFyZ0VxdWFscyhhW2ldLCBiW2ldKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybUxpdGVyYWxUb1BhdGgoc2V4cHIpIHtcbiAgaWYgKCFzZXhwci5wYXRoLnBhcnRzKSB7XG4gICAgbGV0IGxpdGVyYWwgPSBzZXhwci5wYXRoO1xuICAgIC8vIENhc3RpbmcgdG8gc3RyaW5nIGhlcmUgdG8gbWFrZSBmYWxzZSBhbmQgMCBsaXRlcmFsIHZhbHVlcyBwbGF5IG5pY2VseSB3aXRoIHRoZSByZXN0XG4gICAgLy8gb2YgdGhlIHN5c3RlbS5cbiAgICBzZXhwci5wYXRoID0ge1xuICAgICAgdHlwZTogJ1BhdGhFeHByZXNzaW9uJyxcbiAgICAgIGRhdGE6IGZhbHNlLFxuICAgICAgZGVwdGg6IDAsXG4gICAgICBwYXJ0czogW2xpdGVyYWwub3JpZ2luYWwgKyAnJ10sXG4gICAgICBvcmlnaW5hbDogbGl0ZXJhbC5vcmlnaW5hbCArICcnLFxuICAgICAgbG9jOiBsaXRlcmFsLmxvY1xuICAgIH07XG4gIH1cbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/helpers.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/helpers.js new file mode 100644 index 0000000..0f5cbf2 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/helpers.js @@ -0,0 +1,230 @@ +'use strict'; + +exports.__esModule = true; +exports.SourceLocation = SourceLocation; +exports.id = id; +exports.stripFlags = stripFlags; +exports.stripComment = stripComment; +exports.preparePath = preparePath; +exports.prepareMustache = prepareMustache; +exports.prepareRawBlock = prepareRawBlock; +exports.prepareBlock = prepareBlock; +exports.prepareProgram = prepareProgram; +exports.preparePartialBlock = preparePartialBlock; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _exception = require('../exception'); + +var _exception2 = _interopRequireDefault(_exception); + +function validateClose(open, close) { + close = close.path ? close.path.original : close; + + if (open.path.original !== close) { + var errorNode = { loc: open.path.loc }; + + throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode); + } +} + +function SourceLocation(source, locInfo) { + this.source = source; + this.start = { + line: locInfo.first_line, + column: locInfo.first_column + }; + this.end = { + line: locInfo.last_line, + column: locInfo.last_column + }; +} + +function id(token) { + if (/^\[.*\]$/.test(token)) { + return token.substr(1, token.length - 2); + } else { + return token; + } +} + +function stripFlags(open, close) { + return { + open: open.charAt(2) === '~', + close: close.charAt(close.length - 3) === '~' + }; +} + +function stripComment(comment) { + return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, ''); +} + +function preparePath(data, parts, loc) { + loc = this.locInfo(loc); + + var original = data ? '@' : '', + dig = [], + depth = 0, + depthString = ''; + + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i].part, + + // If we have [] syntax then we do not treat path references as operators, + // i.e. foo.[this] resolves to approximately context.foo['this'] + isLiteral = parts[i].original !== part; + original += (parts[i].separator || '') + part; + + if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { + if (dig.length > 0) { + throw new _exception2['default']('Invalid path: ' + original, { loc: loc }); + } else if (part === '..') { + depth++; + depthString += '../'; + } + } else { + dig.push(part); + } + } + + return { + type: 'PathExpression', + data: data, + depth: depth, + parts: dig, + original: original, + loc: loc + }; +} + +function prepareMustache(path, params, hash, open, strip, locInfo) { + // Must use charAt to support IE pre-10 + var escapeFlag = open.charAt(3) || open.charAt(2), + escaped = escapeFlag !== '{' && escapeFlag !== '&'; + + var decorator = /\*/.test(open); + return { + type: decorator ? 'Decorator' : 'MustacheStatement', + path: path, + params: params, + hash: hash, + escaped: escaped, + strip: strip, + loc: this.locInfo(locInfo) + }; +} + +function prepareRawBlock(openRawBlock, contents, close, locInfo) { + validateClose(openRawBlock, close); + + locInfo = this.locInfo(locInfo); + var program = { + type: 'Program', + body: contents, + strip: {}, + loc: locInfo + }; + + return { + type: 'BlockStatement', + path: openRawBlock.path, + params: openRawBlock.params, + hash: openRawBlock.hash, + program: program, + openStrip: {}, + inverseStrip: {}, + closeStrip: {}, + loc: locInfo + }; +} + +function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { + if (close && close.path) { + validateClose(openBlock, close); + } + + var decorator = /\*/.test(openBlock.open); + + program.blockParams = openBlock.blockParams; + + var inverse = undefined, + inverseStrip = undefined; + + if (inverseAndProgram) { + if (decorator) { + throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram); + } + + if (inverseAndProgram.chain) { + inverseAndProgram.program.body[0].closeStrip = close.strip; + } + + inverseStrip = inverseAndProgram.strip; + inverse = inverseAndProgram.program; + } + + if (inverted) { + inverted = inverse; + inverse = program; + program = inverted; + } + + return { + type: decorator ? 'DecoratorBlock' : 'BlockStatement', + path: openBlock.path, + params: openBlock.params, + hash: openBlock.hash, + program: program, + inverse: inverse, + openStrip: openBlock.strip, + inverseStrip: inverseStrip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; +} + +function prepareProgram(statements, loc) { + if (!loc && statements.length) { + var firstLoc = statements[0].loc, + lastLoc = statements[statements.length - 1].loc; + + /* istanbul ignore else */ + if (firstLoc && lastLoc) { + loc = { + source: firstLoc.source, + start: { + line: firstLoc.start.line, + column: firstLoc.start.column + }, + end: { + line: lastLoc.end.line, + column: lastLoc.end.column + } + }; + } + } + + return { + type: 'Program', + body: statements, + strip: {}, + loc: loc + }; +} + +function preparePartialBlock(open, program, close, locInfo) { + validateClose(open, close); + + return { + type: 'PartialBlockStatement', + name: open.path, + params: open.params, + hash: open.hash, + program: program, + openStrip: open.strip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7eUJBQXNCLGNBQWM7Ozs7QUFFcEMsU0FBUyxhQUFhLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRTtBQUNsQyxPQUFLLEdBQUcsS0FBSyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7O0FBRWpELE1BQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEtBQUssS0FBSyxFQUFFO0FBQ2hDLFFBQUksU0FBUyxHQUFHLEVBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFDLENBQUM7O0FBRXJDLFVBQU0sMkJBQWMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEdBQUcsaUJBQWlCLEdBQUcsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0dBQ2hGO0NBQ0Y7O0FBRU0sU0FBUyxjQUFjLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRTtBQUM5QyxNQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztBQUNyQixNQUFJLENBQUMsS0FBSyxHQUFHO0FBQ1gsUUFBSSxFQUFFLE9BQU8sQ0FBQyxVQUFVO0FBQ3hCLFVBQU0sRUFBRSxPQUFPLENBQUMsWUFBWTtHQUM3QixDQUFDO0FBQ0YsTUFBSSxDQUFDLEdBQUcsR0FBRztBQUNULFFBQUksRUFBRSxPQUFPLENBQUMsU0FBUztBQUN2QixVQUFNLEVBQUUsT0FBTyxDQUFDLFdBQVc7R0FDNUIsQ0FBQztDQUNIOztBQUVNLFNBQVMsRUFBRSxDQUFDLEtBQUssRUFBRTtBQUN4QixNQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7QUFDMUIsV0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0dBQzFD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anMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQ2xvc2Uob3BlbiwgY2xvc2UpIHtcbiAgY2xvc2UgPSBjbG9zZS5wYXRoID8gY2xvc2UucGF0aC5vcmlnaW5hbCA6IGNsb3NlO1xuXG4gIGlmIChvcGVuLnBhdGgub3JpZ2luYWwgIT09IGNsb3NlKSB7XG4gICAgbGV0IGVycm9yTm9kZSA9IHtsb2M6IG9wZW4ucGF0aC5sb2N9O1xuXG4gICAgdGhyb3cgbmV3IEV4Y2VwdGlvbihvcGVuLnBhdGgub3JpZ2luYWwgKyBcIiBkb2Vzbid0IG1hdGNoIFwiICsgY2xvc2UsIGVycm9yTm9kZSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNvdXJjZUxvY2F0aW9uKHNvdXJjZSwgbG9jSW5mbykge1xuICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcbiAgdGhpcy5zdGFydCA9IHtcbiAgICBsaW5lOiBsb2NJbmZvLmZpcnN0X2xpbmUsXG4gICAgY29sdW1uOiBsb2NJbmZvLmZpcnN0X2NvbHVtblxuICB9O1xuICB0aGlzLmVuZCA9IHtcbiAgICBsaW5lOiBsb2NJbmZvLmxhc3RfbGluZSxcbiAgICBjb2x1bW46IGxvY0luZm8ubGFzdF9jb2x1bW5cbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlkKHRva2VuKSB7XG4gIGlmICgvXlxcWy4qXFxdJC8udGVzdCh0b2tlbikpIHtcbiAgICByZXR1cm4gdG9rZW4uc3Vic3RyKDEsIHRva2VuLmxlbmd0aCAtIDIpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB0b2tlbjtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBGbGFncyhvcGVuLCBjbG9zZSkge1xuICByZXR1cm4ge1xuICAgIG9wZW46IG9wZW4uY2hhckF0KDIpID09PSAnficsXG4gICAgY2xvc2U6IGNsb3NlLmNoYXJBdChjbG9zZS5sZW5ndGggLSAzKSA9PT0gJ34nXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcENvbW1lbnQoY29tbWVudCkge1xuICByZXR1cm4gY29tbWVudC5yZXBsYWNlKC9eXFx7XFx7fj9cXCEtPy0/LywgJycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLy0/LT9+P1xcfVxcfSQvLCAnJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmVwYXJlUGF0aChkYXRhLCBwYXJ0cywgbG9jKSB7XG4gIGxvYyA9IHRoaXMubG9jSW5mbyhsb2MpO1xuXG4gIGxldCBvcmlnaW5hbCA9IGRhdGEgPyAnQCcgOiAnJyxcbiAgICAgIGRpZyA9IFtdLFxuICAgICAgZGVwdGggPSAwLFxuICAgICAgZGVwdGhTdHJpbmcgPSAnJztcblxuICBmb3IgKGxldCBpID0gMCwgbCA9IHBhcnRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGxldCBwYXJ0ID0gcGFydHNbaV0ucGFydCxcbiAgICAgICAgLy8gSWYgd2UgaGF2ZSBbXSBzeW50YXggdGhlbiB3ZSBkbyBub3QgdHJlYXQgcGF0aCByZWZlcmVuY2VzIGFzIG9wZXJhdG9ycyxcbiAgICAgICAgLy8gaS5lLiBmb28uW3RoaXNdIHJlc29sdmVzIHRvIGFwcHJveGltYXRlbHkgY29udGV4dC5mb29bJ3RoaXMnXVxuICAgICAgICBpc0xpdGVyYWwgPSBwYXJ0c1tpXS5vcmlnaW5hbCAhPT0gcGFydDtcbiAgICBvcmlnaW5hbCArPSAocGFydHNbaV0uc2VwYXJhdG9yIHx8ICcnKSArIHBhcnQ7XG5cbiAgICBpZiAoIWlzTGl0ZXJhbCAmJiAocGFydCA9PT0gJy4uJyB8fCBwYXJ0ID09PSAnLicgfHwgcGFydCA9PT0gJ3RoaXMnKSkge1xuICAgICAgaWYgKGRpZy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0ludmFsaWQgcGF0aDogJyArIG9yaWdpbmFsLCB7bG9jfSk7XG4gICAgICB9IGVsc2UgaWYgKHBhcnQgPT09ICcuLicpIHtcbiAgICAgICAgZGVwdGgrKztcbiAgICAgICAgZGVwdGhTdHJpbmcgKz0gJy4uLyc7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpZy5wdXNoKHBhcnQpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ1BhdGhFeHByZXNzaW9uJyxcbiAgICBkYXRhLFxuICAgIGRlcHRoLFxuICAgIHBhcnRzOiBkaWcsXG4gICAgb3JpZ2luYWwsXG4gICAgbG9jXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmVwYXJlTXVzdGFjaGUocGF0aCwgcGFyYW1zLCBoYXNoLCBvcGVuLCBzdHJpcCwgbG9jSW5mbykge1xuICAvLyBNdXN0IHVzZSBjaGFyQXQgdG8gc3VwcG9ydCBJRSBwcmUtMTBcbiAgbGV0IGVzY2FwZUZsYWcgPSBvcGVuLmNoYXJBdCgzKSB8fCBvcGVuLmNoYXJBdCgyKSxcbiAgICAgIGVzY2FwZWQgPSBlc2NhcGVGbGFnICE9PSAneycgJiYgZXNjYXBlRmxhZyAhPT0gJyYnO1xuXG4gIGxldCBkZWNvcmF0b3IgPSAoL1xcKi8udGVzdChvcGVuKSk7XG4gIHJldHVybiB7XG4gICAgdHlwZTogZGVjb3JhdG9yID8gJ0RlY29yYXRvcicgOiAnTXVzdGFjaGVTdGF0ZW1lbnQnLFxuICAgIHBhdGgsXG4gICAgcGFyYW1zLFxuICAgIGhhc2gsXG4gICAgZXNjYXBlZCxcbiAgICBzdHJpcCxcbiAgICBsb2M6IHRoaXMubG9jSW5mbyhsb2NJbmZvKVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZVJhd0Jsb2NrKG9wZW5SYXdCbG9jaywgY29udGVudHMsIGNsb3NlLCBsb2NJbmZvKSB7XG4gIHZhbGlkYXRlQ2xvc2Uob3BlblJhd0Jsb2NrLCBjbG9zZSk7XG5cbiAgbG9jSW5mbyA9IHRoaXMubG9jSW5mbyhsb2NJbmZvKTtcbiAgbGV0IHByb2dyYW0gPSB7XG4gICAgdHlwZTogJ1Byb2dyYW0nLFxuICAgIGJvZHk6IGNvbnRlbnRzLFxuICAgIHN0cmlwOiB7fSxcbiAgICBsb2M6IGxvY0luZm9cbiAgfTtcblxuICByZXR1cm4ge1xuICAgIHR5cGU6ICdCbG9ja1N0YXRlbWVudCcsXG4gICAgcGF0aDogb3BlblJhd0Jsb2NrLnBhdGgsXG4gICAgcGFyYW1zOiBvcGVuUmF3QmxvY2sucGFyYW1zLFxuICAgIGhhc2g6IG9wZW5SYXdCbG9jay5oYXNoLFxuICAgIHByb2dyYW0sXG4gICAgb3BlblN0cmlwOiB7fSxcbiAgICBpbnZlcnNlU3RyaXA6IHt9LFxuICAgIGNsb3NlU3RyaXA6IHt9LFxuICAgIGxvYzogbG9jSW5mb1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZUJsb2NrKG9wZW5CbG9jaywgcHJvZ3JhbSwgaW52ZXJzZUFuZFByb2dyYW0sIGNsb3NlLCBpbnZlcnRlZCwgbG9jSW5mbykge1xuICBpZiAoY2xvc2UgJiYgY2xvc2UucGF0aCkge1xuICAgIHZhbGlkYXRlQ2xvc2Uob3BlbkJsb2NrLCBjbG9zZSk7XG4gIH1cblxuICBsZXQgZGVjb3JhdG9yID0gKC9cXCovLnRlc3Qob3BlbkJsb2NrLm9wZW4pKTtcblxuICBwcm9ncmFtLmJsb2NrUGFyYW1zID0gb3BlbkJsb2NrLmJsb2NrUGFyYW1zO1xuXG4gIGxldCBpbnZlcnNlLFxuICAgICAgaW52ZXJzZVN0cmlwO1xuXG4gIGlmIChpbnZlcnNlQW5kUHJvZ3JhbSkge1xuICAgIGlmIChkZWNvcmF0b3IpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1VuZXhwZWN0ZWQgaW52ZXJzZSBibG9jayBvbiBkZWNvcmF0b3InLCBpbnZlcnNlQW5kUHJvZ3JhbSk7XG4gICAgfVxuXG4gICAgaWYgKGludmVyc2VBbmRQcm9ncmFtLmNoYWluKSB7XG4gICAgICBpbnZlcnNlQW5kUHJvZ3JhbS5wcm9ncmFtLmJvZHlbMF0uY2xvc2VTdHJpcCA9IGNsb3NlLnN0cmlwO1xuICAgIH1cblxuICAgIGludmVyc2VTdHJpcCA9IGludmVyc2VBbmRQcm9ncmFtLnN0cmlwO1xuICAgIGludmVyc2UgPSBpbnZlcnNlQW5kUHJvZ3JhbS5wcm9ncmFtO1xuICB9XG5cbiAgaWYgKGludmVydGVkKSB7XG4gICAgaW52ZXJ0ZWQgPSBpbnZlcnNlO1xuICAgIGludmVyc2UgPSBwcm9ncmFtO1xuICAgIHByb2dyYW0gPSBpbnZlcnRlZDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdHlwZTogZGVjb3JhdG9yID8gJ0RlY29yYXRvckJsb2NrJyA6ICdCbG9ja1N0YXRlbWVudCcsXG4gICAgcGF0aDogb3BlbkJsb2NrLnBhdGgsXG4gICAgcGFyYW1zOiBvcGVuQmxvY2sucGFyYW1zLFxuICAgIGhhc2g6IG9wZW5CbG9jay5oYXNoLFxuICAgIHByb2dyYW0sXG4gICAgaW52ZXJzZSxcbiAgICBvcGVuU3RyaXA6IG9wZW5CbG9jay5zdHJpcCxcbiAgICBpbnZlcnNlU3RyaXAsXG4gICAgY2xvc2VTdHJpcDogY2xvc2UgJiYgY2xvc2Uuc3RyaXAsXG4gICAgbG9jOiB0aGlzLmxvY0luZm8obG9jSW5mbylcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVQcm9ncmFtKHN0YXRlbWVudHMsIGxvYykge1xuICBpZiAoIWxvYyAmJiBzdGF0ZW1lbnRzLmxlbmd0aCkge1xuICAgIGNvbnN0IGZpcnN0TG9jID0gc3RhdGVtZW50c1swXS5sb2MsXG4gICAgICAgICAgbGFzdExvYyA9IHN0YXRlbWVudHNbc3RhdGVtZW50cy5sZW5ndGggLSAxXS5sb2M7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChmaXJzdExvYyAmJiBsYXN0TG9jKSB7XG4gICAgICBsb2MgPSB7XG4gICAgICAgIHNvdXJjZTogZmlyc3RMb2Muc291cmNlLFxuICAgICAgICBzdGFydDoge1xuICAgICAgICAgIGxpbmU6IGZpcnN0TG9jLnN0YXJ0LmxpbmUsXG4gICAgICAgICAgY29sdW1uOiBmaXJzdExvYy5zdGFydC5jb2x1bW5cbiAgICAgICAgfSxcbiAgICAgICAgZW5kOiB7XG4gICAgICAgICAgbGluZTogbGFzdExvYy5lbmQubGluZSxcbiAgICAgICAgICBjb2x1bW46IGxhc3RMb2MuZW5kLmNvbHVtblxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ1Byb2dyYW0nLFxuICAgIGJvZHk6IHN0YXRlbWVudHMsXG4gICAgc3RyaXA6IHt9LFxuICAgIGxvYzogbG9jXG4gIH07XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVQYXJ0aWFsQmxvY2sob3BlbiwgcHJvZ3JhbSwgY2xvc2UsIGxvY0luZm8pIHtcbiAgdmFsaWRhdGVDbG9zZShvcGVuLCBjbG9zZSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnUGFydGlhbEJsb2NrU3RhdGVtZW50JyxcbiAgICBuYW1lOiBvcGVuLnBhdGgsXG4gICAgcGFyYW1zOiBvcGVuLnBhcmFtcyxcbiAgICBoYXNoOiBvcGVuLmhhc2gsXG4gICAgcHJvZ3JhbSxcbiAgICBvcGVuU3RyaXA6IG9wZW4uc3RyaXAsXG4gICAgY2xvc2VTdHJpcDogY2xvc2UgJiYgY2xvc2Uuc3RyaXAsXG4gICAgbG9jOiB0aGlzLmxvY0luZm8obG9jSW5mbylcbiAgfTtcbn1cblxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js new file mode 100644 index 0000000..4dd5c90 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js @@ -0,0 +1,1128 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _base = require('../base'); + +var _exception = require('../exception'); + +var _exception2 = _interopRequireDefault(_exception); + +var _utils = require('../utils'); + +var _codeGen = require('./code-gen'); + +var _codeGen2 = _interopRequireDefault(_codeGen); + +function Literal(value) { + this.value = value; +} + +function JavaScriptCompiler() {} + +JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function nameLookup(parent, name /* , type*/) { + if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + return [parent, '.', name]; + } else { + return [parent, '[', JSON.stringify(name), ']']; + } + }, + depthedLookup: function depthedLookup(name) { + return [this.aliasable('container.lookup'), '(depths, "', name, '")']; + }, + + compilerInfo: function compilerInfo() { + var revision = _base.COMPILER_REVISION, + versions = _base.REVISION_CHANGES[revision]; + return [revision, versions]; + }, + + appendToBuffer: function appendToBuffer(source, location, explicit) { + // Force a source as this simplifies the merge logic. + if (!_utils.isArray(source)) { + source = [source]; + } + source = this.source.wrap(source, location); + + if (this.environment.isSimple) { + return ['return ', source, ';']; + } else if (explicit) { + // This is a case where the buffer operation occurs as a child of another + // construct, generally braces. We have to explicitly output these buffer + // operations to ensure that the emitted code goes in the correct location. + return ['buffer += ', source, ';']; + } else { + source.appendToBuffer = true; + return source; + } + }, + + initializeBuffer: function initializeBuffer() { + return this.quotedString(''); + }, + // END PUBLIC API + + compile: function compile(environment, options, context, asObject) { + this.environment = environment; + this.options = options; + this.stringParams = this.options.stringParams; + this.trackIds = this.options.trackIds; + this.precompile = !asObject; + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + decorators: [], + programs: [], + environments: [] + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.aliases = {}; + this.registers = { list: [] }; + this.hashes = []; + this.compileStack = []; + this.inlineStack = []; + this.blockParams = []; + + this.compileChildren(environment, options); + + this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; + this.useBlockParams = this.useBlockParams || environment.useBlockParams; + + var opcodes = environment.opcodes, + opcode = undefined, + firstLoc = undefined, + i = undefined, + l = undefined; + + for (i = 0, l = opcodes.length; i < l; i++) { + opcode = opcodes[i]; + + this.source.currentLocation = opcode.loc; + firstLoc = firstLoc || opcode.loc; + this[opcode.opcode].apply(this, opcode.args); + } + + // Flush any trailing content that might be pending. + this.source.currentLocation = firstLoc; + this.pushSource(''); + + /* istanbul ignore next */ + if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { + throw new _exception2['default']('Compile completed with content left on stack'); + } + + if (!this.decorators.isEmpty()) { + this.useDecorators = true; + + this.decorators.prepend('var decorators = container.decorators;\n'); + this.decorators.push('return fn;'); + + if (asObject) { + this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); + } else { + this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); + this.decorators.push('}\n'); + this.decorators = this.decorators.merge(); + } + } else { + this.decorators = undefined; + } + + var fn = this.createFunctionContext(asObject); + if (!this.isChild) { + var ret = { + compiler: this.compilerInfo(), + main: fn + }; + + if (this.decorators) { + ret.main_d = this.decorators; // eslint-disable-line camelcase + ret.useDecorators = true; + } + + var _context = this.context; + var programs = _context.programs; + var decorators = _context.decorators; + + for (i = 0, l = programs.length; i < l; i++) { + if (programs[i]) { + ret[i] = programs[i]; + if (decorators[i]) { + ret[i + '_d'] = decorators[i]; + ret.useDecorators = true; + } + } + } + + if (this.environment.usePartial) { + ret.usePartial = true; + } + if (this.options.data) { + ret.useData = true; + } + if (this.useDepths) { + ret.useDepths = true; + } + if (this.useBlockParams) { + ret.useBlockParams = true; + } + if (this.options.compat) { + ret.compat = true; + } + + if (!asObject) { + ret.compiler = JSON.stringify(ret.compiler); + + this.source.currentLocation = { start: { line: 1, column: 0 } }; + ret = this.objectLiteral(ret); + + if (options.srcName) { + ret = ret.toStringWithSourceMap({ file: options.destName }); + ret.map = ret.map && ret.map.toString(); + } else { + ret = ret.toString(); + } + } else { + ret.compilerOptions = this.options; + } + + return ret; + } else { + return fn; + } + }, + + preamble: function preamble() { + // track the last context pushed into place to allow skipping the + // getContext opcode when it would be a noop + this.lastContext = 0; + this.source = new _codeGen2['default'](this.options.srcName); + this.decorators = new _codeGen2['default'](this.options.srcName); + }, + + createFunctionContext: function createFunctionContext(asObject) { + var varDeclarations = ''; + + var locals = this.stackVars.concat(this.registers.list); + if (locals.length > 0) { + varDeclarations += ', ' + locals.join(', '); + } + + // Generate minimizer alias mappings + // + // When using true SourceNodes, this will update all references to the given alias + // as the source nodes are reused in situ. For the non-source node compilation mode, + // aliases will not be used, but this case is already being run on the client and + // we aren't concern about minimizing the template size. + var aliasCount = 0; + for (var alias in this.aliases) { + // eslint-disable-line guard-for-in + var node = this.aliases[alias]; + + if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { + varDeclarations += ', alias' + ++aliasCount + '=' + alias; + node.children[0] = 'alias' + aliasCount; + } + } + + var params = ['container', 'depth0', 'helpers', 'partials', 'data']; + + if (this.useBlockParams || this.useDepths) { + params.push('blockParams'); + } + if (this.useDepths) { + params.push('depths'); + } + + // Perform a second pass over the output to merge content when possible + var source = this.mergeSource(varDeclarations); + + if (asObject) { + params.push(source); + + return Function.apply(this, params); + } else { + return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); + } + }, + mergeSource: function mergeSource(varDeclarations) { + var isSimple = this.environment.isSimple, + appendOnly = !this.forceBuffer, + appendFirst = undefined, + sourceSeen = undefined, + bufferStart = undefined, + bufferEnd = undefined; + this.source.each(function (line) { + if (line.appendToBuffer) { + if (bufferStart) { + line.prepend(' + '); + } else { + bufferStart = line; + } + bufferEnd = line; + } else { + if (bufferStart) { + if (!sourceSeen) { + appendFirst = true; + } else { + bufferStart.prepend('buffer += '); + } + bufferEnd.add(';'); + bufferStart = bufferEnd = undefined; + } + + sourceSeen = true; + if (!isSimple) { + appendOnly = false; + } + } + }); + + if (appendOnly) { + if (bufferStart) { + bufferStart.prepend('return '); + bufferEnd.add(';'); + } else if (!sourceSeen) { + this.source.push('return "";'); + } + } else { + varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); + + if (bufferStart) { + bufferStart.prepend('return buffer + '); + bufferEnd.add(';'); + } else { + this.source.push('return buffer;'); + } + } + + if (varDeclarations) { + this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); + } + + return this.source.merge(); + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function blockValue(name) { + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs(name, 0, params); + + var blockName = this.popStack(); + params.splice(1, 0, blockName); + + this.push(this.source.functionCall(blockHelperMissing, 'call', params)); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function ambiguousBlockValue() { + // We're being a bit cheeky and reusing the options value from the prior exec + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs('', 0, params, true); + + this.flushInline(); + + var current = this.topStack(); + params.splice(1, 0, current); + + this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function appendContent(content) { + if (this.pendingContent) { + content = this.pendingContent + content; + } else { + this.pendingLocation = this.source.currentLocation; + } + + this.pendingContent = content; + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function append() { + if (this.isInline()) { + this.replaceStack(function (current) { + return [' != null ? ', current, ' : ""']; + }); + + this.pushSource(this.appendToBuffer(this.popStack())); + } else { + var local = this.popStack(); + this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); + if (this.environment.isSimple) { + this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); + } + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function appendEscaped() { + this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function getContext(depth) { + this.lastContext = depth; + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function pushContext() { + this.pushStackLiteral(this.contextName(this.lastContext)); + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) { + var i = 0; + + if (!scoped && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.push(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); + } + + this.resolvePath('context', parts, i, falsy, strict); + }, + + // [lookupBlockParam] + // + // On stack, before: ... + // On stack, after: blockParam[name], ... + // + // Looks up the value of `parts` on the given block param and pushes + // it onto the stack. + lookupBlockParam: function lookupBlockParam(blockParamId, parts) { + this.useBlockParams = true; + + this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); + this.resolvePath('context', parts, 1); + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data, ... + // + // Push the data lookup operator + lookupData: function lookupData(depth, parts, strict) { + if (!depth) { + this.pushStackLiteral('data'); + } else { + this.pushStackLiteral('container.data(data, ' + depth + ')'); + } + + this.resolvePath('data', parts, 0, true, strict); + }, + + resolvePath: function resolvePath(type, parts, i, falsy, strict) { + // istanbul ignore next + + var _this = this; + + if (this.options.strict || this.options.assumeObjects) { + this.push(strictLookup(this.options.strict && strict, this, parts, type)); + return; + } + + var len = parts.length; + for (; i < len; i++) { + /* eslint-disable no-loop-func */ + this.replaceStack(function (current) { + var lookup = _this.nameLookup(current, parts[i], type); + // We want to ensure that zero and false are handled properly if the context (falsy flag) + // needs to have the special handling for these values. + if (!falsy) { + return [' != null ? ', lookup, ' : ', current]; + } else { + // Otherwise we can use generic falsy handling + return [' && ', lookup]; + } + }); + /* eslint-enable no-loop-func */ + } + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function resolvePossibleLambda() { + this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function pushStringParam(string, type) { + this.pushContext(); + this.pushString(type); + + // If it's a subexpression, the string result + // will be pushed after this opcode. + if (type !== 'SubExpression') { + if (typeof string === 'string') { + this.pushString(string); + } else { + this.pushStackLiteral(string); + } + } + }, + + emptyHash: function emptyHash(omitEmpty) { + if (this.trackIds) { + this.push('{}'); // hashIds + } + if (this.stringParams) { + this.push('{}'); // hashContexts + this.push('{}'); // hashTypes + } + this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); + }, + pushHash: function pushHash() { + if (this.hash) { + this.hashes.push(this.hash); + } + this.hash = { values: [], types: [], contexts: [], ids: [] }; + }, + popHash: function popHash() { + var hash = this.hash; + this.hash = this.hashes.pop(); + + if (this.trackIds) { + this.push(this.objectLiteral(hash.ids)); + } + if (this.stringParams) { + this.push(this.objectLiteral(hash.contexts)); + this.push(this.objectLiteral(hash.types)); + } + + this.push(this.objectLiteral(hash.values)); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function pushString(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function pushLiteral(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function pushProgram(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [registerDecorator] + // + // On stack, before: hash, program, params..., ... + // On stack, after: ... + // + // Pops off the decorator's parameters, invokes the decorator, + // and inserts the decorator into the decorators list. + registerDecorator: function registerDecorator(paramSize, name) { + var foundDecorator = this.nameLookup('decorators', name, 'decorator'), + options = this.setupHelperArgs(name, paramSize); + + this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']); + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function invokeHelper(paramSize, name, isSimple) { + var nonHelper = this.popStack(), + helper = this.setupHelper(paramSize, name), + simple = isSimple ? [helper.name, ' || '] : ''; + + var lookup = ['('].concat(simple, nonHelper); + if (!this.options.strict) { + lookup.push(' || ', this.aliasable('helpers.helperMissing')); + } + lookup.push(')'); + + this.push(this.source.functionCall(lookup, 'call', helper.callParams)); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function invokeKnownHelper(paramSize, name) { + var helper = this.setupHelper(paramSize, name); + this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function invokeAmbiguous(name, helperCall) { + this.useRegister('helper'); + + var nonHelper = this.popStack(); + + this.emptyHash(); + var helper = this.setupHelper(0, name, helperCall); + + var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + + var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; + if (!this.options.strict) { + lookup[0] = '(helper = '; + lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing')); + } + + this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function invokePartial(isDynamic, name, indent) { + var params = [], + options = this.setupParams(name, 1, params); + + if (isDynamic) { + name = this.popStack(); + delete options.name; + } + + if (indent) { + options.indent = JSON.stringify(indent); + } + options.helpers = 'helpers'; + options.partials = 'partials'; + options.decorators = 'container.decorators'; + + if (!isDynamic) { + params.unshift(this.nameLookup('partials', name, 'partial')); + } else { + params.unshift(name); + } + + if (this.options.compat) { + options.depths = 'depths'; + } + options = this.objectLiteral(options); + params.push(options); + + this.push(this.source.functionCall('container.invokePartial', '', params)); + }, + + // [assignToHash] + // + // On stack, before: value, ..., hash, ... + // On stack, after: ..., hash, ... + // + // Pops a value off the stack and assigns it to the current hash + assignToHash: function assignToHash(key) { + var value = this.popStack(), + context = undefined, + type = undefined, + id = undefined; + + if (this.trackIds) { + id = this.popStack(); + } + if (this.stringParams) { + type = this.popStack(); + context = this.popStack(); + } + + var hash = this.hash; + if (context) { + hash.contexts[key] = context; + } + if (type) { + hash.types[key] = type; + } + if (id) { + hash.ids[key] = id; + } + hash.values[key] = value; + }, + + pushId: function pushId(type, name, child) { + if (type === 'BlockParam') { + this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : '')); + } else if (type === 'PathExpression') { + this.pushString(name); + } else if (type === 'SubExpression') { + this.pushStackLiteral('true'); + } else { + this.pushStackLiteral('null'); + } + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function compileChildren(environment, options) { + var children = environment.children, + child = undefined, + compiler = undefined; + + for (var i = 0, l = children.length; i < l; i++) { + child = children[i]; + compiler = new this.compiler(); // eslint-disable-line new-cap + + var existing = this.matchExistingProgram(child); + + if (existing == null) { + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + var index = this.context.programs.length; + child.index = index; + child.name = 'program' + index; + this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); + this.context.decorators[index] = compiler.decorators; + this.context.environments[index] = child; + + this.useDepths = this.useDepths || compiler.useDepths; + this.useBlockParams = this.useBlockParams || compiler.useBlockParams; + child.useDepths = this.useDepths; + child.useBlockParams = this.useBlockParams; + } else { + child.index = existing.index; + child.name = 'program' + existing.index; + + this.useDepths = this.useDepths || existing.useDepths; + this.useBlockParams = this.useBlockParams || existing.useBlockParams; + } + } + }, + matchExistingProgram: function matchExistingProgram(child) { + for (var i = 0, len = this.context.environments.length; i < len; i++) { + var environment = this.context.environments[i]; + if (environment && environment.equals(child)) { + return environment; + } + } + }, + + programExpression: function programExpression(guid) { + var child = this.environment.children[guid], + programParams = [child.index, 'data', child.blockParams]; + + if (this.useBlockParams || this.useDepths) { + programParams.push('blockParams'); + } + if (this.useDepths) { + programParams.push('depths'); + } + + return 'container.program(' + programParams.join(', ') + ')'; + }, + + useRegister: function useRegister(name) { + if (!this.registers[name]) { + this.registers[name] = true; + this.registers.list.push(name); + } + }, + + push: function push(expr) { + if (!(expr instanceof Literal)) { + expr = this.source.wrap(expr); + } + + this.inlineStack.push(expr); + return expr; + }, + + pushStackLiteral: function pushStackLiteral(item) { + this.push(new Literal(item)); + }, + + pushSource: function pushSource(source) { + if (this.pendingContent) { + this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); + this.pendingContent = undefined; + } + + if (source) { + this.source.push(source); + } + }, + + replaceStack: function replaceStack(callback) { + var prefix = ['('], + stack = undefined, + createdStack = undefined, + usedLiteral = undefined; + + /* istanbul ignore next */ + if (!this.isInline()) { + throw new _exception2['default']('replaceStack on non-inline'); + } + + // We want to merge the inline statement into the replacement statement via ',' + var top = this.popStack(true); + + if (top instanceof Literal) { + // Literals do not need to be inlined + stack = [top.value]; + prefix = ['(', stack]; + usedLiteral = true; + } else { + // Get or create the current stack name for use by the inline + createdStack = true; + var _name = this.incrStack(); + + prefix = ['((', this.push(_name), ' = ', top, ')']; + stack = this.topStack(); + } + + var item = callback.call(this, stack); + + if (!usedLiteral) { + this.popStack(); + } + if (createdStack) { + this.stackSlot--; + } + this.push(prefix.concat(item, ')')); + }, + + incrStack: function incrStack() { + this.stackSlot++; + if (this.stackSlot > this.stackVars.length) { + this.stackVars.push('stack' + this.stackSlot); + } + return this.topStackName(); + }, + topStackName: function topStackName() { + return 'stack' + this.stackSlot; + }, + flushInline: function flushInline() { + var inlineStack = this.inlineStack; + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + /* istanbul ignore if */ + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + var stack = this.incrStack(); + this.pushSource([stack, ' = ', entry, ';']); + this.compileStack.push(stack); + } + } + }, + isInline: function isInline() { + return this.inlineStack.length; + }, + + popStack: function popStack(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && item instanceof Literal) { + return item.value; + } else { + if (!inline) { + /* istanbul ignore next */ + if (!this.stackSlot) { + throw new _exception2['default']('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function topStack() { + var stack = this.isInline() ? this.inlineStack : this.compileStack, + item = stack[stack.length - 1]; + + /* istanbul ignore if */ + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + contextName: function contextName(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + + quotedString: function quotedString(str) { + return this.source.quotedString(str); + }, + + objectLiteral: function objectLiteral(obj) { + return this.source.objectLiteral(obj); + }, + + aliasable: function aliasable(name) { + var ret = this.aliases[name]; + if (ret) { + ret.referenceCount++; + return ret; + } + + ret = this.aliases[name] = this.source.wrap(name); + ret.aliasable = true; + ret.referenceCount = 1; + + return ret; + }, + + setupHelper: function setupHelper(paramSize, name, blockHelper) { + var params = [], + paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); + var foundHelper = this.nameLookup('helpers', name, 'helper'), + callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : {}'); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: [callContext].concat(params) + }; + }, + + setupParams: function setupParams(helper, paramSize, params) { + var options = {}, + contexts = [], + types = [], + ids = [], + objectArgs = !params, + param = undefined; + + if (objectArgs) { + params = []; + } + + options.name = this.quotedString(helper); + options.hash = this.popStack(); + + if (this.trackIds) { + options.hashIds = this.popStack(); + } + if (this.stringParams) { + options.hashTypes = this.popStack(); + options.hashContexts = this.popStack(); + } + + var inverse = this.popStack(), + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + options.fn = program || 'container.noop'; + options.inverse = inverse || 'container.noop'; + } + + // The parameters go on to the stack in order (making sure that they are evaluated in order) + // so we need to pop them off the stack in reverse order + var i = paramSize; + while (i--) { + param = this.popStack(); + params[i] = param; + + if (this.trackIds) { + ids[i] = this.popStack(); + } + if (this.stringParams) { + types[i] = this.popStack(); + contexts[i] = this.popStack(); + } + } + + if (objectArgs) { + options.args = this.source.generateArray(params); + } + + if (this.trackIds) { + options.ids = this.source.generateArray(ids); + } + if (this.stringParams) { + options.types = this.source.generateArray(types); + options.contexts = this.source.generateArray(contexts); + } + + if (this.options.data) { + options.data = 'data'; + } + if (this.useBlockParams) { + options.blockParams = 'blockParams'; + } + return options; + }, + + setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) { + var options = this.setupParams(helper, paramSize, params); + options = this.objectLiteral(options); + if (useRegister) { + this.useRegister('options'); + params.push('options'); + return ['options=', options]; + } else if (params) { + params.push(options); + return ''; + } else { + return options; + } + } +}; + +(function () { + var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' '); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for (var i = 0, l = reservedWords.length; i < l; i++) { + compilerWords[reservedWords[i]] = true; + } +})(); + +JavaScriptCompiler.isValidJavaScriptVariableName = function (name) { + return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); +}; + +function strictLookup(requireTerminal, compiler, parts, type) { + var stack = compiler.popStack(), + i = 0, + len = parts.length; + if (requireTerminal) { + len--; + } + + for (; i < len; i++) { + stack = compiler.nameLookup(stack, parts[i], type); + } + + if (requireTerminal) { + return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')']; + } else { + return stack; + } +} + +exports['default'] = JavaScriptCompiler; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2phdmFzY3JpcHQtY29tcGlsZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7OztvQkFBb0QsU0FBUzs7eUJBQ3ZDLGNBQWM7Ozs7cUJBQ2QsVUFBVTs7dUJBQ1osWUFBWTs7OztBQUVoQyxTQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUU7QUFDdEIsTUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7Q0FDcEI7O0FBRUQsU0FBUyxrQkFBa0IsR0FBRyxFQUFFOztBQUVoQyxrQkFBa0IsQ0FBQyxTQUFTLEdBQUc7OztBQUc3QixZQUFVLEVBQUUsb0JBQVMsTUFBTSxFQUFFLElBQUksY0FBYTtBQUM1QyxRQUFJLGtCQUFrQixDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxFQUFFO0FBQzFELGFBQU8sQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQzVCLE1BQU07QUFDTCxhQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0tBQ2pEO0dBQ0Y7QUFDRCxlQUFhLEVBQUUsdUJBQVMsSUFBSSxFQUFFO0FBQzVCLFdBQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztHQUN2RTs7QUFFRCxjQUFZLEVBQUUsd0JBQVc7QUFDdkIsUUFBTSxRQUFRLDBCQUFvQjtRQUM1QixRQUFRLEdBQUcsdUJBQWlCLFFBQVEsQ0FBQyxDQUFDO0FBQzVDLFdBQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7R0FDN0I7O0FBRUQsZ0JBQWMsRUFBRSx3QkFBUyxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRTs7QUFFbkQsUUFBSSxDQUFDLGVBQVEsTUFBTSxDQUFDLEVBQUU7QUFD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TUFDTCxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztBQUN2QixNQUFJLGVBQWUsRUFBRTtBQUNuQixPQUFHLEVBQUUsQ0FBQztHQUNQOztBQUVELFNBQU8sQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUNuQixTQUFLLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0dBQ3BEOztBQUVELE1BQUksZUFBZSxFQUFFO0FBQ25CLFdBQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztHQUN6RyxNQUFNO0FBQ0wsV0FBTyxLQUFLLENBQUM7R0FDZDtDQUNGOztxQkFFYyxrQkFBa0IiLCJmaWxlIjoiamF2YXNjcmlwdC1jb21waWxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENPTVBJTEVSX1JFVklTSU9OLCBSRVZJU0lPTl9DSEFOR0VTIH0gZnJvbSAnLi4vYmFzZSc7XG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5pbXBvcnQge2lzQXJyYXl9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCBDb2RlR2VuIGZyb20gJy4vY29kZS1nZW4nO1xuXG5mdW5jdGlvbiBMaXRlcmFsKHZhbHVlKSB7XG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gSmF2YVNjcmlwdENvbXBpbGVyKCkge31cblxuSmF2YVNjcmlwdENvbXBpbGVyLnByb3RvdHlwZSA9IHtcbiAgLy8gUFVCTElDIEFQSTogWW91IGNhbiBvdmVycmlkZSB0aGVzZSBtZXRob2RzIGluIGEgc3ViY2xhc3MgdG8gcHJvdmlkZVxuICAvLyBhbHRlcm5hdGl2ZSBjb21waWxlZCBmb3JtcyBmb3IgbmFtZSBsb29rdXAgYW5kIGJ1ZmZlcmluZyBzZW1hbnRpY3NcbiAgbmFtZUxvb2t1cDogZnVuY3Rpb24ocGFyZW50LCBuYW1lLyogLCB0eXBlKi8pIHtcbiAgICBpZiAoSmF2YVNjcmlwdENvbXBpbGVyLmlzVmFsaWRKYXZhU2NyaXB0VmFyaWFibGVOYW1lKG5hbWUpKSB7XG4gICAgICByZXR1cm4gW3BhcmVudCwgJy4nLCBuYW1lXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtwYXJlbnQsICdbJywgSlNPTi5zdHJpbmdpZnkobmFtZSksICddJ107XG4gICAgfVxuICB9LFxuICBkZXB0aGVkTG9va3VwOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIFt0aGlzLmFsaWFzYWJsZSgnY29udGFpbmVyLmxvb2t1cCcpLCAnKGRlcHRocywgXCInLCBuYW1lLCAnXCIpJ107XG4gIH0sXG5cbiAgY29tcGlsZXJJbmZvOiBmdW5jdGlvbigpIHtcbiAgICBjb25zdCByZXZpc2lvbiA9IENPTVBJTEVSX1JFVklTSU9OLFxuICAgICAgICAgIHZlcnNpb25zID0gUkVWSVNJT05fQ0hBTkdFU1tyZXZpc2lvbl07XG4gICAgcmV0dXJuIFtyZXZpc2lvbiwgdmVyc2lvbnNdO1xuICB9LFxuXG4gIGFwcGVuZFRvQnVmZmVyOiBmdW5jdGlvbihzb3VyY2UsIGxvY2F0aW9uLCBleHBsaWNpdCkge1xuICAgIC8vIEZvcmNlIGEgc291cmNlIGFzIHRoaXMgc2ltcGxpZmllcyB0aGUgbWVyZ2UgbG9naWMuXG4gICAgaWYgKCFpc0FycmF5KHNvdXJjZSkpIHtcbiAgICAgIHNvdXJjZSA9IFtzb3VyY2VdO1xuICAgIH1cbiAgICBzb3VyY2UgPSB0aGlzLnNvdXJjZS53cmFwKHNvdXJjZSwgbG9jYXRpb24pO1xuXG4gICAgaWYgKHRoaXMuZW52aXJvbm1lbnQuaXNTaW1wbGUpIHtcbiAgICAgIHJldHVybiBbJ3JldHVybiAnLCBzb3VyY2UsICc7J107XG4gICAgfSBlbHNlIGlmIChleHBsaWNpdCkge1xuICAgICAgLy8gVGhpcyBpcyBhIGNhc2Ugd2hlcmUgdGhlIGJ1ZmZlciBvcGVyYXRpb24gb2NjdXJzIGFzIGEgY2hpbGQgb2YgYW5vdGhlclxuICAgICAgLy8gY29uc3RydWN0LCBnZW5lcmFsbHkgYnJhY2VzLiBXZSBoYXZlIHRvIGV4cGxpY2l0bHkgb3V0cHV0IHRoZXNlIGJ1ZmZlclxuICAgICAgLy8gb3BlcmF0aW9ucyB0byBlbnN1cmUgdGhhdCB0aGUgZW1pdHRlZCBjb2RlIGdvZXMgaW4gdGhlIGNvcnJlY3QgbG9jYXRpb24uXG4gICAgICByZXR1cm4gWydidWZmZXIgKz0gJywgc291cmNlLCAnOyddO1xuICAgIH0gZWxzZSB7XG4gICAgICBzb3VyY2UuYXBwZW5kVG9CdWZmZXIgPSB0cnVlO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG4gIH0sXG5cbiAgaW5pdGlhbGl6ZUJ1ZmZlcjogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucXVvdGVkU3RyaW5nKCcnKTtcbiAgfSxcbiAgLy8gRU5EIFBVQkxJQyBBUElcblxuICBjb21waWxlOiBmdW5jdGlvbihlbnZpcm9ubWVudCwgb3B0aW9ucywgY29udGV4dCwgYXNPYmplY3QpIHtcbiAgICB0aGlzLmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLnN0cmluZ1BhcmFtcyA9IHRoaXMub3B0aW9ucy5zdHJpbmdQYXJhbXM7XG4gICAgdGhpcy50cmFja0lkcyA9IHRoaXMub3B0aW9ucy50cmFja0lkcztcbiAgICB0aGlzLnByZWNvbXBpbGUgPSAhYXNPYmplY3Q7XG5cbiAgICB0aGlzLm5hbWUgPSB0aGlzLmVudmlyb25tZW50Lm5hbWU7XG4gICAgdGhpcy5pc0NoaWxkID0gISFjb250ZXh0O1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQgfHwge1xuICAgICAgZGVjb3JhdG9yczogW10sXG4gICAgICBwcm9ncmFtczogW10sXG4gICAgICBlbnZpcm9ubWVudHM6IFtdXG4gICAgfTtcblxuICAgIHRoaXMucHJlYW1ibGUoKTtcblxuICAgIHRoaXMuc3RhY2tTbG90ID0gMDtcbiAgICB0aGlzLnN0YWNrVmFycyA9IFtdO1xuICAgIHRoaXMuYWxpYXNlcyA9IHt9O1xuICAgIHRoaXMucmVnaXN0ZXJzID0geyBsaXN0OiBbXSB9O1xuICAgIHRoaXMuaGFzaGVzID0gW107XG4gICAgdGhpcy5jb21waWxlU3RhY2sgPSBbXTtcbiAgICB0aGlzLmlubGluZVN0YWNrID0gW107XG4gICAgdGhpcy5ibG9ja1BhcmFtcyA9IFtdO1xuXG4gICAgdGhpcy5jb21waWxlQ2hpbGRyZW4oZW52aXJvbm1lbnQsIG9wdGlvbnMpO1xuXG4gICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCBlbnZpcm9ubWVudC51c2VEZXB0aHMgfHwgZW52aXJvbm1lbnQudXNlRGVjb3JhdG9ycyB8fCB0aGlzLm9wdGlvbnMuY29tcGF0O1xuICAgIHRoaXMudXNlQmxvY2tQYXJhbXMgPSB0aGlzLnVzZUJsb2NrUGFyYW1zIHx8IGVudmlyb25tZW50LnVzZUJsb2NrUGFyYW1zO1xuXG4gICAgbGV0IG9wY29kZXMgPSBlbnZpcm9ubWVudC5vcGNvZGVzLFxuICAgICAgICBvcGNvZGUsXG4gICAgICAgIGZpcnN0TG9jLFxuICAgICAgICBpLFxuICAgICAgICBsO1xuXG4gICAgZm9yIChpID0gMCwgbCA9IG9wY29kZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICBvcGNvZGUgPSBvcGNvZGVzW2ldO1xuXG4gICAgICB0aGlzLnNvdXJjZS5jdXJyZW50TG9jYXRpb24gPSBvcGNvZGUubG9jO1xuICAgICAgZmlyc3RMb2MgPSBmaXJzdExvYyB8fCBvcGNvZGUubG9jO1xuICAgICAgdGhpc1tvcGNvZGUub3Bjb2RlXS5hcHBseSh0aGlzLCBvcGNvZGUuYXJncyk7XG4gICAgfVxuXG4gICAgLy8gRmx1c2ggYW55IHRyYWlsaW5nIGNvbnRlbnQgdGhhdCBtaWdodCBiZSBwZW5kaW5nLlxuICAgIHRoaXMuc291cmNlLmN1cnJlbnRMb2NhdGlvbiA9IGZpcnN0TG9jO1xuICAgIHRoaXMucHVzaFNvdXJjZSgnJyk7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICh0aGlzLnN0YWNrU2xvdCB8fCB0aGlzLmlubGluZVN0YWNrLmxlbmd0aCB8fCB0aGlzLmNvbXBpbGVTdGFjay5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0NvbXBpbGUgY29tcGxldGVkIHdpdGggY29udGVudCBsZWZ0IG9uIHN0YWNrJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmRlY29yYXRvcnMuaXNFbXB0eSgpKSB7XG4gICAgICB0aGlzLnVzZURlY29yYXRvcnMgPSB0cnVlO1xuXG4gICAgICB0aGlzLmRlY29yYXRvcnMucHJlcGVuZCgndmFyIGRlY29yYXRvcnMgPSBjb250YWluZXIuZGVjb3JhdG9ycztcXG4nKTtcbiAgICAgIHRoaXMuZGVjb3JhdG9ycy5wdXNoKCdyZXR1cm4gZm47Jyk7XG5cbiAgICAgIGlmIChhc09iamVjdCkge1xuICAgICAgICB0aGlzLmRlY29yYXRvcnMgPSBGdW5jdGlvbi5hcHBseSh0aGlzLCBbJ2ZuJywgJ3Byb3BzJywgJ2NvbnRhaW5lcicsICdkZXB0aDAnLCAnZGF0YScsICdibG9ja1BhcmFtcycsICdkZXB0aHMnLCB0aGlzLmRlY29yYXRvcnMubWVyZ2UoKV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzLnByZXBlbmQoJ2Z1bmN0aW9uKGZuLCBwcm9wcywgY29udGFpbmVyLCBkZXB0aDAsIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcXG4nKTtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzLnB1c2goJ31cXG4nKTtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzID0gdGhpcy5kZWNvcmF0b3JzLm1lcmdlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVjb3JhdG9ycyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBsZXQgZm4gPSB0aGlzLmNyZWF0ZUZ1bmN0aW9uQ29udGV4dChhc09iamVjdCk7XG4gICAgaWYgKCF0aGlzLmlzQ2hpbGQpIHtcbiAgICAgIGxldCByZXQgPSB7XG4gICAgICAgIGNvbXBpbGVyOiB0aGlzLmNvbXBpbGVySW5mbygpLFxuICAgICAgICBtYWluOiBmblxuICAgICAgfTtcblxuICAgICAgaWYgKHRoaXMuZGVjb3JhdG9ycykge1xuICAgICAgICByZXQubWFpbl9kID0gdGhpcy5kZWNvcmF0b3JzOyAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY2FtZWxjYXNlXG4gICAgICAgIHJldC51c2VEZWNvcmF0b3JzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgbGV0IHtwcm9ncmFtcywgZGVjb3JhdG9yc30gPSB0aGlzLmNvbnRleHQ7XG4gICAgICBmb3IgKGkgPSAwLCBsID0gcHJvZ3JhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIGlmIChwcm9ncmFtc1tpXSkge1xuICAgICAgICAgIHJldFtpXSA9IHByb2dyYW1zW2ldO1xuICAgICAgICAgIGlmIChkZWNvcmF0b3JzW2ldKSB7XG4gICAgICAgICAgICByZXRbaSArICdfZCddID0gZGVjb3JhdG9yc1tpXTtcbiAgICAgICAgICAgIHJldC51c2VEZWNvcmF0b3JzID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQudXNlUGFydGlhbCkge1xuICAgICAgICByZXQudXNlUGFydGlhbCA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmRhdGEpIHtcbiAgICAgICAgcmV0LnVzZURhdGEgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudXNlRGVwdGhzKSB7XG4gICAgICAgIHJldC51c2VEZXB0aHMgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudXNlQmxvY2tQYXJhbXMpIHtcbiAgICAgICAgcmV0LnVzZUJsb2NrUGFyYW1zID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuY29tcGF0KSB7XG4gICAgICAgIHJldC5jb21wYXQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWFzT2JqZWN0KSB7XG4gICAgICAgIHJldC5jb21waWxlciA9IEpTT04uc3RyaW5naWZ5KHJldC5jb21waWxlcik7XG5cbiAgICAgICAgdGhpcy5zb3VyY2UuY3VycmVudExvY2F0aW9uID0ge3N0YXJ0OiB7bGluZTogMSwgY29sdW1uOiAwfX07XG4gICAgICAgIHJldCA9IHRoaXMub2JqZWN0TGl0ZXJhbChyZXQpO1xuXG4gICAgICAgIGlmIChvcHRpb25zLnNyY05hbWUpIHtcbiAgICAgICAgICByZXQgPSByZXQudG9TdHJpbmdXaXRoU291cmNlTWFwKHtmaWxlOiBvcHRpb25zLmRlc3ROYW1lfSk7XG4gICAgICAgICAgcmV0Lm1hcCA9IHJldC5tYXAgJiYgcmV0Lm1hcC50b1N0cmluZygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldCA9IHJldC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXQuY29tcGlsZXJPcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZm47XG4gICAgfVxuICB9LFxuXG4gIHByZWFtYmxlOiBmdW5jdGlvbigpIHtcbiAgICAvLyB0cmFjayB0aGUgbGFzdCBjb250ZXh0IHB1c2hlZCBpbnRvIHBsYWNlIHRvIGFsbG93IHNraXBwaW5nIHRoZVxuICAgIC8vIGdldENvbnRleHQgb3Bjb2RlIHdoZW4gaXQgd291bGQgYmUgYSBub29wXG4gICAgdGhpcy5sYXN0Q29udGV4dCA9IDA7XG4gICAgdGhpcy5zb3VyY2UgPSBuZXcgQ29kZUdlbih0aGlzLm9wdGlvbnMuc3JjTmFtZSk7XG4gICAgdGhpcy5kZWNvcmF0b3JzID0gbmV3IENvZGVHZW4odGhpcy5vcHRpb25zLnNyY05hbWUpO1xuICB9LFxuXG4gIGNyZWF0ZUZ1bmN0aW9uQ29udGV4dDogZnVuY3Rpb24oYXNPYmplY3QpIHtcbiAgICBsZXQgdmFyRGVjbGFyYXRpb25zID0gJyc7XG5cbiAgICBsZXQgbG9jYWxzID0gdGhpcy5zdGFja1ZhcnMuY29uY2F0KHRoaXMucmVnaXN0ZXJzLmxpc3QpO1xuICAgIGlmIChsb2NhbHMubGVuZ3RoID4gMCkge1xuICAgICAgdmFyRGVjbGFyYXRpb25zICs9ICcsICcgKyBsb2NhbHMuam9pbignLCAnKTtcbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZSBtaW5pbWl6ZXIgYWxpYXMgbWFwcGluZ3NcbiAgICAvL1xuICAgIC8vIFdoZW4gdXNpbmcgdHJ1ZSBTb3VyY2VOb2RlcywgdGhpcyB3aWxsIHVwZGF0ZSBhbGwgcmVmZXJlbmNlcyB0byB0aGUgZ2l2ZW4gYWxpYXNcbiAgICAvLyBhcyB0aGUgc291cmNlIG5vZGVzIGFyZSByZXVzZWQgaW4gc2l0dS4gRm9yIHRoZSBub24tc291cmNlIG5vZGUgY29tcGlsYXRpb24gbW9kZSxcbiAgICAvLyBhbGlhc2VzIHdpbGwgbm90IGJlIHVzZWQsIGJ1dCB0aGlzIGNhc2UgaXMgYWxyZWFkeSBiZWluZyBydW4gb24gdGhlIGNsaWVudCBhbmRcbiAgICAvLyB3ZSBhcmVuJ3QgY29uY2VybiBhYm91dCBtaW5pbWl6aW5nIHRoZSB0ZW1wbGF0ZSBzaXplLlxuICAgIGxldCBhbGlhc0NvdW50ID0gMDtcbiAgICBmb3IgKGxldCBhbGlhcyBpbiB0aGlzLmFsaWFzZXMpIHsgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBndWFyZC1mb3ItaW5cbiAgICAgIGxldCBub2RlID0gdGhpcy5hbGlhc2VzW2FsaWFzXTtcblxuICAgICAgaWYgKHRoaXMuYWxpYXNlcy5oYXNPd25Qcm9wZXJ0eShhbGlhcykgJiYgbm9kZS5jaGlsZHJlbiAmJiBub2RlLnJlZmVyZW5jZUNvdW50ID4gMSkge1xuICAgICAgICB2YXJEZWNsYXJhdGlvbnMgKz0gJywgYWxpYXMnICsgKCsrYWxpYXNDb3VudCkgKyAnPScgKyBhbGlhcztcbiAgICAgICAgbm9kZS5jaGlsZHJlblswXSA9ICdhbGlhcycgKyBhbGlhc0NvdW50O1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBwYXJhbXMgPSBbJ2NvbnRhaW5lcicsICdkZXB0aDAnLCAnaGVscGVycycsICdwYXJ0aWFscycsICdkYXRhJ107XG5cbiAgICBpZiAodGhpcy51c2VCbG9ja1BhcmFtcyB8fCB0aGlzLnVzZURlcHRocykge1xuICAgICAgcGFyYW1zLnB1c2goJ2Jsb2NrUGFyYW1zJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnVzZURlcHRocykge1xuICAgICAgcGFyYW1zLnB1c2goJ2RlcHRocycpO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gYSBzZWNvbmQgcGFzcyBvdmVyIHRoZSBvdXRwdXQgdG8gbWVyZ2UgY29udGVudCB3aGVuIHBvc3NpYmxlXG4gICAgbGV0IHNvdXJjZSA9IHRoaXMubWVyZ2VTb3VyY2UodmFyRGVjbGFyYXRpb25zKTtcblxuICAgIGlmIChhc09iamVjdCkge1xuICAgICAgcGFyYW1zLnB1c2goc291cmNlKTtcblxuICAgICAgcmV0dXJuIEZ1bmN0aW9uLmFwcGx5KHRoaXMsIHBhcmFtcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnNvdXJjZS53cmFwKFsnZnVuY3Rpb24oJywgcGFyYW1zLmpvaW4oJywnKSwgJykge1xcbiAgJywgc291cmNlLCAnfSddKTtcbiAgICB9XG4gIH0sXG4gIG1lcmdlU291cmNlOiBmdW5jdGlvbih2YXJEZWNsYXJhdGlvbnMpIHtcbiAgICBsZXQgaXNTaW1wbGUgPSB0aGlzLmVudmlyb25tZW50LmlzU2ltcGxlLFxuICAgICAgICBhcHBlbmRPbmx5ID0gIXRoaXMuZm9yY2VCdWZmZXIsXG4gICAgICAgIGFwcGVuZEZpcnN0LFxuXG4gICAgICAgIHNvdXJjZVNlZW4sXG4gICAgICAgIGJ1ZmZlclN0YXJ0LFxuICAgICAgICBidWZmZXJFbmQ7XG4gICAgdGhpcy5zb3VyY2UuZWFjaCgobGluZSkgPT4ge1xuICAgICAgaWYgKGxpbmUuYXBwZW5kVG9CdWZmZXIpIHtcbiAgICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgICAgbGluZS5wcmVwZW5kKCcgICsgJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVmZmVyU3RhcnQgPSBsaW5lO1xuICAgICAgICB9XG4gICAgICAgIGJ1ZmZlckVuZCA9IGxpbmU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoYnVmZmVyU3RhcnQpIHtcbiAgICAgICAgICBpZiAoIXNvdXJjZVNlZW4pIHtcbiAgICAgICAgICAgIGFwcGVuZEZpcnN0ID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZmVyU3RhcnQucHJlcGVuZCgnYnVmZmVyICs9ICcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBidWZmZXJFbmQuYWRkKCc7Jyk7XG4gICAgICAgICAgYnVmZmVyU3RhcnQgPSBidWZmZXJFbmQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBzb3VyY2VTZWVuID0gdHJ1ZTtcbiAgICAgICAgaWYgKCFpc1NpbXBsZSkge1xuICAgICAgICAgIGFwcGVuZE9ubHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG5cbiAgICBpZiAoYXBwZW5kT25seSkge1xuICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgIGJ1ZmZlclN0YXJ0LnByZXBlbmQoJ3JldHVybiAnKTtcbiAgICAgICAgYnVmZmVyRW5kLmFkZCgnOycpO1xuICAgICAgfSBlbHNlIGlmICghc291cmNlU2Vlbikge1xuICAgICAgICB0aGlzLnNvdXJjZS5wdXNoKCdyZXR1cm4gXCJcIjsnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyRGVjbGFyYXRpb25zICs9ICcsIGJ1ZmZlciA9ICcgKyAoYXBwZW5kRmlyc3QgPyAnJyA6IHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcigpKTtcblxuICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgIGJ1ZmZlclN0YXJ0LnByZXBlbmQoJ3JldHVybiBidWZmZXIgKyAnKTtcbiAgICAgICAgYnVmZmVyRW5kLmFkZCgnOycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zb3VyY2UucHVzaCgncmV0dXJuIGJ1ZmZlcjsnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodmFyRGVjbGFyYXRpb25zKSB7XG4gICAgICB0aGlzLnNvdXJjZS5wcmVwZW5kKCd2YXIgJyArIHZhckRlY2xhcmF0aW9ucy5zdWJzdHJpbmcoMikgKyAoYXBwZW5kRmlyc3QgPyAnJyA6ICc7XFxuJykpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNvdXJjZS5tZXJnZSgpO1xuICB9LFxuXG4gIC8vIFtibG9ja1ZhbHVlXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCB2YWx1ZVxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJldHVybiB2YWx1ZSBvZiBibG9ja0hlbHBlck1pc3NpbmdcbiAgLy9cbiAgLy8gVGhlIHB1cnBvc2Ugb2YgdGhpcyBvcGNvZGUgaXMgdG8gdGFrZSBhIGJsb2NrIG9mIHRoZSBmb3JtXG4gIC8vIGB7eyN0aGlzLmZvb319Li4ue3svdGhpcy5mb299fWAsIHJlc29sdmUgdGhlIHZhbHVlIG9mIGBmb29gLCBhbmRcbiAgLy8gcmVwbGFjZSBpdCBvbiB0aGUgc3RhY2sgd2l0aCB0aGUgcmVzdWx0IG9mIHByb3Blcmx5XG4gIC8vIGludm9raW5nIGJsb2NrSGVscGVyTWlzc2luZy5cbiAgYmxvY2tWYWx1ZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGxldCBibG9ja0hlbHBlck1pc3NpbmcgPSB0aGlzLmFsaWFzYWJsZSgnaGVscGVycy5ibG9ja0hlbHBlck1pc3NpbmcnKSxcbiAgICAgICAgcGFyYW1zID0gW3RoaXMuY29udGV4dE5hbWUoMCldO1xuICAgIHRoaXMuc2V0dXBIZWxwZXJBcmdzKG5hbWUsIDAsIHBhcmFtcyk7XG5cbiAgICBsZXQgYmxvY2tOYW1lID0gdGhpcy5wb3BTdGFjaygpO1xuICAgIHBhcmFtcy5zcGxpY2UoMSwgMCwgYmxvY2tOYW1lKTtcblxuICAgIHRoaXMucHVzaCh0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwoYmxvY2tIZWxwZXJNaXNzaW5nLCAnY2FsbCcsIHBhcmFtcykpO1xuICB9LFxuXG4gIC8vIFthbWJpZ3VvdXNCbG9ja1ZhbHVlXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCB2YWx1ZVxuICAvLyBDb21waWxlciB2YWx1ZSwgYmVmb3JlOiBsYXN0SGVscGVyPXZhbHVlIG9mIGxhc3QgZm91bmQgaGVscGVyLCBpZiBhbnlcbiAgLy8gT24gc3RhY2ssIGFmdGVyLCBpZiBubyBsYXN0SGVscGVyOiBzYW1lIGFzIFtibG9ja1ZhbHVlXVxuICAvLyBPbiBzdGFjaywgYWZ0ZXIsIGlmIGxhc3RIZWxwZXI6IHZhbHVlXG4gIGFtYmlndW91c0Jsb2NrVmFsdWU6IGZ1bmN0aW9uKCkge1xuICAgIC8vIFdlJ3JlIGJlaW5nIGEgYml0IGNoZWVreSBhbmQgcmV1c2luZyB0aGUgb3B0aW9ucyB2YWx1ZSBmcm9tIHRoZSBwcmlvciBleGVjXG4gICAgbGV0IGJsb2NrSGVscGVyTWlzc2luZyA9IHRoaXMuYWxpYXNhYmxlKCdoZWxwZXJzLmJsb2NrSGVscGVyTWlzc2luZycpLFxuICAgICAgICBwYXJhbXMgPSBbdGhpcy5jb250ZXh0TmFtZSgwKV07XG4gICAgdGhpcy5zZXR1cEhlbHBlckFyZ3MoJycsIDAsIHBhcmFtcywgdHJ1ZSk7XG5cbiAgICB0aGlzLmZsdXNoSW5saW5lKCk7XG5cbiAgICBsZXQgY3VycmVudCA9IHRoaXMudG9wU3RhY2soKTtcbiAgICBwYXJhbXMuc3BsaWNlKDEsIDAsIGN1cnJlbnQpO1xuXG4gICAgdGhpcy5wdXNoU291cmNlKFtcbiAgICAgICAgJ2lmICghJywgdGhpcy5sYXN0SGVscGVyLCAnKSB7ICcsXG4gICAgICAgICAgY3VycmVudCwgJyA9ICcsIHRoaXMuc291cmNlLmZ1bmN0aW9uQ2FsbChibG9ja0hlbHBlck1pc3NpbmcsICdjYWxsJywgcGFyYW1zKSxcbiAgICAgICAgJ30nXSk7XG4gIH0sXG5cbiAgLy8gW2FwcGVuZENvbnRlbnRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBBcHBlbmRzIHRoZSBzdHJpbmcgdmFsdWUgb2YgYGNvbnRlbnRgIHRvIHRoZSBjdXJyZW50IGJ1ZmZlclxuICBhcHBlbmRDb250ZW50OiBmdW5jdGlvbihjb250ZW50KSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIGNvbnRlbnQgPSB0aGlzLnBlbmRpbmdDb250ZW50ICsgY29udGVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wZW5kaW5nTG9jYXRpb24gPSB0aGlzLnNvdXJjZS5jdXJyZW50TG9jYXRpb247XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nQ29udGVudCA9IGNvbnRlbnQ7XG4gIH0sXG5cbiAgLy8gW2FwcGVuZF1cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogdmFsdWUsIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBDb2VyY2VzIGB2YWx1ZWAgdG8gYSBTdHJpbmcgYW5kIGFwcGVuZHMgaXQgdG8gdGhlIGN1cnJlbnQgYnVmZmVyLlxuICAvL1xuICAvLyBJZiBgdmFsdWVgIGlzIHRydXRoeSwgb3IgMCwgaXQgaXMgY29lcmNlZCBpbnRvIGEgc3RyaW5nIGFuZCBhcHBlbmRlZFxuICAvLyBPdGhlcndpc2UsIHRoZSBlbXB0eSBzdHJpbmcgaXMgYXBwZW5kZWRcbiAgYXBwZW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5pc0lubGluZSgpKSB7XG4gICAgICB0aGlzLnJlcGxhY2VTdGFjaygoY3VycmVudCkgPT4gWycgIT0gbnVsbCA/ICcsIGN1cnJlbnQsICcgOiBcIlwiJ10pO1xuXG4gICAgICB0aGlzLnB1c2hTb3VyY2UodGhpcy5hcHBlbmRUb0J1ZmZlcih0aGlzLnBvcFN0YWNrKCkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGxvY2FsID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgdGhpcy5wdXNoU291cmNlKFsnaWYgKCcsIGxvY2FsLCAnICE9IG51bGwpIHsgJywgdGhpcy5hcHBlbmRUb0J1ZmZlcihsb2NhbCwgdW5kZWZpbmVkLCB0cnVlKSwgJyB9J10pO1xuICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQuaXNTaW1wbGUpIHtcbiAgICAgICAgdGhpcy5wdXNoU291cmNlKFsnZWxzZSB7ICcsIHRoaXMuYXBwZW5kVG9CdWZmZXIoXCInJ1wiLCB1bmRlZmluZWQsIHRydWUpLCAnIH0nXSk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8vIFthcHBlbmRFc2NhcGVkXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiB2YWx1ZSwgLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogLi4uXG4gIC8vXG4gIC8vIEVzY2FwZSBgdmFsdWVgIGFuZCBhcHBlbmQgaXQgdG8gdGhlIGJ1ZmZlclxuICBhcHBlbmRFc2NhcGVkOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2hTb3VyY2UodGhpcy5hcHBlbmRUb0J1ZmZlcihcbiAgICAgICAgW3RoaXMuYWxpYXNhYmxlKCdjb250YWluZXIuZXNjYXBlRXhwcmVzc2lvbicpLCAnKCcsIHRoaXMucG9wU3RhY2soKSwgJyknXSkpO1xuICB9LFxuXG4gIC8vIFtnZXRDb250ZXh0XVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiAuLi5cbiAgLy8gQ29tcGlsZXIgdmFsdWUsIGFmdGVyOiBsYXN0Q29udGV4dD1kZXB0aFxuICAvL1xuICAvLyBTZXQgdGhlIHZhbHVlIG9mIHRoZSBgbGFzdENvbnRleHRgIGNvbXBpbGVyIHZhbHVlIHRvIHRoZSBkZXB0aFxuICBnZXRDb250ZXh0OiBmdW5jdGlvbihkZXB0aCkge1xuICAgIHRoaXMubGFzdENvbnRleHQgPSBkZXB0aDtcbiAgfSxcblxuICAvLyBbcHVzaENvbnRleHRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IGN1cnJlbnRDb250ZXh0LCAuLi5cbiAgLy9cbiAgLy8gUHVzaGVzIHRoZSB2YWx1ZSBvZiB0aGUgY3VycmVudCBjb250ZXh0IG9udG8gdGhlIHN0YWNrLlxuICBwdXNoQ29udGV4dDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHRoaXMuY29udGV4dE5hbWUodGhpcy5sYXN0Q29udGV4dCkpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBPbkNvbnRleHRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IGN1cnJlbnRDb250ZXh0W25hbWVdLCAuLi5cbiAgLy9cbiAgLy8gTG9va3MgdXAgdGhlIHZhbHVlIG9mIGBuYW1lYCBvbiB0aGUgY3VycmVudCBjb250ZXh0IGFuZCBwdXNoZXNcbiAgLy8gaXQgb250byB0aGUgc3RhY2suXG4gIGxvb2t1cE9uQ29udGV4dDogZnVuY3Rpb24ocGFydHMsIGZhbHN5LCBzdHJpY3QsIHNjb3BlZCkge1xuICAgIGxldCBpID0gMDtcblxuICAgIGlmICghc2NvcGVkICYmIHRoaXMub3B0aW9ucy5jb21wYXQgJiYgIXRoaXMubGFzdENvbnRleHQpIHtcbiAgICAgIC8vIFRoZSBkZXB0aGVkIHF1ZXJ5IGlzIGV4cGVjdGVkIHRvIGhhbmRsZSB0aGUgdW5kZWZpbmVkIGxvZ2ljIGZvciB0aGUgcm9vdCBsZXZlbCB0aGF0XG4gICAgICAvLyBpcyBpbXBsZW1lbnRlZCBiZWxvdywgc28gd2UgZXZhbHVhdGUgdGhhdCBkaXJlY3RseSBpbiBjb21wYXQgbW9kZVxuICAgICAgdGhpcy5wdXNoKHRoaXMuZGVwdGhlZExvb2t1cChwYXJ0c1tpKytdKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaENvbnRleHQoKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlc29sdmVQYXRoKCdjb250ZXh0JywgcGFydHMsIGksIGZhbHN5LCBzdHJpY3QpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBCbG9ja1BhcmFtXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBibG9ja1BhcmFtW25hbWVdLCAuLi5cbiAgLy9cbiAgLy8gTG9va3MgdXAgdGhlIHZhbHVlIG9mIGBwYXJ0c2Agb24gdGhlIGdpdmVuIGJsb2NrIHBhcmFtIGFuZCBwdXNoZXNcbiAgLy8gaXQgb250byB0aGUgc3RhY2suXG4gIGxvb2t1cEJsb2NrUGFyYW06IGZ1bmN0aW9uKGJsb2NrUGFyYW1JZCwgcGFydHMpIHtcbiAgICB0aGlzLnVzZUJsb2NrUGFyYW1zID0gdHJ1ZTtcblxuICAgIHRoaXMucHVzaChbJ2Jsb2NrUGFyYW1zWycsIGJsb2NrUGFyYW1JZFswXSwgJ11bJywgYmxvY2tQYXJhbUlkWzFdLCAnXSddKTtcbiAgICB0aGlzLnJlc29sdmVQYXRoKCdjb250ZXh0JywgcGFydHMsIDEpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBEYXRhXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBkYXRhLCAuLi5cbiAgLy9cbiAgLy8gUHVzaCB0aGUgZGF0YSBsb29rdXAgb3BlcmF0b3JcbiAgbG9va3VwRGF0YTogZnVuY3Rpb24oZGVwdGgsIHBhcnRzLCBzdHJpY3QpIHtcbiAgICBpZiAoIWRlcHRoKSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwoJ2RhdGEnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKCdjb250YWluZXIuZGF0YShkYXRhLCAnICsgZGVwdGggKyAnKScpO1xuICAgIH1cblxuICAgIHRoaXMucmVzb2x2ZVBhdGgoJ2RhdGEnLCBwYXJ0cywgMCwgdHJ1ZSwgc3RyaWN0KTtcbiAgfSxcblxuICByZXNvbHZlUGF0aDogZnVuY3Rpb24odHlwZSwgcGFydHMsIGksIGZhbHN5LCBzdHJpY3QpIHtcbiAgICBpZiAodGhpcy5vcHRpb25zLnN0cmljdCB8fCB0aGlzLm9wdGlvbnMuYXNzdW1lT2JqZWN0cykge1xuICAgICAgdGhpcy5wdXNoKHN0cmljdExvb2t1cCh0aGlzLm9wdGlvbnMuc3RyaWN0ICYmIHN0cmljdCwgdGhpcywgcGFydHMsIHR5cGUpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgbGVuID0gcGFydHMubGVuZ3RoO1xuICAgIGZvciAoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWxvb3AtZnVuYyAqL1xuICAgICAgdGhpcy5yZXBsYWNlU3RhY2soKGN1cnJlbnQpID0+IHtcbiAgICAgICAgbGV0IGxvb2t1cCA9IHRoaXMubmFtZUxvb2t1cChjdXJyZW50LCBwYXJ0c1tpXSwgdHlwZSk7XG4gICAgICAgIC8vIFdlIHdhbnQgdG8gZW5zdXJlIHRoYXQgemVybyBhbmQgZmFsc2UgYXJlIGhhbmRsZWQgcHJvcGVybHkgaWYgdGhlIGNvbnRleHQgKGZhbHN5IGZsYWcpXG4gICAgICAgIC8vIG5lZWRzIHRvIGhhdmUgdGhlIHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRoZXNlIHZhbHVlcy5cbiAgICAgICAgaWYgKCFmYWxzeSkge1xuICAgICAgICAgIHJldHVybiBbJyAhPSBudWxsID8gJywgbG9va3VwLCAnIDogJywgY3VycmVudF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlIHdlIGNhbiB1c2UgZ2VuZXJpYyBmYWxzeSBoYW5kbGluZ1xuICAgICAgICAgIHJldHVybiBbJyAmJiAnLCBsb29rdXBdO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG4gICAgfVxuICB9LFxuXG4gIC8vIFtyZXNvbHZlUG9zc2libGVMYW1iZGFdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IHZhbHVlLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiByZXNvbHZlZCB2YWx1ZSwgLi4uXG4gIC8vXG4gIC8vIElmIHRoZSBgdmFsdWVgIGlzIGEgbGFtYmRhLCByZXBsYWNlIGl0IG9uIHRoZSBzdGFjayBieVxuICAvLyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBsYW1iZGFcbiAgcmVzb2x2ZVBvc3NpYmxlTGFtYmRhOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2goW3RoaXMuYWxpYXNhYmxlKCdjb250YWluZXIubGFtYmRhJyksICcoJywgdGhpcy5wb3BTdGFjaygpLCAnLCAnLCB0aGlzLmNvbnRleHROYW1lKDApLCAnKSddKTtcbiAgfSxcblxuICAvLyBbcHVzaFN0cmluZ1BhcmFtXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBzdHJpbmcsIGN1cnJlbnRDb250ZXh0LCAuLi5cbiAgLy9cbiAgLy8gVGhpcyBvcGNvZGUgaXMgZGVzaWduZWQgZm9yIHVzZSBpbiBzdHJpbmcgbW9kZSwgd2hpY2hcbiAgLy8gcHJvdmlkZXMgdGhlIHN0cmluZyB2YWx1ZSBvZiBhIHBhcmFtZXRlciBhbG9uZyB3aXRoIGl0c1xuICAvLyBkZXB0aCByYXRoZXIgdGhhbiByZXNvbHZpbmcgaXQgaW1tZWRpYXRlbHkuXG4gIHB1c2hTdHJpbmdQYXJhbTogZnVuY3Rpb24oc3RyaW5nLCB0eXBlKSB7XG4gICAgdGhpcy5wdXNoQ29udGV4dCgpO1xuICAgIHRoaXMucHVzaFN0cmluZyh0eXBlKTtcblxuICAgIC8vIElmIGl0J3MgYSBzdWJleHByZXNzaW9uLCB0aGUgc3RyaW5nIHJlc3VsdFxuICAgIC8vIHdpbGwgYmUgcHVzaGVkIGFmdGVyIHRoaXMgb3Bjb2RlLlxuICAgIGlmICh0eXBlICE9PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgIGlmICh0eXBlb2Ygc3RyaW5nID09PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLnB1c2hTdHJpbmcoc3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChzdHJpbmcpO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBlbXB0eUhhc2g6IGZ1bmN0aW9uKG9taXRFbXB0eSkge1xuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICB0aGlzLnB1c2goJ3t9Jyk7IC8vIGhhc2hJZHNcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0aGlzLnB1c2goJ3t9Jyk7IC8vIGhhc2hDb250ZXh0c1xuICAgICAgdGhpcy5wdXNoKCd7fScpOyAvLyBoYXNoVHlwZXNcbiAgICB9XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKG9taXRFbXB0eSA/ICd1bmRlZmluZWQnIDogJ3t9Jyk7XG4gIH0sXG4gIHB1c2hIYXNoOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5oYXNoKSB7XG4gICAgICB0aGlzLmhhc2hlcy5wdXNoKHRoaXMuaGFzaCk7XG4gICAgfVxuICAgIHRoaXMuaGFzaCA9IHt2YWx1ZXM6IFtdLCB0eXBlczogW10sIGNvbnRleHRzOiBbXSwgaWRzOiBbXX07XG4gIH0sXG4gIHBvcEhhc2g6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBoYXNoID0gdGhpcy5oYXNoO1xuICAgIHRoaXMuaGFzaCA9IHRoaXMuaGFzaGVzLnBvcCgpO1xuXG4gICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC5pZHMpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0aGlzLnB1c2godGhpcy5vYmplY3RMaXRlcmFsKGhhc2guY29udGV4dHMpKTtcbiAgICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC50eXBlcykpO1xuICAgIH1cblxuICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC52YWx1ZXMpKTtcbiAgfSxcblxuICAvLyBbcHVzaFN0cmluZ11cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogcXVvdGVkU3RyaW5nKHN0cmluZyksIC4uLlxuICAvL1xuICAvLyBQdXNoIGEgcXVvdGVkIHZlcnNpb24gb2YgYHN0cmluZ2Agb250byB0aGUgc3RhY2tcbiAgcHVzaFN0cmluZzogZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHRoaXMucXVvdGVkU3RyaW5nKHN0cmluZykpO1xuICB9LFxuXG4gIC8vIFtwdXNoTGl0ZXJhbF1cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogdmFsdWUsIC4uLlxuICAvL1xuICAvLyBQdXNoZXMgYSB2YWx1ZSBvbnRvIHRoZSBzdGFjay4gVGhpcyBvcGVyYXRpb24gcHJldmVudHNcbiAgLy8gdGhlIGNvbXBpbGVyIGZyb20gY3JlYXRpbmcgYSB0ZW1wb3JhcnkgdmFyaWFibGUgdG8gaG9sZFxuICAvLyBpdC5cbiAgcHVzaExpdGVyYWw6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHZhbHVlKTtcbiAgfSxcblxuICAvLyBbcHVzaFByb2dyYW1dXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHByb2dyYW0oZ3VpZCksIC4uLlxuICAvL1xuICAvLyBQdXNoIGEgcHJvZ3JhbSBleHByZXNzaW9uIG9udG8gdGhlIHN0YWNrLiBUaGlzIHRha2VzXG4gIC8vIGEgY29tcGlsZS10aW1lIGd1aWQgYW5kIGNvbnZlcnRzIGl0IGludG8gYSBydW50aW1lLWFjY2Vzc2libGVcbiAgLy8gZXhwcmVzc2lvbi5cbiAgcHVzaFByb2dyYW06IGZ1bmN0aW9uKGd1aWQpIHtcbiAgICBpZiAoZ3VpZCAhPSBudWxsKSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwodGhpcy5wcm9ncmFtRXhwcmVzc2lvbihndWlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChudWxsKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gW3JlZ2lzdGVyRGVjb3JhdG9yXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBQb3BzIG9mZiB0aGUgZGVjb3JhdG9yJ3MgcGFyYW1ldGVycywgaW52b2tlcyB0aGUgZGVjb3JhdG9yLFxuICAvLyBhbmQgaW5zZXJ0cyB0aGUgZGVjb3JhdG9yIGludG8gdGhlIGRlY29yYXRvcnMgbGlzdC5cbiAgcmVnaXN0ZXJEZWNvcmF0b3IocGFyYW1TaXplLCBuYW1lKSB7XG4gICAgbGV0IGZvdW5kRGVjb3JhdG9yID0gdGhpcy5uYW1lTG9va3VwKCdkZWNvcmF0b3JzJywgbmFtZSwgJ2RlY29yYXRvcicpLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5zZXR1cEhlbHBlckFyZ3MobmFtZSwgcGFyYW1TaXplKTtcblxuICAgIHRoaXMuZGVjb3JhdG9ycy5wdXNoKFtcbiAgICAgICdmbiA9ICcsXG4gICAgICB0aGlzLmRlY29yYXRvcnMuZnVuY3Rpb25DYWxsKGZvdW5kRGVjb3JhdG9yLCAnJywgWydmbicsICdwcm9wcycsICdjb250YWluZXInLCBvcHRpb25zXSksXG4gICAgICAnIHx8IGZuOydcbiAgICBdKTtcbiAgfSxcblxuICAvLyBbaW52b2tlSGVscGVyXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJlc3VsdCBvZiBoZWxwZXIgaW52b2NhdGlvblxuICAvL1xuICAvLyBQb3BzIG9mZiB0aGUgaGVscGVyJ3MgcGFyYW1ldGVycywgaW52b2tlcyB0aGUgaGVscGVyLFxuICAvLyBhbmQgcHVzaGVzIHRoZSBoZWxwZXIncyByZXR1cm4gdmFsdWUgb250byB0aGUgc3RhY2suXG4gIC8vXG4gIC8vIElmIHRoZSBoZWxwZXIgaXMgbm90IGZvdW5kLCBgaGVscGVyTWlzc2luZ2AgaXMgY2FsbGVkLlxuICBpbnZva2VIZWxwZXI6IGZ1bmN0aW9uKHBhcmFtU2l6ZSwgbmFtZSwgaXNTaW1wbGUpIHtcbiAgICBsZXQgbm9uSGVscGVyID0gdGhpcy5wb3BTdGFjaygpLFxuICAgICAgICBoZWxwZXIgPSB0aGlzLnNldHVwSGVscGVyKHBhcmFtU2l6ZSwgbmFtZSksXG4gICAgICAgIHNpbXBsZSA9IGlzU2ltcGxlID8gW2hlbHBlci5uYW1lLCAnIHx8ICddIDogJyc7XG5cbiAgICBsZXQgbG9va3VwID0gWycoJ10uY29uY2F0KHNpbXBsZSwgbm9uSGVscGVyKTtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5zdHJpY3QpIHtcbiAgICAgIGxvb2t1cC5wdXNoKCcgfHwgJywgdGhpcy5hbGlhc2FibGUoJ2hlbHBlcnMuaGVscGVyTWlzc2luZycpKTtcbiAgICB9XG4gICAgbG9va3VwLnB1c2goJyknKTtcblxuICAgIHRoaXMucHVzaCh0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwobG9va3VwLCAnY2FsbCcsIGhlbHBlci5jYWxsUGFyYW1zKSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZUtub3duSGVscGVyXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJlc3VsdCBvZiBoZWxwZXIgaW52b2NhdGlvblxuICAvL1xuICAvLyBUaGlzIG9wZXJhdGlvbiBpcyB1c2VkIHdoZW4gdGhlIGhlbHBlciBpcyBrbm93biB0byBleGlzdCxcbiAgLy8gc28gYSBgaGVscGVyTWlzc2luZ2AgZmFsbGJhY2sgaXMgbm90IHJlcXVpcmVkLlxuICBpbnZva2VLbm93bkhlbHBlcjogZnVuY3Rpb24ocGFyYW1TaXplLCBuYW1lKSB7XG4gICAgbGV0IGhlbHBlciA9IHRoaXMuc2V0dXBIZWxwZXIocGFyYW1TaXplLCBuYW1lKTtcbiAgICB0aGlzLnB1c2godGhpcy5zb3VyY2UuZnVuY3Rpb25DYWxsKGhlbHBlci5uYW1lLCAnY2FsbCcsIGhlbHBlci5jYWxsUGFyYW1zKSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZUFtYmlndW91c11cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogaGFzaCwgaW52ZXJzZSwgcHJvZ3JhbSwgcGFyYW1zLi4uLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiByZXN1bHQgb2YgZGlzYW1iaWd1YXRpb25cbiAgLy9cbiAgLy8gVGhpcyBvcGVyYXRpb24gaXMgdXNlZCB3aGVuIGFuIGV4cHJlc3Npb24gbGlrZSBge3tmb299fWBcbiAgLy8gaXMgcHJvdmlkZWQsIGJ1dCB3ZSBkb24ndCBrbm93IGF0IGNvbXBpbGUtdGltZSB3aGV0aGVyIGl0XG4gIC8vIGlzIGEgaGVscGVyIG9yIGEgcGF0aC5cbiAgLy9cbiAgLy8gVGhpcyBvcGVyYXRpb24gZW1pdHMgbW9yZSBjb2RlIHRoYW4gdGhlIG90aGVyIG9wdGlvbnMsXG4gIC8vIGFuZCBjYW4gYmUgYXZvaWRlZCBieSBwYXNzaW5nIHRoZSBga25vd25IZWxwZXJzYCBhbmRcbiAgLy8gYGtub3duSGVscGVyc09ubHlgIGZsYWdzIGF0IGNvbXBpbGUtdGltZS5cbiAgaW52b2tlQW1iaWd1b3VzOiBmdW5jdGlvbihuYW1lLCBoZWxwZXJDYWxsKSB7XG4gICAgdGhpcy51c2VSZWdpc3RlcignaGVscGVyJyk7XG5cbiAgICBsZXQgbm9uSGVscGVyID0gdGhpcy5wb3BTdGFjaygpO1xuXG4gICAgdGhpcy5lbXB0eUhhc2goKTtcbiAgICBsZXQgaGVscGVyID0gdGhpcy5zZXR1cEhlbHBlcigwLCBuYW1lLCBoZWxwZXJDYWxsKTtcblxuICAgIGxldCBoZWxwZXJOYW1lID0gdGhpcy5sYXN0SGVscGVyID0gdGhpcy5uYW1lTG9va3VwKCdoZWxwZXJzJywgbmFtZSwgJ2hlbHBlcicpO1xuXG4gICAgbGV0IGxvb2t1cCA9IFsnKCcsICcoaGVscGVyID0gJywgaGVscGVyTmFtZSwgJyB8fCAnLCBub25IZWxwZXIsICcpJ107XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICBsb29rdXBbMF0gPSAnKGhlbHBlciA9ICc7XG4gICAgICBsb29rdXAucHVzaChcbiAgICAgICAgJyAhPSBudWxsID8gaGVscGVyIDogJyxcbiAgICAgICAgdGhpcy5hbGlhc2FibGUoJ2hlbHBlcnMuaGVscGVyTWlzc2luZycpXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMucHVzaChbXG4gICAgICAgICcoJywgbG9va3VwLFxuICAgICAgICAoaGVscGVyLnBhcmFtc0luaXQgPyBbJyksKCcsIGhlbHBlci5wYXJhbXNJbml0XSA6IFtdKSwgJyksJyxcbiAgICAgICAgJyh0eXBlb2YgaGVscGVyID09PSAnLCB0aGlzLmFsaWFzYWJsZSgnXCJmdW5jdGlvblwiJyksICcgPyAnLFxuICAgICAgICB0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwoJ2hlbHBlcicsICdjYWxsJywgaGVscGVyLmNhbGxQYXJhbXMpLCAnIDogaGVscGVyKSknXG4gICAgXSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZVBhcnRpYWxdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IGNvbnRleHQsIC4uLlxuICAvLyBPbiBzdGFjayBhZnRlcjogcmVzdWx0IG9mIHBhcnRpYWwgaW52b2NhdGlvblxuICAvL1xuICAvLyBUaGlzIG9wZXJhdGlvbiBwb3BzIG9mZiBhIGNvbnRleHQsIGludm9rZXMgYSBwYXJ0aWFsIHdpdGggdGhhdCBjb250ZXh0LFxuICAvLyBhbmQgcHVzaGVzIHRoZSByZXN1bHQgb2YgdGhlIGludm9jYXRpb24gYmFjay5cbiAgaW52b2tlUGFydGlhbDogZnVuY3Rpb24oaXNEeW5hbWljLCBuYW1lLCBpbmRlbnQpIHtcbiAgICBsZXQgcGFyYW1zID0gW10sXG4gICAgICAgIG9wdGlvbnMgPSB0aGlzLnNldHVwUGFyYW1zKG5hbWUsIDEsIHBhcmFtcyk7XG5cbiAgICBpZiAoaXNEeW5hbWljKSB7XG4gICAgICBuYW1lID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgZGVsZXRlIG9wdGlvbnMubmFtZTtcbiAgICB9XG5cbiAgICBpZiAoaW5kZW50KSB7XG4gICAgICBvcHRpb25zLmluZGVudCA9IEpTT04uc3RyaW5naWZ5KGluZGVudCk7XG4gICAgfVxuICAgIG9wdGlvbnMuaGVscGVycyA9ICdoZWxwZXJzJztcbiAgICBvcHRpb25zLnBhcnRpYWxzID0gJ3BhcnRpYWxzJztcbiAgICBvcHRpb25zLmRlY29yYXRvcnMgPSAnY29udGFpbmVyLmRlY29yYXRvcnMnO1xuXG4gICAgaWYgKCFpc0R5bmFtaWMpIHtcbiAgICAgIHBhcmFtcy51bnNoaWZ0KHRoaXMubmFtZUxvb2t1cCgncGFydGlhbHMnLCBuYW1lLCAncGFydGlhbCcpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFyYW1zLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5jb21wYXQpIHtcbiAgICAgIG9wdGlvbnMuZGVwdGhzID0gJ2RlcHRocyc7XG4gICAgfVxuICAgIG9wdGlvbnMgPSB0aGlzLm9iamVjdExpdGVyYWwob3B0aW9ucyk7XG4gICAgcGFyYW1zLnB1c2gob3B0aW9ucyk7XG5cbiAgICB0aGlzLnB1c2godGhpcy5zb3VyY2UuZnVuY3Rpb25DYWxsKCdjb250YWluZXIuaW52b2tlUGFydGlhbCcsICcnLCBwYXJhbXMpKTtcbiAgfSxcblxuICAvLyBbYXNzaWduVG9IYXNoXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiB2YWx1ZSwgLi4uLCBoYXNoLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiAuLi4sIGhhc2gsIC4uLlxuICAvL1xuICAvLyBQb3BzIGEgdmFsdWUgb2ZmIHRoZSBzdGFjayBhbmQgYXNzaWducyBpdCB0byB0aGUgY3VycmVudCBoYXNoXG4gIGFzc2lnblRvSGFzaDogZnVuY3Rpb24oa2V5KSB7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5wb3BTdGFjaygpLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICB0eXBlLFxuICAgICAgICBpZDtcblxuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICBpZCA9IHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0eXBlID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgY29udGV4dCA9IHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG5cbiAgICBsZXQgaGFzaCA9IHRoaXMuaGFzaDtcbiAgICBpZiAoY29udGV4dCkge1xuICAgICAgaGFzaC5jb250ZXh0c1trZXldID0gY29udGV4dDtcbiAgICB9XG4gICAgaWYgKHR5cGUpIHtcbiAgICAgIGhhc2gudHlwZXNba2V5XSA9IHR5cGU7XG4gICAgfVxuICAgIGlmIChpZCkge1xuICAgICAgaGFzaC5pZHNba2V5XSA9IGlkO1xuICAgIH1cbiAgICBoYXNoLnZhbHVlc1trZXldID0gdmFsdWU7XG4gIH0sXG5cbiAgcHVzaElkOiBmdW5jdGlvbih0eXBlLCBuYW1lLCBjaGlsZCkge1xuICAgIGlmICh0eXBlID09PSAnQmxvY2tQYXJhbScpIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChcbiAgICAgICAgICAnYmxvY2tQYXJhbXNbJyArIG5hbWVbMF0gKyAnXS5wYXRoWycgKyBuYW1lWzFdICsgJ10nXG4gICAgICAgICAgKyAoY2hpbGQgPyAnICsgJyArIEpTT04uc3RyaW5naWZ5KCcuJyArIGNoaWxkKSA6ICcnKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnUGF0aEV4cHJlc3Npb24nKSB7XG4gICAgICB0aGlzLnB1c2hTdHJpbmcobmFtZSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbCgndHJ1ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwoJ251bGwnKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gSEVMUEVSU1xuXG4gIGNvbXBpbGVyOiBKYXZhU2NyaXB0Q29tcGlsZXIsXG5cbiAgY29tcGlsZUNoaWxkcmVuOiBmdW5jdGlvbihlbnZpcm9ubWVudCwgb3B0aW9ucykge1xuICAgIGxldCBjaGlsZHJlbiA9IGVudmlyb25tZW50LmNoaWxkcmVuLCBjaGlsZCwgY29tcGlsZXI7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IGNoaWxkcmVuLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgIGNvbXBpbGVyID0gbmV3IHRoaXMuY29tcGlsZXIoKTsgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuZXctY2FwXG5cbiAgICAgIGxldCBleGlzdGluZyA9IHRoaXMubWF0Y2hFeGlzdGluZ1Byb2dyYW0oY2hpbGQpO1xuXG4gICAgICBpZiAoZXhpc3RpbmcgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmNvbnRleHQucHJvZ3JhbXMucHVzaCgnJyk7ICAgICAvLyBQbGFjZWhvbGRlciB0byBwcmV2ZW50IG5hbWUgY29uZmxpY3RzIGZvciBuZXN0ZWQgY2hpbGRyZW5cbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5jb250ZXh0LnByb2dyYW1zLmxlbmd0aDtcbiAgICAgICAgY2hpbGQuaW5kZXggPSBpbmRleDtcbiAgICAgICAgY2hpbGQubmFtZSA9ICdwcm9ncmFtJyArIGluZGV4O1xuICAgICAgICB0aGlzLmNvbnRleHQucHJvZ3JhbXNbaW5kZXhdID0gY29tcGlsZXIuY29tcGlsZShjaGlsZCwgb3B0aW9ucywgdGhpcy5jb250ZXh0LCAhdGhpcy5wcmVjb21waWxlKTtcbiAgICAgICAgdGhpcy5jb250ZXh0LmRlY29yYXRvcnNbaW5kZXhdID0gY29tcGlsZXIuZGVjb3JhdG9ycztcbiAgICAgICAgdGhpcy5jb250ZXh0LmVudmlyb25tZW50c1tpbmRleF0gPSBjaGlsZDtcblxuICAgICAgICB0aGlzLnVzZURlcHRocyA9IHRoaXMudXNlRGVwdGhzIHx8IGNvbXBpbGVyLnVzZURlcHRocztcbiAgICAgICAgdGhpcy51c2VCbG9ja1BhcmFtcyA9IHRoaXMudXNlQmxvY2tQYXJhbXMgfHwgY29tcGlsZXIudXNlQmxvY2tQYXJhbXM7XG4gICAgICAgIGNoaWxkLnVzZURlcHRocyA9IHRoaXMudXNlRGVwdGhzO1xuICAgICAgICBjaGlsZC51c2VCbG9ja1BhcmFtcyA9IHRoaXMudXNlQmxvY2tQYXJhbXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGlsZC5pbmRleCA9IGV4aXN0aW5nLmluZGV4O1xuICAgICAgICBjaGlsZC5uYW1lID0gJ3Byb2dyYW0nICsgZXhpc3RpbmcuaW5kZXg7XG5cbiAgICAgICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCBleGlzdGluZy51c2VEZXB0aHM7XG4gICAgICAgIHRoaXMudXNlQmxvY2tQYXJhbXMgPSB0aGlzLnVzZUJsb2NrUGFyYW1zIHx8IGV4aXN0aW5nLnVzZUJsb2NrUGFyYW1zO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgbWF0Y2hFeGlzdGluZ1Byb2dyYW06IGZ1bmN0aW9uKGNoaWxkKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRoaXMuY29udGV4dC5lbnZpcm9ubWVudHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGxldCBlbnZpcm9ubWVudCA9IHRoaXMuY29udGV4dC5lbnZpcm9ubWVudHNbaV07XG4gICAgICBpZiAoZW52aXJvbm1lbnQgJiYgZW52aXJvbm1lbnQuZXF1YWxzKGNoaWxkKSkge1xuICAgICAgICByZXR1cm4gZW52aXJvbm1lbnQ7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIHByb2dyYW1FeHByZXNzaW9uOiBmdW5jdGlvbihndWlkKSB7XG4gICAgbGV0IGNoaWxkID0gdGhpcy5lbnZpcm9ubWVudC5jaGlsZHJlbltndWlkXSxcbiAgICAgICAgcHJvZ3JhbVBhcmFtcyA9IFtjaGlsZC5pbmRleCwgJ2RhdGEnLCBjaGlsZC5ibG9ja1BhcmFtc107XG5cbiAgICBpZiAodGhpcy51c2VCbG9ja1BhcmFtcyB8fCB0aGlzLnVzZURlcHRocykge1xuICAgICAgcHJvZ3JhbVBhcmFtcy5wdXNoKCdibG9ja1BhcmFtcycpO1xuICAgIH1cbiAgICBpZiAodGhpcy51c2VEZXB0aHMpIHtcbiAgICAgIHByb2dyYW1QYXJhbXMucHVzaCgnZGVwdGhzJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICdjb250YWluZXIucHJvZ3JhbSgnICsgcHJvZ3JhbVBhcmFtcy5qb2luKCcsICcpICsgJyknO1xuICB9LFxuXG4gIHVzZVJlZ2lzdGVyOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLnJlZ2lzdGVyc1tuYW1lXSkge1xuICAgICAgdGhpcy5yZWdpc3RlcnNbbmFtZV0gPSB0cnVlO1xuICAgICAgdGhpcy5yZWdpc3RlcnMubGlzdC5wdXNoKG5hbWUpO1xuICAgIH1cbiAgfSxcblxuICBwdXNoOiBmdW5jdGlvbihleHByKSB7XG4gICAgaWYgKCEoZXhwciBpbnN0YW5jZW9mIExpdGVyYWwpKSB7XG4gICAgICBleHByID0gdGhpcy5zb3VyY2Uud3JhcChleHByKTtcbiAgICB9XG5cbiAgICB0aGlzLmlubGluZVN0YWNrLnB1c2goZXhwcik7XG4gICAgcmV0dXJuIGV4cHI7XG4gIH0sXG5cbiAgcHVzaFN0YWNrTGl0ZXJhbDogZnVuY3Rpb24oaXRlbSkge1xuICAgIHRoaXMucHVzaChuZXcgTGl0ZXJhbChpdGVtKSk7XG4gIH0sXG5cbiAgcHVzaFNvdXJjZTogZnVuY3Rpb24oc291cmNlKSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIHRoaXMuc291cmNlLnB1c2goXG4gICAgICAgICAgdGhpcy5hcHBlbmRUb0J1ZmZlcih0aGlzLnNvdXJjZS5xdW90ZWRTdHJpbmcodGhpcy5wZW5kaW5nQ29udGVudCksIHRoaXMucGVuZGluZ0xvY2F0aW9uKSk7XG4gICAgICB0aGlzLnBlbmRpbmdDb250ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgIHRoaXMuc291cmNlLnB1c2goc291cmNlKTtcbiAgICB9XG4gIH0sXG5cbiAgcmVwbGFjZVN0YWNrOiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIGxldCBwcmVmaXggPSBbJygnXSxcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIGNyZWF0ZWRTdGFjayxcbiAgICAgICAgdXNlZExpdGVyYWw7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICghdGhpcy5pc0lubGluZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdyZXBsYWNlU3RhY2sgb24gbm9uLWlubGluZScpO1xuICAgIH1cblxuICAgIC8vIFdlIHdhbnQgdG8gbWVyZ2UgdGhlIGlubGluZSBzdGF0ZW1lbnQgaW50byB0aGUgcmVwbGFjZW1lbnQgc3RhdGVtZW50IHZpYSAnLCdcbiAgICBsZXQgdG9wID0gdGhpcy5wb3BTdGFjayh0cnVlKTtcblxuICAgIGlmICh0b3AgaW5zdGFuY2VvZiBMaXRlcmFsKSB7XG4gICAgICAvLyBMaXRlcmFscyBkbyBub3QgbmVlZCB0byBiZSBpbmxpbmVkXG4gICAgICBzdGFjayA9IFt0b3AudmFsdWVdO1xuICAgICAgcHJlZml4ID0gWycoJywgc3RhY2tdO1xuICAgICAgdXNlZExpdGVyYWwgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBHZXQgb3IgY3JlYXRlIHRoZSBjdXJyZW50IHN0YWNrIG5hbWUgZm9yIHVzZSBieSB0aGUgaW5saW5lXG4gICAgICBjcmVhdGVkU3RhY2sgPSB0cnVlO1xuICAgICAgbGV0IG5hbWUgPSB0aGlzLmluY3JTdGFjaygpO1xuXG4gICAgICBwcmVmaXggPSBbJygoJywgdGhpcy5wdXNoKG5hbWUpLCAnID0gJywgdG9wLCAnKSddO1xuICAgICAgc3RhY2sgPSB0aGlzLnRvcFN0YWNrKCk7XG4gICAgfVxuXG4gICAgbGV0IGl0ZW0gPSBjYWxsYmFjay5jYWxsKHRoaXMsIHN0YWNrKTtcblxuICAgIGlmICghdXNlZExpdGVyYWwpIHtcbiAgICAgIHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG4gICAgaWYgKGNyZWF0ZWRTdGFjaykge1xuICAgICAgdGhpcy5zdGFja1Nsb3QtLTtcbiAgICB9XG4gICAgdGhpcy5wdXNoKHByZWZpeC5jb25jYXQoaXRlbSwgJyknKSk7XG4gIH0sXG5cbiAgaW5jclN0YWNrOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnN0YWNrU2xvdCsrO1xuICAgIGlmICh0aGlzLnN0YWNrU2xvdCA+IHRoaXMuc3RhY2tWYXJzLmxlbmd0aCkgeyB0aGlzLnN0YWNrVmFycy5wdXNoKCdzdGFjaycgKyB0aGlzLnN0YWNrU2xvdCk7IH1cbiAgICByZXR1cm4gdGhpcy50b3BTdGFja05hbWUoKTtcbiAgfSxcbiAgdG9wU3RhY2tOYW1lOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gJ3N0YWNrJyArIHRoaXMuc3RhY2tTbG90O1xuICB9LFxuICBmbHVzaElubGluZTogZnVuY3Rpb24oKSB7XG4gICAgbGV0IGlubGluZVN0YWNrID0gdGhpcy5pbmxpbmVTdGFjaztcbiAgICB0aGlzLmlubGluZVN0YWNrID0gW107XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGlubGluZVN0YWNrLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBsZXQgZW50cnkgPSBpbmxpbmVTdGFja1tpXTtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgTGl0ZXJhbCkge1xuICAgICAgICB0aGlzLmNvbXBpbGVTdGFjay5wdXNoKGVudHJ5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBzdGFjayA9IHRoaXMuaW5jclN0YWNrKCk7XG4gICAgICAgIHRoaXMucHVzaFNvdXJjZShbc3RhY2ssICcgPSAnLCBlbnRyeSwgJzsnXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVN0YWNrLnB1c2goc3RhY2spO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgaXNJbmxpbmU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmlubGluZVN0YWNrLmxlbmd0aDtcbiAgfSxcblxuICBwb3BTdGFjazogZnVuY3Rpb24od3JhcHBlZCkge1xuICAgIGxldCBpbmxpbmUgPSB0aGlzLmlzSW5saW5lKCksXG4gICAgICAgIGl0ZW0gPSAoaW5saW5lID8gdGhpcy5pbmxpbmVTdGFjayA6IHRoaXMuY29tcGlsZVN0YWNrKS5wb3AoKTtcblxuICAgIGlmICghd3JhcHBlZCAmJiAoaXRlbSBpbnN0YW5jZW9mIExpdGVyYWwpKSB7XG4gICAgICByZXR1cm4gaXRlbS52YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFpbmxpbmUpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgaWYgKCF0aGlzLnN0YWNrU2xvdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0ludmFsaWQgc3RhY2sgcG9wJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGFja1Nsb3QtLTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgfSxcblxuICB0b3BTdGFjazogZnVuY3Rpb24oKSB7XG4gICAgbGV0IHN0YWNrID0gKHRoaXMuaXNJbmxpbmUoKSA/IHRoaXMuaW5saW5lU3RhY2sgOiB0aGlzLmNvbXBpbGVTdGFjayksXG4gICAgICAgIGl0ZW0gPSBzdGFja1tzdGFjay5sZW5ndGggLSAxXTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChpdGVtIGluc3RhbmNlb2YgTGl0ZXJhbCkge1xuICAgICAgcmV0dXJuIGl0ZW0udmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgfSxcblxuICBjb250ZXh0TmFtZTogZnVuY3Rpb24oY29udGV4dCkge1xuICAgIGlmICh0aGlzLnVzZURlcHRocyAmJiBjb250ZXh0KSB7XG4gICAgICByZXR1cm4gJ2RlcHRoc1snICsgY29udGV4dCArICddJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICdkZXB0aCcgKyBjb250ZXh0O1xuICAgIH1cbiAgfSxcblxuICBxdW90ZWRTdHJpbmc6IGZ1bmN0aW9uKHN0cikge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZS5xdW90ZWRTdHJpbmcoc3RyKTtcbiAgfSxcblxuICBvYmplY3RMaXRlcmFsOiBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdGhpcy5zb3VyY2Uub2JqZWN0TGl0ZXJhbChvYmopO1xuICB9LFxuXG4gIGFsaWFzYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGxldCByZXQgPSB0aGlzLmFsaWFzZXNbbmFtZV07XG4gICAgaWYgKHJldCkge1xuICAgICAgcmV0LnJlZmVyZW5jZUNvdW50Kys7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIHJldCA9IHRoaXMuYWxpYXNlc1tuYW1lXSA9IHRoaXMuc291cmNlLndyYXAobmFtZSk7XG4gICAgcmV0LmFsaWFzYWJsZSA9IHRydWU7XG4gICAgcmV0LnJlZmVyZW5jZUNvdW50ID0gMTtcblxuICAgIHJldHVybiByZXQ7XG4gIH0sXG5cbiAgc2V0dXBIZWxwZXI6IGZ1bmN0aW9uKHBhcmFtU2l6ZSwgbmFtZSwgYmxvY2tIZWxwZXIpIHtcbiAgICBsZXQgcGFyYW1zID0gW10sXG4gICAgICAgIHBhcmFtc0luaXQgPSB0aGlzLnNldHVwSGVscGVyQXJncyhuYW1lLCBwYXJhbVNpemUsIHBhcmFtcywgYmxvY2tIZWxwZXIpO1xuICAgIGxldCBmb3VuZEhlbHBlciA9IHRoaXMubmFtZUxvb2t1cCgnaGVscGVycycsIG5hbWUsICdoZWxwZXInKSxcbiAgICAgICAgY2FsbENvbnRleHQgPSB0aGlzLmFsaWFzYWJsZShgJHt0aGlzLmNvbnRleHROYW1lKDApfSAhPSBudWxsID8gJHt0aGlzLmNvbnRleHROYW1lKDApfSA6IHt9YCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFyYW1zOiBwYXJhbXMsXG4gICAgICBwYXJhbXNJbml0OiBwYXJhbXNJbml0LFxuICAgICAgbmFtZTogZm91bmRIZWxwZXIsXG4gICAgICBjYWxsUGFyYW1zOiBbY2FsbENvbnRleHRdLmNvbmNhdChwYXJhbXMpXG4gICAgfTtcbiAgfSxcblxuICBzZXR1cFBhcmFtczogZnVuY3Rpb24oaGVscGVyLCBwYXJhbVNpemUsIHBhcmFtcykge1xuICAgIGxldCBvcHRpb25zID0ge30sXG4gICAgICAgIGNvbnRleHRzID0gW10sXG4gICAgICAgIHR5cGVzID0gW10sXG4gICAgICAgIGlkcyA9IFtdLFxuICAgICAgICBvYmplY3RBcmdzID0gIXBhcmFtcyxcbiAgICAgICAgcGFyYW07XG5cbiAgICBpZiAob2JqZWN0QXJncykge1xuICAgICAgcGFyYW1zID0gW107XG4gICAgfVxuXG4gICAgb3B0aW9ucy5uYW1lID0gdGhpcy5xdW90ZWRTdHJpbmcoaGVscGVyKTtcbiAgICBvcHRpb25zLmhhc2ggPSB0aGlzLnBvcFN0YWNrKCk7XG5cbiAgICBpZiAodGhpcy50cmFja0lkcykge1xuICAgICAgb3B0aW9ucy5oYXNoSWRzID0gdGhpcy5wb3BTdGFjaygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdHJpbmdQYXJhbXMpIHtcbiAgICAgIG9wdGlvbnMuaGFzaFR5cGVzID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgb3B0aW9ucy5oYXNoQ29udGV4dHMgPSB0aGlzLnBvcFN0YWNrKCk7XG4gICAgfVxuXG4gICAgbGV0IGludmVyc2UgPSB0aGlzLnBvcFN0YWNrKCksXG4gICAgICAgIHByb2dyYW0gPSB0aGlzLnBvcFN0YWNrKCk7XG5cbiAgICAvLyBBdm9pZCBzZXR0aW5nIGZuIGFuZCBpbnZlcnNlIGlmIG5laXRoZXIgYXJlIHNldC4gVGhpcyBhbGxvd3NcbiAgICAvLyBoZWxwZXJzIHRvIGRvIGEgY2hlY2sgZm9yIGBpZiAob3B0aW9ucy5mbilgXG4gICAgaWYgKHByb2dyYW0gfHwgaW52ZXJzZSkge1xuICAgICAgb3B0aW9ucy5mbiA9IHByb2dyYW0gfHwgJ2NvbnRhaW5lci5ub29wJztcbiAgICAgIG9wdGlvbnMuaW52ZXJzZSA9IGludmVyc2UgfHwgJ2NvbnRhaW5lci5ub29wJztcbiAgICB9XG5cbiAgICAvLyBUaGUgcGFyYW1ldGVycyBnbyBvbiB0byB0aGUgc3RhY2sgaW4gb3JkZXIgKG1ha2luZyBzdXJlIHRoYXQgdGhleSBhcmUgZXZhbHVhdGVkIGluIG9yZGVyKVxuICAgIC8vIHNvIHdlIG5lZWQgdG8gcG9wIHRoZW0gb2ZmIHRoZSBzdGFjayBpbiByZXZlcnNlIG9yZGVyXG4gICAgbGV0IGkgPSBwYXJhbVNpemU7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgcGFyYW0gPSB0aGlzLnBvcFN0YWNrKCk7XG4gICAgICBwYXJhbXNbaV0gPSBwYXJhbTtcblxuICAgICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgICAgaWRzW2ldID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICAgIHR5cGVzW2ldID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgICBjb250ZXh0c1tpXSA9IHRoaXMucG9wU3RhY2soKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob2JqZWN0QXJncykge1xuICAgICAgb3B0aW9ucy5hcmdzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheShwYXJhbXMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICBvcHRpb25zLmlkcyA9IHRoaXMuc291cmNlLmdlbmVyYXRlQXJyYXkoaWRzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICBvcHRpb25zLnR5cGVzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheSh0eXBlcyk7XG4gICAgICBvcHRpb25zLmNvbnRleHRzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheShjb250ZXh0cyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kYXRhKSB7XG4gICAgICBvcHRpb25zLmRhdGEgPSAnZGF0YSc7XG4gICAgfVxuICAgIGlmICh0aGlzLnVzZUJsb2NrUGFyYW1zKSB7XG4gICAgICBvcHRpb25zLmJsb2NrUGFyYW1zID0gJ2Jsb2NrUGFyYW1zJztcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH0sXG5cbiAgc2V0dXBIZWxwZXJBcmdzOiBmdW5jdGlvbihoZWxwZXIsIHBhcmFtU2l6ZSwgcGFyYW1zLCB1c2VSZWdpc3Rlcikge1xuICAgIGxldCBvcHRpb25zID0gdGhpcy5zZXR1cFBhcmFtcyhoZWxwZXIsIHBhcmFtU2l6ZSwgcGFyYW1zKTtcbiAgICBvcHRpb25zID0gdGhpcy5vYmplY3RMaXRlcmFsKG9wdGlvbnMpO1xuICAgIGlmICh1c2VSZWdpc3Rlcikge1xuICAgICAgdGhpcy51c2VSZWdpc3Rlcignb3B0aW9ucycpO1xuICAgICAgcGFyYW1zLnB1c2goJ29wdGlvbnMnKTtcbiAgICAgIHJldHVybiBbJ29wdGlvbnM9Jywgb3B0aW9uc107XG4gICAgfSBlbHNlIGlmIChwYXJhbXMpIHtcbiAgICAgIHBhcmFtcy5wdXNoKG9wdGlvbnMpO1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9XG4gIH1cbn07XG5cblxuKGZ1bmN0aW9uKCkge1xuICBjb25zdCByZXNlcnZlZFdvcmRzID0gKFxuICAgICdicmVhayBlbHNlIG5ldyB2YXInICtcbiAgICAnIGNhc2UgZmluYWxseSByZXR1cm4gdm9pZCcgK1xuICAgICcgY2F0Y2ggZm9yIHN3aXRjaCB3aGlsZScgK1xuICAgICcgY29udGludWUgZnVuY3Rpb24gdGhpcyB3aXRoJyArXG4gICAgJyBkZWZhdWx0IGlmIHRocm93JyArXG4gICAgJyBkZWxldGUgaW4gdHJ5JyArXG4gICAgJyBkbyBpbnN0YW5jZW9mIHR5cGVvZicgK1xuICAgICcgYWJzdHJhY3QgZW51bSBpbnQgc2hvcnQnICtcbiAgICAnIGJvb2xlYW4gZXhwb3J0IGludGVyZmFjZSBzdGF0aWMnICtcbiAgICAnIGJ5dGUgZXh0ZW5kcyBsb25nIHN1cGVyJyArXG4gICAgJyBjaGFyIGZpbmFsIG5hdGl2ZSBzeW5jaHJvbml6ZWQnICtcbiAgICAnIGNsYXNzIGZsb2F0IHBhY2thZ2UgdGhyb3dzJyArXG4gICAgJyBjb25zdCBnb3RvIHByaXZhdGUgdHJhbnNpZW50JyArXG4gICAgJyBkZWJ1Z2dlciBpbXBsZW1lbnRzIHByb3RlY3RlZCB2b2xhdGlsZScgK1xuICAgICcgZG91YmxlIGltcG9ydCBwdWJsaWMgbGV0IHlpZWxkIGF3YWl0JyArXG4gICAgJyBudWxsIHRydWUgZmFsc2UnXG4gICkuc3BsaXQoJyAnKTtcblxuICBjb25zdCBjb21waWxlcldvcmRzID0gSmF2YVNjcmlwdENvbXBpbGVyLlJFU0VSVkVEX1dPUkRTID0ge307XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSByZXNlcnZlZFdvcmRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGNvbXBpbGVyV29yZHNbcmVzZXJ2ZWRXb3Jkc1tpXV0gPSB0cnVlO1xuICB9XG59KCkpO1xuXG5KYXZhU2NyaXB0Q29tcGlsZXIuaXNWYWxpZEphdmFTY3JpcHRWYXJpYWJsZU5hbWUgPSBmdW5jdGlvbihuYW1lKSB7XG4gIHJldHVybiAhSmF2YVNjcmlwdENvbXBpbGVyLlJFU0VSVkVEX1dPUkRTW25hbWVdICYmICgvXlthLXpBLVpfJF1bMC05YS16QS1aXyRdKiQvKS50ZXN0KG5hbWUpO1xufTtcblxuZnVuY3Rpb24gc3RyaWN0TG9va3VwKHJlcXVpcmVUZXJtaW5hbCwgY29tcGlsZXIsIHBhcnRzLCB0eXBlKSB7XG4gIGxldCBzdGFjayA9IGNvbXBpbGVyLnBvcFN0YWNrKCksXG4gICAgICBpID0gMCxcbiAgICAgIGxlbiA9IHBhcnRzLmxlbmd0aDtcbiAgaWYgKHJlcXVpcmVUZXJtaW5hbCkge1xuICAgIGxlbi0tO1xuICB9XG5cbiAgZm9yICg7IGkgPCBsZW47IGkrKykge1xuICAgIHN0YWNrID0gY29tcGlsZXIubmFtZUxvb2t1cChzdGFjaywgcGFydHNbaV0sIHR5cGUpO1xuICB9XG5cbiAgaWYgKHJlcXVpcmVUZXJtaW5hbCkge1xuICAgIHJldHVybiBbY29tcGlsZXIuYWxpYXNhYmxlKCdjb250YWluZXIuc3RyaWN0JyksICcoJywgc3RhY2ssICcsICcsIGNvbXBpbGVyLnF1b3RlZFN0cmluZyhwYXJ0c1tpXSksICcpJ107XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0YWNrO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEphdmFTY3JpcHRDb21waWxlcjtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js new file mode 100644 index 0000000..cef854c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js @@ -0,0 +1,738 @@ +/* istanbul ignore next */ +/* Jison generated parser */ +"use strict"; + +var handlebars = (function () { + var parser = { trace: function trace() {}, + yy: {}, + symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 }, + terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" }, + productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$ + /**/) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: + return $$[$0 - 1]; + break; + case 2: + this.$ = yy.prepareProgram($$[$0]); + break; + case 3: + this.$ = $$[$0]; + break; + case 4: + this.$ = $$[$0]; + break; + case 5: + this.$ = $$[$0]; + break; + case 6: + this.$ = $$[$0]; + break; + case 7: + this.$ = $$[$0]; + break; + case 8: + this.$ = $$[$0]; + break; + case 9: + this.$ = { + type: 'CommentStatement', + value: yy.stripComment($$[$0]), + strip: yy.stripFlags($$[$0], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 10: + this.$ = { + type: 'ContentStatement', + original: $$[$0], + value: $$[$0], + loc: yy.locInfo(this._$) + }; + + break; + case 11: + this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 12: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] }; + break; + case 13: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$); + break; + case 14: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$); + break; + case 15: + this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 16: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 17: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 18: + this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] }; + break; + case 19: + var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$), + program = yy.prepareProgram([inverse], $$[$0 - 1].loc); + program.chained = true; + + this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true }; + + break; + case 20: + this.$ = $$[$0]; + break; + case 21: + this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) }; + break; + case 22: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 23: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 24: + this.$ = { + type: 'PartialStatement', + name: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + indent: '', + strip: yy.stripFlags($$[$0 - 4], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 25: + this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 26: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) }; + break; + case 27: + this.$ = $$[$0]; + break; + case 28: + this.$ = $$[$0]; + break; + case 29: + this.$ = { + type: 'SubExpression', + path: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + loc: yy.locInfo(this._$) + }; + + break; + case 30: + this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 31: + this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 32: + this.$ = yy.id($$[$0 - 1]); + break; + case 33: + this.$ = $$[$0]; + break; + case 34: + this.$ = $$[$0]; + break; + case 35: + this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 36: + this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) }; + break; + case 37: + this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) }; + break; + case 38: + this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) }; + break; + case 39: + this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) }; + break; + case 40: + this.$ = $$[$0]; + break; + case 41: + this.$ = $$[$0]; + break; + case 42: + this.$ = yy.preparePath(true, $$[$0], this._$); + break; + case 43: + this.$ = yy.preparePath(false, $$[$0], this._$); + break; + case 44: + $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2]; + break; + case 45: + this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }]; + break; + case 46: + this.$ = []; + break; + case 47: + $$[$0 - 1].push($$[$0]); + break; + case 48: + this.$ = [$$[$0]]; + break; + case 49: + $$[$0 - 1].push($$[$0]); + break; + case 50: + this.$ = []; + break; + case 51: + $$[$0 - 1].push($$[$0]); + break; + case 58: + this.$ = []; + break; + case 59: + $$[$0 - 1].push($$[$0]); + break; + case 64: + this.$ = []; + break; + case 65: + $$[$0 - 1].push($$[$0]); + break; + case 70: + this.$ = []; + break; + case 71: + $$[$0 - 1].push($$[$0]); + break; + case 78: + this.$ = []; + break; + case 79: + $$[$0 - 1].push($$[$0]); + break; + case 82: + this.$ = []; + break; + case 83: + $$[$0 - 1].push($$[$0]); + break; + case 86: + this.$ = []; + break; + case 87: + $$[$0 - 1].push($$[$0]); + break; + case 90: + this.$ = []; + break; + case 91: + $$[$0 - 1].push($$[$0]); + break; + case 94: + this.$ = []; + break; + case 95: + $$[$0 - 1].push($$[$0]); + break; + case 98: + this.$ = [$$[$0]]; + break; + case 99: + $$[$0 - 1].push($$[$0]); + break; + case 100: + this.$ = [$$[$0]]; + break; + case 101: + $$[$0 - 1].push($$[$0]); + break; + } + }, + table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }], + defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137: [2, 32] }, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], + lstack = [], + table = this.table, + yytext = "", + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, + preErrorSymbol, + state, + action, + a, + r, + yyval = {}, + p, + len, + newState, + expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected }); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; + } + }; + /* Jison generated lexer */ + var lexer = (function () { + var lexer = { EOF: 1, + parseError: function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput: function setInput(input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; + if (this.options.ranges) this.yylloc.range = [0, 0]; + this.offset = 0; + return this; + }, + input: function input() { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, + unput: function unput(ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); + + if (lines.length - 1) this.yylineno -= lines.length - 1; + var r = this.yylloc.range; + + this.yylloc = { first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, + more: function more() { + this._more = true; + return this; + }, + less: function less(n) { + this.unput(this.match.slice(n)); + }, + pastInput: function pastInput() { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput: function upcomingInput() { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20 - next.length); + } + return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, + showPosition: function showPosition() { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, + next: function next() { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, match, tempMatch, index, col, lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = { first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) this.done = false; + if (token) return token;else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); + } + }, + lex: function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin: function begin(condition) { + this.conditionStack.push(condition); + }, + popState: function popState() { + return this.conditionStack.pop(); + }, + _currentRules: function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + }, + topState: function topState() { + return this.conditionStack[this.conditionStack.length - 2]; + }, + pushState: function begin(condition) { + this.begin(condition); + } }; + lexer.options = {}; + lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START + /**/) { + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end); + } + + var YYSTATE = YY_START; + switch ($avoiding_name_collisions) { + case 0: + if (yy_.yytext.slice(-2) === "\\\\") { + strip(0, 1); + this.begin("mu"); + } else if (yy_.yytext.slice(-1) === "\\") { + strip(0, 1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if (yy_.yytext) return 15; + + break; + case 1: + return 15; + break; + case 2: + this.popState(); + return 15; + + break; + case 3: + this.begin('raw');return 15; + break; + case 4: + this.popState(); + // Should be using `this.topState()` below, but it currently + // returns the second top instead of the first top. Opened an + // issue about it at https://github.com/zaach/jison/issues/291 + if (this.conditionStack[this.conditionStack.length - 1] === 'raw') { + return 15; + } else { + yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9); + return 'END_RAW_BLOCK'; + } + + break; + case 5: + return 15; + break; + case 6: + this.popState(); + return 14; + + break; + case 7: + return 65; + break; + case 8: + return 68; + break; + case 9: + return 19; + break; + case 10: + this.popState(); + this.begin('raw'); + return 23; + + break; + case 11: + return 55; + break; + case 12: + return 60; + break; + case 13: + return 29; + break; + case 14: + return 47; + break; + case 15: + this.popState();return 44; + break; + case 16: + this.popState();return 44; + break; + case 17: + return 34; + break; + case 18: + return 39; + break; + case 19: + return 51; + break; + case 20: + return 48; + break; + case 21: + this.unput(yy_.yytext); + this.popState(); + this.begin('com'); + + break; + case 22: + this.popState(); + return 14; + + break; + case 23: + return 48; + break; + case 24: + return 73; + break; + case 25: + return 72; + break; + case 26: + return 72; + break; + case 27: + return 87; + break; + case 28: + // ignore whitespace + break; + case 29: + this.popState();return 54; + break; + case 30: + this.popState();return 33; + break; + case 31: + yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80; + break; + case 32: + yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80; + break; + case 33: + return 85; + break; + case 34: + return 82; + break; + case 35: + return 82; + break; + case 36: + return 83; + break; + case 37: + return 84; + break; + case 38: + return 81; + break; + case 39: + return 75; + break; + case 40: + return 77; + break; + case 41: + return 72; + break; + case 42: + yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72; + break; + case 43: + return 'INVALID'; + break; + case 44: + return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/]; + lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } }; + return lexer; + })(); + parser.lexer = lexer; + function Parser() { + this.yy = {}; + }Parser.prototype = parser;parser.Parser = Parser; + return new Parser(); +})();exports.__esModule = true; +exports['default'] = handlebars; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3BhcnNlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBRUEsSUFBSSxVQUFVLEdBQUcsQ0FBQyxZQUFVO0FBQzVCLFFBQUksTUFBTSxHQUFHLEVBQUMsS0FBSyxFQUFFLFNBQVMsS0FBSyxHQUFHLEVBQUc7QUFDekMsVUFBRSxFQUFFLEVBQUU7QUFDTixnQkFBUSxFQUFFLEVBQUMsT0FBTyxFQUFDLENBQUMsRUFBQyxNQUFNLEVBQUMsQ0FBQyxFQUFDLFNBQVMsRUFBQyxDQUFDLEVBQUMsS0FBSyxFQUFDLENBQUMsRUFBQyxxQkFBcUIsRUFBQyxDQUFDLEVBQUMsV0FBVyxFQUFDLENBQUMsRUFBQyxVQUFVLEVBQUMsQ0FBQyxFQUFDLE9BQU8sRUFBQyxDQUFDLEVBQUMsVUFBVSxFQUFDLEVBQUUsRUFBQyxTQUFTLEVBQUMsRUFBRSxFQUFDLGNBQWMsRUFBQyxFQUFFLEVBQUMsU0FBUyxFQUFDLEVBQUUsRUFBQyxTQUFTLEVBQUMsRUFBRSxFQUFDLFNBQVMsRUFBQyxFQUFFLEVBQUMsY0FBYyxFQUFDLEVBQUUsRUFBQywyQkFBMkIsRUFBQyxFQUFFLEVBQUMsZUFBZSxFQUFDLEVBQUUsRUFBQyxnQkFBZ0IsRUFBQyxFQUFFLEVBQUMsWUFBWSxFQUFDLEVBQUUsRUFBQywwQkFBMEIsRUFBQyxFQUFFLEVBQUMsc0JBQXNCLEVBQUMsRUFBRSxFQUFDLGlCQUFpQixFQUFDLEVBQUUsRUFBQyxXQUFXLEVBQUMsRUFBRSxFQUFDLGVBQWUsRUFBQyxFQUFFLEVBQUMsWUFBWSxFQUFDLEVBQUUsRUFBQyxhQUFhLEVBQUMsRUFBRSxFQUFDLGVBQWUsRUFBQyxFQUFFLEVBQUMsWUFBWSxFQUFDLEVBQUUsRUFBQyx1QkFBdUIsRUFBQyxFQUFFLEVBQUMsbUJBQW1CLEVBQUMsRUFBRSxFQUFDLG1CQUFtQixFQUFDLEVBQUUsRUFBQyxPQUFPLEVBQUMsRUFBRSxFQUFDLGNBQWMsRUFBQyxFQUFF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QUFFLEVBQUMsS0FBSyxFQUFDO0FBQzVlLG9CQUFZLEVBQUUsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFF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QyxDQUFDLEdBQUcsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN6RSwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUN0RSwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdkYsMEJBQU07QUFBQSxBQUNOLHFCQUFLLEVBQUU7QUFBQyx3QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RGLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDckosMEJBQU07QUFBQSxBQUNOLHFCQUFLLEVBQUU7QUFBQyx3QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNySSwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ3JJLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDL0UsMEJBQU07QUFBQSxBQUNOLHFCQUFLLEVBQUU7QUFDSCx3QkFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQzt3QkFDN0UsT0FBTyxHQUFHLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3pELDJCQUFPLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQzs7QUFFdkIsd0JBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUM7O0FBRXRFLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3hCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsRUFBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFDLENBQUM7QUFDMUUsMEJBQU07QUFBQSxBQUNOLHFCQUFLLEVBQUU7QUFBQyx3QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN0SCwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RILDBCQUFNO0FBQUEs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RUFBRTtBQUFFLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEFBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3hHLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQyxDQUFDO0FBQzNELDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsc0JBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMxQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHNCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDMUIsMEJBQU07QUFBQSxBQUNOLHFCQUFLLEVBQUU7QUFBQyxzQkFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUIsMEJBQU07QUFBQSxBQUNOLHFCQUFLLEdBQUc7QUFBQyx3QkFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxHQUFHO0FBQUMsc0JBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQy9CLDBCQUFNO0FBQUEsYUFDTDtTQUNBO0FBQ0QsYUFBSyxFQUFFLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxDQUFDO0FBQ3hnVyxzQkFBYyxFQUFFLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxH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aEIsMkJBQU8sRUFBRSxDQUFDOztBQUVaLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxDQUFDO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2pCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxDQUFDO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2pCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxDQUFDO0FBQUUsMkJBQU8sRUFBRSxDQUFDO0FBQ2xCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQzJCLHdCQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDaEIsd0JBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbEIsMkJBQU8sRUFBRSxDQUFDOztBQUU1QywwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQUFBQyxPQUFPLEVBQUUsQ0FBQztBQUNuQywwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLHdCQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQUFBQyxPQUFPLEVBQUUsQ0FBQztBQUNuQywwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUFDLDJCQUFPLEVBQUUsQ0FBQztBQUNsQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUNMLHdCQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN2Qix3QkFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ2hCLHdCQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDOztBQUVwQiwwQkFBTTtBQUFBLEFBQ04scUJBQUssRUFBRTtBQUNMLHdCQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDaEIsMkJBQU8sRUFBRSxDQUFDOztBQUVaLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2xCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2xCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2xCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2xCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsMkJBQU8sRUFBRSxDQUFDO0FBQ2xCLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFOztBQUNQLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxBQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ25DLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsd0JBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxBQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ25DLDBCQUFNO0FBQUEsQUFDTixxQkFBSyxFQUFFO0FBQUMsdUJBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFDLEdBQUcsQ0FBQyxDQUFDLEFBQUMsT0FBTyxFQUFFLENBQUM7QUFDL0QsMEJBQU07QUFBQSxBQUNOLHFC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QyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLENBQUMsRUFBQyxXQUFXLEVBQUMsS0FBSyxFQUFDLEVBQUMsS0FBSyxFQUFDLEVBQUMsT0FBTyxFQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUMsV0FBVyxFQUFDLEtBQUssRUFBQyxFQUFDLEtBQUssRUFBQyxFQUFDLE9BQU8sRUFBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxLQUFLLEVBQUMsRUFBQyxLQUFLLEVBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxLQUFLLEVBQUMsRUFBQyxTQUFTLEVBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLFdBQVcsRUFBQyxJQUFJLEVBQUMsRUFBQyxDQUFDO0FBQzNVLGVBQU8sS0FBSyxDQUFDO0tBQUMsQ0FBQSxFQUFHLENBQUE7QUFDakIsVUFBTSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7QUFDckIsYUFBUyxNQUFNLEdBQUk7QUFBRSxZQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztLQUFFLE1BQU0sQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQ3JGLFdBQU8sSUFBSSxNQUFNLEVBQUEsQ0FBQztDQUNqQixDQUFBLEVBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztBQUMvQixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsVUFBVSxDQUFDIiwiZmlsZSI6InBhcnNlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4vKiBKaXNvbiBnZW5lcmF0ZWQgcGFyc2VyICovXG52YXIgaGFuZGxlYmFycyA9IChmdW5jdGlvbigpe1xudmFyIHBhcnNlciA9IHt0cmFjZTogZnVuY3Rpb24gdHJhY2UoKSB7IH0sXG55eToge30sXG5zeW1ib2xzXzoge1wiZXJyb3JcIjoyLFwicm9vdFwiOjMsXCJwcm9ncmFtXCI6NCxcIkVPRlwiOjUsXCJwcm9ncmFtX3JlcGV0aXRpb24wXCI6NixcInN0YXRlbWVudFwiOjcsXCJtdXN0YWNoZVwiOjgsXCJibG9ja1wiOjksXCJyYXdCbG9ja1wiOjEwLFwicGFydGlhbFwiOjExLFwicGFydGlhbEJsb2NrXCI6MTIsXCJjb250ZW50XCI6MTMsXCJDT01NRU5UXCI6MTQsXCJDT05URU5UXCI6MTUsXCJvcGVuUmF3QmxvY2tcIjoxNixcInJhd0Jsb2NrX3JlcGV0aXRpb25fcGx1czBcIjoxNyxcIkVORF9SQVdfQkxPQ0tcIjoxOCxcIk9QRU5fUkFXX0JMT0NLXCI6MTksXCJoZWxwZXJOYW1lXCI6MjAsXCJvcGVuUmF3QmxvY2tfcmVwZXRpdGlvbjBcIjoyMSxcIm9wZW5SYXdCbG9ja19vcHRpb24wXCI6MjIsXCJDTE9TRV9SQVdfQkxPQ0tcIjoyMyxcIm9wZW5CbG9ja1wiOjI0LFwiYmxvY2tfb3B0aW9uMFwiOjI1LFwiY2xvc2VCbG9ja1wiOjI2LFwib3BlbkludmVyc2VcIjoyNyxcImJsb2NrX29wdGlvbjFcIjoyOCxcIk9QRU5fQkxPQ0tcIjoyOSxcIm9wZW5CbG9ja19yZXBldGl0aW9uMFwiOjMwLFwib3BlbkJsb2NrX29wdGlvbjBcIjozMSxcIm9wZW5CbG9ja19vcHRpb24xXCI6MzIsXCJDTE9TRVwiOjMzLFwiT1BFTl9JTlZFUlNFXCI6MzQsXCJvcGVuSW52ZXJzZV9yZXBldGl0aW9uMFwiOjM1LFwib3BlbkludmVyc2Vfb3B0aW9uMFwiOjM2LFwib3BlbkludmVyc2Vfb3B0aW9uMVwiOjM3LFwib3BlbkludmVyc2VDaGFpblwiOjM4LFwiT1BFTl9JTlZFUlNFX0NIQUlOXCI6MzksXCJvcGVuSW52ZXJzZUNoYWluX3JlcGV0aXRpb24wXCI6NDAsXCJvcGVuSW52ZXJzZUNoYWluX29wdGlvbjBcIjo0MSxcIm9wZW5JbnZlcnNlQ2hhaW5fb3B0aW9uMVwiOjQyLFwiaW52ZXJzZUFuZFByb2dyYW1cIjo0MyxcIklOVkVSU0VcIjo0NCxcImludmVyc2VDaGFpblwiOjQ1LFwiaW52ZXJzZUNoYWluX29wdGlvbjBcIjo0NixcIk9QRU5fRU5EQkxPQ0tcIjo0NyxcIk9QRU5cIjo0OCxcIm11c3RhY2hlX3JlcGV0aXRpb24wXCI6NDksXCJtdXN0YWNoZV9vcHRpb24wXCI6NTAsXCJPUEVOX1VORVNDQVBFRFwiOjUxLFwibXVzdGFjaGVfcmVwZXRpdGlvbjFcIjo1MixcIm11c3RhY2hlX29wdGlvbjFcIjo1MyxcIkNMT1NFX1VORVNDQVBFRFwiOjU0LFwiT1BFTl9QQVJUSUFMXCI6NTUsXCJwYXJ0aWFsTmFtZVwiOjU2LFwicGFydGlhbF9yZXBldGl0aW9uMFwiOjU3LFwicGFydGlhbF9vcHRpb24wXCI6NTgsXCJvcGVuUGFydGlhbEJsb2NrXCI6NTksXCJPUEVOX1BBUlRJQUxfQkxPQ0tcIjo2MCxcIm9wZW5QYXJ0aWFsQmxvY2tfcmVwZXRpdGlvbjBcIjo2MSxcIm9wZW5QYXJ0aWFsQmxvY2tfb3B0aW9uMFwiOjYyLFwicGFyYW1cIjo2MyxcInNleHByXCI6NjQsXCJPUEVOX1NFWFBSXCI6NjUsXCJzZXhwcl9yZXBldGl0aW9uMFwiOjY2LFwic2V4cHJfb3B0aW9uMFwiOjY3LFwiQ0xPU0VfU0VYUFJcIjo2OCxcImhhc2hcIjo2OSxcImhhc2hfcmVwZXRpdGlvbl9wbHVzMFwiOjcwLFwiaGFzaFNlZ21lbnRcIjo3MSxcIklEXCI6NzIsXCJFUVVBTFNcIjo3MyxcImJsb2NrUGFyYW1zXCI6NzQsXCJPUEVOX0JMT0NLX1BBUkFNU1wiOjc1LFwiYmxvY2tQYXJhbXNfcmVwZXRpdGlvbl9wbHVzMFwiOjc2LFwiQ0xPU0VfQkxPQ0tfUEFSQU1TXCI6NzcsXCJwYXRoXCI6NzgsXCJkYXRhTmFtZVwiOjc5LFwiU1RSSU5HXCI6ODAsXCJOVU1CRVJcIjo4MSxcIkJPT0xFQU5cIjo4MixcIlVOREVGSU5FRFwiOjgzLFwiTlVMTFwiOjg0LFwiREFUQVwiOjg1LFwicGF0aFNlZ21lbnRzXCI6ODYsXCJTRVBcIjo4NyxcIiRhY2NlcHRcIjowLFwiJGVuZFwiOjF9LFxudGVybWluYWxzXzogezI6XCJlcnJvclwiLDU6XCJFT0ZcIiwxNDpcIkNPTU1FTlRcIiwxNTpcIkNPTlRFTlRcIiwxODpcIkVORF9SQVdfQkxPQ0tcIiwxOTpcIk9QRU5fUkFXX0JMT0NLXCIsMjM6XCJDTE9TRV9SQVdfQkxPQ0tcIiwyOTpcIk9QRU5fQkxPQ0tcIiwzMzpcIkNMT1NFXCIsMzQ6XCJPUEVOX0lOVkVSU0VcIiwzOTpcIk9QRU5fSU5WRVJTRV9DSEFJTlwiLDQ0OlwiSU5WRVJTRVwiLDQ3OlwiT1BFTl9FTkRCTE9DS1wiLDQ4OlwiT1BFTlwiLDUxOlwiT1BFTl9VTkVTQ0FQRURcIiw1NDpcIkNMT1NFX1VORVNDQVBFRFwiLDU1OlwiT1BFTl9QQVJUSUFMXCIsNjA6XCJPUEVOX1BBUlRJQUxfQkxPQ0tcIiw2NTpcIk9QRU5fU0VYUFJcIiw2ODpcIkNMT1NFX1NFWFBSXCIsNzI6XCJJRFwiLDczOlwiRVFVQUxTXCIsNzU6XCJPUEVOX0JMT0NLX1BBUkFNU1wiLDc3OlwiQ0xPU0VfQkxPQ0tfUEFSQU1TXCIsODA6XCJTVFJJTkdcIiw4MTpcIk5VTUJFUlwiLDgyOlwiQk9PTEVBTlwiLDgzOlwiVU5ERUZJTkVEXCIsODQ6XCJOVUxMXCIsODU6XCJEQVRBXCIsODc6XCJTRVBcIn0sXG5wcm9kdWN0aW9uc186IFswLFszLDJdLFs0LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFsxMywxXSxbMTAsM10sWzE2LDVdLFs5LDRdLFs5LDRdLFsyNCw2XSxbMjcsNl0sWzM4LDZdLFs0MywyXSxbNDUsM10sWzQ1LDFdLFsyNiwzXSxbOCw1XSxbOCw1XSxbMTEsNV0sWzEyLDNdLFs1OSw1XSxbNjMsMV0sWzYzLDFdLFs2NCw1XSxbNjksMV0sWzcxLDNdLFs3NCwzXSxbMjAsMV0sWzIwLDFdLFsyMCwxXSxbMjAsMV0sWzIwLDFdLFsyMCwxXSxbMjAsMV0sWzU2LDFdLFs1NiwxXSxbNzksMl0sWzc4LDFdLFs4NiwzXSxbODYsMV0sWzYsMF0sWzYsMl0sWzE3LDFdLFsxNywyXSxbMjEsMF0sWzIxLDJdLFsyMiwwXSxbMjIsMV0sWzI1LDBdLFsyNSwxXSxbMjgsMF0sWzI4LDFdLFszMCwwXSxbMzAsMl0sWzMxLDBdLFszMSwxXSxbMzIsMF0sWzMyLDFdLFszNSwwXSxbMzUsMl0sWzM2LDBdLFszNiwxXSxbMzcsMF0sWzM3LDFdLFs0MCwwXSxbNDAsMl0sWzQxLDBdLFs0MSwxXSxbNDIsMF0sWzQyLDFdLFs0NiwwXSxbNDYsMV0sWzQ5LDBdLFs0OSwyXSxbNTAsMF0sWzUwLDFdLFs1MiwwXSxbNTIsMl0sWzUzLDBdLFs1MywxXSxbNTcsMF0sWzU3LDJdLFs1OCwwXSxbNTgsMV0sWzYxLDBdLFs2MSwyXSxbNjIsMF0sWzYyLDFdLFs2NiwwXSxbNjYsMl0sWzY3LDBdLFs2NywxXSxbNzAsMV0sWzcwLDJdLFs3NiwxXSxbNzYsMl1dLFxucGVyZm9ybUFjdGlvbjogZnVuY3Rpb24gYW5vbnltb3VzKHl5dGV4dCx5eWxlbmcseXlsaW5lbm8seXkseXlzdGF0ZSwkJCxfJFxuLyoqLykge1xuXG52YXIgJDAgPSAkJC5sZW5ndGggLSAxO1xuc3dpdGNoICh5eXN0YXRlKSB7XG5jYXNlIDE6IHJldHVybiAkJFskMC0xXTsgXG5icmVhaztcbmNhc2UgMjp0aGlzLiQgPSB5eS5wcmVwYXJlUHJvZ3JhbSgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDM6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDQ6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDU6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDY6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDc6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDg6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDk6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ0NvbW1lbnRTdGF0ZW1lbnQnLFxuICAgICAgdmFsdWU6IHl5LnN0cmlwQ29tbWVudCgkJFskMF0pLFxuICAgICAgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDBdLCAkJFskMF0pLFxuICAgICAgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpXG4gICAgfTtcbiAgXG5icmVhaztcbmNhc2UgMTA6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ0NvbnRlbnRTdGF0ZW1lbnQnLFxuICAgICAgb3JpZ2luYWw6ICQkWyQwXSxcbiAgICAgIHZhbHVlOiAkJFskMF0sXG4gICAgICBsb2M6IHl5LmxvY0luZm8odGhpcy5fJClcbiAgICB9O1xuICBcbmJyZWFrO1xuY2FzZSAxMTp0aGlzLiQgPSB5eS5wcmVwYXJlUmF3QmxvY2soJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMF0sIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDEyOnRoaXMuJCA9IHsgcGF0aDogJCRbJDAtM10sIHBhcmFtczogJCRbJDAtMl0sIGhhc2g6ICQkWyQwLTFdIH07XG5icmVhaztcbmNhc2UgMTM6dGhpcy4kID0geXkucHJlcGFyZUJsb2NrKCQkWyQwLTNdLCAkJFskMC0yXSwgJCRbJDAtMV0sICQkWyQwXSwgZmFsc2UsIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDE0OnRoaXMuJCA9IHl5LnByZXBhcmVCbG9jaygkJFskMC0zXSwgJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMF0sIHRydWUsIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDE1OnRoaXMuJCA9IHsgb3BlbjogJCRbJDAtNV0sIHBhdGg6ICQkWyQwLTRdLCBwYXJhbXM6ICQkWyQwLTNdLCBoYXNoOiAkJFskMC0yXSwgYmxvY2tQYXJhbXM6ICQkWyQwLTFdLCBzdHJpcDogeXkuc3RyaXBGbGFncygkJFskMC01XSwgJCRbJDBdKSB9O1xuYnJlYWs7XG5jYXNlIDE2OnRoaXMuJCA9IHsgcGF0aDogJCRbJDAtNF0sIHBhcmFtczogJCRbJDAtM10sIGhhc2g6ICQkWyQwLTJdLCBibG9ja1BhcmFtczogJCRbJDAtMV0sIHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTVdLCAkJFskMF0pIH07XG5icmVhaztcbmNhc2UgMTc6dGhpcy4kID0geyBwYXRoOiAkJFskMC00XSwgcGFyYW1zOiAkJFskMC0zXSwgaGFzaDogJCRbJDAtMl0sIGJsb2NrUGFyYW1zOiAkJFskMC0xXSwgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNV0sICQkWyQwXSkgfTtcbmJyZWFrO1xuY2FzZSAxODp0aGlzLiQgPSB7IHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTFdLCAkJFskMC0xXSksIHByb2dyYW06ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDE5OlxuICAgIHZhciBpbnZlcnNlID0geXkucHJlcGFyZUJsb2NrKCQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDBdLCAkJFskMF0sIGZhbHNlLCB0aGlzLl8kKSxcbiAgICAgICAgcHJvZ3JhbSA9IHl5LnByZXBhcmVQcm9ncmFtKFtpbnZlcnNlXSwgJCRbJDAtMV0ubG9jKTtcbiAgICBwcm9ncmFtLmNoYWluZWQgPSB0cnVlO1xuXG4gICAgdGhpcy4kID0geyBzdHJpcDogJCRbJDAtMl0uc3RyaXAsIHByb2dyYW06IHByb2dyYW0sIGNoYWluOiB0cnVlIH07XG4gIFxuYnJlYWs7XG5jYXNlIDIwOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSAyMTp0aGlzLiQgPSB7cGF0aDogJCRbJDAtMV0sIHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTJdLCAkJFskMF0pfTtcbmJyZWFrO1xuY2FzZSAyMjp0aGlzLiQgPSB5eS5wcmVwYXJlTXVzdGFjaGUoJCRbJDAtM10sICQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDAtNF0sIHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSksIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDIzOnRoaXMuJCA9IHl5LnByZXBhcmVNdXN0YWNoZSgkJFskMC0zXSwgJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMC00XSwgeXkuc3RyaXBGbGFncygkJFskMC00XSwgJCRbJDBdKSwgdGhpcy5fJCk7XG5icmVhaztcbmNhc2UgMjQ6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ1BhcnRpYWxTdGF0ZW1lbnQnLFxuICAgICAgbmFtZTogJCRbJDAtM10sXG4gICAgICBwYXJhbXM6ICQkWyQwLTJdLFxuICAgICAgaGFzaDogJCRbJDAtMV0sXG4gICAgICBpbmRlbnQ6ICcnLFxuICAgICAgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSksXG4gICAgICBsb2M6IHl5LmxvY0luZm8odGhpcy5fJClcbiAgICB9O1xuICBcbmJyZWFrO1xuY2FzZSAyNTp0aGlzLiQgPSB5eS5wcmVwYXJlUGFydGlhbEJsb2NrKCQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSAyNjp0aGlzLiQgPSB7IHBhdGg6ICQkWyQwLTNdLCBwYXJhbXM6ICQkWyQwLTJdLCBoYXNoOiAkJFskMC0xXSwgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSkgfTtcbmJyZWFrO1xuY2FzZSAyNzp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgMjg6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDI5OlxuICAgIHRoaXMuJCA9IHtcbiAgICAgIHR5cGU6ICdTdWJFeHByZXNzaW9uJyxcbiAgICAgIHBhdGg6ICQkWyQwLTNdLFxuICAgICAgcGFyYW1zOiAkJFskMC0yXSxcbiAgICAgIGhhc2g6ICQkWyQwLTFdLFxuICAgICAgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpXG4gICAgfTtcbiAgXG5icmVhaztcbmNhc2UgMzA6dGhpcy4kID0ge3R5cGU6ICdIYXNoJywgcGFpcnM6ICQkWyQwXSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzMTp0aGlzLiQgPSB7dHlwZTogJ0hhc2hQYWlyJywga2V5OiB5eS5pZCgkJFskMC0yXSksIHZhbHVlOiAkJFskMF0sIGxvYzogeXkubG9jSW5mbyh0aGlzLl8kKX07XG5icmVhaztcbmNhc2UgMzI6dGhpcy4kID0geXkuaWQoJCRbJDAtMV0pO1xuYnJlYWs7XG5jYXNlIDMzOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSAzNDp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgMzU6dGhpcy4kID0ge3R5cGU6ICdTdHJpbmdMaXRlcmFsJywgdmFsdWU6ICQkWyQwXSwgb3JpZ2luYWw6ICQkWyQwXSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzNjp0aGlzLiQgPSB7dHlwZTogJ051bWJlckxpdGVyYWwnLCB2YWx1ZTogTnVtYmVyKCQkWyQwXSksIG9yaWdpbmFsOiBOdW1iZXIoJCRbJDBdKSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzNzp0aGlzLiQgPSB7dHlwZTogJ0Jvb2xlYW5MaXRlcmFsJywgdmFsdWU6ICQkWyQwXSA9PT0gJ3RydWUnLCBvcmlnaW5hbDogJCRbJDBdID09PSAndHJ1ZScsIGxvYzogeXkubG9jSW5mbyh0aGlzLl8kKX07XG5icmVhaztcbmNhc2UgMzg6dGhpcy4kID0ge3R5cGU6ICdVbmRlZmluZWRMaXRlcmFsJywgb3JpZ2luYWw6IHVuZGVmaW5lZCwgdmFsdWU6IHVuZGVmaW5lZCwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzOTp0aGlzLiQgPSB7dHlwZTogJ051bGxMaXRlcmFsJywgb3JpZ2luYWw6IG51bGwsIHZhbHVlOiBudWxsLCBsb2M6IHl5LmxvY0luZm8odGhpcy5fJCl9O1xuYnJlYWs7XG5jYXNlIDQwOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSA0MTp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgNDI6dGhpcy4kID0geXkucHJlcGFyZVBhdGgodHJ1ZSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSA0Mzp0aGlzLiQgPSB5eS5wcmVwYXJlUGF0aChmYWxzZSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSA0NDogJCRbJDAtMl0ucHVzaCh7cGFydDogeXkuaWQoJCRbJDBdKSwgb3JpZ2luYWw6ICQkWyQwXSwgc2VwYXJhdG9yOiAkJFskMC0xXX0pOyB0aGlzLiQgPSAkJFskMC0yXTsgXG5icmVhaztcbmNhc2UgNDU6dGhpcy4kID0gW3twYXJ0OiB5eS5pZCgkJFskMF0pLCBvcmlnaW5hbDogJCRbJDBdfV07XG5icmVhaztcbmNhc2UgNDY6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNDc6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDQ4OnRoaXMuJCA9IFskJFskMF1dO1xuYnJlYWs7XG5jYXNlIDQ5OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA1MDp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA1MTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgNTg6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNTk6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDY0OnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDY1OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA3MDp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA3MTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgNzg6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNzk6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDgyOnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDgzOiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA4Njp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA4NzokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgOTA6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgOTE6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDk0OnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDk1OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA5ODp0aGlzLiQgPSBbJCRbJDBdXTtcbmJyZWFrO1xuY2FzZSA5OTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgMTAwOnRoaXMuJCA9IFskJFskMF1dO1xuYnJlYWs7XG5jYXNlIDEwMTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbn1cbn0sXG50YWJsZTogW3szOjEsNDoyLDU6WzIsNDZdLDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezE6WzNdfSx7NTpbMSw0XX0sezU6WzIsMl0sNzo1LDg6Niw5OjcsMTA6OCwxMTo5LDEyOjEwLDEzOjExLDE0OlsxLDEyXSwxNTpbMSwyMF0sMTY6MTcsMTk6WzEsMjNdLDI0OjE1LDI3OjE2LDI5OlsxLDIxXSwzNDpbMSwyMl0sMzk6WzIsMl0sNDQ6WzIsMl0sNDc6WzIsMl0sNDg6WzEsMTNdLDUxOlsxLDE0XSw1NTpbMSwxOF0sNTk6MTksNjA6WzEsMjRdfSx7MTpbMiwxXX0sezU6WzIsNDddLDE0OlsyLDQ3XSwxNTpbMiw0N10sMTk6WzIsNDddLDI5OlsyLDQ3XSwzNDpbMiw0N10sMzk6WzIsNDddLDQ0OlsyLDQ3XSw0NzpbMiw0N10sNDg6WzIsNDddLDUxOlsyLDQ3XSw1NTpbMiw0N10sNjA6WzIsNDddfSx7NTpbMiwzXSwxNDpbMiwzXSwxNTpbMiwzXSwxOTpbMiwzXSwyOTpbMiwzXSwzNDpbMiwzXSwzOTpbMiwzXSw0NDpbMiwzXSw0NzpbMiwzXSw0ODpbMiwzXSw1MTpbMiwzXSw1NTpbMiwzXSw2MDpbMiwzXX0sezU6WzIsNF0sMTQ6WzIsNF0sMTU6WzIsNF0sMTk6WzIsNF0sMjk6WzIsNF0sMzQ6WzIsNF0sMzk6WzIsNF0sNDQ6WzIsNF0sNDc6WzIsNF0sNDg6WzIsNF0sNTE6WzIsNF0sNTU6WzIsNF0sNjA6WzIsNF19LHs1OlsyLDVdLDE0OlsyLDVdLDE1OlsyLDVdLDE5OlsyLDVdLDI5OlsyLDVdLDM0OlsyLDVdLDM5OlsyLDVdLDQ0OlsyLDVdLDQ3OlsyLDVdLDQ4OlsyLDVdLDUxOlsyLDVdLDU1OlsyLDVdLDYwOlsyLDVdfSx7NTpbMiw2XSwxNDpbMiw2XSwxNTpbMiw2XSwxOTpbMiw2XSwyOTpbMiw2XSwzNDpbMiw2XSwzOTpbMiw2XSw0NDpbMiw2XSw0NzpbMiw2XSw0ODpbMiw2XSw1MTpbMiw2XSw1NTpbMiw2XSw2MDpbMiw2XX0sezU6WzIsN10sMTQ6WzIsN10sMTU6WzIsN10sMTk6WzIsN10sMjk6WzIsN10sMzQ6WzIsN10sMzk6WzIsN10sNDQ6WzIsN10sNDc6WzIsN10sNDg6WzIsN10sNTE6WzIsN10sNTU6WzIsN10sNjA6WzIsN119LHs1OlsyLDhdLDE0OlsyLDhdLDE1OlsyLDhdLDE5OlsyLDhdLDI5OlsyLDhdLDM0OlsyLDhdLDM5OlsyLDhdLDQ0OlsyLDhdLDQ3OlsyLDhdLDQ4OlsyLDhdLDUxOlsyLDhdLDU1OlsyLDhdLDYwOlsyLDhdfSx7NTpbMiw5XSwxNDpbMiw5XSwxNTpbMiw5XSwxOTpbMiw5XSwyOTpbMiw5XSwzNDpbMiw5XSwzOTpbMiw5XSw0NDpbMiw5XSw0NzpbMiw5XSw0ODpbMiw5XSw1MTpbMiw5XSw1NTpbMiw5XSw2MDpbMiw5XX0sezIwOjI1LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjM2LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezQ6MzcsNjozLDE0OlsyLDQ2XSwxNTpbMiw0Nl0sMTk6WzIsNDZdLDI5OlsyLDQ2XSwzNDpbMiw0Nl0sMzk6WzIsNDZdLDQ0OlsyLDQ2XSw0NzpbMiw0Nl0sNDg6WzIsNDZdLDUxOlsyLDQ2XSw1NTpbMiw0Nl0sNjA6WzIsNDZdfSx7NDozOCw2OjMsMTQ6WzIsNDZdLDE1OlsyLDQ2XSwxOTpbMiw0Nl0sMjk6WzIsNDZdLDM0OlsyLDQ2XSw0NDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezEzOjQwLDE1OlsxLDIwXSwxNzozOX0sezIwOjQyLDU2OjQxLDY0OjQzLDY1OlsxLDQ0XSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs0OjQ1LDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDQ3OlsyLDQ2XSw0ODpbMiw0Nl0sNTE6WzIsNDZdLDU1OlsyLDQ2XSw2MDpbMiw0Nl19LHs1OlsyLDEwXSwxNDpbMiwxMF0sMTU6WzIsMTBdLDE4OlsyLDEwXSwxOTpbMiwxMF0sMjk6WzIsMTBdLDM0OlsyLDEwXSwzOTpbMiwxMF0sNDQ6WzIsMTBdLDQ3OlsyLDEwXSw0ODpbMiwxMF0sNTE6WzIsMTBdLDU1OlsyLDEwXSw2MDpbMiwxMF19LHsyMDo0Niw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0Nyw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0OCw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0Miw1Njo0OSw2NDo0Myw2NTpbMSw0NF0sNzI6WzEsMzVdLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7MzM6WzIsNzhdLDQ5OjUwLDY1OlsyLDc4XSw3MjpbMiw3OF0sODA6WzIsNzhdLDgxOlsyLDc4XSw4MjpbMiw3OF0sODM6WzIsNzhdLDg0OlsyLDc4XSw4NTpbMiw3OF19LHsyMzpbMiwzM10sMzM6WzIsMzNdLDU0OlsyLDMzXSw2NTpbMiwzM10sNjg6WzIsMzNdLDcyOlsyLDMzXSw3NTpbMiwzM10sODA6WzIsMzNdLDgxOlsyLDMzXSw4MjpbMiwzM10sODM6WzIsMzNdLDg0OlsyLDMzXSw4NTpbMiwzM119LHsyMzpbMiwzNF0sMzM6WzIsMzRdLDU0OlsyLDM0XSw2NTpbMiwzNF0sNjg6WzIsMzRdLDcyOlsyLDM0XSw3NTpbMiwzNF0sODA6WzIsMzRdLDgxOlsyLDM0XSw4MjpbMiwzNF0sODM6WzIsMzRdLDg0OlsyLDM0XSw4NTpbMiwzNF19LHsyMzpbMiwzNV0sMzM6WzIsMzVdLDU0OlsyLDM1XSw2NTpbMiwzNV0sNjg6WzIsMzVdLDcyOlsyLDM1XSw3NTpbMiwzNV0sODA6WzIsMzVdLDgxOlsyLDM1XSw4MjpbMiwzNV0sODM6WzIsMzVdLDg0OlsyLDM1XSw4NTpbMiwzNV19LHsyMzpbMiwzNl0sMzM6WzIsMzZdLDU0OlsyLDM2XSw2NTpbMiwzNl0sNjg6WzIsMzZdLDcyOlsyLDM2XSw3NTpbMiwzNl0sODA6WzIsMzZdLDgxOlsyLDM2XSw4MjpbMiwzNl0sODM6WzIsMzZdLDg0OlsyLDM2XSw4NTpbMiwzNl19LHsyMzpbMiwzN10sMzM6WzIsMzddLDU0OlsyLDM3XSw2NTpbMiwzN10sNjg6WzIsMzddLDcyOlsyLDM3XSw3NTpbMiwzN10sODA6WzIsMzddLDgxOlsyLDM3XSw4MjpbMiwzN10sODM6WzIsMzddLDg0OlsyLDM3XSw4NTpbMiwzN119LHsyMzpbMiwzOF0sMzM6WzIsMzhdLDU0OlsyLDM4XSw2NTpbMiwzOF0sNjg6WzIsMzhdLDcyOlsyLDM4XSw3NTpbMiwzOF0sODA6WzIsMzhdLDgxOlsyLDM4XSw4MjpbMiwzOF0sODM6WzIsMzhdLDg0OlsyLDM4XSw4NTpbMiwzOF19LHsyMzpbMiwzOV0sMzM6WzIsMzldLDU0OlsyLDM5XSw2NTpbMiwzOV0sNjg6WzIsMzldLDcyOlsyLDM5XSw3NTpbMiwzOV0sODA6WzIsMzldLDgxOlsyLDM5XSw4MjpbMiwzOV0sODM6WzIsMzldLDg0OlsyLDM5XSw4NTpbMiwzOV19LHsyMzpbMiw0M10sMzM6WzIsNDNdLDU0OlsyLDQzXSw2NTpbMiw0M10sNjg6WzIsNDNdLDcyOlsyLDQzXSw3NTpbMiw0M10sODA6WzIsNDNdLDgxOlsyLDQzXSw4MjpbMiw0M10sODM6WzIsNDNdLDg0OlsyLDQzXSw4NTpbMiw0M10sODc6WzEsNTFdfSx7NzI6WzEsMzVdLDg2OjUyfSx7MjM6WzIsNDVdLDMzOlsyLDQ1XSw1NDpbMiw0NV0sNjU6WzIsNDVdLDY4OlsyLDQ1XSw3MjpbMiw0NV0sNzU6WzIsNDVdLDgwOlsyLDQ1XSw4MTpbMiw0NV0sODI6WzIsNDVdLDgzOlsyLDQ1XSw4NDpbMiw0NV0sODU6WzIsNDVdLDg3OlsyLDQ1XX0sezUyOjUzLDU0OlsyLDgyXSw2NTpbMiw4Ml0sNzI6WzIsODJdLDgwOlsyLDgyXSw4MTpbMiw4Ml0sODI6WzIsODJdLDgzOlsyLDgyXSw4NDpbMiw4Ml0sODU6WzIsODJdfSx7MjU6NTQsMzg6NTYsMzk6WzEsNThdLDQzOjU3LDQ0OlsxLDU5XSw0NTo1NSw0NzpbMiw1NF19LHsyODo2MCw0Mzo2MSw0NDpbMSw1OV0sNDc6WzIsNTZdfSx7MTM6NjMsMTU6WzEsMjBdLDE4OlsxLDYyXX0sezE1OlsyLDQ4XSwxODpbMiw0OF19LHszMzpbMiw4Nl0sNTc6NjQsNjU6WzIsODZdLDcyOlsyLDg2XSw4MDpbMiw4Nl0sODE6WzIsODZdLDgyOlsyLDg2XSw4MzpbMiw4Nl0sODQ6WzIsODZdLDg1OlsyLDg2XX0sezMzOlsyLDQwXSw2NTpbMiw0MF0sNzI6WzIsNDBdLDgwOlsyLDQwXSw4MTpbMiw0MF0sODI6WzIsNDBdLDgzOlsyLDQwXSw4NDpbMiw0MF0sODU6WzIsNDBdfSx7MzM6WzIsNDFdLDY1OlsyLDQxXSw3MjpbMiw0MV0sODA6WzIsNDFdLDgxOlsyLDQxXSw4MjpbMiw0MV0sODM6WzIsNDFdLDg0OlsyLDQxXSw4NTpbMiw0MV19LHsyMDo2NSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyNjo2Niw0NzpbMSw2N119LHszMDo2OCwzMzpbMiw1OF0sNjU6WzIsNThdLDcyOlsyLDU4XSw3NTpbMiw1OF0sODA6WzIsNThdLDgxOlsyLDU4XSw4MjpbMiw1OF0sODM6WzIsNThdLDg0OlsyLDU4XSw4NTpbMiw1OF19LHszMzpbMiw2NF0sMzU6NjksNjU6WzIsNjRdLDcyOlsyLDY0XSw3NTpbMiw2NF0sODA6WzIsNjRdLDgxOlsyLDY0XSw4MjpbMiw2NF0sODM6WzIsNjRdLDg0OlsyLDY0XSw4NTpbMiw2NF19LHsyMTo3MCwyMzpbMiw1MF0sNjU6WzIsNTBdLDcyOlsyLDUwXSw4MDpbMiw1MF0sODE6WzIsNTBdLDgyOlsyLDUwXSw4MzpbMiw1MF0sODQ6WzIsNTBdLDg1OlsyLDUwXX0sezMzOlsyLDkwXSw2MTo3MSw2NTpbMiw5MF0sNzI6WzIsOTBdLDgwOlsyLDkwXSw4MTpbMiw5MF0sODI6WzIsOTBdLDgzOlsyLDkwXSw4NDpbMiw5MF0sODU6WzIsOTBdfSx7MjA6NzUsMzM6WzIsODBdLDUwOjcyLDYzOjczLDY0Ojc2LDY1OlsxLDQ0XSw2OTo3NCw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs3MjpbMSw4MF19LHsyMzpbMiw0Ml0sMzM6WzIsNDJdLDU0OlsyLDQyXSw2NTpbMiw0Ml0sNjg6WzIsNDJdLDcyOlsyLDQyXSw3NTpbMiw0Ml0sODA6WzIsNDJdLDgxOlsyLDQyXSw4MjpbMiw0Ml0sODM6WzIsNDJdLDg0OlsyLDQyXSw4NTpbMiw0Ml0sODc6WzEsNTFdfSx7MjA6NzUsNTM6ODEsNTQ6WzIsODRdLDYzOjgyLDY0Ojc2LDY1OlsxLDQ0XSw2OTo4Myw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyNjo4NCw0NzpbMSw2N119LHs0NzpbMiw1NV19LHs0Ojg1LDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDM5OlsyLDQ2XSw0NDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezQ3OlsyLDIwXX0sezIwOjg2LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezQ6ODcsNjozLDE0OlsyLDQ2XSwxNTpbMiw0Nl0sMTk6WzIsNDZdLDI5OlsyLDQ2XSwzNDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezI2Ojg4LDQ3OlsxLDY3XX0sezQ3OlsyLDU3XX0sezU6WzIsMTFdLDE0OlsyLDExXSwxNTpbMiwxMV0sMTk6WzIsMTFdLDI5OlsyLDExXSwzNDpbMiwxMV0sMzk6WzIsMTFdLDQ0OlsyLDExXSw0NzpbMiwxMV0sNDg6WzIsMTFdLDUxOlsyLDExXSw1NTpbMiwxMV0sNjA6WzIsMTFdfSx7MTU6WzIsNDldLDE4OlsyLDQ5XX0sezIwOjc1LDMzOlsyLDg4XSw1ODo4OSw2Mzo5MCw2NDo3Niw2NTpbMSw0NF0sNjk6OTEsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7NjU6WzIsOTRdLDY2OjkyLDY4OlsyLDk0XSw3MjpbMiw5NF0sODA6WzIsOTRdLDgxOlsyLDk0XSw4MjpbMiw5NF0sODM6WzIsOTRdLDg0OlsyLDk0XSw4NTpbMiw5NF19LHs1OlsyLDI1XSwxNDpbMiwyNV0sMTU6WzIsMjVdLDE5OlsyLDI1XSwyOTpbMiwyNV0sMzQ6WzIsMjVdLDM5OlsyLDI1XSw0NDpbMiwyNV0sNDc6WzIsMjVdLDQ4OlsyLDI1XSw1MTpbMiwyNV0sNTU6WzIsMjVdLDYwOlsyLDI1XX0sezIwOjkzLDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDMxOjk0LDMzOlsyLDYwXSw2Mzo5NSw2NDo3Niw2NTpbMSw0NF0sNjk6OTYsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDYwXSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDMzOlsyLDY2XSwzNjo5Nyw2Mzo5OCw2NDo3Niw2NTpbMSw0NF0sNjk6OTksNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDY2XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDIyOjEwMCwyMzpbMiw1Ml0sNjM6MTAxLDY0Ojc2LDY1OlsxLDQ0XSw2OToxMDIsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7MjA6NzUsMzM6WzIsOTJdLDYyOjEwMyw2MzoxMDQsNjQ6NzYsNjU6WzEsNDRdLDY5OjEwNSw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHszMzpbMSwxMDZdfSx7MzM6WzIsNzldLDY1OlsyLDc5XSw3MjpbMiw3OV0sODA6WzIsNzldLDgxOlsyLDc5XSw4MjpbMiw3OV0sODM6WzIsNzldLDg0OlsyLDc5XSw4NTpbMiw3OV19LHszMzpbMiw4MV19LHsyMzpbMiwyN10sMzM6WzIsMjddLDU0OlsyLDI3XSw2NTpbMiwyN10sNjg6WzIsMjddLDcyOlsyLDI3XSw3NTpbMiwyN10sODA6WzIsMjddLDgxOlsyLDI3XSw4MjpbMiwyN10sODM6WzIsMjddLDg0OlsyLDI3XSw4NTpbMiwyN119LHsyMzpbMiwyOF0sMzM6WzIsMjhdLDU0OlsyLDI4XSw2NTpbMiwyOF0sNjg6WzIsMjhdLDcyOlsyLDI4XSw3NTpbMiwyOF0sODA6WzIsMjhdLDgxOlsyLDI4XSw4MjpbMiwyOF0sODM6WzIsMjhdLDg0OlsyLDI4XSw4NTpbMiwyOF19LHsyMzpbMiwzMF0sMzM6WzIsMzBdLDU0OlsyLDMwXSw2ODpbMiwzMF0sNzE6MTA3LDcyOlsxLDEwOF0sNzU6WzIsMzBdfSx7MjM6WzIsOThdLDMzOlsyLDk4XSw1NDpbMiw5OF0sNjg6WzIsOThdLDcyOlsyLDk4XSw3NTpbMiw5OF19LHsyMzpbMiw0NV0sMzM6WzIsNDVdLDU0OlsyLDQ1XSw2NTpbMiw0NV0sNjg6WzIsNDVdLDcyOlsyLDQ1XSw3MzpbMSwxMDldLDc1OlsyLDQ1XSw4MDpbMiw0NV0sODE6WzIsNDVdLDgyOlsyLDQ1XSw4MzpbMiw0NV0sODQ6WzIsNDVdLDg1OlsyLDQ1XSw4NzpbMiw0NV19LHsyMzpbMiw0NF0sMzM6WzIsNDRdLDU0OlsyLDQ0XSw2NTpbMiw0NF0sNjg6WzIsNDRdLDcyOlsyLDQ0XSw3NTpbMiw0NF0sODA6WzIsNDRdLDgxOlsyLDQ0XSw4MjpbMiw0NF0sODM6WzIsNDRdLDg0OlsyLDQ0XSw4NTpbMiw0NF0sODc6WzIsNDRdfSx7NTQ6WzEsMTEwXX0sezU0OlsyLDgzXSw2NTpbMiw4M10sNzI6WzIsODNdLDgwOlsyLDgzXSw4MTpbMiw4M10sODI6WzIsODNdLDgzOlsyLDgzXSw4NDpbMiw4M10sODU6WzIsODNdfSx7NTQ6WzIsODVdfSx7NTpbMiwxM10sMTQ6WzIsMTNdLDE1OlsyLDEzXSwxOTpbMiwxM10sMjk6WzIsMTNdLDM0OlsyLDEzXSwzOTpbMiwxM10sNDQ6WzIsMTNdLDQ3OlsyLDEzXSw0ODpbMiwxM10sNTE6WzIsMTNdLDU1OlsyLDEzXSw2MDpbMiwxM119LHszODo1NiwzOTpbMSw1OF0sNDM6NTcsNDQ6WzEsNTldLDQ1OjExMiw0NjoxMTEsNDc6WzIsNzZdfSx7MzM6WzIsNzBdLDQwOjExMyw2NTpbMiw3MF0sNzI6WzIsNzBdLDc1OlsyLDcwXSw4MDpbMiw3MF0sODE6WzIsNzBdLDgyOlsyLDcwXSw4MzpbMiw3MF0sODQ6WzIsNzBdLDg1OlsyLDcwXX0sezQ3OlsyLDE4XX0sezU6WzIsMTRdLDE0OlsyLDE0XSwxNTpbMiwxNF0sMTk6WzIsMTRdLDI5OlsyLDE0XSwzNDpbMiwxNF0sMzk6WzIsMTRdLDQ0OlsyLDE0XSw0NzpbMiwxNF0sNDg6WzIsMTRdLDUxOlsyLDE0XSw1NTpbMiwxNF0sNjA6WzIsMTRdfSx7MzM6WzEsMTE0XX0sezMzOlsyLDg3XSw2NTpbMiw4N10sNzI6WzIsODddLDgwOlsyLDg3XSw4MTpbMiw4N10sODI6WzIsODddLDgzOlsyLDg3XSw4NDpbMiw4N10sODU6WzIsODddfSx7MzM6WzIsODldfSx7MjA6NzUsNjM6MTE2LDY0Ojc2LDY1OlsxLDQ0XSw2NzoxMTUsNjg6WzIsOTZdLDY5OjExNyw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHszMzpbMSwxMThdfSx7MzI6MTE5LDMzOlsyLDYyXSw3NDoxMjAsNzU6WzEsMTIxXX0sezMzOlsyLDU5XSw2NTpbMiw1OV0sNzI6WzIsNTldLDc1OlsyLDU5XSw4MDpbMiw1OV0sODE6WzIsNTldLDgyOlsyLDU5XSw4MzpbMiw1OV0sODQ6WzIsNTldLDg1OlsyLDU5XX0sezMzOlsyLDYxXSw3NTpbMiw2MV19LHszMzpbMiw2OF0sMzc6MTIyLDc0OjEyMyw3NTpbMSwxMjFdfSx7MzM6WzIsNjVdLDY1OlsyLDY1XSw3MjpbMiw2NV0sNzU6WzIsNjVdLDgwOlsyLDY1XSw4MTpbMiw2NV0sODI6WzIsNjVdLDgzOlsyLDY1XSw4NDpbMiw2NV0sODU6WzIsNjVdfSx7MzM6WzIsNjddLDc1OlsyLDY3XX0sezIzOlsxLDEyNF19LHsyMzpbMiw1MV0sNjU6WzIsNTFdLDcyOlsyLDUxXSw4MDpbMiw1MV0sODE6WzIsNTFdLDgyOlsyLDUxXSw4MzpbMiw1MV0sODQ6WzIsNTFdLDg1OlsyLDUxXX0sezIzOlsyLDUzXX0sezMzOlsxLDEyNV19LHszMzpbMiw5MV0sNjU6WzIsOTFdLDcyOlsyLDkxXSw4MDpbMiw5MV0sODE6WzIsOTFdLDgyOlsyLDkxXSw4MzpbMiw5MV0sODQ6WzIsOTFdLDg1OlsyLDkxXX0sezMzOlsyLDkzXX0sezU6WzIsMjJdLDE0OlsyLDIyXSwxNTpbMiwyMl0sMTk6WzIsMjJdLDI5OlsyLDIyXSwzNDpbMiwyMl0sMzk6WzIsMjJdLDQ0OlsyLDIyXSw0NzpbMiwyMl0sNDg6WzIsMjJdLDUxOlsyLDIyXSw1NTpbMiwyMl0sNjA6WzIsMjJdfSx7MjM6WzIsOTldLDMzOlsyLDk5XSw1NDpbMiw5OV0sNjg6WzIsOTldLDcyOlsyLDk5XSw3NTpbMiw5OV19LHs3MzpbMSwxMDldfSx7MjA6NzUsNjM6MTI2LDY0Ojc2LDY1OlsxLDQ0XSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs1OlsyLDIzXSwxNDpbMiwyM10sMTU6WzIsMjNdLDE5OlsyLDIzXSwyOTpbMiwyM10sMzQ6WzIsMjNdLDM5OlsyLDIzXSw0NDpbMiwyM10sNDc6WzIsMjNdLDQ4OlsyLDIzXSw1MTpbMiwyM10sNTU6WzIsMjNdLDYwOlsyLDIzXX0sezQ3OlsyLDE5XX0sezQ3OlsyLDc3XX0sezIwOjc1LDMzOlsyLDcyXSw0MToxMjcsNjM6MTI4LDY0Ojc2LDY1OlsxLDQ0XSw2OToxMjksNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDcyXSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezU6WzIsMjRdLDE0OlsyLDI0XSwxNTpbMiwyNF0sMTk6WzIsMjRdLDI5OlsyLDI0XSwzNDpbMiwyNF0sMzk6WzIsMjRdLDQ0OlsyLDI0XSw0NzpbMiwyNF0sNDg6WzIsMjRdLDUxOlsyLDI0XSw1NTpbMiwyNF0sNjA6WzIsMjRdfSx7Njg6WzEsMTMwXX0sezY1OlsyLDk1XSw2ODpbMiw5NV0sNzI6WzIsOTVdLDgwOlsyLDk1XSw4MTpbMiw5NV0sODI6WzIsOTVdLDgzOlsyLDk1XSw4NDpbMiw5NV0sODU6WzIsOTVdfSx7Njg6WzIsOTddfSx7NTpbMiwyMV0sMTQ6WzIsMjFdLDE1OlsyLDIxXSwxOTpbMiwyMV0sMjk6WzIsMjFdLDM0OlsyLDIxXSwzOTpbMiwyMV0sNDQ6WzIsMjFdLDQ3OlsyLDIxXSw0ODpbMiwyMV0sNTE6WzIsMjFdLDU1OlsyLDIxXSw2MDpbMiwyMV19LHszMzpbMSwxMzFdfSx7MzM6WzIsNjNdfSx7NzI6WzEsMTMzXSw3NjoxMzJ9LHszMzpbMSwxMzRdfSx7MzM6WzIsNjldfSx7MTU6WzIsMTJdfSx7MTQ6WzIsMjZdLDE1OlsyLDI2XSwxOTpbMiwyNl0sMjk6WzIsMjZdLDM0OlsyLDI2XSw0NzpbMiwyNl0sNDg6WzIsMjZdLDUxOlsyLDI2XSw1NTpbMiwyNl0sNjA6WzIsMjZdfSx7MjM6WzIsMzFdLDMzOlsyLDMxXSw1NDpbMiwzMV0sNjg6WzIsMzFdLDcyOlsyLDMxXSw3NTpbMiwzMV19LHszMzpbMiw3NF0sNDI6MTM1LDc0OjEzNiw3NTpbMSwxMjFdfSx7MzM6WzIsNzFdLDY1OlsyLDcxXSw3MjpbMiw3MV0sNzU6WzIsNzFdLDgwOlsyLDcxXSw4MTpbMiw3MV0sODI6WzIsNzFdLDgzOlsyLDcxXSw4NDpbMiw3MV0sODU6WzIsNzFdfSx7MzM6WzIsNzNdLDc1OlsyLDczXX0sezIzOlsyLDI5XSwzMzpbMiwyOV0sNTQ6WzIsMjldLDY1OlsyLDI5XSw2ODpbMiwyOV0sNzI6WzIsMjldLDc1OlsyLDI5XSw4MDpbMiwyOV0sODE6WzIsMjldLDgyOlsyLDI5XSw4MzpbMiwyOV0sODQ6WzIsMjldLDg1OlsyLDI5XX0sezE0OlsyLDE1XSwxNTpbMiwxNV0sMTk6WzIsMTVdLDI5OlsyLDE1XSwzNDpbMiwxNV0sMzk6WzIsMTVdLDQ0OlsyLDE1XSw0NzpbMiwxNV0sNDg6WzIsMTVdLDUxOlsyLDE1XSw1NTpbMiwxNV0sNjA6WzIsMTVdfSx7NzI6WzEsMTM4XSw3NzpbMSwxMzddfSx7NzI6WzIsMTAwXSw3NzpbMiwxMDBdfSx7MTQ6WzIsMTZdLDE1OlsyLDE2XSwxOTpbMiwxNl0sMjk6WzIsMTZdLDM0OlsyLDE2XSw0NDpbMiwxNl0sNDc6WzIsMTZdLDQ4OlsyLDE2XSw1MTpbMiwxNl0sNTU6WzIsMTZdLDYwOlsyLDE2XX0sezMzOlsxLDEzOV19LHszMzpbMiw3NV19LHszMzpbMiwzMl19LHs3MjpbMiwxMDFdLDc3OlsyLDEwMV19LHsxNDpbMiwxN10sMTU6WzIsMTddLDE5OlsyLDE3XSwyOTpbMiwxN10sMzQ6WzIsMTddLDM5OlsyLDE3XSw0NDpbMiwxN10sNDc6WzIsMTddLDQ4OlsyLDE3XSw1MTpbMiwxN10sNTU6WzIsMTddLDYwOlsyLDE3XX1dLFxuZGVmYXVsdEFjdGlvbnM6IHs0OlsyLDFdLDU1OlsyLDU1XSw1NzpbMiwyMF0sNjE6WzIsNTddLDc0OlsyLDgxXSw4MzpbMiw4NV0sODc6WzIsMThdLDkxOlsyLDg5XSwxMDI6WzIsNTNdLDEwNTpbMiw5M10sMTExOlsyLDE5XSwxMTI6WzIsNzddLDExNzpbMiw5N10sMTIwOlsyLDYzXSwxMjM6WzIsNjldLDEyNDpbMiwxMl0sMTM2OlsyLDc1XSwxMzc6WzIsMzJdfSxcbnBhcnNlRXJyb3I6IGZ1bmN0aW9uIHBhcnNlRXJyb3Ioc3RyLCBoYXNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHN0cik7XG59LFxucGFyc2U6IGZ1bmN0aW9uIHBhcnNlKGlucHV0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzLCBzdGFjayA9IFswXSwgdnN0YWNrID0gW251bGxdLCBsc3RhY2sgPSBbXSwgdGFibGUgPSB0aGlzLnRhYmxlLCB5eXRleHQgPSBcIlwiLCB5eWxpbmVubyA9IDAsIHl5bGVuZyA9IDAsIHJlY292ZXJpbmcgPSAwLCBURVJST1IgPSAyLCBFT0YgPSAxO1xuICAgIHRoaXMubGV4ZXIuc2V0SW5wdXQoaW5wdXQpO1xuICAgIHRoaXMubGV4ZXIueXkgPSB0aGlzLnl5O1xuICAgIHRoaXMueXkubGV4ZXIgPSB0aGlzLmxleGVyO1xuICAgIHRoaXMueXkucGFyc2VyID0gdGhpcztcbiAgICBpZiAodHlwZW9mIHRoaXMubGV4ZXIueXlsbG9jID09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgIHRoaXMubGV4ZXIueXlsbG9jID0ge307XG4gICAgdmFyIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgbHN0YWNrLnB1c2goeXlsb2MpO1xuICAgIHZhciByYW5nZXMgPSB0aGlzLmxleGVyLm9wdGlvbnMgJiYgdGhpcy5sZXhlci5vcHRpb25zLnJhbmdlcztcbiAgICBpZiAodHlwZW9mIHRoaXMueXkucGFyc2VFcnJvciA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSB0aGlzLnl5LnBhcnNlRXJyb3I7XG4gICAgZnVuY3Rpb24gcG9wU3RhY2sobikge1xuICAgICAgICBzdGFjay5sZW5ndGggPSBzdGFjay5sZW5ndGggLSAyICogbjtcbiAgICAgICAgdnN0YWNrLmxlbmd0aCA9IHZzdGFjay5sZW5ndGggLSBuO1xuICAgICAgICBsc3RhY2subGVuZ3RoID0gbHN0YWNrLmxlbmd0aCAtIG47XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxleCgpIHtcbiAgICAgICAgdmFyIHRva2VuO1xuICAgICAgICB0b2tlbiA9IHNlbGYubGV4ZXIubGV4KCkgfHwgMTtcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdG9rZW4gPSBzZWxmLnN5bWJvbHNfW3Rva2VuXSB8fCB0b2tlbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9rZW47XG4gICAgfVxuICAgIHZhciBzeW1ib2wsIHByZUVycm9yU3ltYm9sLCBzdGF0ZSwgYWN0aW9uLCBhLCByLCB5eXZhbCA9IHt9LCBwLCBsZW4sIG5ld1N0YXRlLCBleHBlY3RlZDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBzdGF0ZSA9IHN0YWNrW3N0YWNrLmxlbmd0aCAtIDFdO1xuICAgICAgICBpZiAodGhpcy5kZWZhdWx0QWN0aW9uc1tzdGF0ZV0pIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IHRoaXMuZGVmYXVsdEFjdGlvbnNbc3RhdGVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHN5bWJvbCA9PT0gbnVsbCB8fCB0eXBlb2Ygc3ltYm9sID09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICBzeW1ib2wgPSBsZXgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjdGlvbiA9IHRhYmxlW3N0YXRlXSAmJiB0YWJsZVtzdGF0ZV1bc3ltYm9sXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGFjdGlvbiA9PT0gXCJ1bmRlZmluZWRcIiB8fCAhYWN0aW9uLmxlbmd0aCB8fCAhYWN0aW9uWzBdKSB7XG4gICAgICAgICAgICB2YXIgZXJyU3RyID0gXCJcIjtcbiAgICAgICAgICAgIGlmICghcmVjb3ZlcmluZykge1xuICAgICAgICAgICAgICAgIGV4cGVjdGVkID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChwIGluIHRhYmxlW3N0YXRlXSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudGVybWluYWxzX1twXSAmJiBwID4gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQucHVzaChcIidcIiArIHRoaXMudGVybWluYWxzX1twXSArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxleGVyLnNob3dQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBlcnJTdHIgPSBcIlBhcnNlIGVycm9yIG9uIGxpbmUgXCIgKyAoeXlsaW5lbm8gKyAxKSArIFwiOlxcblwiICsgdGhpcy5sZXhlci5zaG93UG9zaXRpb24oKSArIFwiXFxuRXhwZWN0aW5nIFwiICsgZXhwZWN0ZWQuam9pbihcIiwgXCIpICsgXCIsIGdvdCAnXCIgKyAodGhpcy50ZXJtaW5hbHNfW3N5bWJvbF0gfHwgc3ltYm9sKSArIFwiJ1wiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVyclN0ciA9IFwiUGFyc2UgZXJyb3Igb24gbGluZSBcIiArICh5eWxpbmVubyArIDEpICsgXCI6IFVuZXhwZWN0ZWQgXCIgKyAoc3ltYm9sID09IDE/XCJlbmQgb2YgaW5wdXRcIjpcIidcIiArICh0aGlzLnRlcm1pbmFsc19bc3ltYm9sXSB8fCBzeW1ib2wpICsgXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IoZXJyU3RyLCB7dGV4dDogdGhpcy5sZXhlci5tYXRjaCwgdG9rZW46IHRoaXMudGVybWluYWxzX1tzeW1ib2xdIHx8IHN5bWJvbCwgbGluZTogdGhpcy5sZXhlci55eWxpbmVubywgbG9jOiB5eWxvYywgZXhwZWN0ZWQ6IGV4cGVjdGVkfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGlvblswXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFjdGlvbi5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQYXJzZSBFcnJvcjogbXVsdGlwbGUgYWN0aW9ucyBwb3NzaWJsZSBhdCBzdGF0ZTogXCIgKyBzdGF0ZSArIFwiLCB0b2tlbjogXCIgKyBzeW1ib2wpO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uWzBdKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHN0YWNrLnB1c2goc3ltYm9sKTtcbiAgICAgICAgICAgIHZzdGFjay5wdXNoKHRoaXMubGV4ZXIueXl0ZXh0KTtcbiAgICAgICAgICAgIGxzdGFjay5wdXNoKHRoaXMubGV4ZXIueXlsbG9jKTtcbiAgICAgICAgICAgIHN0YWNrLnB1c2goYWN0aW9uWzFdKTtcbiAgICAgICAgICAgIHN5bWJvbCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIXByZUVycm9yU3ltYm9sKSB7XG4gICAgICAgICAgICAgICAgeXlsZW5nID0gdGhpcy5sZXhlci55eWxlbmc7XG4gICAgICAgICAgICAgICAgeXl0ZXh0ID0gdGhpcy5sZXhlci55eXRleHQ7XG4gICAgICAgICAgICAgICAgeXlsaW5lbm8gPSB0aGlzLmxleGVyLnl5bGluZW5vO1xuICAgICAgICAgICAgICAgIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgICAgICAgICAgICAgaWYgKHJlY292ZXJpbmcgPiAwKVxuICAgICAgICAgICAgICAgICAgICByZWNvdmVyaW5nLS07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN5bWJvbCA9IHByZUVycm9yU3ltYm9sO1xuICAgICAgICAgICAgICAgIHByZUVycm9yU3ltYm9sID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICBsZW4gPSB0aGlzLnByb2R1Y3Rpb25zX1thY3Rpb25bMV1dWzFdO1xuICAgICAgICAgICAgeXl2YWwuJCA9IHZzdGFja1t2c3RhY2subGVuZ3RoIC0gbGVuXTtcbiAgICAgICAgICAgIHl5dmFsLl8kID0ge2ZpcnN0X2xpbmU6IGxzdGFja1tsc3RhY2subGVuZ3RoIC0gKGxlbiB8fCAxKV0uZmlyc3RfbGluZSwgbGFzdF9saW5lOiBsc3RhY2tbbHN0YWNrLmxlbmd0aCAtIDFdLmxhc3RfbGluZSwgZmlyc3RfY29sdW1uOiBsc3RhY2tbbHN0YWNrLmxlbmd0aCAtIChsZW4gfHwgMSldLmZpcnN0X2NvbHVtbiwgbGFzdF9jb2x1bW46IGxzdGFja1tsc3RhY2subGVuZ3RoIC0gMV0ubGFzdF9jb2x1bW59O1xuICAgICAgICAgICAgaWYgKHJhbmdlcykge1xuICAgICAgICAgICAgICAgIHl5dmFsLl8kLnJhbmdlID0gW2xzdGFja1tsc3RhY2subGVuZ3RoIC0gKGxlbiB8fCAxKV0ucmFuZ2VbMF0sIGxzdGFja1tsc3RhY2subGVuZ3RoIC0gMV0ucmFuZ2VbMV1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgciA9IHRoaXMucGVyZm9ybUFjdGlvbi5jYWxsKHl5dmFsLCB5eXRleHQsIHl5bGVuZywgeXlsaW5lbm8sIHRoaXMueXksIGFjdGlvblsxXSwgdnN0YWNrLCBsc3RhY2spO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGVuKSB7XG4gICAgICAgICAgICAgICAgc3RhY2sgPSBzdGFjay5zbGljZSgwLCAtMSAqIGxlbiAqIDIpO1xuICAgICAgICAgICAgICAgIHZzdGFjayA9IHZzdGFjay5zbGljZSgwLCAtMSAqIGxlbik7XG4gICAgICAgICAgICAgICAgbHN0YWNrID0gbHN0YWNrLnNsaWNlKDAsIC0xICogbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YWNrLnB1c2godGhpcy5wcm9kdWN0aW9uc19bYWN0aW9uWzFdXVswXSk7XG4gICAgICAgICAgICB2c3RhY2sucHVzaCh5eXZhbC4kKTtcbiAgICAgICAgICAgIGxzdGFjay5wdXNoKHl5dmFsLl8kKTtcbiAgICAgICAgICAgIG5ld1N0YXRlID0gdGFibGVbc3RhY2tbc3RhY2subGVuZ3RoIC0gMl1dW3N0YWNrW3N0YWNrLmxlbmd0aCAtIDFdXTtcbiAgICAgICAgICAgIHN0YWNrLnB1c2gobmV3U3RhdGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxufTtcbi8qIEppc29uIGdlbmVyYXRlZCBsZXhlciAqL1xudmFyIGxleGVyID0gKGZ1bmN0aW9uKCl7XG52YXIgbGV4ZXIgPSAoe0VPRjoxLFxucGFyc2VFcnJvcjpmdW5jdGlvbiBwYXJzZUVycm9yKHN0ciwgaGFzaCkge1xuICAgICAgICBpZiAodGhpcy55eS5wYXJzZXIpIHtcbiAgICAgICAgICAgIHRoaXMueXkucGFyc2VyLnBhcnNlRXJyb3Ioc3RyLCBoYXNoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihzdHIpO1xuICAgICAgICB9XG4gICAgfSxcbnNldElucHV0OmZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICB0aGlzLl9pbnB1dCA9IGlucHV0O1xuICAgICAgICB0aGlzLl9tb3JlID0gdGhpcy5fbGVzcyA9IHRoaXMuZG9uZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnl5bGluZW5vID0gdGhpcy55eWxlbmcgPSAwO1xuICAgICAgICB0aGlzLnl5dGV4dCA9IHRoaXMubWF0Y2hlZCA9IHRoaXMubWF0Y2ggPSAnJztcbiAgICAgICAgdGhpcy5jb25kaXRpb25TdGFjayA9IFsnSU5JVElBTCddO1xuICAgICAgICB0aGlzLnl5bGxvYyA9IHtmaXJzdF9saW5lOjEsZmlyc3RfY29sdW1uOjAsbGFzdF9saW5lOjEsbGFzdF9jb2x1bW46MH07XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB0aGlzLnl5bGxvYy5yYW5nZSA9IFswLDBdO1xuICAgICAgICB0aGlzLm9mZnNldCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5pbnB1dDpmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjaCA9IHRoaXMuX2lucHV0WzBdO1xuICAgICAgICB0aGlzLnl5dGV4dCArPSBjaDtcbiAgICAgICAgdGhpcy55eWxlbmcrKztcbiAgICAgICAgdGhpcy5vZmZzZXQrKztcbiAgICAgICAgdGhpcy5tYXRjaCArPSBjaDtcbiAgICAgICAgdGhpcy5tYXRjaGVkICs9IGNoO1xuICAgICAgICB2YXIgbGluZXMgPSBjaC5tYXRjaCgvKD86XFxyXFxuP3xcXG4pLiovZyk7XG4gICAgICAgIGlmIChsaW5lcykge1xuICAgICAgICAgICAgdGhpcy55eWxpbmVubysrO1xuICAgICAgICAgICAgdGhpcy55eWxsb2MubGFzdF9saW5lKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnl5bGxvYy5sYXN0X2NvbHVtbisrO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB0aGlzLnl5bGxvYy5yYW5nZVsxXSsrO1xuXG4gICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiBjaDtcbiAgICB9LFxudW5wdXQ6ZnVuY3Rpb24gKGNoKSB7XG4gICAgICAgIHZhciBsZW4gPSBjaC5sZW5ndGg7XG4gICAgICAgIHZhciBsaW5lcyA9IGNoLnNwbGl0KC8oPzpcXHJcXG4/fFxcbikvZyk7XG5cbiAgICAgICAgdGhpcy5faW5wdXQgPSBjaCArIHRoaXMuX2lucHV0O1xuICAgICAgICB0aGlzLnl5dGV4dCA9IHRoaXMueXl0ZXh0LnN1YnN0cigwLCB0aGlzLnl5dGV4dC5sZW5ndGgtbGVuLTEpO1xuICAgICAgICAvL3RoaXMueXlsZW5nIC09IGxlbjtcbiAgICAgICAgdGhpcy5vZmZzZXQgLT0gbGVuO1xuICAgICAgICB2YXIgb2xkTGluZXMgPSB0aGlzLm1hdGNoLnNwbGl0KC8oPzpcXHJcXG4/fFxcbikvZyk7XG4gICAgICAgIHRoaXMubWF0Y2ggPSB0aGlzLm1hdGNoLnN1YnN0cigwLCB0aGlzLm1hdGNoLmxlbmd0aC0xKTtcbiAgICAgICAgdGhpcy5tYXRjaGVkID0gdGhpcy5tYXRjaGVkLnN1YnN0cigwLCB0aGlzLm1hdGNoZWQubGVuZ3RoLTEpO1xuXG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGgtMSkgdGhpcy55eWxpbmVubyAtPSBsaW5lcy5sZW5ndGgtMTtcbiAgICAgICAgdmFyIHIgPSB0aGlzLnl5bGxvYy5yYW5nZTtcblxuICAgICAgICB0aGlzLnl5bGxvYyA9IHtmaXJzdF9saW5lOiB0aGlzLnl5bGxvYy5maXJzdF9saW5lLFxuICAgICAgICAgIGxhc3RfbGluZTogdGhpcy55eWxpbmVubysxLFxuICAgICAgICAgIGZpcnN0X2NvbHVtbjogdGhpcy55eWxsb2MuZmlyc3RfY29sdW1uLFxuICAgICAgICAgIGxhc3RfY29sdW1uOiBsaW5lcyA/XG4gICAgICAgICAgICAgIChsaW5lcy5sZW5ndGggPT09IG9sZExpbmVzLmxlbmd0aCA/IHRoaXMueXlsbG9jLmZpcnN0X2NvbHVtbiA6IDApICsgb2xkTGluZXNbb2xkTGluZXMubGVuZ3RoIC0gbGluZXMubGVuZ3RoXS5sZW5ndGggLSBsaW5lc1swXS5sZW5ndGg6XG4gICAgICAgICAgICAgIHRoaXMueXlsbG9jLmZpcnN0X2NvbHVtbiAtIGxlblxuICAgICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5yYW5nZXMpIHtcbiAgICAgICAgICAgIHRoaXMueXlsbG9jLnJhbmdlID0gW3JbMF0sIHJbMF0gKyB0aGlzLnl5bGVuZyAtIGxlbl07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbm1vcmU6ZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9tb3JlID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbmxlc3M6ZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgdGhpcy51bnB1dCh0aGlzLm1hdGNoLnNsaWNlKG4pKTtcbiAgICB9LFxucGFzdElucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHBhc3QgPSB0aGlzLm1hdGNoZWQuc3Vic3RyKDAsIHRoaXMubWF0Y2hlZC5sZW5ndGggLSB0aGlzLm1hdGNoLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiAocGFzdC5sZW5ndGggPiAyMCA/ICcuLi4nOicnKSArIHBhc3Quc3Vic3RyKC0yMCkucmVwbGFjZSgvXFxuL2csIFwiXCIpO1xuICAgIH0sXG51cGNvbWluZ0lucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5leHQgPSB0aGlzLm1hdGNoO1xuICAgICAgICBpZiAobmV4dC5sZW5ndGggPCAyMCkge1xuICAgICAgICAgICAgbmV4dCArPSB0aGlzLl9pbnB1dC5zdWJzdHIoMCwgMjAtbmV4dC5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAobmV4dC5zdWJzdHIoMCwyMCkrKG5leHQubGVuZ3RoID4gMjAgPyAnLi4uJzonJykpLnJlcGxhY2UoL1xcbi9nLCBcIlwiKTtcbiAgICB9LFxuc2hvd1Bvc2l0aW9uOmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByZSA9IHRoaXMucGFzdElucHV0KCk7XG4gICAgICAgIHZhciBjID0gbmV3IEFycmF5KHByZS5sZW5ndGggKyAxKS5qb2luKFwiLVwiKTtcbiAgICAgICAgcmV0dXJuIHByZSArIHRoaXMudXBjb21pbmdJbnB1dCgpICsgXCJcXG5cIiArIGMrXCJeXCI7XG4gICAgfSxcbm5leHQ6ZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kb25lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5FT0Y7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9pbnB1dCkgdGhpcy5kb25lID0gdHJ1ZTtcblxuICAgICAgICB2YXIgdG9rZW4sXG4gICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgIHRlbXBNYXRjaCxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgY29sLFxuICAgICAgICAgICAgbGluZXM7XG4gICAgICAgIGlmICghdGhpcy5fbW9yZSkge1xuICAgICAgICAgICAgdGhpcy55eXRleHQgPSAnJztcbiAgICAgICAgICAgIHRoaXMubWF0Y2ggPSAnJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcnVsZXMgPSB0aGlzLl9jdXJyZW50UnVsZXMoKTtcbiAgICAgICAgZm9yICh2YXIgaT0wO2kgPCBydWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGVtcE1hdGNoID0gdGhpcy5faW5wdXQubWF0Y2godGhpcy5ydWxlc1tydWxlc1tpXV0pO1xuICAgICAgICAgICAgaWYgKHRlbXBNYXRjaCAmJiAoIW1hdGNoIHx8IHRlbXBNYXRjaFswXS5sZW5ndGggPiBtYXRjaFswXS5sZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2ggPSB0ZW1wTWF0Y2g7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5vcHRpb25zLmZsZXgpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgbGluZXMgPSBtYXRjaFswXS5tYXRjaCgvKD86XFxyXFxuP3xcXG4pLiovZyk7XG4gICAgICAgICAgICBpZiAobGluZXMpIHRoaXMueXlsaW5lbm8gKz0gbGluZXMubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy55eWxsb2MgPSB7Zmlyc3RfbGluZTogdGhpcy55eWxsb2MubGFzdF9saW5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9saW5lOiB0aGlzLnl5bGluZW5vKzEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBmaXJzdF9jb2x1bW46IHRoaXMueXlsbG9jLmxhc3RfY29sdW1uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9jb2x1bW46IGxpbmVzID8gbGluZXNbbGluZXMubGVuZ3RoLTFdLmxlbmd0aC1saW5lc1tsaW5lcy5sZW5ndGgtMV0ubWF0Y2goL1xccj9cXG4/LylbMF0ubGVuZ3RoIDogdGhpcy55eWxsb2MubGFzdF9jb2x1bW4gKyBtYXRjaFswXS5sZW5ndGh9O1xuICAgICAgICAgICAgdGhpcy55eXRleHQgKz0gbWF0Y2hbMF07XG4gICAgICAgICAgICB0aGlzLm1hdGNoICs9IG1hdGNoWzBdO1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzID0gbWF0Y2g7XG4gICAgICAgICAgICB0aGlzLnl5bGVuZyA9IHRoaXMueXl0ZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy55eWxsb2MucmFuZ2UgPSBbdGhpcy5vZmZzZXQsIHRoaXMub2Zmc2V0ICs9IHRoaXMueXlsZW5nXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX21vcmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UobWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMubWF0Y2hlZCArPSBtYXRjaFswXTtcbiAgICAgICAgICAgIHRva2VuID0gdGhpcy5wZXJmb3JtQWN0aW9uLmNhbGwodGhpcywgdGhpcy55eSwgdGhpcywgcnVsZXNbaW5kZXhdLHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMV0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuZG9uZSAmJiB0aGlzLl9pbnB1dCkgdGhpcy5kb25lID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodG9rZW4pIHJldHVybiB0b2tlbjtcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnB1dCA9PT0gXCJcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuRU9GO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VFcnJvcignTGV4aWNhbCBlcnJvciBvbiBsaW5lICcrKHRoaXMueXlsaW5lbm8rMSkrJy4gVW5yZWNvZ25pemVkIHRleHQuXFxuJyt0aGlzLnNob3dQb3NpdGlvbigpLFxuICAgICAgICAgICAgICAgICAgICB7dGV4dDogXCJcIiwgdG9rZW46IG51bGwsIGxpbmU6IHRoaXMueXlsaW5lbm99KTtcbiAgICAgICAgfVxuICAgIH0sXG5sZXg6ZnVuY3Rpb24gbGV4KCkge1xuICAgICAgICB2YXIgciA9IHRoaXMubmV4dCgpO1xuICAgICAgICBpZiAodHlwZW9mIHIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxleCgpO1xuICAgICAgICB9XG4gICAgfSxcbmJlZ2luOmZ1bmN0aW9uIGJlZ2luKGNvbmRpdGlvbikge1xuICAgICAgICB0aGlzLmNvbmRpdGlvblN0YWNrLnB1c2goY29uZGl0aW9uKTtcbiAgICB9LFxucG9wU3RhdGU6ZnVuY3Rpb24gcG9wU3RhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRpdGlvblN0YWNrLnBvcCgpO1xuICAgIH0sXG5fY3VycmVudFJ1bGVzOmZ1bmN0aW9uIF9jdXJyZW50UnVsZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRpdGlvbnNbdGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0xXV0ucnVsZXM7XG4gICAgfSxcbnRvcFN0YXRlOmZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMl07XG4gICAgfSxcbnB1c2hTdGF0ZTpmdW5jdGlvbiBiZWdpbihjb25kaXRpb24pIHtcbiAgICAgICAgdGhpcy5iZWdpbihjb25kaXRpb24pO1xuICAgIH19KTtcbmxleGVyLm9wdGlvbnMgPSB7fTtcbmxleGVyLnBlcmZvcm1BY3Rpb24gPSBmdW5jdGlvbiBhbm9ueW1vdXMoeXkseXlfLCRhdm9pZGluZ19uYW1lX2NvbGxpc2lvbnMsWVlfU1RBUlRcbi8qKi8pIHtcblxuXG5mdW5jdGlvbiBzdHJpcChzdGFydCwgZW5kKSB7XG4gIHJldHVybiB5eV8ueXl0ZXh0ID0geXlfLnl5dGV4dC5zdWJzdHIoc3RhcnQsIHl5Xy55eWxlbmctZW5kKTtcbn1cblxuXG52YXIgWVlTVEFURT1ZWV9TVEFSVFxuc3dpdGNoKCRhdm9pZGluZ19uYW1lX2NvbGxpc2lvbnMpIHtcbmNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoeXlfLnl5dGV4dC5zbGljZSgtMikgPT09IFwiXFxcXFxcXFxcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmlwKDAsMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iZWdpbihcIm11XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeXlfLnl5dGV4dC5zbGljZSgtMSkgPT09IFwiXFxcXFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaXAoMCwxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luKFwiZW11XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmVnaW4oXCJtdVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZih5eV8ueXl0ZXh0KSByZXR1cm4gMTU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmJyZWFrO1xuY2FzZSAxOnJldHVybiAxNTtcbmJyZWFrO1xuY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvcFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxNTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuYnJlYWs7XG5jYXNlIDM6dGhpcy5iZWdpbigncmF3Jyk7IHJldHVybiAxNTtcbmJyZWFrO1xuY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9wU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgYmUgdXNpbmcgYHRoaXMudG9wU3RhdGUoKWAgYmVsb3csIGJ1dCBpdCBjdXJyZW50bHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm5zIHRoZSBzZWNvbmQgdG9wIGluc3RlYWQgb2YgdGhlIGZpcnN0IHRvcC4gT3BlbmVkIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXNzdWUgYWJvdXQgaXQgYXQgaHR0cHM6Ly9naXRodWIuY29tL3phYWNoL2ppc29uL2lzc3Vlcy8yOTFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0xXSA9PT0gJ3JhdycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxNTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeXlfLnl5dGV4dCA9IHl5Xy55eXRleHQuc3Vic3RyKDUsIHl5Xy55eWxlbmctOSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ0VORF9SQVdfQkxPQ0snO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuYnJlYWs7XG5jYXNlIDU6IHJldHVybiAxNTsgXG5icmVhaztcbmNhc2UgNjpcbiAgdGhpcy5wb3BTdGF0ZSgpO1xuICByZXR1cm4gMTQ7XG5cbmJyZWFrO1xuY2FzZSA3OnJldHVybiA2NTtcbmJyZWFrO1xuY2FzZSA4OnJldHVybiA2ODtcbmJyZWFrO1xuY2FzZSA5OiByZXR1cm4gMTk7IFxuYnJlYWs7XG5jYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9wU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luKCdyYXcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMjM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmJyZWFrO1xuY2FzZSAxMTpyZXR1cm4gNTU7XG5icmVhaztcbmNhc2UgMTI6cmV0dXJuIDYwO1xuYnJlYWs7XG5jYXNlIDEzOnJldHVybiAyOTtcbmJyZWFrO1xuY2FzZSAxNDpyZXR1cm4gNDc7XG5icmVhaztcbmNhc2UgMTU6dGhpcy5wb3BTdGF0ZSgpOyByZXR1cm4gNDQ7XG5icmVhaztcbmNhc2UgMTY6dGhpcy5wb3BTdGF0ZSgpOyByZXR1cm4gNDQ7XG5icmVhaztcbmNhc2UgMTc6cmV0dXJuIDM0O1xuYnJlYWs7XG5jYXNlIDE4OnJldHVybiAzOTtcbmJyZWFrO1xuY2FzZSAxOTpyZXR1cm4gNTE7XG5icmVhaztcbmNhc2UgMjA6cmV0dXJuIDQ4O1xuYnJlYWs7XG5jYXNlIDIxOlxuICB0aGlzLnVucHV0KHl5Xy55eXRleHQpO1xuICB0aGlzLnBvcFN0YXRlKCk7XG4gIHRoaXMuYmVnaW4oJ2NvbScpO1xuXG5icmVhaztcbmNhc2UgMjI6XG4gIHRoaXMucG9wU3RhdGUoKTtcbiAgcmV0dXJuIDE0O1xuXG5icmVhaztcbmNhc2UgMjM6cmV0dXJuIDQ4O1xuYnJlYWs7XG5jYXNlIDI0OnJldHVybiA3MztcbmJyZWFrO1xuY2FzZSAyNTpyZXR1cm4gNzI7XG5icmVhaztcbmNhc2UgMjY6cmV0dXJuIDcyO1xuYnJlYWs7XG5jYXNlIDI3OnJldHVybiA4NztcbmJyZWFrO1xuY2FzZSAyODovLyBpZ25vcmUgd2hpdGVzcGFjZVxuYnJlYWs7XG5jYXNlIDI5OnRoaXMucG9wU3RhdGUoKTsgcmV0dXJuIDU0O1xuYnJlYWs7XG5jYXNlIDMwOnRoaXMucG9wU3RhdGUoKTsgcmV0dXJuIDMzO1xuYnJlYWs7XG5jYXNlIDMxOnl5Xy55eXRleHQgPSBzdHJpcCgxLDIpLnJlcGxhY2UoL1xcXFxcIi9nLCdcIicpOyByZXR1cm4gODA7XG5icmVhaztcbmNhc2UgMzI6eXlfLnl5dGV4dCA9IHN0cmlwKDEsMikucmVwbGFjZSgvXFxcXCcvZyxcIidcIik7IHJldHVybiA4MDtcbmJyZWFrO1xuY2FzZSAzMzpyZXR1cm4gODU7XG5icmVhaztcbmNhc2UgMzQ6cmV0dXJuIDgyO1xuYnJlYWs7XG5jYXNlIDM1OnJldHVybiA4MjtcbmJyZWFrO1xuY2FzZSAzNjpyZXR1cm4gODM7XG5icmVhaztcbmNhc2UgMzc6cmV0dXJuIDg0O1xuYnJlYWs7XG5jYXNlIDM4OnJldHVybiA4MTtcbmJyZWFrO1xuY2FzZSAzOTpyZXR1cm4gNzU7XG5icmVhaztcbmNhc2UgNDA6cmV0dXJuIDc3O1xuYnJlYWs7XG5jYXNlIDQxOnJldHVybiA3MjtcbmJyZWFrO1xuY2FzZSA0Mjp5eV8ueXl0ZXh0ID0geXlfLnl5dGV4dC5yZXBsYWNlKC9cXFxcKFtcXFxcXFxdXSkvZywnJDEnKTsgcmV0dXJuIDcyO1xuYnJlYWs7XG5jYXNlIDQzOnJldHVybiAnSU5WQUxJRCc7XG5icmVhaztcbmNhc2UgNDQ6cmV0dXJuIDU7XG5icmVhaztcbn1cbn07XG5sZXhlci5ydWxlcyA9IFsvXig/OlteXFx4MDBdKj8oPz0oXFx7XFx7KSkpLywvXig/OlteXFx4MDBdKykvLC9eKD86W15cXHgwMF17Mix9Pyg/PShcXHtcXHt8XFxcXFxce1xce3xcXFxcXFxcXFxce1xce3wkKSkpLywvXig/Olxce1xce1xce1xceyg/PVteXFwvXSkpLywvXig/Olxce1xce1xce1xce1xcL1teXFxzIVwiIyUtLFxcLlxcLzstPkBcXFstXFxeYFxcey1+XSsoPz1bPX1cXHNcXC8uXSlcXH1cXH1cXH1cXH0pLywvXig/OlteXFx4MDBdKj8oPz0oXFx7XFx7XFx7XFx7KSkpLywvXig/OltcXHNcXFNdKj8tLSh+KT9cXH1cXH0pLywvXig/OlxcKCkvLC9eKD86XFwpKS8sL14oPzpcXHtcXHtcXHtcXHspLywvXig/OlxcfVxcfVxcfVxcfSkvLC9eKD86XFx7XFx7KH4pPz4pLywvXig/Olxce1xceyh+KT8jPikvLC9eKD86XFx7XFx7KH4pPyNcXCo/KS8sL14oPzpcXHtcXHsofik/XFwvKS8sL14oPzpcXHtcXHsofik/XFxeXFxzKih+KT9cXH1cXH0pLywvXig/Olxce1xceyh+KT9cXHMqZWxzZVxccyoofik/XFx9XFx9KS8sL14oPzpcXHtcXHsofik/XFxeKS8sL14oPzpcXHtcXHsofik/XFxzKmVsc2VcXGIpLywvXig/Olxce1xceyh+KT9cXHspLywvXig/Olxce1xceyh+KT8mKS8sL14oPzpcXHtcXHsofik/IS0tKS8sL14oPzpcXHtcXHsofik/IVtcXHNcXFNdKj9cXH1cXH0pLywvXig/Olxce1xceyh+KT9cXCo/KS8sL14oPzo9KS8sL14oPzpcXC5cXC4pLywvXig/OlxcLig/PShbPX59XFxzXFwvLil8XSkpKS8sL14oPzpbXFwvLl0pLywvXig/OlxccyspLywvXig/OlxcfSh+KT9cXH1cXH0pLywvXig/Oih+KT9cXH1cXH0pLywvXig/OlwiKFxcXFxbXCJdfFteXCJdKSpcIikvLC9eKD86JyhcXFxcWyddfFteJ10pKicpLywvXig/OkApLywvXig/OnRydWUoPz0oW359XFxzKV0pKSkvLC9eKD86ZmFsc2UoPz0oW359XFxzKV0pKSkvLC9eKD86dW5kZWZpbmVkKD89KFt+fVxccyldKSkpLywvXig/Om51bGwoPz0oW359XFxzKV0pKSkvLC9eKD86LT9bMC05XSsoPzpcXC5bMC05XSspPyg/PShbfn1cXHMpXSkpKS8sL14oPzphc1xccytcXHwpLywvXig/OlxcfCkvLC9eKD86KFteXFxzIVwiIyUtLFxcLlxcLzstPkBcXFstXFxeYFxcey1+XSsoPz0oWz1+fVxcc1xcLy4pfF0pKSkpLywvXig/OlxcWyhcXFxcXFxdfFteXFxdXSkqXFxdKS8sL14oPzouKS8sL14oPzokKS9dO1xubGV4ZXIuY29uZGl0aW9ucyA9IHtcIm11XCI6e1wicnVsZXNcIjpbNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDRdLFwiaW5jbHVzaXZlXCI6ZmFsc2V9LFwiZW11XCI6e1wicnVsZXNcIjpbMl0sXCJpbmNsdXNpdmVcIjpmYWxzZX0sXCJjb21cIjp7XCJydWxlc1wiOls2XSxcImluY2x1c2l2ZVwiOmZhbHNlfSxcInJhd1wiOntcInJ1bGVzXCI6WzMsNCw1XSxcImluY2x1c2l2ZVwiOmZhbHNlfSxcIklOSVRJQUxcIjp7XCJydWxlc1wiOlswLDEsNDRdLFwiaW5jbHVzaXZlXCI6dHJ1ZX19O1xucmV0dXJuIGxleGVyO30pKClcbnBhcnNlci5sZXhlciA9IGxleGVyO1xuZnVuY3Rpb24gUGFyc2VyICgpIHsgdGhpcy55eSA9IHt9OyB9UGFyc2VyLnByb3RvdHlwZSA9IHBhcnNlcjtwYXJzZXIuUGFyc2VyID0gUGFyc2VyO1xucmV0dXJuIG5ldyBQYXJzZXI7XG59KSgpO2V4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5leHBvcnRzWydkZWZhdWx0J10gPSBoYW5kbGViYXJzO1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/printer.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/printer.js new file mode 100644 index 0000000..069645d --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/printer.js @@ -0,0 +1,186 @@ +/* eslint-disable new-cap */ +'use strict'; + +exports.__esModule = true; +exports.print = print; +exports.PrintVisitor = PrintVisitor; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _visitor = require('./visitor'); + +var _visitor2 = _interopRequireDefault(_visitor); + +function print(ast) { + return new PrintVisitor().accept(ast); +} + +function PrintVisitor() { + this.padding = 0; +} + +PrintVisitor.prototype = new _visitor2['default'](); + +PrintVisitor.prototype.pad = function (string) { + var out = ''; + + for (var i = 0, l = this.padding; i < l; i++) { + out += ' '; + } + + out += string + '\n'; + return out; +}; + +PrintVisitor.prototype.Program = function (program) { + var out = '', + body = program.body, + i = undefined, + l = undefined; + + if (program.blockParams) { + var blockParams = 'BLOCK PARAMS: ['; + for (i = 0, l = program.blockParams.length; i < l; i++) { + blockParams += ' ' + program.blockParams[i]; + } + blockParams += ' ]'; + out += this.pad(blockParams); + } + + for (i = 0, l = body.length; i < l; i++) { + out += this.accept(body[i]); + } + + this.padding--; + + return out; +}; + +PrintVisitor.prototype.MustacheStatement = function (mustache) { + return this.pad('{{ ' + this.SubExpression(mustache) + ' }}'); +}; +PrintVisitor.prototype.Decorator = function (mustache) { + return this.pad('{{ DIRECTIVE ' + this.SubExpression(mustache) + ' }}'); +}; + +PrintVisitor.prototype.BlockStatement = PrintVisitor.prototype.DecoratorBlock = function (block) { + var out = ''; + + out += this.pad((block.type === 'DecoratorBlock' ? 'DIRECTIVE ' : '') + 'BLOCK:'); + this.padding++; + out += this.pad(this.SubExpression(block)); + if (block.program) { + out += this.pad('PROGRAM:'); + this.padding++; + out += this.accept(block.program); + this.padding--; + } + if (block.inverse) { + if (block.program) { + this.padding++; + } + out += this.pad('{{^}}'); + this.padding++; + out += this.accept(block.inverse); + this.padding--; + if (block.program) { + this.padding--; + } + } + this.padding--; + + return out; +}; + +PrintVisitor.prototype.PartialStatement = function (partial) { + var content = 'PARTIAL:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + return this.pad('{{> ' + content + ' }}'); +}; +PrintVisitor.prototype.PartialBlockStatement = function (partial) { + var content = 'PARTIAL BLOCK:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + + content += ' ' + this.pad('PROGRAM:'); + this.padding++; + content += this.accept(partial.program); + this.padding--; + + return this.pad('{{> ' + content + ' }}'); +}; + +PrintVisitor.prototype.ContentStatement = function (content) { + return this.pad("CONTENT[ '" + content.value + "' ]"); +}; + +PrintVisitor.prototype.CommentStatement = function (comment) { + return this.pad("{{! '" + comment.value + "' }}"); +}; + +PrintVisitor.prototype.SubExpression = function (sexpr) { + var params = sexpr.params, + paramStrings = [], + hash = undefined; + + for (var i = 0, l = params.length; i < l; i++) { + paramStrings.push(this.accept(params[i])); + } + + params = '[' + paramStrings.join(', ') + ']'; + + hash = sexpr.hash ? ' ' + this.accept(sexpr.hash) : ''; + + return this.accept(sexpr.path) + ' ' + params + hash; +}; + +PrintVisitor.prototype.PathExpression = function (id) { + var path = id.parts.join('/'); + return (id.data ? '@' : '') + 'PATH:' + path; +}; + +PrintVisitor.prototype.StringLiteral = function (string) { + return '"' + string.value + '"'; +}; + +PrintVisitor.prototype.NumberLiteral = function (number) { + return 'NUMBER{' + number.value + '}'; +}; + +PrintVisitor.prototype.BooleanLiteral = function (bool) { + return 'BOOLEAN{' + bool.value + '}'; +}; + +PrintVisitor.prototype.UndefinedLiteral = function () { + return 'UNDEFINED'; +}; + +PrintVisitor.prototype.NullLiteral = function () { + return 'NULL'; +}; + +PrintVisitor.prototype.Hash = function (hash) { + var pairs = hash.pairs, + joinedPairs = []; + + for (var i = 0, l = pairs.length; i < l; i++) { + joinedPairs.push(this.accept(pairs[i])); + } + + return 'HASH{' + joinedPairs.join(', ') + '}'; +}; +PrintVisitor.prototype.HashPair = function (pair) { + return pair.key + '=' + this.accept(pair.value); +}; +/* eslint-enable new-cap */ +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3ByaW50ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozt1QkFDb0IsV0FBVzs7OztBQUV4QixTQUFTLEtBQUssQ0FBQyxHQUFHLEVBQUU7QUFDekIsU0FBTyxJQUFJLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztDQUN2Qzs7QUFFTSxTQUFTLFlBQVksR0FBRztBQUM3QixNQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztDQUNsQjs7QUFFRCxZQUFZLENBQUMsU0FBUyxHQUFHLDBCQUFhLENBQUM7O0FBRXZDLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxHQUFHLFVBQVMsTUFBTSxFQUFFO0FBQzVDLE1BQUksR0FBRyxHQUFHLEVBQUUsQ0FBQzs7QUFFYixPQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQzVDLE9BQUcsSUFBSSxJQUFJLENBQUM7R0FDYjs7QUFFRCxLQUFHLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQztBQUNyQixTQUFPLEdBQUcsQ0FBQztDQUNaLENBQUM7O0FBRUYsWUFBWSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEdBQUcsVUFBUyxPQUFPLEVBQUU7QUFDakQsTUFBSSxHQUFHLEdBQUcsRUFBRTtNQUNSLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSTtNQUNuQixDQUFDLFlBQUE7TUFBRSxDQUFDLFlBQUEsQ0FBQzs7QUFFVCxNQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUU7QUFDdkIsUUFBSSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7QUFDcEMsU0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMs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SUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0dBQ3pDOztBQUVELFNBQU8sT0FBTyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDO0NBQy9DLENBQUM7QUFDRixZQUFZLENBQUMsU0FBUyxDQUFDLFFBQVEsR0FBRyxVQUFTLElBQUksRUFBRTtBQUMvQyxTQUFPLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0NBQ2pELENBQUMiLCJmaWxlIjoicHJpbnRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5ldy1jYXAgKi9cbmltcG9ydCBWaXNpdG9yIGZyb20gJy4vdmlzaXRvcic7XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmludChhc3QpIHtcbiAgcmV0dXJuIG5ldyBQcmludFZpc2l0b3IoKS5hY2NlcHQoYXN0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFByaW50VmlzaXRvcigpIHtcbiAgdGhpcy5wYWRkaW5nID0gMDtcbn1cblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZSA9IG5ldyBWaXNpdG9yKCk7XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUucGFkID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gIGxldCBvdXQgPSAnJztcblxuICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMucGFkZGluZzsgaSA8IGw7IGkrKykge1xuICAgIG91dCArPSAnICAnO1xuICB9XG5cbiAgb3V0ICs9IHN0cmluZyArICdcXG4nO1xuICByZXR1cm4gb3V0O1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5Qcm9ncmFtID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICBsZXQgb3V0ID0gJycsXG4gICAgICBib2R5ID0gcHJvZ3JhbS5ib2R5LFxuICAgICAgaSwgbDtcblxuICBpZiAocHJvZ3JhbS5ibG9ja1BhcmFtcykge1xuICAgIGxldCBibG9ja1BhcmFtcyA9ICdCTE9DSyBQQVJBTVM6IFsnO1xuICAgIGZvciAoaSA9IDAsIGwgPSBwcm9ncmFtLmJsb2NrUGFyYW1zLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgIGJsb2NrUGFyYW1zICs9ICcgJyArIHByb2dyYW0uYmxvY2tQYXJhbXNbaV07XG4gICAgfVxuICAgIGJsb2NrUGFyYW1zICs9ICcgXSc7XG4gICAgb3V0ICs9IHRoaXMucGFkKGJsb2NrUGFyYW1zKTtcbiAgfVxuXG4gIGZvciAoaSA9IDAsIGwgPSBib2R5Lmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIG91dCArPSB0aGlzLmFjY2VwdChib2R5W2ldKTtcbiAgfVxuXG4gIHRoaXMucGFkZGluZy0tO1xuXG4gIHJldHVybiBvdXQ7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLk11c3RhY2hlU3RhdGVtZW50ID0gZnVuY3Rpb24obXVzdGFjaGUpIHtcbiAgcmV0dXJuIHRoaXMucGFkKCd7eyAnICsgdGhpcy5TdWJFeHByZXNzaW9uKG11c3RhY2hlKSArICcgfX0nKTtcbn07XG5QcmludFZpc2l0b3IucHJvdG90eXBlLkRlY29yYXRvciA9IGZ1bmN0aW9uKG11c3RhY2hlKSB7XG4gIHJldHVybiB0aGlzLnBhZCgne3sgRElSRUNUSVZFICcgKyB0aGlzLlN1YkV4cHJlc3Npb24obXVzdGFjaGUpICsgJyB9fScpO1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5CbG9ja1N0YXRlbWVudCA9XG5QcmludFZpc2l0b3IucHJvdG90eXBlLkRlY29yYXRvckJsb2NrID0gZnVuY3Rpb24oYmxvY2spIHtcbiAgbGV0IG91dCA9ICcnO1xuXG4gIG91dCArPSB0aGlzLnBhZCgoYmxvY2sudHlwZSA9PT0gJ0RlY29yYXRvckJsb2NrJyA/ICdESVJFQ1RJVkUgJyA6ICcnKSArICdCTE9DSzonKTtcbiAgdGhpcy5wYWRkaW5nKys7XG4gIG91dCArPSB0aGlzLnBhZCh0aGlzLlN1YkV4cHJlc3Npb24oYmxvY2spKTtcbiAgaWYgKGJsb2NrLnByb2dyYW0pIHtcbiAgICBvdXQgKz0gdGhpcy5wYWQoJ1BST0dSQU06Jyk7XG4gICAgdGhpcy5wYWRkaW5nKys7XG4gICAgb3V0ICs9IHRoaXMuYWNjZXB0KGJsb2NrLnByb2dyYW0pO1xuICAgIHRoaXMucGFkZGluZy0tO1xuICB9XG4gIGlmIChibG9jay5pbnZlcnNlKSB7XG4gICAgaWYgKGJsb2NrLnByb2dyYW0pIHsgdGhpcy5wYWRkaW5nKys7IH1cbiAgICBvdXQgKz0gdGhpcy5wYWQoJ3t7Xn19Jyk7XG4gICAgdGhpcy5wYWRkaW5nKys7XG4gICAgb3V0ICs9IHRoaXMuYWNjZXB0KGJsb2NrLmludmVyc2UpO1xuICAgIHRoaXMucGFkZGluZy0tO1xuICAgIGlmIChibG9jay5wcm9ncmFtKSB7IHRoaXMucGFkZGluZy0tOyB9XG4gIH1cbiAgdGhpcy5wYWRkaW5nLS07XG5cbiAgcmV0dXJuIG91dDtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuUGFydGlhbFN0YXRlbWVudCA9IGZ1bmN0aW9uKHBhcnRpYWwpIHtcbiAgbGV0IGNvbnRlbnQgPSAnUEFSVElBTDonICsgcGFydGlhbC5uYW1lLm9yaWdpbmFsO1xuICBpZiAocGFydGlhbC5wYXJhbXNbMF0pIHtcbiAgICBjb250ZW50ICs9ICcgJyArIHRoaXMuYWNjZXB0KHBhcnRpYWwucGFyYW1zWzBdKTtcbiAgfVxuICBpZiAocGFydGlhbC5oYXNoKSB7XG4gICAgY29udGVudCArPSAnICcgKyB0aGlzLmFjY2VwdChwYXJ0aWFsLmhhc2gpO1xuICB9XG4gIHJldHVybiB0aGlzLnBhZCgne3s+ICcgKyBjb250ZW50ICsgJyB9fScpO1xufTtcblByaW50VmlzaXRvci5wcm90b3R5cGUuUGFydGlhbEJsb2NrU3RhdGVtZW50ID0gZnVuY3Rpb24ocGFydGlhbCkge1xuICBsZXQgY29udGVudCA9ICdQQVJUSUFMIEJMT0NLOicgKyBwYXJ0aWFsLm5hbWUub3JpZ2luYWw7XG4gIGlmIChwYXJ0aWFsLnBhcmFtc1swXSkge1xuICAgIGNvbnRlbnQgKz0gJyAnICsgdGhpcy5hY2NlcHQocGFydGlhbC5wYXJhbXNbMF0pO1xuICB9XG4gIGlmIChwYXJ0aWFsLmhhc2gpIHtcbiAgICBjb250ZW50ICs9ICcgJyArIHRoaXMuYWNjZXB0KHBhcnRpYWwuaGFzaCk7XG4gIH1cblxuICBjb250ZW50ICs9ICcgJyArIHRoaXMucGFkKCdQUk9HUkFNOicpO1xuICB0aGlzLnBhZGRpbmcrKztcbiAgY29udGVudCArPSB0aGlzLmFjY2VwdChwYXJ0aWFsLnByb2dyYW0pO1xuICB0aGlzLnBhZGRpbmctLTtcblxuICByZXR1cm4gdGhpcy5wYWQoJ3t7PiAnICsgY29udGVudCArICcgfX0nKTtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuQ29udGVudFN0YXRlbWVudCA9IGZ1bmN0aW9uKGNvbnRlbnQpIHtcbiAgcmV0dXJuIHRoaXMucGFkKFwiQ09OVEVOVFsgJ1wiICsgY29udGVudC52YWx1ZSArIFwiJyBdXCIpO1xufTtcblxuUHJpbnRWaXNpdG9yLnByb3RvdHlwZS5Db21tZW50U3RhdGVtZW50ID0gZnVuY3Rpb24oY29tbWVudCkge1xuICByZXR1cm4gdGhpcy5wYWQoXCJ7eyEgJ1wiICsgY29tbWVudC52YWx1ZSArIFwiJyB9fVwiKTtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuU3ViRXhwcmVzc2lvbiA9IGZ1bmN0aW9uKHNleHByKSB7XG4gIGxldCBwYXJhbXMgPSBzZXhwci5wYXJhbXMsXG4gICAgICBwYXJhbVN0cmluZ3MgPSBbXSxcbiAgICAgIGhhc2g7XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBwYXJhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgcGFyYW1TdHJpbmdzLnB1c2godGhpcy5hY2NlcHQocGFyYW1zW2ldKSk7XG4gIH1cblxuICBwYXJhbXMgPSAnWycgKyBwYXJhbVN0cmluZ3Muam9pbignLCAnKSArICddJztcblxuICBoYXNoID0gc2V4cHIuaGFzaCA/ICcgJyArIHRoaXMuYWNjZXB0KHNleHByLmhhc2gpIDogJyc7XG5cbiAgcmV0dXJuIHRoaXMuYWNjZXB0KHNleHByLnBhdGgpICsgJyAnICsgcGFyYW1zICsgaGFzaDtcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuUGF0aEV4cHJlc3Npb24gPSBmdW5jdGlvbihpZCkge1xuICBsZXQgcGF0aCA9IGlkLnBhcnRzLmpvaW4oJy8nKTtcbiAgcmV0dXJuIChpZC5kYXRhID8gJ0AnIDogJycpICsgJ1BBVEg6JyArIHBhdGg7XG59O1xuXG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuU3RyaW5nTGl0ZXJhbCA9IGZ1bmN0aW9uKHN0cmluZykge1xuICByZXR1cm4gJ1wiJyArIHN0cmluZy52YWx1ZSArICdcIic7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLk51bWJlckxpdGVyYWwgPSBmdW5jdGlvbihudW1iZXIpIHtcbiAgcmV0dXJuICdOVU1CRVJ7JyArIG51bWJlci52YWx1ZSArICd9Jztcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuQm9vbGVhbkxpdGVyYWwgPSBmdW5jdGlvbihib29sKSB7XG4gIHJldHVybiAnQk9PTEVBTnsnICsgYm9vbC52YWx1ZSArICd9Jztcbn07XG5cblByaW50VmlzaXRvci5wcm90b3R5cGUuVW5kZWZpbmVkTGl0ZXJhbCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gJ1VOREVGSU5FRCc7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLk51bGxMaXRlcmFsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAnTlVMTCc7XG59O1xuXG5QcmludFZpc2l0b3IucHJvdG90eXBlLkhhc2ggPSBmdW5jdGlvbihoYXNoKSB7XG4gIGxldCBwYWlycyA9IGhhc2gucGFpcnMsXG4gICAgICBqb2luZWRQYWlycyA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwLCBsID0gcGFpcnMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgam9pbmVkUGFpcnMucHVzaCh0aGlzLmFjY2VwdChwYWlyc1tpXSkpO1xuICB9XG5cbiAgcmV0dXJuICdIQVNIeycgKyBqb2luZWRQYWlycy5qb2luKCcsICcpICsgJ30nO1xufTtcblByaW50VmlzaXRvci5wcm90b3R5cGUuSGFzaFBhaXIgPSBmdW5jdGlvbihwYWlyKSB7XG4gIHJldHVybiBwYWlyLmtleSArICc9JyArIHRoaXMuYWNjZXB0KHBhaXIudmFsdWUpO1xufTtcbi8qIGVzbGludC1lbmFibGUgbmV3LWNhcCAqL1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/visitor.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/visitor.js new file mode 100644 index 0000000..7814d1e --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/visitor.js @@ -0,0 +1,140 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _exception = require('../exception'); + +var _exception2 = _interopRequireDefault(_exception); + +function Visitor() { + this.parents = []; +} + +Visitor.prototype = { + constructor: Visitor, + mutating: false, + + // Visits a given value. If mutating, will replace the value if necessary. + acceptKey: function acceptKey(node, name) { + var value = this.accept(node[name]); + if (this.mutating) { + // Hacky sanity check: This may have a few false positives for type for the helper + // methods but will generally do the right thing without a lot of overhead. + if (value && !Visitor.prototype[value.type]) { + throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); + } + node[name] = value; + } + }, + + // Performs an accept operation with added sanity check to ensure + // required keys are not removed. + acceptRequired: function acceptRequired(node, name) { + this.acceptKey(node, name); + + if (!node[name]) { + throw new _exception2['default'](node.type + ' requires ' + name); + } + }, + + // Traverses a given array. If mutating, empty respnses will be removed + // for child elements. + acceptArray: function acceptArray(array) { + for (var i = 0, l = array.length; i < l; i++) { + this.acceptKey(array, i); + + if (!array[i]) { + array.splice(i, 1); + i--; + l--; + } + } + }, + + accept: function accept(object) { + if (!object) { + return; + } + + /* istanbul ignore next: Sanity code */ + if (!this[object.type]) { + throw new _exception2['default']('Unknown type: ' + object.type, object); + } + + if (this.current) { + this.parents.unshift(this.current); + } + this.current = object; + + var ret = this[object.type](object); + + this.current = this.parents.shift(); + + if (!this.mutating || ret) { + return ret; + } else if (ret !== false) { + return object; + } + }, + + Program: function Program(program) { + this.acceptArray(program.body); + }, + + MustacheStatement: visitSubExpression, + Decorator: visitSubExpression, + + BlockStatement: visitBlock, + DecoratorBlock: visitBlock, + + PartialStatement: visitPartial, + PartialBlockStatement: function PartialBlockStatement(partial) { + visitPartial.call(this, partial); + + this.acceptKey(partial, 'program'); + }, + + ContentStatement: function ContentStatement() /* content */{}, + CommentStatement: function CommentStatement() /* comment */{}, + + SubExpression: visitSubExpression, + + PathExpression: function PathExpression() /* path */{}, + + StringLiteral: function StringLiteral() /* string */{}, + NumberLiteral: function NumberLiteral() /* number */{}, + BooleanLiteral: function BooleanLiteral() /* bool */{}, + UndefinedLiteral: function UndefinedLiteral() /* literal */{}, + NullLiteral: function NullLiteral() /* literal */{}, + + Hash: function Hash(hash) { + this.acceptArray(hash.pairs); + }, + HashPair: function HashPair(pair) { + this.acceptRequired(pair, 'value'); + } +}; + +function visitSubExpression(mustache) { + this.acceptRequired(mustache, 'path'); + this.acceptArray(mustache.params); + this.acceptKey(mustache, 'hash'); +} +function visitBlock(block) { + visitSubExpression.call(this, block); + + this.acceptKey(block, 'program'); + this.acceptKey(block, 'inverse'); +} +function visitPartial(partial) { + this.acceptRequired(partial, 'name'); + this.acceptArray(partial.params); + this.acceptKey(partial, 'hash'); +} + +exports['default'] = Visitor; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3Zpc2l0b3IuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozt5QkFBc0IsY0FBYzs7OztBQUVwQyxTQUFTLE9BQU8sR0FBRztBQUNqQixNQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztDQUNuQjs7QUFFRCxPQUFPLENBQUMsU0FBUyxHQUFHO0FBQ2xCLGFBQVcsRUFBRSxPQUFPO0FBQ3BCLFVBQVEsRUFBRSxLQUFLOzs7QUFHZixXQUFTLEVBQUUsbUJBQVMsSUFBSSxFQUFFLElBQUksRUFBRTtBQUM5QixRQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3BDLFFBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTs7O0FBR2pCLFVBQUksS0FBSyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7QUFDM0MsY0FBTSwyQkFBYyx3QkFBd0IsR0FBRyxLQUFLLENBQUMsSUFBSSxHQUFHLHlCQUF5QixHQUFHLElBQUksR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ3BIO0FBQ0QsVUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQztLQUNwQjtHQUNGOzs7O0FBSUQsZ0JBQWMsRUFBRSx3QkFBUyxJQUFJLEVBQUUsSUFBSSxFQUFFO0FBQ25DLFFBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDOztBQUUzQixRQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO0FBQ2YsWUFBTSwyQkFBYyxJQUFJLENBQUMsSUFBSSxHQUFHLFlBQVksR0FBRyxJQUFJLENBQUMsQ0FBQztLQUN0RDtHQUNGOzs7O0FBSUQsYUFBVyxFQUFFLHFCQUFTLEtBQUssRUFBRTtBQUMzQixTQUFLLElBQUksQ0FBQyxHQUFH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O0FBQ2xDLE1BQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0NBQ2xDO0FBQ0QsU0FBUyxVQUFVLENBQUMsS0FBSyxFQUFFO0FBQ3pCLG9CQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7O0FBRXJDLE1BQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2pDLE1BQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0NBQ2xDO0FBQ0QsU0FBUyxZQUFZLENBQUMsT0FBTyxFQUFFO0FBQzdCLE1BQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3JDLE1BQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2pDLE1BQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0NBQ2pDOztxQkFFYyxPQUFPIiwiZmlsZSI6InZpc2l0b3IuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5cbmZ1bmN0aW9uIFZpc2l0b3IoKSB7XG4gIHRoaXMucGFyZW50cyA9IFtdO1xufVxuXG5WaXNpdG9yLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFZpc2l0b3IsXG4gIG11dGF0aW5nOiBmYWxzZSxcblxuICAvLyBWaXNpdHMgYSBnaXZlbiB2YWx1ZS4gSWYgbXV0YXRpbmcsIHdpbGwgcmVwbGFjZSB0aGUgdmFsdWUgaWYgbmVjZXNzYXJ5LlxuICBhY2NlcHRLZXk6IGZ1bmN0aW9uKG5vZGUsIG5hbWUpIHtcbiAgICBsZXQgdmFsdWUgPSB0aGlzLmFjY2VwdChub2RlW25hbWVdKTtcbiAgICBpZiAodGhpcy5tdXRhdGluZykge1xuICAgICAgLy8gSGFja3kgc2FuaXR5IGNoZWNrOiBUaGlzIG1heSBoYXZlIGEgZmV3IGZhbHNlIHBvc2l0aXZlcyBmb3IgdHlwZSBmb3IgdGhlIGhlbHBlclxuICAgICAgLy8gbWV0aG9kcyBidXQgd2lsbCBnZW5lcmFsbHkgZG8gdGhlIHJpZ2h0IHRoaW5nIHdpdGhvdXQgYSBsb3Qgb2Ygb3ZlcmhlYWQuXG4gICAgICBpZiAodmFsdWUgJiYgIVZpc2l0b3IucHJvdG90eXBlW3ZhbHVlLnR5cGVdKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1VuZXhwZWN0ZWQgbm9kZSB0eXBlIFwiJyArIHZhbHVlLnR5cGUgKyAnXCIgZm91bmQgd2hlbiBhY2NlcHRpbmcgJyArIG5hbWUgKyAnIG9uICcgKyBub2RlLnR5cGUpO1xuICAgICAgfVxuICAgICAgbm9kZVtuYW1lXSA9IHZhbHVlO1xuICAgIH1cbiAgfSxcblxuICAvLyBQZXJmb3JtcyBhbiBhY2NlcHQgb3BlcmF0aW9uIHdpdGggYWRkZWQgc2FuaXR5IGNoZWNrIHRvIGVuc3VyZVxuICAvLyByZXF1aXJlZCBrZXlzIGFyZSBub3QgcmVtb3ZlZC5cbiAgYWNjZXB0UmVxdWlyZWQ6IGZ1bmN0aW9uKG5vZGUsIG5hbWUpIHtcbiAgICB0aGlzLmFjY2VwdEtleShub2RlLCBuYW1lKTtcblxuICAgIGlmICghbm9kZVtuYW1lXSkge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbihub2RlLnR5cGUgKyAnIHJlcXVpcmVzICcgKyBuYW1lKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gVHJhdmVyc2VzIGEgZ2l2ZW4gYXJyYXkuIElmIG11dGF0aW5nLCBlbXB0eSByZXNwbnNlcyB3aWxsIGJlIHJlbW92ZWRcbiAgLy8gZm9yIGNoaWxkIGVsZW1lbnRzLlxuICBhY2NlcHRBcnJheTogZnVuY3Rpb24oYXJyYXkpIHtcbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IGFycmF5Lmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgdGhpcy5hY2NlcHRLZXkoYXJyYXksIGkpO1xuXG4gICAgICBpZiAoIWFycmF5W2ldKSB7XG4gICAgICAgIGFycmF5LnNwbGljZShpLCAxKTtcbiAgICAgICAgaS0tO1xuICAgICAgICBsLS07XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIGFjY2VwdDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgaWYgKCFvYmplY3QpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogU2FuaXR5IGNvZGUgKi9cbiAgICBpZiAoIXRoaXNbb2JqZWN0LnR5cGVdKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdVbmtub3duIHR5cGU6ICcgKyBvYmplY3QudHlwZSwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jdXJyZW50KSB7XG4gICAgICB0aGlzLnBhcmVudHMudW5zaGlmdCh0aGlzLmN1cnJlbnQpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnQgPSBvYmplY3Q7XG5cbiAgICBsZXQgcmV0ID0gdGhpc1tvYmplY3QudHlwZV0ob2JqZWN0KTtcblxuICAgIHRoaXMuY3VycmVudCA9IHRoaXMucGFyZW50cy5zaGlmdCgpO1xuXG4gICAgaWYgKCF0aGlzLm11dGF0aW5nIHx8IHJldCkge1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9IGVsc2UgaWYgKHJldCAhPT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuICB9LFxuXG4gIFByb2dyYW06IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgICB0aGlzLmFjY2VwdEFycmF5KHByb2dyYW0uYm9keSk7XG4gIH0sXG5cbiAgTXVzdGFjaGVTdGF0ZW1lbnQ6IHZpc2l0U3ViRXhwcmVzc2lvbixcbiAgRGVjb3JhdG9yOiB2aXNpdFN1YkV4cHJlc3Npb24sXG5cbiAgQmxvY2tTdGF0ZW1lbnQ6IHZpc2l0QmxvY2ssXG4gIERlY29yYXRvckJsb2NrOiB2aXNpdEJsb2NrLFxuXG4gIFBhcnRpYWxTdGF0ZW1lbnQ6IHZpc2l0UGFydGlhbCxcbiAgUGFydGlhbEJsb2NrU3RhdGVtZW50OiBmdW5jdGlvbihwYXJ0aWFsKSB7XG4gICAgdmlzaXRQYXJ0aWFsLmNhbGwodGhpcywgcGFydGlhbCk7XG5cbiAgICB0aGlzLmFjY2VwdEtleShwYXJ0aWFsLCAncHJvZ3JhbScpO1xuICB9LFxuXG4gIENvbnRlbnRTdGF0ZW1lbnQ6IGZ1bmN0aW9uKC8qIGNvbnRlbnQgKi8pIHt9LFxuICBDb21tZW50U3RhdGVtZW50OiBmdW5jdGlvbigvKiBjb21tZW50ICovKSB7fSxcblxuICBTdWJFeHByZXNzaW9uOiB2aXNpdFN1YkV4cHJlc3Npb24sXG5cbiAgUGF0aEV4cHJlc3Npb246IGZ1bmN0aW9uKC8qIHBhdGggKi8pIHt9LFxuXG4gIFN0cmluZ0xpdGVyYWw6IGZ1bmN0aW9uKC8qIHN0cmluZyAqLykge30sXG4gIE51bWJlckxpdGVyYWw6IGZ1bmN0aW9uKC8qIG51bWJlciAqLykge30sXG4gIEJvb2xlYW5MaXRlcmFsOiBmdW5jdGlvbigvKiBib29sICovKSB7fSxcbiAgVW5kZWZpbmVkTGl0ZXJhbDogZnVuY3Rpb24oLyogbGl0ZXJhbCAqLykge30sXG4gIE51bGxMaXRlcmFsOiBmdW5jdGlvbigvKiBsaXRlcmFsICovKSB7fSxcblxuICBIYXNoOiBmdW5jdGlvbihoYXNoKSB7XG4gICAgdGhpcy5hY2NlcHRBcnJheShoYXNoLnBhaXJzKTtcbiAgfSxcbiAgSGFzaFBhaXI6IGZ1bmN0aW9uKHBhaXIpIHtcbiAgICB0aGlzLmFjY2VwdFJlcXVpcmVkKHBhaXIsICd2YWx1ZScpO1xuICB9XG59O1xuXG5mdW5jdGlvbiB2aXNpdFN1YkV4cHJlc3Npb24obXVzdGFjaGUpIHtcbiAgdGhpcy5hY2NlcHRSZXF1aXJlZChtdXN0YWNoZSwgJ3BhdGgnKTtcbiAgdGhpcy5hY2NlcHRBcnJheShtdXN0YWNoZS5wYXJhbXMpO1xuICB0aGlzLmFjY2VwdEtleShtdXN0YWNoZSwgJ2hhc2gnKTtcbn1cbmZ1bmN0aW9uIHZpc2l0QmxvY2soYmxvY2spIHtcbiAgdmlzaXRTdWJFeHByZXNzaW9uLmNhbGwodGhpcywgYmxvY2spO1xuXG4gIHRoaXMuYWNjZXB0S2V5KGJsb2NrLCAncHJvZ3JhbScpO1xuICB0aGlzLmFjY2VwdEtleShibG9jaywgJ2ludmVyc2UnKTtcbn1cbmZ1bmN0aW9uIHZpc2l0UGFydGlhbChwYXJ0aWFsKSB7XG4gIHRoaXMuYWNjZXB0UmVxdWlyZWQocGFydGlhbCwgJ25hbWUnKTtcbiAgdGhpcy5hY2NlcHRBcnJheShwYXJ0aWFsLnBhcmFtcyk7XG4gIHRoaXMuYWNjZXB0S2V5KHBhcnRpYWwsICdoYXNoJyk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IFZpc2l0b3I7XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/whitespace-control.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/whitespace-control.js new file mode 100644 index 0000000..e453b53 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/compiler/whitespace-control.js @@ -0,0 +1,221 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _visitor = require('./visitor'); + +var _visitor2 = _interopRequireDefault(_visitor); + +function WhitespaceControl() { + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + this.options = options; +} +WhitespaceControl.prototype = new _visitor2['default'](); + +WhitespaceControl.prototype.Program = function (program) { + var doStandalone = !this.options.ignoreStandalone; + + var isRoot = !this.isRootSeen; + this.isRootSeen = true; + + var body = program.body; + for (var i = 0, l = body.length; i < l; i++) { + var current = body[i], + strip = this.accept(current); + + if (!strip) { + continue; + } + + var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), + _isNextWhitespace = isNextWhitespace(body, i, isRoot), + openStandalone = strip.openStandalone && _isPrevWhitespace, + closeStandalone = strip.closeStandalone && _isNextWhitespace, + inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; + + if (strip.close) { + omitRight(body, i, true); + } + if (strip.open) { + omitLeft(body, i, true); + } + + if (doStandalone && inlineStandalone) { + omitRight(body, i); + + if (omitLeft(body, i)) { + // If we are on a standalone node, save the indent info for partials + if (current.type === 'PartialStatement') { + // Pull out the whitespace from the final line + current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1]; + } + } + } + if (doStandalone && openStandalone) { + omitRight((current.program || current.inverse).body); + + // Strip out the previous content node if it's whitespace only + omitLeft(body, i); + } + if (doStandalone && closeStandalone) { + // Always strip the next node + omitRight(body, i); + + omitLeft((current.inverse || current.program).body); + } + } + + return program; +}; + +WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) { + this.accept(block.program); + this.accept(block.inverse); + + // Find the inverse program that is involed with whitespace stripping. + var program = block.program || block.inverse, + inverse = block.program && block.inverse, + firstInverse = inverse, + lastInverse = inverse; + + if (inverse && inverse.chained) { + firstInverse = inverse.body[0].program; + + // Walk the inverse chain to find the last inverse that is actually in the chain. + while (lastInverse.chained) { + lastInverse = lastInverse.body[lastInverse.body.length - 1].program; + } + } + + var strip = { + open: block.openStrip.open, + close: block.closeStrip.close, + + // Determine the standalone candiacy. Basically flag our content as being possibly standalone + // so our parent can determine if we actually are standalone + openStandalone: isNextWhitespace(program.body), + closeStandalone: isPrevWhitespace((firstInverse || program).body) + }; + + if (block.openStrip.close) { + omitRight(program.body, null, true); + } + + if (inverse) { + var inverseStrip = block.inverseStrip; + + if (inverseStrip.open) { + omitLeft(program.body, null, true); + } + + if (inverseStrip.close) { + omitRight(firstInverse.body, null, true); + } + if (block.closeStrip.open) { + omitLeft(lastInverse.body, null, true); + } + + // Find standalone else statments + if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) { + omitLeft(program.body); + omitRight(firstInverse.body); + } + } else if (block.closeStrip.open) { + omitLeft(program.body, null, true); + } + + return strip; +}; + +WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) { + return mustache.strip; +}; + +WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) { + /* istanbul ignore next */ + var strip = node.strip || {}; + return { + inlineStandalone: true, + open: strip.open, + close: strip.close + }; +}; + +function isPrevWhitespace(body, i, isRoot) { + if (i === undefined) { + i = body.length; + } + + // Nodes that end with newlines are considered whitespace (but are special + // cased for strip operations) + var prev = body[i - 1], + sibling = body[i - 2]; + if (!prev) { + return isRoot; + } + + if (prev.type === 'ContentStatement') { + return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original); + } +} +function isNextWhitespace(body, i, isRoot) { + if (i === undefined) { + i = -1; + } + + var next = body[i + 1], + sibling = body[i + 2]; + if (!next) { + return isRoot; + } + + if (next.type === 'ContentStatement') { + return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original); + } +} + +// Marks the node to the right of the position as omitted. +// I.e. {{foo}}' ' will mark the ' ' node as omitted. +// +// If i is undefined, then the first child will be marked as such. +// +// If mulitple is truthy then all whitespace will be stripped out until non-whitespace +// content is met. +function omitRight(body, i, multiple) { + var current = body[i == null ? 0 : i + 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) { + return; + } + + var original = current.value; + current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, ''); + current.rightStripped = current.value !== original; +} + +// Marks the node to the left of the position as omitted. +// I.e. ' '{{foo}} will mark the ' ' node as omitted. +// +// If i is undefined then the last child will be marked as such. +// +// If mulitple is truthy then all whitespace will be stripped out until non-whitespace +// content is met. +function omitLeft(body, i, multiple) { + var current = body[i == null ? body.length - 1 : i - 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) { + return; + } + + // We omit the last node if it's whitespace only and not preceeded by a non-content node. + var original = current.value; + current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, ''); + current.leftStripped = current.value !== original; + return current.leftStripped; +} + +exports['default'] = WhitespaceControl; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3doaXRlc3BhY2UtY29udHJvbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7O3VCQUFvQixXQUFXOzs7O0FBRS9CLFNBQVMsaUJBQWlCLEdBQWU7TUFBZCxPQUFPLHlEQUFHLEVBQUU7O0FBQ3JDLE1BQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0NBQ3hCO0FBQ0QsaUJBQWlCLENBQUMsU0FBUyxHQUFHLDBCQUFhLENBQUM7O0FBRTVDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxPQUFPLEdBQUcsVUFBUyxPQUFPLEVBQUU7QUFDdEQsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDOztBQUVwRCxNQUFJLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7QUFDOUIsTUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7O0FBRXZCLE1BQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUFDeEIsT0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUMzQyxRQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2pCLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDOztBQUVqQyxRQUFJLENBQUMsS0FBSyxFQUFFO0FBQ1YsZUFBUztLQUNWOztBQUVELFFBQUksaUJBQWlCLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDckQsaUJBQWlCLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUM7UUFFckQsY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLElBQUksaUJBQWlCO1FBQzFE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QUFDeEQsTUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLGtCQUFrQixJQUFLLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxZQUFZLEFBQUMsRUFBRTtBQUMxRixXQUFPO0dBQ1I7OztBQUdELE1BQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7QUFDN0IsU0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEdBQUksTUFBTSxHQUFLLFNBQVMsQUFBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQzdFLFNBQU8sQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUM7QUFDbEQsU0FBTyxPQUFPLENBQUMsWUFBWSxDQUFDO0NBQzdCOztxQkFFYyxpQkFBaUIiLCJmaWxlIjoid2hpdGVzcGFjZS1jb250cm9sLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFZpc2l0b3IgZnJvbSAnLi92aXNpdG9yJztcblxuZnVuY3Rpb24gV2hpdGVzcGFjZUNvbnRyb2wob3B0aW9ucyA9IHt9KSB7XG4gIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG59XG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUgPSBuZXcgVmlzaXRvcigpO1xuXG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuUHJvZ3JhbSA9IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgY29uc3QgZG9TdGFuZGFsb25lID0gIXRoaXMub3B0aW9ucy5pZ25vcmVTdGFuZGFsb25lO1xuXG4gIGxldCBpc1Jvb3QgPSAhdGhpcy5pc1Jvb3RTZWVuO1xuICB0aGlzLmlzUm9vdFNlZW4gPSB0cnVlO1xuXG4gIGxldCBib2R5ID0gcHJvZ3JhbS5ib2R5O1xuICBmb3IgKGxldCBpID0gMCwgbCA9IGJvZHkubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnQgPSBib2R5W2ldLFxuICAgICAgICBzdHJpcCA9IHRoaXMuYWNjZXB0KGN1cnJlbnQpO1xuXG4gICAgaWYgKCFzdHJpcCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgbGV0IF9pc1ByZXZXaGl0ZXNwYWNlID0gaXNQcmV2V2hpdGVzcGFjZShib2R5LCBpLCBpc1Jvb3QpLFxuICAgICAgICBfaXNOZXh0V2hpdGVzcGFjZSA9IGlzTmV4dFdoaXRlc3BhY2UoYm9keSwgaSwgaXNSb290KSxcblxuICAgICAgICBvcGVuU3RhbmRhbG9uZSA9IHN0cmlwLm9wZW5TdGFuZGFsb25lICYmIF9pc1ByZXZXaGl0ZXNwYWNlLFxuICAgICAgICBjbG9zZVN0YW5kYWxvbmUgPSBzdHJpcC5jbG9zZVN0YW5kYWxvbmUgJiYgX2lzTmV4dFdoaXRlc3BhY2UsXG4gICAgICAgIGlubGluZVN0YW5kYWxvbmUgPSBzdHJpcC5pbmxpbmVTdGFuZGFsb25lICYmIF9pc1ByZXZXaGl0ZXNwYWNlICYmIF9pc05leHRXaGl0ZXNwYWNlO1xuXG4gICAgaWYgKHN0cmlwLmNsb3NlKSB7XG4gICAgICBvbWl0UmlnaHQoYm9keSwgaSwgdHJ1ZSk7XG4gICAgfVxuICAgIGlmIChzdHJpcC5vcGVuKSB7XG4gICAgICBvbWl0TGVmdChib2R5LCBpLCB0cnVlKTtcbiAgICB9XG5cbiAgICBpZiAoZG9TdGFuZGFsb25lICYmIGlubGluZVN0YW5kYWxvbmUpIHtcbiAgICAgIG9taXRSaWdodChib2R5LCBpKTtcblxuICAgICAgaWYgKG9taXRMZWZ0KGJvZHksIGkpKSB7XG4gICAgICAgIC8vIElmIHdlIGFyZSBvbiBhIHN0YW5kYWxvbmUgbm9kZSwgc2F2ZSB0aGUgaW5kZW50IGluZm8gZm9yIHBhcnRpYWxzXG4gICAgICAgIGlmIChjdXJyZW50LnR5cGUgPT09ICdQYXJ0aWFsU3RhdGVtZW50Jykge1xuICAgICAgICAgIC8vIFB1bGwgb3V0IHRoZSB3aGl0ZXNwYWNlIGZyb20gdGhlIGZpbmFsIGxpbmVcbiAgICAgICAgICBjdXJyZW50LmluZGVudCA9ICgvKFsgXFx0XSskKS8pLmV4ZWMoYm9keVtpIC0gMV0ub3JpZ2luYWwpWzFdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChkb1N0YW5kYWxvbmUgJiYgb3BlblN0YW5kYWxvbmUpIHtcbiAgICAgIG9taXRSaWdodCgoY3VycmVudC5wcm9ncmFtIHx8IGN1cnJlbnQuaW52ZXJzZSkuYm9keSk7XG5cbiAgICAgIC8vIFN0cmlwIG91dCB0aGUgcHJldmlvdXMgY29udGVudCBub2RlIGlmIGl0J3Mgd2hpdGVzcGFjZSBvbmx5XG4gICAgICBvbWl0TGVmdChib2R5LCBpKTtcbiAgICB9XG4gICAgaWYgKGRvU3RhbmRhbG9uZSAmJiBjbG9zZVN0YW5kYWxvbmUpIHtcbiAgICAgIC8vIEFsd2F5cyBzdHJpcCB0aGUgbmV4dCBub2RlXG4gICAgICBvbWl0UmlnaHQoYm9keSwgaSk7XG5cbiAgICAgIG9taXRMZWZ0KChjdXJyZW50LmludmVyc2UgfHwgY3VycmVudC5wcm9ncmFtKS5ib2R5KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcHJvZ3JhbTtcbn07XG5cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5CbG9ja1N0YXRlbWVudCA9XG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuRGVjb3JhdG9yQmxvY2sgPVxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLlBhcnRpYWxCbG9ja1N0YXRlbWVudCA9IGZ1bmN0aW9uKGJsb2NrKSB7XG4gIHRoaXMuYWNjZXB0KGJsb2NrLnByb2dyYW0pO1xuICB0aGlzLmFjY2VwdChibG9jay5pbnZlcnNlKTtcblxuICAvLyBGaW5kIHRoZSBpbnZlcnNlIHByb2dyYW0gdGhhdCBpcyBpbnZvbGVkIHdpdGggd2hpdGVzcGFjZSBzdHJpcHBpbmcuXG4gIGxldCBwcm9ncmFtID0gYmxvY2sucHJvZ3JhbSB8fCBibG9jay5pbnZlcnNlLFxuICAgICAgaW52ZXJzZSA9IGJsb2NrLnByb2dyYW0gJiYgYmxvY2suaW52ZXJzZSxcbiAgICAgIGZpcnN0SW52ZXJzZSA9IGludmVyc2UsXG4gICAgICBsYXN0SW52ZXJzZSA9IGludmVyc2U7XG5cbiAgaWYgKGludmVyc2UgJiYgaW52ZXJzZS5jaGFpbmVkKSB7XG4gICAgZmlyc3RJbnZlcnNlID0gaW52ZXJzZS5ib2R5WzBdLnByb2dyYW07XG5cbiAgICAvLyBXYWxrIHRoZSBpbnZlcnNlIGNoYWluIHRvIGZpbmQgdGhlIGxhc3QgaW52ZXJzZSB0aGF0IGlzIGFjdHVhbGx5IGluIHRoZSBjaGFpbi5cbiAgICB3aGlsZSAobGFzdEludmVyc2UuY2hhaW5lZCkge1xuICAgICAgbGFzdEludmVyc2UgPSBsYXN0SW52ZXJzZS5ib2R5W2xhc3RJbnZlcnNlLmJvZHkubGVuZ3RoIC0gMV0ucHJvZ3JhbTtcbiAgICB9XG4gIH1cblxuICBsZXQgc3RyaXAgPSB7XG4gICAgb3BlbjogYmxvY2sub3BlblN0cmlwLm9wZW4sXG4gICAgY2xvc2U6IGJsb2NrLmNsb3NlU3RyaXAuY2xvc2UsXG5cbiAgICAvLyBEZXRlcm1pbmUgdGhlIHN0YW5kYWxvbmUgY2FuZGlhY3kuIEJhc2ljYWxseSBmbGFnIG91ciBjb250ZW50IGFzIGJlaW5nIHBvc3NpYmx5IHN0YW5kYWxvbmVcbiAgICAvLyBzbyBvdXIgcGFyZW50IGNhbiBkZXRlcm1pbmUgaWYgd2UgYWN0dWFsbHkgYXJlIHN0YW5kYWxvbmVcbiAgICBvcGVuU3RhbmRhbG9uZTogaXNOZXh0V2hpdGVzcGFjZShwcm9ncmFtLmJvZHkpLFxuICAgIGNsb3NlU3RhbmRhbG9uZTogaXNQcmV2V2hpdGVzcGFjZSgoZmlyc3RJbnZlcnNlIHx8IHByb2dyYW0pLmJvZHkpXG4gIH07XG5cbiAgaWYgKGJsb2NrLm9wZW5TdHJpcC5jbG9zZSkge1xuICAgIG9taXRSaWdodChwcm9ncmFtLmJvZHksIG51bGwsIHRydWUpO1xuICB9XG5cbiAgaWYgKGludmVyc2UpIHtcbiAgICBsZXQgaW52ZXJzZVN0cmlwID0gYmxvY2suaW52ZXJzZVN0cmlwO1xuXG4gICAgaWYgKGludmVyc2VTdHJpcC5vcGVuKSB7XG4gICAgICBvbWl0TGVmdChwcm9ncmFtLmJvZHksIG51bGwsIHRydWUpO1xuICAgIH1cblxuICAgIGlmIChpbnZlcnNlU3RyaXAuY2xvc2UpIHtcbiAgICAgIG9taXRSaWdodChmaXJzdEludmVyc2UuYm9keSwgbnVsbCwgdHJ1ZSk7XG4gICAgfVxuICAgIGlmIChibG9jay5jbG9zZVN0cmlwLm9wZW4pIHtcbiAgICAgIG9taXRMZWZ0KGxhc3RJbnZlcnNlLmJvZHksIG51bGwsIHRydWUpO1xuICAgIH1cblxuICAgIC8vIEZpbmQgc3RhbmRhbG9uZSBlbHNlIHN0YXRtZW50c1xuICAgIGlmICghdGhpcy5vcHRpb25zLmlnbm9yZVN0YW5kYWxvbmVcbiAgICAgICAgJiYgaXNQcmV2V2hpdGVzcGFjZShwcm9ncmFtLmJvZHkpXG4gICAgICAgICYmIGlzTmV4dFdoaXRlc3BhY2UoZmlyc3RJbnZlcnNlLmJvZHkpKSB7XG4gICAgICBvbWl0TGVmdChwcm9ncmFtLmJvZHkpO1xuICAgICAgb21pdFJpZ2h0KGZpcnN0SW52ZXJzZS5ib2R5KTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoYmxvY2suY2xvc2VTdHJpcC5vcGVuKSB7XG4gICAgb21pdExlZnQocHJvZ3JhbS5ib2R5LCBudWxsLCB0cnVlKTtcbiAgfVxuXG4gIHJldHVybiBzdHJpcDtcbn07XG5cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5EZWNvcmF0b3IgPVxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLk11c3RhY2hlU3RhdGVtZW50ID0gZnVuY3Rpb24obXVzdGFjaGUpIHtcbiAgcmV0dXJuIG11c3RhY2hlLnN0cmlwO1xufTtcblxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLlBhcnRpYWxTdGF0ZW1lbnQgPVxuICAgIFdoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5Db21tZW50U3RhdGVtZW50ID0gZnVuY3Rpb24obm9kZSkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBsZXQgc3RyaXAgPSBub2RlLnN0cmlwIHx8IHt9O1xuICByZXR1cm4ge1xuICAgIGlubGluZVN0YW5kYWxvbmU6IHRydWUsXG4gICAgb3Blbjogc3RyaXAub3BlbixcbiAgICBjbG9zZTogc3RyaXAuY2xvc2VcbiAgfTtcbn07XG5cblxuZnVuY3Rpb24gaXNQcmV2V2hpdGVzcGFjZShib2R5LCBpLCBpc1Jvb3QpIHtcbiAgaWYgKGkgPT09IHVuZGVmaW5lZCkge1xuICAgIGkgPSBib2R5Lmxlbmd0aDtcbiAgfVxuXG4gIC8vIE5vZGVzIHRoYXQgZW5kIHdpdGggbmV3bGluZXMgYXJlIGNvbnNpZGVyZWQgd2hpdGVzcGFjZSAoYnV0IGFyZSBzcGVjaWFsXG4gIC8vIGNhc2VkIGZvciBzdHJpcCBvcGVyYXRpb25zKVxuICBsZXQgcHJldiA9IGJvZHlbaSAtIDFdLFxuICAgICAgc2libGluZyA9IGJvZHlbaSAtIDJdO1xuICBpZiAoIXByZXYpIHtcbiAgICByZXR1cm4gaXNSb290O1xuICB9XG5cbiAgaWYgKHByZXYudHlwZSA9PT0gJ0NvbnRlbnRTdGF0ZW1lbnQnKSB7XG4gICAgcmV0dXJuIChzaWJsaW5nIHx8ICFpc1Jvb3QgPyAoL1xccj9cXG5cXHMqPyQvKSA6ICgvKF58XFxyP1xcbilcXHMqPyQvKSkudGVzdChwcmV2Lm9yaWdpbmFsKTtcbiAgfVxufVxuZnVuY3Rpb24gaXNOZXh0V2hpdGVzcGFjZShib2R5LCBpLCBpc1Jvb3QpIHtcbiAgaWYgKGkgPT09IHVuZGVmaW5lZCkge1xuICAgIGkgPSAtMTtcbiAgfVxuXG4gIGxldCBuZXh0ID0gYm9keVtpICsgMV0sXG4gICAgICBzaWJsaW5nID0gYm9keVtpICsgMl07XG4gIGlmICghbmV4dCkge1xuICAgIHJldHVybiBpc1Jvb3Q7XG4gIH1cblxuICBpZiAobmV4dC50eXBlID09PSAnQ29udGVudFN0YXRlbWVudCcpIHtcbiAgICByZXR1cm4gKHNpYmxpbmcgfHwgIWlzUm9vdCA/ICgvXlxccyo/XFxyP1xcbi8pIDogKC9eXFxzKj8oXFxyP1xcbnwkKS8pKS50ZXN0KG5leHQub3JpZ2luYWwpO1xuICB9XG59XG5cbi8vIE1hcmtzIHRoZSBub2RlIHRvIHRoZSByaWdodCBvZiB0aGUgcG9zaXRpb24gYXMgb21pdHRlZC5cbi8vIEkuZS4ge3tmb299fScgJyB3aWxsIG1hcmsgdGhlICcgJyBub2RlIGFzIG9taXR0ZWQuXG4vL1xuLy8gSWYgaSBpcyB1bmRlZmluZWQsIHRoZW4gdGhlIGZpcnN0IGNoaWxkIHdpbGwgYmUgbWFya2VkIGFzIHN1Y2guXG4vL1xuLy8gSWYgbXVsaXRwbGUgaXMgdHJ1dGh5IHRoZW4gYWxsIHdoaXRlc3BhY2Ugd2lsbCBiZSBzdHJpcHBlZCBvdXQgdW50aWwgbm9uLXdoaXRlc3BhY2Vcbi8vIGNvbnRlbnQgaXMgbWV0LlxuZnVuY3Rpb24gb21pdFJpZ2h0KGJvZHksIGksIG11bHRpcGxlKSB7XG4gIGxldCBjdXJyZW50ID0gYm9keVtpID09IG51bGwgPyAwIDogaSArIDFdO1xuICBpZiAoIWN1cnJlbnQgfHwgY3VycmVudC50eXBlICE9PSAnQ29udGVudFN0YXRlbWVudCcgfHwgKCFtdWx0aXBsZSAmJiBjdXJyZW50LnJpZ2h0U3RyaXBwZWQpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IG9yaWdpbmFsID0gY3VycmVudC52YWx1ZTtcbiAgY3VycmVudC52YWx1ZSA9IGN1cnJlbnQudmFsdWUucmVwbGFjZShtdWx0aXBsZSA/ICgvXlxccysvKSA6ICgvXlsgXFx0XSpcXHI/XFxuPy8pLCAnJyk7XG4gIGN1cnJlbnQucmlnaHRTdHJpcHBlZCA9IGN1cnJlbnQudmFsdWUgIT09IG9yaWdpbmFsO1xufVxuXG4vLyBNYXJrcyB0aGUgbm9kZSB0byB0aGUgbGVmdCBvZiB0aGUgcG9zaXRpb24gYXMgb21pdHRlZC5cbi8vIEkuZS4gJyAne3tmb299fSB3aWxsIG1hcmsgdGhlICcgJyBub2RlIGFzIG9taXR0ZWQuXG4vL1xuLy8gSWYgaSBpcyB1bmRlZmluZWQgdGhlbiB0aGUgbGFzdCBjaGlsZCB3aWxsIGJlIG1hcmtlZCBhcyBzdWNoLlxuLy9cbi8vIElmIG11bGl0cGxlIGlzIHRydXRoeSB0aGVuIGFsbCB3aGl0ZXNwYWNlIHdpbGwgYmUgc3RyaXBwZWQgb3V0IHVudGlsIG5vbi13aGl0ZXNwYWNlXG4vLyBjb250ZW50IGlzIG1ldC5cbmZ1bmN0aW9uIG9taXRMZWZ0KGJvZHksIGksIG11bHRpcGxlKSB7XG4gIGxldCBjdXJyZW50ID0gYm9keVtpID09IG51bGwgPyBib2R5Lmxlbmd0aCAtIDEgOiBpIC0gMV07XG4gIGlmICghY3VycmVudCB8fCBjdXJyZW50LnR5cGUgIT09ICdDb250ZW50U3RhdGVtZW50JyB8fCAoIW11bHRpcGxlICYmIGN1cnJlbnQubGVmdFN0cmlwcGVkKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFdlIG9taXQgdGhlIGxhc3Qgbm9kZSBpZiBpdCdzIHdoaXRlc3BhY2Ugb25seSBhbmQgbm90IHByZWNlZWRlZCBieSBhIG5vbi1jb250ZW50IG5vZGUuXG4gIGxldCBvcmlnaW5hbCA9IGN1cnJlbnQudmFsdWU7XG4gIGN1cnJlbnQudmFsdWUgPSBjdXJyZW50LnZhbHVlLnJlcGxhY2UobXVsdGlwbGUgPyAoL1xccyskLykgOiAoL1sgXFx0XSskLyksICcnKTtcbiAgY3VycmVudC5sZWZ0U3RyaXBwZWQgPSBjdXJyZW50LnZhbHVlICE9PSBvcmlnaW5hbDtcbiAgcmV0dXJuIGN1cnJlbnQubGVmdFN0cmlwcGVkO1xufVxuXG5leHBvcnQgZGVmYXVsdCBXaGl0ZXNwYWNlQ29udHJvbDtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/decorators.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/decorators.js new file mode 100644 index 0000000..e82e0ef --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/decorators.js @@ -0,0 +1,16 @@ +'use strict'; + +exports.__esModule = true; +exports.registerDefaultDecorators = registerDefaultDecorators; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _decoratorsInline = require('./decorators/inline'); + +var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline); + +function registerDefaultDecorators(instance) { + _decoratorsInline2['default'](instance); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Z0NBQTJCLHFCQUFxQjs7OztBQUV6QyxTQUFTLHlCQUF5QixDQUFDLFFBQVEsRUFBRTtBQUNsRCxnQ0FBZSxRQUFRLENBQUMsQ0FBQztDQUMxQiIsImZpbGUiOiJkZWNvcmF0b3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZ2lzdGVySW5saW5lIGZyb20gJy4vZGVjb3JhdG9ycy9pbmxpbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0RGVjb3JhdG9ycyhpbnN0YW5jZSkge1xuICByZWdpc3RlcklubGluZShpbnN0YW5jZSk7XG59XG5cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/decorators/inline.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/decorators/inline.js new file mode 100644 index 0000000..f2f1c7c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/decorators/inline.js @@ -0,0 +1,29 @@ +'use strict'; + +exports.__esModule = true; + +var _utils = require('../utils'); + +exports['default'] = function (instance) { + instance.registerDecorator('inline', function (fn, props, container, options) { + var ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function (context, options) { + // Create a new partials stack frame prior to exec. + var original = container.partials; + container.partials = _utils.extend({}, original, props.partials); + var ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMvaW5saW5lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7cUJBQXFCLFVBQVU7O3FCQUVoQixVQUFTLFFBQVEsRUFBRTtBQUNoQyxVQUFRLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFVBQVMsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFO0FBQzNFLFFBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNiLFFBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFO0FBQ25CLFdBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLFNBQUcsR0FBRyxVQUFTLE9BQU8sRUFBRSxPQUFPLEVBQUU7O0FBRS9CLFlBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUM7QUFDbEMsaUJBQVMsQ0FBQyxRQUFRLEdBQUcsY0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMxRCxZQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9CLGlCQUFTLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUM5QixlQUFPLEdBQUcsQ0FBQztPQUNaLENBQUM7S0FDSDs7QUFFRCxTQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDOztBQUU3QyxXQUFPLEdBQUcsQ0FBQztHQUNaLENBQUMsQ0FBQztDQUNKIiwiZmlsZSI6ImlubGluZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7ZXh0ZW5kfSBmcm9tICcuLi91dGlscyc7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVyRGVjb3JhdG9yKCdpbmxpbmUnLCBmdW5jdGlvbihmbiwgcHJvcHMsIGNvbnRhaW5lciwgb3B0aW9ucykge1xuICAgIGxldCByZXQgPSBmbjtcbiAgICBpZiAoIXByb3BzLnBhcnRpYWxzKSB7XG4gICAgICBwcm9wcy5wYXJ0aWFscyA9IHt9O1xuICAgICAgcmV0ID0gZnVuY3Rpb24oY29udGV4dCwgb3B0aW9ucykge1xuICAgICAgICAvLyBDcmVhdGUgYSBuZXcgcGFydGlhbHMgc3RhY2sgZnJhbWUgcHJpb3IgdG8gZXhlYy5cbiAgICAgICAgbGV0IG9yaWdpbmFsID0gY29udGFpbmVyLnBhcnRpYWxzO1xuICAgICAgICBjb250YWluZXIucGFydGlhbHMgPSBleHRlbmQoe30sIG9yaWdpbmFsLCBwcm9wcy5wYXJ0aWFscyk7XG4gICAgICAgIGxldCByZXQgPSBmbihjb250ZXh0LCBvcHRpb25zKTtcbiAgICAgICAgY29udGFpbmVyLnBhcnRpYWxzID0gb3JpZ2luYWw7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIHByb3BzLnBhcnRpYWxzW29wdGlvbnMuYXJnc1swXV0gPSBvcHRpb25zLmZuO1xuXG4gICAgcmV0dXJuIHJldDtcbiAgfSk7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/exception.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/exception.js new file mode 100644 index 0000000..076d407 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/exception.js @@ -0,0 +1,51 @@ +'use strict'; + +exports.__esModule = true; + +var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + +function Exception(message, node) { + var loc = node && node.loc, + line = undefined, + column = undefined; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (Object.defineProperty) { + Object.defineProperty(this, 'column', { value: column }); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } +} + +Exception.prototype = new Error(); + +exports['default'] = Exception; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2V4Y2VwdGlvbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQ0EsSUFBTSxVQUFVLEdBQUcsQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQzs7QUFFbkcsU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRTtBQUNoQyxNQUFJLEdBQUcsR0FBRyxJQUFJLElBQUksSUFBSSxDQUFDLEdBQUc7TUFDdEIsSUFBSSxZQUFBO01BQ0osTUFBTSxZQUFBLENBQUM7QUFDWCxNQUFJLEdBQUcsRUFBRTtBQUNQLFFBQUksR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztBQUN0QixVQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7O0FBRTFCLFdBQU8sSUFBSSxLQUFLLEdBQUcsSUFBSSxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUM7R0FDeEM7O0FBRUQsTUFBSSxHQUFHLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQzs7O0FBRzFELE9BQUssSUFBSSxHQUFHLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxVQUFVLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFO0FBQ2hELFFBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7R0FDOUM7OztBQUdELE1BQUksS0FBSyxDQUFDLGlCQUFpQixFQUFFO0FBQzNCLFNBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7R0FDMUM7O0FBRUQsTUFBSTtBQUNGLFFBQUksR0FBRyxFQUFFO0FBQ1AsVUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7Ozs7QUFJdkIsVUFBSSxNQUFNLENBQUMsY0FBYyxFQUFFO0FBQ3pCLGNBQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFDO09BQ3hELE1BQU07QUFDTCxZQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztPQUN0QjtLQUNGO0dBQ0YsQ0FBQyxPQUFPLEdBQUcsRUFBRTs7R0FFYjtDQUNGOztBQUVELFNBQVMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQzs7cUJBRW5CLFNBQVMiLCJmaWxlIjoiZXhjZXB0aW9uLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5jb25zdCBlcnJvclByb3BzID0gWydkZXNjcmlwdGlvbicsICdmaWxlTmFtZScsICdsaW5lTnVtYmVyJywgJ21lc3NhZ2UnLCAnbmFtZScsICdudW1iZXInLCAnc3RhY2snXTtcblxuZnVuY3Rpb24gRXhjZXB0aW9uKG1lc3NhZ2UsIG5vZGUpIHtcbiAgbGV0IGxvYyA9IG5vZGUgJiYgbm9kZS5sb2MsXG4gICAgICBsaW5lLFxuICAgICAgY29sdW1uO1xuICBpZiAobG9jKSB7XG4gICAgbGluZSA9IGxvYy5zdGFydC5saW5lO1xuICAgIGNvbHVtbiA9IGxvYy5zdGFydC5jb2x1bW47XG5cbiAgICBtZXNzYWdlICs9ICcgLSAnICsgbGluZSArICc6JyArIGNvbHVtbjtcbiAgfVxuXG4gIGxldCB0bXAgPSBFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IuY2FsbCh0aGlzLCBtZXNzYWdlKTtcblxuICAvLyBVbmZvcnR1bmF0ZWx5IGVycm9ycyBhcmUgbm90IGVudW1lcmFibGUgaW4gQ2hyb21lIChhdCBsZWFzdCksIHNvIGBmb3IgcHJvcCBpbiB0bXBgIGRvZXNuJ3Qgd29yay5cbiAgZm9yIChsZXQgaWR4ID0gMDsgaWR4IDwgZXJyb3JQcm9wcy5sZW5ndGg7IGlkeCsrKSB7XG4gICAgdGhpc1tlcnJvclByb3BzW2lkeF1dID0gdG1wW2Vycm9yUHJvcHNbaWR4XV07XG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBFeGNlcHRpb24pO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAobG9jKSB7XG4gICAgICB0aGlzLmxpbmVOdW1iZXIgPSBsaW5lO1xuXG4gICAgICAvLyBXb3JrIGFyb3VuZCBpc3N1ZSB1bmRlciBzYWZhcmkgd2hlcmUgd2UgY2FuJ3QgZGlyZWN0bHkgc2V0IHRoZSBjb2x1bW4gdmFsdWVcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnY29sdW1uJywge3ZhbHVlOiBjb2x1bW59KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY29sdW1uID0gY29sdW1uO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAobm9wKSB7XG4gICAgLyogSWdub3JlIGlmIHRoZSBicm93c2VyIGlzIHZlcnkgcGFydGljdWxhciAqL1xuICB9XG59XG5cbkV4Y2VwdGlvbi5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTtcblxuZXhwb3J0IGRlZmF1bHQgRXhjZXB0aW9uO1xuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers.js new file mode 100644 index 0000000..1ab84a4 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers.js @@ -0,0 +1,46 @@ +'use strict'; + +exports.__esModule = true; +exports.registerDefaultHelpers = registerDefaultHelpers; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _helpersBlockHelperMissing = require('./helpers/block-helper-missing'); + +var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing); + +var _helpersEach = require('./helpers/each'); + +var _helpersEach2 = _interopRequireDefault(_helpersEach); + +var _helpersHelperMissing = require('./helpers/helper-missing'); + +var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing); + +var _helpersIf = require('./helpers/if'); + +var _helpersIf2 = _interopRequireDefault(_helpersIf); + +var _helpersLog = require('./helpers/log'); + +var _helpersLog2 = _interopRequireDefault(_helpersLog); + +var _helpersLookup = require('./helpers/lookup'); + +var _helpersLookup2 = _interopRequireDefault(_helpersLookup); + +var _helpersWith = require('./helpers/with'); + +var _helpersWith2 = _interopRequireDefault(_helpersWith); + +function registerDefaultHelpers(instance) { + _helpersBlockHelperMissing2['default'](instance); + _helpersEach2['default'](instance); + _helpersHelperMissing2['default'](instance); + _helpersIf2['default'](instance); + _helpersLog2['default'](instance); + _helpersLookup2['default'](instance); + _helpersWith2['default'](instance); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7eUNBQXVDLGdDQUFnQzs7OzsyQkFDOUMsZ0JBQWdCOzs7O29DQUNQLDBCQUEwQjs7Ozt5QkFDckMsY0FBYzs7OzswQkFDYixlQUFlOzs7OzZCQUNaLGtCQUFrQjs7OzsyQkFDcEIsZ0JBQWdCOzs7O0FBRWxDLFNBQVMsc0JBQXNCLENBQUMsUUFBUSxFQUFFO0FBQy9DLHlDQUEyQixRQUFRLENBQUMsQ0FBQztBQUNyQywyQkFBYSxRQUFRLENBQUMsQ0FBQztBQUN2QixvQ0FBc0IsUUFBUSxDQUFDLENBQUM7QUFDaEMseUJBQVcsUUFBUSxDQUFDLENBQUM7QUFDckIsMEJBQVksUUFBUSxDQUFDLENBQUM7QUFDdEIsNkJBQWUsUUFBUSxDQUFDLENBQUM7QUFDekIsMkJBQWEsUUFBUSxDQUFDLENBQUM7Q0FDeEIiLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCByZWdpc3RlckJsb2NrSGVscGVyTWlzc2luZyBmcm9tICcuL2hlbHBlcnMvYmxvY2staGVscGVyLW1pc3NpbmcnO1xuaW1wb3J0IHJlZ2lzdGVyRWFjaCBmcm9tICcuL2hlbHBlcnMvZWFjaCc7XG5pbXBvcnQgcmVnaXN0ZXJIZWxwZXJNaXNzaW5nIGZyb20gJy4vaGVscGVycy9oZWxwZXItbWlzc2luZyc7XG5pbXBvcnQgcmVnaXN0ZXJJZiBmcm9tICcuL2hlbHBlcnMvaWYnO1xuaW1wb3J0IHJlZ2lzdGVyTG9nIGZyb20gJy4vaGVscGVycy9sb2cnO1xuaW1wb3J0IHJlZ2lzdGVyTG9va3VwIGZyb20gJy4vaGVscGVycy9sb29rdXAnO1xuaW1wb3J0IHJlZ2lzdGVyV2l0aCBmcm9tICcuL2hlbHBlcnMvd2l0aCc7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckRlZmF1bHRIZWxwZXJzKGluc3RhbmNlKSB7XG4gIHJlZ2lzdGVyQmxvY2tIZWxwZXJNaXNzaW5nKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJFYWNoKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJIZWxwZXJNaXNzaW5nKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJJZihpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyTG9nKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJMb29rdXAoaW5zdGFuY2UpO1xuICByZWdpc3RlcldpdGgoaW5zdGFuY2UpO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/block-helper-missing.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/block-helper-missing.js new file mode 100644 index 0000000..f82d2ac --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/block-helper-missing.js @@ -0,0 +1,39 @@ +'use strict'; + +exports.__esModule = true; + +var _utils = require('../utils'); + +exports['default'] = function (instance) { + instance.registerHelper('blockHelperMissing', function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvYmxvY2staGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztxQkFBc0QsVUFBVTs7cUJBRWpELFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFVBQVEsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3ZFLFFBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPO1FBQ3pCLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDOztBQUVwQixRQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUU7QUFDcEIsYUFBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDakIsTUFBTSxJQUFJLE9BQU8sS0FBSyxLQUFLLElBQUksT0FBTyxJQUFJLElBQUksRUFBRTtBQUMvQyxhQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUN0QixNQUFNLElBQUksZUFBUSxPQUFPLENBQUMsRUFBRTtBQUMzQixVQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0FBQ3RCLFlBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUNmLGlCQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzlCOztBQUVELGVBQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO09BQ2hELE1BQU07QUFDTCxlQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUN0QjtLQUNGLE1BQU07QUFDTCxVQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUMvQixZQUFJLElBQUksR0FBRyxtQkFBWSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDckMsWUFBSSxDQUFDLFdBQVcsR0FBRyx5QkFBa0IsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzdFLGVBQU8sR0FBRyxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQztPQUN4Qjs7QUFFRCxhQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDN0I7R0FDRixDQUFDLENBQUM7Q0FDSiIsImZpbGUiOiJibG9jay1oZWxwZXItbWlzc2luZy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXBwZW5kQ29udGV4dFBhdGgsIGNyZWF0ZUZyYW1lLCBpc0FycmF5fSBmcm9tICcuLi91dGlscyc7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdibG9ja0hlbHBlck1pc3NpbmcnLCBmdW5jdGlvbihjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgbGV0IGludmVyc2UgPSBvcHRpb25zLmludmVyc2UsXG4gICAgICAgIGZuID0gb3B0aW9ucy5mbjtcblxuICAgIGlmIChjb250ZXh0ID09PSB0cnVlKSB7XG4gICAgICByZXR1cm4gZm4odGhpcyk7XG4gICAgfSBlbHNlIGlmIChjb250ZXh0ID09PSBmYWxzZSB8fCBjb250ZXh0ID09IG51bGwpIHtcbiAgICAgIHJldHVybiBpbnZlcnNlKHRoaXMpO1xuICAgIH0gZWxzZSBpZiAoaXNBcnJheShjb250ZXh0KSkge1xuICAgICAgaWYgKGNvbnRleHQubGVuZ3RoID4gMCkge1xuICAgICAgICBpZiAob3B0aW9ucy5pZHMpIHtcbiAgICAgICAgICBvcHRpb25zLmlkcyA9IFtvcHRpb25zLm5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGluc3RhbmNlLmhlbHBlcnMuZWFjaChjb250ZXh0LCBvcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpbnZlcnNlKHRoaXMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICAgIGxldCBkYXRhID0gY3JlYXRlRnJhbWUob3B0aW9ucy5kYXRhKTtcbiAgICAgICAgZGF0YS5jb250ZXh0UGF0aCA9IGFwcGVuZENvbnRleHRQYXRoKG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aCwgb3B0aW9ucy5uYW1lKTtcbiAgICAgICAgb3B0aW9ucyA9IHtkYXRhOiBkYXRhfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZuKGNvbnRleHQsIG9wdGlvbnMpO1xuICAgIH1cbiAgfSk7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/each.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/each.js new file mode 100644 index 0000000..003274b --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/each.js @@ -0,0 +1,94 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _utils = require('../utils'); + +var _exception = require('../exception'); + +var _exception2 = _interopRequireDefault(_exception); + +exports['default'] = function (instance) { + instance.registerHelper('each', function (context, options) { + if (!options) { + throw new _exception2['default']('Must pass iterator to #each'); + } + + var fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data = undefined, + contextPath = undefined; + + if (options.data && options.ids) { + contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (_utils.isFunction(context)) { + context = context.call(this); + } + + if (options.data) { + data = _utils.createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (_utils.isArray(context)) { + for (var j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + var priorKey = undefined; + + for (var key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvZWFjaC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7O3FCQUErRSxVQUFVOzt5QkFDbkUsY0FBYzs7OztxQkFFckIsVUFBUyxRQUFRLEVBQUU7QUFDaEMsVUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFFBQUksQ0FBQyxPQUFPLEVBQUU7QUFDWixZQUFNLDJCQUFjLDZCQUE2QixDQUFDLENBQUM7S0FDcEQ7O0FBRUQsUUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUU7UUFDZixPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU87UUFDekIsQ0FBQyxHQUFHLENBQUM7UUFDTCxHQUFHLEdBQUcsRUFBRTtRQUNSLElBQUksWUFBQTtRQUNKLFdBQVcsWUFBQSxDQUFDOztBQUVoQixRQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUMvQixpQkFBVyxHQUFHLHlCQUFrQixPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO0tBQ2pGOztBQUVELFFBQUksa0JBQVcsT0FBTyxDQUFDLEVBQUU7QUFBRSxhQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUFFOztBQUUxRCxRQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUU7QUFDaEIsVUFBSSxHQUFHLG1CQUFZLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUNsQzs7QUFFRCxhQUFTLGFBQWEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRTtBQUN6QyxVQUFJLElBQUksRUFBRTtBQUNSLFlBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDO0FBQ2pCLFlBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0FBQ25CLFlBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxLQUFLLENBQUMsQ0FBQztBQUN6QixZQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7O0FBRW5CLFlBQUksV0FBVyxFQUFFO0FBQ2YsY0FBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLEdBQUcsS0FBSyxDQUFDO1NBQ3hDO09BQ0Y7O0FBRUQsU0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO0FBQzdCLFlBQUksRUFBRSxJQUFJO0FBQ1YsbUJBQVcsRUFBRSxtQkFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFdBQVcsR0FBRyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7T0FDL0UsQ0FBQyxDQUFDO0tBQ0o7O0FBRUQsUUFBSSxPQUFPLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO0FBQzFDLFVBQUksZUFBUSxPQUFPLENBQUMsRUFBRTtBQUNwQixhQUFLLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUN2QyxjQUFJLENBQUMsSUFBSSxPQUFPLEVBQUU7QUFDaEIseUJBQWEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1dBQy9DO1NBQ0Y7T0FDRixNQUFNO0FBQ0wsWUFBSSxRQUFRLFlBQUEsQ0FBQzs7QUFFYixhQUFLLElBQUksR0FBRyxJQUFJLE9BQU8sRUFBRTtBQUN2QixjQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUU7Ozs7QUFJL0IsZ0JBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQiwyQkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7YUFDaEM7QUFDRCxvQkFBUSxHQUFHLEdBQUcsQ0FBQztBQUNmLGFBQUMsRUFBRSxDQUFDO1dBQ0w7U0FDRjtBQUNELFlBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQix1QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3RDO09BQ0Y7S0FDRjs7QUFFRCxRQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7QUFDWCxTQUFHLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ3JCOztBQUVELFdBQU8sR0FBRyxDQUFDO0dBQ1osQ0FBQyxDQUFDO0NBQ0oiLCJmaWxlIjoiZWFjaC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXBwZW5kQ29udGV4dFBhdGgsIGJsb2NrUGFyYW1zLCBjcmVhdGVGcmFtZSwgaXNBcnJheSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuLi9leGNlcHRpb24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignZWFjaCcsIGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ011c3QgcGFzcyBpdGVyYXRvciB0byAjZWFjaCcpO1xuICAgIH1cblxuICAgIGxldCBmbiA9IG9wdGlvbnMuZm4sXG4gICAgICAgIGludmVyc2UgPSBvcHRpb25zLmludmVyc2UsXG4gICAgICAgIGkgPSAwLFxuICAgICAgICByZXQgPSAnJyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29udGV4dFBhdGg7XG5cbiAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICBjb250ZXh0UGF0aCA9IGFwcGVuZENvbnRleHRQYXRoKG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aCwgb3B0aW9ucy5pZHNbMF0pICsgJy4nO1xuICAgIH1cblxuICAgIGlmIChpc0Z1bmN0aW9uKGNvbnRleHQpKSB7IGNvbnRleHQgPSBjb250ZXh0LmNhbGwodGhpcyk7IH1cblxuICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4ZWNJdGVyYXRpb24oZmllbGQsIGluZGV4LCBsYXN0KSB7XG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICBkYXRhLmtleSA9IGZpZWxkO1xuICAgICAgICBkYXRhLmluZGV4ID0gaW5kZXg7XG4gICAgICAgIGRhdGEuZmlyc3QgPSBpbmRleCA9PT0gMDtcbiAgICAgICAgZGF0YS5sYXN0ID0gISFsYXN0O1xuXG4gICAgICAgIGlmIChjb250ZXh0UGF0aCkge1xuICAgICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBjb250ZXh0UGF0aCArIGZpZWxkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldCA9IHJldCArIGZuKGNvbnRleHRbZmllbGRdLCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dFtmaWVsZF0sIGZpZWxkXSwgW2NvbnRleHRQYXRoICsgZmllbGQsIG51bGxdKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoaXNBcnJheShjb250ZXh0KSkge1xuICAgICAgICBmb3IgKGxldCBqID0gY29udGV4dC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcbiAgICAgICAgICBpZiAoaSBpbiBjb250ZXh0KSB7XG4gICAgICAgICAgICBleGVjSXRlcmF0aW9uKGksIGksIGkgPT09IGNvbnRleHQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcHJpb3JLZXk7XG5cbiAgICAgICAgZm9yIChsZXQga2V5IGluIGNvbnRleHQpIHtcbiAgICAgICAgICBpZiAoY29udGV4dC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBydW5uaW5nIHRoZSBpdGVyYXRpb25zIG9uZSBzdGVwIG91dCBvZiBzeW5jIHNvIHdlIGNhbiBkZXRlY3RcbiAgICAgICAgICAgIC8vIHRoZSBsYXN0IGl0ZXJhdGlvbiB3aXRob3V0IGhhdmUgdG8gc2NhbiB0aGUgb2JqZWN0IHR3aWNlIGFuZCBjcmVhdGVcbiAgICAgICAgICAgIC8vIGFuIGl0ZXJtZWRpYXRlIGtleXMgYXJyYXkuXG4gICAgICAgICAgICBpZiAocHJpb3JLZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmlvcktleSA9IGtleTtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByaW9yS2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgcmV0ID0gaW52ZXJzZSh0aGlzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/helper-missing.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/helper-missing.js new file mode 100644 index 0000000..1ff367a --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/helper-missing.js @@ -0,0 +1,25 @@ +'use strict'; + +exports.__esModule = true; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _exception = require('../exception'); + +var _exception2 = _interopRequireDefault(_exception); + +exports['default'] = function (instance) { + instance.registerHelper('helperMissing', function () /* [args, ]options */{ + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozt5QkFBc0IsY0FBYzs7OztxQkFFckIsVUFBUyxRQUFRLEVBQUU7QUFDaEMsVUFBUSxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUUsaUNBQWdDO0FBQ3ZFLFFBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7O0FBRTFCLGFBQU8sU0FBUyxDQUFDO0tBQ2xCLE1BQU07O0FBRUwsWUFBTSwyQkFBYyxtQkFBbUIsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7S0FDdkY7R0FDRixDQUFDLENBQUM7Q0FDSiIsImZpbGUiOiJoZWxwZXItbWlzc2luZy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi4vZXhjZXB0aW9uJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oaW5zdGFuY2UpIHtcbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ2hlbHBlck1pc3NpbmcnLCBmdW5jdGlvbigvKiBbYXJncywgXW9wdGlvbnMgKi8pIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgLy8gQSBtaXNzaW5nIGZpZWxkIGluIGEge3tmb299fSBjb25zdHJ1Y3QuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTb21lb25lIGlzIGFjdHVhbGx5IHRyeWluZyB0byBjYWxsIHNvbWV0aGluZywgYmxvdyB1cC5cbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ01pc3NpbmcgaGVscGVyOiBcIicgKyBhcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aCAtIDFdLm5hbWUgKyAnXCInKTtcbiAgICB9XG4gIH0pO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/if.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/if.js new file mode 100644 index 0000000..1abfa4b --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/if.js @@ -0,0 +1,29 @@ +'use strict'; + +exports.__esModule = true; + +var _utils = require('../utils'); + +exports['default'] = function (instance) { + instance.registerHelper('if', function (conditional, options) { + if (_utils.isFunction(conditional)) { + conditional = conditional.call(this); + } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function (conditional, options) { + return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaWYuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztxQkFBa0MsVUFBVTs7cUJBRTdCLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFVBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVMsV0FBVyxFQUFFLE9BQU8sRUFBRTtBQUMzRCxRQUFJLGtCQUFXLFdBQVcsQ0FBQyxFQUFFO0FBQUUsaUJBQVcsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQUU7Ozs7O0FBS3RFLFFBQUksQUFBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxJQUFLLGVBQVEsV0FBVyxDQUFDLEVBQUU7QUFDdkUsYUFBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQzlCLE1BQU07QUFDTCxhQUFPLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDekI7R0FDRixDQUFDLENBQUM7O0FBRUgsVUFBUSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsVUFBUyxXQUFXLEVBQUUsT0FBTyxFQUFFO0FBQy9ELFdBQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQztHQUN2SCxDQUFDLENBQUM7Q0FDSiIsImZpbGUiOiJpZi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aXNFbXB0eSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignaWYnLCBmdW5jdGlvbihjb25kaXRpb25hbCwgb3B0aW9ucykge1xuICAgIGlmIChpc0Z1bmN0aW9uKGNvbmRpdGlvbmFsKSkgeyBjb25kaXRpb25hbCA9IGNvbmRpdGlvbmFsLmNhbGwodGhpcyk7IH1cblxuICAgIC8vIERlZmF1bHQgYmVoYXZpb3IgaXMgdG8gcmVuZGVyIHRoZSBwb3NpdGl2ZSBwYXRoIGlmIHRoZSB2YWx1ZSBpcyB0cnV0aHkgYW5kIG5vdCBlbXB0eS5cbiAgICAvLyBUaGUgYGluY2x1ZGVaZXJvYCBvcHRpb24gbWF5IGJlIHNldCB0byB0cmVhdCB0aGUgY29uZHRpb25hbCBhcyBwdXJlbHkgbm90IGVtcHR5IGJhc2VkIG9uIHRoZVxuICAgIC8vIGJlaGF2aW9yIG9mIGlzRW1wdHkuIEVmZmVjdGl2ZWx5IHRoaXMgZGV0ZXJtaW5lcyBpZiAwIGlzIGhhbmRsZWQgYnkgdGhlIHBvc2l0aXZlIHBhdGggb3IgbmVnYXRpdmUuXG4gICAgaWYgKCghb3B0aW9ucy5oYXNoLmluY2x1ZGVaZXJvICYmICFjb25kaXRpb25hbCkgfHwgaXNFbXB0eShjb25kaXRpb25hbCkpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmZuKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3VubGVzcycsIGZ1bmN0aW9uKGNvbmRpdGlvbmFsLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGluc3RhbmNlLmhlbHBlcnNbJ2lmJ10uY2FsbCh0aGlzLCBjb25kaXRpb25hbCwge2ZuOiBvcHRpb25zLmludmVyc2UsIGludmVyc2U6IG9wdGlvbnMuZm4sIGhhc2g6IG9wdGlvbnMuaGFzaH0pO1xuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/log.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/log.js new file mode 100644 index 0000000..042b6fc --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/log.js @@ -0,0 +1,26 @@ +'use strict'; + +exports.__esModule = true; + +exports['default'] = function (instance) { + instance.registerHelper('log', function () /* message, options */{ + var args = [undefined], + options = arguments[arguments.length - 1]; + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + var level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log.apply(instance, args); + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7cUJBQWUsVUFBUyxRQUFRLEVBQUU7QUFDaEMsVUFBUSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsa0NBQWlDO0FBQzlELFFBQUksSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDO1FBQ2xCLE9BQU8sR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztBQUM5QyxTQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDN0MsVUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN6Qjs7QUFFRCxRQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7QUFDZCxRQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksRUFBRTtBQUM5QixXQUFLLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7S0FDNUIsTUFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFO0FBQ3JELFdBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztLQUM1QjtBQUNELFFBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7O0FBRWhCLFlBQVEsQ0FBQyxHQUFHLE1BQUEsQ0FBWixRQUFRLEVBQVMsSUFBSSxDQUFDLENBQUM7R0FDeEIsQ0FBQyxDQUFDO0NBQ0oiLCJmaWxlIjoibG9nLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oaW5zdGFuY2UpIHtcbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ2xvZycsIGZ1bmN0aW9uKC8qIG1lc3NhZ2UsIG9wdGlvbnMgKi8pIHtcbiAgICBsZXQgYXJncyA9IFt1bmRlZmluZWRdLFxuICAgICAgICBvcHRpb25zID0gYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgIGFyZ3MucHVzaChhcmd1bWVudHNbaV0pO1xuICAgIH1cblxuICAgIGxldCBsZXZlbCA9IDE7XG4gICAgaWYgKG9wdGlvbnMuaGFzaC5sZXZlbCAhPSBudWxsKSB7XG4gICAgICBsZXZlbCA9IG9wdGlvbnMuaGFzaC5sZXZlbDtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLmRhdGEubGV2ZWwgIT0gbnVsbCkge1xuICAgICAgbGV2ZWwgPSBvcHRpb25zLmRhdGEubGV2ZWw7XG4gICAgfVxuICAgIGFyZ3NbMF0gPSBsZXZlbDtcblxuICAgIGluc3RhbmNlLmxvZyguLi4gYXJncyk7XG4gIH0pO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/lookup.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/lookup.js new file mode 100644 index 0000000..e5efdce --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/lookup.js @@ -0,0 +1,12 @@ +'use strict'; + +exports.__esModule = true; + +exports['default'] = function (instance) { + instance.registerHelper('lookup', function (obj, field) { + return obj && obj[field]; + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9va3VwLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7cUJBQWUsVUFBUyxRQUFRLEVBQUU7QUFDaEMsVUFBUSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsVUFBUyxHQUFHLEVBQUUsS0FBSyxFQUFFO0FBQ3JELFdBQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUMxQixDQUFDLENBQUM7Q0FDSiIsImZpbGUiOiJsb29rdXAuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignbG9va3VwJywgZnVuY3Rpb24ob2JqLCBmaWVsZCkge1xuICAgIHJldHVybiBvYmogJiYgb2JqW2ZpZWxkXTtcbiAgfSk7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js new file mode 100644 index 0000000..c23cdde --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js @@ -0,0 +1,33 @@ +'use strict'; + +exports.__esModule = true; + +var _utils = require('../utils'); + +exports['default'] = function (instance) { + instance.registerHelper('with', function (context, options) { + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvd2l0aC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O3FCQUErRSxVQUFVOztxQkFFMUUsVUFBUyxRQUFRLEVBQUU7QUFDaEMsVUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFFBQUksa0JBQVcsT0FBTyxDQUFDLEVBQUU7QUFBRSxhQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUFFOztBQUUxRCxRQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDOztBQUVwQixRQUFJLENBQUMsZUFBUSxPQUFPLENBQUMsRUFBRTtBQUNyQixVQUFJLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO0FBQ3hCLFVBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO0FBQy9CLFlBQUksR0FBRyxtQkFBWSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDakMsWUFBSSxDQUFDLFdBQVcsR0FBRyx5QkFBa0IsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO09BQ2hGOztBQUVELGFBQU8sRUFBRSxDQUFDLE9BQU8sRUFBRTtBQUNqQixZQUFJLEVBQUUsSUFBSTtBQUNWLG1CQUFXLEVBQUUsbUJBQVksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7T0FDaEUsQ0FBQyxDQUFDO0tBQ0osTUFBTTtBQUNMLGFBQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUM5QjtHQUNGLENBQUMsQ0FBQztDQUNKIiwiZmlsZSI6IndpdGguanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBibG9ja1BhcmFtcywgY3JlYXRlRnJhbWUsIGlzRW1wdHksIGlzRnVuY3Rpb259IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oaW5zdGFuY2UpIHtcbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3dpdGgnLCBmdW5jdGlvbihjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24oY29udGV4dCkpIHsgY29udGV4dCA9IGNvbnRleHQuY2FsbCh0aGlzKTsgfVxuXG4gICAgbGV0IGZuID0gb3B0aW9ucy5mbjtcblxuICAgIGlmICghaXNFbXB0eShjb250ZXh0KSkge1xuICAgICAgbGV0IGRhdGEgPSBvcHRpb25zLmRhdGE7XG4gICAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgICAgICBkYXRhLmNvbnRleHRQYXRoID0gYXBwZW5kQ29udGV4dFBhdGgob3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoLCBvcHRpb25zLmlkc1swXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dF0sIFtkYXRhICYmIGRhdGEuY29udGV4dFBhdGhdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/logger.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/logger.js new file mode 100644 index 0000000..7678244 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/logger.js @@ -0,0 +1,47 @@ +'use strict'; + +exports.__esModule = true; + +var _utils = require('./utils'); + +var logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function lookupLevel(level) { + if (typeof level === 'string') { + var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function log(level) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + var method = logger.methodMap[level]; + if (!console[method]) { + // eslint-disable-line no-console + method = 'log'; + } + + for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + message[_key - 1] = arguments[_key]; + } + + console[method].apply(console, message); // eslint-disable-line no-console + } + } +}; + +exports['default'] = logger; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2xvZ2dlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O3FCQUFzQixTQUFTOztBQUUvQixJQUFJLE1BQU0sR0FBRztBQUNYLFdBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQztBQUM3QyxPQUFLLEVBQUUsTUFBTTs7O0FBR2IsYUFBVyxFQUFFLHFCQUFTLEtBQUssRUFBRTtBQUMzQixRQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtBQUM3QixVQUFJLFFBQVEsR0FBRyxlQUFRLE1BQU0sQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFDOUQsVUFBSSxRQUFRLElBQUksQ0FBQyxFQUFFO0FBQ2pCLGFBQUssR0FBRyxRQUFRLENBQUM7T0FDbEIsTUFBTTtBQUNMLGFBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO09BQzdCO0tBQ0Y7O0FBRUQsV0FBTyxLQUFLLENBQUM7R0FDZDs7O0FBR0QsS0FBRyxFQUFFLGFBQVMsS0FBSyxFQUFjO0FBQy9CLFNBQUssR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDOztBQUVsQyxRQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVcsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLEVBQUU7QUFDL0UsVUFBSSxNQUFNLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNyQyxVQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFOztBQUNwQixjQUFNLEdBQUcsS0FBSyxDQUFDO09BQ2hCOzt3Q0FQbUIsT0FBTztBQUFQLGVBQU87OztBQVEzQixhQUFPLENBQUMsTUFBTSxPQUFDLENBQWYsT0FBTyxFQUFZLE9BQU8sQ0FBQyxDQUFDO0tBQzdCO0dBQ0Y7Q0FDRixDQUFDOztxQkFFYSxNQUFNIiwiZmlsZSI6ImxvZ2dlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aW5kZXhPZn0gZnJvbSAnLi91dGlscyc7XG5cbmxldCBsb2dnZXIgPSB7XG4gIG1ldGhvZE1hcDogWydkZWJ1ZycsICdpbmZvJywgJ3dhcm4nLCAnZXJyb3InXSxcbiAgbGV2ZWw6ICdpbmZvJyxcblxuICAvLyBNYXBzIGEgZ2l2ZW4gbGV2ZWwgdmFsdWUgdG8gdGhlIGBtZXRob2RNYXBgIGluZGV4ZXMgYWJvdmUuXG4gIGxvb2t1cExldmVsOiBmdW5jdGlvbihsZXZlbCkge1xuICAgIGlmICh0eXBlb2YgbGV2ZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBsZXQgbGV2ZWxNYXAgPSBpbmRleE9mKGxvZ2dlci5tZXRob2RNYXAsIGxldmVsLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgaWYgKGxldmVsTWFwID49IDApIHtcbiAgICAgICAgbGV2ZWwgPSBsZXZlbE1hcDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldmVsID0gcGFyc2VJbnQobGV2ZWwsIDEwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGV2ZWw7XG4gIH0sXG5cbiAgLy8gQ2FuIGJlIG92ZXJyaWRkZW4gaW4gdGhlIGhvc3QgZW52aXJvbm1lbnRcbiAgbG9nOiBmdW5jdGlvbihsZXZlbCwgLi4ubWVzc2FnZSkge1xuICAgIGxldmVsID0gbG9nZ2VyLmxvb2t1cExldmVsKGxldmVsKTtcblxuICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbG9nZ2VyLmxvb2t1cExldmVsKGxvZ2dlci5sZXZlbCkgPD0gbGV2ZWwpIHtcbiAgICAgIGxldCBtZXRob2QgPSBsb2dnZXIubWV0aG9kTWFwW2xldmVsXTtcbiAgICAgIGlmICghY29uc29sZVttZXRob2RdKSB7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG4gICAgICAgIG1ldGhvZCA9ICdsb2cnO1xuICAgICAgfVxuICAgICAgY29uc29sZVttZXRob2RdKC4uLm1lc3NhZ2UpOyAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IGxvZ2dlcjtcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/no-conflict.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/no-conflict.js new file mode 100644 index 0000000..882ff00 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/no-conflict.js @@ -0,0 +1,20 @@ +/* global window */ +'use strict'; + +exports.__esModule = true; + +exports['default'] = function (Handlebars) { + /* istanbul ignore next */ + var root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function () { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; +}; + +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL25vLWNvbmZsaWN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O3FCQUNlLFVBQVMsVUFBVSxFQUFFOztBQUVsQyxNQUFJLElBQUksR0FBRyxPQUFPLE1BQU0sS0FBSyxXQUFXLEdBQUcsTUFBTSxHQUFHLE1BQU07TUFDdEQsV0FBVyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7O0FBRWxDLFlBQVUsQ0FBQyxVQUFVLEdBQUcsWUFBVztBQUNqQyxRQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFO0FBQ2xDLFVBQUksQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFDO0tBQy9CO0FBQ0QsV0FBTyxVQUFVLENBQUM7R0FDbkIsQ0FBQztDQUNIIiwiZmlsZSI6Im5vLWNvbmZsaWN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZ2xvYmFsIHdpbmRvdyAqL1xuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oSGFuZGxlYmFycykge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBsZXQgcm9vdCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogd2luZG93LFxuICAgICAgJEhhbmRsZWJhcnMgPSByb290LkhhbmRsZWJhcnM7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIEhhbmRsZWJhcnMubm9Db25mbGljdCA9IGZ1bmN0aW9uKCkge1xuICAgIGlmIChyb290LkhhbmRsZWJhcnMgPT09IEhhbmRsZWJhcnMpIHtcbiAgICAgIHJvb3QuSGFuZGxlYmFycyA9ICRIYW5kbGViYXJzO1xuICAgIH1cbiAgICByZXR1cm4gSGFuZGxlYmFycztcbiAgfTtcbn1cbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/runtime.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/runtime.js new file mode 100644 index 0000000..e265380 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/runtime.js @@ -0,0 +1,297 @@ +'use strict'; + +exports.__esModule = true; +exports.checkRevision = checkRevision; +exports.template = template; +exports.wrapProgram = wrapProgram; +exports.resolvePartial = resolvePartial; +exports.invokePartial = invokePartial; +exports.noop = noop; +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +// istanbul ignore next + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } + +var _utils = require('./utils'); + +var Utils = _interopRequireWildcard(_utils); + +var _exception = require('./exception'); + +var _exception2 = _interopRequireDefault(_exception); + +var _base = require('./base'); + +function checkRevision(compilerInfo) { + var compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = _base.COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = _base.REVISION_CHANGES[currentRevision], + compilerVersions = _base.REVISION_CHANGES[compilerRevision]; + throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } +} + +function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new _exception2['default']('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new _exception2['default']('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = Utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + var result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + var lines = result.split('\n'); + for (var i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + var container = { + strict: function strict(obj, name) { + if (!(name in obj)) { + throw new _exception2['default']('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function lookup(depths, name) { + var len = depths.length; + for (var i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function lambda(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: Utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function fn(i) { + var ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function program(i, data, declaredBlockParams, blockParams, depths) { + var programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function data(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function merge(param, common) { + var obj = param || common; + + if (param && common && param !== common) { + obj = Utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function (options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function (i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new _exception2['default']('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new _exception2['default']('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; +} + +function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; +} + +function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + var data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; +} + +function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + var partialBlock = undefined; + if (options.fn && options.fn !== noop) { + options.data = _base.createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = Utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new _exception2['default']('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } +} + +function noop() { + return ''; +} + +function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? _base.createFrame(data) : {}; + data.root = context; + } + return data; +} + +function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + var props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + Utils.extend(prog, props); + } + return prog; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3J1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7cUJBQXVCLFNBQVM7O0lBQXBCLEtBQUs7O3lCQUNLLGFBQWE7Ozs7b0JBQzhCLFFBQVE7O0FBRWxFLFNBQVMsYUFBYSxDQUFDLFlBQVksRUFBRTtBQUMxQyxNQUFNLGdCQUFnQixHQUFHLFlBQVksSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztNQUN2RCxlQUFlLDBCQUFvQixDQUFDOztBQUUxQyxNQUFJLGdCQUFnQixLQUFLLGVBQWUsRUFBRTtBQUN4QyxRQUFJLGdCQUFnQixHQUFHLGVBQWUsRUFBRTtBQUN0QyxVQUFNLGVBQWUsR0FBRyx1QkFBaUIsZUFBZSxDQUFDO1VBQ25ELGdCQUFnQixHQUFHLHVCQUFpQixnQkFBZ0IsQ0FBQyxDQUFDO0FBQzVELFlBQU0sMkJBQWMseUZBQXlGLEdBQ3ZHLHFEQUFxRCxHQUFHLGVBQWUsR0FBRyxtREFBbUQsR0FBRyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsQ0FBQztLQUNoSyxNQUFNOztBQUVMLFlBQU0sMkJBQWMsd0ZBQXdGLEdBQ3RHLGlEQUFpRCxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztLQUNuRjtHQUNGO0NBQ0Y7O0FBRU0sU0FBUyxRQUFRLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTs7QUFFMUMsTUFBSSxDQUFDLEdBQUcsRUFBRTtBQUNSLFVBQU0sMkJBQWMsbUNBQW1DLENBQUMsQ0FBQztHQUMxRDtBQUNELE1BQUksQ0FBQyxZQUFZLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFO0FBQ3ZDLFVBQU0sMkJBQWMsMkJBQTJCLEdBQUcsT0FBTyxZQUFZLENBQUMsQ0FBQztHQUN4RTs7QUFFRCxjQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDOzs7O0FBSWxELEtBQUcs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QixVQUFNLDJCQUFjLGNBQWMsR0FBRyxPQUFPLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDLENBQUM7R0FDNUUsTUFBTSxJQUFJLE9BQU8sWUFBWSxRQUFRLEVBQUU7QUFDdEMsV0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0dBQ2xDO0NBQ0Y7O0FBRU0sU0FBUyxJQUFJLEdBQUc7QUFBRSxTQUFPLEVBQUUsQ0FBQztDQUFFOztBQUVyQyxTQUFTLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQy9CLE1BQUksQ0FBQyxJQUFJLElBQUksRUFBRSxNQUFNLElBQUksSUFBSSxDQUFBLEFBQUMsRUFBRTtBQUM5QixRQUFJLEdBQUcsSUFBSSxHQUFHLGtCQUFZLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNyQyxRQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztHQUNyQjtBQUNELFNBQU8sSUFBSSxDQUFDO0NBQ2I7O0FBRUQsU0FBUyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRTtBQUN6RSxNQUFJLEVBQUUsQ0FBQyxTQUFTLEVBQUU7QUFDaEIsUUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO0FBQ2YsUUFBSSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQzVGLFNBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0dBQzNCO0FBQ0QsU0FBTyxJQUFJLENBQUM7Q0FDYiIsImZpbGUiOiJydW50aW1lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgVXRpbHMgZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4vZXhjZXB0aW9uJztcbmltcG9ydCB7IENPTVBJTEVSX1JFVklTSU9OLCBSRVZJU0lPTl9DSEFOR0VTLCBjcmVhdGVGcmFtZSB9IGZyb20gJy4vYmFzZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGVja1JldmlzaW9uKGNvbXBpbGVySW5mbykge1xuICBjb25zdCBjb21waWxlclJldmlzaW9uID0gY29tcGlsZXJJbmZvICYmIGNvbXBpbGVySW5mb1swXSB8fCAxLFxuICAgICAgICBjdXJyZW50UmV2aXNpb24gPSBDT01QSUxFUl9SRVZJU0lPTjtcblxuICBpZiAoY29tcGlsZXJSZXZpc2lvbiAhPT0gY3VycmVudFJldmlzaW9uKSB7XG4gICAgaWYgKGNvbXBpbGVyUmV2aXNpb24gPCBjdXJyZW50UmV2aXNpb24pIHtcbiAgICAgIGNvbnN0IHJ1bnRpbWVWZXJzaW9ucyA9IFJFVklTSU9OX0NIQU5HRVNbY3VycmVudFJldmlzaW9uXSxcbiAgICAgICAgICAgIGNvbXBpbGVyVmVyc2lvbnMgPSBSRVZJU0lPTl9DSEFOR0VTW2NvbXBpbGVyUmV2aXNpb25dO1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVGVtcGxhdGUgd2FzIHByZWNvbXBpbGVkIHdpdGggYW4gb2xkZXIgdmVyc2lvbiBvZiBIYW5kbGViYXJzIHRoYW4gdGhlIGN1cnJlbnQgcnVudGltZS4gJyArXG4gICAgICAgICAgICAnUGxlYXNlIHVwZGF0ZSB5b3VyIHByZWNvbXBpbGVyIHRvIGEgbmV3ZXIgdmVyc2lvbiAoJyArIHJ1bnRpbWVWZXJzaW9ucyArICcpIG9yIGRvd25ncmFkZSB5b3VyIHJ1bnRpbWUgdG8gYW4gb2xkZXIgdmVyc2lvbiAoJyArIGNvbXBpbGVyVmVyc2lvbnMgKyAnKS4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVXNlIHRoZSBlbWJlZGRlZCB2ZXJzaW9uIGluZm8gc2luY2UgdGhlIHJ1bnRpbWUgZG9lc24ndCBrbm93IGFib3V0IHRoaXMgcmV2aXNpb24geWV0XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUZW1wbGF0ZSB3YXMgcHJlY29tcGlsZWQgd2l0aCBhIG5ld2VyIHZlcnNpb24gb2YgSGFuZGxlYmFycyB0aGFuIHRoZSBjdXJyZW50IHJ1bnRpbWUuICcgK1xuICAgICAgICAgICAgJ1BsZWFzZSB1cGRhdGUgeW91ciBydW50aW1lIHRvIGEgbmV3ZXIgdmVyc2lvbiAoJyArIGNvbXBpbGVySW5mb1sxXSArICcpLicpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdGVtcGxhdGUodGVtcGxhdGVTcGVjLCBlbnYpIHtcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgaWYgKCFlbnYpIHtcbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdObyBlbnZpcm9ubWVudCBwYXNzZWQgdG8gdGVtcGxhdGUnKTtcbiAgfVxuICBpZiAoIXRlbXBsYXRlU3BlYyB8fCAhdGVtcGxhdGVTcGVjLm1haW4pIHtcbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdVbmtub3duIHRlbXBsYXRlIG9iamVjdDogJyArIHR5cGVvZiB0ZW1wbGF0ZVNwZWMpO1xuICB9XG5cbiAgdGVtcGxhdGVTcGVjLm1haW4uZGVjb3JhdG9yID0gdGVtcGxhdGVTcGVjLm1haW5fZDtcblxuICAvLyBOb3RlOiBVc2luZyBlbnYuVk0gcmVmZXJlbmNlcyByYXRoZXIgdGhhbiBsb2NhbCB2YXIgcmVmZXJlbmNlcyB0aHJvdWdob3V0IHRoaXMgc2VjdGlvbiB0byBhbGxvd1xuICAvLyBmb3IgZXh0ZXJuYWwgdXNlcnMgdG8gb3ZlcnJpZGUgdGhlc2UgYXMgcHN1ZWRvLXN1cHBvcnRlZCBBUElzLlxuICBlbnYuVk0uY2hlY2tSZXZpc2lvbih0ZW1wbGF0ZVNwZWMuY29tcGlsZXIpO1xuXG4gIGZ1bmN0aW9uIGludm9rZVBhcnRpYWxXcmFwcGVyKHBhcnRpYWwsIGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy5oYXNoKSB7XG4gICAgICBjb250ZXh0ID0gVXRpbHMuZXh0ZW5kKHt9LCBjb250ZXh0LCBvcHRpb25zLmhhc2gpO1xuICAgICAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgICAgIG9wdGlvbnMuaWRzWzBdID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwYXJ0aWFsID0gZW52LlZNLnJlc29sdmVQYXJ0aWFsLmNhbGwodGhpcywgcGFydGlhbCwgY29udGV4dCwgb3B0aW9ucyk7XG4gICAgbGV0IHJlc3VsdCA9IGVudi5WTS5pbnZva2VQYXJ0aWFsLmNhbGwodGhpcywgcGFydGlhbCwgY29udGV4dCwgb3B0aW9ucyk7XG5cbiAgICBpZiAocmVzdWx0ID09IG51bGwgJiYgZW52LmNvbXBpbGUpIHtcbiAgICAgIG9wdGlvbnMucGFydGlhbHNbb3B0aW9ucy5uYW1lXSA9IGVudi5jb21waWxlKHBhcnRpYWwsIHRlbXBsYXRlU3BlYy5jb21waWxlck9wdGlvbnMsIGVudik7XG4gICAgICByZXN1bHQgPSBvcHRpb25zLnBhcnRpYWxzW29wdGlvbnMubmFtZV0oY29udGV4dCwgb3B0aW9ucyk7XG4gICAgfVxuICAgIGlmIChyZXN1bHQgIT0gbnVsbCkge1xuICAgICAgaWYgKG9wdGlvbnMuaW5kZW50KSB7XG4gICAgICAgIGxldCBsaW5lcyA9IHJlc3VsdC5zcGxpdCgnXFxuJyk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwLCBsID0gbGluZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgaWYgKCFsaW5lc1tpXSAmJiBpICsgMSA9PT0gbCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGluZXNbaV0gPSBvcHRpb25zLmluZGVudCArIGxpbmVzW2ldO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCA9IGxpbmVzLmpvaW4oJ1xcbicpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVGhlIHBhcnRpYWwgJyArIG9wdGlvbnMubmFtZSArICcgY291bGQgbm90IGJlIGNvbXBpbGVkIHdoZW4gcnVubmluZyBpbiBydW50aW1lLW9ubHkgbW9kZScpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEp1c3QgYWRkIHdhdGVyXG4gIGxldCBjb250YWluZXIgPSB7XG4gICAgc3RyaWN0OiBmdW5jdGlvbihvYmosIG5hbWUpIHtcbiAgICAgIGlmICghKG5hbWUgaW4gb2JqKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdcIicgKyBuYW1lICsgJ1wiIG5vdCBkZWZpbmVkIGluICcgKyBvYmopO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9ialtuYW1lXTtcbiAgICB9LFxuICAgIGxvb2t1cDogZnVuY3Rpb24oZGVwdGhzLCBuYW1lKSB7XG4gICAgICBjb25zdCBsZW4gPSBkZXB0aHMubGVuZ3RoO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZiAoZGVwdGhzW2ldICYmIGRlcHRoc1tpXVtuYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGRlcHRoc1tpXVtuYW1lXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgbGFtYmRhOiBmdW5jdGlvbihjdXJyZW50LCBjb250ZXh0KSB7XG4gICAgICByZXR1cm4gdHlwZW9mIGN1cnJlbnQgPT09ICdmdW5jdGlvbicgPyBjdXJyZW50LmNhbGwoY29udGV4dCkgOiBjdXJyZW50O1xuICAgIH0sXG5cbiAgICBlc2NhcGVFeHByZXNzaW9uOiBVdGlscy5lc2NhcGVFeHByZXNzaW9uLFxuICAgIGludm9rZVBhcnRpYWw6IGludm9rZVBhcnRpYWxXcmFwcGVyLFxuXG4gICAgZm46IGZ1bmN0aW9uKGkpIHtcbiAgICAgIGxldCByZXQgPSB0ZW1wbGF0ZVNwZWNbaV07XG4gICAgICByZXQuZGVjb3JhdG9yID0gdGVtcGxhdGVTcGVjW2kgKyAnX2QnXTtcbiAgICAgIHJldHVybiByZXQ7XG4gICAgfSxcblxuICAgIHByb2dyYW1zOiBbXSxcbiAgICBwcm9ncmFtOiBmdW5jdGlvbihpLCBkYXRhLCBkZWNsYXJlZEJsb2NrUGFyYW1zLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gICAgICBsZXQgcHJvZ3JhbVdyYXBwZXIgPSB0aGlzLnByb2dyYW1zW2ldLFxuICAgICAgICAgIGZuID0gdGhpcy5mbihpKTtcbiAgICAgIGlmIChkYXRhIHx8IGRlcHRocyB8fCBibG9ja1BhcmFtcyB8fCBkZWNsYXJlZEJsb2NrUGFyYW1zKSB7XG4gICAgICAgIHByb2dyYW1XcmFwcGVyID0gd3JhcFByb2dyYW0odGhpcywgaSwgZm4sIGRhdGEsIGRlY2xhcmVkQmxvY2tQYXJhbXMsIGJsb2NrUGFyYW1zLCBkZXB0aHMpO1xuICAgICAgfSBlbHNlIGlmICghcHJvZ3JhbVdyYXBwZXIpIHtcbiAgICAgICAgcHJvZ3JhbVdyYXBwZXIgPSB0aGlzLnByb2dyYW1zW2ldID0gd3JhcFByb2dyYW0odGhpcywgaSwgZm4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb2dyYW1XcmFwcGVyO1xuICAgIH0sXG5cbiAgICBkYXRhOiBmdW5jdGlvbih2YWx1ZSwgZGVwdGgpIHtcbiAgICAgIHdoaWxlICh2YWx1ZSAmJiBkZXB0aC0tKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuX3BhcmVudDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuICAgIG1lcmdlOiBmdW5jdGlvbihwYXJhbSwgY29tbW9uKSB7XG4gICAgICBsZXQgb2JqID0gcGFyYW0gfHwgY29tbW9uO1xuXG4gICAgICBpZiAocGFyYW0gJiYgY29tbW9uICYmIChwYXJhbSAhPT0gY29tbW9uKSkge1xuICAgICAgICBvYmogPSBVdGlscy5leHRlbmQoe30sIGNvbW1vbiwgcGFyYW0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gb2JqO1xuICAgIH0sXG5cbiAgICBub29wOiBlbnYuVk0ubm9vcCxcbiAgICBjb21waWxlckluZm86IHRlbXBsYXRlU3BlYy5jb21waWxlclxuICB9O1xuXG4gIGZ1bmN0aW9uIHJldChjb250ZXh0LCBvcHRpb25zID0ge30pIHtcbiAgICBsZXQgZGF0YSA9IG9wdGlvbnMuZGF0YTtcblxuICAgIHJldC5fc2V0dXAob3B0aW9ucyk7XG4gICAgaWYgKCFvcHRpb25zLnBhcnRpYWwgJiYgdGVtcGxhdGVTcGVjLnVzZURhdGEpIHtcbiAgICAgIGRhdGEgPSBpbml0RGF0YShjb250ZXh0LCBkYXRhKTtcbiAgICB9XG4gICAgbGV0IGRlcHRocyxcbiAgICAgICAgYmxvY2tQYXJhbXMgPSB0ZW1wbGF0ZVNwZWMudXNlQmxvY2tQYXJhbXMgPyBbXSA6IHVuZGVmaW5lZDtcbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZURlcHRocykge1xuICAgICAgaWYgKG9wdGlvbnMuZGVwdGhzKSB7XG4gICAgICAgIGRlcHRocyA9IGNvbnRleHQgIT0gb3B0aW9ucy5kZXB0aHNbMF0gPyBbY29udGV4dF0uY29uY2F0KG9wdGlvbnMuZGVwdGhzKSA6IG9wdGlvbnMuZGVwdGhzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVwdGhzID0gW2NvbnRleHRdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1haW4oY29udGV4dC8qLCBvcHRpb25zKi8pIHtcbiAgICAgIHJldHVybiAnJyArIHRlbXBsYXRlU3BlYy5tYWluKGNvbnRhaW5lciwgY29udGV4dCwgY29udGFpbmVyLmhlbHBlcnMsIGNvbnRhaW5lci5wYXJ0aWFscywgZGF0YSwgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gICAgfVxuICAgIG1haW4gPSBleGVjdXRlRGVjb3JhdG9ycyh0ZW1wbGF0ZVNwZWMubWFpbiwgbWFpbiwgY29udGFpbmVyLCBvcHRpb25zLmRlcHRocyB8fCBbXSwgZGF0YSwgYmxvY2tQYXJhbXMpO1xuICAgIHJldHVybiBtYWluKGNvbnRleHQsIG9wdGlvbnMpO1xuICB9XG4gIHJldC5pc1RvcCA9IHRydWU7XG5cbiAgcmV0Ll9zZXR1cCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMucGFydGlhbCkge1xuICAgICAgY29udGFpbmVyLmhlbHBlcnMgPSBjb250YWluZXIubWVyZ2Uob3B0aW9ucy5oZWxwZXJzLCBlbnYuaGVscGVycyk7XG5cbiAgICAgIGlmICh0ZW1wbGF0ZVNwZWMudXNlUGFydGlhbCkge1xuICAgICAgICBjb250YWluZXIucGFydGlhbHMgPSBjb250YWluZXIubWVyZ2Uob3B0aW9ucy5wYXJ0aWFscywgZW52LnBhcnRpYWxzKTtcbiAgICAgIH1cbiAgICAgIGlmICh0ZW1wbGF0ZVNwZWMudXNlUGFydGlhbCB8fCB0ZW1wbGF0ZVNwZWMudXNlRGVjb3JhdG9ycykge1xuICAgICAgICBjb250YWluZXIuZGVjb3JhdG9ycyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLmRlY29yYXRvcnMsIGVudi5kZWNvcmF0b3JzKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29udGFpbmVyLmhlbHBlcnMgPSBvcHRpb25zLmhlbHBlcnM7XG4gICAgICBjb250YWluZXIucGFydGlhbHMgPSBvcHRpb25zLnBhcnRpYWxzO1xuICAgICAgY29udGFpbmVyLmRlY29yYXRvcnMgPSBvcHRpb25zLmRlY29yYXRvcnM7XG4gICAgfVxuICB9O1xuXG4gIHJldC5fY2hpbGQgPSBmdW5jdGlvbihpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gICAgaWYgKHRlbXBsYXRlU3BlYy51c2VCbG9ja1BhcmFtcyAmJiAhYmxvY2tQYXJhbXMpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ211c3QgcGFzcyBibG9jayBwYXJhbXMnKTtcbiAgICB9XG4gICAgaWYgKHRlbXBsYXRlU3BlYy51c2VEZXB0aHMgJiYgIWRlcHRocykge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignbXVzdCBwYXNzIHBhcmVudCBkZXB0aHMnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gd3JhcFByb2dyYW0oY29udGFpbmVyLCBpLCB0ZW1wbGF0ZVNwZWNbaV0sIGRhdGEsIDAsIGJsb2NrUGFyYW1zLCBkZXB0aHMpO1xuICB9O1xuICByZXR1cm4gcmV0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JhcFByb2dyYW0oY29udGFpbmVyLCBpLCBmbiwgZGF0YSwgZGVjbGFyZWRCbG9ja1BhcmFtcywgYmxvY2tQYXJhbXMsIGRlcHRocykge1xuICBmdW5jdGlvbiBwcm9nKGNvbnRleHQsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBjdXJyZW50RGVwdGhzID0gZGVwdGhzO1xuICAgIGlmIChkZXB0aHMgJiYgY29udGV4dCAhPSBkZXB0aHNbMF0pIHtcbiAgICAgIGN1cnJlbnREZXB0aHMgPSBbY29udGV4dF0uY29uY2F0KGRlcHRocyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZuKGNvbnRhaW5lcixcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgY29udGFpbmVyLmhlbHBlcnMsIGNvbnRhaW5lci5wYXJ0aWFscyxcbiAgICAgICAgb3B0aW9ucy5kYXRhIHx8IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zICYmIFtvcHRpb25zLmJsb2NrUGFyYW1zXS5jb25jYXQoYmxvY2tQYXJhbXMpLFxuICAgICAgICBjdXJyZW50RGVwdGhzKTtcbiAgfVxuXG4gIHByb2cgPSBleGVjdXRlRGVjb3JhdG9ycyhmbiwgcHJvZywgY29udGFpbmVyLCBkZXB0aHMsIGRhdGEsIGJsb2NrUGFyYW1zKTtcblxuICBwcm9nLnByb2dyYW0gPSBpO1xuICBwcm9nLmRlcHRoID0gZGVwdGhzID8gZGVwdGhzLmxlbmd0aCA6IDA7XG4gIHByb2cuYmxvY2tQYXJhbXMgPSBkZWNsYXJlZEJsb2NrUGFyYW1zIHx8IDA7XG4gIHJldHVybiBwcm9nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVBhcnRpYWwocGFydGlhbCwgY29udGV4dCwgb3B0aW9ucykge1xuICBpZiAoIXBhcnRpYWwpIHtcbiAgICBpZiAob3B0aW9ucy5uYW1lID09PSAnQHBhcnRpYWwtYmxvY2snKSB7XG4gICAgICBsZXQgZGF0YSA9IG9wdGlvbnMuZGF0YTtcbiAgICAgIHdoaWxlIChkYXRhWydwYXJ0aWFsLWJsb2NrJ10gPT09IG5vb3ApIHtcbiAgICAgICAgZGF0YSA9IGRhdGEuX3BhcmVudDtcbiAgICAgIH1cbiAgICAgIHBhcnRpYWwgPSBkYXRhWydwYXJ0aWFsLWJsb2NrJ107XG4gICAgICBkYXRhWydwYXJ0aWFsLWJsb2NrJ10gPSBub29wO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYXJ0aWFsID0gb3B0aW9ucy5wYXJ0aWFsc1tvcHRpb25zLm5hbWVdO1xuICAgIH1cbiAgfSBlbHNlIGlmICghcGFydGlhbC5jYWxsICYmICFvcHRpb25zLm5hbWUpIHtcbiAgICAvLyBUaGlzIGlzIGEgZHluYW1pYyBwYXJ0aWFsIHRoYXQgcmV0dXJuZWQgYSBzdHJpbmdcbiAgICBvcHRpb25zLm5hbWUgPSBwYXJ0aWFsO1xuICAgIHBhcnRpYWwgPSBvcHRpb25zLnBhcnRpYWxzW3BhcnRpYWxdO1xuICB9XG4gIHJldHVybiBwYXJ0aWFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW52b2tlUGFydGlhbChwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKSB7XG4gIG9wdGlvbnMucGFydGlhbCA9IHRydWU7XG4gIGlmIChvcHRpb25zLmlkcykge1xuICAgIG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aCA9IG9wdGlvbnMuaWRzWzBdIHx8IG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aDtcbiAgfVxuXG4gIGxldCBwYXJ0aWFsQmxvY2s7XG4gIGlmIChvcHRpb25zLmZuICYmIG9wdGlvbnMuZm4gIT09IG5vb3ApIHtcbiAgICBvcHRpb25zLmRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgIHBhcnRpYWxCbG9jayA9IG9wdGlvbnMuZGF0YVsncGFydGlhbC1ibG9jayddID0gb3B0aW9ucy5mbjtcblxuICAgIGlmIChwYXJ0aWFsQmxvY2sucGFydGlhbHMpIHtcbiAgICAgIG9wdGlvbnMucGFydGlhbHMgPSBVdGlscy5leHRlbmQoe30sIG9wdGlvbnMucGFydGlhbHMsIHBhcnRpYWxCbG9jay5wYXJ0aWFscyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHBhcnRpYWwgPT09IHVuZGVmaW5lZCAmJiBwYXJ0aWFsQmxvY2spIHtcbiAgICBwYXJ0aWFsID0gcGFydGlhbEJsb2NrO1xuICB9XG5cbiAgaWYgKHBhcnRpYWwgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1RoZSBwYXJ0aWFsICcgKyBvcHRpb25zLm5hbWUgKyAnIGNvdWxkIG5vdCBiZSBmb3VuZCcpO1xuICB9IGVsc2UgaWYgKHBhcnRpYWwgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBwYXJ0aWFsKGNvbnRleHQsIG9wdGlvbnMpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBub29wKCkgeyByZXR1cm4gJyc7IH1cblxuZnVuY3Rpb24gaW5pdERhdGEoY29udGV4dCwgZGF0YSkge1xuICBpZiAoIWRhdGEgfHwgISgncm9vdCcgaW4gZGF0YSkpIHtcbiAgICBkYXRhID0gZGF0YSA/IGNyZWF0ZUZyYW1lKGRhdGEpIDoge307XG4gICAgZGF0YS5yb290ID0gY29udGV4dDtcbiAgfVxuICByZXR1cm4gZGF0YTtcbn1cblxuZnVuY3Rpb24gZXhlY3V0ZURlY29yYXRvcnMoZm4sIHByb2csIGNvbnRhaW5lciwgZGVwdGhzLCBkYXRhLCBibG9ja1BhcmFtcykge1xuICBpZiAoZm4uZGVjb3JhdG9yKSB7XG4gICAgbGV0IHByb3BzID0ge307XG4gICAgcHJvZyA9IGZuLmRlY29yYXRvcihwcm9nLCBwcm9wcywgY29udGFpbmVyLCBkZXB0aHMgJiYgZGVwdGhzWzBdLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgICBVdGlscy5leHRlbmQocHJvZywgcHJvcHMpO1xuICB9XG4gIHJldHVybiBwcm9nO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/safe-string.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/safe-string.js new file mode 100644 index 0000000..428b3a1 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/safe-string.js @@ -0,0 +1,15 @@ +// Build out our basic SafeString type +'use strict'; + +exports.__esModule = true; +function SafeString(string) { + this.string = string; +} + +SafeString.prototype.toString = SafeString.prototype.toHTML = function () { + return '' + this.string; +}; + +exports['default'] = SafeString; +module.exports = exports['default']; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3NhZmUtc3RyaW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFDQSxTQUFTLFVBQVUsQ0FBQyxNQUFNLEVBQUU7QUFDMUIsTUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7Q0FDdEI7O0FBRUQsVUFBVSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsWUFBVztBQUN2RSxTQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0NBQ3pCLENBQUM7O3FCQUVhLFVBQVUiLCJmaWxlIjoic2FmZS1zdHJpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBCdWlsZCBvdXQgb3VyIGJhc2ljIFNhZmVTdHJpbmcgdHlwZVxuZnVuY3Rpb24gU2FmZVN0cmluZyhzdHJpbmcpIHtcbiAgdGhpcy5zdHJpbmcgPSBzdHJpbmc7XG59XG5cblNhZmVTdHJpbmcucHJvdG90eXBlLnRvU3RyaW5nID0gU2FmZVN0cmluZy5wcm90b3R5cGUudG9IVE1MID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAnJyArIHRoaXMuc3RyaW5nO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgU2FmZVN0cmluZztcbiJdfQ== diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/utils.js b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/utils.js new file mode 100644 index 0000000..2d15214 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/handlebars/utils.js @@ -0,0 +1,124 @@ +'use strict'; + +exports.__esModule = true; +exports.extend = extend; +exports.indexOf = indexOf; +exports.escapeExpression = escapeExpression; +exports.isEmpty = isEmpty; +exports.createFrame = createFrame; +exports.blockParams = blockParams; +exports.appendContextPath = appendContextPath; +var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' +}; + +var badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + +function escapeChar(chr) { + return escape[chr]; +} + +function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; +} + +var toString = Object.prototype.toString; + +exports.toString = toString; +// Sourced from lodash +// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt +/* eslint-disable func-style */ +var isFunction = function isFunction(value) { + return typeof value === 'function'; +}; +// fallback for older versions of Chrome and Safari +/* istanbul ignore next */ +if (isFunction(/x/)) { + exports.isFunction = isFunction = function (value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; +} +exports.isFunction = isFunction; + +/* eslint-enable func-style */ + +/* istanbul ignore next */ +var isArray = Array.isArray || function (value) { + return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; +}; + +exports.isArray = isArray; +// Older IE versions do not directly support indexOf so we must implement our own, sadly. + +function indexOf(array, value) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; +} + +function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); +} + +function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } +} + +function createFrame(object) { + var frame = extend({}, object); + frame._parent = object; + return frame; +} + +function blockParams(params, ids) { + params.path = ids; + return params; +} + +function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3V0aWxzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSxJQUFNLE1BQU0sR0FBRztBQUNiLEtBQUcsRUFBRSxPQUFPO0FBQ1osS0FBRyxFQUFFLE1BQU07QUFDWCxLQUFHLEVBQUUsTUFBTTtBQUNYLEtBQUcsRUFBRSxRQUFRO0FBQ2IsS0FBRyxFQUFFLFFBQVE7QUFDYixLQUFHLEVBQUUsUUFBUTtBQUNiLEtBQUcsRUFBRSxRQUFRO0NBQ2QsQ0FBQzs7QUFFRixJQUFNLFFBQVEsR0FBRyxZQUFZO0lBQ3ZCLFFBQVEsR0FBRyxXQUFXLENBQUM7O0FBRTdCLFNBQVMsVUFBVSxDQUFDLEdBQUcsRUFBRTtBQUN2QixTQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztDQUNwQjs7QUFFTSxTQUFTLE1BQU0sQ0FBQyxHQUFHLG9CQUFtQjtBQUMzQyxPQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUN6QyxTQUFLLElBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRTtBQUM1QixVQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUU7QUFDM0QsV0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztPQUM5QjtLQUNGO0dBQ0Y7O0FBRUQsU0FBTyxHQUFHLENBQUM7Q0FDWjs7QUFFTSxJQUFJLFFBQVEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQzs7Ozs7O0FBS2hELElBQUksVUFBVSxHQUFHLG9CQUFTLEtBQUssRUFBRTtBQUMvQixTQUFPLE9BQU8sS0FBSyxLQUFLLFVBQVUsQ0FBQztDQUNwQyxDQUFDOzs7QUFHRixJQUFJLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRTtBQUNuQixVQUlNLFVBQVUsR0FKaEIsVUFBVSxHQUFHLFVBQVMsS0FBSyxFQUFFO0FBQzNCLFdBQU8sT0FBTyxLQUFLLEtBQUssVUFBVSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssbUJBQW1CLENBQUM7R0FDcEYsQ0FBQztDQUNIO1FBQ08sVUFBVSxHQUFWLFVBQVU7Ozs7O0FBSVgsSUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sSUFBSSxVQUFTLEtBQUssRUFBRTtBQUN0RCxTQUFPLEFBQUMsS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsR0FBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLGdCQUFnQixHQUFHLEtBQUssQ0FBQztDQUNqRyxDQUFDOzs7OztBQUdLLFNBQVMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDcEMsT0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUNoRCxRQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEVBQUU7QUFDdEIsYUFBTyxDQUFDLENBQUM7S0FDVjtHQUNGO0FBQ0QsU0FBTyxDQUFDLENBQUMsQ0FBQztDQUNYOztBQUdNLFNBQVMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFO0FBQ3ZDLE1BQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFOztBQUU5QixRQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFO0FBQzNCLGFBQU8sTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO0tBQ3hCLE1BQU0sSUFBSSxNQUFNLElBQUksSUFBSSxFQUFFO0FBQ3pCLGFBQU8sRUFBRSxDQUFDO0tBQ1gsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFO0FBQ2xCLGFBQU8sTUFBTSxHQUFHLEVBQUUsQ0FBQztLQUNwQjs7Ozs7QUFLRCxVQUFNLEdBQUcsRUFBRSxHQUFHLE1BQU0sQ0FBQztHQUN0Qjs7QUFFRCxNQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtBQUFFLFdBQU8sTUFBTSxDQUFDO0dBQUU7QUFDOUMsU0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztDQUM3Qzs7QUFFTSxTQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUU7QUFDN0IsTUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLEtBQUssQ0FBQyxFQUFFO0FBQ3pCLFdBQU8sSUFBSSxDQUFDO0dBQ2IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtBQUMvQyxXQUFPLElBQUksQ0FBQztHQUNiLE1BQU07QUFDTCxXQUFPLEtBQUssQ0FBQztHQUNkO0NBQ0Y7O0FBRU0sU0FBUyxXQUFXLENBQUMsTUFBTSxFQUFFO0FBQ2xDLE1BQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDL0IsT0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7QUFDdkIsU0FBTyxLQUFLLENBQUM7Q0FDZDs7QUFFTSxTQUFTLFdBQVcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO0FBQ3ZDLFFBQU0sQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDO0FBQ2xCLFNBQU8sTUFBTSxDQUFDO0NBQ2Y7O0FBRU0sU0FBUyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsRUFBRSxFQUFFO0FBQ2pELFNBQU8sQ0FBQyxXQUFXLEdBQUcsV0FBVyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUEsR0FBSSxFQUFFLENBQUM7Q0FDcEQiLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBlc2NhcGUgPSB7XG4gICcmJzogJyZhbXA7JyxcbiAgJzwnOiAnJmx0OycsXG4gICc+JzogJyZndDsnLFxuICAnXCInOiAnJnF1b3Q7JyxcbiAgXCInXCI6ICcmI3gyNzsnLFxuICAnYCc6ICcmI3g2MDsnLFxuICAnPSc6ICcmI3gzRDsnXG59O1xuXG5jb25zdCBiYWRDaGFycyA9IC9bJjw+XCInYD1dL2csXG4gICAgICBwb3NzaWJsZSA9IC9bJjw+XCInYD1dLztcblxuZnVuY3Rpb24gZXNjYXBlQ2hhcihjaHIpIHtcbiAgcmV0dXJuIGVzY2FwZVtjaHJdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXh0ZW5kKG9iai8qICwgLi4uc291cmNlICovKSB7XG4gIGZvciAobGV0IGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgZm9yIChsZXQga2V5IGluIGFyZ3VtZW50c1tpXSkge1xuICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhcmd1bWVudHNbaV0sIGtleSkpIHtcbiAgICAgICAgb2JqW2tleV0gPSBhcmd1bWVudHNbaV1ba2V5XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gb2JqO1xufVxuXG5leHBvcnQgbGV0IHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuLy8gU291cmNlZCBmcm9tIGxvZGFzaFxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2Jlc3RpZWpzL2xvZGFzaC9ibG9iL21hc3Rlci9MSUNFTlNFLnR4dFxuLyogZXNsaW50LWRpc2FibGUgZnVuYy1zdHlsZSAqL1xubGV0IGlzRnVuY3Rpb24gPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nO1xufTtcbi8vIGZhbGxiYWNrIGZvciBvbGRlciB2ZXJzaW9ucyBvZiBDaHJvbWUgYW5kIFNhZmFyaVxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmlmIChpc0Z1bmN0aW9uKC94LykpIHtcbiAgaXNGdW5jdGlvbiA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJyAmJiB0b1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbiAgfTtcbn1cbmV4cG9ydCB7aXNGdW5jdGlvbn07XG4vKiBlc2xpbnQtZW5hYmxlIGZ1bmMtc3R5bGUgKi9cblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmV4cG9ydCBjb25zdCBpc0FycmF5ID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpID8gdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IEFycmF5XScgOiBmYWxzZTtcbn07XG5cbi8vIE9sZGVyIElFIHZlcnNpb25zIGRvIG5vdCBkaXJlY3RseSBzdXBwb3J0IGluZGV4T2Ygc28gd2UgbXVzdCBpbXBsZW1lbnQgb3VyIG93biwgc2FkbHkuXG5leHBvcnQgZnVuY3Rpb24gaW5kZXhPZihhcnJheSwgdmFsdWUpIHtcbiAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGFycmF5Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGFycmF5W2ldID09PSB2YWx1ZSkge1xuICAgICAgcmV0dXJuIGk7XG4gICAgfVxuICB9XG4gIHJldHVybiAtMTtcbn1cblxuXG5leHBvcnQgZnVuY3Rpb24gZXNjYXBlRXhwcmVzc2lvbihzdHJpbmcpIHtcbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgLy8gZG9uJ3QgZXNjYXBlIFNhZmVTdHJpbmdzLCBzaW5jZSB0aGV5J3JlIGFscmVhZHkgc2FmZVxuICAgIGlmIChzdHJpbmcgJiYgc3RyaW5nLnRvSFRNTCkge1xuICAgICAgcmV0dXJuIHN0cmluZy50b0hUTUwoKTtcbiAgICB9IGVsc2UgaWYgKHN0cmluZyA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfSBlbHNlIGlmICghc3RyaW5nKSB7XG4gICAgICByZXR1cm4gc3RyaW5nICsgJyc7XG4gICAgfVxuXG4gICAgLy8gRm9yY2UgYSBzdHJpbmcgY29udmVyc2lvbiBhcyB0aGlzIHdpbGwgYmUgZG9uZSBieSB0aGUgYXBwZW5kIHJlZ2FyZGxlc3MgYW5kXG4gICAgLy8gdGhlIHJlZ2V4IHRlc3Qgd2lsbCBkbyB0aGlzIHRyYW5zcGFyZW50bHkgYmVoaW5kIHRoZSBzY2VuZXMsIGNhdXNpbmcgaXNzdWVzIGlmXG4gICAgLy8gYW4gb2JqZWN0J3MgdG8gc3RyaW5nIGhhcyBlc2NhcGVkIGNoYXJhY3RlcnMgaW4gaXQuXG4gICAgc3RyaW5nID0gJycgKyBzdHJpbmc7XG4gIH1cblxuICBpZiAoIXBvc3NpYmxlLnRlc3Qoc3RyaW5nKSkgeyByZXR1cm4gc3RyaW5nOyB9XG4gIHJldHVybiBzdHJpbmcucmVwbGFjZShiYWRDaGFycywgZXNjYXBlQ2hhcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0VtcHR5KHZhbHVlKSB7XG4gIGlmICghdmFsdWUgJiYgdmFsdWUgIT09IDApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmIChpc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZyYW1lKG9iamVjdCkge1xuICBsZXQgZnJhbWUgPSBleHRlbmQoe30sIG9iamVjdCk7XG4gIGZyYW1lLl9wYXJlbnQgPSBvYmplY3Q7XG4gIHJldHVybiBmcmFtZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJsb2NrUGFyYW1zKHBhcmFtcywgaWRzKSB7XG4gIHBhcmFtcy5wYXRoID0gaWRzO1xuICByZXR1cm4gcGFyYW1zO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwZW5kQ29udGV4dFBhdGgoY29udGV4dFBhdGgsIGlkKSB7XG4gIHJldHVybiAoY29udGV4dFBhdGggPyBjb250ZXh0UGF0aCArICcuJyA6ICcnKSArIGlkO1xufVxuIl19 diff --git a/hm_sunwell/node_modules/handlebars/dist/cjs/precompiler.js b/hm_sunwell/node_modules/handlebars/dist/cjs/precompiler.js new file mode 100644 index 0000000..bddca8e --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/cjs/precompiler.js @@ -0,0 +1,308 @@ +/* eslint-disable no-console */ +'use strict'; + +// istanbul ignore next + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } + +// istanbul ignore next + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _async = require('async'); + +var _async2 = _interopRequireDefault(_async); + +var _fs = require('fs'); + +var _fs2 = _interopRequireDefault(_fs); + +var _handlebars = require('./handlebars'); + +var Handlebars = _interopRequireWildcard(_handlebars); + +var _path = require('path'); + +var _sourceMap = require('source-map'); + +var _uglifyJs = require('uglify-js'); + +var _uglifyJs2 = _interopRequireDefault(_uglifyJs); + +module.exports.loadTemplates = function (opts, callback) { + loadStrings(opts, function (err, strings) { + if (err) { + callback(err); + } else { + loadFiles(opts, function (err, files) { + if (err) { + callback(err); + } else { + opts.templates = strings.concat(files); + callback(undefined, opts); + } + }); + } + }); +}; + +function loadStrings(opts, callback) { + var strings = arrayCast(opts.string), + names = arrayCast(opts.name); + + if (names.length !== strings.length && strings.length > 1) { + return callback(new Handlebars.Exception('Number of names did not match the number of string inputs')); + } + + _async2['default'].map(strings, function (string, callback) { + if (string !== '-') { + callback(undefined, string); + } else { + (function () { + // Load from stdin + var buffer = ''; + process.stdin.setEncoding('utf8'); + + process.stdin.on('data', function (chunk) { + buffer += chunk; + }); + process.stdin.on('end', function () { + callback(undefined, buffer); + }); + })(); + } + }, function (err, strings) { + strings = strings.map(function (string, index) { + return { + name: names[index], + path: names[index], + source: string + }; + }); + callback(err, strings); + }); +} + +function loadFiles(opts, callback) { + // Build file extension pattern + var extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function (arg) { + return '\\' + arg; + }); + extension = new RegExp('\\.' + extension + '$'); + + var ret = [], + queue = (opts.files || []).map(function (template) { + return { template: template, root: opts.root }; + }); + _async2['default'].whilst(function () { + return queue.length; + }, function (callback) { + var _queue$shift = queue.shift(); + + var path = _queue$shift.template; + var root = _queue$shift.root; + + _fs2['default'].stat(path, function (err, stat) { + if (err) { + return callback(new Handlebars.Exception('Unable to open template file "' + path + '"')); + } + + if (stat.isDirectory()) { + opts.hasDirectory = true; + + _fs2['default'].readdir(path, function (err, children) { + /* istanbul ignore next : Race condition that being too lazy to test */ + if (err) { + return callback(err); + } + children.forEach(function (file) { + var childPath = path + '/' + file; + + if (extension.test(childPath) || _fs2['default'].statSync(childPath).isDirectory()) { + queue.push({ template: childPath, root: root || path }); + } + }); + + callback(); + }); + } else { + _fs2['default'].readFile(path, 'utf8', function (err, data) { + /* istanbul ignore next : Race condition that being too lazy to test */ + if (err) { + return callback(err); + } + + if (opts.bom && data.indexOf('') === 0) { + data = data.substring(1); + } + + // Clean the template name + var name = path; + if (!root) { + name = _path.basename(name); + } else if (name.indexOf(root) === 0) { + name = name.substring(root.length + 1); + } + name = name.replace(extension, ''); + + ret.push({ + path: path, + name: name, + source: data + }); + + callback(); + }); + } + }); + }, function (err) { + if (err) { + callback(err); + } else { + callback(undefined, ret); + } + }); +} + +module.exports.cli = function (opts) { + if (opts.version) { + console.log(Handlebars.VERSION); + return; + } + + if (!opts.templates.length && !opts.hasDirectory) { + throw new Handlebars.Exception('Must define at least one template or directory.'); + } + + if (opts.simple && opts.min) { + throw new Handlebars.Exception('Unable to minimize simple output'); + } + + var multiple = opts.templates.length !== 1 || opts.hasDirectory; + if (opts.simple && multiple) { + throw new Handlebars.Exception('Unable to output multiple templates in simple mode'); + } + + // Force simple mode if we have only one template and it's unnamed. + if (!opts.amd && !opts.commonjs && opts.templates.length === 1 && !opts.templates[0].name) { + opts.simple = true; + } + + // Convert the known list into a hash + var known = {}; + if (opts.known && !Array.isArray(opts.known)) { + opts.known = [opts.known]; + } + if (opts.known) { + for (var i = 0, len = opts.known.length; i < len; i++) { + known[opts.known[i]] = true; + } + } + + var objectName = opts.partial ? 'Handlebars.partials' : 'templates'; + + var output = new _sourceMap.SourceNode(); + if (!opts.simple) { + if (opts.amd) { + output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];'); + } else if (opts.commonjs) { + output.add('var Handlebars = require("' + opts.commonjs + '");'); + } else { + output.add('(function() {\n'); + } + output.add(' var template = Handlebars.template, templates = '); + if (opts.namespace) { + output.add(opts.namespace); + output.add(' = '); + output.add(opts.namespace); + output.add(' || '); + } + output.add('{};\n'); + } + + opts.templates.forEach(function (template) { + var options = { + knownHelpers: known, + knownHelpersOnly: opts.o + }; + + if (opts.map) { + options.srcName = template.path; + } + if (opts.data) { + options.data = true; + } + + var precompiled = Handlebars.precompile(template.source, options); + + // If we are generating a source map, we have to reconstruct the SourceNode object + if (opts.map) { + var consumer = new _sourceMap.SourceMapConsumer(precompiled.map); + precompiled = _sourceMap.SourceNode.fromStringWithSourceMap(precompiled.code, consumer); + } + + if (opts.simple) { + output.add([precompiled, '\n']); + } else { + if (!template.name) { + throw new Handlebars.Exception('Name missing for template'); + } + + if (opts.amd && !multiple) { + output.add('return '); + } + output.add([objectName, '[\'', template.name, '\'] = template(', precompiled, ');\n']); + } + }); + + // Output the content + if (!opts.simple) { + if (opts.amd) { + if (multiple) { + output.add(['return ', objectName, ';\n']); + } + output.add('});'); + } else if (!opts.commonjs) { + output.add('})();'); + } + } + + if (opts.map) { + output.add('\n//# sourceMappingURL=' + opts.map + '\n'); + } + + output = output.toStringWithSourceMap(); + output.map = output.map + ''; + + if (opts.min) { + output = _uglifyJs2['default'].minify(output.code, { + fromString: true, + + outSourceMap: opts.map, + inSourceMap: JSON.parse(output.map) + }); + if (opts.map) { + output.code += '\n//# sourceMappingURL=' + opts.map + '\n'; + } + } + + if (opts.map) { + _fs2['default'].writeFileSync(opts.map, output.map, 'utf8'); + } + output = output.code; + + if (opts.output) { + _fs2['default'].writeFileSync(opts.output, output, 'utf8'); + } else { + console.log(output); + } +}; + +function arrayCast(value) { + value = value != null ? value : []; + if (!Array.isArray(value)) { + value = [value]; + } + return value; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9wcmVjb21waWxlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztxQkFDa0IsT0FBTzs7OztrQkFDVixJQUFJOzs7OzBCQUNTLGNBQWM7O0lBQTlCLFVBQVU7O29CQUNDLE1BQU07O3lCQUNlLFlBQVk7O3dCQUNyQyxXQUFXOzs7O0FBRTlCLE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxHQUFHLFVBQVMsSUFBSSxFQUFFLFFBQVEsRUFBRTtBQUN0RCxhQUFXLENBQUMsSUFBSSxFQUFFLFVBQVMsR0FBRyxFQUFFLE9BQU8sRUFBRTtBQUN2QyxRQUFJLEdBQUcsRUFBRTtBQUNQLGNBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUNmLE1BQU07QUFDTCxlQUFTLENBQUMsSUFBSSxFQUFFLFVBQVMsR0FBRyxFQUFFLEtBQUssRUFBRTtBQUNuQyxZQUFJLEdBQUcsRUFBRTtBQUNQLGtCQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDZixNQUFNO0FBQ0wsY0FBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3ZDLGtCQUFRLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQzNCO09BQ0YsQ0FBQyxDQUFDO0tBQ0o7R0FDRixDQUFDLENBQUM7Q0FDSixDQUFDOztBQUVGLFNBQVMsV0FBVyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUU7QUFDbkMsTUFBSSxPQUFPLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7TUFDaEMsS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7O0FBRWpDLE1BQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxJQUM1QixPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtBQUN6QixXQUFPLFFBQVEsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsMkRBQTJELENBQUMs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QUUsSUFBSSxDQUFDLEdBQUc7QUFDdEIsaUJBQVcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7S0FDcEMsQ0FBQyxDQUFDO0FBQ0gsUUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO0FBQ1osWUFBTSxDQUFDLElBQUksSUFBSSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztLQUM1RDtHQUNGOztBQUVELE1BQUksSUFBSSxDQUFDLEdBQUcsRUFBRTtBQUNaLG9CQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7R0FDaEQ7QUFDRCxRQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQzs7QUFFckIsTUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO0FBQ2Ysb0JBQUcsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0dBQy9DLE1BQU07QUFDTCxXQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0dBQ3JCO0NBQ0YsQ0FBQzs7QUFFRixTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUU7QUFDeEIsT0FBSyxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQztBQUNuQyxNQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUN6QixTQUFLLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUNqQjtBQUNELFNBQU8sS0FBSyxDQUFDO0NBQ2QiLCJmaWxlIjoicHJlY29tcGlsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgQXN5bmMgZnJvbSAnYXN5bmMnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIEhhbmRsZWJhcnMgZnJvbSAnLi9oYW5kbGViYXJzJztcbmltcG9ydCB7YmFzZW5hbWV9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtTb3VyY2VNYXBDb25zdW1lciwgU291cmNlTm9kZX0gZnJvbSAnc291cmNlLW1hcCc7XG5pbXBvcnQgdWdsaWZ5IGZyb20gJ3VnbGlmeS1qcyc7XG5cbm1vZHVsZS5leHBvcnRzLmxvYWRUZW1wbGF0ZXMgPSBmdW5jdGlvbihvcHRzLCBjYWxsYmFjaykge1xuICBsb2FkU3RyaW5ncyhvcHRzLCBmdW5jdGlvbihlcnIsIHN0cmluZ3MpIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICBjYWxsYmFjayhlcnIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2FkRmlsZXMob3B0cywgZnVuY3Rpb24oZXJyLCBmaWxlcykge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvcHRzLnRlbXBsYXRlcyA9IHN0cmluZ3MuY29uY2F0KGZpbGVzKTtcbiAgICAgICAgICBjYWxsYmFjayh1bmRlZmluZWQsIG9wdHMpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gbG9hZFN0cmluZ3Mob3B0cywgY2FsbGJhY2spIHtcbiAgbGV0IHN0cmluZ3MgPSBhcnJheUNhc3Qob3B0cy5zdHJpbmcpLFxuICAgICAgbmFtZXMgPSBhcnJheUNhc3Qob3B0cy5uYW1lKTtcblxuICBpZiAobmFtZXMubGVuZ3RoICE9PSBzdHJpbmdzLmxlbmd0aFxuICAgICAgJiYgc3RyaW5ncy5sZW5ndGggPiAxKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBIYW5kbGViYXJzLkV4Y2VwdGlvbignTnVtYmVyIG9mIG5hbWVzIGRpZCBub3QgbWF0Y2ggdGhlIG51bWJlciBvZiBzdHJpbmcgaW5wdXRzJykpO1xuICB9XG5cbiAgQXN5bmMubWFwKHN0cmluZ3MsIGZ1bmN0aW9uKHN0cmluZywgY2FsbGJhY2spIHtcbiAgICAgIGlmIChzdHJpbmcgIT09ICctJykge1xuICAgICAgICBjYWxsYmFjayh1bmRlZmluZWQsIHN0cmluZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBMb2FkIGZyb20gc3RkaW5cbiAgICAgICAgbGV0IGJ1ZmZlciA9ICcnO1xuICAgICAgICBwcm9jZXNzLnN0ZGluLnNldEVuY29kaW5nKCd1dGY4Jyk7XG5cbiAgICAgICAgcHJvY2Vzcy5zdGRpbi5vbignZGF0YScsIGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgICAgICAgYnVmZmVyICs9IGNodW5rO1xuICAgICAgICB9KTtcbiAgICAgICAgcHJvY2Vzcy5zdGRpbi5vbignZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkLCBidWZmZXIpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGZ1bmN0aW9uKGVyciwgc3RyaW5ncykge1xuICAgICAgc3RyaW5ncyA9IHN0cmluZ3MubWFwKChzdHJpbmcsIGluZGV4KSA9PiAoe1xuICAgICAgICBuYW1lOiBuYW1lc1tpbmRleF0sXG4gICAgICAgIHBhdGg6IG5hbWVzW2luZGV4XSxcbiAgICAgICAgc291cmNlOiBzdHJpbmdcbiAgICAgIH0pKTtcbiAgICAgIGNhbGxiYWNrKGVyciwgc3RyaW5ncyk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGxvYWRGaWxlcyhvcHRzLCBjYWxsYmFjaykge1xuICAvLyBCdWlsZCBmaWxlIGV4dGVuc2lvbiBwYXR0ZXJuXG4gIGxldCBleHRlbnNpb24gPSAob3B0cy5leHRlbnNpb24gfHwgJ2hhbmRsZWJhcnMnKS5yZXBsYWNlKC9bXFxcXF4kKis/LigpOj0hfHt9XFwtXFxbXFxdXS9nLCBmdW5jdGlvbihhcmcpIHsgcmV0dXJuICdcXFxcJyArIGFyZzsgfSk7XG4gIGV4dGVuc2lvbiA9IG5ldyBSZWdFeHAoJ1xcXFwuJyArIGV4dGVuc2lvbiArICckJyk7XG5cbiAgbGV0IHJldCA9IFtdLFxuICAgICAgcXVldWUgPSAob3B0cy5maWxlcyB8fCBbXSkubWFwKCh0ZW1wbGF0ZSkgPT4gKHt0ZW1wbGF0ZSwgcm9vdDogb3B0cy5yb290fSkpO1xuICBBc3luYy53aGlsc3QoKCkgPT4gcXVldWUubGVuZ3RoLCBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIGxldCB7dGVtcGxhdGU6IHBhdGgsIHJvb3R9ID0gcXVldWUuc2hpZnQoKTtcblxuICAgIGZzLnN0YXQocGF0aCwgZnVuY3Rpb24oZXJyLCBzdGF0KSB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhuZXcgSGFuZGxlYmFycy5FeGNlcHRpb24oYFVuYWJsZSB0byBvcGVuIHRlbXBsYXRlIGZpbGUgXCIke3BhdGh9XCJgKSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgb3B0cy5oYXNEaXJlY3RvcnkgPSB0cnVlO1xuXG4gICAgICAgIGZzLnJlYWRkaXIocGF0aCwgZnVuY3Rpb24oZXJyLCBjaGlsZHJlbikge1xuICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0IDogUmFjZSBjb25kaXRpb24gdGhhdCBiZWluZyB0b28gbGF6eSB0byB0ZXN0ICovXG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24oZmlsZSkge1xuICAgICAgICAgICAgbGV0IGNoaWxkUGF0aCA9IHBhdGggKyAnLycgKyBmaWxlO1xuXG4gICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLnRlc3QoY2hpbGRQYXRoKSB8fCBmcy5zdGF0U3luYyhjaGlsZFBhdGgpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgICAgcXVldWUucHVzaCh7dGVtcGxhdGU6IGNoaWxkUGF0aCwgcm9vdDogcm9vdCB8fCBwYXRofSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZzLnJlYWRGaWxlKHBhdGgsICd1dGY4JywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgOiBSYWNlIGNvbmRpdGlvbiB0aGF0IGJlaW5nIHRvbyBsYXp5IHRvIHRlc3QgKi9cbiAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAob3B0cy5ib20gJiYgZGF0YS5pbmRleE9mKCdcXHVGRUZGJykgPT09IDApIHtcbiAgICAgICAgICAgIGRhdGEgPSBkYXRhLnN1YnN0cmluZygxKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBDbGVhbiB0aGUgdGVtcGxhdGUgbmFtZVxuICAgICAgICAgIGxldCBuYW1lID0gcGF0aDtcbiAgICAgICAgICBpZiAoIXJvb3QpIHtcbiAgICAgICAgICAgIG5hbWUgPSBiYXNlbmFtZShuYW1lKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKG5hbWUuaW5kZXhPZihyb290KSA9PT0gMCkge1xuICAgICAgICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyaW5nKHJvb3QubGVuZ3RoICsgMSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG5hbWUgPSBuYW1lLnJlcGxhY2UoZXh0ZW5zaW9uLCAnJyk7XG5cbiAgICAgICAgICByZXQucHVzaCh7XG4gICAgICAgICAgICBwYXRoOiBwYXRoLFxuICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgIHNvdXJjZTogZGF0YVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0sXG4gIGZ1bmN0aW9uKGVycikge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCwgcmV0KTtcbiAgICB9XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cy5jbGkgPSBmdW5jdGlvbihvcHRzKSB7XG4gIGlmIChvcHRzLnZlcnNpb24pIHtcbiAgICBjb25zb2xlLmxvZyhIYW5kbGViYXJzLlZFUlNJT04pO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghb3B0cy50ZW1wbGF0ZXMubGVuZ3RoICYmICFvcHRzLmhhc0RpcmVjdG9yeSkge1xuICAgIHRocm93IG5ldyBIYW5kbGViYXJzLkV4Y2VwdGlvbignTXVzdCBkZWZpbmUgYXQgbGVhc3Qgb25lIHRlbXBsYXRlIG9yIGRpcmVjdG9yeS4nKTtcbiAgfVxuXG4gIGlmIChvcHRzLnNpbXBsZSAmJiBvcHRzLm1pbikge1xuICAgIHRocm93IG5ldyBIYW5kbGViYXJzLkV4Y2VwdGlvbignVW5hYmxlIHRvIG1pbmltaXplIHNpbXBsZSBvdXRwdXQnKTtcbiAgfVxuXG4gIGNvbnN0IG11bHRpcGxlID0gb3B0cy50ZW1wbGF0ZXMubGVuZ3RoICE9PSAxIHx8IG9wdHMuaGFzRGlyZWN0b3J5O1xuICBpZiAob3B0cy5zaW1wbGUgJiYgbXVsdGlwbGUpIHtcbiAgICB0aHJvdyBuZXcgSGFuZGxlYmFycy5FeGNlcHRpb24oJ1VuYWJsZSB0byBvdXRwdXQgbXVsdGlwbGUgdGVtcGxhdGVzIGluIHNpbXBsZSBtb2RlJyk7XG4gIH1cblxuICAvLyBGb3JjZSBzaW1wbGUgbW9kZSBpZiB3ZSBoYXZlIG9ubHkgb25lIHRlbXBsYXRlIGFuZCBpdCdzIHVubmFtZWQuXG4gIGlmICghb3B0cy5hbWQgJiYgIW9wdHMuY29tbW9uanMgJiYgb3B0cy50ZW1wbGF0ZXMubGVuZ3RoID09PSAxXG4gICAgICAmJiAhb3B0cy50ZW1wbGF0ZXNbMF0ubmFtZSkge1xuICAgIG9wdHMuc2ltcGxlID0gdHJ1ZTtcbiAgfVxuXG4gIC8vIENvbnZlcnQgdGhlIGtub3duIGxpc3QgaW50byBhIGhhc2hcbiAgbGV0IGtub3duID0ge307XG4gIGlmIChvcHRzLmtub3duICYmICFBcnJheS5pc0FycmF5KG9wdHMua25vd24pKSB7XG4gICAgb3B0cy5rbm93biA9IFtvcHRzLmtub3duXTtcbiAgfVxuICBpZiAob3B0cy5rbm93bikge1xuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBvcHRzLmtub3duLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBrbm93bltvcHRzLmtub3duW2ldXSA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgY29uc3Qgb2JqZWN0TmFtZSA9IG9wdHMucGFydGlhbCA/ICdIYW5kbGViYXJzLnBhcnRpYWxzJyA6ICd0ZW1wbGF0ZXMnO1xuXG4gIGxldCBvdXRwdXQgPSBuZXcgU291cmNlTm9kZSgpO1xuICBpZiAoIW9wdHMuc2ltcGxlKSB7XG4gICAgaWYgKG9wdHMuYW1kKSB7XG4gICAgICBvdXRwdXQuYWRkKCdkZWZpbmUoW1xcJycgKyBvcHRzLmhhbmRsZWJhclBhdGggKyAnaGFuZGxlYmFycy5ydW50aW1lXFwnXSwgZnVuY3Rpb24oSGFuZGxlYmFycykge1xcbiAgSGFuZGxlYmFycyA9IEhhbmRsZWJhcnNbXCJkZWZhdWx0XCJdOycpO1xuICAgIH0gZWxzZSBpZiAob3B0cy5jb21tb25qcykge1xuICAgICAgb3V0cHV0LmFkZCgndmFyIEhhbmRsZWJhcnMgPSByZXF1aXJlKFwiJyArIG9wdHMuY29tbW9uanMgKyAnXCIpOycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXRwdXQuYWRkKCcoZnVuY3Rpb24oKSB7XFxuJyk7XG4gICAgfVxuICAgIG91dHB1dC5hZGQoJyAgdmFyIHRlbXBsYXRlID0gSGFuZGxlYmFycy50ZW1wbGF0ZSwgdGVtcGxhdGVzID0gJyk7XG4gICAgaWYgKG9wdHMubmFtZXNwYWNlKSB7XG4gICAgICBvdXRwdXQuYWRkKG9wdHMubmFtZXNwYWNlKTtcbiAgICAgIG91dHB1dC5hZGQoJyA9ICcpO1xuICAgICAgb3V0cHV0LmFkZChvcHRzLm5hbWVzcGFjZSk7XG4gICAgICBvdXRwdXQuYWRkKCcgfHwgJyk7XG4gICAgfVxuICAgIG91dHB1dC5hZGQoJ3t9O1xcbicpO1xuICB9XG5cbiAgb3B0cy50ZW1wbGF0ZXMuZm9yRWFjaChmdW5jdGlvbih0ZW1wbGF0ZSkge1xuICAgIGxldCBvcHRpb25zID0ge1xuICAgICAga25vd25IZWxwZXJzOiBrbm93bixcbiAgICAgIGtub3duSGVscGVyc09ubHk6IG9wdHMub1xuICAgIH07XG5cbiAgICBpZiAob3B0cy5tYXApIHtcbiAgICAgIG9wdGlvbnMuc3JjTmFtZSA9IHRlbXBsYXRlLnBhdGg7XG4gICAgfVxuICAgIGlmIChvcHRzLmRhdGEpIHtcbiAgICAgIG9wdGlvbnMuZGF0YSA9IHRydWU7XG4gICAgfVxuXG4gICAgbGV0IHByZWNvbXBpbGVkID0gSGFuZGxlYmFycy5wcmVjb21waWxlKHRlbXBsYXRlLnNvdXJjZSwgb3B0aW9ucyk7XG5cbiAgICAvLyBJZiB3ZSBhcmUgZ2VuZXJhdGluZyBhIHNvdXJjZSBtYXAsIHdlIGhhdmUgdG8gcmVjb25zdHJ1Y3QgdGhlIFNvdXJjZU5vZGUgb2JqZWN0XG4gICAgaWYgKG9wdHMubWFwKSB7XG4gICAgICBsZXQgY29uc3VtZXIgPSBuZXcgU291cmNlTWFwQ29uc3VtZXIocHJlY29tcGlsZWQubWFwKTtcbiAgICAgIHByZWNvbXBpbGVkID0gU291cmNlTm9kZS5mcm9tU3RyaW5nV2l0aFNvdXJjZU1hcChwcmVjb21waWxlZC5jb2RlLCBjb25zdW1lcik7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuc2ltcGxlKSB7XG4gICAgICBvdXRwdXQuYWRkKFtwcmVjb21waWxlZCwgJ1xcbiddKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCF0ZW1wbGF0ZS5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBIYW5kbGViYXJzLkV4Y2VwdGlvbignTmFtZSBtaXNzaW5nIGZvciB0ZW1wbGF0ZScpO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0cy5hbWQgJiYgIW11bHRpcGxlKSB7XG4gICAgICAgIG91dHB1dC5hZGQoJ3JldHVybiAnKTtcbiAgICAgIH1cbiAgICAgIG91dHB1dC5hZGQoW29iamVjdE5hbWUsICdbXFwnJywgdGVtcGxhdGUubmFtZSwgJ1xcJ10gPSB0ZW1wbGF0ZSgnLCBwcmVjb21waWxlZCwgJyk7XFxuJ10pO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gT3V0cHV0IHRoZSBjb250ZW50XG4gIGlmICghb3B0cy5zaW1wbGUpIHtcbiAgICBpZiAob3B0cy5hbWQpIHtcbiAgICAgIGlmIChtdWx0aXBsZSkge1xuICAgICAgICBvdXRwdXQuYWRkKFsncmV0dXJuICcsIG9iamVjdE5hbWUsICc7XFxuJ10pO1xuICAgICAgfVxuICAgICAgb3V0cHV0LmFkZCgnfSk7Jyk7XG4gICAgfSBlbHNlIGlmICghb3B0cy5jb21tb25qcykge1xuICAgICAgb3V0cHV0LmFkZCgnfSkoKTsnKTtcbiAgICB9XG4gIH1cblxuXG4gIGlmIChvcHRzLm1hcCkge1xuICAgIG91dHB1dC5hZGQoJ1xcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPScgKyBvcHRzLm1hcCArICdcXG4nKTtcbiAgfVxuXG4gIG91dHB1dCA9IG91dHB1dC50b1N0cmluZ1dpdGhTb3VyY2VNYXAoKTtcbiAgb3V0cHV0Lm1hcCA9IG91dHB1dC5tYXAgKyAnJztcblxuICBpZiAob3B0cy5taW4pIHtcbiAgICBvdXRwdXQgPSB1Z2xpZnkubWluaWZ5KG91dHB1dC5jb2RlLCB7XG4gICAgICBmcm9tU3RyaW5nOiB0cnVlLFxuXG4gICAgICBvdXRTb3VyY2VNYXA6IG9wdHMubWFwLFxuICAgICAgaW5Tb3VyY2VNYXA6IEpTT04ucGFyc2Uob3V0cHV0Lm1hcClcbiAgICB9KTtcbiAgICBpZiAob3B0cy5tYXApIHtcbiAgICAgIG91dHB1dC5jb2RlICs9ICdcXG4vLyMgc291cmNlTWFwcGluZ1VSTD0nICsgb3B0cy5tYXAgKyAnXFxuJztcbiAgICB9XG4gIH1cblxuICBpZiAob3B0cy5tYXApIHtcbiAgICBmcy53cml0ZUZpbGVTeW5jKG9wdHMubWFwLCBvdXRwdXQubWFwLCAndXRmOCcpO1xuICB9XG4gIG91dHB1dCA9IG91dHB1dC5jb2RlO1xuXG4gIGlmIChvcHRzLm91dHB1dCkge1xuICAgIGZzLndyaXRlRmlsZVN5bmMob3B0cy5vdXRwdXQsIG91dHB1dCwgJ3V0ZjgnKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZyhvdXRwdXQpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBhcnJheUNhc3QodmFsdWUpIHtcbiAgdmFsdWUgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiBbXTtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHZhbHVlID0gW3ZhbHVlXTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG4iXX0= diff --git a/hm_sunwell/node_modules/handlebars/dist/handlebars.amd.js b/hm_sunwell/node_modules/handlebars/dist/handlebars.amd.js new file mode 100644 index 0000000..6cf7bdd --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/handlebars.amd.js @@ -0,0 +1,4339 @@ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +define('handlebars/utils',['exports'], function (exports) { + 'use strict'; + + exports.__esModule = true; + exports.extend = extend; + exports.indexOf = indexOf; + exports.escapeExpression = escapeExpression; + exports.isEmpty = isEmpty; + exports.createFrame = createFrame; + exports.blockParams = blockParams; + exports.appendContextPath = appendContextPath; + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' + }; + + var badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + + function escapeChar(chr) { + return escape[chr]; + } + + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; + } + + var toString = Object.prototype.toString; + + exports.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + /* eslint-disable func-style */ + var isFunction = function isFunction(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + exports.isFunction = isFunction = function (value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + exports.isFunction = isFunction; + + /* eslint-enable func-style */ + + /* istanbul ignore next */ + var isArray = Array.isArray || function (value) { + return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; + }; + + exports.isArray = isArray; + // Older IE versions do not directly support indexOf so we must implement our own, sadly. + + function indexOf(array, value) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; + } + + function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); + } + + function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + function createFrame(object) { + var frame = extend({}, object); + frame._parent = object; + return frame; + } + + function blockParams(params, ids) { + params.path = ids; + return params; + } + + function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3V0aWxzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQUEsTUFBTSxNQUFNLEdBQUc7QUFDYixPQUFHLEVBQUUsT0FBTztBQUNaLE9BQUcsRUFBRSxNQUFNO0FBQ1gsT0FBRyxFQUFFLE1BQU07QUFDWCxPQUFHLEVBQUUsUUFBUTtBQUNiLE9BQUcsRUFBRSxRQUFRO0FBQ2IsT0FBRyxFQUFFLFFBQVE7QUFDYixPQUFHLEVBQUUsUUFBUTtHQUNkLENBQUM7O0FBRUYsTUFBTSxRQUFRLEdBQUcsWUFBWTtNQUN2QixRQUFRLEdBQUcsV0FBVyxDQUFDOztBQUU3QixXQUFTLFVBQVUsQ0FBQyxHQUFHLEVBQUU7QUFDdkIsV0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7R0FDcEI7O0FBRU0sV0FBUyxNQUFNLENBQUMsR0FBRyxvQkFBbUI7QUFDM0MsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDekMsV0FBSyxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7QUFDNUIsWUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFO0FBQzNELGFBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDOUI7T0FDRjtLQUNGOztBQUVELFdBQU8sR0FBRyxDQUFDO0dBQ1o7O0FBRU0sTUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7Ozs7OztBQUtoRCxNQUFJLFVBQVUsR0FBRyxvQkFBUyxLQUFLLEVBQUU7QUFDL0IsV0FBTyxPQUFPLEtBQUssS0FBSyxVQUFVLENBQUM7R0FDcEMsQ0FBQzs7O0FBR0YsTUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7QUFDbkIsWUFJTSxVQUFVLEdBSmhCLFVBQVUsR0FBRyxVQUFTLEtBQUssRUFBRTtBQUMzQixhQUFPLE9BQU8sS0FBSyxLQUFLLFVBQVUsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLG1CQUFtQixDQUFDO0tBQ3BGLENBQUM7R0FDSDtVQUNPLFVBQVUsR0FBVixVQUFVOzs7OztBQUlYLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLElBQUksVUFBUyxLQUFLLEVBQUU7QUFDdEQsV0FBTyxBQUFDLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEdBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7R0FDakcsQ0FBQzs7Ozs7QUFHSyxXQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQ3BDLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDaEQsVUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxFQUFFO0FBQ3RCLGVBQU8sQ0FBQyxDQUFDO09BQ1Y7S0FDRjtBQUNELFdBQU8sQ0FBQyxDQUFDLENBQUM7R0FDWDs7QUFHTSxXQUFTLGdCQUFnQixDQUFDLE1BQU0sRUFBRTtBQUN2QyxRQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsRUFBRTs7QUFFOUIsVUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtBQUMzQixlQUFPLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztPQUN4QixNQUFNLElBQUksTUFBTSxJQUFJLElBQUksRUFBRTtBQUN6QixlQUFPLEVBQUUsQ0FBQztPQUNYLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRTtBQUNsQixlQUFPLE1BQU0sR0FBRyxFQUFFLENBQUM7T0FDcEI7Ozs7O0FBS0QsWUFBTSxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUM7S0FDdEI7O0FBRUQsUUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7QUFBRSxhQUFPLE1BQU0sQ0FBQztLQUFFO0FBQzlDLFdBQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7R0FDN0M7O0FBRU0sV0FBUyxPQUFPLENBQUMsS0FBSyxFQUFFO0FBQzdCLFFBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxLQUFLLENBQUMsRUFBRTtBQUN6QixhQUFPLElBQUksQ0FBQztLQUNiLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7QUFDL0MsYUFBTyxJQUFJLENBQUM7S0FDYixNQUFNO0FBQ0wsYUFBTyxLQUFLLENBQUM7S0FDZDtHQUNGOztBQUVNLFdBQVMsV0FBVyxDQUFDLE1BQU0sRUFBRTtBQUNsQyxRQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQy9CLFNBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO0FBQ3ZCLFdBQU8sS0FBSyxDQUFDO0dBQ2Q7O0FBRU0sV0FBUyxXQUFXLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtBQUN2QyxVQUFNLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztBQUNsQixXQUFPLE1BQU0sQ0FBQztHQUNmOztBQUVNLFdBQVMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEVBQUUsRUFBRTtBQUNqRCxXQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFBLEdBQUksRUFBRSxDQUFDO0dBQ3BEIiwiZmlsZSI6InV0aWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgZXNjYXBlID0ge1xuICAnJic6ICcmYW1wOycsXG4gICc8JzogJyZsdDsnLFxuICAnPic6ICcmZ3Q7JyxcbiAgJ1wiJzogJyZxdW90OycsXG4gIFwiJ1wiOiAnJiN4Mjc7JyxcbiAgJ2AnOiAnJiN4NjA7JyxcbiAgJz0nOiAnJiN4M0Q7J1xufTtcblxuY29uc3QgYmFkQ2hhcnMgPSAvWyY8PlwiJ2A9XS9nLFxuICAgICAgcG9zc2libGUgPSAvWyY8PlwiJ2A9XS87XG5cbmZ1bmN0aW9uIGVzY2FwZUNoYXIoY2hyKSB7XG4gIHJldHVybiBlc2NhcGVbY2hyXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZChvYmovKiAsIC4uLnNvdXJjZSAqLykge1xuICBmb3IgKGxldCBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIGZvciAobGV0IGtleSBpbiBhcmd1bWVudHNbaV0pIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYXJndW1lbnRzW2ldLCBrZXkpKSB7XG4gICAgICAgIG9ialtrZXldID0gYXJndW1lbnRzW2ldW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZXhwb3J0IGxldCB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8vIFNvdXJjZWQgZnJvbSBsb2Rhc2hcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iZXN0aWVqcy9sb2Rhc2gvYmxvYi9tYXN0ZXIvTElDRU5TRS50eHRcbi8qIGVzbGludC1kaXNhYmxlIGZ1bmMtc3R5bGUgKi9cbmxldCBpc0Z1bmN0aW9uID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcbn07XG4vLyBmYWxsYmFjayBmb3Igb2xkZXIgdmVyc2lvbnMgb2YgQ2hyb21lIGFuZCBTYWZhcmlcbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5pZiAoaXNGdW5jdGlvbigveC8pKSB7XG4gIGlzRnVuY3Rpb24gPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicgJiYgdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG4gIH07XG59XG5leHBvcnQge2lzRnVuY3Rpb259O1xuLyogZXNsaW50LWVuYWJsZSBmdW5jLXN0eWxlICovXG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5leHBvcnQgY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSA/IHRvU3RyaW5nLmNhbGwodmFsdWUpID09PSAnW29iamVjdCBBcnJheV0nIDogZmFsc2U7XG59O1xuXG4vLyBPbGRlciBJRSB2ZXJzaW9ucyBkbyBub3QgZGlyZWN0bHkgc3VwcG9ydCBpbmRleE9mIHNvIHdlIG11c3QgaW1wbGVtZW50IG91ciBvd24sIHNhZGx5LlxuZXhwb3J0IGZ1bmN0aW9uIGluZGV4T2YoYXJyYXksIHZhbHVlKSB7XG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBhcnJheS5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGlmIChhcnJheVtpXSA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gLTE7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZUV4cHJlc3Npb24oc3RyaW5nKSB7XG4gIGlmICh0eXBlb2Ygc3RyaW5nICE9PSAnc3RyaW5nJykge1xuICAgIC8vIGRvbid0IGVzY2FwZSBTYWZlU3RyaW5ncywgc2luY2UgdGhleSdyZSBhbHJlYWR5IHNhZmVcbiAgICBpZiAoc3RyaW5nICYmIHN0cmluZy50b0hUTUwpIHtcbiAgICAgIHJldHVybiBzdHJpbmcudG9IVE1MKCk7XG4gICAgfSBlbHNlIGlmIChzdHJpbmcgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSBpZiAoIXN0cmluZykge1xuICAgICAgcmV0dXJuIHN0cmluZyArICcnO1xuICAgIH1cblxuICAgIC8vIEZvcmNlIGEgc3RyaW5nIGNvbnZlcnNpb24gYXMgdGhpcyB3aWxsIGJlIGRvbmUgYnkgdGhlIGFwcGVuZCByZWdhcmRsZXNzIGFuZFxuICAgIC8vIHRoZSByZWdleCB0ZXN0IHdpbGwgZG8gdGhpcyB0cmFuc3BhcmVudGx5IGJlaGluZCB0aGUgc2NlbmVzLCBjYXVzaW5nIGlzc3VlcyBpZlxuICAgIC8vIGFuIG9iamVjdCdzIHRvIHN0cmluZyBoYXMgZXNjYXBlZCBjaGFyYWN0ZXJzIGluIGl0LlxuICAgIHN0cmluZyA9ICcnICsgc3RyaW5nO1xuICB9XG5cbiAgaWYgKCFwb3NzaWJsZS50ZXN0KHN0cmluZykpIHsgcmV0dXJuIHN0cmluZzsgfVxuICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoYmFkQ2hhcnMsIGVzY2FwZUNoYXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSkge1xuICBpZiAoIXZhbHVlICYmIHZhbHVlICE9PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAoaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVGcmFtZShvYmplY3QpIHtcbiAgbGV0IGZyYW1lID0gZXh0ZW5kKHt9LCBvYmplY3QpO1xuICBmcmFtZS5fcGFyZW50ID0gb2JqZWN0O1xuICByZXR1cm4gZnJhbWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBibG9ja1BhcmFtcyhwYXJhbXMsIGlkcykge1xuICBwYXJhbXMucGF0aCA9IGlkcztcbiAgcmV0dXJuIHBhcmFtcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZENvbnRleHRQYXRoKGNvbnRleHRQYXRoLCBpZCkge1xuICByZXR1cm4gKGNvbnRleHRQYXRoID8gY29udGV4dFBhdGggKyAnLicgOiAnJykgKyBpZDtcbn1cbiJdfQ== +; +define('handlebars/exception',['exports', 'module'], function (exports, module) { + 'use strict'; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var loc = node && node.loc, + line = undefined, + column = undefined; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (Object.defineProperty) { + Object.defineProperty(this, 'column', { value: column }); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } + } + + Exception.prototype = new Error(); + + module.exports = Exception; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2V4Y2VwdGlvbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxNQUFNLFVBQVUsR0FBRyxDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDOztBQUVuRyxXQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQ2hDLFFBQUksR0FBRyxHQUFHLElBQUksSUFBSSxJQUFJLENBQUMsR0FBRztRQUN0QixJQUFJLFlBQUE7UUFDSixNQUFNLFlBQUEsQ0FBQztBQUNYLFFBQUksR0FBRyxFQUFFO0FBQ1AsVUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO0FBQ3RCLFlBQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQzs7QUFFMUIsYUFBTyxJQUFJLEtBQUssR0FBRyxJQUFJLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztLQUN4Qzs7QUFFRCxRQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDOzs7QUFHMUQsU0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUU7QUFDaEQsVUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztLQUM5Qzs7O0FBR0QsUUFBSSxLQUFLLENBQUMsaUJBQWlCLEVBQUU7QUFDM0IsV0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztLQUMxQzs7QUFFRCxRQUFJO0FBQ0YsVUFBSSxHQUFHLEVBQUU7QUFDUCxZQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQzs7OztBQUl2QixZQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUU7QUFDekIsZ0JBQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFDO1NBQ3hELE1BQU07QUFDTCxjQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztTQUN0QjtPQUNGO0tBQ0YsQ0FBQyxPQUFPLEdBQUcsRUFBRTs7S0FFYjtHQUNGOztBQUVELFdBQVMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQzs7bUJBRW5CLFNBQVMiLCJmaWxlIjoiZXhjZXB0aW9uLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5jb25zdCBlcnJvclByb3BzID0gWydkZXNjcmlwdGlvbicsICdmaWxlTmFtZScsICdsaW5lTnVtYmVyJywgJ21lc3NhZ2UnLCAnbmFtZScsICdudW1iZXInLCAnc3RhY2snXTtcblxuZnVuY3Rpb24gRXhjZXB0aW9uKG1lc3NhZ2UsIG5vZGUpIHtcbiAgbGV0IGxvYyA9IG5vZGUgJiYgbm9kZS5sb2MsXG4gICAgICBsaW5lLFxuICAgICAgY29sdW1uO1xuICBpZiAobG9jKSB7XG4gICAgbGluZSA9IGxvYy5zdGFydC5saW5lO1xuICAgIGNvbHVtbiA9IGxvYy5zdGFydC5jb2x1bW47XG5cbiAgICBtZXNzYWdlICs9ICcgLSAnICsgbGluZSArICc6JyArIGNvbHVtbjtcbiAgfVxuXG4gIGxldCB0bXAgPSBFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IuY2FsbCh0aGlzLCBtZXNzYWdlKTtcblxuICAvLyBVbmZvcnR1bmF0ZWx5IGVycm9ycyBhcmUgbm90IGVudW1lcmFibGUgaW4gQ2hyb21lIChhdCBsZWFzdCksIHNvIGBmb3IgcHJvcCBpbiB0bXBgIGRvZXNuJ3Qgd29yay5cbiAgZm9yIChsZXQgaWR4ID0gMDsgaWR4IDwgZXJyb3JQcm9wcy5sZW5ndGg7IGlkeCsrKSB7XG4gICAgdGhpc1tlcnJvclByb3BzW2lkeF1dID0gdG1wW2Vycm9yUHJvcHNbaWR4XV07XG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBFeGNlcHRpb24pO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAobG9jKSB7XG4gICAgICB0aGlzLmxpbmVOdW1iZXIgPSBsaW5lO1xuXG4gICAgICAvLyBXb3JrIGFyb3VuZCBpc3N1ZSB1bmRlciBzYWZhcmkgd2hlcmUgd2UgY2FuJ3QgZGlyZWN0bHkgc2V0IHRoZSBjb2x1bW4gdmFsdWVcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnY29sdW1uJywge3ZhbHVlOiBjb2x1bW59KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY29sdW1uID0gY29sdW1uO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAobm9wKSB7XG4gICAgLyogSWdub3JlIGlmIHRoZSBicm93c2VyIGlzIHZlcnkgcGFydGljdWxhciAqL1xuICB9XG59XG5cbkV4Y2VwdGlvbi5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTtcblxuZXhwb3J0IGRlZmF1bHQgRXhjZXB0aW9uO1xuIl19 +; +define('handlebars/helpers/block-helper-missing',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('blockHelperMissing', function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvYmxvY2staGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3ZFLFVBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPO1VBQ3pCLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDOztBQUVwQixVQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUU7QUFDcEIsZUFBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDakIsTUFBTSxJQUFJLE9BQU8sS0FBSyxLQUFLLElBQUksT0FBTyxJQUFJLElBQUksRUFBRTtBQUMvQyxlQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUN0QixNQUFNLElBQUksT0FYeUIsT0FBTyxDQVd4QixPQUFPLENBQUMsRUFBRTtBQUMzQixZQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0FBQ3RCLGNBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUNmLG1CQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1dBQzlCOztBQUVELGlCQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztTQUNoRCxNQUFNO0FBQ0wsaUJBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3RCO09BQ0YsTUFBTTtBQUNMLFlBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO0FBQy9CLGNBQUksSUFBSSxHQUFHLE9BdkJRLFdBQVcsQ0F1QlAsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JDLGNBQUksQ0FBQyxXQUFXLEdBQUcsT0F4Qm5CLGlCQUFpQixDQXdCb0IsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzdFLGlCQUFPLEdBQUcsRUFBQyxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUM7U0FDeEI7O0FBRUQsZUFBTyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO09BQzdCO0tBQ0YsQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiYmxvY2staGVscGVyLW1pc3NpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBjcmVhdGVGcmFtZSwgaXNBcnJheX0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignYmxvY2tIZWxwZXJNaXNzaW5nJywgZnVuY3Rpb24oY29udGV4dCwgb3B0aW9ucykge1xuICAgIGxldCBpbnZlcnNlID0gb3B0aW9ucy5pbnZlcnNlLFxuICAgICAgICBmbiA9IG9wdGlvbnMuZm47XG5cbiAgICBpZiAoY29udGV4dCA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIGZuKHRoaXMpO1xuICAgIH0gZWxzZSBpZiAoY29udGV4dCA9PT0gZmFsc2UgfHwgY29udGV4dCA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gaW52ZXJzZSh0aGlzKTtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkoY29udGV4dCkpIHtcbiAgICAgIGlmIChjb250ZXh0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgICAgICAgb3B0aW9ucy5pZHMgPSBbb3B0aW9ucy5uYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbnN0YW5jZS5oZWxwZXJzLmVhY2goY29udGV4dCwgb3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gaW52ZXJzZSh0aGlzKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLmlkcykge1xuICAgICAgICBsZXQgZGF0YSA9IGNyZWF0ZUZyYW1lKG9wdGlvbnMuZGF0YSk7XG4gICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBhcHBlbmRDb250ZXh0UGF0aChvcHRpb25zLmRhdGEuY29udGV4dFBhdGgsIG9wdGlvbnMubmFtZSk7XG4gICAgICAgIG9wdGlvbnMgPSB7ZGF0YTogZGF0YX07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCBvcHRpb25zKTtcbiAgICB9XG4gIH0pO1xufVxuIl19 +; +define('handlebars/helpers/each',['exports', 'module', '../utils', '../exception'], function (exports, module, _utils, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + module.exports = function (instance) { + instance.registerHelper('each', function (context, options) { + if (!options) { + throw new _Exception['default']('Must pass iterator to #each'); + } + + var fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data = undefined, + contextPath = undefined; + + if (options.data && options.ids) { + contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (_utils.isFunction(context)) { + context = context.call(this); + } + + if (options.data) { + data = _utils.createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (_utils.isArray(context)) { + for (var j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + var priorKey = undefined; + + for (var key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvZWFjaC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7bUJBR2UsVUFBUyxRQUFRLEVBQUU7QUFDaEMsWUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFVBQUksQ0FBQyxPQUFPLEVBQUU7QUFDWixjQUFNLDBCQUFjLDZCQUE2QixDQUFDLENBQUM7T0FDcEQ7O0FBRUQsVUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUU7VUFDZixPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU87VUFDekIsQ0FBQyxHQUFHLENBQUM7VUFDTCxHQUFHLEdBQUcsRUFBRTtVQUNSLElBQUksWUFBQTtVQUNKLFdBQVcsWUFBQSxDQUFDOztBQUVoQixVQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUMvQixtQkFBVyxHQUFHLE9BakJaLGlCQUFpQixDQWlCYSxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO09BQ2pGOztBQUVELFVBQUksT0FwQnNELFVBQVUsQ0FvQnJELE9BQU8sQ0FBQyxFQUFFO0FBQUUsZUFBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7T0FBRTs7QUFFMUQsVUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFO0FBQ2hCLFlBQUksR0FBRyxPQXZCMkIsV0FBVyxDQXVCMUIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ2xDOztBQUVELGVBQVMsYUFBYSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO0FBQ3pDLFlBQUksSUFBSSxFQUFFO0FBQ1IsY0FBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFDakIsY0FBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7QUFDbkIsY0FBSSxDQUFDLEtBQUssR0FBRyxLQUFLLEtBQUssQ0FBQyxDQUFDO0FBQ3pCLGNBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQzs7QUFFbkIsY0FBSSxXQUFXLEVBQUU7QUFDZixnQkFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLEdBQUcsS0FBSyxDQUFDO1dBQ3hDO1NBQ0Y7O0FBRUQsV0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO0FBQzdCLGNBQUksRUFBRSxJQUFJO0FBQ1YscUJBQVcsRUFBRSxPQXhDTSxXQUFXLENBd0NMLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxHQUFHLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUMvRSxDQUFDLENBQUM7T0FDSjs7QUFFRCxVQUFJLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7QUFDMUMsWUFBSSxPQTdDMkMsT0FBTyxDQTZDMUMsT0FBTyxDQUFDLEVBQUU7QUFDcEIsZUFBSyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDdkMsZ0JBQUksQ0FBQyxJQUFJLE9BQU8sRUFBRTtBQUNoQiwyQkFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7YUFDL0M7V0FDRjtTQUNGLE1BQU07QUFDTCxjQUFJLFFBQVEsWUFBQSxDQUFDOztBQUViLGVBQUssSUFBSSxHQUFHLElBQUksT0FBTyxFQUFFO0FBQ3ZCLGdCQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUU7Ozs7QUFJL0Isa0JBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQiw2QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7ZUFDaEM7QUFDRCxzQkFBUSxHQUFHLEdBQUcsQ0FBQztBQUNmLGVBQUMsRUFBRSxDQUFDO2FBQ0w7V0FDRjtBQUNELGNBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQix5QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1dBQ3RDO1NBQ0Y7T0FDRjs7QUFFRCxVQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7QUFDWCxXQUFHLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ3JCOztBQUVELGFBQU8sR0FBRyxDQUFDO0tBQ1osQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiZWFjaC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXBwZW5kQ29udGV4dFBhdGgsIGJsb2NrUGFyYW1zLCBjcmVhdGVGcmFtZSwgaXNBcnJheSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuLi9leGNlcHRpb24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignZWFjaCcsIGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ011c3QgcGFzcyBpdGVyYXRvciB0byAjZWFjaCcpO1xuICAgIH1cblxuICAgIGxldCBmbiA9IG9wdGlvbnMuZm4sXG4gICAgICAgIGludmVyc2UgPSBvcHRpb25zLmludmVyc2UsXG4gICAgICAgIGkgPSAwLFxuICAgICAgICByZXQgPSAnJyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29udGV4dFBhdGg7XG5cbiAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICBjb250ZXh0UGF0aCA9IGFwcGVuZENvbnRleHRQYXRoKG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aCwgb3B0aW9ucy5pZHNbMF0pICsgJy4nO1xuICAgIH1cblxuICAgIGlmIChpc0Z1bmN0aW9uKGNvbnRleHQpKSB7IGNvbnRleHQgPSBjb250ZXh0LmNhbGwodGhpcyk7IH1cblxuICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4ZWNJdGVyYXRpb24oZmllbGQsIGluZGV4LCBsYXN0KSB7XG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICBkYXRhLmtleSA9IGZpZWxkO1xuICAgICAgICBkYXRhLmluZGV4ID0gaW5kZXg7XG4gICAgICAgIGRhdGEuZmlyc3QgPSBpbmRleCA9PT0gMDtcbiAgICAgICAgZGF0YS5sYXN0ID0gISFsYXN0O1xuXG4gICAgICAgIGlmIChjb250ZXh0UGF0aCkge1xuICAgICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBjb250ZXh0UGF0aCArIGZpZWxkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldCA9IHJldCArIGZuKGNvbnRleHRbZmllbGRdLCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dFtmaWVsZF0sIGZpZWxkXSwgW2NvbnRleHRQYXRoICsgZmllbGQsIG51bGxdKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoaXNBcnJheShjb250ZXh0KSkge1xuICAgICAgICBmb3IgKGxldCBqID0gY29udGV4dC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcbiAgICAgICAgICBpZiAoaSBpbiBjb250ZXh0KSB7XG4gICAgICAgICAgICBleGVjSXRlcmF0aW9uKGksIGksIGkgPT09IGNvbnRleHQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcHJpb3JLZXk7XG5cbiAgICAgICAgZm9yIChsZXQga2V5IGluIGNvbnRleHQpIHtcbiAgICAgICAgICBpZiAoY29udGV4dC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBydW5uaW5nIHRoZSBpdGVyYXRpb25zIG9uZSBzdGVwIG91dCBvZiBzeW5jIHNvIHdlIGNhbiBkZXRlY3RcbiAgICAgICAgICAgIC8vIHRoZSBsYXN0IGl0ZXJhdGlvbiB3aXRob3V0IGhhdmUgdG8gc2NhbiB0aGUgb2JqZWN0IHR3aWNlIGFuZCBjcmVhdGVcbiAgICAgICAgICAgIC8vIGFuIGl0ZXJtZWRpYXRlIGtleXMgYXJyYXkuXG4gICAgICAgICAgICBpZiAocHJpb3JLZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmlvcktleSA9IGtleTtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByaW9yS2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgcmV0ID0gaW52ZXJzZSh0aGlzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/helper-missing',['exports', 'module', '../exception'], function (exports, module, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + module.exports = function (instance) { + instance.registerHelper('helperMissing', function () /* [args, ]options */{ + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new _Exception['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsZUFBZSxFQUFFLGlDQUFnQztBQUN2RSxVQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFOztBQUUxQixlQUFPLFNBQVMsQ0FBQztPQUNsQixNQUFNOztBQUVMLGNBQU0sMEJBQWMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO09BQ3ZGO0tBQ0YsQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiaGVscGVyLW1pc3NpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdoZWxwZXJNaXNzaW5nJywgZnVuY3Rpb24oLyogW2FyZ3MsIF1vcHRpb25zICovKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIC8vIEEgbWlzc2luZyBmaWVsZCBpbiBhIHt7Zm9vfX0gY29uc3RydWN0LlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU29tZW9uZSBpcyBhY3R1YWxseSB0cnlpbmcgdG8gY2FsbCBzb21ldGhpbmcsIGJsb3cgdXAuXG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdNaXNzaW5nIGhlbHBlcjogXCInICsgYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXS5uYW1lICsgJ1wiJyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/if',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('if', function (conditional, options) { + if (_utils.isFunction(conditional)) { + conditional = conditional.call(this); + } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function (conditional, options) { + return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaWYuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVMsV0FBVyxFQUFFLE9BQU8sRUFBRTtBQUMzRCxVQUFJLE9BSlMsVUFBVSxDQUlSLFdBQVcsQ0FBQyxFQUFFO0FBQUUsbUJBQVcsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQUU7Ozs7O0FBS3RFLFVBQUksQUFBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxJQUFLLE9BVC9DLE9BQU8sQ0FTZ0QsV0FBVyxDQUFDLEVBQUU7QUFDdkUsZUFBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQzlCLE1BQU07QUFDTCxlQUFPLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDekI7S0FDRixDQUFDLENBQUM7O0FBRUgsWUFBUSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsVUFBUyxXQUFXLEVBQUUsT0FBTyxFQUFFO0FBQy9ELGFBQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQztLQUN2SCxDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJpZi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aXNFbXB0eSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignaWYnLCBmdW5jdGlvbihjb25kaXRpb25hbCwgb3B0aW9ucykge1xuICAgIGlmIChpc0Z1bmN0aW9uKGNvbmRpdGlvbmFsKSkgeyBjb25kaXRpb25hbCA9IGNvbmRpdGlvbmFsLmNhbGwodGhpcyk7IH1cblxuICAgIC8vIERlZmF1bHQgYmVoYXZpb3IgaXMgdG8gcmVuZGVyIHRoZSBwb3NpdGl2ZSBwYXRoIGlmIHRoZSB2YWx1ZSBpcyB0cnV0aHkgYW5kIG5vdCBlbXB0eS5cbiAgICAvLyBUaGUgYGluY2x1ZGVaZXJvYCBvcHRpb24gbWF5IGJlIHNldCB0byB0cmVhdCB0aGUgY29uZHRpb25hbCBhcyBwdXJlbHkgbm90IGVtcHR5IGJhc2VkIG9uIHRoZVxuICAgIC8vIGJlaGF2aW9yIG9mIGlzRW1wdHkuIEVmZmVjdGl2ZWx5IHRoaXMgZGV0ZXJtaW5lcyBpZiAwIGlzIGhhbmRsZWQgYnkgdGhlIHBvc2l0aXZlIHBhdGggb3IgbmVnYXRpdmUuXG4gICAgaWYgKCghb3B0aW9ucy5oYXNoLmluY2x1ZGVaZXJvICYmICFjb25kaXRpb25hbCkgfHwgaXNFbXB0eShjb25kaXRpb25hbCkpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmZuKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3VubGVzcycsIGZ1bmN0aW9uKGNvbmRpdGlvbmFsLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGluc3RhbmNlLmhlbHBlcnNbJ2lmJ10uY2FsbCh0aGlzLCBjb25kaXRpb25hbCwge2ZuOiBvcHRpb25zLmludmVyc2UsIGludmVyc2U6IG9wdGlvbnMuZm4sIGhhc2g6IG9wdGlvbnMuaGFzaH0pO1xuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/log',['exports', 'module'], function (exports, module) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('log', function () /* message, options */{ + var args = [undefined], + options = arguments[arguments.length - 1]; + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + var level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log.apply(instance, args); + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFBZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxrQ0FBaUM7QUFDOUQsVUFBSSxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUM7VUFDbEIsT0FBTyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQzlDLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM3QyxZQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO09BQ3pCOztBQUVELFVBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztBQUNkLFVBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFO0FBQzlCLGFBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztPQUM1QixNQUFNLElBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUU7QUFDckQsYUFBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO09BQzVCO0FBQ0QsVUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQzs7QUFFaEIsY0FBUSxDQUFDLEdBQUcsTUFBQSxDQUFaLFFBQVEsRUFBUyxJQUFJLENBQUMsQ0FBQztLQUN4QixDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJsb2cuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignbG9nJywgZnVuY3Rpb24oLyogbWVzc2FnZSwgb3B0aW9ucyAqLykge1xuICAgIGxldCBhcmdzID0gW3VuZGVmaW5lZF0sXG4gICAgICAgIG9wdGlvbnMgPSBhcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aCAtIDFdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgYXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gICAgfVxuXG4gICAgbGV0IGxldmVsID0gMTtcbiAgICBpZiAob3B0aW9ucy5oYXNoLmxldmVsICE9IG51bGwpIHtcbiAgICAgIGxldmVsID0gb3B0aW9ucy5oYXNoLmxldmVsO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuZGF0YS5sZXZlbCAhPSBudWxsKSB7XG4gICAgICBsZXZlbCA9IG9wdGlvbnMuZGF0YS5sZXZlbDtcbiAgICB9XG4gICAgYXJnc1swXSA9IGxldmVsO1xuXG4gICAgaW5zdGFuY2UubG9nKC4uLiBhcmdzKTtcbiAgfSk7XG59XG4iXX0= +; +define('handlebars/helpers/lookup',['exports', 'module'], function (exports, module) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('lookup', function (obj, field) { + return obj && obj[field]; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9va3VwLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFBZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxVQUFTLEdBQUcsRUFBRSxLQUFLLEVBQUU7QUFDckQsYUFBTyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQzFCLENBQUMsQ0FBQztHQUNKIiwiZmlsZSI6Imxvb2t1cC5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdsb29rdXAnLCBmdW5jdGlvbihvYmosIGZpZWxkKSB7XG4gICAgcmV0dXJuIG9iaiAmJiBvYmpbZmllbGRdO1xuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/with',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('with', function (context, options) { + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvd2l0aC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7bUJBRWUsVUFBUyxRQUFRLEVBQUU7QUFDaEMsWUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFVBQUksT0FKc0QsVUFBVSxDQUlyRCxPQUFPLENBQUMsRUFBRTtBQUFFLGVBQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQUU7O0FBRTFELFVBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUM7O0FBRXBCLFVBQUksQ0FBQyxPQVI0QyxPQUFPLENBUTNDLE9BQU8sQ0FBQyxFQUFFO0FBQ3JCLFlBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUFDeEIsWUFBSSxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7QUFDL0IsY0FBSSxHQUFHLE9BWHlCLFdBQVcsQ0FXeEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2pDLGNBQUksQ0FBQyxXQUFXLEdBQUcsT0FabkIsaUJBQWlCLENBWW9CLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoRjs7QUFFRCxlQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUU7QUFDakIsY0FBSSxFQUFFLElBQUk7QUFDVixxQkFBVyxFQUFFLE9BakJNLFdBQVcsQ0FpQkwsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDaEUsQ0FBQyxDQUFDO09BQ0osTUFBTTtBQUNMLGVBQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUM5QjtLQUNGLENBQUMsQ0FBQztHQUNKIiwiZmlsZSI6IndpdGguanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBibG9ja1BhcmFtcywgY3JlYXRlRnJhbWUsIGlzRW1wdHksIGlzRnVuY3Rpb259IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oaW5zdGFuY2UpIHtcbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3dpdGgnLCBmdW5jdGlvbihjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24oY29udGV4dCkpIHsgY29udGV4dCA9IGNvbnRleHQuY2FsbCh0aGlzKTsgfVxuXG4gICAgbGV0IGZuID0gb3B0aW9ucy5mbjtcblxuICAgIGlmICghaXNFbXB0eShjb250ZXh0KSkge1xuICAgICAgbGV0IGRhdGEgPSBvcHRpb25zLmRhdGE7XG4gICAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgICAgICBkYXRhLmNvbnRleHRQYXRoID0gYXBwZW5kQ29udGV4dFBhdGgob3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoLCBvcHRpb25zLmlkc1swXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dF0sIFtkYXRhICYmIGRhdGEuY29udGV4dFBhdGhdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers',['exports', './helpers/block-helper-missing', './helpers/each', './helpers/helper-missing', './helpers/if', './helpers/log', './helpers/lookup', './helpers/with'], function (exports, _helpersBlockHelperMissing, _helpersEach, _helpersHelperMissing, _helpersIf, _helpersLog, _helpersLookup, _helpersWith) { + 'use strict'; + + exports.__esModule = true; + exports.registerDefaultHelpers = registerDefaultHelpers; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _registerBlockHelperMissing = _interopRequireDefault(_helpersBlockHelperMissing); + + var _registerEach = _interopRequireDefault(_helpersEach); + + var _registerHelperMissing = _interopRequireDefault(_helpersHelperMissing); + + var _registerIf = _interopRequireDefault(_helpersIf); + + var _registerLog = _interopRequireDefault(_helpersLog); + + var _registerLookup = _interopRequireDefault(_helpersLookup); + + var _registerWith = _interopRequireDefault(_helpersWith); + + function registerDefaultHelpers(instance) { + _registerBlockHelperMissing['default'](instance); + _registerEach['default'](instance); + _registerHelperMissing['default'](instance); + _registerIf['default'](instance); + _registerLog['default'](instance); + _registerLookup['default'](instance); + _registerWith['default'](instance); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRTyxXQUFTLHNCQUFzQixDQUFDLFFBQVEsRUFBRTtBQUMvQywyQ0FBMkIsUUFBUSxDQUFDLENBQUM7QUFDckMsNkJBQWEsUUFBUSxDQUFDLENBQUM7QUFDdkIsc0NBQXNCLFFBQVEsQ0FBQyxDQUFDO0FBQ2hDLDJCQUFXLFFBQVEsQ0FBQyxDQUFDO0FBQ3JCLDRCQUFZLFFBQVEsQ0FBQyxDQUFDO0FBQ3RCLCtCQUFlLFFBQVEsQ0FBQyxDQUFDO0FBQ3pCLDZCQUFhLFFBQVEsQ0FBQyxDQUFDO0dBQ3hCIiwiZmlsZSI6ImhlbHBlcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcmVnaXN0ZXJCbG9ja0hlbHBlck1pc3NpbmcgZnJvbSAnLi9oZWxwZXJzL2Jsb2NrLWhlbHBlci1taXNzaW5nJztcbmltcG9ydCByZWdpc3RlckVhY2ggZnJvbSAnLi9oZWxwZXJzL2VhY2gnO1xuaW1wb3J0IHJlZ2lzdGVySGVscGVyTWlzc2luZyBmcm9tICcuL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcnO1xuaW1wb3J0IHJlZ2lzdGVySWYgZnJvbSAnLi9oZWxwZXJzL2lmJztcbmltcG9ydCByZWdpc3RlckxvZyBmcm9tICcuL2hlbHBlcnMvbG9nJztcbmltcG9ydCByZWdpc3Rlckxvb2t1cCBmcm9tICcuL2hlbHBlcnMvbG9va3VwJztcbmltcG9ydCByZWdpc3RlcldpdGggZnJvbSAnLi9oZWxwZXJzL3dpdGgnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0SGVscGVycyhpbnN0YW5jZSkge1xuICByZWdpc3RlckJsb2NrSGVscGVyTWlzc2luZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyRWFjaChpbnN0YW5jZSk7XG4gIHJlZ2lzdGVySGVscGVyTWlzc2luZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVySWYoaW5zdGFuY2UpO1xuICByZWdpc3RlckxvZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyTG9va3VwKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJXaXRoKGluc3RhbmNlKTtcbn1cbiJdfQ== +; +define('handlebars/decorators/inline',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerDecorator('inline', function (fn, props, container, options) { + var ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function (context, options) { + // Create a new partials stack frame prior to exec. + var original = container.partials; + container.partials = _utils.extend({}, original, props.partials); + var ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMvaW5saW5lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFFZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFVBQVMsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFO0FBQzNFLFVBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNiLFVBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFO0FBQ25CLGFBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLFdBQUcsR0FBRyxVQUFTLE9BQU8sRUFBRSxPQUFPLEVBQUU7O0FBRS9CLGNBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUM7QUFDbEMsbUJBQVMsQ0FBQyxRQUFRLEdBQUcsT0FWckIsTUFBTSxDQVVzQixFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMxRCxjQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9CLG1CQUFTLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUM5QixpQkFBTyxHQUFHLENBQUM7U0FDWixDQUFDO09BQ0g7O0FBRUQsV0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsQ0FBQzs7QUFFN0MsYUFBTyxHQUFHLENBQUM7S0FDWixDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJpbmxpbmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2V4dGVuZH0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckRlY29yYXRvcignaW5saW5lJywgZnVuY3Rpb24oZm4sIHByb3BzLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICBsZXQgcmV0ID0gZm47XG4gICAgaWYgKCFwcm9wcy5wYXJ0aWFscykge1xuICAgICAgcHJvcHMucGFydGlhbHMgPSB7fTtcbiAgICAgIHJldCA9IGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHBhcnRpYWxzIHN0YWNrIGZyYW1lIHByaW9yIHRvIGV4ZWMuXG4gICAgICAgIGxldCBvcmlnaW5hbCA9IGNvbnRhaW5lci5wYXJ0aWFscztcbiAgICAgICAgY29udGFpbmVyLnBhcnRpYWxzID0gZXh0ZW5kKHt9LCBvcmlnaW5hbCwgcHJvcHMucGFydGlhbHMpO1xuICAgICAgICBsZXQgcmV0ID0gZm4oY29udGV4dCwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IG9yaWdpbmFsO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBwcm9wcy5wYXJ0aWFsc1tvcHRpb25zLmFyZ3NbMF1dID0gb3B0aW9ucy5mbjtcblxuICAgIHJldHVybiByZXQ7XG4gIH0pO1xufVxuIl19 +; +define('handlebars/decorators',['exports', './decorators/inline'], function (exports, _decoratorsInline) { + 'use strict'; + + exports.__esModule = true; + exports.registerDefaultDecorators = registerDefaultDecorators; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _registerInline = _interopRequireDefault(_decoratorsInline); + + function registerDefaultDecorators(instance) { + _registerInline['default'](instance); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFFTyxXQUFTLHlCQUF5QixDQUFDLFFBQVEsRUFBRTtBQUNsRCwrQkFBZSxRQUFRLENBQUMsQ0FBQztHQUMxQiIsImZpbGUiOiJkZWNvcmF0b3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZ2lzdGVySW5saW5lIGZyb20gJy4vZGVjb3JhdG9ycy9pbmxpbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0RGVjb3JhdG9ycyhpbnN0YW5jZSkge1xuICByZWdpc3RlcklubGluZShpbnN0YW5jZSk7XG59XG5cbiJdfQ== +; +define('handlebars/logger',['exports', 'module', './utils'], function (exports, module, _utils) { + 'use strict'; + + var logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function lookupLevel(level) { + if (typeof level === 'string') { + var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function log(level) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + var method = logger.methodMap[level]; + if (!console[method]) { + // eslint-disable-line no-console + method = 'log'; + } + + for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + message[_key - 1] = arguments[_key]; + } + + console[method].apply(console, message); // eslint-disable-line no-console + } + } + }; + + module.exports = logger; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2xvZ2dlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxNQUFJLE1BQU0sR0FBRztBQUNYLGFBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQztBQUM3QyxTQUFLLEVBQUUsTUFBTTs7O0FBR2IsZUFBVyxFQUFFLHFCQUFTLEtBQUssRUFBRTtBQUMzQixVQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtBQUM3QixZQUFJLFFBQVEsR0FBRyxPQVRiLE9BQU8sQ0FTYyxNQUFNLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzlELFlBQUksUUFBUSxJQUFJLENBQUMsRUFBRTtBQUNqQixlQUFLLEdBQUcsUUFBUSxDQUFDO1NBQ2xCLE1BQU07QUFDTCxlQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztTQUM3QjtPQUNGOztBQUVELGFBQU8sS0FBSyxDQUFDO0tBQ2Q7OztBQUdELE9BQUcsRUFBRSxhQUFTLEtBQUssRUFBYztBQUMvQixXQUFLLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQzs7QUFFbEMsVUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxFQUFFO0FBQy9FLFlBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDckMsWUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTs7QUFDcEIsZ0JBQU0sR0FBRyxLQUFLLENBQUM7U0FDaEI7OzBDQVBtQixPQUFPO0FBQVAsaUJBQU87OztBQVEzQixlQUFPLENBQUMsTUFBTSxPQUFDLENBQWYsT0FBTyxFQUFZLE9BQU8sQ0FBQyxDQUFDO09BQzdCO0tBQ0Y7R0FDRixDQUFDOzttQkFFYSxNQUFNIiwiZmlsZSI6ImxvZ2dlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aW5kZXhPZn0gZnJvbSAnLi91dGlscyc7XG5cbmxldCBsb2dnZXIgPSB7XG4gIG1ldGhvZE1hcDogWydkZWJ1ZycsICdpbmZvJywgJ3dhcm4nLCAnZXJyb3InXSxcbiAgbGV2ZWw6ICdpbmZvJyxcblxuICAvLyBNYXBzIGEgZ2l2ZW4gbGV2ZWwgdmFsdWUgdG8gdGhlIGBtZXRob2RNYXBgIGluZGV4ZXMgYWJvdmUuXG4gIGxvb2t1cExldmVsOiBmdW5jdGlvbihsZXZlbCkge1xuICAgIGlmICh0eXBlb2YgbGV2ZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBsZXQgbGV2ZWxNYXAgPSBpbmRleE9mKGxvZ2dlci5tZXRob2RNYXAsIGxldmVsLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgaWYgKGxldmVsTWFwID49IDApIHtcbiAgICAgICAgbGV2ZWwgPSBsZXZlbE1hcDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldmVsID0gcGFyc2VJbnQobGV2ZWwsIDEwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGV2ZWw7XG4gIH0sXG5cbiAgLy8gQ2FuIGJlIG92ZXJyaWRkZW4gaW4gdGhlIGhvc3QgZW52aXJvbm1lbnRcbiAgbG9nOiBmdW5jdGlvbihsZXZlbCwgLi4ubWVzc2FnZSkge1xuICAgIGxldmVsID0gbG9nZ2VyLmxvb2t1cExldmVsKGxldmVsKTtcblxuICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbG9nZ2VyLmxvb2t1cExldmVsKGxvZ2dlci5sZXZlbCkgPD0gbGV2ZWwpIHtcbiAgICAgIGxldCBtZXRob2QgPSBsb2dnZXIubWV0aG9kTWFwW2xldmVsXTtcbiAgICAgIGlmICghY29uc29sZVttZXRob2RdKSB7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG4gICAgICAgIG1ldGhvZCA9ICdsb2cnO1xuICAgICAgfVxuICAgICAgY29uc29sZVttZXRob2RdKC4uLm1lc3NhZ2UpOyAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IGxvZ2dlcjtcbiJdfQ== +; +define('handlebars/base',['exports', './utils', './exception', './helpers', './decorators', './logger'], function (exports, _utils, _exception, _helpers, _decorators, _logger) { + 'use strict'; + + exports.__esModule = true; + exports.HandlebarsEnvironment = HandlebarsEnvironment; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _logger2 = _interopRequireDefault(_logger); + + var VERSION = '4.0.6'; + exports.VERSION = VERSION; + var COMPILER_REVISION = 7; + + exports.COMPILER_REVISION = COMPILER_REVISION; + var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '== 1.x.x', + 5: '== 2.0.0-alpha.x', + 6: '>= 2.0.0-beta.1', + 7: '>= 4.0.0' + }; + + exports.REVISION_CHANGES = REVISION_CHANGES; + var objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + _helpers.registerDefaultHelpers(this); + _decorators.registerDefaultDecorators(this); + } + + HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: _logger2['default'], + log: _logger2['default'].log, + + registerHelper: function registerHelper(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _Exception['default']('Arg not supported with multiple helpers'); + } + _utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function unregisterHelper(name) { + delete this.helpers[name]; + }, + + registerPartial: function registerPartial(name, partial) { + if (_utils.toString.call(name) === objectType) { + _utils.extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new _Exception['default']('Attempting to register a partial called "' + name + '" as undefined'); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function unregisterPartial(name) { + delete this.partials[name]; + }, + + registerDecorator: function registerDecorator(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _Exception['default']('Arg not supported with multiple decorators'); + } + _utils.extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function unregisterDecorator(name) { + delete this.decorators[name]; + } + }; + + var log = _logger2['default'].log; + + exports.log = log; + exports.createFrame = _utils.createFrame; + exports.logger = _logger2['default']; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQU1PLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQzs7QUFDeEIsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7OztBQUU1QixNQUFNLGdCQUFnQixHQUFHO0FBQzlCLEtBQUMsRUFBRSxhQUFhO0FBQ2hCLEtBQUMsRUFBRSxlQUFlO0FBQ2xCLEtBQUMsRUFBRSxlQUFlO0FBQ2xCLEtBQUMsRUFBRSxVQUFVO0FBQ2IsS0FBQyxFQUFFLGtCQUFrQjtBQUNyQixLQUFDLEVBQUUsaUJBQWlCO0FBQ3BCLEtBQUMsRUFBRSxVQUFVO0dBQ2QsQ0FBQzs7O0FBRUYsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUM7O0FBRTlCLFdBQVMscUJBQXFCLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUU7QUFDbkUsUUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO0FBQzdCLFFBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztBQUMvQixRQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsSUFBSSxFQUFFLENBQUM7O0FBRW5DLGFBeEJNLHNCQUFzQixDQXdCTCxJQUFJLENBQUMsQ0FBQztBQUM3QixnQkF4Qk0seUJBQXlCLENBd0JMLElBQUksQ0FBQyxDQUFDO0dBQ2pDOztBQUVELHVCQUFxQixDQUFDLFNBQVMsR0FBRztBQUNoQyxlQUFXLEVBQUUscUJBQXFCOztBQUVsQyxVQUFNLHFCQUFRO0FBQ2QsT0FBRyxFQUFFLG9CQUFPLEdBQUc7O0FBRWYsa0JBQWMsRUFBRSx3QkFBUyxJQUFJLEVBQUUsRUFBRSxFQUFFO0FBQ2pDLFVBQUksT0FyQ3FCLFFBQVEsQ0FxQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxVQUFVLEVBQUU7QUFDdEMsWUFBSSxFQUFFLEVBQUU7QUFBRSxnQkFBTSwwQkFBYyx5Q0FBeUMsQ0FBQyxDQUFDO1NBQUU7QUFDM0UsZUF2Q2UsTUFBTSxDQXVDZCxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO09BQzVCLE1BQU07QUFDTCxZQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztPQUN6QjtLQUNGO0FBQ0Qsb0JBQWdCLEVBQUUsMEJBQVMsSUFBSSxFQUFFO0FBQy9CLGFBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUMzQjs7QUFFRCxtQkFBZSxFQUFFLHlCQUFTLElBQUksRUFBRSxPQUFPLEVBQUU7QUFDdkMsVUFBSSxPQWpEcUIsUUFBUSxDQWlEcEIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLFVBQVUsRUFBRTtBQUN0QyxlQWxEZSxNQUFNLENBa0RkLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7T0FDN0IsTUFBTTtBQUNMLFlBQUksT0FBTyxPQUFPLEtBQUssV0FBVyxFQUFFO0FBQ2xDLGdCQUFNLHdFQUEwRCxJQUFJLG9CQUFpQixDQUFDO1NBQ3ZGO0FBQ0QsWUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUM7T0FDL0I7S0FDRjtBQUNELHFCQUFpQixFQUFFLDJCQUFTLElBQUksRUFBRTtBQUNoQyxhQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDNUI7O0FBRUQscUJBQWlCLEVBQUUsMkJBQVMsSUFBSSxFQUFFLEVBQUUsRUFBRTtBQUNwQyxVQUFJLE9BL0RxQixRQUFRLENBK0RwQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssVUFBVSxFQUFFO0FBQ3RDLFlBQUksRUFBRSxFQUFFO0FBQUUsZ0JBQU0sMEJBQWMsNENBQTRDLENBQUMsQ0FBQztTQUFFO0FBQzlFLGVBakVlLE1BQU0sQ0FpRWQsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztPQUMvQixNQUFNO0FBQ0wsWUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7T0FDNUI7S0FDRjtBQUNELHVCQUFtQixFQUFFLDZCQUFTLElBQUksRUFBRTtBQUNsQyxhQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDOUI7R0FDRixDQUFDOztBQUVLLE1BQUksR0FBRyxHQUFHLG9CQUFPLEdBQUcsQ0FBQzs7O1VBRXBCLFdBQVcsVUE3RVgsV0FBVztVQTZFRSxNQUFNIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2NyZWF0ZUZyYW1lLCBleHRlbmQsIHRvU3RyaW5nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi9leGNlcHRpb24nO1xuaW1wb3J0IHtyZWdpc3RlckRlZmF1bHRIZWxwZXJzfSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtyZWdpc3RlckRlZmF1bHREZWNvcmF0b3JzfSBmcm9tICcuL2RlY29yYXRvcnMnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuL2xvZ2dlcic7XG5cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gJzQuMC42JztcbmV4cG9ydCBjb25zdCBDT01QSUxFUl9SRVZJU0lPTiA9IDc7XG5cbmV4cG9ydCBjb25zdCBSRVZJU0lPTl9DSEFOR0VTID0ge1xuICAxOiAnPD0gMS4wLnJjLjInLCAvLyAxLjAucmMuMiBpcyBhY3R1YWxseSByZXYyIGJ1dCBkb2Vzbid0IHJlcG9ydCBpdFxuICAyOiAnPT0gMS4wLjAtcmMuMycsXG4gIDM6ICc9PSAxLjAuMC1yYy40JyxcbiAgNDogJz09IDEueC54JyxcbiAgNTogJz09IDIuMC4wLWFscGhhLngnLFxuICA2OiAnPj0gMi4wLjAtYmV0YS4xJyxcbiAgNzogJz49IDQuMC4wJ1xufTtcblxuY29uc3Qgb2JqZWN0VHlwZSA9ICdbb2JqZWN0IE9iamVjdF0nO1xuXG5leHBvcnQgZnVuY3Rpb24gSGFuZGxlYmFyc0Vudmlyb25tZW50KGhlbHBlcnMsIHBhcnRpYWxzLCBkZWNvcmF0b3JzKSB7XG4gIHRoaXMuaGVscGVycyA9IGhlbHBlcnMgfHwge307XG4gIHRoaXMucGFydGlhbHMgPSBwYXJ0aWFscyB8fCB7fTtcbiAgdGhpcy5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycyB8fCB7fTtcblxuICByZWdpc3RlckRlZmF1bHRIZWxwZXJzKHRoaXMpO1xuICByZWdpc3RlckRlZmF1bHREZWNvcmF0b3JzKHRoaXMpO1xufVxuXG5IYW5kbGViYXJzRW52aXJvbm1lbnQucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogSGFuZGxlYmFyc0Vudmlyb25tZW50LFxuXG4gIGxvZ2dlcjogbG9nZ2VyLFxuICBsb2c6IGxvZ2dlci5sb2csXG5cbiAgcmVnaXN0ZXJIZWxwZXI6IGZ1bmN0aW9uKG5hbWUsIGZuKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGlmIChmbikgeyB0aHJvdyBuZXcgRXhjZXB0aW9uKCdBcmcgbm90IHN1cHBvcnRlZCB3aXRoIG11bHRpcGxlIGhlbHBlcnMnKTsgfVxuICAgICAgZXh0ZW5kKHRoaXMuaGVscGVycywgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGVscGVyc1tuYW1lXSA9IGZuO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlckhlbHBlcjogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLmhlbHBlcnNbbmFtZV07XG4gIH0sXG5cbiAgcmVnaXN0ZXJQYXJ0aWFsOiBmdW5jdGlvbihuYW1lLCBwYXJ0aWFsKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGV4dGVuZCh0aGlzLnBhcnRpYWxzLCBuYW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGVvZiBwYXJ0aWFsID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKGBBdHRlbXB0aW5nIHRvIHJlZ2lzdGVyIGEgcGFydGlhbCBjYWxsZWQgXCIke25hbWV9XCIgYXMgdW5kZWZpbmVkYCk7XG4gICAgICB9XG4gICAgICB0aGlzLnBhcnRpYWxzW25hbWVdID0gcGFydGlhbDtcbiAgICB9XG4gIH0sXG4gIHVucmVnaXN0ZXJQYXJ0aWFsOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMucGFydGlhbHNbbmFtZV07XG4gIH0sXG5cbiAgcmVnaXN0ZXJEZWNvcmF0b3I6IGZ1bmN0aW9uKG5hbWUsIGZuKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGlmIChmbikgeyB0aHJvdyBuZXcgRXhjZXB0aW9uKCdBcmcgbm90IHN1cHBvcnRlZCB3aXRoIG11bHRpcGxlIGRlY29yYXRvcnMnKTsgfVxuICAgICAgZXh0ZW5kKHRoaXMuZGVjb3JhdG9ycywgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVjb3JhdG9yc1tuYW1lXSA9IGZuO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlckRlY29yYXRvcjogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLmRlY29yYXRvcnNbbmFtZV07XG4gIH1cbn07XG5cbmV4cG9ydCBsZXQgbG9nID0gbG9nZ2VyLmxvZztcblxuZXhwb3J0IHtjcmVhdGVGcmFtZSwgbG9nZ2VyfTtcbiJdfQ== +; +define('handlebars/safe-string',['exports', 'module'], function (exports, module) { + // Build out our basic SafeString type + 'use strict'; + + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = SafeString.prototype.toHTML = function () { + return '' + this.string; + }; + + module.exports = SafeString; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3NhZmUtc3RyaW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFDQSxXQUFTLFVBQVUsQ0FBQyxNQUFNLEVBQUU7QUFDMUIsUUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7R0FDdEI7O0FBRUQsWUFBVSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsWUFBVztBQUN2RSxXQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0dBQ3pCLENBQUM7O21CQUVhLFVBQVUiLCJmaWxlIjoic2FmZS1zdHJpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBCdWlsZCBvdXQgb3VyIGJhc2ljIFNhZmVTdHJpbmcgdHlwZVxuZnVuY3Rpb24gU2FmZVN0cmluZyhzdHJpbmcpIHtcbiAgdGhpcy5zdHJpbmcgPSBzdHJpbmc7XG59XG5cblNhZmVTdHJpbmcucHJvdG90eXBlLnRvU3RyaW5nID0gU2FmZVN0cmluZy5wcm90b3R5cGUudG9IVE1MID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAnJyArIHRoaXMuc3RyaW5nO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgU2FmZVN0cmluZztcbiJdfQ== +; +define('handlebars/runtime',['exports', './utils', './exception', './base'], function (exports, _utils, _exception, _base) { + 'use strict'; + + exports.__esModule = true; + exports.checkRevision = checkRevision; + exports.template = template; + exports.wrapProgram = wrapProgram; + exports.resolvePartial = resolvePartial; + exports.invokePartial = invokePartial; + exports.noop = noop; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function checkRevision(compilerInfo) { + var compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = _base.COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = _base.REVISION_CHANGES[currentRevision], + compilerVersions = _base.REVISION_CHANGES[compilerRevision]; + throw new _Exception['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new _Exception['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } + } + + function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new _Exception['default']('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new _Exception['default']('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = _utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + var result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + var lines = result.split('\n'); + for (var i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new _Exception['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + var container = { + strict: function strict(obj, name) { + if (!(name in obj)) { + throw new _Exception['default']('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function lookup(depths, name) { + var len = depths.length; + for (var i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function lambda(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: _utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function fn(i) { + var ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function program(i, data, declaredBlockParams, blockParams, depths) { + var programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function data(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function merge(param, common) { + var obj = param || common; + + if (param && common && param !== common) { + obj = _utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function (options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function (i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new _Exception['default']('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new _Exception['default']('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; + } + + function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; + } + + function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + var data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; + } + + function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + var partialBlock = undefined; + if (options.fn && options.fn !== noop) { + options.data = _base.createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = _utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new _Exception['default']('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } + } + + function noop() { + return ''; + } + + function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? _base.createFrame(data) : {}; + data.root = context; + } + return data; + } + + function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + var props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + _utils.extend(prog, props); + } + return prog; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3J1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUlPLFdBQVMsYUFBYSxDQUFDLFlBQVksRUFBRTtBQUMxQyxRQUFNLGdCQUFnQixHQUFHLFlBQVksSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUN2RCxlQUFlLFNBSmQsaUJBQWlCLEFBSWlCLENBQUM7O0FBRTFDLFFBQUksZ0JBQWdCLEtBQUssZUFBZSxFQUFFO0FBQ3hDLFVBQUksZ0JBQWdCLEdBQUcsZUFBZSxFQUFFO0FBQ3RDLFlBQU0sZUFBZSxHQUFHLE1BUkYsZ0JBQWdCLENBUUcsZUFBZSxDQUFDO1lBQ25ELGdCQUFnQixHQUFHLE1BVEgsZ0JBQWdCLENBU0ksZ0JBQWdCLENBQUMsQ0FBQztBQUM1RCxjQUFNLDBCQUFjLHlGQUF5RixHQUN2RyxxREFBcUQsR0FBRyxlQUFlLEdBQUcsbURBQW1ELEdBQUcsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDaEssTUFBTTs7QUFFTCxjQUFNLDBCQUFjLHdGQUF3RixHQUN0RyxpREFBaUQsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDbkY7S0FDRjtHQUNGOztBQUVNLFdBQVMsUUFBUSxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7O0FBRTFDLFFBQUksQ0FBQyxHQUFHLEVBQUU7QUFDUixZQUFNLDBCQUFjLG1DQUFtQyxDQUFDLENBQUM7S0FDMUQ7QUFDRCxRQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRTtBQUN2QyxZQUFNLDBCQUFjLDJCQUEyQixHQUFHLE9BQU8sWUFBWSxDQUFDLENBQUM7S0FDeEU7O0FBRUQsZ0JBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUM7Ozs7QUFJbEQsT0FBRyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDOztBQUU1QyxhQUFTLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3ZELFVBQUksT0FBTyxDQUFDLElBQUksRUFBRTtBQUNoQixlQUFPLEdBQUcsT0FBTSxNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDbEQsWUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO0FBQ2YsaUJBQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO1NBQ3ZCO09BQ0Y7O0FBRUQsYUFBTyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztBQUN0RSxVQUFJLE1BQU0sR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7O0FBRXhFLFVBQUksTUFBTSxJQUFJLElBQUksSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFO0FBQ2pDLGVBQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDekYsY0FBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztPQUMzRDtBQUNELFVBQUksTUFBTSxJQUFJLElBQUksRUFBRTtBQUNsQixZQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUU7QUFDbEIsY0FBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMvQixlQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQzVDLGdCQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFO0FBQzVCLG9CQUFNO2FBQ1A7O0FBRUQsaUJBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztXQUN0QztBQUNELGdCQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMzQjtBQUNELGVBQU8sTUFBTSxDQUFDO09BQ2YsTUFBTTtBQUNMLGNBQU0sMEJBQWMsY0FBYyxHQUFHLE9BQU8sQ0FBQyxJQUFJLEdBQUcsMERBQTBELENBQUMsQ0FBQztPQUNqSDtLQUNGOzs7QUFHRCxRQUFJLFNBQVMsR0FBRztBQUNkLFlBQU0sRUFBRSxnQkFBUyxHQUFHLEVBQUUsSUFBSSxFQUFFO0FBQzFCLFlBQUksRUFBRSxJQUFJLElBQUksR0FBRyxDQUFBLEFBQUMsRUFBRTtBQUNsQixnQkFBTSwwQkFBYyxHQUFHLEdBQUcsSUFBSSxHQUFHLG1CQUFtQixHQUFHLEdBQUcsQ0FBQyxDQUFDO1NBQzdEO0FBQ0QsZUFBTyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDbEI7QUFDRCxZQUFNLEVBQUUsZ0JBQVMsTUFBTSxFQUFFLElBQUksRUFBRTtBQUM3QixZQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0FBQzFCLGFBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDNUIsY0FBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRTtBQUN4QyxtQkFBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7V0FDeEI7U0FDRjtPQUNGO0FBQ0QsWUFBTSxFQUFFLGdCQUFTLE9BQU8sRUFBRSxPQUFPLEVBQUU7QUFDakMsZUFBTyxPQUFPLE9BQU8sS0FBSyxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUM7T0FDeEU7O0FBRUQsc0JBQWdCLEVBQUUsT0FBTSxnQkFBZ0I7QUFDeEMsbUJBQWEsRUFBRSxvQkFBb0I7O0FBRW5DLFFBQUUsRUFBRSxZQUFTLENBQUMsRUFBRTtBQUNkLFlBQUksR0FBRyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxQixXQUFHLENBQUMsU0FBUyxHQUFHLFlBQVksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDdkMsZUFBTyxHQUFHLENBQUM7T0FDWjs7QUFFRCxjQUFRLEVBQUUsRUFBRTtBQUNaLGFBQU8sRUFBRSxpQkFBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUU7QUFDbkUsWUFBSSxjQUFjLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDakMsRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDcEIsWUFBSSxJQUFJLElBQUksTUFBTSxJQUFJLFdBQVcsSUFBSSxtQkFBbUIsRUFBRTtBQUN4RCx3QkFBYyxHQUFHLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzNGLE1BQU0sSUFBSSxDQUFDLGNBQWMsRUFBRTtBQUMxQix3QkFBYyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDOUQ7QUFDRCxlQUFPLGNBQWMsQ0FBQztPQUN2Qjs7QUFFRCxVQUFJLEVBQUUsY0FBUyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQzNCLGVBQU8sS0FBSyxJQUFJLEtBQUssRUFBRSxFQUFFO0FBQ3ZCLGVBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1NBQ3ZCO0FBQ0QsZUFBTyxLQUFLLENBQUM7T0FDZDtBQUNELFdBQUssRUFBRSxlQUFTLEtBQUssRUFBRSxNQUFNLEVBQUU7QUFDN0IsWUFBSSxHQUFHLEdBQUcsS0FBSyxJQUFJLE1BQU0sQ0FBQzs7QUFFMUIsWUFBSSxLQUFLLElBQUksTUFBTSxJQUFLLEtBQUssS0FBSyxNQUFNLEFBQUMsRUFBRTtBQUN6QyxhQUFHLEdBQUcsT0FBTSxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN2Qzs7QUFFRCxlQUFPLEdBQUcsQ0FBQztPQUNaOztBQUVELFVBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUk7QUFDakIsa0JBQVksRUFBRSxZQUFZLENBQUMsUUFBUTtLQUNwQyxDQUFDOztBQUVGLGFBQVMsR0FBRyxDQUFDLE9BQU8sRUFBZ0I7VUFBZCxPQUFPLHlEQUFHLEVBQUU7O0FBQ2hDLFVBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7O0FBRXhCLFNBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDcEIsVUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLElBQUksWUFBWSxDQUFDLE9BQU8sRUFBRTtBQUM1QyxZQUFJLEdBQUcsUUFBUSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztPQUNoQztBQUNELFVBQUksTUFBTSxZQUFBO1VBQ04sV0FBVyxHQUFHLFlBQVksQ0FBQyxjQUFjLEdBQUcsRUFBRSxHQUFHLFNBQVMsQ0FBQztBQUMvRCxVQUFJLFlBQVksQ0FBQyxTQUFTLEVBQUU7QUFDMUIsWUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFO0FBQ2xCLGdCQUFNLEdBQUcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7U0FDM0YsTUFBTTtBQUNMLGdCQUFNLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNwQjtPQUNGOztBQUVELGVBQVMsSUFBSSxDQUFDLE9BQU8sZ0JBQWU7QUFDbEMsZUFBTyxFQUFFLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO09BQ3JIO0FBQ0QsVUFBSSxHQUFHLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFDdEcsYUFBTyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0tBQy9CO0FBQ0QsT0FBRyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7O0FBRWpCLE9BQUcsQ0FBQyxNQUFNLEdBQUcsVUFBUyxPQUFPLEVBQUU7QUFDN0IsVUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUU7QUFDcEIsaUJBQVMsQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQzs7QUFFbEUsWUFBSSxZQUFZLENBQUMsVUFBVSxFQUFFO0FBQzNCLG1CQUFTLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDdEU7QUFDRCxZQUFJLFlBQVksQ0FBQyxVQUFVLElBQUksWUFBWSxDQUFDLGFBQWEsRUFBRTtBQUN6RCxtQkFBUyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQzVFO09BQ0YsTUFBTTtBQUNMLGlCQUFTLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7QUFDcEMsaUJBQVMsQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztBQUN0QyxpQkFBUyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO09BQzNDO0tBQ0YsQ0FBQzs7QUFFRixPQUFHLENBQUMsTUFBTSxHQUFHLFVBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFO0FBQ2xELFVBQUksWUFBWSxDQUFDLGNBQWMsSUFBSSxDQUFDLFdBQVcsRUFBRTtBQUMvQyxjQUFNLDBCQUFjLHdCQUF3QixDQUFDLENBQUM7T0FDL0M7QUFDRCxVQUFJLFlBQVksQ0FBQyxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUU7QUFDckMsY0FBTSwwQkFBYyx5QkFBeUIsQ0FBQyxDQUFDO09BQ2hEOztBQUVELGFBQU8sV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQ2pGLENBQUM7QUFDRixXQUFPLEdBQUcsQ0FBQztHQUNaOztBQUVNLFdBQVMsV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFO0FBQzVGLGFBQVMsSUFBSSxDQUFDLE9BQU8sRUFBZ0I7VUFBZCxPQUFPLHlEQUFHLEVBQUU7O0FBQ2pDLFVBQUksYUFBYSxHQUFHLE1BQU0sQ0FBQztBQUMzQixVQUFJLE1BQU0sSUFBSSxPQUFPLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFO0FBQ2xDLHFCQUFhLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7T0FDMUM7O0FBRUQsYUFBTyxFQUFFLENBQUMsU0FBUyxFQUNmLE9BQU8sRUFDUCxTQUFTLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxRQUFRLEVBQ3JDLE9BQU8sQ0FBQyxJQUFJLElBQUksSUFBSSxFQUNwQixXQUFXLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUN4RCxhQUFhLENBQUMsQ0FBQztLQUNwQjs7QUFFRCxRQUFJLEdBQUcsaUJBQWlCLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQzs7QUFFekUsUUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFDakIsUUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFDeEMsUUFBSSxDQUFDLFdBQVcsR0FBRyxtQkFBbUIsSUFBSSxDQUFDLENBQUM7QUFDNUMsV0FBTyxJQUFJLENBQUM7R0FDYjs7QUFFTSxXQUFTLGNBQWMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRTtBQUN4RCxRQUFJLENBQUMsT0FBTyxFQUFFO0FBQ1osVUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLGdCQUFnQixFQUFFO0FBQ3JDLFlBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUFDeEIsZUFBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssSUFBSSxFQUFFO0FBQ3JDLGNBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1NBQ3JCO0FBQ0QsZUFBTyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUNoQyxZQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsSUFBSSxDQUFDO09BQzlCLE1BQU07QUFDTCxlQUFPLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDMUM7S0FDRixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRTs7QUFFekMsYUFBTyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7QUFDdkIsYUFBTyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7S0FDckM7QUFDRCxXQUFPLE9BQU8sQ0FBQztHQUNoQjs7QUFFTSxXQUFTLGFBQWEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRTtBQUN2RCxXQUFPLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztBQUN2QixRQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7QUFDZixhQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO0tBQ3ZFOztBQUVELFFBQUksWUFBWSxZQUFBLENBQUM7QUFDakIsUUFBSSxPQUFPLENBQUMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssSUFBSSxFQUFFO0FBQ3JDLGFBQU8sQ0FBQyxJQUFJLEdBQUcsTUEzTzJCLFdBQVcsQ0EyTzFCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN6QyxrQkFBWSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsQ0FBQzs7QUFFMUQsVUFBSSxZQUFZLENBQUMsUUFBUSxFQUFFO0FBQ3pCLGVBQU8sQ0FBQyxRQUFRLEdBQUcsT0FBTSxNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO09BQzlFO0tBQ0Y7O0FBRUQsUUFBSSxPQUFPLEtBQUssU0FBUyxJQUFJLFlBQVksRUFBRTtBQUN6QyxhQUFPLEdBQUcsWUFBWSxDQUFDO0tBQ3hCOztBQUVELFFBQUksT0FBTyxLQUFLLFNBQVMsRUFBRTtBQUN6QixZQUFNLDBCQUFjLGNBQWMsR0FBRyxPQUFPLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDLENBQUM7S0FDNUUsTUFBTSxJQUFJLE9BQU8sWUFBWSxRQUFRLEVBQUU7QUFDdEMsYUFBTyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0tBQ2xDO0dBQ0Y7O0FBRU0sV0FBUyxJQUFJLEdBQUc7QUFBRSxXQUFPLEVBQUUsQ0FBQztHQUFFOztBQUVyQyxXQUFTLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQy9CLFFBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxNQUFNLElBQUksSUFBSSxDQUFBLEFBQUMsRUFBRTtBQUM5QixVQUFJLEdBQUcsSUFBSSxHQUFHLE1BbFE0QixXQUFXLENBa1EzQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDckMsVUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7S0FDckI7QUFDRCxXQUFPLElBQUksQ0FBQztHQUNiOztBQUVELFdBQVMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7QUFDekUsUUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFO0FBQ2hCLFVBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztBQUNmLFVBQUksR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUM1RixhQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDM0I7QUFDRCxXQUFPLElBQUksQ0FBQztHQUNiIiwiZmlsZSI6InJ1bnRpbWUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBVdGlscyBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi9leGNlcHRpb24nO1xuaW1wb3J0IHsgQ09NUElMRVJfUkVWSVNJT04sIFJFVklTSU9OX0NIQU5HRVMsIGNyZWF0ZUZyYW1lIH0gZnJvbSAnLi9iYXNlJztcblxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrUmV2aXNpb24oY29tcGlsZXJJbmZvKSB7XG4gIGNvbnN0IGNvbXBpbGVyUmV2aXNpb24gPSBjb21waWxlckluZm8gJiYgY29tcGlsZXJJbmZvWzBdIHx8IDEsXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbiA9IENPTVBJTEVSX1JFVklTSU9OO1xuXG4gIGlmIChjb21waWxlclJldmlzaW9uICE9PSBjdXJyZW50UmV2aXNpb24pIHtcbiAgICBpZiAoY29tcGlsZXJSZXZpc2lvbiA8IGN1cnJlbnRSZXZpc2lvbikge1xuICAgICAgY29uc3QgcnVudGltZVZlcnNpb25zID0gUkVWSVNJT05fQ0hBTkdFU1tjdXJyZW50UmV2aXNpb25dLFxuICAgICAgICAgICAgY29tcGlsZXJWZXJzaW9ucyA9IFJFVklTSU9OX0NIQU5HRVNbY29tcGlsZXJSZXZpc2lvbl07XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUZW1wbGF0ZSB3YXMgcHJlY29tcGlsZWQgd2l0aCBhbiBvbGRlciB2ZXJzaW9uIG9mIEhhbmRsZWJhcnMgdGhhbiB0aGUgY3VycmVudCBydW50aW1lLiAnICtcbiAgICAgICAgICAgICdQbGVhc2UgdXBkYXRlIHlvdXIgcHJlY29tcGlsZXIgdG8gYSBuZXdlciB2ZXJzaW9uICgnICsgcnVudGltZVZlcnNpb25zICsgJykgb3IgZG93bmdyYWRlIHlvdXIgcnVudGltZSB0byBhbiBvbGRlciB2ZXJzaW9uICgnICsgY29tcGlsZXJWZXJzaW9ucyArICcpLicpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBVc2UgdGhlIGVtYmVkZGVkIHZlcnNpb24gaW5mbyBzaW5jZSB0aGUgcnVudGltZSBkb2Vzbid0IGtub3cgYWJvdXQgdGhpcyByZXZpc2lvbiB5ZXRcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1RlbXBsYXRlIHdhcyBwcmVjb21waWxlZCB3aXRoIGEgbmV3ZXIgdmVyc2lvbiBvZiBIYW5kbGViYXJzIHRoYW4gdGhlIGN1cnJlbnQgcnVudGltZS4gJyArXG4gICAgICAgICAgICAnUGxlYXNlIHVwZGF0ZSB5b3VyIHJ1bnRpbWUgdG8gYSBuZXdlciB2ZXJzaW9uICgnICsgY29tcGlsZXJJbmZvWzFdICsgJykuJyk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0ZW1wbGF0ZSh0ZW1wbGF0ZVNwZWMsIGVudikge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAoIWVudikge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ05vIGVudmlyb25tZW50IHBhc3NlZCB0byB0ZW1wbGF0ZScpO1xuICB9XG4gIGlmICghdGVtcGxhdGVTcGVjIHx8ICF0ZW1wbGF0ZVNwZWMubWFpbikge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdGVtcGxhdGUgb2JqZWN0OiAnICsgdHlwZW9mIHRlbXBsYXRlU3BlYyk7XG4gIH1cblxuICB0ZW1wbGF0ZVNwZWMubWFpbi5kZWNvcmF0b3IgPSB0ZW1wbGF0ZVNwZWMubWFpbl9kO1xuXG4gIC8vIE5vdGU6IFVzaW5nIGVudi5WTSByZWZlcmVuY2VzIHJhdGhlciB0aGFuIGxvY2FsIHZhciByZWZlcmVuY2VzIHRocm91Z2hvdXQgdGhpcyBzZWN0aW9uIHRvIGFsbG93XG4gIC8vIGZvciBleHRlcm5hbCB1c2VycyB0byBvdmVycmlkZSB0aGVzZSBhcyBwc3VlZG8tc3VwcG9ydGVkIEFQSXMuXG4gIGVudi5WTS5jaGVja1JldmlzaW9uKHRlbXBsYXRlU3BlYy5jb21waWxlcik7XG5cbiAgZnVuY3Rpb24gaW52b2tlUGFydGlhbFdyYXBwZXIocGFydGlhbCwgY29udGV4dCwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmhhc2gpIHtcbiAgICAgIGNvbnRleHQgPSBVdGlscy5leHRlbmQoe30sIGNvbnRleHQsIG9wdGlvbnMuaGFzaCk7XG4gICAgICBpZiAob3B0aW9ucy5pZHMpIHtcbiAgICAgICAgb3B0aW9ucy5pZHNbMF0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHBhcnRpYWwgPSBlbnYuVk0ucmVzb2x2ZVBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKTtcbiAgICBsZXQgcmVzdWx0ID0gZW52LlZNLmludm9rZVBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKTtcblxuICAgIGlmIChyZXN1bHQgPT0gbnVsbCAmJiBlbnYuY29tcGlsZSkge1xuICAgICAgb3B0aW9ucy5wYXJ0aWFsc1tvcHRpb25zLm5hbWVdID0gZW52LmNvbXBpbGUocGFydGlhbCwgdGVtcGxhdGVTcGVjLmNvbXBpbGVyT3B0aW9ucywgZW52KTtcbiAgICAgIHJlc3VsdCA9IG9wdGlvbnMucGFydGlhbHNbb3B0aW9ucy5uYW1lXShjb250ZXh0LCBvcHRpb25zKTtcbiAgICB9XG4gICAgaWYgKHJlc3VsdCAhPSBudWxsKSB7XG4gICAgICBpZiAob3B0aW9ucy5pbmRlbnQpIHtcbiAgICAgICAgbGV0IGxpbmVzID0gcmVzdWx0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBsaW5lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICBpZiAoIWxpbmVzW2ldICYmIGkgKyAxID09PSBsKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsaW5lc1tpXSA9IG9wdGlvbnMuaW5kZW50ICsgbGluZXNbaV07XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0ID0gbGluZXMuam9pbignXFxuJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUaGUgcGFydGlhbCAnICsgb3B0aW9ucy5uYW1lICsgJyBjb3VsZCBub3QgYmUgY29tcGlsZWQgd2hlbiBydW5uaW5nIGluIHJ1bnRpbWUtb25seSBtb2RlJyk7XG4gICAgfVxuICB9XG5cbiAgLy8gSnVzdCBhZGQgd2F0ZXJcbiAgbGV0IGNvbnRhaW5lciA9IHtcbiAgICBzdHJpY3Q6IGZ1bmN0aW9uKG9iaiwgbmFtZSkge1xuICAgICAgaWYgKCEobmFtZSBpbiBvYmopKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1wiJyArIG5hbWUgKyAnXCIgbm90IGRlZmluZWQgaW4gJyArIG9iaik7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqW25hbWVdO1xuICAgIH0sXG4gICAgbG9va3VwOiBmdW5jdGlvbihkZXB0aHMsIG5hbWUpIHtcbiAgICAgIGNvbnN0IGxlbiA9IGRlcHRocy5sZW5ndGg7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmIChkZXB0aHNbaV0gJiYgZGVwdGhzW2ldW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gZGVwdGhzW2ldW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBsYW1iZGE6IGZ1bmN0aW9uKGN1cnJlbnQsIGNvbnRleHQpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgY3VycmVudCA9PT0gJ2Z1bmN0aW9uJyA/IGN1cnJlbnQuY2FsbChjb250ZXh0KSA6IGN1cnJlbnQ7XG4gICAgfSxcblxuICAgIGVzY2FwZUV4cHJlc3Npb246IFV0aWxzLmVzY2FwZUV4cHJlc3Npb24sXG4gICAgaW52b2tlUGFydGlhbDogaW52b2tlUGFydGlhbFdyYXBwZXIsXG5cbiAgICBmbjogZnVuY3Rpb24oaSkge1xuICAgICAgbGV0IHJldCA9IHRlbXBsYXRlU3BlY1tpXTtcbiAgICAgIHJldC5kZWNvcmF0b3IgPSB0ZW1wbGF0ZVNwZWNbaSArICdfZCddO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9LFxuXG4gICAgcHJvZ3JhbXM6IFtdLFxuICAgIHByb2dyYW06IGZ1bmN0aW9uKGksIGRhdGEsIGRlY2xhcmVkQmxvY2tQYXJhbXMsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcbiAgICAgIGxldCBwcm9ncmFtV3JhcHBlciA9IHRoaXMucHJvZ3JhbXNbaV0sXG4gICAgICAgICAgZm4gPSB0aGlzLmZuKGkpO1xuICAgICAgaWYgKGRhdGEgfHwgZGVwdGhzIHx8IGJsb2NrUGFyYW1zIHx8IGRlY2xhcmVkQmxvY2tQYXJhbXMpIHtcbiAgICAgICAgcHJvZ3JhbVdyYXBwZXIgPSB3cmFwUHJvZ3JhbSh0aGlzLCBpLCBmbiwgZGF0YSwgZGVjbGFyZWRCbG9ja1BhcmFtcywgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gICAgICB9IGVsc2UgaWYgKCFwcm9ncmFtV3JhcHBlcikge1xuICAgICAgICBwcm9ncmFtV3JhcHBlciA9IHRoaXMucHJvZ3JhbXNbaV0gPSB3cmFwUHJvZ3JhbSh0aGlzLCBpLCBmbik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvZ3JhbVdyYXBwZXI7XG4gICAgfSxcblxuICAgIGRhdGE6IGZ1bmN0aW9uKHZhbHVlLCBkZXB0aCkge1xuICAgICAgd2hpbGUgKHZhbHVlICYmIGRlcHRoLS0pIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5fcGFyZW50O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sXG4gICAgbWVyZ2U6IGZ1bmN0aW9uKHBhcmFtLCBjb21tb24pIHtcbiAgICAgIGxldCBvYmogPSBwYXJhbSB8fCBjb21tb247XG5cbiAgICAgIGlmIChwYXJhbSAmJiBjb21tb24gJiYgKHBhcmFtICE9PSBjb21tb24pKSB7XG4gICAgICAgIG9iaiA9IFV0aWxzLmV4dGVuZCh7fSwgY29tbW9uLCBwYXJhbSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmo7XG4gICAgfSxcblxuICAgIG5vb3A6IGVudi5WTS5ub29wLFxuICAgIGNvbXBpbGVySW5mbzogdGVtcGxhdGVTcGVjLmNvbXBpbGVyXG4gIH07XG5cbiAgZnVuY3Rpb24gcmV0KGNvbnRleHQsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBkYXRhID0gb3B0aW9ucy5kYXRhO1xuXG4gICAgcmV0Ll9zZXR1cChvcHRpb25zKTtcbiAgICBpZiAoIW9wdGlvbnMucGFydGlhbCAmJiB0ZW1wbGF0ZVNwZWMudXNlRGF0YSkge1xuICAgICAgZGF0YSA9IGluaXREYXRhKGNvbnRleHQsIGRhdGEpO1xuICAgIH1cbiAgICBsZXQgZGVwdGhzLFxuICAgICAgICBibG9ja1BhcmFtcyA9IHRlbXBsYXRlU3BlYy51c2VCbG9ja1BhcmFtcyA/IFtdIDogdW5kZWZpbmVkO1xuICAgIGlmICh0ZW1wbGF0ZVNwZWMudXNlRGVwdGhzKSB7XG4gICAgICBpZiAob3B0aW9ucy5kZXB0aHMpIHtcbiAgICAgICAgZGVwdGhzID0gY29udGV4dCAhPSBvcHRpb25zLmRlcHRoc1swXSA/IFtjb250ZXh0XS5jb25jYXQob3B0aW9ucy5kZXB0aHMpIDogb3B0aW9ucy5kZXB0aHM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZXB0aHMgPSBbY29udGV4dF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFpbihjb250ZXh0LyosIG9wdGlvbnMqLykge1xuICAgICAgcmV0dXJuICcnICsgdGVtcGxhdGVTcGVjLm1haW4oY29udGFpbmVyLCBjb250ZXh0LCBjb250YWluZXIuaGVscGVycywgY29udGFpbmVyLnBhcnRpYWxzLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgICB9XG4gICAgbWFpbiA9IGV4ZWN1dGVEZWNvcmF0b3JzKHRlbXBsYXRlU3BlYy5tYWluLCBtYWluLCBjb250YWluZXIsIG9wdGlvbnMuZGVwdGhzIHx8IFtdLCBkYXRhLCBibG9ja1BhcmFtcyk7XG4gICAgcmV0dXJuIG1haW4oY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cbiAgcmV0LmlzVG9wID0gdHJ1ZTtcblxuICByZXQuX3NldHVwID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucy5wYXJ0aWFsKSB7XG4gICAgICBjb250YWluZXIuaGVscGVycyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLmhlbHBlcnMsIGVudi5oZWxwZXJzKTtcblxuICAgICAgaWYgKHRlbXBsYXRlU3BlYy51c2VQYXJ0aWFsKSB7XG4gICAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLnBhcnRpYWxzLCBlbnYucGFydGlhbHMpO1xuICAgICAgfVxuICAgICAgaWYgKHRlbXBsYXRlU3BlYy51c2VQYXJ0aWFsIHx8IHRlbXBsYXRlU3BlYy51c2VEZWNvcmF0b3JzKSB7XG4gICAgICAgIGNvbnRhaW5lci5kZWNvcmF0b3JzID0gY29udGFpbmVyLm1lcmdlKG9wdGlvbnMuZGVjb3JhdG9ycywgZW52LmRlY29yYXRvcnMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb250YWluZXIuaGVscGVycyA9IG9wdGlvbnMuaGVscGVycztcbiAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IG9wdGlvbnMucGFydGlhbHM7XG4gICAgICBjb250YWluZXIuZGVjb3JhdG9ycyA9IG9wdGlvbnMuZGVjb3JhdG9ycztcbiAgICB9XG4gIH07XG5cbiAgcmV0Ll9jaGlsZCA9IGZ1bmN0aW9uKGksIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZUJsb2NrUGFyYW1zICYmICFibG9ja1BhcmFtcykge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignbXVzdCBwYXNzIGJsb2NrIHBhcmFtcycpO1xuICAgIH1cbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZURlcHRocyAmJiAhZGVwdGhzKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdtdXN0IHBhc3MgcGFyZW50IGRlcHRocycpO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwUHJvZ3JhbShjb250YWluZXIsIGksIHRlbXBsYXRlU3BlY1tpXSwgZGF0YSwgMCwgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gIH07XG4gIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cmFwUHJvZ3JhbShjb250YWluZXIsIGksIGZuLCBkYXRhLCBkZWNsYXJlZEJsb2NrUGFyYW1zLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gIGZ1bmN0aW9uIHByb2coY29udGV4dCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgbGV0IGN1cnJlbnREZXB0aHMgPSBkZXB0aHM7XG4gICAgaWYgKGRlcHRocyAmJiBjb250ZXh0ICE9IGRlcHRoc1swXSkge1xuICAgICAgY3VycmVudERlcHRocyA9IFtjb250ZXh0XS5jb25jYXQoZGVwdGhzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZm4oY29udGFpbmVyLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICBjb250YWluZXIuaGVscGVycywgY29udGFpbmVyLnBhcnRpYWxzLFxuICAgICAgICBvcHRpb25zLmRhdGEgfHwgZGF0YSxcbiAgICAgICAgYmxvY2tQYXJhbXMgJiYgW29wdGlvbnMuYmxvY2tQYXJhbXNdLmNvbmNhdChibG9ja1BhcmFtcyksXG4gICAgICAgIGN1cnJlbnREZXB0aHMpO1xuICB9XG5cbiAgcHJvZyA9IGV4ZWN1dGVEZWNvcmF0b3JzKGZuLCBwcm9nLCBjb250YWluZXIsIGRlcHRocywgZGF0YSwgYmxvY2tQYXJhbXMpO1xuXG4gIHByb2cucHJvZ3JhbSA9IGk7XG4gIHByb2cuZGVwdGggPSBkZXB0aHMgPyBkZXB0aHMubGVuZ3RoIDogMDtcbiAgcHJvZy5ibG9ja1BhcmFtcyA9IGRlY2xhcmVkQmxvY2tQYXJhbXMgfHwgMDtcbiAgcmV0dXJuIHByb2c7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUGFydGlhbChwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKSB7XG4gIGlmICghcGFydGlhbCkge1xuICAgIGlmIChvcHRpb25zLm5hbWUgPT09ICdAcGFydGlhbC1ibG9jaycpIHtcbiAgICAgIGxldCBkYXRhID0gb3B0aW9ucy5kYXRhO1xuICAgICAgd2hpbGUgKGRhdGFbJ3BhcnRpYWwtYmxvY2snXSA9PT0gbm9vcCkge1xuICAgICAgICBkYXRhID0gZGF0YS5fcGFyZW50O1xuICAgICAgfVxuICAgICAgcGFydGlhbCA9IGRhdGFbJ3BhcnRpYWwtYmxvY2snXTtcbiAgICAgIGRhdGFbJ3BhcnRpYWwtYmxvY2snXSA9IG5vb3A7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcnRpYWwgPSBvcHRpb25zLnBhcnRpYWxzW29wdGlvbnMubmFtZV07XG4gICAgfVxuICB9IGVsc2UgaWYgKCFwYXJ0aWFsLmNhbGwgJiYgIW9wdGlvbnMubmFtZSkge1xuICAgIC8vIFRoaXMgaXMgYSBkeW5hbWljIHBhcnRpYWwgdGhhdCByZXR1cm5lZCBhIHN0cmluZ1xuICAgIG9wdGlvbnMubmFtZSA9IHBhcnRpYWw7XG4gICAgcGFydGlhbCA9IG9wdGlvbnMucGFydGlhbHNbcGFydGlhbF07XG4gIH1cbiAgcmV0dXJuIHBhcnRpYWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZva2VQYXJ0aWFsKHBhcnRpYWwsIGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucy5wYXJ0aWFsID0gdHJ1ZTtcbiAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgb3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoID0gb3B0aW9ucy5pZHNbMF0gfHwgb3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoO1xuICB9XG5cbiAgbGV0IHBhcnRpYWxCbG9jaztcbiAgaWYgKG9wdGlvbnMuZm4gJiYgb3B0aW9ucy5mbiAhPT0gbm9vcCkge1xuICAgIG9wdGlvbnMuZGF0YSA9IGNyZWF0ZUZyYW1lKG9wdGlvbnMuZGF0YSk7XG4gICAgcGFydGlhbEJsb2NrID0gb3B0aW9ucy5kYXRhWydwYXJ0aWFsLWJsb2NrJ10gPSBvcHRpb25zLmZuO1xuXG4gICAgaWYgKHBhcnRpYWxCbG9jay5wYXJ0aWFscykge1xuICAgICAgb3B0aW9ucy5wYXJ0aWFscyA9IFV0aWxzLmV4dGVuZCh7fSwgb3B0aW9ucy5wYXJ0aWFscywgcGFydGlhbEJsb2NrLnBhcnRpYWxzKTtcbiAgICB9XG4gIH1cblxuICBpZiAocGFydGlhbCA9PT0gdW5kZWZpbmVkICYmIHBhcnRpYWxCbG9jaykge1xuICAgIHBhcnRpYWwgPSBwYXJ0aWFsQmxvY2s7XG4gIH1cblxuICBpZiAocGFydGlhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVGhlIHBhcnRpYWwgJyArIG9wdGlvbnMubmFtZSArICcgY291bGQgbm90IGJlIGZvdW5kJyk7XG4gIH0gZWxzZSBpZiAocGFydGlhbCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIHBhcnRpYWwoY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5vb3AoKSB7IHJldHVybiAnJzsgfVxuXG5mdW5jdGlvbiBpbml0RGF0YShjb250ZXh0LCBkYXRhKSB7XG4gIGlmICghZGF0YSB8fCAhKCdyb290JyBpbiBkYXRhKSkge1xuICAgIGRhdGEgPSBkYXRhID8gY3JlYXRlRnJhbWUoZGF0YSkgOiB7fTtcbiAgICBkYXRhLnJvb3QgPSBjb250ZXh0O1xuICB9XG4gIHJldHVybiBkYXRhO1xufVxuXG5mdW5jdGlvbiBleGVjdXRlRGVjb3JhdG9ycyhmbiwgcHJvZywgY29udGFpbmVyLCBkZXB0aHMsIGRhdGEsIGJsb2NrUGFyYW1zKSB7XG4gIGlmIChmbi5kZWNvcmF0b3IpIHtcbiAgICBsZXQgcHJvcHMgPSB7fTtcbiAgICBwcm9nID0gZm4uZGVjb3JhdG9yKHByb2csIHByb3BzLCBjb250YWluZXIsIGRlcHRocyAmJiBkZXB0aHNbMF0sIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpO1xuICAgIFV0aWxzLmV4dGVuZChwcm9nLCBwcm9wcyk7XG4gIH1cbiAgcmV0dXJuIHByb2c7XG59XG4iXX0= +; +define('handlebars/no-conflict',['exports', 'module'], function (exports, module) { + /* global window */ + 'use strict'; + + module.exports = function (Handlebars) { + /* istanbul ignore next */ + var root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function () { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL25vLWNvbmZsaWN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7bUJBQ2UsVUFBUyxVQUFVLEVBQUU7O0FBRWxDLFFBQUksSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsR0FBRyxNQUFNLEdBQUcsTUFBTTtRQUN0RCxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQzs7QUFFbEMsY0FBVSxDQUFDLFVBQVUsR0FBRyxZQUFXO0FBQ2pDLFVBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUU7QUFDbEMsWUFBSSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUM7T0FDL0I7QUFDRCxhQUFPLFVBQVUsQ0FBQztLQUNuQixDQUFDO0dBQ0giLCJmaWxlIjoibm8tY29uZmxpY3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBnbG9iYWwgd2luZG93ICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihIYW5kbGViYXJzKSB7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGxldCByb290ID0gdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3csXG4gICAgICAkSGFuZGxlYmFycyA9IHJvb3QuSGFuZGxlYmFycztcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgSGFuZGxlYmFycy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHJvb3QuSGFuZGxlYmFycyA9PT0gSGFuZGxlYmFycykge1xuICAgICAgcm9vdC5IYW5kbGViYXJzID0gJEhhbmRsZWJhcnM7XG4gICAgfVxuICAgIHJldHVybiBIYW5kbGViYXJzO1xuICB9O1xufVxuIl19 +; +define('handlebars.runtime',['exports', 'module', './handlebars/base', './handlebars/safe-string', './handlebars/exception', './handlebars/utils', './handlebars/runtime', './handlebars/no-conflict'], function (exports, module, _handlebarsBase, _handlebarsSafeString, _handlebarsException, _handlebarsUtils, _handlebarsRuntime, _handlebarsNoConflict) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + // Each of these augment the Handlebars object. No need to setup here. + // (This is done to easily share code between commonjs and browse envs) + + var _SafeString = _interopRequireDefault(_handlebarsSafeString); + + var _Exception = _interopRequireDefault(_handlebarsException); + + var _noConflict = _interopRequireDefault(_handlebarsNoConflict); + + // For compatibility and usage outside of module systems, make the Handlebars object a namespace + function create() { + var hb = new _handlebarsBase.HandlebarsEnvironment(); + + _handlebarsUtils.extend(hb, _handlebarsBase); + hb.SafeString = _SafeString['default']; + hb.Exception = _Exception['default']; + hb.Utils = _handlebarsUtils; + hb.escapeExpression = _handlebarsUtils.escapeExpression; + + hb.VM = _handlebarsRuntime; + hb.template = function (spec) { + return _handlebarsRuntime.template(spec, hb); + }; + + return hb; + } + + var inst = create(); + inst.create = create; + + _noConflict['default'](inst); + + inst['default'] = inst; + + module.exports = inst; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLnJ1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFZQSxXQUFTLE1BQU0sR0FBRztBQUNoQixRQUFJLEVBQUUsR0FBRyxJQUFJLGdCQUFLLHFCQUFxQixFQUFFLENBQUM7O0FBRTFDLHFCQUFNLE1BQU0sQ0FBQyxFQUFFLGtCQUFPLENBQUM7QUFDdkIsTUFBRSxDQUFDLFVBQVUseUJBQWEsQ0FBQztBQUMzQixNQUFFLENBQUMsU0FBUyx3QkFBWSxDQUFDO0FBQ3pCLE1BQUUsQ0FBQyxLQUFLLG1CQUFRLENBQUM7QUFDakIsTUFBRSxDQUFDLGdCQUFnQixHQUFHLGlCQUFNLGdCQUFnQixDQUFDOztBQUU3QyxNQUFFLENBQUMsRUFBRSxxQkFBVSxDQUFDO0FBQ2hCLE1BQUUsQ0FBQyxRQUFRLEdBQUcsVUFBUyxJQUFJLEVBQUU7QUFDM0IsYUFBTyxtQkFBUSxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ25DLENBQUM7O0FBRUYsV0FBTyxFQUFFLENBQUM7R0FDWDs7QUFFRCxNQUFJLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQztBQUNwQixNQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7QUFFckIseUJBQVcsSUFBSSxDQUFDLENBQUM7O0FBRWpCLE1BQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7O21CQUVSLElBQUkiLCJmaWxlIjoiaGFuZGxlYmFycy5ydW50aW1lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYmFzZSBmcm9tICcuL2hhbmRsZWJhcnMvYmFzZSc7XG5cbi8vIEVhY2ggb2YgdGhlc2UgYXVnbWVudCB0aGUgSGFuZGxlYmFycyBvYmplY3QuIE5vIG5lZWQgdG8gc2V0dXAgaGVyZS5cbi8vIChUaGlzIGlzIGRvbmUgdG8gZWFzaWx5IHNoYXJlIGNvZGUgYmV0d2VlbiBjb21tb25qcyBhbmQgYnJvd3NlIGVudnMpXG5pbXBvcnQgU2FmZVN0cmluZyBmcm9tICcuL2hhbmRsZWJhcnMvc2FmZS1zdHJpbmcnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuL2hhbmRsZWJhcnMvZXhjZXB0aW9uJztcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gJy4vaGFuZGxlYmFycy91dGlscyc7XG5pbXBvcnQgKiBhcyBydW50aW1lIGZyb20gJy4vaGFuZGxlYmFycy9ydW50aW1lJztcblxuaW1wb3J0IG5vQ29uZmxpY3QgZnJvbSAnLi9oYW5kbGViYXJzL25vLWNvbmZsaWN0JztcblxuLy8gRm9yIGNvbXBhdGliaWxpdHkgYW5kIHVzYWdlIG91dHNpZGUgb2YgbW9kdWxlIHN5c3RlbXMsIG1ha2UgdGhlIEhhbmRsZWJhcnMgb2JqZWN0IGEgbmFtZXNwYWNlXG5mdW5jdGlvbiBjcmVhdGUoKSB7XG4gIGxldCBoYiA9IG5ldyBiYXNlLkhhbmRsZWJhcnNFbnZpcm9ubWVudCgpO1xuXG4gIFV0aWxzLmV4dGVuZChoYiwgYmFzZSk7XG4gIGhiLlNhZmVTdHJpbmcgPSBTYWZlU3RyaW5nO1xuICBoYi5FeGNlcHRpb24gPSBFeGNlcHRpb247XG4gIGhiLlV0aWxzID0gVXRpbHM7XG4gIGhiLmVzY2FwZUV4cHJlc3Npb24gPSBVdGlscy5lc2NhcGVFeHByZXNzaW9uO1xuXG4gIGhiLlZNID0gcnVudGltZTtcbiAgaGIudGVtcGxhdGUgPSBmdW5jdGlvbihzcGVjKSB7XG4gICAgcmV0dXJuIHJ1bnRpbWUudGVtcGxhdGUoc3BlYywgaGIpO1xuICB9O1xuXG4gIHJldHVybiBoYjtcbn1cblxubGV0IGluc3QgPSBjcmVhdGUoKTtcbmluc3QuY3JlYXRlID0gY3JlYXRlO1xuXG5ub0NvbmZsaWN0KGluc3QpO1xuXG5pbnN0WydkZWZhdWx0J10gPSBpbnN0O1xuXG5leHBvcnQgZGVmYXVsdCBpbnN0O1xuIl19 +; +define('handlebars/compiler/ast',['exports', 'module'], function (exports, module) { + 'use strict'; + + var AST = { + // Public API used to evaluate derived attributes regarding AST nodes + helpers: { + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + helperExpression: function helperExpression(node) { + return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash); + }, + + scopedId: function scopedId(path) { + return (/^\.|this\b/.test(path.original) + ); + }, + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + simpleId: function simpleId(path) { + return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; + } + } + }; + + // Must be exported as an object rather than the root of the module as the jison lexer + // must modify the object to operate properly. + module.exports = AST; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2FzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxNQUFJLEdBQUcsR0FBRzs7QUFFUixXQUFPLEVBQUU7Ozs7QUFJUCxzQkFBZ0IsRUFBRSwwQkFBUyxJQUFJLEVBQUU7QUFDL0IsZUFBTyxBQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssZUFBZSxJQUM3QixDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssbUJBQW1CLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxnQkFBZ0IsQ0FBQSxJQUNuRSxDQUFDLEVBQUUsQUFBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFLLElBQUksQ0FBQyxJQUFJLENBQUEsQUFBQyxBQUFDLENBQUM7T0FDaEU7O0FBRUQsY0FBUSxFQUFFLGtCQUFTLElBQUksRUFBRTtBQUN2QixlQUFPLEFBQUMsYUFBWSxDQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1VBQUM7T0FDM0M7Ozs7QUFJRCxjQUFRLEVBQUUsa0JBQVMsSUFBSSxFQUFFO0FBQ3ZCLGVBQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO09BQzlFO0tBQ0Y7R0FDRixDQUFDOzs7O21CQUthLEdBQUciLCJmaWxlIjoiYXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsibGV0IEFTVCA9IHtcbiAgLy8gUHVibGljIEFQSSB1c2VkIHRvIGV2YWx1YXRlIGRlcml2ZWQgYXR0cmlidXRlcyByZWdhcmRpbmcgQVNUIG5vZGVzXG4gIGhlbHBlcnM6IHtcbiAgICAvLyBhIG11c3RhY2hlIGlzIGRlZmluaXRlbHkgYSBoZWxwZXIgaWY6XG4gICAgLy8gKiBpdCBpcyBhbiBlbGlnaWJsZSBoZWxwZXIsIGFuZFxuICAgIC8vICogaXQgaGFzIGF0IGxlYXN0IG9uZSBwYXJhbWV0ZXIgb3IgaGFzaCBzZWdtZW50XG4gICAgaGVscGVyRXhwcmVzc2lvbjogZnVuY3Rpb24obm9kZSkge1xuICAgICAgcmV0dXJuIChub2RlLnR5cGUgPT09ICdTdWJFeHByZXNzaW9uJylcbiAgICAgICAgICB8fCAoKG5vZGUudHlwZSA9PT0gJ011c3RhY2hlU3RhdGVtZW50JyB8fCBub2RlLnR5cGUgPT09ICdCbG9ja1N0YXRlbWVudCcpXG4gICAgICAgICAgICAmJiAhISgobm9kZS5wYXJhbXMgJiYgbm9kZS5wYXJhbXMubGVuZ3RoKSB8fCBub2RlLmhhc2gpKTtcbiAgICB9LFxuXG4gICAgc2NvcGVkSWQ6IGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgIHJldHVybiAoL15cXC58dGhpc1xcYi8pLnRlc3QocGF0aC5vcmlnaW5hbCk7XG4gICAgfSxcblxuICAgIC8vIGFuIElEIGlzIHNpbXBsZSBpZiBpdCBvbmx5IGhhcyBvbmUgcGFydCwgYW5kIHRoYXQgcGFydCBpcyBub3RcbiAgICAvLyBgLi5gIG9yIGB0aGlzYC5cbiAgICBzaW1wbGVJZDogZnVuY3Rpb24ocGF0aCkge1xuICAgICAgcmV0dXJuIHBhdGgucGFydHMubGVuZ3RoID09PSAxICYmICFBU1QuaGVscGVycy5zY29wZWRJZChwYXRoKSAmJiAhcGF0aC5kZXB0aDtcbiAgICB9XG4gIH1cbn07XG5cblxuLy8gTXVzdCBiZSBleHBvcnRlZCBhcyBhbiBvYmplY3QgcmF0aGVyIHRoYW4gdGhlIHJvb3Qgb2YgdGhlIG1vZHVsZSBhcyB0aGUgamlzb24gbGV4ZXJcbi8vIG11c3QgbW9kaWZ5IHRoZSBvYmplY3QgdG8gb3BlcmF0ZSBwcm9wZXJseS5cbmV4cG9ydCBkZWZhdWx0IEFTVDtcbiJdfQ== +; +define('handlebars/compiler/parser',["exports"], function (exports) { + /* istanbul ignore next */ + /* Jison generated parser */ + "use strict"; + + var handlebars = (function () { + var parser = { trace: function trace() {}, + yy: {}, + symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 }, + terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" }, + productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$ + /**/) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: + return $$[$0 - 1]; + break; + case 2: + this.$ = yy.prepareProgram($$[$0]); + break; + case 3: + this.$ = $$[$0]; + break; + case 4: + this.$ = $$[$0]; + break; + case 5: + this.$ = $$[$0]; + break; + case 6: + this.$ = $$[$0]; + break; + case 7: + this.$ = $$[$0]; + break; + case 8: + this.$ = $$[$0]; + break; + case 9: + this.$ = { + type: 'CommentStatement', + value: yy.stripComment($$[$0]), + strip: yy.stripFlags($$[$0], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 10: + this.$ = { + type: 'ContentStatement', + original: $$[$0], + value: $$[$0], + loc: yy.locInfo(this._$) + }; + + break; + case 11: + this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 12: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] }; + break; + case 13: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$); + break; + case 14: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$); + break; + case 15: + this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 16: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 17: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 18: + this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] }; + break; + case 19: + var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$), + program = yy.prepareProgram([inverse], $$[$0 - 1].loc); + program.chained = true; + + this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true }; + + break; + case 20: + this.$ = $$[$0]; + break; + case 21: + this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) }; + break; + case 22: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 23: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 24: + this.$ = { + type: 'PartialStatement', + name: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + indent: '', + strip: yy.stripFlags($$[$0 - 4], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 25: + this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 26: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) }; + break; + case 27: + this.$ = $$[$0]; + break; + case 28: + this.$ = $$[$0]; + break; + case 29: + this.$ = { + type: 'SubExpression', + path: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + loc: yy.locInfo(this._$) + }; + + break; + case 30: + this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 31: + this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 32: + this.$ = yy.id($$[$0 - 1]); + break; + case 33: + this.$ = $$[$0]; + break; + case 34: + this.$ = $$[$0]; + break; + case 35: + this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 36: + this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) }; + break; + case 37: + this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) }; + break; + case 38: + this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) }; + break; + case 39: + this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) }; + break; + case 40: + this.$ = $$[$0]; + break; + case 41: + this.$ = $$[$0]; + break; + case 42: + this.$ = yy.preparePath(true, $$[$0], this._$); + break; + case 43: + this.$ = yy.preparePath(false, $$[$0], this._$); + break; + case 44: + $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2]; + break; + case 45: + this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }]; + break; + case 46: + this.$ = []; + break; + case 47: + $$[$0 - 1].push($$[$0]); + break; + case 48: + this.$ = [$$[$0]]; + break; + case 49: + $$[$0 - 1].push($$[$0]); + break; + case 50: + this.$ = []; + break; + case 51: + $$[$0 - 1].push($$[$0]); + break; + case 58: + this.$ = []; + break; + case 59: + $$[$0 - 1].push($$[$0]); + break; + case 64: + this.$ = []; + break; + case 65: + $$[$0 - 1].push($$[$0]); + break; + case 70: + this.$ = []; + break; + case 71: + $$[$0 - 1].push($$[$0]); + break; + case 78: + this.$ = []; + break; + case 79: + $$[$0 - 1].push($$[$0]); + break; + case 82: + this.$ = []; + break; + case 83: + $$[$0 - 1].push($$[$0]); + break; + case 86: + this.$ = []; + break; + case 87: + $$[$0 - 1].push($$[$0]); + break; + case 90: + this.$ = []; + break; + case 91: + $$[$0 - 1].push($$[$0]); + break; + case 94: + this.$ = []; + break; + case 95: + $$[$0 - 1].push($$[$0]); + break; + case 98: + this.$ = [$$[$0]]; + break; + case 99: + $$[$0 - 1].push($$[$0]); + break; + case 100: + this.$ = [$$[$0]]; + break; + case 101: + $$[$0 - 1].push($$[$0]); + break; + } + }, + table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }], + defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137: [2, 32] }, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], + lstack = [], + table = this.table, + yytext = "", + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, + preErrorSymbol, + state, + action, + a, + r, + yyval = {}, + p, + len, + newState, + expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected }); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; + } + }; + /* Jison generated lexer */ + var lexer = (function () { + var lexer = { EOF: 1, + parseError: function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput: function setInput(input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; + if (this.options.ranges) this.yylloc.range = [0, 0]; + this.offset = 0; + return this; + }, + input: function input() { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, + unput: function unput(ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); + + if (lines.length - 1) this.yylineno -= lines.length - 1; + var r = this.yylloc.range; + + this.yylloc = { first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, + more: function more() { + this._more = true; + return this; + }, + less: function less(n) { + this.unput(this.match.slice(n)); + }, + pastInput: function pastInput() { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput: function upcomingInput() { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20 - next.length); + } + return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, + showPosition: function showPosition() { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, + next: function next() { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, match, tempMatch, index, col, lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = { first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) this.done = false; + if (token) return token;else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); + } + }, + lex: function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin: function begin(condition) { + this.conditionStack.push(condition); + }, + popState: function popState() { + return this.conditionStack.pop(); + }, + _currentRules: function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + }, + topState: function topState() { + return this.conditionStack[this.conditionStack.length - 2]; + }, + pushState: function begin(condition) { + this.begin(condition); + } }; + lexer.options = {}; + lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START + /**/) { + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end); + } + + var YYSTATE = YY_START; + switch ($avoiding_name_collisions) { + case 0: + if (yy_.yytext.slice(-2) === "\\\\") { + strip(0, 1); + this.begin("mu"); + } else if (yy_.yytext.slice(-1) === "\\") { + strip(0, 1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if (yy_.yytext) return 15; + + break; + case 1: + return 15; + break; + case 2: + this.popState(); + return 15; + + break; + case 3: + this.begin('raw');return 15; + break; + case 4: + this.popState(); + // Should be using `this.topState()` below, but it currently + // returns the second top instead of the first top. Opened an + // issue about it at https://github.com/zaach/jison/issues/291 + if (this.conditionStack[this.conditionStack.length - 1] === 'raw') { + return 15; + } else { + yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9); + return 'END_RAW_BLOCK'; + } + + break; + case 5: + return 15; + break; + case 6: + this.popState(); + return 14; + + break; + case 7: + return 65; + break; + case 8: + return 68; + break; + case 9: + return 19; + break; + case 10: + this.popState(); + this.begin('raw'); + return 23; + + break; + case 11: + return 55; + break; + case 12: + return 60; + break; + case 13: + return 29; + break; + case 14: + return 47; + break; + case 15: + this.popState();return 44; + break; + case 16: + this.popState();return 44; + break; + case 17: + return 34; + break; + case 18: + return 39; + break; + case 19: + return 51; + break; + case 20: + return 48; + break; + case 21: + this.unput(yy_.yytext); + this.popState(); + this.begin('com'); + + break; + case 22: + this.popState(); + return 14; + + break; + case 23: + return 48; + break; + case 24: + return 73; + break; + case 25: + return 72; + break; + case 26: + return 72; + break; + case 27: + return 87; + break; + case 28: + // ignore whitespace + break; + case 29: + this.popState();return 54; + break; + case 30: + this.popState();return 33; + break; + case 31: + yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80; + break; + case 32: + yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80; + break; + case 33: + return 85; + break; + case 34: + return 82; + break; + case 35: + return 82; + break; + case 36: + return 83; + break; + case 37: + return 84; + break; + case 38: + return 81; + break; + case 39: + return 75; + break; + case 40: + return 77; + break; + case 41: + return 72; + break; + case 42: + yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72; + break; + case 43: + return 'INVALID'; + break; + case 44: + return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/]; + lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } }; + return lexer; + })(); + parser.lexer = lexer; + function Parser() { + this.yy = {}; + }Parser.prototype = parser;parser.Parser = Parser; + return new Parser(); + })();exports.__esModule = true; + exports['default'] = handlebars; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3BhcnNlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLFFBQUksVUFBVSxHQUFHLENBQUMsWUFBVTtBQUM1QixZQUFJLE1BQU0sR0FBRyxFQUFDLEtBQUssRUFBRSxTQUFTLEtBQUssR0FBRyxFQUFHO0FBQ3pDLGNBQUUsRUFBRSxFQUFFO0FBQ04sb0JBQVEsRUFBRSxFQUFDLE9BQU8sRUFBQyxDQUFDLEVBQUMsTUFBTSxFQUFDLENBQUMsRUFBQyxTQUFTLEVBQUMsQ0FBQyxFQUFDLEtBQUssRUFBQyxDQUFDLEVBQUMscUJBQXFCLEVBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxDQUFDLEVBQUMsVUFBVSxFQUFDLENBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxFQUFDLFVBQVUsRUFBQyxFQUFFLEVBQUMsU0FBUyxFQUFDLEVBQUUsRUFBQyxjQUFjLEVBQUMsRUFBRSxFQUFDLFNBQVMsRUFBQyxFQUFFLEVBQUMsU0FBUyxFQUFDLEVBQUUsRUFBQyxTQUFTLEVBQUMsRUFBRSxFQUFDLGNBQWMsRUFBQyxFQUFFLEVBQUMsMkJBQTJCLEVBQUMsRUFBRSxFQUFDLGVBQWUsRUFBQyxFQUFFLEVBQUMsZ0JBQWdCLEVBQUMsRUFBRSxFQUFDLFlBQVksRUFBQyxFQUFFLEVBQUMsMEJBQTBCLEVBQUMsRUFBRSxFQUFDLHNCQUFzQixFQUFDLEVBQUUsRUFBQyxpQkFBaUIsRUFBQyxFQUFFLEVBQUMsV0FBVyxFQUFDLEVBQUUsRUFBQyxlQUFlLEVBQUMsRUFBRSxFQUFDLFlBQVksRUFBQyxFQUFFLEVBQUMsYUFBYSxFQUFDLEVBQUUsRUFBQyxlQUFlLEVBQUMsRUFBRSxFQUFDLFlBQVksRUFBQyxFQUFFLEVBQUMsdUJBQXVCLEVBQUMsRUFBRSxFQUFDLG1CQUFtQixFQUFDLEVBQUUsRUFBQyxtQkFBbUIsRUFBQyxFQUFFLEVBQUMsT0FBTyxFQUFDLEVBQUUsRUFBQyxjQUFjLEVBQUMsRUFB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RUFBRSxFQUFDLEtBQUssRUFBQztBQUM1ZSx3QkFBWSxFQUFFLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFB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QUFDLENBQUMsR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3pFLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ3RFLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN2Riw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdEYsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNySiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ3JJLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDckksOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztBQUMvRSw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUNILDRCQUFJLE9BQU8sR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDOzRCQUM3RSxPQUFPLEdBQUcsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDekQsK0JBQU8sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDOztBQUV2Qiw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQzs7QUFFdEUsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDeEIsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUMsQ0FBQztBQUMxRSw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RILDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdEgsOEJBQU07QUFB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SyxFQUFFO0FBQUUsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQUFBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEcsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUM7QUFDM0QsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDcEIsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQywwQkFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUIsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEVBQUU7QUFBQyw0QkFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzFCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMEJBQUUsQ0FBQyxFQUFFLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMxQiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLDBCQUFFLENBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5Qiw4QkFBTTtBQUFBLEFBQ04seUJBQUssR0FBRztBQUFDLDRCQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDM0IsOEJBQU07QUFBQSxBQUNOLHlCQUFLLEdBQUc7QUFBQywwQkFBRSxDQUFDLEVBQUUsR0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDL0IsOEJBQU07QUFBQSxpQkFDTDthQUNBO0FBQ0QsaUJBQUssRUFBRSxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxFQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsRUFBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsR0FBRyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBQyxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxHQUFHLEVBQUMsRUFBRSxFQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxHQUFHLENBQUMsRUFBQyxFQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztBQUN4Z1csMEJBQWMsRUFBRSxFQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsRUFBRSxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEVBQUUsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxFQUFFLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDLENBQUMsRUFBQyxFQUFFLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxDQUFDLEVBQUMsRUFBRSxDQUFDLEVB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QUFBLEFBQ04seUJBQUssRUFBRTtBQUFDLCtCQUFPLEVBQUUsQ0FBQztBQUNsQiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUNMLDRCQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN2Qiw0QkFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ2hCLDRCQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDOztBQUVwQiw4QkFBTTtBQUFBLEFBQ04seUJBQUssRUFBRTtBQUNMLDRCQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDaEIsK0JBQU8sRUFBRSxDQUFDOztBQUVaLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsK0JBQU8sRUFBRSxDQUFDO0FBQ2xCLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFOztBQUNQLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxBQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ25DLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsNEJBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxBQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ25DLDhCQUFNO0FBQUEsQUFDTix5QkFBSyxFQUFFO0FBQUMsMkJBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFDLEdBQUcsQ0FBQyxDQUFDLEFBQUMsT0FBTyxFQUFF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RUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBQyxFQUFFLENBQUMsRUFBQyxXQUFXLEVBQUMsS0FBSyxFQUFDLEVBQUMsS0FBSyxFQUFDLEVBQUMsT0FBTyxFQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUMsV0FBVyxFQUFDLEtBQUssRUFBQyxFQUFDLEtBQUssRUFBQyxFQUFDLE9BQU8sRUFBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxLQUFLLEVBQUMsRUFBQyxLQUFLLEVBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLFdBQVcsRUFBQyxLQUFLLEVBQUMsRUFBQyxTQUFTLEVBQUMsRUFBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFDLEVBQUUsQ0FBQyxFQUFDLFdBQVcsRUFBQyxJQUFJLEVBQUMsRUFBQyxDQUFDO0FBQzNVLG1CQUFPLEtBQUssQ0FBQztTQUFDLENBQUEsRUFBRyxDQUFBO0FBQ2pCLGNBQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0FBQ3JCLGlCQUFTLE1BQU0sR0FBSTtBQUFFLGdCQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztTQUFFLE1BQU0sQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQ3JGLGVBQU8sSUFBSSxNQUFNLEVBQUEsQ0FBQztLQUNqQixDQUFBLEVBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztBQUMvQixXQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsVUFBVSxDQUFDIiwiZmlsZSI6InBhcnNlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4vKiBKaXNvbiBnZW5lcmF0ZWQgcGFyc2VyICovXG52YXIgaGFuZGxlYmFycyA9IChmdW5jdGlvbigpe1xudmFyIHBhcnNlciA9IHt0cmFjZTogZnVuY3Rpb24gdHJhY2UoKSB7IH0sXG55eToge30sXG5zeW1ib2xzXzoge1wiZXJyb3JcIjoyLFwicm9vdFwiOjMsXCJwcm9ncmFtXCI6NCxcIkVPRlwiOjUsXCJwcm9ncmFtX3JlcGV0aXRpb24wXCI6NixcInN0YXRlbWVudFwiOjcsXCJtdXN0YWNoZVwiOjgsXCJibG9ja1wiOjksXCJyYXdCbG9ja1wiOjEwLFwicGFydGlhbFwiOjExLFwicGFydGlhbEJsb2NrXCI6MTIsXCJjb250ZW50XCI6MTMsXCJDT01NRU5UXCI6MTQsXCJDT05URU5UXCI6MTUsXCJvcGVuUmF3QmxvY2tcIjoxNixcInJhd0Jsb2NrX3JlcGV0aXRpb25fcGx1czBcIjoxNyxcIkVORF9SQVdfQkxPQ0tcIjoxOCxcIk9QRU5fUkFXX0JMT0NLXCI6MTksXCJoZWxwZXJOYW1lXCI6MjAsXCJvcGVuUmF3QmxvY2tfcmVwZXRpdGlvbjBcIjoyMSxcIm9wZW5SYXdCbG9ja19vcHRpb24wXCI6MjIsXCJDTE9TRV9SQVdfQkxPQ0tcIjoyMyxcIm9wZW5CbG9ja1wiOjI0LFwiYmxvY2tfb3B0aW9uMFwiOjI1LFwiY2xvc2VCbG9ja1wiOjI2LFwib3BlbkludmVyc2VcIjoyNyxcImJsb2NrX29wdGlvbjFcIjoyOCxcIk9QRU5fQkxPQ0tcIjoyOSxcIm9wZW5CbG9ja19yZXBldGl0aW9uMFwiOjMwLFwib3BlbkJsb2NrX29wdGlvbjBcIjozMSxcIm9wZW5CbG9ja19vcHRpb24xXCI6MzIsXCJDTE9TRVwiOjMzLFwiT1BFTl9JTlZFUlNFXCI6MzQsXCJvcGVuSW52ZXJzZV9yZXBldGl0aW9uMFwiOjM1LFwib3BlbkludmVyc2Vfb3B0aW9uMFwiOjM2LFwib3BlbkludmVyc2Vfb3B0aW9uMVwiOjM3LFwib3BlbkludmVyc2VDaGFpblwiOjM4LFwiT1BFTl9JTlZFUlNFX0NIQUlOXCI6MzksXCJvcGVuSW52ZXJzZUNoYWluX3JlcGV0aXRpb24wXCI6NDAsXCJvcGVuSW52ZXJzZUNoYWluX29wdGlvbjBcIjo0MSxcIm9wZW5JbnZlcnNlQ2hhaW5fb3B0aW9uMVwiOjQyLFwiaW52ZXJzZUFuZFByb2dyYW1cIjo0MyxcIklOVkVSU0VcIjo0NCxcImludmVyc2VDaGFpblwiOjQ1LFwiaW52ZXJzZUNoYWluX29wdGlvbjBcIjo0NixcIk9QRU5fRU5EQkxPQ0tcIjo0NyxcIk9QRU5cIjo0OCxcIm11c3RhY2hlX3JlcGV0aXRpb24wXCI6NDksXCJtdXN0YWNoZV9vcHRpb24wXCI6NTAsXCJPUEVOX1VORVNDQVBFRFwiOjUxLFwibXVzdGFjaGVfcmVwZXRpdGlvbjFcIjo1MixcIm11c3RhY2hlX29wdGlvbjFcIjo1MyxcIkNMT1NFX1VORVNDQVBFRFwiOjU0LFwiT1BFTl9QQVJUSUFMXCI6NTUsXCJwYXJ0aWFsTmFtZVwiOjU2LFwicGFydGlhbF9yZXBldGl0aW9uMFwiOjU3LFwicGFydGlhbF9vcHRpb24wXCI6NTgsXCJvcGVuUGFydGlhbEJsb2NrXCI6NTksXCJPUEVOX1BBUlRJQUxfQkxPQ0tcIjo2MCxcIm9wZW5QYXJ0aWFsQmxvY2tfcmVwZXRpdGlvbjBcIjo2MSxcIm9wZW5QYXJ0aWFsQmxvY2tfb3B0aW9uMFwiOjYyLFwicGFyYW1cIjo2MyxcInNleHByXCI6NjQsXCJPUEVOX1NFWFBSXCI6NjUsXCJzZXhwcl9yZXBldGl0aW9uMFwiOjY2LFwic2V4cHJfb3B0aW9uMFwiOjY3LFwiQ0xPU0VfU0VYUFJcIjo2OCxcImhhc2hcIjo2OSxcImhhc2hfcmVwZXRpdGlvbl9wbHVzMFwiOjcwLFwiaGFzaFNlZ21lbnRcIjo3MSxcIklEXCI6NzIsXCJFUVVBTFNcIjo3MyxcImJsb2NrUGFyYW1zXCI6NzQsXCJPUEVOX0JMT0NLX1BBUkFNU1wiOjc1LFwiYmxvY2tQYXJhbXNfcmVwZXRpdGlvbl9wbHVzMFwiOjc2LFwiQ0xPU0VfQkxPQ0tfUEFSQU1TXCI6NzcsXCJwYXRoXCI6NzgsXCJkYXRhTmFtZVwiOjc5LFwiU1RSSU5HXCI6ODAsXCJOVU1CRVJcIjo4MSxcIkJPT0xFQU5cIjo4MixcIlVOREVGSU5FRFwiOjgzLFwiTlVMTFwiOjg0LFwiREFUQVwiOjg1LFwicGF0aFNlZ21lbnRzXCI6ODYsXCJTRVBcIjo4NyxcIiRhY2NlcHRcIjowLFwiJGVuZFwiOjF9LFxudGVybWluYWxzXzogezI6XCJlcnJvclwiLDU6XCJFT0ZcIiwxNDpcIkNPTU1FTlRcIiwxNTpcIkNPTlRFTlRcIiwxODpcIkVORF9SQVdfQkxPQ0tcIiwxOTpcIk9QRU5fUkFXX0JMT0NLXCIsMjM6XCJDTE9TRV9SQVdfQkxPQ0tcIiwyOTpcIk9QRU5fQkxPQ0tcIiwzMzpcIkNMT1NFXCIsMzQ6XCJPUEVOX0lOVkVSU0VcIiwzOTpcIk9QRU5fSU5WRVJTRV9DSEFJTlwiLDQ0OlwiSU5WRVJTRVwiLDQ3OlwiT1BFTl9FTkRCTE9DS1wiLDQ4OlwiT1BFTlwiLDUxOlwiT1BFTl9VTkVTQ0FQRURcIiw1NDpcIkNMT1NFX1VORVNDQVBFRFwiLDU1OlwiT1BFTl9QQVJUSUFMXCIsNjA6XCJPUEVOX1BBUlRJQUxfQkxPQ0tcIiw2NTpcIk9QRU5fU0VYUFJcIiw2ODpcIkNMT1NFX1NFWFBSXCIsNzI6XCJJRFwiLDczOlwiRVFVQUxTXCIsNzU6XCJPUEVOX0JMT0NLX1BBUkFNU1wiLDc3OlwiQ0xPU0VfQkxPQ0tfUEFSQU1TXCIsODA6XCJTVFJJTkdcIiw4MTpcIk5VTUJFUlwiLDgyOlwiQk9PTEVBTlwiLDgzOlwiVU5ERUZJTkVEXCIsODQ6XCJOVUxMXCIsODU6XCJEQVRBXCIsODc6XCJTRVBcIn0sXG5wcm9kdWN0aW9uc186IFswLFszLDJdLFs0LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFs3LDFdLFsxMywxXSxbMTAsM10sWzE2LDVdLFs5LDRdLFs5LDRdLFsyNCw2XSxbMjcsNl0sWzM4LDZdLFs0MywyXSxbNDUsM10sWzQ1LDFdLFsyNiwzXSxbOCw1XSxbOCw1XSxbMTEsNV0sWzEyLDNdLFs1OSw1XSxbNjMsMV0sWzYzLDFdLFs2NCw1XSxbNjksMV0sWzcxLDNdLFs3NCwzXSxbMjAsMV0sWzIwLDFdLFsyMCwxXSxbMjAsMV0sWzIwLDFdLFsyMCwxXSxbMjAsMV0sWzU2LDFdLFs1NiwxXSxbNzksMl0sWzc4LDFdLFs4NiwzXSxbODYsMV0sWzYsMF0sWzYsMl0sWzE3LDFdLFsxNywyXSxbMjEsMF0sWzIxLDJdLFsyMiwwXSxbMjIsMV0sWzI1LDBdLFsyNSwxXSxbMjgsMF0sWzI4LDFdLFszMCwwXSxbMzAsMl0sWzMxLDBdLFszMSwxXSxbMzIsMF0sWzMyLDFdLFszNSwwXSxbMzUsMl0sWzM2LDBdLFszNiwxXSxbMzcsMF0sWzM3LDFdLFs0MCwwXSxbNDAsMl0sWzQxLDBdLFs0MSwxXSxbNDIsMF0sWzQyLDFdLFs0NiwwXSxbNDYsMV0sWzQ5LDBdLFs0OSwyXSxbNTAsMF0sWzUwLDFdLFs1MiwwXSxbNTIsMl0sWzUzLDBdLFs1MywxXSxbNTcsMF0sWzU3LDJdLFs1OCwwXSxbNTgsMV0sWzYxLDBdLFs2MSwyXSxbNjIsMF0sWzYyLDFdLFs2NiwwXSxbNjYsMl0sWzY3LDBdLFs2NywxXSxbNzAsMV0sWzcwLDJdLFs3NiwxXSxbNzYsMl1dLFxucGVyZm9ybUFjdGlvbjogZnVuY3Rpb24gYW5vbnltb3VzKHl5dGV4dCx5eWxlbmcseXlsaW5lbm8seXkseXlzdGF0ZSwkJCxfJFxuLyoqLykge1xuXG52YXIgJDAgPSAkJC5sZW5ndGggLSAxO1xuc3dpdGNoICh5eXN0YXRlKSB7XG5jYXNlIDE6IHJldHVybiAkJFskMC0xXTsgXG5icmVhaztcbmNhc2UgMjp0aGlzLiQgPSB5eS5wcmVwYXJlUHJvZ3JhbSgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDM6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDQ6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDU6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDY6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDc6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDg6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDk6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ0NvbW1lbnRTdGF0ZW1lbnQnLFxuICAgICAgdmFsdWU6IHl5LnN0cmlwQ29tbWVudCgkJFskMF0pLFxuICAgICAgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDBdLCAkJFskMF0pLFxuICAgICAgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpXG4gICAgfTtcbiAgXG5icmVhaztcbmNhc2UgMTA6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ0NvbnRlbnRTdGF0ZW1lbnQnLFxuICAgICAgb3JpZ2luYWw6ICQkWyQwXSxcbiAgICAgIHZhbHVlOiAkJFskMF0sXG4gICAgICBsb2M6IHl5LmxvY0luZm8odGhpcy5fJClcbiAgICB9O1xuICBcbmJyZWFrO1xuY2FzZSAxMTp0aGlzLiQgPSB5eS5wcmVwYXJlUmF3QmxvY2soJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMF0sIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDEyOnRoaXMuJCA9IHsgcGF0aDogJCRbJDAtM10sIHBhcmFtczogJCRbJDAtMl0sIGhhc2g6ICQkWyQwLTFdIH07XG5icmVhaztcbmNhc2UgMTM6dGhpcy4kID0geXkucHJlcGFyZUJsb2NrKCQkWyQwLTNdLCAkJFskMC0yXSwgJCRbJDAtMV0sICQkWyQwXSwgZmFsc2UsIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDE0OnRoaXMuJCA9IHl5LnByZXBhcmVCbG9jaygkJFskMC0zXSwgJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMF0sIHRydWUsIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDE1OnRoaXMuJCA9IHsgb3BlbjogJCRbJDAtNV0sIHBhdGg6ICQkWyQwLTRdLCBwYXJhbXM6ICQkWyQwLTNdLCBoYXNoOiAkJFskMC0yXSwgYmxvY2tQYXJhbXM6ICQkWyQwLTFdLCBzdHJpcDogeXkuc3RyaXBGbGFncygkJFskMC01XSwgJCRbJDBdKSB9O1xuYnJlYWs7XG5jYXNlIDE2OnRoaXMuJCA9IHsgcGF0aDogJCRbJDAtNF0sIHBhcmFtczogJCRbJDAtM10sIGhhc2g6ICQkWyQwLTJdLCBibG9ja1BhcmFtczogJCRbJDAtMV0sIHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTVdLCAkJFskMF0pIH07XG5icmVhaztcbmNhc2UgMTc6dGhpcy4kID0geyBwYXRoOiAkJFskMC00XSwgcGFyYW1zOiAkJFskMC0zXSwgaGFzaDogJCRbJDAtMl0sIGJsb2NrUGFyYW1zOiAkJFskMC0xXSwgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNV0sICQkWyQwXSkgfTtcbmJyZWFrO1xuY2FzZSAxODp0aGlzLiQgPSB7IHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTFdLCAkJFskMC0xXSksIHByb2dyYW06ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDE5OlxuICAgIHZhciBpbnZlcnNlID0geXkucHJlcGFyZUJsb2NrKCQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDBdLCAkJFskMF0sIGZhbHNlLCB0aGlzLl8kKSxcbiAgICAgICAgcHJvZ3JhbSA9IHl5LnByZXBhcmVQcm9ncmFtKFtpbnZlcnNlXSwgJCRbJDAtMV0ubG9jKTtcbiAgICBwcm9ncmFtLmNoYWluZWQgPSB0cnVlO1xuXG4gICAgdGhpcy4kID0geyBzdHJpcDogJCRbJDAtMl0uc3RyaXAsIHByb2dyYW06IHByb2dyYW0sIGNoYWluOiB0cnVlIH07XG4gIFxuYnJlYWs7XG5jYXNlIDIwOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSAyMTp0aGlzLiQgPSB7cGF0aDogJCRbJDAtMV0sIHN0cmlwOiB5eS5zdHJpcEZsYWdzKCQkWyQwLTJdLCAkJFskMF0pfTtcbmJyZWFrO1xuY2FzZSAyMjp0aGlzLiQgPSB5eS5wcmVwYXJlTXVzdGFjaGUoJCRbJDAtM10sICQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDAtNF0sIHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSksIHRoaXMuXyQpO1xuYnJlYWs7XG5jYXNlIDIzOnRoaXMuJCA9IHl5LnByZXBhcmVNdXN0YWNoZSgkJFskMC0zXSwgJCRbJDAtMl0sICQkWyQwLTFdLCAkJFskMC00XSwgeXkuc3RyaXBGbGFncygkJFskMC00XSwgJCRbJDBdKSwgdGhpcy5fJCk7XG5icmVhaztcbmNhc2UgMjQ6XG4gICAgdGhpcy4kID0ge1xuICAgICAgdHlwZTogJ1BhcnRpYWxTdGF0ZW1lbnQnLFxuICAgICAgbmFtZTogJCRbJDAtM10sXG4gICAgICBwYXJhbXM6ICQkWyQwLTJdLFxuICAgICAgaGFzaDogJCRbJDAtMV0sXG4gICAgICBpbmRlbnQ6ICcnLFxuICAgICAgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSksXG4gICAgICBsb2M6IHl5LmxvY0luZm8odGhpcy5fJClcbiAgICB9O1xuICBcbmJyZWFrO1xuY2FzZSAyNTp0aGlzLiQgPSB5eS5wcmVwYXJlUGFydGlhbEJsb2NrKCQkWyQwLTJdLCAkJFskMC0xXSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSAyNjp0aGlzLiQgPSB7IHBhdGg6ICQkWyQwLTNdLCBwYXJhbXM6ICQkWyQwLTJdLCBoYXNoOiAkJFskMC0xXSwgc3RyaXA6IHl5LnN0cmlwRmxhZ3MoJCRbJDAtNF0sICQkWyQwXSkgfTtcbmJyZWFrO1xuY2FzZSAyNzp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgMjg6dGhpcy4kID0gJCRbJDBdO1xuYnJlYWs7XG5jYXNlIDI5OlxuICAgIHRoaXMuJCA9IHtcbiAgICAgIHR5cGU6ICdTdWJFeHByZXNzaW9uJyxcbiAgICAgIHBhdGg6ICQkWyQwLTNdLFxuICAgICAgcGFyYW1zOiAkJFskMC0yXSxcbiAgICAgIGhhc2g6ICQkWyQwLTFdLFxuICAgICAgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpXG4gICAgfTtcbiAgXG5icmVhaztcbmNhc2UgMzA6dGhpcy4kID0ge3R5cGU6ICdIYXNoJywgcGFpcnM6ICQkWyQwXSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzMTp0aGlzLiQgPSB7dHlwZTogJ0hhc2hQYWlyJywga2V5OiB5eS5pZCgkJFskMC0yXSksIHZhbHVlOiAkJFskMF0sIGxvYzogeXkubG9jSW5mbyh0aGlzLl8kKX07XG5icmVhaztcbmNhc2UgMzI6dGhpcy4kID0geXkuaWQoJCRbJDAtMV0pO1xuYnJlYWs7XG5jYXNlIDMzOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSAzNDp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgMzU6dGhpcy4kID0ge3R5cGU6ICdTdHJpbmdMaXRlcmFsJywgdmFsdWU6ICQkWyQwXSwgb3JpZ2luYWw6ICQkWyQwXSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzNjp0aGlzLiQgPSB7dHlwZTogJ051bWJlckxpdGVyYWwnLCB2YWx1ZTogTnVtYmVyKCQkWyQwXSksIG9yaWdpbmFsOiBOdW1iZXIoJCRbJDBdKSwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzNzp0aGlzLiQgPSB7dHlwZTogJ0Jvb2xlYW5MaXRlcmFsJywgdmFsdWU6ICQkWyQwXSA9PT0gJ3RydWUnLCBvcmlnaW5hbDogJCRbJDBdID09PSAndHJ1ZScsIGxvYzogeXkubG9jSW5mbyh0aGlzLl8kKX07XG5icmVhaztcbmNhc2UgMzg6dGhpcy4kID0ge3R5cGU6ICdVbmRlZmluZWRMaXRlcmFsJywgb3JpZ2luYWw6IHVuZGVmaW5lZCwgdmFsdWU6IHVuZGVmaW5lZCwgbG9jOiB5eS5sb2NJbmZvKHRoaXMuXyQpfTtcbmJyZWFrO1xuY2FzZSAzOTp0aGlzLiQgPSB7dHlwZTogJ051bGxMaXRlcmFsJywgb3JpZ2luYWw6IG51bGwsIHZhbHVlOiBudWxsLCBsb2M6IHl5LmxvY0luZm8odGhpcy5fJCl9O1xuYnJlYWs7XG5jYXNlIDQwOnRoaXMuJCA9ICQkWyQwXTtcbmJyZWFrO1xuY2FzZSA0MTp0aGlzLiQgPSAkJFskMF07XG5icmVhaztcbmNhc2UgNDI6dGhpcy4kID0geXkucHJlcGFyZVBhdGgodHJ1ZSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSA0Mzp0aGlzLiQgPSB5eS5wcmVwYXJlUGF0aChmYWxzZSwgJCRbJDBdLCB0aGlzLl8kKTtcbmJyZWFrO1xuY2FzZSA0NDogJCRbJDAtMl0ucHVzaCh7cGFydDogeXkuaWQoJCRbJDBdKSwgb3JpZ2luYWw6ICQkWyQwXSwgc2VwYXJhdG9yOiAkJFskMC0xXX0pOyB0aGlzLiQgPSAkJFskMC0yXTsgXG5icmVhaztcbmNhc2UgNDU6dGhpcy4kID0gW3twYXJ0OiB5eS5pZCgkJFskMF0pLCBvcmlnaW5hbDogJCRbJDBdfV07XG5icmVhaztcbmNhc2UgNDY6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNDc6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDQ4OnRoaXMuJCA9IFskJFskMF1dO1xuYnJlYWs7XG5jYXNlIDQ5OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA1MDp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA1MTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgNTg6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNTk6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDY0OnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDY1OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA3MDp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA3MTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgNzg6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgNzk6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDgyOnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDgzOiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA4Njp0aGlzLiQgPSBbXTtcbmJyZWFrO1xuY2FzZSA4NzokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgOTA6dGhpcy4kID0gW107XG5icmVhaztcbmNhc2UgOTE6JCRbJDAtMV0ucHVzaCgkJFskMF0pO1xuYnJlYWs7XG5jYXNlIDk0OnRoaXMuJCA9IFtdO1xuYnJlYWs7XG5jYXNlIDk1OiQkWyQwLTFdLnB1c2goJCRbJDBdKTtcbmJyZWFrO1xuY2FzZSA5ODp0aGlzLiQgPSBbJCRbJDBdXTtcbmJyZWFrO1xuY2FzZSA5OTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbmNhc2UgMTAwOnRoaXMuJCA9IFskJFskMF1dO1xuYnJlYWs7XG5jYXNlIDEwMTokJFskMC0xXS5wdXNoKCQkWyQwXSk7XG5icmVhaztcbn1cbn0sXG50YWJsZTogW3szOjEsNDoyLDU6WzIsNDZdLDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezE6WzNdfSx7NTpbMSw0XX0sezU6WzIsMl0sNzo1LDg6Niw5OjcsMTA6OCwxMTo5LDEyOjEwLDEzOjExLDE0OlsxLDEyXSwxNTpbMSwyMF0sMTY6MTcsMTk6WzEsMjNdLDI0OjE1LDI3OjE2LDI5OlsxLDIxXSwzNDpbMSwyMl0sMzk6WzIsMl0sNDQ6WzIsMl0sNDc6WzIsMl0sNDg6WzEsMTNdLDUxOlsxLDE0XSw1NTpbMSwxOF0sNTk6MTksNjA6WzEsMjRdfSx7MTpbMiwxXX0sezU6WzIsNDddLDE0OlsyLDQ3XSwxNTpbMiw0N10sMTk6WzIsNDddLDI5OlsyLDQ3XSwzNDpbMiw0N10sMzk6WzIsNDddLDQ0OlsyLDQ3XSw0NzpbMiw0N10sNDg6WzIsNDddLDUxOlsyLDQ3XSw1NTpbMiw0N10sNjA6WzIsNDddfSx7NTpbMiwzXSwxNDpbMiwzXSwxNTpbMiwzXSwxOTpbMiwzXSwyOTpbMiwzXSwzNDpbMiwzXSwzOTpbMiwzXSw0NDpbMiwzXSw0NzpbMiwzXSw0ODpbMiwzXSw1MTpbMiwzXSw1NTpbMiwzXSw2MDpbMiwzXX0sezU6WzIsNF0sMTQ6WzIsNF0sMTU6WzIsNF0sMTk6WzIsNF0sMjk6WzIsNF0sMzQ6WzIsNF0sMzk6WzIsNF0sNDQ6WzIsNF0sNDc6WzIsNF0sNDg6WzIsNF0sNTE6WzIsNF0sNTU6WzIsNF0sNjA6WzIsNF19LHs1OlsyLDVdLDE0OlsyLDVdLDE1OlsyLDVdLDE5OlsyLDVdLDI5OlsyLDVdLDM0OlsyLDVdLDM5OlsyLDVdLDQ0OlsyLDVdLDQ3OlsyLDVdLDQ4OlsyLDVdLDUxOlsyLDVdLDU1OlsyLDVdLDYwOlsyLDVdfSx7NTpbMiw2XSwxNDpbMiw2XSwxNTpbMiw2XSwxOTpbMiw2XSwyOTpbMiw2XSwzNDpbMiw2XSwzOTpbMiw2XSw0NDpbMiw2XSw0NzpbMiw2XSw0ODpbMiw2XSw1MTpbMiw2XSw1NTpbMiw2XSw2MDpbMiw2XX0sezU6WzIsN10sMTQ6WzIsN10sMTU6WzIsN10sMTk6WzIsN10sMjk6WzIsN10sMzQ6WzIsN10sMzk6WzIsN10sNDQ6WzIsN10sNDc6WzIsN10sNDg6WzIsN10sNTE6WzIsN10sNTU6WzIsN10sNjA6WzIsN119LHs1OlsyLDhdLDE0OlsyLDhdLDE1OlsyLDhdLDE5OlsyLDhdLDI5OlsyLDhdLDM0OlsyLDhdLDM5OlsyLDhdLDQ0OlsyLDhdLDQ3OlsyLDhdLDQ4OlsyLDhdLDUxOlsyLDhdLDU1OlsyLDhdLDYwOlsyLDhdfSx7NTpbMiw5XSwxNDpbMiw5XSwxNTpbMiw5XSwxOTpbMiw5XSwyOTpbMiw5XSwzNDpbMiw5XSwzOTpbMiw5XSw0NDpbMiw5XSw0NzpbMiw5XSw0ODpbMiw5XSw1MTpbMiw5XSw1NTpbMiw5XSw2MDpbMiw5XX0sezIwOjI1LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjM2LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezQ6MzcsNjozLDE0OlsyLDQ2XSwxNTpbMiw0Nl0sMTk6WzIsNDZdLDI5OlsyLDQ2XSwzNDpbMiw0Nl0sMzk6WzIsNDZdLDQ0OlsyLDQ2XSw0NzpbMiw0Nl0sNDg6WzIsNDZdLDUxOlsyLDQ2XSw1NTpbMiw0Nl0sNjA6WzIsNDZdfSx7NDozOCw2OjMsMTQ6WzIsNDZdLDE1OlsyLDQ2XSwxOTpbMiw0Nl0sMjk6WzIsNDZdLDM0OlsyLDQ2XSw0NDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezEzOjQwLDE1OlsxLDIwXSwxNzozOX0sezIwOjQyLDU2OjQxLDY0OjQzLDY1OlsxLDQ0XSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs0OjQ1LDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDQ3OlsyLDQ2XSw0ODpbMiw0Nl0sNTE6WzIsNDZdLDU1OlsyLDQ2XSw2MDpbMiw0Nl19LHs1OlsyLDEwXSwxNDpbMiwxMF0sMTU6WzIsMTBdLDE4OlsyLDEwXSwxOTpbMiwxMF0sMjk6WzIsMTBdLDM0OlsyLDEwXSwzOTpbMiwxMF0sNDQ6WzIsMTBdLDQ3OlsyLDEwXSw0ODpbMiwxMF0sNTE6WzIsMTBdLDU1OlsyLDEwXSw2MDpbMiwxMF19LHsyMDo0Niw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0Nyw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0OCw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyMDo0Miw1Njo0OSw2NDo0Myw2NTpbMSw0NF0sNzI6WzEsMzVdLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7MzM6WzIsNzhdLDQ5OjUwLDY1OlsyLDc4XSw3MjpbMiw3OF0sODA6WzIsNzhdLDgxOlsyLDc4XSw4MjpbMiw3OF0sODM6WzIsNzhdLDg0OlsyLDc4XSw4NTpbMiw3OF19LHsyMzpbMiwzM10sMzM6WzIsMzNdLDU0OlsyLDMzXSw2NTpbMiwzM10sNjg6WzIsMzNdLDcyOlsyLDMzXSw3NTpbMiwzM10sODA6WzIsMzNdLDgxOlsyLDMzXSw4MjpbMiwzM10sODM6WzIsMzNdLDg0OlsyLDMzXSw4NTpbMiwzM119LHsyMzpbMiwzNF0sMzM6WzIsMzRdLDU0OlsyLDM0XSw2NTpbMiwzNF0sNjg6WzIsMzRdLDcyOlsyLDM0XSw3NTpbMiwzNF0sODA6WzIsMzRdLDgxOlsyLDM0XSw4MjpbMiwzNF0sODM6WzIsMzRdLDg0OlsyLDM0XSw4NTpbMiwzNF19LHsyMzpbMiwzNV0sMzM6WzIsMzVdLDU0OlsyLDM1XSw2NTpbMiwzNV0sNjg6WzIsMzVdLDcyOlsyLDM1XSw3NTpbMiwzNV0sODA6WzIsMzVdLDgxOlsyLDM1XSw4MjpbMiwzNV0sODM6WzIsMzVdLDg0OlsyLDM1XSw4NTpbMiwzNV19LHsyMzpbMiwzNl0sMzM6WzIsMzZdLDU0OlsyLDM2XSw2NTpbMiwzNl0sNjg6WzIsMzZdLDcyOlsyLDM2XSw3NTpbMiwzNl0sODA6WzIsMzZdLDgxOlsyLDM2XSw4MjpbMiwzNl0sODM6WzIsMzZdLDg0OlsyLDM2XSw4NTpbMiwzNl19LHsyMzpbMiwzN10sMzM6WzIsMzddLDU0OlsyLDM3XSw2NTpbMiwzN10sNjg6WzIsMzddLDcyOlsyLDM3XSw3NTpbMiwzN10sODA6WzIsMzddLDgxOlsyLDM3XSw4MjpbMiwzN10sODM6WzIsMzddLDg0OlsyLDM3XSw4NTpbMiwzN119LHsyMzpbMiwzOF0sMzM6WzIsMzhdLDU0OlsyLDM4XSw2NTpbMiwzOF0sNjg6WzIsMzhdLDcyOlsyLDM4XSw3NTpbMiwzOF0sODA6WzIsMzhdLDgxOlsyLDM4XSw4MjpbMiwzOF0sODM6WzIsMzhdLDg0OlsyLDM4XSw4NTpbMiwzOF19LHsyMzpbMiwzOV0sMzM6WzIsMzldLDU0OlsyLDM5XSw2NTpbMiwzOV0sNjg6WzIsMzldLDcyOlsyLDM5XSw3NTpbMiwzOV0sODA6WzIsMzldLDgxOlsyLDM5XSw4MjpbMiwzOV0sODM6WzIsMzldLDg0OlsyLDM5XSw4NTpbMiwzOV19LHsyMzpbMiw0M10sMzM6WzIsNDNdLDU0OlsyLDQzXSw2NTpbMiw0M10sNjg6WzIsNDNdLDcyOlsyLDQzXSw3NTpbMiw0M10sODA6WzIsNDNdLDgxOlsyLDQzXSw4MjpbMiw0M10sODM6WzIsNDNdLDg0OlsyLDQzXSw4NTpbMiw0M10sODc6WzEsNTFdfSx7NzI6WzEsMzVdLDg2OjUyfSx7MjM6WzIsNDVdLDMzOlsyLDQ1XSw1NDpbMiw0NV0sNjU6WzIsNDVdLDY4OlsyLDQ1XSw3MjpbMiw0NV0sNzU6WzIsNDVdLDgwOlsyLDQ1XSw4MTpbMiw0NV0sODI6WzIsNDVdLDgzOlsyLDQ1XSw4NDpbMiw0NV0sODU6WzIsNDVdLDg3OlsyLDQ1XX0sezUyOjUzLDU0OlsyLDgyXSw2NTpbMiw4Ml0sNzI6WzIsODJdLDgwOlsyLDgyXSw4MTpbMiw4Ml0sODI6WzIsODJdLDgzOlsyLDgyXSw4NDpbMiw4Ml0sODU6WzIsODJdfSx7MjU6NTQsMzg6NTYsMzk6WzEsNThdLDQzOjU3LDQ0OlsxLDU5XSw0NTo1NSw0NzpbMiw1NF19LHsyODo2MCw0Mzo2MSw0NDpbMSw1OV0sNDc6WzIsNTZdfSx7MTM6NjMsMTU6WzEsMjBdLDE4OlsxLDYyXX0sezE1OlsyLDQ4XSwxODpbMiw0OF19LHszMzpbMiw4Nl0sNTc6NjQsNjU6WzIsODZdLDcyOlsyLDg2XSw4MDpbMiw4Nl0sODE6WzIsODZdLDgyOlsyLDg2XSw4MzpbMiw4Nl0sODQ6WzIsODZdLDg1OlsyLDg2XX0sezMzOlsyLDQwXSw2NTpbMiw0MF0sNzI6WzIsNDBdLDgwOlsyLDQwXSw4MTpbMiw0MF0sODI6WzIsNDBdLDgzOlsyLDQwXSw4NDpbMiw0MF0sODU6WzIsNDBdfSx7MzM6WzIsNDFdLDY1OlsyLDQxXSw3MjpbMiw0MV0sODA6WzIsNDFdLDgxOlsyLDQxXSw4MjpbMiw0MV0sODM6WzIsNDFdLDg0OlsyLDQxXSw4NTpbMiw0MV19LHsyMDo2NSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyNjo2Niw0NzpbMSw2N119LHszMDo2OCwzMzpbMiw1OF0sNjU6WzIsNThdLDcyOlsyLDU4XSw3NTpbMiw1OF0sODA6WzIsNThdLDgxOlsyLDU4XSw4MjpbMiw1OF0sODM6WzIsNThdLDg0OlsyLDU4XSw4NTpbMiw1OF19LHszMzpbMiw2NF0sMzU6NjksNjU6WzIsNjRdLDcyOlsyLDY0XSw3NTpbMiw2NF0sODA6WzIsNjRdLDgxOlsyLDY0XSw4MjpbMiw2NF0sODM6WzIsNjRdLDg0OlsyLDY0XSw4NTpbMiw2NF19LHsyMTo3MCwyMzpbMiw1MF0sNjU6WzIsNTBdLDcyOlsyLDUwXSw4MDpbMiw1MF0sODE6WzIsNTBdLDgyOlsyLDUwXSw4MzpbMiw1MF0sODQ6WzIsNTBdLDg1OlsyLDUwXX0sezMzOlsyLDkwXSw2MTo3MSw2NTpbMiw5MF0sNzI6WzIsOTBdLDgwOlsyLDkwXSw4MTpbMiw5MF0sODI6WzIsOTBdLDgzOlsyLDkwXSw4NDpbMiw5MF0sODU6WzIsOTBdfSx7MjA6NzUsMzM6WzIsODBdLDUwOjcyLDYzOjczLDY0Ojc2LDY1OlsxLDQ0XSw2OTo3NCw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs3MjpbMSw4MF19LHsyMzpbMiw0Ml0sMzM6WzIsNDJdLDU0OlsyLDQyXSw2NTpbMiw0Ml0sNjg6WzIsNDJdLDcyOlsyLDQyXSw3NTpbMiw0Ml0sODA6WzIsNDJdLDgxOlsyLDQyXSw4MjpbMiw0Ml0sODM6WzIsNDJdLDg0OlsyLDQyXSw4NTpbMiw0Ml0sODc6WzEsNTFdfSx7MjA6NzUsNTM6ODEsNTQ6WzIsODRdLDYzOjgyLDY0Ojc2LDY1OlsxLDQ0XSw2OTo4Myw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHsyNjo4NCw0NzpbMSw2N119LHs0NzpbMiw1NV19LHs0Ojg1LDY6MywxNDpbMiw0Nl0sMTU6WzIsNDZdLDE5OlsyLDQ2XSwyOTpbMiw0Nl0sMzQ6WzIsNDZdLDM5OlsyLDQ2XSw0NDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezQ3OlsyLDIwXX0sezIwOjg2LDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezQ6ODcsNjozLDE0OlsyLDQ2XSwxNTpbMiw0Nl0sMTk6WzIsNDZdLDI5OlsyLDQ2XSwzNDpbMiw0Nl0sNDc6WzIsNDZdLDQ4OlsyLDQ2XSw1MTpbMiw0Nl0sNTU6WzIsNDZdLDYwOlsyLDQ2XX0sezI2Ojg4LDQ3OlsxLDY3XX0sezQ3OlsyLDU3XX0sezU6WzIsMTFdLDE0OlsyLDExXSwxNTpbMiwxMV0sMTk6WzIsMTFdLDI5OlsyLDExXSwzNDpbMiwxMV0sMzk6WzIsMTFdLDQ0OlsyLDExXSw0NzpbMiwxMV0sNDg6WzIsMTFdLDUxOlsyLDExXSw1NTpbMiwxMV0sNjA6WzIsMTFdfSx7MTU6WzIsNDldLDE4OlsyLDQ5XX0sezIwOjc1LDMzOlsyLDg4XSw1ODo4OSw2Mzo5MCw2NDo3Niw2NTpbMSw0NF0sNjk6OTEsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7NjU6WzIsOTRdLDY2OjkyLDY4OlsyLDk0XSw3MjpbMiw5NF0sODA6WzIsOTRdLDgxOlsyLDk0XSw4MjpbMiw5NF0sODM6WzIsOTRdLDg0OlsyLDk0XSw4NTpbMiw5NF19LHs1OlsyLDI1XSwxNDpbMiwyNV0sMTU6WzIsMjVdLDE5OlsyLDI1XSwyOTpbMiwyNV0sMzQ6WzIsMjVdLDM5OlsyLDI1XSw0NDpbMiwyNV0sNDc6WzIsMjVdLDQ4OlsyLDI1XSw1MTpbMiwyNV0sNTU6WzIsMjVdLDYwOlsyLDI1XX0sezIwOjkzLDcyOlsxLDM1XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDMxOjk0LDMzOlsyLDYwXSw2Mzo5NSw2NDo3Niw2NTpbMSw0NF0sNjk6OTYsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDYwXSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDMzOlsyLDY2XSwzNjo5Nyw2Mzo5OCw2NDo3Niw2NTpbMSw0NF0sNjk6OTksNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDY2XSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezIwOjc1LDIyOjEwMCwyMzpbMiw1Ml0sNjM6MTAxLDY0Ojc2LDY1OlsxLDQ0XSw2OToxMDIsNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc4OjI2LDc5OjI3LDgwOlsxLDI4XSw4MTpbMSwyOV0sODI6WzEsMzBdLDgzOlsxLDMxXSw4NDpbMSwzMl0sODU6WzEsMzRdLDg2OjMzfSx7MjA6NzUsMzM6WzIsOTJdLDYyOjEwMyw2MzoxMDQsNjQ6NzYsNjU6WzEsNDRdLDY5OjEwNSw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHszMzpbMSwxMDZdfSx7MzM6WzIsNzldLDY1OlsyLDc5XSw3MjpbMiw3OV0sODA6WzIsNzldLDgxOlsyLDc5XSw4MjpbMiw3OV0sODM6WzIsNzldLDg0OlsyLDc5XSw4NTpbMiw3OV19LHszMzpbMiw4MV19LHsyMzpbMiwyN10sMzM6WzIsMjddLDU0OlsyLDI3XSw2NTpbMiwyN10sNjg6WzIsMjddLDcyOlsyLDI3XSw3NTpbMiwyN10sODA6WzIsMjddLDgxOlsyLDI3XSw4MjpbMiwyN10sODM6WzIsMjddLDg0OlsyLDI3XSw4NTpbMiwyN119LHsyMzpbMiwyOF0sMzM6WzIsMjhdLDU0OlsyLDI4XSw2NTpbMiwyOF0sNjg6WzIsMjhdLDcyOlsyLDI4XSw3NTpbMiwyOF0sODA6WzIsMjhdLDgxOlsyLDI4XSw4MjpbMiwyOF0sODM6WzIsMjhdLDg0OlsyLDI4XSw4NTpbMiwyOF19LHsyMzpbMiwzMF0sMzM6WzIsMzBdLDU0OlsyLDMwXSw2ODpbMiwzMF0sNzE6MTA3LDcyOlsxLDEwOF0sNzU6WzIsMzBdfSx7MjM6WzIsOThdLDMzOlsyLDk4XSw1NDpbMiw5OF0sNjg6WzIsOThdLDcyOlsyLDk4XSw3NTpbMiw5OF19LHsyMzpbMiw0NV0sMzM6WzIsNDVdLDU0OlsyLDQ1XSw2NTpbMiw0NV0sNjg6WzIsNDVdLDcyOlsyLDQ1XSw3MzpbMSwxMDldLDc1OlsyLDQ1XSw4MDpbMiw0NV0sODE6WzIsNDVdLDgyOlsyLDQ1XSw4MzpbMiw0NV0sODQ6WzIsNDVdLDg1OlsyLDQ1XSw4NzpbMiw0NV19LHsyMzpbMiw0NF0sMzM6WzIsNDRdLDU0OlsyLDQ0XSw2NTpbMiw0NF0sNjg6WzIsNDRdLDcyOlsyLDQ0XSw3NTpbMiw0NF0sODA6WzIsNDRdLDgxOlsyLDQ0XSw4MjpbMiw0NF0sODM6WzIsNDRdLDg0OlsyLDQ0XSw4NTpbMiw0NF0sODc6WzIsNDRdfSx7NTQ6WzEsMTEwXX0sezU0OlsyLDgzXSw2NTpbMiw4M10sNzI6WzIsODNdLDgwOlsyLDgzXSw4MTpbMiw4M10sODI6WzIsODNdLDgzOlsyLDgzXSw4NDpbMiw4M10sODU6WzIsODNdfSx7NTQ6WzIsODVdfSx7NTpbMiwxM10sMTQ6WzIsMTNdLDE1OlsyLDEzXSwxOTpbMiwxM10sMjk6WzIsMTNdLDM0OlsyLDEzXSwzOTpbMiwxM10sNDQ6WzIsMTNdLDQ3OlsyLDEzXSw0ODpbMiwxM10sNTE6WzIsMTNdLDU1OlsyLDEzXSw2MDpbMiwxM119LHszODo1NiwzOTpbMSw1OF0sNDM6NTcsNDQ6WzEsNTldLDQ1OjExMiw0NjoxMTEsNDc6WzIsNzZdfSx7MzM6WzIsNzBdLDQwOjExMyw2NTpbMiw3MF0sNzI6WzIsNzBdLDc1OlsyLDcwXSw4MDpbMiw3MF0sODE6WzIsNzBdLDgyOlsyLDcwXSw4MzpbMiw3MF0sODQ6WzIsNzBdLDg1OlsyLDcwXX0sezQ3OlsyLDE4XX0sezU6WzIsMTRdLDE0OlsyLDE0XSwxNTpbMiwxNF0sMTk6WzIsMTRdLDI5OlsyLDE0XSwzNDpbMiwxNF0sMzk6WzIsMTRdLDQ0OlsyLDE0XSw0NzpbMiwxNF0sNDg6WzIsMTRdLDUxOlsyLDE0XSw1NTpbMiwxNF0sNjA6WzIsMTRdfSx7MzM6WzEsMTE0XX0sezMzOlsyLDg3XSw2NTpbMiw4N10sNzI6WzIsODddLDgwOlsyLDg3XSw4MTpbMiw4N10sODI6WzIsODddLDgzOlsyLDg3XSw4NDpbMiw4N10sODU6WzIsODddfSx7MzM6WzIsODldfSx7MjA6NzUsNjM6MTE2LDY0Ojc2LDY1OlsxLDQ0XSw2NzoxMTUsNjg6WzIsOTZdLDY5OjExNyw3MDo3Nyw3MTo3OCw3MjpbMSw3OV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHszMzpbMSwxMThdfSx7MzI6MTE5LDMzOlsyLDYyXSw3NDoxMjAsNzU6WzEsMTIxXX0sezMzOlsyLDU5XSw2NTpbMiw1OV0sNzI6WzIsNTldLDc1OlsyLDU5XSw4MDpbMiw1OV0sODE6WzIsNTldLDgyOlsyLDU5XSw4MzpbMiw1OV0sODQ6WzIsNTldLDg1OlsyLDU5XX0sezMzOlsyLDYxXSw3NTpbMiw2MV19LHszMzpbMiw2OF0sMzc6MTIyLDc0OjEyMyw3NTpbMSwxMjFdfSx7MzM6WzIsNjVdLDY1OlsyLDY1XSw3MjpbMiw2NV0sNzU6WzIsNjVdLDgwOlsyLDY1XSw4MTpbMiw2NV0sODI6WzIsNjVdLDgzOlsyLDY1XSw4NDpbMiw2NV0sODU6WzIsNjVdfSx7MzM6WzIsNjddLDc1OlsyLDY3XX0sezIzOlsxLDEyNF19LHsyMzpbMiw1MV0sNjU6WzIsNTFdLDcyOlsyLDUxXSw4MDpbMiw1MV0sODE6WzIsNTFdLDgyOlsyLDUxXSw4MzpbMiw1MV0sODQ6WzIsNTFdLDg1OlsyLDUxXX0sezIzOlsyLDUzXX0sezMzOlsxLDEyNV19LHszMzpbMiw5MV0sNjU6WzIsOTFdLDcyOlsyLDkxXSw4MDpbMiw5MV0sODE6WzIsOTFdLDgyOlsyLDkxXSw4MzpbMiw5MV0sODQ6WzIsOTFdLDg1OlsyLDkxXX0sezMzOlsyLDkzXX0sezU6WzIsMjJdLDE0OlsyLDIyXSwxNTpbMiwyMl0sMTk6WzIsMjJdLDI5OlsyLDIyXSwzNDpbMiwyMl0sMzk6WzIsMjJdLDQ0OlsyLDIyXSw0NzpbMiwyMl0sNDg6WzIsMjJdLDUxOlsyLDIyXSw1NTpbMiwyMl0sNjA6WzIsMjJdfSx7MjM6WzIsOTldLDMzOlsyLDk5XSw1NDpbMiw5OV0sNjg6WzIsOTldLDcyOlsyLDk5XSw3NTpbMiw5OV19LHs3MzpbMSwxMDldfSx7MjA6NzUsNjM6MTI2LDY0Ojc2LDY1OlsxLDQ0XSw3MjpbMSwzNV0sNzg6MjYsNzk6MjcsODA6WzEsMjhdLDgxOlsxLDI5XSw4MjpbMSwzMF0sODM6WzEsMzFdLDg0OlsxLDMyXSw4NTpbMSwzNF0sODY6MzN9LHs1OlsyLDIzXSwxNDpbMiwyM10sMTU6WzIsMjNdLDE5OlsyLDIzXSwyOTpbMiwyM10sMzQ6WzIsMjNdLDM5OlsyLDIzXSw0NDpbMiwyM10sNDc6WzIsMjNdLDQ4OlsyLDIzXSw1MTpbMiwyM10sNTU6WzIsMjNdLDYwOlsyLDIzXX0sezQ3OlsyLDE5XX0sezQ3OlsyLDc3XX0sezIwOjc1LDMzOlsyLDcyXSw0MToxMjcsNjM6MTI4LDY0Ojc2LDY1OlsxLDQ0XSw2OToxMjksNzA6NzcsNzE6NzgsNzI6WzEsNzldLDc1OlsyLDcyXSw3ODoyNiw3OToyNyw4MDpbMSwyOF0sODE6WzEsMjldLDgyOlsxLDMwXSw4MzpbMSwzMV0sODQ6WzEsMzJdLDg1OlsxLDM0XSw4NjozM30sezU6WzIsMjRdLDE0OlsyLDI0XSwxNTpbMiwyNF0sMTk6WzIsMjRdLDI5OlsyLDI0XSwzNDpbMiwyNF0sMzk6WzIsMjRdLDQ0OlsyLDI0XSw0NzpbMiwyNF0sNDg6WzIsMjRdLDUxOlsyLDI0XSw1NTpbMiwyNF0sNjA6WzIsMjRdfSx7Njg6WzEsMTMwXX0sezY1OlsyLDk1XSw2ODpbMiw5NV0sNzI6WzIsOTVdLDgwOlsyLDk1XSw4MTpbMiw5NV0sODI6WzIsOTVdLDgzOlsyLDk1XSw4NDpbMiw5NV0sODU6WzIsOTVdfSx7Njg6WzIsOTddfSx7NTpbMiwyMV0sMTQ6WzIsMjFdLDE1OlsyLDIxXSwxOTpbMiwyMV0sMjk6WzIsMjFdLDM0OlsyLDIxXSwzOTpbMiwyMV0sNDQ6WzIsMjFdLDQ3OlsyLDIxXSw0ODpbMiwyMV0sNTE6WzIsMjFdLDU1OlsyLDIxXSw2MDpbMiwyMV19LHszMzpbMSwxMzFdfSx7MzM6WzIsNjNdfSx7NzI6WzEsMTMzXSw3NjoxMzJ9LHszMzpbMSwxMzRdfSx7MzM6WzIsNjldfSx7MTU6WzIsMTJdfSx7MTQ6WzIsMjZdLDE1OlsyLDI2XSwxOTpbMiwyNl0sMjk6WzIsMjZdLDM0OlsyLDI2XSw0NzpbMiwyNl0sNDg6WzIsMjZdLDUxOlsyLDI2XSw1NTpbMiwyNl0sNjA6WzIsMjZdfSx7MjM6WzIsMzFdLDMzOlsyLDMxXSw1NDpbMiwzMV0sNjg6WzIsMzFdLDcyOlsyLDMxXSw3NTpbMiwzMV19LHszMzpbMiw3NF0sNDI6MTM1LDc0OjEzNiw3NTpbMSwxMjFdfSx7MzM6WzIsNzFdLDY1OlsyLDcxXSw3MjpbMiw3MV0sNzU6WzIsNzFdLDgwOlsyLDcxXSw4MTpbMiw3MV0sODI6WzIsNzFdLDgzOlsyLDcxXSw4NDpbMiw3MV0sODU6WzIsNzFdfSx7MzM6WzIsNzNdLDc1OlsyLDczXX0sezIzOlsyLDI5XSwzMzpbMiwyOV0sNTQ6WzIsMjldLDY1OlsyLDI5XSw2ODpbMiwyOV0sNzI6WzIsMjldLDc1OlsyLDI5XSw4MDpbMiwyOV0sODE6WzIsMjldLDgyOlsyLDI5XSw4MzpbMiwyOV0sODQ6WzIsMjldLDg1OlsyLDI5XX0sezE0OlsyLDE1XSwxNTpbMiwxNV0sMTk6WzIsMTVdLDI5OlsyLDE1XSwzNDpbMiwxNV0sMzk6WzIsMTVdLDQ0OlsyLDE1XSw0NzpbMiwxNV0sNDg6WzIsMTVdLDUxOlsyLDE1XSw1NTpbMiwxNV0sNjA6WzIsMTVdfSx7NzI6WzEsMTM4XSw3NzpbMSwxMzddfSx7NzI6WzIsMTAwXSw3NzpbMiwxMDBdfSx7MTQ6WzIsMTZdLDE1OlsyLDE2XSwxOTpbMiwxNl0sMjk6WzIsMTZdLDM0OlsyLDE2XSw0NDpbMiwxNl0sNDc6WzIsMTZdLDQ4OlsyLDE2XSw1MTpbMiwxNl0sNTU6WzIsMTZdLDYwOlsyLDE2XX0sezMzOlsxLDEzOV19LHszMzpbMiw3NV19LHszMzpbMiwzMl19LHs3MjpbMiwxMDFdLDc3OlsyLDEwMV19LHsxNDpbMiwxN10sMTU6WzIsMTddLDE5OlsyLDE3XSwyOTpbMiwxN10sMzQ6WzIsMTddLDM5OlsyLDE3XSw0NDpbMiwxN10sNDc6WzIsMTddLDQ4OlsyLDE3XSw1MTpbMiwxN10sNTU6WzIsMTddLDYwOlsyLDE3XX1dLFxuZGVmYXVsdEFjdGlvbnM6IHs0OlsyLDFdLDU1OlsyLDU1XSw1NzpbMiwyMF0sNjE6WzIsNTddLDc0OlsyLDgxXSw4MzpbMiw4NV0sODc6WzIsMThdLDkxOlsyLDg5XSwxMDI6WzIsNTNdLDEwNTpbMiw5M10sMTExOlsyLDE5XSwxMTI6WzIsNzddLDExNzpbMiw5N10sMTIwOlsyLDYzXSwxMjM6WzIsNjldLDEyNDpbMiwxMl0sMTM2OlsyLDc1XSwxMzc6WzIsMzJdfSxcbnBhcnNlRXJyb3I6IGZ1bmN0aW9uIHBhcnNlRXJyb3Ioc3RyLCBoYXNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHN0cik7XG59LFxucGFyc2U6IGZ1bmN0aW9uIHBhcnNlKGlucHV0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzLCBzdGFjayA9IFswXSwgdnN0YWNrID0gW251bGxdLCBsc3RhY2sgPSBbXSwgdGFibGUgPSB0aGlzLnRhYmxlLCB5eXRleHQgPSBcIlwiLCB5eWxpbmVubyA9IDAsIHl5bGVuZyA9IDAsIHJlY292ZXJpbmcgPSAwLCBURVJST1IgPSAyLCBFT0YgPSAxO1xuICAgIHRoaXMubGV4ZXIuc2V0SW5wdXQoaW5wdXQpO1xuICAgIHRoaXMubGV4ZXIueXkgPSB0aGlzLnl5O1xuICAgIHRoaXMueXkubGV4ZXIgPSB0aGlzLmxleGVyO1xuICAgIHRoaXMueXkucGFyc2VyID0gdGhpcztcbiAgICBpZiAodHlwZW9mIHRoaXMubGV4ZXIueXlsbG9jID09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgIHRoaXMubGV4ZXIueXlsbG9jID0ge307XG4gICAgdmFyIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgbHN0YWNrLnB1c2goeXlsb2MpO1xuICAgIHZhciByYW5nZXMgPSB0aGlzLmxleGVyLm9wdGlvbnMgJiYgdGhpcy5sZXhlci5vcHRpb25zLnJhbmdlcztcbiAgICBpZiAodHlwZW9mIHRoaXMueXkucGFyc2VFcnJvciA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSB0aGlzLnl5LnBhcnNlRXJyb3I7XG4gICAgZnVuY3Rpb24gcG9wU3RhY2sobikge1xuICAgICAgICBzdGFjay5sZW5ndGggPSBzdGFjay5sZW5ndGggLSAyICogbjtcbiAgICAgICAgdnN0YWNrLmxlbmd0aCA9IHZzdGFjay5sZW5ndGggLSBuO1xuICAgICAgICBsc3RhY2subGVuZ3RoID0gbHN0YWNrLmxlbmd0aCAtIG47XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxleCgpIHtcbiAgICAgICAgdmFyIHRva2VuO1xuICAgICAgICB0b2tlbiA9IHNlbGYubGV4ZXIubGV4KCkgfHwgMTtcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdG9rZW4gPSBzZWxmLnN5bWJvbHNfW3Rva2VuXSB8fCB0b2tlbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9rZW47XG4gICAgfVxuICAgIHZhciBzeW1ib2wsIHByZUVycm9yU3ltYm9sLCBzdGF0ZSwgYWN0aW9uLCBhLCByLCB5eXZhbCA9IHt9LCBwLCBsZW4sIG5ld1N0YXRlLCBleHBlY3RlZDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBzdGF0ZSA9IHN0YWNrW3N0YWNrLmxlbmd0aCAtIDFdO1xuICAgICAgICBpZiAodGhpcy5kZWZhdWx0QWN0aW9uc1tzdGF0ZV0pIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IHRoaXMuZGVmYXVsdEFjdGlvbnNbc3RhdGVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHN5bWJvbCA9PT0gbnVsbCB8fCB0eXBlb2Ygc3ltYm9sID09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICBzeW1ib2wgPSBsZXgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjdGlvbiA9IHRhYmxlW3N0YXRlXSAmJiB0YWJsZVtzdGF0ZV1bc3ltYm9sXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGFjdGlvbiA9PT0gXCJ1bmRlZmluZWRcIiB8fCAhYWN0aW9uLmxlbmd0aCB8fCAhYWN0aW9uWzBdKSB7XG4gICAgICAgICAgICB2YXIgZXJyU3RyID0gXCJcIjtcbiAgICAgICAgICAgIGlmICghcmVjb3ZlcmluZykge1xuICAgICAgICAgICAgICAgIGV4cGVjdGVkID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChwIGluIHRhYmxlW3N0YXRlXSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudGVybWluYWxzX1twXSAmJiBwID4gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQucHVzaChcIidcIiArIHRoaXMudGVybWluYWxzX1twXSArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxleGVyLnNob3dQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBlcnJTdHIgPSBcIlBhcnNlIGVycm9yIG9uIGxpbmUgXCIgKyAoeXlsaW5lbm8gKyAxKSArIFwiOlxcblwiICsgdGhpcy5sZXhlci5zaG93UG9zaXRpb24oKSArIFwiXFxuRXhwZWN0aW5nIFwiICsgZXhwZWN0ZWQuam9pbihcIiwgXCIpICsgXCIsIGdvdCAnXCIgKyAodGhpcy50ZXJtaW5hbHNfW3N5bWJvbF0gfHwgc3ltYm9sKSArIFwiJ1wiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVyclN0ciA9IFwiUGFyc2UgZXJyb3Igb24gbGluZSBcIiArICh5eWxpbmVubyArIDEpICsgXCI6IFVuZXhwZWN0ZWQgXCIgKyAoc3ltYm9sID09IDE/XCJlbmQgb2YgaW5wdXRcIjpcIidcIiArICh0aGlzLnRlcm1pbmFsc19bc3ltYm9sXSB8fCBzeW1ib2wpICsgXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IoZXJyU3RyLCB7dGV4dDogdGhpcy5sZXhlci5tYXRjaCwgdG9rZW46IHRoaXMudGVybWluYWxzX1tzeW1ib2xdIHx8IHN5bWJvbCwgbGluZTogdGhpcy5sZXhlci55eWxpbmVubywgbG9jOiB5eWxvYywgZXhwZWN0ZWQ6IGV4cGVjdGVkfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGlvblswXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFjdGlvbi5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQYXJzZSBFcnJvcjogbXVsdGlwbGUgYWN0aW9ucyBwb3NzaWJsZSBhdCBzdGF0ZTogXCIgKyBzdGF0ZSArIFwiLCB0b2tlbjogXCIgKyBzeW1ib2wpO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uWzBdKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHN0YWNrLnB1c2goc3ltYm9sKTtcbiAgICAgICAgICAgIHZzdGFjay5wdXNoKHRoaXMubGV4ZXIueXl0ZXh0KTtcbiAgICAgICAgICAgIGxzdGFjay5wdXNoKHRoaXMubGV4ZXIueXlsbG9jKTtcbiAgICAgICAgICAgIHN0YWNrLnB1c2goYWN0aW9uWzFdKTtcbiAgICAgICAgICAgIHN5bWJvbCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIXByZUVycm9yU3ltYm9sKSB7XG4gICAgICAgICAgICAgICAgeXlsZW5nID0gdGhpcy5sZXhlci55eWxlbmc7XG4gICAgICAgICAgICAgICAgeXl0ZXh0ID0gdGhpcy5sZXhlci55eXRleHQ7XG4gICAgICAgICAgICAgICAgeXlsaW5lbm8gPSB0aGlzLmxleGVyLnl5bGluZW5vO1xuICAgICAgICAgICAgICAgIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgICAgICAgICAgICAgaWYgKHJlY292ZXJpbmcgPiAwKVxuICAgICAgICAgICAgICAgICAgICByZWNvdmVyaW5nLS07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN5bWJvbCA9IHByZUVycm9yU3ltYm9sO1xuICAgICAgICAgICAgICAgIHByZUVycm9yU3ltYm9sID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICBsZW4gPSB0aGlzLnByb2R1Y3Rpb25zX1thY3Rpb25bMV1dWzFdO1xuICAgICAgICAgICAgeXl2YWwuJCA9IHZzdGFja1t2c3RhY2subGVuZ3RoIC0gbGVuXTtcbiAgICAgICAgICAgIHl5dmFsLl8kID0ge2ZpcnN0X2xpbmU6IGxzdGFja1tsc3RhY2subGVuZ3RoIC0gKGxlbiB8fCAxKV0uZmlyc3RfbGluZSwgbGFzdF9saW5lOiBsc3RhY2tbbHN0YWNrLmxlbmd0aCAtIDFdLmxhc3RfbGluZSwgZmlyc3RfY29sdW1uOiBsc3RhY2tbbHN0YWNrLmxlbmd0aCAtIChsZW4gfHwgMSldLmZpcnN0X2NvbHVtbiwgbGFzdF9jb2x1bW46IGxzdGFja1tsc3RhY2subGVuZ3RoIC0gMV0ubGFzdF9jb2x1bW59O1xuICAgICAgICAgICAgaWYgKHJhbmdlcykge1xuICAgICAgICAgICAgICAgIHl5dmFsLl8kLnJhbmdlID0gW2xzdGFja1tsc3RhY2subGVuZ3RoIC0gKGxlbiB8fCAxKV0ucmFuZ2VbMF0sIGxzdGFja1tsc3RhY2subGVuZ3RoIC0gMV0ucmFuZ2VbMV1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgciA9IHRoaXMucGVyZm9ybUFjdGlvbi5jYWxsKHl5dmFsLCB5eXRleHQsIHl5bGVuZywgeXlsaW5lbm8sIHRoaXMueXksIGFjdGlvblsxXSwgdnN0YWNrLCBsc3RhY2spO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGVuKSB7XG4gICAgICAgICAgICAgICAgc3RhY2sgPSBzdGFjay5zbGljZSgwLCAtMSAqIGxlbiAqIDIpO1xuICAgICAgICAgICAgICAgIHZzdGFjayA9IHZzdGFjay5zbGljZSgwLCAtMSAqIGxlbik7XG4gICAgICAgICAgICAgICAgbHN0YWNrID0gbHN0YWNrLnNsaWNlKDAsIC0xICogbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YWNrLnB1c2godGhpcy5wcm9kdWN0aW9uc19bYWN0aW9uWzFdXVswXSk7XG4gICAgICAgICAgICB2c3RhY2sucHVzaCh5eXZhbC4kKTtcbiAgICAgICAgICAgIGxzdGFjay5wdXNoKHl5dmFsLl8kKTtcbiAgICAgICAgICAgIG5ld1N0YXRlID0gdGFibGVbc3RhY2tbc3RhY2subGVuZ3RoIC0gMl1dW3N0YWNrW3N0YWNrLmxlbmd0aCAtIDFdXTtcbiAgICAgICAgICAgIHN0YWNrLnB1c2gobmV3U3RhdGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxufTtcbi8qIEppc29uIGdlbmVyYXRlZCBsZXhlciAqL1xudmFyIGxleGVyID0gKGZ1bmN0aW9uKCl7XG52YXIgbGV4ZXIgPSAoe0VPRjoxLFxucGFyc2VFcnJvcjpmdW5jdGlvbiBwYXJzZUVycm9yKHN0ciwgaGFzaCkge1xuICAgICAgICBpZiAodGhpcy55eS5wYXJzZXIpIHtcbiAgICAgICAgICAgIHRoaXMueXkucGFyc2VyLnBhcnNlRXJyb3Ioc3RyLCBoYXNoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihzdHIpO1xuICAgICAgICB9XG4gICAgfSxcbnNldElucHV0OmZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICB0aGlzLl9pbnB1dCA9IGlucHV0O1xuICAgICAgICB0aGlzLl9tb3JlID0gdGhpcy5fbGVzcyA9IHRoaXMuZG9uZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnl5bGluZW5vID0gdGhpcy55eWxlbmcgPSAwO1xuICAgICAgICB0aGlzLnl5dGV4dCA9IHRoaXMubWF0Y2hlZCA9IHRoaXMubWF0Y2ggPSAnJztcbiAgICAgICAgdGhpcy5jb25kaXRpb25TdGFjayA9IFsnSU5JVElBTCddO1xuICAgICAgICB0aGlzLnl5bGxvYyA9IHtmaXJzdF9saW5lOjEsZmlyc3RfY29sdW1uOjAsbGFzdF9saW5lOjEsbGFzdF9jb2x1bW46MH07XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB0aGlzLnl5bGxvYy5yYW5nZSA9IFswLDBdO1xuICAgICAgICB0aGlzLm9mZnNldCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5pbnB1dDpmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjaCA9IHRoaXMuX2lucHV0WzBdO1xuICAgICAgICB0aGlzLnl5dGV4dCArPSBjaDtcbiAgICAgICAgdGhpcy55eWxlbmcrKztcbiAgICAgICAgdGhpcy5vZmZzZXQrKztcbiAgICAgICAgdGhpcy5tYXRjaCArPSBjaDtcbiAgICAgICAgdGhpcy5tYXRjaGVkICs9IGNoO1xuICAgICAgICB2YXIgbGluZXMgPSBjaC5tYXRjaCgvKD86XFxyXFxuP3xcXG4pLiovZyk7XG4gICAgICAgIGlmIChsaW5lcykge1xuICAgICAgICAgICAgdGhpcy55eWxpbmVubysrO1xuICAgICAgICAgICAgdGhpcy55eWxsb2MubGFzdF9saW5lKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnl5bGxvYy5sYXN0X2NvbHVtbisrO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB0aGlzLnl5bGxvYy5yYW5nZVsxXSsrO1xuXG4gICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiBjaDtcbiAgICB9LFxudW5wdXQ6ZnVuY3Rpb24gKGNoKSB7XG4gICAgICAgIHZhciBsZW4gPSBjaC5sZW5ndGg7XG4gICAgICAgIHZhciBsaW5lcyA9IGNoLnNwbGl0KC8oPzpcXHJcXG4/fFxcbikvZyk7XG5cbiAgICAgICAgdGhpcy5faW5wdXQgPSBjaCArIHRoaXMuX2lucHV0O1xuICAgICAgICB0aGlzLnl5dGV4dCA9IHRoaXMueXl0ZXh0LnN1YnN0cigwLCB0aGlzLnl5dGV4dC5sZW5ndGgtbGVuLTEpO1xuICAgICAgICAvL3RoaXMueXlsZW5nIC09IGxlbjtcbiAgICAgICAgdGhpcy5vZmZzZXQgLT0gbGVuO1xuICAgICAgICB2YXIgb2xkTGluZXMgPSB0aGlzLm1hdGNoLnNwbGl0KC8oPzpcXHJcXG4/fFxcbikvZyk7XG4gICAgICAgIHRoaXMubWF0Y2ggPSB0aGlzLm1hdGNoLnN1YnN0cigwLCB0aGlzLm1hdGNoLmxlbmd0aC0xKTtcbiAgICAgICAgdGhpcy5tYXRjaGVkID0gdGhpcy5tYXRjaGVkLnN1YnN0cigwLCB0aGlzLm1hdGNoZWQubGVuZ3RoLTEpO1xuXG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGgtMSkgdGhpcy55eWxpbmVubyAtPSBsaW5lcy5sZW5ndGgtMTtcbiAgICAgICAgdmFyIHIgPSB0aGlzLnl5bGxvYy5yYW5nZTtcblxuICAgICAgICB0aGlzLnl5bGxvYyA9IHtmaXJzdF9saW5lOiB0aGlzLnl5bGxvYy5maXJzdF9saW5lLFxuICAgICAgICAgIGxhc3RfbGluZTogdGhpcy55eWxpbmVubysxLFxuICAgICAgICAgIGZpcnN0X2NvbHVtbjogdGhpcy55eWxsb2MuZmlyc3RfY29sdW1uLFxuICAgICAgICAgIGxhc3RfY29sdW1uOiBsaW5lcyA/XG4gICAgICAgICAgICAgIChsaW5lcy5sZW5ndGggPT09IG9sZExpbmVzLmxlbmd0aCA/IHRoaXMueXlsbG9jLmZpcnN0X2NvbHVtbiA6IDApICsgb2xkTGluZXNbb2xkTGluZXMubGVuZ3RoIC0gbGluZXMubGVuZ3RoXS5sZW5ndGggLSBsaW5lc1swXS5sZW5ndGg6XG4gICAgICAgICAgICAgIHRoaXMueXlsbG9jLmZpcnN0X2NvbHVtbiAtIGxlblxuICAgICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5yYW5nZXMpIHtcbiAgICAgICAgICAgIHRoaXMueXlsbG9jLnJhbmdlID0gW3JbMF0sIHJbMF0gKyB0aGlzLnl5bGVuZyAtIGxlbl07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbm1vcmU6ZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9tb3JlID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbmxlc3M6ZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgdGhpcy51bnB1dCh0aGlzLm1hdGNoLnNsaWNlKG4pKTtcbiAgICB9LFxucGFzdElucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHBhc3QgPSB0aGlzLm1hdGNoZWQuc3Vic3RyKDAsIHRoaXMubWF0Y2hlZC5sZW5ndGggLSB0aGlzLm1hdGNoLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiAocGFzdC5sZW5ndGggPiAyMCA/ICcuLi4nOicnKSArIHBhc3Quc3Vic3RyKC0yMCkucmVwbGFjZSgvXFxuL2csIFwiXCIpO1xuICAgIH0sXG51cGNvbWluZ0lucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5leHQgPSB0aGlzLm1hdGNoO1xuICAgICAgICBpZiAobmV4dC5sZW5ndGggPCAyMCkge1xuICAgICAgICAgICAgbmV4dCArPSB0aGlzLl9pbnB1dC5zdWJzdHIoMCwgMjAtbmV4dC5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAobmV4dC5zdWJzdHIoMCwyMCkrKG5leHQubGVuZ3RoID4gMjAgPyAnLi4uJzonJykpLnJlcGxhY2UoL1xcbi9nLCBcIlwiKTtcbiAgICB9LFxuc2hvd1Bvc2l0aW9uOmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByZSA9IHRoaXMucGFzdElucHV0KCk7XG4gICAgICAgIHZhciBjID0gbmV3IEFycmF5KHByZS5sZW5ndGggKyAxKS5qb2luKFwiLVwiKTtcbiAgICAgICAgcmV0dXJuIHByZSArIHRoaXMudXBjb21pbmdJbnB1dCgpICsgXCJcXG5cIiArIGMrXCJeXCI7XG4gICAgfSxcbm5leHQ6ZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kb25lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5FT0Y7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9pbnB1dCkgdGhpcy5kb25lID0gdHJ1ZTtcblxuICAgICAgICB2YXIgdG9rZW4sXG4gICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgIHRlbXBNYXRjaCxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgY29sLFxuICAgICAgICAgICAgbGluZXM7XG4gICAgICAgIGlmICghdGhpcy5fbW9yZSkge1xuICAgICAgICAgICAgdGhpcy55eXRleHQgPSAnJztcbiAgICAgICAgICAgIHRoaXMubWF0Y2ggPSAnJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcnVsZXMgPSB0aGlzLl9jdXJyZW50UnVsZXMoKTtcbiAgICAgICAgZm9yICh2YXIgaT0wO2kgPCBydWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGVtcE1hdGNoID0gdGhpcy5faW5wdXQubWF0Y2godGhpcy5ydWxlc1tydWxlc1tpXV0pO1xuICAgICAgICAgICAgaWYgKHRlbXBNYXRjaCAmJiAoIW1hdGNoIHx8IHRlbXBNYXRjaFswXS5sZW5ndGggPiBtYXRjaFswXS5sZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2ggPSB0ZW1wTWF0Y2g7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5vcHRpb25zLmZsZXgpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgbGluZXMgPSBtYXRjaFswXS5tYXRjaCgvKD86XFxyXFxuP3xcXG4pLiovZyk7XG4gICAgICAgICAgICBpZiAobGluZXMpIHRoaXMueXlsaW5lbm8gKz0gbGluZXMubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy55eWxsb2MgPSB7Zmlyc3RfbGluZTogdGhpcy55eWxsb2MubGFzdF9saW5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9saW5lOiB0aGlzLnl5bGluZW5vKzEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBmaXJzdF9jb2x1bW46IHRoaXMueXlsbG9jLmxhc3RfY29sdW1uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9jb2x1bW46IGxpbmVzID8gbGluZXNbbGluZXMubGVuZ3RoLTFdLmxlbmd0aC1saW5lc1tsaW5lcy5sZW5ndGgtMV0ubWF0Y2goL1xccj9cXG4/LylbMF0ubGVuZ3RoIDogdGhpcy55eWxsb2MubGFzdF9jb2x1bW4gKyBtYXRjaFswXS5sZW5ndGh9O1xuICAgICAgICAgICAgdGhpcy55eXRleHQgKz0gbWF0Y2hbMF07XG4gICAgICAgICAgICB0aGlzLm1hdGNoICs9IG1hdGNoWzBdO1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzID0gbWF0Y2g7XG4gICAgICAgICAgICB0aGlzLnl5bGVuZyA9IHRoaXMueXl0ZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy55eWxsb2MucmFuZ2UgPSBbdGhpcy5vZmZzZXQsIHRoaXMub2Zmc2V0ICs9IHRoaXMueXlsZW5nXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX21vcmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UobWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMubWF0Y2hlZCArPSBtYXRjaFswXTtcbiAgICAgICAgICAgIHRva2VuID0gdGhpcy5wZXJmb3JtQWN0aW9uLmNhbGwodGhpcywgdGhpcy55eSwgdGhpcywgcnVsZXNbaW5kZXhdLHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMV0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuZG9uZSAmJiB0aGlzLl9pbnB1dCkgdGhpcy5kb25lID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodG9rZW4pIHJldHVybiB0b2tlbjtcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnB1dCA9PT0gXCJcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuRU9GO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VFcnJvcignTGV4aWNhbCBlcnJvciBvbiBsaW5lICcrKHRoaXMueXlsaW5lbm8rMSkrJy4gVW5yZWNvZ25pemVkIHRleHQuXFxuJyt0aGlzLnNob3dQb3NpdGlvbigpLFxuICAgICAgICAgICAgICAgICAgICB7dGV4dDogXCJcIiwgdG9rZW46IG51bGwsIGxpbmU6IHRoaXMueXlsaW5lbm99KTtcbiAgICAgICAgfVxuICAgIH0sXG5sZXg6ZnVuY3Rpb24gbGV4KCkge1xuICAgICAgICB2YXIgciA9IHRoaXMubmV4dCgpO1xuICAgICAgICBpZiAodHlwZW9mIHIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxleCgpO1xuICAgICAgICB9XG4gICAgfSxcbmJlZ2luOmZ1bmN0aW9uIGJlZ2luKGNvbmRpdGlvbikge1xuICAgICAgICB0aGlzLmNvbmRpdGlvblN0YWNrLnB1c2goY29uZGl0aW9uKTtcbiAgICB9LFxucG9wU3RhdGU6ZnVuY3Rpb24gcG9wU3RhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRpdGlvblN0YWNrLnBvcCgpO1xuICAgIH0sXG5fY3VycmVudFJ1bGVzOmZ1bmN0aW9uIF9jdXJyZW50UnVsZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRpdGlvbnNbdGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0xXV0ucnVsZXM7XG4gICAgfSxcbnRvcFN0YXRlOmZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMl07XG4gICAgfSxcbnB1c2hTdGF0ZTpmdW5jdGlvbiBiZWdpbihjb25kaXRpb24pIHtcbiAgICAgICAgdGhpcy5iZWdpbihjb25kaXRpb24pO1xuICAgIH19KTtcbmxleGVyLm9wdGlvbnMgPSB7fTtcbmxleGVyLnBlcmZvcm1BY3Rpb24gPSBmdW5jdGlvbiBhbm9ueW1vdXMoeXkseXlfLCRhdm9pZGluZ19uYW1lX2NvbGxpc2lvbnMsWVlfU1RBUlRcbi8qKi8pIHtcblxuXG5mdW5jdGlvbiBzdHJpcChzdGFydCwgZW5kKSB7XG4gIHJldHVybiB5eV8ueXl0ZXh0ID0geXlfLnl5dGV4dC5zdWJzdHIoc3RhcnQsIHl5Xy55eWxlbmctZW5kKTtcbn1cblxuXG52YXIgWVlTVEFURT1ZWV9TVEFSVFxuc3dpdGNoKCRhdm9pZGluZ19uYW1lX2NvbGxpc2lvbnMpIHtcbmNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoeXlfLnl5dGV4dC5zbGljZSgtMikgPT09IFwiXFxcXFxcXFxcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmlwKDAsMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iZWdpbihcIm11XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeXlfLnl5dGV4dC5zbGljZSgtMSkgPT09IFwiXFxcXFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaXAoMCwxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luKFwiZW11XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmVnaW4oXCJtdVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZih5eV8ueXl0ZXh0KSByZXR1cm4gMTU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmJyZWFrO1xuY2FzZSAxOnJldHVybiAxNTtcbmJyZWFrO1xuY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvcFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxNTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuYnJlYWs7XG5jYXNlIDM6dGhpcy5iZWdpbigncmF3Jyk7IHJldHVybiAxNTtcbmJyZWFrO1xuY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9wU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgYmUgdXNpbmcgYHRoaXMudG9wU3RhdGUoKWAgYmVsb3csIGJ1dCBpdCBjdXJyZW50bHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm5zIHRoZSBzZWNvbmQgdG9wIGluc3RlYWQgb2YgdGhlIGZpcnN0IHRvcC4gT3BlbmVkIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXNzdWUgYWJvdXQgaXQgYXQgaHR0cHM6Ly9naXRodWIuY29tL3phYWNoL2ppc29uL2lzc3Vlcy8yOTFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0xXSA9PT0gJ3JhdycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxNTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeXlfLnl5dGV4dCA9IHl5Xy55eXRleHQuc3Vic3RyKDUsIHl5Xy55eWxlbmctOSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ0VORF9SQVdfQkxPQ0snO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuYnJlYWs7XG5jYXNlIDU6IHJldHVybiAxNTsgXG5icmVhaztcbmNhc2UgNjpcbiAgdGhpcy5wb3BTdGF0ZSgpO1xuICByZXR1cm4gMTQ7XG5cbmJyZWFrO1xuY2FzZSA3OnJldHVybiA2NTtcbmJyZWFrO1xuY2FzZSA4OnJldHVybiA2ODtcbmJyZWFrO1xuY2FzZSA5OiByZXR1cm4gMTk7IFxuYnJlYWs7XG5jYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9wU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luKCdyYXcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMjM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmJyZWFrO1xuY2FzZSAxMTpyZXR1cm4gNTU7XG5icmVhaztcbmNhc2UgMTI6cmV0dXJuIDYwO1xuYnJlYWs7XG5jYXNlIDEzOnJldHVybiAyOTtcbmJyZWFrO1xuY2FzZSAxNDpyZXR1cm4gNDc7XG5icmVhaztcbmNhc2UgMTU6dGhpcy5wb3BTdGF0ZSgpOyByZXR1cm4gNDQ7XG5icmVhaztcbmNhc2UgMTY6dGhpcy5wb3BTdGF0ZSgpOyByZXR1cm4gNDQ7XG5icmVhaztcbmNhc2UgMTc6cmV0dXJuIDM0O1xuYnJlYWs7XG5jYXNlIDE4OnJldHVybiAzOTtcbmJyZWFrO1xuY2FzZSAxOTpyZXR1cm4gNTE7XG5icmVhaztcbmNhc2UgMjA6cmV0dXJuIDQ4O1xuYnJlYWs7XG5jYXNlIDIxOlxuICB0aGlzLnVucHV0KHl5Xy55eXRleHQpO1xuICB0aGlzLnBvcFN0YXRlKCk7XG4gIHRoaXMuYmVnaW4oJ2NvbScpO1xuXG5icmVhaztcbmNhc2UgMjI6XG4gIHRoaXMucG9wU3RhdGUoKTtcbiAgcmV0dXJuIDE0O1xuXG5icmVhaztcbmNhc2UgMjM6cmV0dXJuIDQ4O1xuYnJlYWs7XG5jYXNlIDI0OnJldHVybiA3MztcbmJyZWFrO1xuY2FzZSAyNTpyZXR1cm4gNzI7XG5icmVhaztcbmNhc2UgMjY6cmV0dXJuIDcyO1xuYnJlYWs7XG5jYXNlIDI3OnJldHVybiA4NztcbmJyZWFrO1xuY2FzZSAyODovLyBpZ25vcmUgd2hpdGVzcGFjZVxuYnJlYWs7XG5jYXNlIDI5OnRoaXMucG9wU3RhdGUoKTsgcmV0dXJuIDU0O1xuYnJlYWs7XG5jYXNlIDMwOnRoaXMucG9wU3RhdGUoKTsgcmV0dXJuIDMzO1xuYnJlYWs7XG5jYXNlIDMxOnl5Xy55eXRleHQgPSBzdHJpcCgxLDIpLnJlcGxhY2UoL1xcXFxcIi9nLCdcIicpOyByZXR1cm4gODA7XG5icmVhaztcbmNhc2UgMzI6eXlfLnl5dGV4dCA9IHN0cmlwKDEsMikucmVwbGFjZSgvXFxcXCcvZyxcIidcIik7IHJldHVybiA4MDtcbmJyZWFrO1xuY2FzZSAzMzpyZXR1cm4gODU7XG5icmVhaztcbmNhc2UgMzQ6cmV0dXJuIDgyO1xuYnJlYWs7XG5jYXNlIDM1OnJldHVybiA4MjtcbmJyZWFrO1xuY2FzZSAzNjpyZXR1cm4gODM7XG5icmVhaztcbmNhc2UgMzc6cmV0dXJuIDg0O1xuYnJlYWs7XG5jYXNlIDM4OnJldHVybiA4MTtcbmJyZWFrO1xuY2FzZSAzOTpyZXR1cm4gNzU7XG5icmVhaztcbmNhc2UgNDA6cmV0dXJuIDc3O1xuYnJlYWs7XG5jYXNlIDQxOnJldHVybiA3MjtcbmJyZWFrO1xuY2FzZSA0Mjp5eV8ueXl0ZXh0ID0geXlfLnl5dGV4dC5yZXBsYWNlKC9cXFxcKFtcXFxcXFxdXSkvZywnJDEnKTsgcmV0dXJuIDcyO1xuYnJlYWs7XG5jYXNlIDQzOnJldHVybiAnSU5WQUxJRCc7XG5icmVhaztcbmNhc2UgNDQ6cmV0dXJuIDU7XG5icmVhaztcbn1cbn07XG5sZXhlci5ydWxlcyA9IFsvXig/OlteXFx4MDBdKj8oPz0oXFx7XFx7KSkpLywvXig/OlteXFx4MDBdKykvLC9eKD86W15cXHgwMF17Mix9Pyg/PShcXHtcXHt8XFxcXFxce1xce3xcXFxcXFxcXFxce1xce3wkKSkpLywvXig/Olxce1xce1xce1xceyg/PVteXFwvXSkpLywvXig/Olxce1xce1xce1xce1xcL1teXFxzIVwiIyUtLFxcLlxcLzstPkBcXFstXFxeYFxcey1+XSsoPz1bPX1cXHNcXC8uXSlcXH1cXH1cXH1cXH0pLywvXig/OlteXFx4MDBdKj8oPz0oXFx7XFx7XFx7XFx7KSkpLywvXig/OltcXHNcXFNdKj8tLSh+KT9cXH1cXH0pLywvXig/OlxcKCkvLC9eKD86XFwpKS8sL14oPzpcXHtcXHtcXHtcXHspLywvXig/OlxcfVxcfVxcfVxcfSkvLC9eKD86XFx7XFx7KH4pPz4pLywvXig/Olxce1xceyh+KT8jPikvLC9eKD86XFx7XFx7KH4pPyNcXCo/KS8sL14oPzpcXHtcXHsofik/XFwvKS8sL14oPzpcXHtcXHsofik/XFxeXFxzKih+KT9cXH1cXH0pLywvXig/Olxce1xceyh+KT9cXHMqZWxzZVxccyoofik/XFx9XFx9KS8sL14oPzpcXHtcXHsofik/XFxeKS8sL14oPzpcXHtcXHsofik/XFxzKmVsc2VcXGIpLywvXig/Olxce1xceyh+KT9cXHspLywvXig/Olxce1xceyh+KT8mKS8sL14oPzpcXHtcXHsofik/IS0tKS8sL14oPzpcXHtcXHsofik/IVtcXHNcXFNdKj9cXH1cXH0pLywvXig/Olxce1xceyh+KT9cXCo/KS8sL14oPzo9KS8sL14oPzpcXC5cXC4pLywvXig/OlxcLig/PShbPX59XFxzXFwvLil8XSkpKS8sL14oPzpbXFwvLl0pLywvXig/OlxccyspLywvXig/OlxcfSh+KT9cXH1cXH0pLywvXig/Oih+KT9cXH1cXH0pLywvXig/OlwiKFxcXFxbXCJdfFteXCJdKSpcIikvLC9eKD86JyhcXFxcWyddfFteJ10pKicpLywvXig/OkApLywvXig/OnRydWUoPz0oW359XFxzKV0pKSkvLC9eKD86ZmFsc2UoPz0oW359XFxzKV0pKSkvLC9eKD86dW5kZWZpbmVkKD89KFt+fVxccyldKSkpLywvXig/Om51bGwoPz0oW359XFxzKV0pKSkvLC9eKD86LT9bMC05XSsoPzpcXC5bMC05XSspPyg/PShbfn1cXHMpXSkpKS8sL14oPzphc1xccytcXHwpLywvXig/OlxcfCkvLC9eKD86KFteXFxzIVwiIyUtLFxcLlxcLzstPkBcXFstXFxeYFxcey1+XSsoPz0oWz1+fVxcc1xcLy4pfF0pKSkpLywvXig/OlxcWyhcXFxcXFxdfFteXFxdXSkqXFxdKS8sL14oPzouKS8sL14oPzokKS9dO1xubGV4ZXIuY29uZGl0aW9ucyA9IHtcIm11XCI6e1wicnVsZXNcIjpbNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDRdLFwiaW5jbHVzaXZlXCI6ZmFsc2V9LFwiZW11XCI6e1wicnVsZXNcIjpbMl0sXCJpbmNsdXNpdmVcIjpmYWxzZX0sXCJjb21cIjp7XCJydWxlc1wiOls2XSxcImluY2x1c2l2ZVwiOmZhbHNlfSxcInJhd1wiOntcInJ1bGVzXCI6WzMsNCw1XSxcImluY2x1c2l2ZVwiOmZhbHNlfSxcIklOSVRJQUxcIjp7XCJydWxlc1wiOlswLDEsNDRdLFwiaW5jbHVzaXZlXCI6dHJ1ZX19O1xucmV0dXJuIGxleGVyO30pKClcbnBhcnNlci5sZXhlciA9IGxleGVyO1xuZnVuY3Rpb24gUGFyc2VyICgpIHsgdGhpcy55eSA9IHt9OyB9UGFyc2VyLnByb3RvdHlwZSA9IHBhcnNlcjtwYXJzZXIuUGFyc2VyID0gUGFyc2VyO1xucmV0dXJuIG5ldyBQYXJzZXI7XG59KSgpO2V4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5leHBvcnRzWydkZWZhdWx0J10gPSBoYW5kbGViYXJzO1xuIl19 +; +define('handlebars/compiler/visitor',['exports', 'module', '../exception'], function (exports, module, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function Visitor() { + this.parents = []; + } + + Visitor.prototype = { + constructor: Visitor, + mutating: false, + + // Visits a given value. If mutating, will replace the value if necessary. + acceptKey: function acceptKey(node, name) { + var value = this.accept(node[name]); + if (this.mutating) { + // Hacky sanity check: This may have a few false positives for type for the helper + // methods but will generally do the right thing without a lot of overhead. + if (value && !Visitor.prototype[value.type]) { + throw new _Exception['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); + } + node[name] = value; + } + }, + + // Performs an accept operation with added sanity check to ensure + // required keys are not removed. + acceptRequired: function acceptRequired(node, name) { + this.acceptKey(node, name); + + if (!node[name]) { + throw new _Exception['default'](node.type + ' requires ' + name); + } + }, + + // Traverses a given array. If mutating, empty respnses will be removed + // for child elements. + acceptArray: function acceptArray(array) { + for (var i = 0, l = array.length; i < l; i++) { + this.acceptKey(array, i); + + if (!array[i]) { + array.splice(i, 1); + i--; + l--; + } + } + }, + + accept: function accept(object) { + if (!object) { + return; + } + + /* istanbul ignore next: Sanity code */ + if (!this[object.type]) { + throw new _Exception['default']('Unknown type: ' + object.type, object); + } + + if (this.current) { + this.parents.unshift(this.current); + } + this.current = object; + + var ret = this[object.type](object); + + this.current = this.parents.shift(); + + if (!this.mutating || ret) { + return ret; + } else if (ret !== false) { + return object; + } + }, + + Program: function Program(program) { + this.acceptArray(program.body); + }, + + MustacheStatement: visitSubExpression, + Decorator: visitSubExpression, + + BlockStatement: visitBlock, + DecoratorBlock: visitBlock, + + PartialStatement: visitPartial, + PartialBlockStatement: function PartialBlockStatement(partial) { + visitPartial.call(this, partial); + + this.acceptKey(partial, 'program'); + }, + + ContentStatement: function ContentStatement() /* content */{}, + CommentStatement: function CommentStatement() /* comment */{}, + + SubExpression: visitSubExpression, + + PathExpression: function PathExpression() /* path */{}, + + StringLiteral: function StringLiteral() /* string */{}, + NumberLiteral: function NumberLiteral() /* number */{}, + BooleanLiteral: function BooleanLiteral() /* bool */{}, + UndefinedLiteral: function UndefinedLiteral() /* literal */{}, + NullLiteral: function NullLiteral() /* literal */{}, + + Hash: function Hash(hash) { + this.acceptArray(hash.pairs); + }, + HashPair: function HashPair(pair) { + this.acceptRequired(pair, 'value'); + } + }; + + function visitSubExpression(mustache) { + this.acceptRequired(mustache, 'path'); + this.acceptArray(mustache.params); + this.acceptKey(mustache, 'hash'); + } + function visitBlock(block) { + visitSubExpression.call(this, block); + + this.acceptKey(block, 'program'); + this.acceptKey(block, 'inverse'); + } + function visitPartial(partial) { + this.acceptRequired(partial, 'name'); + this.acceptArray(partial.params); + this.acceptKey(partial, 'hash'); + } + + module.exports = Visitor; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3Zpc2l0b3IuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBRUEsV0FBUyxPQUFPLEdBQUc7QUFDakIsUUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7R0FDbkI7O0FBRUQsU0FBTyxDQUFDLFNBQVMsR0FBRztBQUNsQixlQUFXLEVBQUUsT0FBTztBQUNwQixZQUFRLEVBQUUsS0FBSzs7O0FBR2YsYUFBUyxFQUFFLG1CQUFTLElBQUksRUFBRSxJQUFJLEVBQUU7QUFDOUIsVUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUNwQyxVQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7OztBQUdqQixZQUFJLEtBQUssSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFO0FBQzNDLGdCQUFNLDBCQUFjLHdCQUF3QixHQUFHLEtBQUssQ0FBQyxJQUFJLEdBQUcseUJBQXlCLEdBQUcsSUFBSSxHQUFHLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDcEg7QUFDRCxZQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO09BQ3BCO0tBQ0Y7Ozs7QUFJRCxrQkFBYyxFQUFFLHdCQUFTLElBQUksRUFBRSxJQUFJLEVBQUU7QUFDbkMsVUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7O0FBRTNCLFVBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7QUFDZixjQUFNLDBCQUFjLElBQUksQ0FBQyxJQUFJLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQyxDQUFDO09BQ3REO0tBQ0Y7Ozs7QUFJRCxlQUFXLEVBQUUscUJBQVMsS0FBSyxFQUFFO0FBQzNCLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDNUMsWUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7O0FBRXpCLFlBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7QUFDYixlQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNuQixXQUFDLEVBQUUsQ0FBQztBQUNKLFdBQUMsRUFBRSxDQUFDO1NBQ0w7T0FDRjtLQUNGOztBQUVELFVBQU0sRUFBRSxnQkFBUyxNQUFNLEVBQUU7QUFDdkIsVUFBSSxDQUFDLE1BQU0sRUFBRTtBQUNYLGVBQU87T0FDUjs7O0FBR0QsVUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7QUFDdEIsY0FBTSwwQkFBYyxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO09BQzdEOztBQUVELFVBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNoQixZQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7T0FDcEM7QUFDRCxVQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQzs7QUFFdEIsVUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQzs7QUFFcEMsVUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDOztBQUVwQyxVQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxHQUFHLEVBQUU7QUFDekIsZUFBTyxHQUFHLENBQUM7T0FDWixNQUFNLElBQUksR0FBRyxLQUFLLEtBQUssRUFBRTtBQUN4QixlQUFPLE1BQU0sQ0FBQztPQUNmO0tBQ0Y7O0FBRUQsV0FBTyxFQUFFLGlCQUFTLE9BQU8sRUFBRTtBQUN6QixVQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUNoQzs7QUFFRCxxQkFBaUIsRUFBRSxrQkFBa0I7QUFDckMsYUFBUyxFQUFFLGtCQUFrQjs7QUFFN0Isa0JBQWMsRUFBRSxVQUFVO0FBQzFCLGtCQUFjLEVBQUUsVUFBVTs7QUFFMUIsb0JBQWdCLEVBQUUsWUFBWTtBQUM5Qix5QkFBcUIsRUFBRSwrQkFBUyxPQUFPLEVBQUU7QUFDdkMsa0JBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDOztBQUVqQyxVQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztLQUNwQzs7QUFFRCxvQkFBZ0IsRUFBRSx5Q0FBd0IsRUFBRTtBQUM1QyxvQkFBZ0IsRUFBRSx5Q0FBd0IsRUFBRTs7QUFFNUMsaUJBQWEsRUFBRSxrQkFBa0I7O0FBRWpDLGtCQUFjLEVBQUUsb0NBQXFCLEVBQUU7O0FBRXZDLGlCQUFhLEVBQUUscUNBQXVCLEVBQUU7QUFDeEMsaUJBQWEsRUFBRSxxQ0FBdUIsRUFBRTtBQUN4QyxrQkFBYyxFQUFFLG9DQUFxQixFQUFFO0FBQ3ZDLG9CQUFnQixFQUFFLHlDQUF3QixFQUFFO0FBQzVDLGVBQVcsRUFBRSxvQ0FBd0IsRUFBRTs7QUFFdkMsUUFBSSxFQUFFLGNBQVMsSUFBSSxFQUFFO0FBQ25CLFVBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQzlCO0FBQ0QsWUFBUSxFQUFFLGtCQUFTLElBQUksRUFBRTtBQUN2QixVQUFJLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztLQUNwQztHQUNGLENBQUM7O0FBRUYsV0FBUyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUU7QUFDcEMsUUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDdEMsUUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbEMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7R0FDbEM7QUFDRCxXQUFTLFVBQVUsQ0FBQyxLQUFLLEVBQUU7QUFDekIsc0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQzs7QUFFckMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDakMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7R0FDbEM7QUFDRCxXQUFTLFlBQVksQ0FBQyxPQUFPLEVBQUU7QUFDN0IsUUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDckMsUUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDakMsUUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7R0FDakM7O21CQUVjLE9BQU8iLCJmaWxlIjoidmlzaXRvci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi4vZXhjZXB0aW9uJztcblxuZnVuY3Rpb24gVmlzaXRvcigpIHtcbiAgdGhpcy5wYXJlbnRzID0gW107XG59XG5cblZpc2l0b3IucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogVmlzaXRvcixcbiAgbXV0YXRpbmc6IGZhbHNlLFxuXG4gIC8vIFZpc2l0cyBhIGdpdmVuIHZhbHVlLiBJZiBtdXRhdGluZywgd2lsbCByZXBsYWNlIHRoZSB2YWx1ZSBpZiBuZWNlc3NhcnkuXG4gIGFjY2VwdEtleTogZnVuY3Rpb24obm9kZSwgbmFtZSkge1xuICAgIGxldCB2YWx1ZSA9IHRoaXMuYWNjZXB0KG5vZGVbbmFtZV0pO1xuICAgIGlmICh0aGlzLm11dGF0aW5nKSB7XG4gICAgICAvLyBIYWNreSBzYW5pdHkgY2hlY2s6IFRoaXMgbWF5IGhhdmUgYSBmZXcgZmFsc2UgcG9zaXRpdmVzIGZvciB0eXBlIGZvciB0aGUgaGVscGVyXG4gICAgICAvLyBtZXRob2RzIGJ1dCB3aWxsIGdlbmVyYWxseSBkbyB0aGUgcmlnaHQgdGhpbmcgd2l0aG91dCBhIGxvdCBvZiBvdmVyaGVhZC5cbiAgICAgIGlmICh2YWx1ZSAmJiAhVmlzaXRvci5wcm90b3R5cGVbdmFsdWUudHlwZV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVW5leHBlY3RlZCBub2RlIHR5cGUgXCInICsgdmFsdWUudHlwZSArICdcIiBmb3VuZCB3aGVuIGFjY2VwdGluZyAnICsgbmFtZSArICcgb24gJyArIG5vZGUudHlwZSk7XG4gICAgICB9XG4gICAgICBub2RlW25hbWVdID0gdmFsdWU7XG4gICAgfVxuICB9LFxuXG4gIC8vIFBlcmZvcm1zIGFuIGFjY2VwdCBvcGVyYXRpb24gd2l0aCBhZGRlZCBzYW5pdHkgY2hlY2sgdG8gZW5zdXJlXG4gIC8vIHJlcXVpcmVkIGtleXMgYXJlIG5vdCByZW1vdmVkLlxuICBhY2NlcHRSZXF1aXJlZDogZnVuY3Rpb24obm9kZSwgbmFtZSkge1xuICAgIHRoaXMuYWNjZXB0S2V5KG5vZGUsIG5hbWUpO1xuXG4gICAgaWYgKCFub2RlW25hbWVdKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKG5vZGUudHlwZSArICcgcmVxdWlyZXMgJyArIG5hbWUpO1xuICAgIH1cbiAgfSxcblxuICAvLyBUcmF2ZXJzZXMgYSBnaXZlbiBhcnJheS4gSWYgbXV0YXRpbmcsIGVtcHR5IHJlc3Buc2VzIHdpbGwgYmUgcmVtb3ZlZFxuICAvLyBmb3IgY2hpbGQgZWxlbWVudHMuXG4gIGFjY2VwdEFycmF5OiBmdW5jdGlvbihhcnJheSkge1xuICAgIGZvciAobGV0IGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICB0aGlzLmFjY2VwdEtleShhcnJheSwgaSk7XG5cbiAgICAgIGlmICghYXJyYXlbaV0pIHtcbiAgICAgICAgYXJyYXkuc3BsaWNlKGksIDEpO1xuICAgICAgICBpLS07XG4gICAgICAgIGwtLTtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgYWNjZXB0OiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBpZiAoIW9iamVjdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBTYW5pdHkgY29kZSAqL1xuICAgIGlmICghdGhpc1tvYmplY3QudHlwZV0pIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdHlwZTogJyArIG9iamVjdC50eXBlLCBvYmplY3QpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmN1cnJlbnQpIHtcbiAgICAgIHRoaXMucGFyZW50cy51bnNoaWZ0KHRoaXMuY3VycmVudCk7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudCA9IG9iamVjdDtcblxuICAgIGxldCByZXQgPSB0aGlzW29iamVjdC50eXBlXShvYmplY3QpO1xuXG4gICAgdGhpcy5jdXJyZW50ID0gdGhpcy5wYXJlbnRzLnNoaWZ0KCk7XG5cbiAgICBpZiAoIXRoaXMubXV0YXRpbmcgfHwgcmV0KSB7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0gZWxzZSBpZiAocmV0ICE9PSBmYWxzZSkge1xuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG4gIH0sXG5cbiAgUHJvZ3JhbTogZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgIHRoaXMuYWNjZXB0QXJyYXkocHJvZ3JhbS5ib2R5KTtcbiAgfSxcblxuICBNdXN0YWNoZVN0YXRlbWVudDogdmlzaXRTdWJFeHByZXNzaW9uLFxuICBEZWNvcmF0b3I6IHZpc2l0U3ViRXhwcmVzc2lvbixcblxuICBCbG9ja1N0YXRlbWVudDogdmlzaXRCbG9jayxcbiAgRGVjb3JhdG9yQmxvY2s6IHZpc2l0QmxvY2ssXG5cbiAgUGFydGlhbFN0YXRlbWVudDogdmlzaXRQYXJ0aWFsLFxuICBQYXJ0aWFsQmxvY2tTdGF0ZW1lbnQ6IGZ1bmN0aW9uKHBhcnRpYWwpIHtcbiAgICB2aXNpdFBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsKTtcblxuICAgIHRoaXMuYWNjZXB0S2V5KHBhcnRpYWwsICdwcm9ncmFtJyk7XG4gIH0sXG5cbiAgQ29udGVudFN0YXRlbWVudDogZnVuY3Rpb24oLyogY29udGVudCAqLykge30sXG4gIENvbW1lbnRTdGF0ZW1lbnQ6IGZ1bmN0aW9uKC8qIGNvbW1lbnQgKi8pIHt9LFxuXG4gIFN1YkV4cHJlc3Npb246IHZpc2l0U3ViRXhwcmVzc2lvbixcblxuICBQYXRoRXhwcmVzc2lvbjogZnVuY3Rpb24oLyogcGF0aCAqLykge30sXG5cbiAgU3RyaW5nTGl0ZXJhbDogZnVuY3Rpb24oLyogc3RyaW5nICovKSB7fSxcbiAgTnVtYmVyTGl0ZXJhbDogZnVuY3Rpb24oLyogbnVtYmVyICovKSB7fSxcbiAgQm9vbGVhbkxpdGVyYWw6IGZ1bmN0aW9uKC8qIGJvb2wgKi8pIHt9LFxuICBVbmRlZmluZWRMaXRlcmFsOiBmdW5jdGlvbigvKiBsaXRlcmFsICovKSB7fSxcbiAgTnVsbExpdGVyYWw6IGZ1bmN0aW9uKC8qIGxpdGVyYWwgKi8pIHt9LFxuXG4gIEhhc2g6IGZ1bmN0aW9uKGhhc2gpIHtcbiAgICB0aGlzLmFjY2VwdEFycmF5KGhhc2gucGFpcnMpO1xuICB9LFxuICBIYXNoUGFpcjogZnVuY3Rpb24ocGFpcikge1xuICAgIHRoaXMuYWNjZXB0UmVxdWlyZWQocGFpciwgJ3ZhbHVlJyk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHZpc2l0U3ViRXhwcmVzc2lvbihtdXN0YWNoZSkge1xuICB0aGlzLmFjY2VwdFJlcXVpcmVkKG11c3RhY2hlLCAncGF0aCcpO1xuICB0aGlzLmFjY2VwdEFycmF5KG11c3RhY2hlLnBhcmFtcyk7XG4gIHRoaXMuYWNjZXB0S2V5KG11c3RhY2hlLCAnaGFzaCcpO1xufVxuZnVuY3Rpb24gdmlzaXRCbG9jayhibG9jaykge1xuICB2aXNpdFN1YkV4cHJlc3Npb24uY2FsbCh0aGlzLCBibG9jayk7XG5cbiAgdGhpcy5hY2NlcHRLZXkoYmxvY2ssICdwcm9ncmFtJyk7XG4gIHRoaXMuYWNjZXB0S2V5KGJsb2NrLCAnaW52ZXJzZScpO1xufVxuZnVuY3Rpb24gdmlzaXRQYXJ0aWFsKHBhcnRpYWwpIHtcbiAgdGhpcy5hY2NlcHRSZXF1aXJlZChwYXJ0aWFsLCAnbmFtZScpO1xuICB0aGlzLmFjY2VwdEFycmF5KHBhcnRpYWwucGFyYW1zKTtcbiAgdGhpcy5hY2NlcHRLZXkocGFydGlhbCwgJ2hhc2gnKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgVmlzaXRvcjtcbiJdfQ== +; +define('handlebars/compiler/whitespace-control',['exports', 'module', './visitor'], function (exports, module, _visitor) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Visitor = _interopRequireDefault(_visitor); + + function WhitespaceControl() { + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + this.options = options; + } + WhitespaceControl.prototype = new _Visitor['default'](); + + WhitespaceControl.prototype.Program = function (program) { + var doStandalone = !this.options.ignoreStandalone; + + var isRoot = !this.isRootSeen; + this.isRootSeen = true; + + var body = program.body; + for (var i = 0, l = body.length; i < l; i++) { + var current = body[i], + strip = this.accept(current); + + if (!strip) { + continue; + } + + var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), + _isNextWhitespace = isNextWhitespace(body, i, isRoot), + openStandalone = strip.openStandalone && _isPrevWhitespace, + closeStandalone = strip.closeStandalone && _isNextWhitespace, + inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; + + if (strip.close) { + omitRight(body, i, true); + } + if (strip.open) { + omitLeft(body, i, true); + } + + if (doStandalone && inlineStandalone) { + omitRight(body, i); + + if (omitLeft(body, i)) { + // If we are on a standalone node, save the indent info for partials + if (current.type === 'PartialStatement') { + // Pull out the whitespace from the final line + current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1]; + } + } + } + if (doStandalone && openStandalone) { + omitRight((current.program || current.inverse).body); + + // Strip out the previous content node if it's whitespace only + omitLeft(body, i); + } + if (doStandalone && closeStandalone) { + // Always strip the next node + omitRight(body, i); + + omitLeft((current.inverse || current.program).body); + } + } + + return program; + }; + + WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) { + this.accept(block.program); + this.accept(block.inverse); + + // Find the inverse program that is involed with whitespace stripping. + var program = block.program || block.inverse, + inverse = block.program && block.inverse, + firstInverse = inverse, + lastInverse = inverse; + + if (inverse && inverse.chained) { + firstInverse = inverse.body[0].program; + + // Walk the inverse chain to find the last inverse that is actually in the chain. + while (lastInverse.chained) { + lastInverse = lastInverse.body[lastInverse.body.length - 1].program; + } + } + + var strip = { + open: block.openStrip.open, + close: block.closeStrip.close, + + // Determine the standalone candiacy. Basically flag our content as being possibly standalone + // so our parent can determine if we actually are standalone + openStandalone: isNextWhitespace(program.body), + closeStandalone: isPrevWhitespace((firstInverse || program).body) + }; + + if (block.openStrip.close) { + omitRight(program.body, null, true); + } + + if (inverse) { + var inverseStrip = block.inverseStrip; + + if (inverseStrip.open) { + omitLeft(program.body, null, true); + } + + if (inverseStrip.close) { + omitRight(firstInverse.body, null, true); + } + if (block.closeStrip.open) { + omitLeft(lastInverse.body, null, true); + } + + // Find standalone else statments + if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) { + omitLeft(program.body); + omitRight(firstInverse.body); + } + } else if (block.closeStrip.open) { + omitLeft(program.body, null, true); + } + + return strip; + }; + + WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) { + return mustache.strip; + }; + + WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) { + /* istanbul ignore next */ + var strip = node.strip || {}; + return { + inlineStandalone: true, + open: strip.open, + close: strip.close + }; + }; + + function isPrevWhitespace(body, i, isRoot) { + if (i === undefined) { + i = body.length; + } + + // Nodes that end with newlines are considered whitespace (but are special + // cased for strip operations) + var prev = body[i - 1], + sibling = body[i - 2]; + if (!prev) { + return isRoot; + } + + if (prev.type === 'ContentStatement') { + return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original); + } + } + function isNextWhitespace(body, i, isRoot) { + if (i === undefined) { + i = -1; + } + + var next = body[i + 1], + sibling = body[i + 2]; + if (!next) { + return isRoot; + } + + if (next.type === 'ContentStatement') { + return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original); + } + } + + // Marks the node to the right of the position as omitted. + // I.e. {{foo}}' ' will mark the ' ' node as omitted. + // + // If i is undefined, then the first child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitRight(body, i, multiple) { + var current = body[i == null ? 0 : i + 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) { + return; + } + + var original = current.value; + current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, ''); + current.rightStripped = current.value !== original; + } + + // Marks the node to the left of the position as omitted. + // I.e. ' '{{foo}} will mark the ' ' node as omitted. + // + // If i is undefined then the last child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitLeft(body, i, multiple) { + var current = body[i == null ? body.length - 1 : i - 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) { + return; + } + + // We omit the last node if it's whitespace only and not preceeded by a non-content node. + var original = current.value; + current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, ''); + current.leftStripped = current.value !== original; + return current.leftStripped; + } + + module.exports = WhitespaceControl; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL3doaXRlc3BhY2UtY29udHJvbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFFQSxXQUFTLGlCQUFpQixHQUFlO1FBQWQsT0FBTyx5REFBRyxFQUFFOztBQUNyQyxRQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztHQUN4QjtBQUNELG1CQUFpQixDQUFDLFNBQVMsR0FBRyx5QkFBYSxDQUFDOztBQUU1QyxtQkFBaUIsQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLFVBQVMsT0FBTyxFQUFFO0FBQ3RELFFBQU0sWUFBWSxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQzs7QUFFcEQsUUFBSSxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO0FBQzlCLFFBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDOztBQUV2QixRQUFJLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO0FBQ3hCLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDM0MsVUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztVQUNqQixLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQzs7QUFFakMsVUFBSSxDQUFDLEtBQUssRUFBRTtBQUNWLGlCQUFTO09BQ1Y7O0FBRUQsVUFBSSxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztVQUNyRCxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztVQUVyRCxjQUFjLEdBQUcsS0FBSyxDQUFDLGNBQWMsSUFBSSxpQkFBaUI7VUFDMUQsZUFBZSxHQUFHLEtB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QUN4RCxRQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssa0JBQWtCLElBQUssQ0FBQyxRQUFRLElBQUksT0FBTyxDQUFDLFlBQVksQUFBQyxFQUFFO0FBQzFGLGFBQU87S0FDUjs7O0FBR0QsUUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztBQUM3QixXQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsR0FBSSxNQUFNLEdBQUssU0FBUyxBQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDN0UsV0FBTyxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQztBQUNsRCxXQUFPLE9BQU8sQ0FBQyxZQUFZLENBQUM7R0FDN0I7O21CQUVjLGlCQUFpQiIsImZpbGUiOiJ3aGl0ZXNwYWNlLWNvbnRyb2wuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgVmlzaXRvciBmcm9tICcuL3Zpc2l0b3InO1xuXG5mdW5jdGlvbiBXaGl0ZXNwYWNlQ29udHJvbChvcHRpb25zID0ge30pIHtcbiAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbn1cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZSA9IG5ldyBWaXNpdG9yKCk7XG5cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5Qcm9ncmFtID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICBjb25zdCBkb1N0YW5kYWxvbmUgPSAhdGhpcy5vcHRpb25zLmlnbm9yZVN0YW5kYWxvbmU7XG5cbiAgbGV0IGlzUm9vdCA9ICF0aGlzLmlzUm9vdFNlZW47XG4gIHRoaXMuaXNSb290U2VlbiA9IHRydWU7XG5cbiAgbGV0IGJvZHkgPSBwcm9ncmFtLmJvZHk7XG4gIGZvciAobGV0IGkgPSAwLCBsID0gYm9keS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICBsZXQgY3VycmVudCA9IGJvZHlbaV0sXG4gICAgICAgIHN0cmlwID0gdGhpcy5hY2NlcHQoY3VycmVudCk7XG5cbiAgICBpZiAoIXN0cmlwKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBsZXQgX2lzUHJldldoaXRlc3BhY2UgPSBpc1ByZXZXaGl0ZXNwYWNlKGJvZHksIGksIGlzUm9vdCksXG4gICAgICAgIF9pc05leHRXaGl0ZXNwYWNlID0gaXNOZXh0V2hpdGVzcGFjZShib2R5LCBpLCBpc1Jvb3QpLFxuXG4gICAgICAgIG9wZW5TdGFuZGFsb25lID0gc3RyaXAub3BlblN0YW5kYWxvbmUgJiYgX2lzUHJldldoaXRlc3BhY2UsXG4gICAgICAgIGNsb3NlU3RhbmRhbG9uZSA9IHN0cmlwLmNsb3NlU3RhbmRhbG9uZSAmJiBfaXNOZXh0V2hpdGVzcGFjZSxcbiAgICAgICAgaW5saW5lU3RhbmRhbG9uZSA9IHN0cmlwLmlubGluZVN0YW5kYWxvbmUgJiYgX2lzUHJldldoaXRlc3BhY2UgJiYgX2lzTmV4dFdoaXRlc3BhY2U7XG5cbiAgICBpZiAoc3RyaXAuY2xvc2UpIHtcbiAgICAgIG9taXRSaWdodChib2R5LCBpLCB0cnVlKTtcbiAgICB9XG4gICAgaWYgKHN0cmlwLm9wZW4pIHtcbiAgICAgIG9taXRMZWZ0KGJvZHksIGksIHRydWUpO1xuICAgIH1cblxuICAgIGlmIChkb1N0YW5kYWxvbmUgJiYgaW5saW5lU3RhbmRhbG9uZSkge1xuICAgICAgb21pdFJpZ2h0KGJvZHksIGkpO1xuXG4gICAgICBpZiAob21pdExlZnQoYm9keSwgaSkpIHtcbiAgICAgICAgLy8gSWYgd2UgYXJlIG9uIGEgc3RhbmRhbG9uZSBub2RlLCBzYXZlIHRoZSBpbmRlbnQgaW5mbyBmb3IgcGFydGlhbHNcbiAgICAgICAgaWYgKGN1cnJlbnQudHlwZSA9PT0gJ1BhcnRpYWxTdGF0ZW1lbnQnKSB7XG4gICAgICAgICAgLy8gUHVsbCBvdXQgdGhlIHdoaXRlc3BhY2UgZnJvbSB0aGUgZmluYWwgbGluZVxuICAgICAgICAgIGN1cnJlbnQuaW5kZW50ID0gKC8oWyBcXHRdKyQpLykuZXhlYyhib2R5W2kgLSAxXS5vcmlnaW5hbClbMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGRvU3RhbmRhbG9uZSAmJiBvcGVuU3RhbmRhbG9uZSkge1xuICAgICAgb21pdFJpZ2h0KChjdXJyZW50LnByb2dyYW0gfHwgY3VycmVudC5pbnZlcnNlKS5ib2R5KTtcblxuICAgICAgLy8gU3RyaXAgb3V0IHRoZSBwcmV2aW91cyBjb250ZW50IG5vZGUgaWYgaXQncyB3aGl0ZXNwYWNlIG9ubHlcbiAgICAgIG9taXRMZWZ0KGJvZHksIGkpO1xuICAgIH1cbiAgICBpZiAoZG9TdGFuZGFsb25lICYmIGNsb3NlU3RhbmRhbG9uZSkge1xuICAgICAgLy8gQWx3YXlzIHN0cmlwIHRoZSBuZXh0IG5vZGVcbiAgICAgIG9taXRSaWdodChib2R5LCBpKTtcblxuICAgICAgb21pdExlZnQoKGN1cnJlbnQuaW52ZXJzZSB8fCBjdXJyZW50LnByb2dyYW0pLmJvZHkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwcm9ncmFtO1xufTtcblxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLkJsb2NrU3RhdGVtZW50ID1cbldoaXRlc3BhY2VDb250cm9sLnByb3RvdHlwZS5EZWNvcmF0b3JCbG9jayA9XG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuUGFydGlhbEJsb2NrU3RhdGVtZW50ID0gZnVuY3Rpb24oYmxvY2spIHtcbiAgdGhpcy5hY2NlcHQoYmxvY2sucHJvZ3JhbSk7XG4gIHRoaXMuYWNjZXB0KGJsb2NrLmludmVyc2UpO1xuXG4gIC8vIEZpbmQgdGhlIGludmVyc2UgcHJvZ3JhbSB0aGF0IGlzIGludm9sZWQgd2l0aCB3aGl0ZXNwYWNlIHN0cmlwcGluZy5cbiAgbGV0IHByb2dyYW0gPSBibG9jay5wcm9ncmFtIHx8IGJsb2NrLmludmVyc2UsXG4gICAgICBpbnZlcnNlID0gYmxvY2sucHJvZ3JhbSAmJiBibG9jay5pbnZlcnNlLFxuICAgICAgZmlyc3RJbnZlcnNlID0gaW52ZXJzZSxcbiAgICAgIGxhc3RJbnZlcnNlID0gaW52ZXJzZTtcblxuICBpZiAoaW52ZXJzZSAmJiBpbnZlcnNlLmNoYWluZWQpIHtcbiAgICBmaXJzdEludmVyc2UgPSBpbnZlcnNlLmJvZHlbMF0ucHJvZ3JhbTtcblxuICAgIC8vIFdhbGsgdGhlIGludmVyc2UgY2hhaW4gdG8gZmluZCB0aGUgbGFzdCBpbnZlcnNlIHRoYXQgaXMgYWN0dWFsbHkgaW4gdGhlIGNoYWluLlxuICAgIHdoaWxlIChsYXN0SW52ZXJzZS5jaGFpbmVkKSB7XG4gICAgICBsYXN0SW52ZXJzZSA9IGxhc3RJbnZlcnNlLmJvZHlbbGFzdEludmVyc2UuYm9keS5sZW5ndGggLSAxXS5wcm9ncmFtO1xuICAgIH1cbiAgfVxuXG4gIGxldCBzdHJpcCA9IHtcbiAgICBvcGVuOiBibG9jay5vcGVuU3RyaXAub3BlbixcbiAgICBjbG9zZTogYmxvY2suY2xvc2VTdHJpcC5jbG9zZSxcblxuICAgIC8vIERldGVybWluZSB0aGUgc3RhbmRhbG9uZSBjYW5kaWFjeS4gQmFzaWNhbGx5IGZsYWcgb3VyIGNvbnRlbnQgYXMgYmVpbmcgcG9zc2libHkgc3RhbmRhbG9uZVxuICAgIC8vIHNvIG91ciBwYXJlbnQgY2FuIGRldGVybWluZSBpZiB3ZSBhY3R1YWxseSBhcmUgc3RhbmRhbG9uZVxuICAgIG9wZW5TdGFuZGFsb25lOiBpc05leHRXaGl0ZXNwYWNlKHByb2dyYW0uYm9keSksXG4gICAgY2xvc2VTdGFuZGFsb25lOiBpc1ByZXZXaGl0ZXNwYWNlKChmaXJzdEludmVyc2UgfHwgcHJvZ3JhbSkuYm9keSlcbiAgfTtcblxuICBpZiAoYmxvY2sub3BlblN0cmlwLmNsb3NlKSB7XG4gICAgb21pdFJpZ2h0KHByb2dyYW0uYm9keSwgbnVsbCwgdHJ1ZSk7XG4gIH1cblxuICBpZiAoaW52ZXJzZSkge1xuICAgIGxldCBpbnZlcnNlU3RyaXAgPSBibG9jay5pbnZlcnNlU3RyaXA7XG5cbiAgICBpZiAoaW52ZXJzZVN0cmlwLm9wZW4pIHtcbiAgICAgIG9taXRMZWZ0KHByb2dyYW0uYm9keSwgbnVsbCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgaWYgKGludmVyc2VTdHJpcC5jbG9zZSkge1xuICAgICAgb21pdFJpZ2h0KGZpcnN0SW52ZXJzZS5ib2R5LCBudWxsLCB0cnVlKTtcbiAgICB9XG4gICAgaWYgKGJsb2NrLmNsb3NlU3RyaXAub3Blbikge1xuICAgICAgb21pdExlZnQobGFzdEludmVyc2UuYm9keSwgbnVsbCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLy8gRmluZCBzdGFuZGFsb25lIGVsc2Ugc3RhdG1lbnRzXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuaWdub3JlU3RhbmRhbG9uZVxuICAgICAgICAmJiBpc1ByZXZXaGl0ZXNwYWNlKHByb2dyYW0uYm9keSlcbiAgICAgICAgJiYgaXNOZXh0V2hpdGVzcGFjZShmaXJzdEludmVyc2UuYm9keSkpIHtcbiAgICAgIG9taXRMZWZ0KHByb2dyYW0uYm9keSk7XG4gICAgICBvbWl0UmlnaHQoZmlyc3RJbnZlcnNlLmJvZHkpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChibG9jay5jbG9zZVN0cmlwLm9wZW4pIHtcbiAgICBvbWl0TGVmdChwcm9ncmFtLmJvZHksIG51bGwsIHRydWUpO1xuICB9XG5cbiAgcmV0dXJuIHN0cmlwO1xufTtcblxuV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLkRlY29yYXRvciA9XG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuTXVzdGFjaGVTdGF0ZW1lbnQgPSBmdW5jdGlvbihtdXN0YWNoZSkge1xuICByZXR1cm4gbXVzdGFjaGUuc3RyaXA7XG59O1xuXG5XaGl0ZXNwYWNlQ29udHJvbC5wcm90b3R5cGUuUGFydGlhbFN0YXRlbWVudCA9XG4gICAgV2hpdGVzcGFjZUNvbnRyb2wucHJvdG90eXBlLkNvbW1lbnRTdGF0ZW1lbnQgPSBmdW5jdGlvbihub2RlKSB7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGxldCBzdHJpcCA9IG5vZGUuc3RyaXAgfHwge307XG4gIHJldHVybiB7XG4gICAgaW5saW5lU3RhbmRhbG9uZTogdHJ1ZSxcbiAgICBvcGVuOiBzdHJpcC5vcGVuLFxuICAgIGNsb3NlOiBzdHJpcC5jbG9zZVxuICB9O1xufTtcblxuXG5mdW5jdGlvbiBpc1ByZXZXaGl0ZXNwYWNlKGJvZHksIGksIGlzUm9vdCkge1xuICBpZiAoaSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgaSA9IGJvZHkubGVuZ3RoO1xuICB9XG5cbiAgLy8gTm9kZXMgdGhhdCBlbmQgd2l0aCBuZXdsaW5lcyBhcmUgY29uc2lkZXJlZCB3aGl0ZXNwYWNlIChidXQgYXJlIHNwZWNpYWxcbiAgLy8gY2FzZWQgZm9yIHN0cmlwIG9wZXJhdGlvbnMpXG4gIGxldCBwcmV2ID0gYm9keVtpIC0gMV0sXG4gICAgICBzaWJsaW5nID0gYm9keVtpIC0gMl07XG4gIGlmICghcHJldikge1xuICAgIHJldHVybiBpc1Jvb3Q7XG4gIH1cblxuICBpZiAocHJldi50eXBlID09PSAnQ29udGVudFN0YXRlbWVudCcpIHtcbiAgICByZXR1cm4gKHNpYmxpbmcgfHwgIWlzUm9vdCA/ICgvXFxyP1xcblxccyo/JC8pIDogKC8oXnxcXHI/XFxuKVxccyo/JC8pKS50ZXN0KHByZXYub3JpZ2luYWwpO1xuICB9XG59XG5mdW5jdGlvbiBpc05leHRXaGl0ZXNwYWNlKGJvZHksIGksIGlzUm9vdCkge1xuICBpZiAoaSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgaSA9IC0xO1xuICB9XG5cbiAgbGV0IG5leHQgPSBib2R5W2kgKyAxXSxcbiAgICAgIHNpYmxpbmcgPSBib2R5W2kgKyAyXTtcbiAgaWYgKCFuZXh0KSB7XG4gICAgcmV0dXJuIGlzUm9vdDtcbiAgfVxuXG4gIGlmIChuZXh0LnR5cGUgPT09ICdDb250ZW50U3RhdGVtZW50Jykge1xuICAgIHJldHVybiAoc2libGluZyB8fCAhaXNSb290ID8gKC9eXFxzKj9cXHI/XFxuLykgOiAoL15cXHMqPyhcXHI/XFxufCQpLykpLnRlc3QobmV4dC5vcmlnaW5hbCk7XG4gIH1cbn1cblxuLy8gTWFya3MgdGhlIG5vZGUgdG8gdGhlIHJpZ2h0IG9mIHRoZSBwb3NpdGlvbiBhcyBvbWl0dGVkLlxuLy8gSS5lLiB7e2Zvb319JyAnIHdpbGwgbWFyayB0aGUgJyAnIG5vZGUgYXMgb21pdHRlZC5cbi8vXG4vLyBJZiBpIGlzIHVuZGVmaW5lZCwgdGhlbiB0aGUgZmlyc3QgY2hpbGQgd2lsbCBiZSBtYXJrZWQgYXMgc3VjaC5cbi8vXG4vLyBJZiBtdWxpdHBsZSBpcyB0cnV0aHkgdGhlbiBhbGwgd2hpdGVzcGFjZSB3aWxsIGJlIHN0cmlwcGVkIG91dCB1bnRpbCBub24td2hpdGVzcGFjZVxuLy8gY29udGVudCBpcyBtZXQuXG5mdW5jdGlvbiBvbWl0UmlnaHQoYm9keSwgaSwgbXVsdGlwbGUpIHtcbiAgbGV0IGN1cnJlbnQgPSBib2R5W2kgPT0gbnVsbCA/IDAgOiBpICsgMV07XG4gIGlmICghY3VycmVudCB8fCBjdXJyZW50LnR5cGUgIT09ICdDb250ZW50U3RhdGVtZW50JyB8fCAoIW11bHRpcGxlICYmIGN1cnJlbnQucmlnaHRTdHJpcHBlZCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgb3JpZ2luYWwgPSBjdXJyZW50LnZhbHVlO1xuICBjdXJyZW50LnZhbHVlID0gY3VycmVudC52YWx1ZS5yZXBsYWNlKG11bHRpcGxlID8gKC9eXFxzKy8pIDogKC9eWyBcXHRdKlxccj9cXG4/LyksICcnKTtcbiAgY3VycmVudC5yaWdodFN0cmlwcGVkID0gY3VycmVudC52YWx1ZSAhPT0gb3JpZ2luYWw7XG59XG5cbi8vIE1hcmtzIHRoZSBub2RlIHRvIHRoZSBsZWZ0IG9mIHRoZSBwb3NpdGlvbiBhcyBvbWl0dGVkLlxuLy8gSS5lLiAnICd7e2Zvb319IHdpbGwgbWFyayB0aGUgJyAnIG5vZGUgYXMgb21pdHRlZC5cbi8vXG4vLyBJZiBpIGlzIHVuZGVmaW5lZCB0aGVuIHRoZSBsYXN0IGNoaWxkIHdpbGwgYmUgbWFya2VkIGFzIHN1Y2guXG4vL1xuLy8gSWYgbXVsaXRwbGUgaXMgdHJ1dGh5IHRoZW4gYWxsIHdoaXRlc3BhY2Ugd2lsbCBiZSBzdHJpcHBlZCBvdXQgdW50aWwgbm9uLXdoaXRlc3BhY2Vcbi8vIGNvbnRlbnQgaXMgbWV0LlxuZnVuY3Rpb24gb21pdExlZnQoYm9keSwgaSwgbXVsdGlwbGUpIHtcbiAgbGV0IGN1cnJlbnQgPSBib2R5W2kgPT0gbnVsbCA/IGJvZHkubGVuZ3RoIC0gMSA6IGkgLSAxXTtcbiAgaWYgKCFjdXJyZW50IHx8IGN1cnJlbnQudHlwZSAhPT0gJ0NvbnRlbnRTdGF0ZW1lbnQnIHx8ICghbXVsdGlwbGUgJiYgY3VycmVudC5sZWZ0U3RyaXBwZWQpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gV2Ugb21pdCB0aGUgbGFzdCBub2RlIGlmIGl0J3Mgd2hpdGVzcGFjZSBvbmx5IGFuZCBub3QgcHJlY2VlZGVkIGJ5IGEgbm9uLWNvbnRlbnQgbm9kZS5cbiAgbGV0IG9yaWdpbmFsID0gY3VycmVudC52YWx1ZTtcbiAgY3VycmVudC52YWx1ZSA9IGN1cnJlbnQudmFsdWUucmVwbGFjZShtdWx0aXBsZSA/ICgvXFxzKyQvKSA6ICgvWyBcXHRdKyQvKSwgJycpO1xuICBjdXJyZW50LmxlZnRTdHJpcHBlZCA9IGN1cnJlbnQudmFsdWUgIT09IG9yaWdpbmFsO1xuICByZXR1cm4gY3VycmVudC5sZWZ0U3RyaXBwZWQ7XG59XG5cbmV4cG9ydCBkZWZhdWx0IFdoaXRlc3BhY2VDb250cm9sO1xuIl19 +; +define('handlebars/compiler/helpers',['exports', '../exception'], function (exports, _exception) { + 'use strict'; + + exports.__esModule = true; + exports.SourceLocation = SourceLocation; + exports.id = id; + exports.stripFlags = stripFlags; + exports.stripComment = stripComment; + exports.preparePath = preparePath; + exports.prepareMustache = prepareMustache; + exports.prepareRawBlock = prepareRawBlock; + exports.prepareBlock = prepareBlock; + exports.prepareProgram = prepareProgram; + exports.preparePartialBlock = preparePartialBlock; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function validateClose(open, close) { + close = close.path ? close.path.original : close; + + if (open.path.original !== close) { + var errorNode = { loc: open.path.loc }; + + throw new _Exception['default'](open.path.original + " doesn't match " + close, errorNode); + } + } + + function SourceLocation(source, locInfo) { + this.source = source; + this.start = { + line: locInfo.first_line, + column: locInfo.first_column + }; + this.end = { + line: locInfo.last_line, + column: locInfo.last_column + }; + } + + function id(token) { + if (/^\[.*\]$/.test(token)) { + return token.substr(1, token.length - 2); + } else { + return token; + } + } + + function stripFlags(open, close) { + return { + open: open.charAt(2) === '~', + close: close.charAt(close.length - 3) === '~' + }; + } + + function stripComment(comment) { + return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, ''); + } + + function preparePath(data, parts, loc) { + loc = this.locInfo(loc); + + var original = data ? '@' : '', + dig = [], + depth = 0, + depthString = ''; + + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i].part, + + // If we have [] syntax then we do not treat path references as operators, + // i.e. foo.[this] resolves to approximately context.foo['this'] + isLiteral = parts[i].original !== part; + original += (parts[i].separator || '') + part; + + if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { + if (dig.length > 0) { + throw new _Exception['default']('Invalid path: ' + original, { loc: loc }); + } else if (part === '..') { + depth++; + depthString += '../'; + } + } else { + dig.push(part); + } + } + + return { + type: 'PathExpression', + data: data, + depth: depth, + parts: dig, + original: original, + loc: loc + }; + } + + function prepareMustache(path, params, hash, open, strip, locInfo) { + // Must use charAt to support IE pre-10 + var escapeFlag = open.charAt(3) || open.charAt(2), + escaped = escapeFlag !== '{' && escapeFlag !== '&'; + + var decorator = /\*/.test(open); + return { + type: decorator ? 'Decorator' : 'MustacheStatement', + path: path, + params: params, + hash: hash, + escaped: escaped, + strip: strip, + loc: this.locInfo(locInfo) + }; + } + + function prepareRawBlock(openRawBlock, contents, close, locInfo) { + validateClose(openRawBlock, close); + + locInfo = this.locInfo(locInfo); + var program = { + type: 'Program', + body: contents, + strip: {}, + loc: locInfo + }; + + return { + type: 'BlockStatement', + path: openRawBlock.path, + params: openRawBlock.params, + hash: openRawBlock.hash, + program: program, + openStrip: {}, + inverseStrip: {}, + closeStrip: {}, + loc: locInfo + }; + } + + function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { + if (close && close.path) { + validateClose(openBlock, close); + } + + var decorator = /\*/.test(openBlock.open); + + program.blockParams = openBlock.blockParams; + + var inverse = undefined, + inverseStrip = undefined; + + if (inverseAndProgram) { + if (decorator) { + throw new _Exception['default']('Unexpected inverse block on decorator', inverseAndProgram); + } + + if (inverseAndProgram.chain) { + inverseAndProgram.program.body[0].closeStrip = close.strip; + } + + inverseStrip = inverseAndProgram.strip; + inverse = inverseAndProgram.program; + } + + if (inverted) { + inverted = inverse; + inverse = program; + program = inverted; + } + + return { + type: decorator ? 'DecoratorBlock' : 'BlockStatement', + path: openBlock.path, + params: openBlock.params, + hash: openBlock.hash, + program: program, + inverse: inverse, + openStrip: openBlock.strip, + inverseStrip: inverseStrip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; + } + + function prepareProgram(statements, loc) { + if (!loc && statements.length) { + var firstLoc = statements[0].loc, + lastLoc = statements[statements.length - 1].loc; + + /* istanbul ignore else */ + if (firstLoc && lastLoc) { + loc = { + source: firstLoc.source, + start: { + line: firstLoc.start.line, + column: firstLoc.start.column + }, + end: { + line: lastLoc.end.line, + column: lastLoc.end.column + } + }; + } + } + + return { + type: 'Program', + body: statements, + strip: {}, + loc: loc + }; + } + + function preparePartialBlock(open, program, close, locInfo) { + validateClose(open, close); + + return { + type: 'PartialBlockStatement', + name: open.path, + params: open.params, + hash: open.hash, + program: program, + openStrip: open.strip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxXQUFTLGFBQWEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO0FBQ2xDLFNBQUssR0FBRyxLQUFLLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQzs7QUFFakQsUUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsS0FBSyxLQUFLLEVBQUU7QUFDaEMsVUFBSSxTQUFTLEdBQUcsRUFBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUMsQ0FBQzs7QUFFckMsWUFBTSwwQkFBYyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7S0FDaEY7R0FDRjs7QUFFTSxXQUFTLGNBQWMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFO0FBQzlDLFFBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQ3JCLFFBQUksQ0FBQyxLQUFLLEdBQUc7QUFDWCxVQUFJLEVBQUUsT0FBTyxDQUFDLFVBQVU7QUFDeEIsWUFBTSxFQUFFLE9BQU8sQ0FBQyxZQUFZO0tBQzdCLENBQUM7QUFDRixRQUFJLENBQUMsR0FBRyxHQUFHO0FBQ1QsVUFBSSxFQUFFLE9BQU8sQ0FBQyxTQUFTO0FBQ3ZCLFlBQU0sRUFBRSxPQUFPLENBQUMsV0FBVztLQUM1QixDQUFDO0dBQ0g7O0FBRU0sV0FBUyxFQUFFLENBQUMsS0FBSyxFQUFFO0FBQ3hCLFFBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUMxQixhQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7S0FDMUMsTUFBTTtBQUNMLGFB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InNvdXJjZXNDb250ZW50IjpbImltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi4vZXhjZXB0aW9uJztcblxuZnVuY3Rpb24gdmFsaWRhdGVDbG9zZShvcGVuLCBjbG9zZSkge1xuICBjbG9zZSA9IGNsb3NlLnBhdGggPyBjbG9zZS5wYXRoLm9yaWdpbmFsIDogY2xvc2U7XG5cbiAgaWYgKG9wZW4ucGF0aC5vcmlnaW5hbCAhPT0gY2xvc2UpIHtcbiAgICBsZXQgZXJyb3JOb2RlID0ge2xvYzogb3Blbi5wYXRoLmxvY307XG5cbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKG9wZW4ucGF0aC5vcmlnaW5hbCArIFwiIGRvZXNuJ3QgbWF0Y2ggXCIgKyBjbG9zZSwgZXJyb3JOb2RlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gU291cmNlTG9jYXRpb24oc291cmNlLCBsb2NJbmZvKSB7XG4gIHRoaXMuc291cmNlID0gc291cmNlO1xuICB0aGlzLnN0YXJ0ID0ge1xuICAgIGxpbmU6IGxvY0luZm8uZmlyc3RfbGluZSxcbiAgICBjb2x1bW46IGxvY0luZm8uZmlyc3RfY29sdW1uXG4gIH07XG4gIHRoaXMuZW5kID0ge1xuICAgIGxpbmU6IGxvY0luZm8ubGFzdF9saW5lLFxuICAgIGNvbHVtbjogbG9jSW5mby5sYXN0X2NvbHVtblxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaWQodG9rZW4pIHtcbiAgaWYgKC9eXFxbLipcXF0kLy50ZXN0KHRva2VuKSkge1xuICAgIHJldHVybiB0b2tlbi5zdWJzdHIoMSwgdG9rZW4ubGVuZ3RoIC0gMik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcEZsYWdzKG9wZW4sIGNsb3NlKSB7XG4gIHJldHVybiB7XG4gICAgb3Blbjogb3Blbi5jaGFyQXQoMikgPT09ICd+JyxcbiAgICBjbG9zZTogY2xvc2UuY2hhckF0KGNsb3NlLmxlbmd0aCAtIDMpID09PSAnfidcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmlwQ29tbWVudChjb21tZW50KSB7XG4gIHJldHVybiBjb21tZW50LnJlcGxhY2UoL15cXHtcXHt+P1xcIS0/LT8vLCAnJylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvLT8tP34/XFx9XFx9JC8sICcnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVQYXRoKGRhdGEsIHBhcnRzLCBsb2MpIHtcbiAgbG9jID0gdGhpcy5sb2NJbmZvKGxvYyk7XG5cbiAgbGV0IG9yaWdpbmFsID0gZGF0YSA/ICdAJyA6ICcnLFxuICAgICAgZGlnID0gW10sXG4gICAgICBkZXB0aCA9IDAsXG4gICAgICBkZXB0aFN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwLCBsID0gcGFydHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgbGV0IHBhcnQgPSBwYXJ0c1tpXS5wYXJ0LFxuICAgICAgICAvLyBJZiB3ZSBoYXZlIFtdIHN5bnRheCB0aGVuIHdlIGRvIG5vdCB0cmVhdCBwYXRoIHJlZmVyZW5jZXMgYXMgb3BlcmF0b3JzLFxuICAgICAgICAvLyBpLmUuIGZvby5bdGhpc10gcmVzb2x2ZXMgdG8gYXBwcm94aW1hdGVseSBjb250ZXh0LmZvb1sndGhpcyddXG4gICAgICAgIGlzTGl0ZXJhbCA9IHBhcnRzW2ldLm9yaWdpbmFsICE9PSBwYXJ0O1xuICAgIG9yaWdpbmFsICs9IChwYXJ0c1tpXS5zZXBhcmF0b3IgfHwgJycpICsgcGFydDtcblxuICAgIGlmICghaXNMaXRlcmFsICYmIChwYXJ0ID09PSAnLi4nIHx8IHBhcnQgPT09ICcuJyB8fCBwYXJ0ID09PSAndGhpcycpKSB7XG4gICAgICBpZiAoZGlnLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignSW52YWxpZCBwYXRoOiAnICsgb3JpZ2luYWwsIHtsb2N9KTtcbiAgICAgIH0gZWxzZSBpZiAocGFydCA9PT0gJy4uJykge1xuICAgICAgICBkZXB0aCsrO1xuICAgICAgICBkZXB0aFN0cmluZyArPSAnLi4vJztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZGlnLnB1c2gocGFydCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnUGF0aEV4cHJlc3Npb24nLFxuICAgIGRhdGEsXG4gICAgZGVwdGgsXG4gICAgcGFydHM6IGRpZyxcbiAgICBvcmlnaW5hbCxcbiAgICBsb2NcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVNdXN0YWNoZShwYXRoLCBwYXJhbXMsIGhhc2gsIG9wZW4sIHN0cmlwLCBsb2NJbmZvKSB7XG4gIC8vIE11c3QgdXNlIGNoYXJBdCB0byBzdXBwb3J0IElFIHByZS0xMFxuICBsZXQgZXNjYXBlRmxhZyA9IG9wZW4uY2hhckF0KDMpIHx8IG9wZW4uY2hhckF0KDIpLFxuICAgICAgZXNjYXBlZCA9IGVzY2FwZUZsYWcgIT09ICd7JyAmJiBlc2NhcGVGbGFnICE9PSAnJic7XG5cbiAgbGV0IGRlY29yYXRvciA9ICgvXFwqLy50ZXN0KG9wZW4pKTtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBkZWNvcmF0b3IgPyAnRGVjb3JhdG9yJyA6ICdNdXN0YWNoZVN0YXRlbWVudCcsXG4gICAgcGF0aCxcbiAgICBwYXJhbXMsXG4gICAgaGFzaCxcbiAgICBlc2NhcGVkLFxuICAgIHN0cmlwLFxuICAgIGxvYzogdGhpcy5sb2NJbmZvKGxvY0luZm8pXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmVwYXJlUmF3QmxvY2sob3BlblJhd0Jsb2NrLCBjb250ZW50cywgY2xvc2UsIGxvY0luZm8pIHtcbiAgdmFsaWRhdGVDbG9zZShvcGVuUmF3QmxvY2ssIGNsb3NlKTtcblxuICBsb2NJbmZvID0gdGhpcy5sb2NJbmZvKGxvY0luZm8pO1xuICBsZXQgcHJvZ3JhbSA9IHtcbiAgICB0eXBlOiAnUHJvZ3JhbScsXG4gICAgYm9keTogY29udGVudHMsXG4gICAgc3RyaXA6IHt9LFxuICAgIGxvYzogbG9jSW5mb1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0Jsb2NrU3RhdGVtZW50JyxcbiAgICBwYXRoOiBvcGVuUmF3QmxvY2sucGF0aCxcbiAgICBwYXJhbXM6IG9wZW5SYXdCbG9jay5wYXJhbXMsXG4gICAgaGFzaDogb3BlblJhd0Jsb2NrLmhhc2gsXG4gICAgcHJvZ3JhbSxcbiAgICBvcGVuU3RyaXA6IHt9LFxuICAgIGludmVyc2VTdHJpcDoge30sXG4gICAgY2xvc2VTdHJpcDoge30sXG4gICAgbG9jOiBsb2NJbmZvXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmVwYXJlQmxvY2sob3BlbkJsb2NrLCBwcm9ncmFtLCBpbnZlcnNlQW5kUHJvZ3JhbSwgY2xvc2UsIGludmVydGVkLCBsb2NJbmZvKSB7XG4gIGlmIChjbG9zZSAmJiBjbG9zZS5wYXRoKSB7XG4gICAgdmFsaWRhdGVDbG9zZShvcGVuQmxvY2ssIGNsb3NlKTtcbiAgfVxuXG4gIGxldCBkZWNvcmF0b3IgPSAoL1xcKi8udGVzdChvcGVuQmxvY2sub3BlbikpO1xuXG4gIHByb2dyYW0uYmxvY2tQYXJhbXMgPSBvcGVuQmxvY2suYmxvY2tQYXJhbXM7XG5cbiAgbGV0IGludmVyc2UsXG4gICAgICBpbnZlcnNlU3RyaXA7XG5cbiAgaWYgKGludmVyc2VBbmRQcm9ncmFtKSB7XG4gICAgaWYgKGRlY29yYXRvcikge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVW5leHBlY3RlZCBpbnZlcnNlIGJsb2NrIG9uIGRlY29yYXRvcicsIGludmVyc2VBbmRQcm9ncmFtKTtcbiAgICB9XG5cbiAgICBpZiAoaW52ZXJzZUFuZFByb2dyYW0uY2hhaW4pIHtcbiAgICAgIGludmVyc2VBbmRQcm9ncmFtLnByb2dyYW0uYm9keVswXS5jbG9zZVN0cmlwID0gY2xvc2Uuc3RyaXA7XG4gICAgfVxuXG4gICAgaW52ZXJzZVN0cmlwID0gaW52ZXJzZUFuZFByb2dyYW0uc3RyaXA7XG4gICAgaW52ZXJzZSA9IGludmVyc2VBbmRQcm9ncmFtLnByb2dyYW07XG4gIH1cblxuICBpZiAoaW52ZXJ0ZWQpIHtcbiAgICBpbnZlcnRlZCA9IGludmVyc2U7XG4gICAgaW52ZXJzZSA9IHByb2dyYW07XG4gICAgcHJvZ3JhbSA9IGludmVydGVkO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBkZWNvcmF0b3IgPyAnRGVjb3JhdG9yQmxvY2snIDogJ0Jsb2NrU3RhdGVtZW50JyxcbiAgICBwYXRoOiBvcGVuQmxvY2sucGF0aCxcbiAgICBwYXJhbXM6IG9wZW5CbG9jay5wYXJhbXMsXG4gICAgaGFzaDogb3BlbkJsb2NrLmhhc2gsXG4gICAgcHJvZ3JhbSxcbiAgICBpbnZlcnNlLFxuICAgIG9wZW5TdHJpcDogb3BlbkJsb2NrLnN0cmlwLFxuICAgIGludmVyc2VTdHJpcCxcbiAgICBjbG9zZVN0cmlwOiBjbG9zZSAmJiBjbG9zZS5zdHJpcCxcbiAgICBsb2M6IHRoaXMubG9jSW5mbyhsb2NJbmZvKVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZVByb2dyYW0oc3RhdGVtZW50cywgbG9jKSB7XG4gIGlmICghbG9jICYmIHN0YXRlbWVudHMubGVuZ3RoKSB7XG4gICAgY29uc3QgZmlyc3RMb2MgPSBzdGF0ZW1lbnRzWzBdLmxvYyxcbiAgICAgICAgICBsYXN0TG9jID0gc3RhdGVtZW50c1tzdGF0ZW1lbnRzLmxlbmd0aCAtIDFdLmxvYztcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKGZpcnN0TG9jICYmIGxhc3RMb2MpIHtcbiAgICAgIGxvYyA9IHtcbiAgICAgICAgc291cmNlOiBmaXJzdExvYy5zb3VyY2UsXG4gICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgbGluZTogZmlyc3RMb2Muc3RhcnQubGluZSxcbiAgICAgICAgICBjb2x1bW46IGZpcnN0TG9jLnN0YXJ0LmNvbHVtblxuICAgICAgICB9LFxuICAgICAgICBlbmQ6IHtcbiAgICAgICAgICBsaW5lOiBsYXN0TG9jLmVuZC5saW5lLFxuICAgICAgICAgIGNvbHVtbjogbGFzdExvYy5lbmQuY29sdW1uXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnUHJvZ3JhbScsXG4gICAgYm9keTogc3RhdGVtZW50cyxcbiAgICBzdHJpcDoge30sXG4gICAgbG9jOiBsb2NcbiAgfTtcbn1cblxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZVBhcnRpYWxCbG9jayhvcGVuLCBwcm9ncmFtLCBjbG9zZSwgbG9jSW5mbykge1xuICB2YWxpZGF0ZUNsb3NlKG9wZW4sIGNsb3NlKTtcblxuICByZXR1cm4ge1xuICAgIHR5cGU6ICdQYXJ0aWFsQmxvY2tTdGF0ZW1lbnQnLFxuICAgIG5hbWU6IG9wZW4ucGF0aCxcbiAgICBwYXJhbXM6IG9wZW4ucGFyYW1zLFxuICAgIGhhc2g6IG9wZW4uaGFzaCxcbiAgICBwcm9ncmFtLFxuICAgIG9wZW5TdHJpcDogb3Blbi5zdHJpcCxcbiAgICBjbG9zZVN0cmlwOiBjbG9zZSAmJiBjbG9zZS5zdHJpcCxcbiAgICBsb2M6IHRoaXMubG9jSW5mbyhsb2NJbmZvKVxuICB9O1xufVxuXG4iXX0= +; +define('handlebars/compiler/base',['exports', './parser', './whitespace-control', './helpers', '../utils'], function (exports, _parser, _whitespaceControl, _helpers, _utils) { + 'use strict'; + + exports.__esModule = true; + exports.parse = parse; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _parser2 = _interopRequireDefault(_parser); + + var _WhitespaceControl = _interopRequireDefault(_whitespaceControl); + + exports.parser = _parser2['default']; + + var yy = {}; + _utils.extend(yy, _helpers); + + function parse(input, options) { + // Just return if an already-compiled AST was passed in. + if (input.type === 'Program') { + return input; + } + + _parser2['default'].yy = yy; + + // Altering the shared object here, but this is ok as parser is a sync operation + yy.locInfo = function (locInfo) { + return new yy.SourceLocation(options && options.srcName, locInfo); + }; + + var strip = new _WhitespaceControl['default'](options); + return strip.accept(_parser2['default'].parse(input)); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztVQUtTLE1BQU07O0FBRWYsTUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBQ1osU0FMUyxNQUFNLENBS1IsRUFBRSxXQUFVLENBQUM7O0FBRWIsV0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRTs7QUFFcEMsUUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTtBQUFFLGFBQU8sS0FBSyxDQUFDO0tBQUU7O0FBRS9DLHdCQUFPLEVBQUUsR0FBRyxFQUFFLENBQUM7OztBQUdmLE1BQUUsQ0FBQyxPQUFPLEdBQUcsVUFBUyxPQUFPLEVBQUU7QUFDN0IsYUFBTyxJQUFJLEVBQUUsQ0FBQyxjQUFjLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDbkUsQ0FBQzs7QUFFRixRQUFJLEtBQUssR0FBRyxrQ0FBc0IsT0FBTyxDQUFDLENBQUM7QUFDM0MsV0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLG9CQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0dBQzFDIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGFyc2VyIGZyb20gJy4vcGFyc2VyJztcbmltcG9ydCBXaGl0ZXNwYWNlQ29udHJvbCBmcm9tICcuL3doaXRlc3BhY2UtY29udHJvbCc7XG5pbXBvcnQgKiBhcyBIZWxwZXJzIGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgeyBleHRlbmQgfSBmcm9tICcuLi91dGlscyc7XG5cbmV4cG9ydCB7IHBhcnNlciB9O1xuXG5sZXQgeXkgPSB7fTtcbmV4dGVuZCh5eSwgSGVscGVycyk7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZShpbnB1dCwgb3B0aW9ucykge1xuICAvLyBKdXN0IHJldHVybiBpZiBhbiBhbHJlYWR5LWNvbXBpbGVkIEFTVCB3YXMgcGFzc2VkIGluLlxuICBpZiAoaW5wdXQudHlwZSA9PT0gJ1Byb2dyYW0nKSB7IHJldHVybiBpbnB1dDsgfVxuXG4gIHBhcnNlci55eSA9IHl5O1xuXG4gIC8vIEFsdGVyaW5nIHRoZSBzaGFyZWQgb2JqZWN0IGhlcmUsIGJ1dCB0aGlzIGlzIG9rIGFzIHBhcnNlciBpcyBhIHN5bmMgb3BlcmF0aW9uXG4gIHl5LmxvY0luZm8gPSBmdW5jdGlvbihsb2NJbmZvKSB7XG4gICAgcmV0dXJuIG5ldyB5eS5Tb3VyY2VMb2NhdGlvbihvcHRpb25zICYmIG9wdGlvbnMuc3JjTmFtZSwgbG9jSW5mbyk7XG4gIH07XG5cbiAgbGV0IHN0cmlwID0gbmV3IFdoaXRlc3BhY2VDb250cm9sKG9wdGlvbnMpO1xuICByZXR1cm4gc3RyaXAuYWNjZXB0KHBhcnNlci5wYXJzZShpbnB1dCkpO1xufVxuIl19 +; +define('handlebars/compiler/compiler',['exports', '../exception', '../utils', './ast'], function (exports, _exception, _utils, _ast) { + /* eslint-disable new-cap */ + + 'use strict'; + + exports.__esModule = true; + exports.Compiler = Compiler; + exports.precompile = precompile; + exports.compile = compile; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _AST = _interopRequireDefault(_ast); + + var slice = [].slice; + + function Compiler() {} + + // the foundHelper register will disambiguate helper lookup from finding a + // function in a context. This is necessary for mustache compatibility, which + // requires that context functions in blocks are evaluated by blockHelperMissing, + // and then proceed as if the resulting value was provided to blockHelperMissing. + + Compiler.prototype = { + compiler: Compiler, + + equals: function equals(other) { + var len = this.opcodes.length; + if (other.opcodes.length !== len) { + return false; + } + + for (var i = 0; i < len; i++) { + var opcode = this.opcodes[i], + otherOpcode = other.opcodes[i]; + if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { + return false; + } + } + + // We know that length is the same between the two arrays because they are directly tied + // to the opcode behavior above. + len = this.children.length; + for (var i = 0; i < len; i++) { + if (!this.children[i].equals(other.children[i])) { + return false; + } + } + + return true; + }, + + guid: 0, + + compile: function compile(program, options) { + this.sourceNode = []; + this.opcodes = []; + this.children = []; + this.options = options; + this.stringParams = options.stringParams; + this.trackIds = options.trackIds; + + options.blockParams = options.blockParams || []; + + // These changes will propagate to the other compiler components + var knownHelpers = options.knownHelpers; + options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true, + 'lookup': true + }; + if (knownHelpers) { + for (var _name in knownHelpers) { + /* istanbul ignore else */ + if (_name in knownHelpers) { + options.knownHelpers[_name] = knownHelpers[_name]; + } + } + } + + return this.accept(program); + }, + + compileProgram: function compileProgram(program) { + var childCompiler = new this.compiler(), + // eslint-disable-line new-cap + result = childCompiler.compile(program, this.options), + guid = this.guid++; + + this.usePartial = this.usePartial || result.usePartial; + + this.children[guid] = result; + this.useDepths = this.useDepths || result.useDepths; + + return guid; + }, + + accept: function accept(node) { + /* istanbul ignore next: Sanity code */ + if (!this[node.type]) { + throw new _Exception['default']('Unknown type: ' + node.type, node); + } + + this.sourceNode.unshift(node); + var ret = this[node.type](node); + this.sourceNode.shift(); + return ret; + }, + + Program: function Program(program) { + this.options.blockParams.unshift(program.blockParams); + + var body = program.body, + bodyLength = body.length; + for (var i = 0; i < bodyLength; i++) { + this.accept(body[i]); + } + + this.options.blockParams.shift(); + + this.isSimple = bodyLength === 1; + this.blockParams = program.blockParams ? program.blockParams.length : 0; + + return this; + }, + + BlockStatement: function BlockStatement(block) { + transformLiteralToPath(block); + + var program = block.program, + inverse = block.inverse; + + program = program && this.compileProgram(program); + inverse = inverse && this.compileProgram(inverse); + + var type = this.classifySexpr(block); + + if (type === 'helper') { + this.helperSexpr(block, program, inverse); + } else if (type === 'simple') { + this.simpleSexpr(block); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('blockValue', block.path.original); + } else { + this.ambiguousSexpr(block, program, inverse); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('ambiguousBlockValue'); + } + + this.opcode('append'); + }, + + DecoratorBlock: function DecoratorBlock(decorator) { + var program = decorator.program && this.compileProgram(decorator.program); + var params = this.setupFullMustacheParams(decorator, program, undefined), + path = decorator.path; + + this.useDecorators = true; + this.opcode('registerDecorator', params.length, path.original); + }, + + PartialStatement: function PartialStatement(partial) { + this.usePartial = true; + + var program = partial.program; + if (program) { + program = this.compileProgram(partial.program); + } + + var params = partial.params; + if (params.length > 1) { + throw new _Exception['default']('Unsupported number of partial arguments: ' + params.length, partial); + } else if (!params.length) { + if (this.options.explicitPartialContext) { + this.opcode('pushLiteral', 'undefined'); + } else { + params.push({ type: 'PathExpression', parts: [], depth: 0 }); + } + } + + var partialName = partial.name.original, + isDynamic = partial.name.type === 'SubExpression'; + if (isDynamic) { + this.accept(partial.name); + } + + this.setupFullMustacheParams(partial, program, undefined, true); + + var indent = partial.indent || ''; + if (this.options.preventIndent && indent) { + this.opcode('appendContent', indent); + indent = ''; + } + + this.opcode('invokePartial', isDynamic, partialName, indent); + this.opcode('append'); + }, + PartialBlockStatement: function PartialBlockStatement(partialBlock) { + this.PartialStatement(partialBlock); + }, + + MustacheStatement: function MustacheStatement(mustache) { + this.SubExpression(mustache); + + if (mustache.escaped && !this.options.noEscape) { + this.opcode('appendEscaped'); + } else { + this.opcode('append'); + } + }, + Decorator: function Decorator(decorator) { + this.DecoratorBlock(decorator); + }, + + ContentStatement: function ContentStatement(content) { + if (content.value) { + this.opcode('appendContent', content.value); + } + }, + + CommentStatement: function CommentStatement() {}, + + SubExpression: function SubExpression(sexpr) { + transformLiteralToPath(sexpr); + var type = this.classifySexpr(sexpr); + + if (type === 'simple') { + this.simpleSexpr(sexpr); + } else if (type === 'helper') { + this.helperSexpr(sexpr); + } else { + this.ambiguousSexpr(sexpr); + } + }, + ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) { + var path = sexpr.path, + name = path.parts[0], + isBlock = program != null || inverse != null; + + this.opcode('getContext', path.depth); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + path.strict = true; + this.accept(path); + + this.opcode('invokeAmbiguous', name, isBlock); + }, + + simpleSexpr: function simpleSexpr(sexpr) { + var path = sexpr.path; + path.strict = true; + this.accept(path); + this.opcode('resolvePossibleLambda'); + }, + + helperSexpr: function helperSexpr(sexpr, program, inverse) { + var params = this.setupFullMustacheParams(sexpr, program, inverse), + path = sexpr.path, + name = path.parts[0]; + + if (this.options.knownHelpers[name]) { + this.opcode('invokeKnownHelper', params.length, name); + } else if (this.options.knownHelpersOnly) { + throw new _Exception['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); + } else { + path.strict = true; + path.falsy = true; + + this.accept(path); + this.opcode('invokeHelper', params.length, path.original, _AST['default'].helpers.simpleId(path)); + } + }, + + PathExpression: function PathExpression(path) { + this.addDepth(path.depth); + this.opcode('getContext', path.depth); + + var name = path.parts[0], + scoped = _AST['default'].helpers.scopedId(path), + blockParamId = !path.depth && !scoped && this.blockParamIndex(name); + + if (blockParamId) { + this.opcode('lookupBlockParam', blockParamId, path.parts); + } else if (!name) { + // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` + this.opcode('pushContext'); + } else if (path.data) { + this.options.data = true; + this.opcode('lookupData', path.depth, path.parts, path.strict); + } else { + this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); + } + }, + + StringLiteral: function StringLiteral(string) { + this.opcode('pushString', string.value); + }, + + NumberLiteral: function NumberLiteral(number) { + this.opcode('pushLiteral', number.value); + }, + + BooleanLiteral: function BooleanLiteral(bool) { + this.opcode('pushLiteral', bool.value); + }, + + UndefinedLiteral: function UndefinedLiteral() { + this.opcode('pushLiteral', 'undefined'); + }, + + NullLiteral: function NullLiteral() { + this.opcode('pushLiteral', 'null'); + }, + + Hash: function Hash(hash) { + var pairs = hash.pairs, + i = 0, + l = pairs.length; + + this.opcode('pushHash'); + + for (; i < l; i++) { + this.pushParam(pairs[i].value); + } + while (i--) { + this.opcode('assignToHash', pairs[i].key); + } + this.opcode('popHash'); + }, + + // HELPERS + opcode: function opcode(name) { + this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc }); + }, + + addDepth: function addDepth(depth) { + if (!depth) { + return; + } + + this.useDepths = true; + }, + + classifySexpr: function classifySexpr(sexpr) { + var isSimple = _AST['default'].helpers.simpleId(sexpr.path); + + var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + var isHelper = !isBlockParam && _AST['default'].helpers.helperExpression(sexpr); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + var isEligible = !isBlockParam && (isHelper || isSimple); + + // if ambiguous, we can possibly resolve the ambiguity now + // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. + if (isEligible && !isHelper) { + var _name2 = sexpr.path.parts[0], + options = this.options; + + if (options.knownHelpers[_name2]) { + isHelper = true; + } else if (options.knownHelpersOnly) { + isEligible = false; + } + } + + if (isHelper) { + return 'helper'; + } else if (isEligible) { + return 'ambiguous'; + } else { + return 'simple'; + } + }, + + pushParams: function pushParams(params) { + for (var i = 0, l = params.length; i < l; i++) { + this.pushParam(params[i]); + } + }, + + pushParam: function pushParam(val) { + var value = val.value != null ? val.value : val.original || ''; + + if (this.stringParams) { + if (value.replace) { + value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.'); + } + + if (val.depth) { + this.addDepth(val.depth); + } + this.opcode('getContext', val.depth || 0); + this.opcode('pushStringParam', value, val.type); + + if (val.type === 'SubExpression') { + // SubExpressions get evaluated and passed in + // in string params mode. + this.accept(val); + } + } else { + if (this.trackIds) { + var blockParamIndex = undefined; + if (val.parts && !_AST['default'].helpers.scopedId(val) && !val.depth) { + blockParamIndex = this.blockParamIndex(val.parts[0]); + } + if (blockParamIndex) { + var blockParamChild = val.parts.slice(1).join('.'); + this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); + } else { + value = val.original || value; + if (value.replace) { + value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, ''); + } + + this.opcode('pushId', val.type, value); + } + } + this.accept(val); + } + }, + + setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) { + var params = sexpr.params; + this.pushParams(params); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + if (sexpr.hash) { + this.accept(sexpr.hash); + } else { + this.opcode('emptyHash', omitEmpty); + } + + return params; + }, + + blockParamIndex: function blockParamIndex(name) { + for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { + var blockParams = this.options.blockParams[depth], + param = blockParams && _utils.indexOf(blockParams, name); + if (blockParams && param >= 0) { + return [depth, param]; + } + } + } + }; + + function precompile(input, options, env) { + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _Exception['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); + } + + options = options || {}; + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options); + return new env.JavaScriptCompiler().compile(environment, options); + } + + function compile(input, options, env) { + if (options === undefined) options = {}; + + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _Exception['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); + } + + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var compiled = undefined; + + function compileInput() { + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options), + templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); + return env.template(templateSpec); + } + + // Template is only compiled on first use and cached after that point. + function ret(context, execOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled.call(this, context, execOptions); + } + ret._setup = function (setupOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._setup(setupOptions); + }; + ret._child = function (i, data, blockParams, depths) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._child(i, data, blockParams, depths); + }; + return ret; + } + + function argEquals(a, b) { + if (a === b) { + return true; + } + + if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) { + for (var i = 0; i < a.length; i++) { + if (!argEquals(a[i], b[i])) { + return false; + } + } + return true; + } + } + + function transformLiteralToPath(sexpr) { + if (!sexpr.path.parts) { + var literal = sexpr.path; + // Casting to string here to make false and 0 literal values play nicely with the rest + // of the system. + sexpr.path = { + type: 'PathExpression', + data: false, + depth: 0, + parts: [literal.original + ''], + original: literal.original + '', + loc: literal.loc + }; + } + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvbXBpbGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBTUEsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQzs7QUFFaEIsV0FBUyxRQUFRLEdBQUcsRUFBRTs7Ozs7OztBQU83QixVQUFRLENBQUMsU0FBUyxHQUFHO0FBQ25CLFlBQVEsRUFBRSxRQUFROztBQUVsQixVQUFNLEVBQUUsZ0JBQVMsS0FBSyxFQUFFO0FBQ3RCLFVBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO0FBQzlCLFVBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFO0FBQ2hDLGVBQU8sS0FBSyxDQUFDO09BQ2Q7O0FBRUQsV0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM1QixZQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN4QixXQUFXLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNuQyxZQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssV0FBVyxDQUFDLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRTtBQUNyRixpQkFBTyxLQUFLLENBQUM7U0FDZDtPQUNGOzs7O0FBSUQsU0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO0FBQzNCLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDNUIsWUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FB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S0FBSyxDQUFDLENBQUMsTUFBTSxFQUFFO0FBQ3JELFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQ2pDLFlBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0FBQzFCLGlCQUFPLEtBQUssQ0FBQztTQUNkO09BQ0Y7QUFDRCxhQUFPLElBQUksQ0FBQztLQUNiO0dBQ0Y7O0FBRUQsV0FBUyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUU7QUFDckMsUUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO0FBQ3JCLFVBQUksT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7OztBQUd6QixXQUFLLENBQUMsSUFBSSxHQUFHO0FBQ1gsWUFBSSxFQUFFLGdCQUFnQjtBQUN0QixZQUFJLEVBQUUsS0FBSztBQUNYLGFBQUssRUFBRSxDQUFDO0FBQ1IsYUFBSyxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7QUFDOUIsZ0JBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxHQUFHLEVBQUU7QUFDL0IsV0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO09BQ2pCLENBQUM7S0FDSDtHQUNGIiwiZmlsZSI6ImNvbXBpbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbmV3LWNhcCAqL1xuXG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5pbXBvcnQge2lzQXJyYXksIGluZGV4T2Z9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCBBU1QgZnJvbSAnLi9hc3QnO1xuXG5jb25zdCBzbGljZSA9IFtdLnNsaWNlO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcGlsZXIoKSB7fVxuXG4vLyB0aGUgZm91bmRIZWxwZXIgcmVnaXN0ZXIgd2lsbCBkaXNhbWJpZ3VhdGUgaGVscGVyIGxvb2t1cCBmcm9tIGZpbmRpbmcgYVxuLy8gZnVuY3Rpb24gaW4gYSBjb250ZXh0LiBUaGlzIGlzIG5lY2Vzc2FyeSBmb3IgbXVzdGFjaGUgY29tcGF0aWJpbGl0eSwgd2hpY2hcbi8vIHJlcXVpcmVzIHRoYXQgY29udGV4dCBmdW5jdGlvbnMgaW4gYmxvY2tzIGFyZSBldmFsdWF0ZWQgYnkgYmxvY2tIZWxwZXJNaXNzaW5nLFxuLy8gYW5kIHRoZW4gcHJvY2VlZCBhcyBpZiB0aGUgcmVzdWx0aW5nIHZhbHVlIHdhcyBwcm92aWRlZCB0byBibG9ja0hlbHBlck1pc3NpbmcuXG5cbkNvbXBpbGVyLnByb3RvdHlwZSA9IHtcbiAgY29tcGlsZXI6IENvbXBpbGVyLFxuXG4gIGVxdWFsczogZnVuY3Rpb24ob3RoZXIpIHtcbiAgICBsZXQgbGVuID0gdGhpcy5vcGNvZGVzLmxlbmd0aDtcbiAgICBpZiAob3RoZXIub3Bjb2Rlcy5sZW5ndGggIT09IGxlbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGxldCBvcGNvZGUgPSB0aGlzLm9wY29kZXNbaV0sXG4gICAgICAgICAgb3RoZXJPcGNvZGUgPSBvdGhlci5vcGNvZGVzW2ldO1xuICAgICAgaWYgKG9wY29kZS5vcGNvZGUgIT09IG90aGVyT3Bjb2RlLm9wY29kZSB8fCAhYXJnRXF1YWxzKG9wY29kZS5hcmdzLCBvdGhlck9wY29kZS5hcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gV2Uga25vdyB0aGF0IGxlbmd0aCBpcyB0aGUgc2FtZSBiZXR3ZWVuIHRoZSB0d28gYXJyYXlzIGJlY2F1c2UgdGhleSBhcmUgZGlyZWN0bHkgdGllZFxuICAgIC8vIHRvIHRoZSBvcGNvZGUgYmVoYXZpb3IgYWJvdmUuXG4gICAgbGVuID0gdGhpcy5jaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgaWYgKCF0aGlzLmNoaWxkcmVuW2ldLmVxdWFscyhvdGhlci5jaGlsZHJlbltpXSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGd1aWQ6IDAsXG5cbiAgY29tcGlsZTogZnVuY3Rpb24ocHJvZ3JhbSwgb3B0aW9ucykge1xuICAgIHRoaXMuc291cmNlTm9kZSA9IFtdO1xuICAgIHRoaXMub3Bjb2RlcyA9IFtdO1xuICAgIHRoaXMuY2hpbGRyZW4gPSBbXTtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMuc3RyaW5nUGFyYW1zID0gb3B0aW9ucy5zdHJpbmdQYXJhbXM7XG4gICAgdGhpcy50cmFja0lkcyA9IG9wdGlvbnMudHJhY2tJZHM7XG5cbiAgICBvcHRpb25zLmJsb2NrUGFyYW1zID0gb3B0aW9ucy5ibG9ja1BhcmFtcyB8fCBbXTtcblxuICAgIC8vIFRoZXNlIGNoYW5nZXMgd2lsbCBwcm9wYWdhdGUgdG8gdGhlIG90aGVyIGNvbXBpbGVyIGNvbXBvbmVudHNcbiAgICBsZXQga25vd25IZWxwZXJzID0gb3B0aW9ucy5rbm93bkhlbHBlcnM7XG4gICAgb3B0aW9ucy5rbm93bkhlbHBlcnMgPSB7XG4gICAgICAnaGVscGVyTWlzc2luZyc6IHRydWUsXG4gICAgICAnYmxvY2tIZWxwZXJNaXNzaW5nJzogdHJ1ZSxcbiAgICAgICdlYWNoJzogdHJ1ZSxcbiAgICAgICdpZic6IHRydWUsXG4gICAgICAndW5sZXNzJzogdHJ1ZSxcbiAgICAgICd3aXRoJzogdHJ1ZSxcbiAgICAgICdsb2cnOiB0cnVlLFxuICAgICAgJ2xvb2t1cCc6IHRydWVcbiAgICB9O1xuICAgIGlmIChrbm93bkhlbHBlcnMpIHtcbiAgICAgIGZvciAobGV0IG5hbWUgaW4ga25vd25IZWxwZXJzKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgIGlmIChuYW1lIGluIGtub3duSGVscGVycykge1xuICAgICAgICAgIG9wdGlvbnMua25vd25IZWxwZXJzW25hbWVdID0ga25vd25IZWxwZXJzW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYWNjZXB0KHByb2dyYW0pO1xuICB9LFxuXG4gIGNvbXBpbGVQcm9ncmFtOiBmdW5jdGlvbihwcm9ncmFtKSB7XG4gICAgbGV0IGNoaWxkQ29tcGlsZXIgPSBuZXcgdGhpcy5jb21waWxlcigpLCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5ldy1jYXBcbiAgICAgICAgcmVzdWx0ID0gY2hpbGRDb21waWxlci5jb21waWxlKHByb2dyYW0sIHRoaXMub3B0aW9ucyksXG4gICAgICAgIGd1aWQgPSB0aGlzLmd1aWQrKztcblxuICAgIHRoaXMudXNlUGFydGlhbCA9IHRoaXMudXNlUGFydGlhbCB8fCByZXN1bHQudXNlUGFydGlhbDtcblxuICAgIHRoaXMuY2hpbGRyZW5bZ3VpZF0gPSByZXN1bHQ7XG4gICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCByZXN1bHQudXNlRGVwdGhzO1xuXG4gICAgcmV0dXJuIGd1aWQ7XG4gIH0sXG5cbiAgYWNjZXB0OiBmdW5jdGlvbihub2RlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IFNhbml0eSBjb2RlICovXG4gICAgaWYgKCF0aGlzW25vZGUudHlwZV0pIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdHlwZTogJyArIG5vZGUudHlwZSwgbm9kZSk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VOb2RlLnVuc2hpZnQobm9kZSk7XG4gICAgbGV0IHJldCA9IHRoaXNbbm9kZS50eXBlXShub2RlKTtcbiAgICB0aGlzLnNvdXJjZU5vZGUuc2hpZnQoKTtcbiAgICByZXR1cm4gcmV0O1xuICB9LFxuXG4gIFByb2dyYW06IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgICB0aGlzLm9wdGlvbnMuYmxvY2tQYXJhbXMudW5zaGlmdChwcm9ncmFtLmJsb2NrUGFyYW1zKTtcblxuICAgIGxldCBib2R5ID0gcHJvZ3JhbS5ib2R5LFxuICAgICAgICBib2R5TGVuZ3RoID0gYm9keS5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBib2R5TGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuYWNjZXB0KGJvZHlbaV0pO1xuICAgIH1cblxuICAgIHRoaXMub3B0aW9ucy5ibG9ja1BhcmFtcy5zaGlmdCgpO1xuXG4gICAgdGhpcy5pc1NpbXBsZSA9IGJvZHlMZW5ndGggPT09IDE7XG4gICAgdGhpcy5ibG9ja1BhcmFtcyA9IHByb2dyYW0uYmxvY2tQYXJhbXMgPyBwcm9ncmFtLmJsb2NrUGFyYW1zLmxlbmd0aCA6IDA7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBCbG9ja1N0YXRlbWVudDogZnVuY3Rpb24oYmxvY2spIHtcbiAgICB0cmFuc2Zvcm1MaXRlcmFsVG9QYXRoKGJsb2NrKTtcblxuICAgIGxldCBwcm9ncmFtID0gYmxvY2sucHJvZ3JhbSxcbiAgICAgICAgaW52ZXJzZSA9IGJsb2NrLmludmVyc2U7XG5cbiAgICBwcm9ncmFtID0gcHJvZ3JhbSAmJiB0aGlzLmNvbXBpbGVQcm9ncmFtKHByb2dyYW0pO1xuICAgIGludmVyc2UgPSBpbnZlcnNlICYmIHRoaXMuY29tcGlsZVByb2dyYW0oaW52ZXJzZSk7XG5cbiAgICBsZXQgdHlwZSA9IHRoaXMuY2xhc3NpZnlTZXhwcihibG9jayk7XG5cbiAgICBpZiAodHlwZSA9PT0gJ2hlbHBlcicpIHtcbiAgICAgIHRoaXMuaGVscGVyU2V4cHIoYmxvY2ssIHByb2dyYW0sIGludmVyc2UpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3NpbXBsZScpIHtcbiAgICAgIHRoaXMuc2ltcGxlU2V4cHIoYmxvY2spO1xuXG4gICAgICAvLyBub3cgdGhhdCB0aGUgc2ltcGxlIG11c3RhY2hlIGlzIHJlc29sdmVkLCB3ZSBuZWVkIHRvXG4gICAgICAvLyBldmFsdWF0ZSBpdCBieSBleGVjdXRpbmcgYGJsb2NrSGVscGVyTWlzc2luZ2BcbiAgICAgIHRoaXMub3Bjb2RlKCdwdXNoUHJvZ3JhbScsIHByb2dyYW0pO1xuICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgaW52ZXJzZSk7XG4gICAgICB0aGlzLm9wY29kZSgnZW1wdHlIYXNoJyk7XG4gICAgICB0aGlzLm9wY29kZSgnYmxvY2tWYWx1ZScsIGJsb2NrLnBhdGgub3JpZ2luYWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFtYmlndW91c1NleHByKGJsb2NrLCBwcm9ncmFtLCBpbnZlcnNlKTtcblxuICAgICAgLy8gbm93IHRoYXQgdGhlIHNpbXBsZSBtdXN0YWNoZSBpcyByZXNvbHZlZCwgd2UgbmVlZCB0b1xuICAgICAgLy8gZXZhbHVhdGUgaXQgYnkgZXhlY3V0aW5nIGBibG9ja0hlbHBlck1pc3NpbmdgXG4gICAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBwcm9ncmFtKTtcbiAgICAgIHRoaXMub3Bjb2RlKCdwdXNoUHJvZ3JhbScsIGludmVyc2UpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2VtcHR5SGFzaCcpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2FtYmlndW91c0Jsb2NrVmFsdWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLm9wY29kZSgnYXBwZW5kJyk7XG4gIH0sXG5cbiAgRGVjb3JhdG9yQmxvY2soZGVjb3JhdG9yKSB7XG4gICAgbGV0IHByb2dyYW0gPSBkZWNvcmF0b3IucHJvZ3JhbSAmJiB0aGlzLmNvbXBpbGVQcm9ncmFtKGRlY29yYXRvci5wcm9ncmFtKTtcbiAgICBsZXQgcGFyYW1zID0gdGhpcy5zZXR1cEZ1bGxNdXN0YWNoZVBhcmFtcyhkZWNvcmF0b3IsIHByb2dyYW0sIHVuZGVmaW5lZCksXG4gICAgICAgIHBhdGggPSBkZWNvcmF0b3IucGF0aDtcblxuICAgIHRoaXMudXNlRGVjb3JhdG9ycyA9IHRydWU7XG4gICAgdGhpcy5vcGNvZGUoJ3JlZ2lzdGVyRGVjb3JhdG9yJywgcGFyYW1zLmxlbmd0aCwgcGF0aC5vcmlnaW5hbCk7XG4gIH0sXG5cbiAgUGFydGlhbFN0YXRlbWVudDogZnVuY3Rpb24ocGFydGlhbCkge1xuICAgIHRoaXMudXNlUGFydGlhbCA9IHRydWU7XG5cbiAgICBsZXQgcHJvZ3JhbSA9IHBhcnRpYWwucHJvZ3JhbTtcbiAgICBpZiAocHJvZ3JhbSkge1xuICAgICAgcHJvZ3JhbSA9IHRoaXMuY29tcGlsZVByb2dyYW0ocGFydGlhbC5wcm9ncmFtKTtcbiAgICB9XG5cbiAgICBsZXQgcGFyYW1zID0gcGFydGlhbC5wYXJhbXM7XG4gICAgaWYgKHBhcmFtcy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdVbnN1cHBvcnRlZCBudW1iZXIgb2YgcGFydGlhbCBhcmd1bWVudHM6ICcgKyBwYXJhbXMubGVuZ3RoLCBwYXJ0aWFsKTtcbiAgICB9IGVsc2UgaWYgKCFwYXJhbXMubGVuZ3RoKSB7XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmV4cGxpY2l0UGFydGlhbENvbnRleHQpIHtcbiAgICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgJ3VuZGVmaW5lZCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zLnB1c2goe3R5cGU6ICdQYXRoRXhwcmVzc2lvbicsIHBhcnRzOiBbXSwgZGVwdGg6IDB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgcGFydGlhbE5hbWUgPSBwYXJ0aWFsLm5hbWUub3JpZ2luYWwsXG4gICAgICAgIGlzRHluYW1pYyA9IHBhcnRpYWwubmFtZS50eXBlID09PSAnU3ViRXhwcmVzc2lvbic7XG4gICAgaWYgKGlzRHluYW1pYykge1xuICAgICAgdGhpcy5hY2NlcHQocGFydGlhbC5uYW1lKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldHVwRnVsbE11c3RhY2hlUGFyYW1zKHBhcnRpYWwsIHByb2dyYW0sIHVuZGVmaW5lZCwgdHJ1ZSk7XG5cbiAgICBsZXQgaW5kZW50ID0gcGFydGlhbC5pbmRlbnQgfHwgJyc7XG4gICAgaWYgKHRoaXMub3B0aW9ucy5wcmV2ZW50SW5kZW50ICYmIGluZGVudCkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZENvbnRlbnQnLCBpbmRlbnQpO1xuICAgICAgaW5kZW50ID0gJyc7XG4gICAgfVxuXG4gICAgdGhpcy5vcGNvZGUoJ2ludm9rZVBhcnRpYWwnLCBpc0R5bmFtaWMsIHBhcnRpYWxOYW1lLCBpbmRlbnQpO1xuICAgIHRoaXMub3Bjb2RlKCdhcHBlbmQnKTtcbiAgfSxcbiAgUGFydGlhbEJsb2NrU3RhdGVtZW50OiBmdW5jdGlvbihwYXJ0aWFsQmxvY2spIHtcbiAgICB0aGlzLlBhcnRpYWxTdGF0ZW1lbnQocGFydGlhbEJsb2NrKTtcbiAgfSxcblxuICBNdXN0YWNoZVN0YXRlbWVudDogZnVuY3Rpb24obXVzdGFjaGUpIHtcbiAgICB0aGlzLlN1YkV4cHJlc3Npb24obXVzdGFjaGUpO1xuXG4gICAgaWYgKG11c3RhY2hlLmVzY2FwZWQgJiYgIXRoaXMub3B0aW9ucy5ub0VzY2FwZSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZEVzY2FwZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZCcpO1xuICAgIH1cbiAgfSxcbiAgRGVjb3JhdG9yKGRlY29yYXRvcikge1xuICAgIHRoaXMuRGVjb3JhdG9yQmxvY2soZGVjb3JhdG9yKTtcbiAgfSxcblxuXG4gIENvbnRlbnRTdGF0ZW1lbnQ6IGZ1bmN0aW9uKGNvbnRlbnQpIHtcbiAgICBpZiAoY29udGVudC52YWx1ZSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2FwcGVuZENvbnRlbnQnLCBjb250ZW50LnZhbHVlKTtcbiAgICB9XG4gIH0sXG5cbiAgQ29tbWVudFN0YXRlbWVudDogZnVuY3Rpb24oKSB7fSxcblxuICBTdWJFeHByZXNzaW9uOiBmdW5jdGlvbihzZXhwcikge1xuICAgIHRyYW5zZm9ybUxpdGVyYWxUb1BhdGgoc2V4cHIpO1xuICAgIGxldCB0eXBlID0gdGhpcy5jbGFzc2lmeVNleHByKHNleHByKTtcblxuICAgIGlmICh0eXBlID09PSAnc2ltcGxlJykge1xuICAgICAgdGhpcy5zaW1wbGVTZXhwcihzZXhwcik7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnaGVscGVyJykge1xuICAgICAgdGhpcy5oZWxwZXJTZXhwcihzZXhwcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYW1iaWd1b3VzU2V4cHIoc2V4cHIpO1xuICAgIH1cbiAgfSxcbiAgYW1iaWd1b3VzU2V4cHI6IGZ1bmN0aW9uKHNleHByLCBwcm9ncmFtLCBpbnZlcnNlKSB7XG4gICAgbGV0IHBhdGggPSBzZXhwci5wYXRoLFxuICAgICAgICBuYW1lID0gcGF0aC5wYXJ0c1swXSxcbiAgICAgICAgaXNCbG9jayA9IHByb2dyYW0gIT0gbnVsbCB8fCBpbnZlcnNlICE9IG51bGw7XG5cbiAgICB0aGlzLm9wY29kZSgnZ2V0Q29udGV4dCcsIHBhdGguZGVwdGgpO1xuXG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgcHJvZ3JhbSk7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hQcm9ncmFtJywgaW52ZXJzZSk7XG5cbiAgICBwYXRoLnN0cmljdCA9IHRydWU7XG4gICAgdGhpcy5hY2NlcHQocGF0aCk7XG5cbiAgICB0aGlzLm9wY29kZSgnaW52b2tlQW1iaWd1b3VzJywgbmFtZSwgaXNCbG9jayk7XG4gIH0sXG5cbiAgc2ltcGxlU2V4cHI6IGZ1bmN0aW9uKHNleHByKSB7XG4gICAgbGV0IHBhdGggPSBzZXhwci5wYXRoO1xuICAgIHBhdGguc3RyaWN0ID0gdHJ1ZTtcbiAgICB0aGlzLmFjY2VwdChwYXRoKTtcbiAgICB0aGlzLm9wY29kZSgncmVzb2x2ZVBvc3NpYmxlTGFtYmRhJyk7XG4gIH0sXG5cbiAgaGVscGVyU2V4cHI6IGZ1bmN0aW9uKHNleHByLCBwcm9ncmFtLCBpbnZlcnNlKSB7XG4gICAgbGV0IHBhcmFtcyA9IHRoaXMuc2V0dXBGdWxsTXVzdGFjaGVQYXJhbXMoc2V4cHIsIHByb2dyYW0sIGludmVyc2UpLFxuICAgICAgICBwYXRoID0gc2V4cHIucGF0aCxcbiAgICAgICAgbmFtZSA9IHBhdGgucGFydHNbMF07XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmtub3duSGVscGVyc1tuYW1lXSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2ludm9rZUtub3duSGVscGVyJywgcGFyYW1zLmxlbmd0aCwgbmFtZSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMua25vd25IZWxwZXJzT25seSkge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignWW91IHNwZWNpZmllZCBrbm93bkhlbHBlcnNPbmx5LCBidXQgdXNlZCB0aGUgdW5rbm93biBoZWxwZXIgJyArIG5hbWUsIHNleHByKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0aC5zdHJpY3QgPSB0cnVlO1xuICAgICAgcGF0aC5mYWxzeSA9IHRydWU7XG5cbiAgICAgIHRoaXMuYWNjZXB0KHBhdGgpO1xuICAgICAgdGhpcy5vcGNvZGUoJ2ludm9rZUhlbHBlcicsIHBhcmFtcy5sZW5ndGgsIHBhdGgub3JpZ2luYWwsIEFTVC5oZWxwZXJzLnNpbXBsZUlkKHBhdGgpKTtcbiAgICB9XG4gIH0sXG5cbiAgUGF0aEV4cHJlc3Npb246IGZ1bmN0aW9uKHBhdGgpIHtcbiAgICB0aGlzLmFkZERlcHRoKHBhdGguZGVwdGgpO1xuICAgIHRoaXMub3Bjb2RlKCdnZXRDb250ZXh0JywgcGF0aC5kZXB0aCk7XG5cbiAgICBsZXQgbmFtZSA9IHBhdGgucGFydHNbMF0sXG4gICAgICAgIHNjb3BlZCA9IEFTVC5oZWxwZXJzLnNjb3BlZElkKHBhdGgpLFxuICAgICAgICBibG9ja1BhcmFtSWQgPSAhcGF0aC5kZXB0aCAmJiAhc2NvcGVkICYmIHRoaXMuYmxvY2tQYXJhbUluZGV4KG5hbWUpO1xuXG4gICAgaWYgKGJsb2NrUGFyYW1JZCkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2xvb2t1cEJsb2NrUGFyYW0nLCBibG9ja1BhcmFtSWQsIHBhdGgucGFydHMpO1xuICAgIH0gZWxzZSBpZiAoIW5hbWUpIHtcbiAgICAgIC8vIENvbnRleHQgcmVmZXJlbmNlLCBpLmUuIGB7e2ZvbyAufX1gIG9yIGB7e2ZvbyAuLn19YFxuICAgICAgdGhpcy5vcGNvZGUoJ3B1c2hDb250ZXh0Jyk7XG4gICAgfSBlbHNlIGlmIChwYXRoLmRhdGEpIHtcbiAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gdHJ1ZTtcbiAgICAgIHRoaXMub3Bjb2RlKCdsb29rdXBEYXRhJywgcGF0aC5kZXB0aCwgcGF0aC5wYXJ0cywgcGF0aC5zdHJpY3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm9wY29kZSgnbG9va3VwT25Db250ZXh0JywgcGF0aC5wYXJ0cywgcGF0aC5mYWxzeSwgcGF0aC5zdHJpY3QsIHNjb3BlZCk7XG4gICAgfVxuICB9LFxuXG4gIFN0cmluZ0xpdGVyYWw6IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHRoaXMub3Bjb2RlKCdwdXNoU3RyaW5nJywgc3RyaW5nLnZhbHVlKTtcbiAgfSxcblxuICBOdW1iZXJMaXRlcmFsOiBmdW5jdGlvbihudW1iZXIpIHtcbiAgICB0aGlzLm9wY29kZSgncHVzaExpdGVyYWwnLCBudW1iZXIudmFsdWUpO1xuICB9LFxuXG4gIEJvb2xlYW5MaXRlcmFsOiBmdW5jdGlvbihib29sKSB7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgYm9vbC52YWx1ZSk7XG4gIH0sXG5cbiAgVW5kZWZpbmVkTGl0ZXJhbDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5vcGNvZGUoJ3B1c2hMaXRlcmFsJywgJ3VuZGVmaW5lZCcpO1xuICB9LFxuXG4gIE51bGxMaXRlcmFsOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLm9wY29kZSgncHVzaExpdGVyYWwnLCAnbnVsbCcpO1xuICB9LFxuXG4gIEhhc2g6IGZ1bmN0aW9uKGhhc2gpIHtcbiAgICBsZXQgcGFpcnMgPSBoYXNoLnBhaXJzLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbCA9IHBhaXJzLmxlbmd0aDtcblxuICAgIHRoaXMub3Bjb2RlKCdwdXNoSGFzaCcpO1xuXG4gICAgZm9yICg7IGkgPCBsOyBpKyspIHtcbiAgICAgIHRoaXMucHVzaFBhcmFtKHBhaXJzW2ldLnZhbHVlKTtcbiAgICB9XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgdGhpcy5vcGNvZGUoJ2Fzc2lnblRvSGFzaCcsIHBhaXJzW2ldLmtleSk7XG4gICAgfVxuICAgIHRoaXMub3Bjb2RlKCdwb3BIYXNoJyk7XG4gIH0sXG5cbiAgLy8gSEVMUEVSU1xuICBvcGNvZGU6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB0aGlzLm9wY29kZXMucHVzaCh7IG9wY29kZTogbmFtZSwgYXJnczogc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLCBsb2M6IHRoaXMuc291cmNlTm9kZVswXS5sb2MgfSk7XG4gIH0sXG5cbiAgYWRkRGVwdGg6IGZ1bmN0aW9uKGRlcHRoKSB7XG4gICAgaWYgKCFkZXB0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudXNlRGVwdGhzID0gdHJ1ZTtcbiAgfSxcblxuICBjbGFzc2lmeVNleHByOiBmdW5jdGlvbihzZXhwcikge1xuICAgIGxldCBpc1NpbXBsZSA9IEFTVC5oZWxwZXJzLnNpbXBsZUlkKHNleHByLnBhdGgpO1xuXG4gICAgbGV0IGlzQmxvY2tQYXJhbSA9IGlzU2ltcGxlICYmICEhdGhpcy5ibG9ja1BhcmFtSW5kZXgoc2V4cHIucGF0aC5wYXJ0c1swXSk7XG5cbiAgICAvLyBhIG11c3RhY2hlIGlzIGFuIGVsaWdpYmxlIGhlbHBlciBpZjpcbiAgICAvLyAqIGl0cyBpZCBpcyBzaW1wbGUgKGEgc2luZ2xlIHBhcnQsIG5vdCBgdGhpc2Agb3IgYC4uYClcbiAgICBsZXQgaXNIZWxwZXIgPSAhaXNCbG9ja1BhcmFtICYmIEFTVC5oZWxwZXJzLmhlbHBlckV4cHJlc3Npb24oc2V4cHIpO1xuXG4gICAgLy8gaWYgYSBtdXN0YWNoZSBpcyBhbiBlbGlnaWJsZSBoZWxwZXIgYnV0IG5vdCBhIGRlZmluaXRlXG4gICAgLy8gaGVscGVyLCBpdCBpcyBhbWJpZ3VvdXMsIGFuZCB3aWxsIGJlIHJlc29sdmVkIGluIGEgbGF0ZXJcbiAgICAvLyBwYXNzIG9yIGF0IHJ1bnRpbWUuXG4gICAgbGV0IGlzRWxpZ2libGUgPSAhaXNCbG9ja1BhcmFtICYmIChpc0hlbHBlciB8fCBpc1NpbXBsZSk7XG5cbiAgICAvLyBpZiBhbWJpZ3VvdXMsIHdlIGNhbiBwb3NzaWJseSByZXNvbHZlIHRoZSBhbWJpZ3VpdHkgbm93XG4gICAgLy8gQW4gZWxpZ2libGUgaGVscGVyIGlzIG9uZSB0aGF0IGRvZXMgbm90IGhhdmUgYSBjb21wbGV4IHBhdGgsIGkuZS4gYHRoaXMuZm9vYCwgYC4uL2Zvb2AgZXRjLlxuICAgIGlmIChpc0VsaWdpYmxlICYmICFpc0hlbHBlcikge1xuICAgICAgbGV0IG5hbWUgPSBzZXhwci5wYXRoLnBhcnRzWzBdLFxuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgICAgIGlmIChvcHRpb25zLmtub3duSGVscGVyc1tuYW1lXSkge1xuICAgICAgICBpc0hlbHBlciA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnMua25vd25IZWxwZXJzT25seSkge1xuICAgICAgICBpc0VsaWdpYmxlID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzSGVscGVyKSB7XG4gICAgICByZXR1cm4gJ2hlbHBlcic7XG4gICAgfSBlbHNlIGlmIChpc0VsaWdpYmxlKSB7XG4gICAgICByZXR1cm4gJ2FtYmlndW91cyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnc2ltcGxlJztcbiAgICB9XG4gIH0sXG5cbiAgcHVzaFBhcmFtczogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBwYXJhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICB0aGlzLnB1c2hQYXJhbShwYXJhbXNbaV0pO1xuICAgIH1cbiAgfSxcblxuICBwdXNoUGFyYW06IGZ1bmN0aW9uKHZhbCkge1xuICAgIGxldCB2YWx1ZSA9IHZhbC52YWx1ZSAhPSBudWxsID8gdmFsLnZhbHVlIDogdmFsLm9yaWdpbmFsIHx8ICcnO1xuXG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICBpZiAodmFsdWUucmVwbGFjZSkge1xuICAgICAgICB2YWx1ZSA9IHZhbHVlXG4gICAgICAgICAgICAucmVwbGFjZSgvXihcXC4/XFwuXFwvKSovZywgJycpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFwvL2csICcuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh2YWwuZGVwdGgpIHtcbiAgICAgICAgdGhpcy5hZGREZXB0aCh2YWwuZGVwdGgpO1xuICAgICAgfVxuICAgICAgdGhpcy5vcGNvZGUoJ2dldENvbnRleHQnLCB2YWwuZGVwdGggfHwgMCk7XG4gICAgICB0aGlzLm9wY29kZSgncHVzaFN0cmluZ1BhcmFtJywgdmFsdWUsIHZhbC50eXBlKTtcblxuICAgICAgaWYgKHZhbC50eXBlID09PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgICAgLy8gU3ViRXhwcmVzc2lvbnMgZ2V0IGV2YWx1YXRlZCBhbmQgcGFzc2VkIGluXG4gICAgICAgIC8vIGluIHN0cmluZyBwYXJhbXMgbW9kZS5cbiAgICAgICAgdGhpcy5hY2NlcHQodmFsKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgICAgbGV0IGJsb2NrUGFyYW1JbmRleDtcbiAgICAgICAgaWYgKHZhbC5wYXJ0cyAmJiAhQVNULmhlbHBlcnMuc2NvcGVkSWQodmFsKSAmJiAhdmFsLmRlcHRoKSB7XG4gICAgICAgICAgIGJsb2NrUGFyYW1JbmRleCA9IHRoaXMuYmxvY2tQYXJhbUluZGV4KHZhbC5wYXJ0c1swXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJsb2NrUGFyYW1JbmRleCkge1xuICAgICAgICAgIGxldCBibG9ja1BhcmFtQ2hpbGQgPSB2YWwucGFydHMuc2xpY2UoMSkuam9pbignLicpO1xuICAgICAgICAgIHRoaXMub3Bjb2RlKCdwdXNoSWQnLCAnQmxvY2tQYXJhbScsIGJsb2NrUGFyYW1JbmRleCwgYmxvY2tQYXJhbUNoaWxkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWx1ZSA9IHZhbC5vcmlnaW5hbCB8fCB2YWx1ZTtcbiAgICAgICAgICBpZiAodmFsdWUucmVwbGFjZSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9edGhpcyg/OlxcLnwkKS8sICcnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9eXFwuXFwvLywgJycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL15cXC4kLywgJycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMub3Bjb2RlKCdwdXNoSWQnLCB2YWwudHlwZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmFjY2VwdCh2YWwpO1xuICAgIH1cbiAgfSxcblxuICBzZXR1cEZ1bGxNdXN0YWNoZVBhcmFtczogZnVuY3Rpb24oc2V4cHIsIHByb2dyYW0sIGludmVyc2UsIG9taXRFbXB0eSkge1xuICAgIGxldCBwYXJhbXMgPSBzZXhwci5wYXJhbXM7XG4gICAgdGhpcy5wdXNoUGFyYW1zKHBhcmFtcyk7XG5cbiAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBwcm9ncmFtKTtcbiAgICB0aGlzLm9wY29kZSgncHVzaFByb2dyYW0nLCBpbnZlcnNlKTtcblxuICAgIGlmIChzZXhwci5oYXNoKSB7XG4gICAgICB0aGlzLmFjY2VwdChzZXhwci5oYXNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGNvZGUoJ2VtcHR5SGFzaCcsIG9taXRFbXB0eSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmFtcztcbiAgfSxcblxuICBibG9ja1BhcmFtSW5kZXg6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBmb3IgKGxldCBkZXB0aCA9IDAsIGxlbiA9IHRoaXMub3B0aW9ucy5ibG9ja1BhcmFtcy5sZW5ndGg7IGRlcHRoIDwgbGVuOyBkZXB0aCsrKSB7XG4gICAgICBsZXQgYmxvY2tQYXJhbXMgPSB0aGlzLm9wdGlvbnMuYmxvY2tQYXJhbXNbZGVwdGhdLFxuICAgICAgICAgIHBhcmFtID0gYmxvY2tQYXJhbXMgJiYgaW5kZXhPZihibG9ja1BhcmFtcywgbmFtZSk7XG4gICAgICBpZiAoYmxvY2tQYXJhbXMgJiYgcGFyYW0gPj0gMCkge1xuICAgICAgICByZXR1cm4gW2RlcHRoLCBwYXJhbV07XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gcHJlY29tcGlsZShpbnB1dCwgb3B0aW9ucywgZW52KSB7XG4gIGlmIChpbnB1dCA9PSBudWxsIHx8ICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnICYmIGlucHV0LnR5cGUgIT09ICdQcm9ncmFtJykpIHtcbiAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdZb3UgbXVzdCBwYXNzIGEgc3RyaW5nIG9yIEhhbmRsZWJhcnMgQVNUIHRvIEhhbmRsZWJhcnMucHJlY29tcGlsZS4gWW91IHBhc3NlZCAnICsgaW5wdXQpO1xuICB9XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGlmICghKCdkYXRhJyBpbiBvcHRpb25zKSkge1xuICAgIG9wdGlvbnMuZGF0YSA9IHRydWU7XG4gIH1cbiAgaWYgKG9wdGlvbnMuY29tcGF0KSB7XG4gICAgb3B0aW9ucy51c2VEZXB0aHMgPSB0cnVlO1xuICB9XG5cbiAgbGV0IGFzdCA9IGVudi5wYXJzZShpbnB1dCwgb3B0aW9ucyksXG4gICAgICBlbnZpcm9ubWVudCA9IG5ldyBlbnYuQ29tcGlsZXIoKS5jb21waWxlKGFzdCwgb3B0aW9ucyk7XG4gIHJldHVybiBuZXcgZW52LkphdmFTY3JpcHRDb21waWxlcigpLmNvbXBpbGUoZW52aXJvbm1lbnQsIG9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZShpbnB1dCwgb3B0aW9ucyA9IHt9LCBlbnYpIHtcbiAgaWYgKGlucHV0ID09IG51bGwgfHwgKHR5cGVvZiBpbnB1dCAhPT0gJ3N0cmluZycgJiYgaW5wdXQudHlwZSAhPT0gJ1Byb2dyYW0nKSkge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1lvdSBtdXN0IHBhc3MgYSBzdHJpbmcgb3IgSGFuZGxlYmFycyBBU1QgdG8gSGFuZGxlYmFycy5jb21waWxlLiBZb3UgcGFzc2VkICcgKyBpbnB1dCk7XG4gIH1cblxuICBpZiAoISgnZGF0YScgaW4gb3B0aW9ucykpIHtcbiAgICBvcHRpb25zLmRhdGEgPSB0cnVlO1xuICB9XG4gIGlmIChvcHRpb25zLmNvbXBhdCkge1xuICAgIG9wdGlvbnMudXNlRGVwdGhzID0gdHJ1ZTtcbiAgfVxuXG4gIGxldCBjb21waWxlZDtcblxuICBmdW5jdGlvbiBjb21waWxlSW5wdXQoKSB7XG4gICAgbGV0IGFzdCA9IGVudi5wYXJzZShpbnB1dCwgb3B0aW9ucyksXG4gICAgICAgIGVudmlyb25tZW50ID0gbmV3IGVudi5Db21waWxlcigpLmNvbXBpbGUoYXN0LCBvcHRpb25zKSxcbiAgICAgICAgdGVtcGxhdGVTcGVjID0gbmV3IGVudi5KYXZhU2NyaXB0Q29tcGlsZXIoKS5jb21waWxlKGVudmlyb25tZW50LCBvcHRpb25zLCB1bmRlZmluZWQsIHRydWUpO1xuICAgIHJldHVybiBlbnYudGVtcGxhdGUodGVtcGxhdGVTcGVjKTtcbiAgfVxuXG4gIC8vIFRlbXBsYXRlIGlzIG9ubHkgY29tcGlsZWQgb24gZmlyc3QgdXNlIGFuZCBjYWNoZWQgYWZ0ZXIgdGhhdCBwb2ludC5cbiAgZnVuY3Rpb24gcmV0KGNvbnRleHQsIGV4ZWNPcHRpb25zKSB7XG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgY29tcGlsZWQgPSBjb21waWxlSW5wdXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBpbGVkLmNhbGwodGhpcywgY29udGV4dCwgZXhlY09wdGlvbnMpO1xuICB9XG4gIHJldC5fc2V0dXAgPSBmdW5jdGlvbihzZXR1cE9wdGlvbnMpIHtcbiAgICBpZiAoIWNvbXBpbGVkKSB7XG4gICAgICBjb21waWxlZCA9IGNvbXBpbGVJbnB1dCgpO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGlsZWQuX3NldHVwKHNldHVwT3B0aW9ucyk7XG4gIH07XG4gIHJldC5fY2hpbGQgPSBmdW5jdGlvbihpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgY29tcGlsZWQgPSBjb21waWxlSW5wdXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBpbGVkLl9jaGlsZChpLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgfTtcbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gYXJnRXF1YWxzKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChpc0FycmF5KGEpICYmIGlzQXJyYXkoYikgJiYgYS5sZW5ndGggPT09IGIubGVuZ3RoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIWFyZ0VxdWFscyhhW2ldLCBiW2ldKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybUxpdGVyYWxUb1BhdGgoc2V4cHIpIHtcbiAgaWYgKCFzZXhwci5wYXRoLnBhcnRzKSB7XG4gICAgbGV0IGxpdGVyYWwgPSBzZXhwci5wYXRoO1xuICAgIC8vIENhc3RpbmcgdG8gc3RyaW5nIGhlcmUgdG8gbWFrZSBmYWxzZSBhbmQgMCBsaXRlcmFsIHZhbHVlcyBwbGF5IG5pY2VseSB3aXRoIHRoZSByZXN0XG4gICAgLy8gb2YgdGhlIHN5c3RlbS5cbiAgICBzZXhwci5wYXRoID0ge1xuICAgICAgdHlwZTogJ1BhdGhFeHByZXNzaW9uJyxcbiAgICAgIGRhdGE6IGZhbHNlLFxuICAgICAgZGVwdGg6IDAsXG4gICAgICBwYXJ0czogW2xpdGVyYWwub3JpZ2luYWwgKyAnJ10sXG4gICAgICBvcmlnaW5hbDogbGl0ZXJhbC5vcmlnaW5hbCArICcnLFxuICAgICAgbG9jOiBsaXRlcmFsLmxvY1xuICAgIH07XG4gIH1cbn1cbiJdfQ== +; +define('handlebars/compiler/code-gen',['exports', 'module', '../utils'], function (exports, module, _utils) { + /* global define */ + 'use strict'; + + var SourceNode = undefined; + + try { + /* istanbul ignore next */ + if (typeof define !== 'function' || !define.amd) { + // We don't support this in AMD environments. For these environments, we asusme that + // they are running on the browser and thus have no need for the source-map library. + var SourceMap = require('source-map'); + SourceNode = SourceMap.SourceNode; + } + } catch (err) {} + /* NOP */ + + /* istanbul ignore if: tested but not covered in istanbul due to dist build */ + if (!SourceNode) { + SourceNode = function (line, column, srcFile, chunks) { + this.src = ''; + if (chunks) { + this.add(chunks); + } + }; + /* istanbul ignore next */ + SourceNode.prototype = { + add: function add(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src += chunks; + }, + prepend: function prepend(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src = chunks + this.src; + }, + toStringWithSourceMap: function toStringWithSourceMap() { + return { code: this.toString() }; + }, + toString: function toString() { + return this.src; + } + }; + } + + function castChunk(chunk, codeGen, loc) { + if (_utils.isArray(chunk)) { + var ret = []; + + for (var i = 0, len = chunk.length; i < len; i++) { + ret.push(codeGen.wrap(chunk[i], loc)); + } + return ret; + } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { + // Handle primitives that the SourceNode will throw up on + return chunk + ''; + } + return chunk; + } + + function CodeGen(srcFile) { + this.srcFile = srcFile; + this.source = []; + } + + CodeGen.prototype = { + isEmpty: function isEmpty() { + return !this.source.length; + }, + prepend: function prepend(source, loc) { + this.source.unshift(this.wrap(source, loc)); + }, + push: function push(source, loc) { + this.source.push(this.wrap(source, loc)); + }, + + merge: function merge() { + var source = this.empty(); + this.each(function (line) { + source.add([' ', line, '\n']); + }); + return source; + }, + + each: function each(iter) { + for (var i = 0, len = this.source.length; i < len; i++) { + iter(this.source[i]); + } + }, + + empty: function empty() { + var loc = this.currentLocation || { start: {} }; + return new SourceNode(loc.start.line, loc.start.column, this.srcFile); + }, + wrap: function wrap(chunk) { + var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1]; + + if (chunk instanceof SourceNode) { + return chunk; + } + + chunk = castChunk(chunk, this, loc); + + return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); + }, + + functionCall: function functionCall(fn, type, params) { + params = this.generateList(params); + return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); + }, + + quotedString: function quotedString(str) { + return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + objectLiteral: function objectLiteral(obj) { + var pairs = []; + + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var value = castChunk(obj[key], this); + if (value !== 'undefined') { + pairs.push([this.quotedString(key), ':', value]); + } + } + } + + var ret = this.generateList(pairs); + ret.prepend('{'); + ret.add('}'); + return ret; + }, + + generateList: function generateList(entries) { + var ret = this.empty(); + + for (var i = 0, len = entries.length; i < len; i++) { + if (i) { + ret.add(','); + } + + ret.add(castChunk(entries[i], this)); + } + + return ret; + }, + + generateArray: function generateArray(entries) { + var ret = this.generateList(entries); + ret.prepend('['); + ret.add(']'); + + return ret; + } + }; + + module.exports = CodeGen; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2NvZGUtZ2VuLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFHQSxNQUFJLFVBQVUsWUFBQSxDQUFDOztBQUVmLE1BQUk7O0FBRUYsUUFBSSxPQUFPLE1BQU0sS0FBSyxVQUFVLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFOzs7QUFHL0MsVUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3RDLGdCQUFVLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQztLQUNuQztHQUNGLENBQUMsT0FBTyxHQUFHLEVBQUUsRUFFYjs7OztBQUFBLEFBR0QsTUFBSSxDQUFDLFVBQVUsRUFBRTtBQUNmLGNBQVUsR0FBRyxVQUFTLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUNuRCxVQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNkLFVBQUksTUFBTSxFQUFFO0FBQ1YsWUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztPQUNsQjtLQUNGLENBQUM7O0FBRUYsY0FBVSxDQUFDLFNBQVMsR0FBRztBQUNyQixTQUFHLEVBQUUsYUFBUyxNQUFNLEVBQUU7QUFDcEIsWUFBSSxPQTNCRixPQUFPLENBMkJHLE1BQU0sQ0FBQyxFQUFFO0FBQ25CLGdCQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUMxQjtBQUNELFlBQUksQ0FBQyxHQUFHLElBQUksTUFBTSxDQUFDO09BQ3BCO0FBQ0QsYUFBTyxFQUFFLGlCQUFTLE1BQU0sRUFBRTtBQUN4QixZQUFJLE9BakNGLE9BQU8sQ0FpQ0csTUFBTSxDQUFDLEVBQUU7QUFDbkIsZ0JBQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQzFCO0FBQ0QsWUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFD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QUFZLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDckMsU0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqQixTQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztBQUViLGFBQU8sR0FBRyxDQUFDO0tBQ1o7R0FDRixDQUFDOzttQkFFYSxPQUFPIiwiZmlsZSI6ImNvZGUtZ2VuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZ2xvYmFsIGRlZmluZSAqL1xuaW1wb3J0IHtpc0FycmF5fSBmcm9tICcuLi91dGlscyc7XG5cbmxldCBTb3VyY2VOb2RlO1xuXG50cnkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAodHlwZW9mIGRlZmluZSAhPT0gJ2Z1bmN0aW9uJyB8fCAhZGVmaW5lLmFtZCkge1xuICAgIC8vIFdlIGRvbid0IHN1cHBvcnQgdGhpcyBpbiBBTUQgZW52aXJvbm1lbnRzLiBGb3IgdGhlc2UgZW52aXJvbm1lbnRzLCB3ZSBhc3VzbWUgdGhhdFxuICAgIC8vIHRoZXkgYXJlIHJ1bm5pbmcgb24gdGhlIGJyb3dzZXIgYW5kIHRodXMgaGF2ZSBubyBuZWVkIGZvciB0aGUgc291cmNlLW1hcCBsaWJyYXJ5LlxuICAgIGxldCBTb3VyY2VNYXAgPSByZXF1aXJlKCdzb3VyY2UtbWFwJyk7XG4gICAgU291cmNlTm9kZSA9IFNvdXJjZU1hcC5Tb3VyY2VOb2RlO1xuICB9XG59IGNhdGNoIChlcnIpIHtcbiAgLyogTk9QICovXG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBpZjogdGVzdGVkIGJ1dCBub3QgY292ZXJlZCBpbiBpc3RhbmJ1bCBkdWUgdG8gZGlzdCBidWlsZCAgKi9cbmlmICghU291cmNlTm9kZSkge1xuICBTb3VyY2VOb2RlID0gZnVuY3Rpb24obGluZSwgY29sdW1uLCBzcmNGaWxlLCBjaHVua3MpIHtcbiAgICB0aGlzLnNyYyA9ICcnO1xuICAgIGlmIChjaHVua3MpIHtcbiAgICAgIHRoaXMuYWRkKGNodW5rcyk7XG4gICAgfVxuICB9O1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBTb3VyY2VOb2RlLnByb3RvdHlwZSA9IHtcbiAgICBhZGQ6IGZ1bmN0aW9uKGNodW5rcykge1xuICAgICAgaWYgKGlzQXJyYXkoY2h1bmtzKSkge1xuICAgICAgICBjaHVua3MgPSBjaHVua3Muam9pbignJyk7XG4gICAgICB9XG4gICAgICB0aGlzLnNyYyArPSBjaHVua3M7XG4gICAgfSxcbiAgICBwcmVwZW5kOiBmdW5jdGlvbihjaHVua3MpIHtcbiAgICAgIGlmIChpc0FycmF5KGNodW5rcykpIHtcbiAgICAgICAgY2h1bmtzID0gY2h1bmtzLmpvaW4oJycpO1xuICAgICAgfVxuICAgICAgdGhpcy5zcmMgPSBjaHVua3MgKyB0aGlzLnNyYztcbiAgICB9LFxuICAgIHRvU3RyaW5nV2l0aFNvdXJjZU1hcDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4ge2NvZGU6IHRoaXMudG9TdHJpbmcoKX07XG4gICAgfSxcbiAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5zcmM7XG4gICAgfVxuICB9O1xufVxuXG5cbmZ1bmN0aW9uIGNhc3RDaHVuayhjaHVuaywgY29kZUdlbiwgbG9jKSB7XG4gIGlmIChpc0FycmF5KGNodW5rKSkge1xuICAgIGxldCByZXQgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBjaHVuay5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgcmV0LnB1c2goY29kZUdlbi53cmFwKGNodW5rW2ldLCBsb2MpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY2h1bmsgPT09ICdib29sZWFuJyB8fCB0eXBlb2YgY2h1bmsgPT09ICdudW1iZXInKSB7XG4gICAgLy8gSGFuZGxlIHByaW1pdGl2ZXMgdGhhdCB0aGUgU291cmNlTm9kZSB3aWxsIHRocm93IHVwIG9uXG4gICAgcmV0dXJuIGNodW5rICsgJyc7XG4gIH1cbiAgcmV0dXJuIGNodW5rO1xufVxuXG5cbmZ1bmN0aW9uIENvZGVHZW4oc3JjRmlsZSkge1xuICB0aGlzLnNyY0ZpbGUgPSBzcmNGaWxlO1xuICB0aGlzLnNvdXJjZSA9IFtdO1xufVxuXG5Db2RlR2VuLnByb3RvdHlwZSA9IHtcbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gIXRoaXMuc291cmNlLmxlbmd0aDtcbiAgfSxcbiAgcHJlcGVuZDogZnVuY3Rpb24oc291cmNlLCBsb2MpIHtcbiAgICB0aGlzLnNvdXJjZS51bnNoaWZ0KHRoaXMud3JhcChzb3VyY2UsIGxvYykpO1xuICB9LFxuICBwdXNoOiBmdW5jdGlvbihzb3VyY2UsIGxvYykge1xuICAgIHRoaXMuc291cmNlLnB1c2godGhpcy53cmFwKHNvdXJjZSwgbG9jKSk7XG4gIH0sXG5cbiAgbWVyZ2U6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBzb3VyY2UgPSB0aGlzLmVtcHR5KCk7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIHNvdXJjZS5hZGQoWycgICcsIGxpbmUsICdcXG4nXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHNvdXJjZTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbihpdGVyKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRoaXMuc291cmNlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpdGVyKHRoaXMuc291cmNlW2ldKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBsb2MgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbiB8fCB7c3RhcnQ6IHt9fTtcbiAgICByZXR1cm4gbmV3IFNvdXJjZU5vZGUobG9jLnN0YXJ0LmxpbmUsIGxvYy5zdGFydC5jb2x1bW4sIHRoaXMuc3JjRmlsZSk7XG4gIH0sXG4gIHdyYXA6IGZ1bmN0aW9uKGNodW5rLCBsb2MgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbiB8fCB7c3RhcnQ6IHt9fSkge1xuICAgIGlmIChjaHVuayBpbnN0YW5jZW9mIFNvdXJjZU5vZGUpIHtcbiAgICAgIHJldHVybiBjaHVuaztcbiAgICB9XG5cbiAgICBjaHVuayA9IGNhc3RDaHVuayhjaHVuaywgdGhpcywgbG9jKTtcblxuICAgIHJldHVybiBuZXcgU291cmNlTm9kZShsb2Muc3RhcnQubGluZSwgbG9jLnN0YXJ0LmNvbHVtbiwgdGhpcy5zcmNGaWxlLCBjaHVuayk7XG4gIH0sXG5cbiAgZnVuY3Rpb25DYWxsOiBmdW5jdGlvbihmbiwgdHlwZSwgcGFyYW1zKSB7XG4gICAgcGFyYW1zID0gdGhpcy5nZW5lcmF0ZUxpc3QocGFyYW1zKTtcbiAgICByZXR1cm4gdGhpcy53cmFwKFtmbiwgdHlwZSA/ICcuJyArIHR5cGUgKyAnKCcgOiAnKCcsIHBhcmFtcywgJyknXSk7XG4gIH0sXG5cbiAgcXVvdGVkU3RyaW5nOiBmdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gJ1wiJyArIChzdHIgKyAnJylcbiAgICAgIC5yZXBsYWNlKC9cXFxcL2csICdcXFxcXFxcXCcpXG4gICAgICAucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpXG4gICAgICAucmVwbGFjZSgvXFxuL2csICdcXFxcbicpXG4gICAgICAucmVwbGFjZSgvXFxyL2csICdcXFxccicpXG4gICAgICAucmVwbGFjZSgvXFx1MjAyOC9nLCAnXFxcXHUyMDI4JykgICAvLyBQZXIgRWNtYS0yNjIgNy4zICsgNy44LjRcbiAgICAgIC5yZXBsYWNlKC9cXHUyMDI5L2csICdcXFxcdTIwMjknKSArICdcIic7XG4gIH0sXG5cbiAgb2JqZWN0TGl0ZXJhbDogZnVuY3Rpb24ob2JqKSB7XG4gICAgbGV0IHBhaXJzID0gW107XG5cbiAgICBmb3IgKGxldCBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgbGV0IHZhbHVlID0gY2FzdENodW5rKG9ialtrZXldLCB0aGlzKTtcbiAgICAgICAgaWYgKHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHBhaXJzLnB1c2goW3RoaXMucXVvdGVkU3RyaW5nKGtleSksICc6JywgdmFsdWVdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGxldCByZXQgPSB0aGlzLmdlbmVyYXRlTGlzdChwYWlycyk7XG4gICAgcmV0LnByZXBlbmQoJ3snKTtcbiAgICByZXQuYWRkKCd9Jyk7XG4gICAgcmV0dXJuIHJldDtcbiAgfSxcblxuXG4gIGdlbmVyYXRlTGlzdDogZnVuY3Rpb24oZW50cmllcykge1xuICAgIGxldCByZXQgPSB0aGlzLmVtcHR5KCk7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gZW50cmllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgaWYgKGkpIHtcbiAgICAgICAgcmV0LmFkZCgnLCcpO1xuICAgICAgfVxuXG4gICAgICByZXQuYWRkKGNhc3RDaHVuayhlbnRyaWVzW2ldLCB0aGlzKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfSxcblxuICBnZW5lcmF0ZUFycmF5OiBmdW5jdGlvbihlbnRyaWVzKSB7XG4gICAgbGV0IHJldCA9IHRoaXMuZ2VuZXJhdGVMaXN0KGVudHJpZXMpO1xuICAgIHJldC5wcmVwZW5kKCdbJyk7XG4gICAgcmV0LmFkZCgnXScpO1xuXG4gICAgcmV0dXJuIHJldDtcbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgQ29kZUdlbjtcblxuIl19 +; +define('handlebars/compiler/javascript-compiler',['exports', 'module', '../base', '../exception', '../utils', './code-gen'], function (exports, module, _base, _exception, _utils, _codeGen) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _CodeGen = _interopRequireDefault(_codeGen); + + function Literal(value) { + this.value = value; + } + + function JavaScriptCompiler() {} + + JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function nameLookup(parent, name /* , type*/) { + if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + return [parent, '.', name]; + } else { + return [parent, '[', JSON.stringify(name), ']']; + } + }, + depthedLookup: function depthedLookup(name) { + return [this.aliasable('container.lookup'), '(depths, "', name, '")']; + }, + + compilerInfo: function compilerInfo() { + var revision = _base.COMPILER_REVISION, + versions = _base.REVISION_CHANGES[revision]; + return [revision, versions]; + }, + + appendToBuffer: function appendToBuffer(source, location, explicit) { + // Force a source as this simplifies the merge logic. + if (!_utils.isArray(source)) { + source = [source]; + } + source = this.source.wrap(source, location); + + if (this.environment.isSimple) { + return ['return ', source, ';']; + } else if (explicit) { + // This is a case where the buffer operation occurs as a child of another + // construct, generally braces. We have to explicitly output these buffer + // operations to ensure that the emitted code goes in the correct location. + return ['buffer += ', source, ';']; + } else { + source.appendToBuffer = true; + return source; + } + }, + + initializeBuffer: function initializeBuffer() { + return this.quotedString(''); + }, + // END PUBLIC API + + compile: function compile(environment, options, context, asObject) { + this.environment = environment; + this.options = options; + this.stringParams = this.options.stringParams; + this.trackIds = this.options.trackIds; + this.precompile = !asObject; + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + decorators: [], + programs: [], + environments: [] + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.aliases = {}; + this.registers = { list: [] }; + this.hashes = []; + this.compileStack = []; + this.inlineStack = []; + this.blockParams = []; + + this.compileChildren(environment, options); + + this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; + this.useBlockParams = this.useBlockParams || environment.useBlockParams; + + var opcodes = environment.opcodes, + opcode = undefined, + firstLoc = undefined, + i = undefined, + l = undefined; + + for (i = 0, l = opcodes.length; i < l; i++) { + opcode = opcodes[i]; + + this.source.currentLocation = opcode.loc; + firstLoc = firstLoc || opcode.loc; + this[opcode.opcode].apply(this, opcode.args); + } + + // Flush any trailing content that might be pending. + this.source.currentLocation = firstLoc; + this.pushSource(''); + + /* istanbul ignore next */ + if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { + throw new _Exception['default']('Compile completed with content left on stack'); + } + + if (!this.decorators.isEmpty()) { + this.useDecorators = true; + + this.decorators.prepend('var decorators = container.decorators;\n'); + this.decorators.push('return fn;'); + + if (asObject) { + this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); + } else { + this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); + this.decorators.push('}\n'); + this.decorators = this.decorators.merge(); + } + } else { + this.decorators = undefined; + } + + var fn = this.createFunctionContext(asObject); + if (!this.isChild) { + var ret = { + compiler: this.compilerInfo(), + main: fn + }; + + if (this.decorators) { + ret.main_d = this.decorators; // eslint-disable-line camelcase + ret.useDecorators = true; + } + + var _context = this.context; + var programs = _context.programs; + var decorators = _context.decorators; + + for (i = 0, l = programs.length; i < l; i++) { + if (programs[i]) { + ret[i] = programs[i]; + if (decorators[i]) { + ret[i + '_d'] = decorators[i]; + ret.useDecorators = true; + } + } + } + + if (this.environment.usePartial) { + ret.usePartial = true; + } + if (this.options.data) { + ret.useData = true; + } + if (this.useDepths) { + ret.useDepths = true; + } + if (this.useBlockParams) { + ret.useBlockParams = true; + } + if (this.options.compat) { + ret.compat = true; + } + + if (!asObject) { + ret.compiler = JSON.stringify(ret.compiler); + + this.source.currentLocation = { start: { line: 1, column: 0 } }; + ret = this.objectLiteral(ret); + + if (options.srcName) { + ret = ret.toStringWithSourceMap({ file: options.destName }); + ret.map = ret.map && ret.map.toString(); + } else { + ret = ret.toString(); + } + } else { + ret.compilerOptions = this.options; + } + + return ret; + } else { + return fn; + } + }, + + preamble: function preamble() { + // track the last context pushed into place to allow skipping the + // getContext opcode when it would be a noop + this.lastContext = 0; + this.source = new _CodeGen['default'](this.options.srcName); + this.decorators = new _CodeGen['default'](this.options.srcName); + }, + + createFunctionContext: function createFunctionContext(asObject) { + var varDeclarations = ''; + + var locals = this.stackVars.concat(this.registers.list); + if (locals.length > 0) { + varDeclarations += ', ' + locals.join(', '); + } + + // Generate minimizer alias mappings + // + // When using true SourceNodes, this will update all references to the given alias + // as the source nodes are reused in situ. For the non-source node compilation mode, + // aliases will not be used, but this case is already being run on the client and + // we aren't concern about minimizing the template size. + var aliasCount = 0; + for (var alias in this.aliases) { + // eslint-disable-line guard-for-in + var node = this.aliases[alias]; + + if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { + varDeclarations += ', alias' + ++aliasCount + '=' + alias; + node.children[0] = 'alias' + aliasCount; + } + } + + var params = ['container', 'depth0', 'helpers', 'partials', 'data']; + + if (this.useBlockParams || this.useDepths) { + params.push('blockParams'); + } + if (this.useDepths) { + params.push('depths'); + } + + // Perform a second pass over the output to merge content when possible + var source = this.mergeSource(varDeclarations); + + if (asObject) { + params.push(source); + + return Function.apply(this, params); + } else { + return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); + } + }, + mergeSource: function mergeSource(varDeclarations) { + var isSimple = this.environment.isSimple, + appendOnly = !this.forceBuffer, + appendFirst = undefined, + sourceSeen = undefined, + bufferStart = undefined, + bufferEnd = undefined; + this.source.each(function (line) { + if (line.appendToBuffer) { + if (bufferStart) { + line.prepend(' + '); + } else { + bufferStart = line; + } + bufferEnd = line; + } else { + if (bufferStart) { + if (!sourceSeen) { + appendFirst = true; + } else { + bufferStart.prepend('buffer += '); + } + bufferEnd.add(';'); + bufferStart = bufferEnd = undefined; + } + + sourceSeen = true; + if (!isSimple) { + appendOnly = false; + } + } + }); + + if (appendOnly) { + if (bufferStart) { + bufferStart.prepend('return '); + bufferEnd.add(';'); + } else if (!sourceSeen) { + this.source.push('return "";'); + } + } else { + varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); + + if (bufferStart) { + bufferStart.prepend('return buffer + '); + bufferEnd.add(';'); + } else { + this.source.push('return buffer;'); + } + } + + if (varDeclarations) { + this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); + } + + return this.source.merge(); + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function blockValue(name) { + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs(name, 0, params); + + var blockName = this.popStack(); + params.splice(1, 0, blockName); + + this.push(this.source.functionCall(blockHelperMissing, 'call', params)); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function ambiguousBlockValue() { + // We're being a bit cheeky and reusing the options value from the prior exec + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs('', 0, params, true); + + this.flushInline(); + + var current = this.topStack(); + params.splice(1, 0, current); + + this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function appendContent(content) { + if (this.pendingContent) { + content = this.pendingContent + content; + } else { + this.pendingLocation = this.source.currentLocation; + } + + this.pendingContent = content; + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function append() { + if (this.isInline()) { + this.replaceStack(function (current) { + return [' != null ? ', current, ' : ""']; + }); + + this.pushSource(this.appendToBuffer(this.popStack())); + } else { + var local = this.popStack(); + this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); + if (this.environment.isSimple) { + this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); + } + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function appendEscaped() { + this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function getContext(depth) { + this.lastContext = depth; + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function pushContext() { + this.pushStackLiteral(this.contextName(this.lastContext)); + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) { + var i = 0; + + if (!scoped && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.push(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); + } + + this.resolvePath('context', parts, i, falsy, strict); + }, + + // [lookupBlockParam] + // + // On stack, before: ... + // On stack, after: blockParam[name], ... + // + // Looks up the value of `parts` on the given block param and pushes + // it onto the stack. + lookupBlockParam: function lookupBlockParam(blockParamId, parts) { + this.useBlockParams = true; + + this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); + this.resolvePath('context', parts, 1); + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data, ... + // + // Push the data lookup operator + lookupData: function lookupData(depth, parts, strict) { + if (!depth) { + this.pushStackLiteral('data'); + } else { + this.pushStackLiteral('container.data(data, ' + depth + ')'); + } + + this.resolvePath('data', parts, 0, true, strict); + }, + + resolvePath: function resolvePath(type, parts, i, falsy, strict) { + // istanbul ignore next + + var _this = this; + + if (this.options.strict || this.options.assumeObjects) { + this.push(strictLookup(this.options.strict && strict, this, parts, type)); + return; + } + + var len = parts.length; + for (; i < len; i++) { + /* eslint-disable no-loop-func */ + this.replaceStack(function (current) { + var lookup = _this.nameLookup(current, parts[i], type); + // We want to ensure that zero and false are handled properly if the context (falsy flag) + // needs to have the special handling for these values. + if (!falsy) { + return [' != null ? ', lookup, ' : ', current]; + } else { + // Otherwise we can use generic falsy handling + return [' && ', lookup]; + } + }); + /* eslint-enable no-loop-func */ + } + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function resolvePossibleLambda() { + this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function pushStringParam(string, type) { + this.pushContext(); + this.pushString(type); + + // If it's a subexpression, the string result + // will be pushed after this opcode. + if (type !== 'SubExpression') { + if (typeof string === 'string') { + this.pushString(string); + } else { + this.pushStackLiteral(string); + } + } + }, + + emptyHash: function emptyHash(omitEmpty) { + if (this.trackIds) { + this.push('{}'); // hashIds + } + if (this.stringParams) { + this.push('{}'); // hashContexts + this.push('{}'); // hashTypes + } + this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); + }, + pushHash: function pushHash() { + if (this.hash) { + this.hashes.push(this.hash); + } + this.hash = { values: [], types: [], contexts: [], ids: [] }; + }, + popHash: function popHash() { + var hash = this.hash; + this.hash = this.hashes.pop(); + + if (this.trackIds) { + this.push(this.objectLiteral(hash.ids)); + } + if (this.stringParams) { + this.push(this.objectLiteral(hash.contexts)); + this.push(this.objectLiteral(hash.types)); + } + + this.push(this.objectLiteral(hash.values)); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function pushString(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function pushLiteral(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function pushProgram(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [registerDecorator] + // + // On stack, before: hash, program, params..., ... + // On stack, after: ... + // + // Pops off the decorator's parameters, invokes the decorator, + // and inserts the decorator into the decorators list. + registerDecorator: function registerDecorator(paramSize, name) { + var foundDecorator = this.nameLookup('decorators', name, 'decorator'), + options = this.setupHelperArgs(name, paramSize); + + this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']); + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function invokeHelper(paramSize, name, isSimple) { + var nonHelper = this.popStack(), + helper = this.setupHelper(paramSize, name), + simple = isSimple ? [helper.name, ' || '] : ''; + + var lookup = ['('].concat(simple, nonHelper); + if (!this.options.strict) { + lookup.push(' || ', this.aliasable('helpers.helperMissing')); + } + lookup.push(')'); + + this.push(this.source.functionCall(lookup, 'call', helper.callParams)); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function invokeKnownHelper(paramSize, name) { + var helper = this.setupHelper(paramSize, name); + this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function invokeAmbiguous(name, helperCall) { + this.useRegister('helper'); + + var nonHelper = this.popStack(); + + this.emptyHash(); + var helper = this.setupHelper(0, name, helperCall); + + var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + + var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; + if (!this.options.strict) { + lookup[0] = '(helper = '; + lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing')); + } + + this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function invokePartial(isDynamic, name, indent) { + var params = [], + options = this.setupParams(name, 1, params); + + if (isDynamic) { + name = this.popStack(); + delete options.name; + } + + if (indent) { + options.indent = JSON.stringify(indent); + } + options.helpers = 'helpers'; + options.partials = 'partials'; + options.decorators = 'container.decorators'; + + if (!isDynamic) { + params.unshift(this.nameLookup('partials', name, 'partial')); + } else { + params.unshift(name); + } + + if (this.options.compat) { + options.depths = 'depths'; + } + options = this.objectLiteral(options); + params.push(options); + + this.push(this.source.functionCall('container.invokePartial', '', params)); + }, + + // [assignToHash] + // + // On stack, before: value, ..., hash, ... + // On stack, after: ..., hash, ... + // + // Pops a value off the stack and assigns it to the current hash + assignToHash: function assignToHash(key) { + var value = this.popStack(), + context = undefined, + type = undefined, + id = undefined; + + if (this.trackIds) { + id = this.popStack(); + } + if (this.stringParams) { + type = this.popStack(); + context = this.popStack(); + } + + var hash = this.hash; + if (context) { + hash.contexts[key] = context; + } + if (type) { + hash.types[key] = type; + } + if (id) { + hash.ids[key] = id; + } + hash.values[key] = value; + }, + + pushId: function pushId(type, name, child) { + if (type === 'BlockParam') { + this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : '')); + } else if (type === 'PathExpression') { + this.pushString(name); + } else if (type === 'SubExpression') { + this.pushStackLiteral('true'); + } else { + this.pushStackLiteral('null'); + } + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function compileChildren(environment, options) { + var children = environment.children, + child = undefined, + compiler = undefined; + + for (var i = 0, l = children.length; i < l; i++) { + child = children[i]; + compiler = new this.compiler(); // eslint-disable-line new-cap + + var existing = this.matchExistingProgram(child); + + if (existing == null) { + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + var index = this.context.programs.length; + child.index = index; + child.name = 'program' + index; + this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); + this.context.decorators[index] = compiler.decorators; + this.context.environments[index] = child; + + this.useDepths = this.useDepths || compiler.useDepths; + this.useBlockParams = this.useBlockParams || compiler.useBlockParams; + child.useDepths = this.useDepths; + child.useBlockParams = this.useBlockParams; + } else { + child.index = existing.index; + child.name = 'program' + existing.index; + + this.useDepths = this.useDepths || existing.useDepths; + this.useBlockParams = this.useBlockParams || existing.useBlockParams; + } + } + }, + matchExistingProgram: function matchExistingProgram(child) { + for (var i = 0, len = this.context.environments.length; i < len; i++) { + var environment = this.context.environments[i]; + if (environment && environment.equals(child)) { + return environment; + } + } + }, + + programExpression: function programExpression(guid) { + var child = this.environment.children[guid], + programParams = [child.index, 'data', child.blockParams]; + + if (this.useBlockParams || this.useDepths) { + programParams.push('blockParams'); + } + if (this.useDepths) { + programParams.push('depths'); + } + + return 'container.program(' + programParams.join(', ') + ')'; + }, + + useRegister: function useRegister(name) { + if (!this.registers[name]) { + this.registers[name] = true; + this.registers.list.push(name); + } + }, + + push: function push(expr) { + if (!(expr instanceof Literal)) { + expr = this.source.wrap(expr); + } + + this.inlineStack.push(expr); + return expr; + }, + + pushStackLiteral: function pushStackLiteral(item) { + this.push(new Literal(item)); + }, + + pushSource: function pushSource(source) { + if (this.pendingContent) { + this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); + this.pendingContent = undefined; + } + + if (source) { + this.source.push(source); + } + }, + + replaceStack: function replaceStack(callback) { + var prefix = ['('], + stack = undefined, + createdStack = undefined, + usedLiteral = undefined; + + /* istanbul ignore next */ + if (!this.isInline()) { + throw new _Exception['default']('replaceStack on non-inline'); + } + + // We want to merge the inline statement into the replacement statement via ',' + var top = this.popStack(true); + + if (top instanceof Literal) { + // Literals do not need to be inlined + stack = [top.value]; + prefix = ['(', stack]; + usedLiteral = true; + } else { + // Get or create the current stack name for use by the inline + createdStack = true; + var _name = this.incrStack(); + + prefix = ['((', this.push(_name), ' = ', top, ')']; + stack = this.topStack(); + } + + var item = callback.call(this, stack); + + if (!usedLiteral) { + this.popStack(); + } + if (createdStack) { + this.stackSlot--; + } + this.push(prefix.concat(item, ')')); + }, + + incrStack: function incrStack() { + this.stackSlot++; + if (this.stackSlot > this.stackVars.length) { + this.stackVars.push('stack' + this.stackSlot); + } + return this.topStackName(); + }, + topStackName: function topStackName() { + return 'stack' + this.stackSlot; + }, + flushInline: function flushInline() { + var inlineStack = this.inlineStack; + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + /* istanbul ignore if */ + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + var stack = this.incrStack(); + this.pushSource([stack, ' = ', entry, ';']); + this.compileStack.push(stack); + } + } + }, + isInline: function isInline() { + return this.inlineStack.length; + }, + + popStack: function popStack(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && item instanceof Literal) { + return item.value; + } else { + if (!inline) { + /* istanbul ignore next */ + if (!this.stackSlot) { + throw new _Exception['default']('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function topStack() { + var stack = this.isInline() ? this.inlineStack : this.compileStack, + item = stack[stack.length - 1]; + + /* istanbul ignore if */ + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + contextName: function contextName(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + + quotedString: function quotedString(str) { + return this.source.quotedString(str); + }, + + objectLiteral: function objectLiteral(obj) { + return this.source.objectLiteral(obj); + }, + + aliasable: function aliasable(name) { + var ret = this.aliases[name]; + if (ret) { + ret.referenceCount++; + return ret; + } + + ret = this.aliases[name] = this.source.wrap(name); + ret.aliasable = true; + ret.referenceCount = 1; + + return ret; + }, + + setupHelper: function setupHelper(paramSize, name, blockHelper) { + var params = [], + paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); + var foundHelper = this.nameLookup('helpers', name, 'helper'), + callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : {}'); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: [callContext].concat(params) + }; + }, + + setupParams: function setupParams(helper, paramSize, params) { + var options = {}, + contexts = [], + types = [], + ids = [], + objectArgs = !params, + param = undefined; + + if (objectArgs) { + params = []; + } + + options.name = this.quotedString(helper); + options.hash = this.popStack(); + + if (this.trackIds) { + options.hashIds = this.popStack(); + } + if (this.stringParams) { + options.hashTypes = this.popStack(); + options.hashContexts = this.popStack(); + } + + var inverse = this.popStack(), + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + options.fn = program || 'container.noop'; + options.inverse = inverse || 'container.noop'; + } + + // The parameters go on to the stack in order (making sure that they are evaluated in order) + // so we need to pop them off the stack in reverse order + var i = paramSize; + while (i--) { + param = this.popStack(); + params[i] = param; + + if (this.trackIds) { + ids[i] = this.popStack(); + } + if (this.stringParams) { + types[i] = this.popStack(); + contexts[i] = this.popStack(); + } + } + + if (objectArgs) { + options.args = this.source.generateArray(params); + } + + if (this.trackIds) { + options.ids = this.source.generateArray(ids); + } + if (this.stringParams) { + options.types = this.source.generateArray(types); + options.contexts = this.source.generateArray(contexts); + } + + if (this.options.data) { + options.data = 'data'; + } + if (this.useBlockParams) { + options.blockParams = 'blockParams'; + } + return options; + }, + + setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) { + var options = this.setupParams(helper, paramSize, params); + options = this.objectLiteral(options); + if (useRegister) { + this.useRegister('options'); + params.push('options'); + return ['options=', options]; + } else if (params) { + params.push(options); + return ''; + } else { + return options; + } + } + }; + + (function () { + var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' '); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for (var i = 0, l = reservedWords.length; i < l; i++) { + compilerWords[reservedWords[i]] = true; + } + })(); + + JavaScriptCompiler.isValidJavaScriptVariableName = function (name) { + return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); + }; + + function strictLookup(requireTerminal, compiler, parts, type) { + var stack = compiler.popStack(), + i = 0, + len = parts.length; + if (requireTerminal) { + len--; + } + + for (; i < len; i++) { + stack = compiler.nameLookup(stack, parts[i], type); + } + + if (requireTerminal) { + return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')']; + } else { + return stack; + } + } + + module.exports = JavaScriptCompiler; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2NvbXBpbGVyL2phdmFzY3JpcHQtY29tcGlsZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFLQSxXQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUU7QUFDdEIsUUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7R0FDcEI7O0FBRUQsV0FBUyxrQkFBa0IsR0FBRyxFQUFFOztBQUVoQyxvQkFBa0IsQ0FBQyxTQUFTLEdBQUc7OztBQUc3QixjQUFVLEVBQUUsb0JBQVMsTUFBTSxFQUFFLElBQUksY0FBYTtBQUM1QyxVQUFJLGtCQUFrQixDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxFQUFFO0FBQzFELGVBQU8sQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO09BQzVCLE1BQU07QUFDTCxlQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO09BQ2pEO0tBQ0Y7QUFDRCxpQkFBYSxFQUFFLHVCQUFTLElBQUksRUFBRTtBQUM1QixhQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdkU7O0FBRUQsZ0JBQVksRUFBRSx3QkFBVztBQUN2QixVQUFNLFFBQVEsU0ExQlQsaUJBQWlCLEFBMEJZO1VBQzVCLFFBQVEsR0FBRyxNQTNCTyxnQkFBZ0IsQ0EyQk4sUUFBUSxDQUFDLENBQUM7QUFDNUMsYUFBTyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztLQUM3Qjs7QUFFRCxrQkFBYyxFQUFFLHdCQUFTLE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFOztBQUVuRCxVQUFJLENBQUMsT0EvQkQsT0FBTyxDQStCRSxNQUFNLENBQUMsRUFBRTtBQUNwQixjQUFNLEdBQUcs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LENBQUM7UUFDTCxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztBQUN2QixRQUFJLGVBQWUsRUFBRTtBQUNuQixTQUFHLEVBQUUsQ0FBQztLQUNQOztBQUVELFdBQU8sQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUNuQixXQUFLLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3BEOztBQUVELFFBQUksZUFBZSxFQUFFO0FBQ25CLGFBQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztLQUN6RyxNQUFNO0FBQ0wsYUFBTyxLQUFLLENBQUM7S0FDZDtHQUNGOzttQkFFYyxrQkFBa0IiLCJmaWxlIjoiamF2YXNjcmlwdC1jb21waWxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENPTVBJTEVSX1JFVklTSU9OLCBSRVZJU0lPTl9DSEFOR0VTIH0gZnJvbSAnLi4vYmFzZSc7XG5pbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5pbXBvcnQge2lzQXJyYXl9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCBDb2RlR2VuIGZyb20gJy4vY29kZS1nZW4nO1xuXG5mdW5jdGlvbiBMaXRlcmFsKHZhbHVlKSB7XG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gSmF2YVNjcmlwdENvbXBpbGVyKCkge31cblxuSmF2YVNjcmlwdENvbXBpbGVyLnByb3RvdHlwZSA9IHtcbiAgLy8gUFVCTElDIEFQSTogWW91IGNhbiBvdmVycmlkZSB0aGVzZSBtZXRob2RzIGluIGEgc3ViY2xhc3MgdG8gcHJvdmlkZVxuICAvLyBhbHRlcm5hdGl2ZSBjb21waWxlZCBmb3JtcyBmb3IgbmFtZSBsb29rdXAgYW5kIGJ1ZmZlcmluZyBzZW1hbnRpY3NcbiAgbmFtZUxvb2t1cDogZnVuY3Rpb24ocGFyZW50LCBuYW1lLyogLCB0eXBlKi8pIHtcbiAgICBpZiAoSmF2YVNjcmlwdENvbXBpbGVyLmlzVmFsaWRKYXZhU2NyaXB0VmFyaWFibGVOYW1lKG5hbWUpKSB7XG4gICAgICByZXR1cm4gW3BhcmVudCwgJy4nLCBuYW1lXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtwYXJlbnQsICdbJywgSlNPTi5zdHJpbmdpZnkobmFtZSksICddJ107XG4gICAgfVxuICB9LFxuICBkZXB0aGVkTG9va3VwOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIFt0aGlzLmFsaWFzYWJsZSgnY29udGFpbmVyLmxvb2t1cCcpLCAnKGRlcHRocywgXCInLCBuYW1lLCAnXCIpJ107XG4gIH0sXG5cbiAgY29tcGlsZXJJbmZvOiBmdW5jdGlvbigpIHtcbiAgICBjb25zdCByZXZpc2lvbiA9IENPTVBJTEVSX1JFVklTSU9OLFxuICAgICAgICAgIHZlcnNpb25zID0gUkVWSVNJT05fQ0hBTkdFU1tyZXZpc2lvbl07XG4gICAgcmV0dXJuIFtyZXZpc2lvbiwgdmVyc2lvbnNdO1xuICB9LFxuXG4gIGFwcGVuZFRvQnVmZmVyOiBmdW5jdGlvbihzb3VyY2UsIGxvY2F0aW9uLCBleHBsaWNpdCkge1xuICAgIC8vIEZvcmNlIGEgc291cmNlIGFzIHRoaXMgc2ltcGxpZmllcyB0aGUgbWVyZ2UgbG9naWMuXG4gICAgaWYgKCFpc0FycmF5KHNvdXJjZSkpIHtcbiAgICAgIHNvdXJjZSA9IFtzb3VyY2VdO1xuICAgIH1cbiAgICBzb3VyY2UgPSB0aGlzLnNvdXJjZS53cmFwKHNvdXJjZSwgbG9jYXRpb24pO1xuXG4gICAgaWYgKHRoaXMuZW52aXJvbm1lbnQuaXNTaW1wbGUpIHtcbiAgICAgIHJldHVybiBbJ3JldHVybiAnLCBzb3VyY2UsICc7J107XG4gICAgfSBlbHNlIGlmIChleHBsaWNpdCkge1xuICAgICAgLy8gVGhpcyBpcyBhIGNhc2Ugd2hlcmUgdGhlIGJ1ZmZlciBvcGVyYXRpb24gb2NjdXJzIGFzIGEgY2hpbGQgb2YgYW5vdGhlclxuICAgICAgLy8gY29uc3RydWN0LCBnZW5lcmFsbHkgYnJhY2VzLiBXZSBoYXZlIHRvIGV4cGxpY2l0bHkgb3V0cHV0IHRoZXNlIGJ1ZmZlclxuICAgICAgLy8gb3BlcmF0aW9ucyB0byBlbnN1cmUgdGhhdCB0aGUgZW1pdHRlZCBjb2RlIGdvZXMgaW4gdGhlIGNvcnJlY3QgbG9jYXRpb24uXG4gICAgICByZXR1cm4gWydidWZmZXIgKz0gJywgc291cmNlLCAnOyddO1xuICAgIH0gZWxzZSB7XG4gICAgICBzb3VyY2UuYXBwZW5kVG9CdWZmZXIgPSB0cnVlO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG4gIH0sXG5cbiAgaW5pdGlhbGl6ZUJ1ZmZlcjogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucXVvdGVkU3RyaW5nKCcnKTtcbiAgfSxcbiAgLy8gRU5EIFBVQkxJQyBBUElcblxuICBjb21waWxlOiBmdW5jdGlvbihlbnZpcm9ubWVudCwgb3B0aW9ucywgY29udGV4dCwgYXNPYmplY3QpIHtcbiAgICB0aGlzLmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLnN0cmluZ1BhcmFtcyA9IHRoaXMub3B0aW9ucy5zdHJpbmdQYXJhbXM7XG4gICAgdGhpcy50cmFja0lkcyA9IHRoaXMub3B0aW9ucy50cmFja0lkcztcbiAgICB0aGlzLnByZWNvbXBpbGUgPSAhYXNPYmplY3Q7XG5cbiAgICB0aGlzLm5hbWUgPSB0aGlzLmVudmlyb25tZW50Lm5hbWU7XG4gICAgdGhpcy5pc0NoaWxkID0gISFjb250ZXh0O1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQgfHwge1xuICAgICAgZGVjb3JhdG9yczogW10sXG4gICAgICBwcm9ncmFtczogW10sXG4gICAgICBlbnZpcm9ubWVudHM6IFtdXG4gICAgfTtcblxuICAgIHRoaXMucHJlYW1ibGUoKTtcblxuICAgIHRoaXMuc3RhY2tTbG90ID0gMDtcbiAgICB0aGlzLnN0YWNrVmFycyA9IFtdO1xuICAgIHRoaXMuYWxpYXNlcyA9IHt9O1xuICAgIHRoaXMucmVnaXN0ZXJzID0geyBsaXN0OiBbXSB9O1xuICAgIHRoaXMuaGFzaGVzID0gW107XG4gICAgdGhpcy5jb21waWxlU3RhY2sgPSBbXTtcbiAgICB0aGlzLmlubGluZVN0YWNrID0gW107XG4gICAgdGhpcy5ibG9ja1BhcmFtcyA9IFtdO1xuXG4gICAgdGhpcy5jb21waWxlQ2hpbGRyZW4oZW52aXJvbm1lbnQsIG9wdGlvbnMpO1xuXG4gICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCBlbnZpcm9ubWVudC51c2VEZXB0aHMgfHwgZW52aXJvbm1lbnQudXNlRGVjb3JhdG9ycyB8fCB0aGlzLm9wdGlvbnMuY29tcGF0O1xuICAgIHRoaXMudXNlQmxvY2tQYXJhbXMgPSB0aGlzLnVzZUJsb2NrUGFyYW1zIHx8IGVudmlyb25tZW50LnVzZUJsb2NrUGFyYW1zO1xuXG4gICAgbGV0IG9wY29kZXMgPSBlbnZpcm9ubWVudC5vcGNvZGVzLFxuICAgICAgICBvcGNvZGUsXG4gICAgICAgIGZpcnN0TG9jLFxuICAgICAgICBpLFxuICAgICAgICBsO1xuXG4gICAgZm9yIChpID0gMCwgbCA9IG9wY29kZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICBvcGNvZGUgPSBvcGNvZGVzW2ldO1xuXG4gICAgICB0aGlzLnNvdXJjZS5jdXJyZW50TG9jYXRpb24gPSBvcGNvZGUubG9jO1xuICAgICAgZmlyc3RMb2MgPSBmaXJzdExvYyB8fCBvcGNvZGUubG9jO1xuICAgICAgdGhpc1tvcGNvZGUub3Bjb2RlXS5hcHBseSh0aGlzLCBvcGNvZGUuYXJncyk7XG4gICAgfVxuXG4gICAgLy8gRmx1c2ggYW55IHRyYWlsaW5nIGNvbnRlbnQgdGhhdCBtaWdodCBiZSBwZW5kaW5nLlxuICAgIHRoaXMuc291cmNlLmN1cnJlbnRMb2NhdGlvbiA9IGZpcnN0TG9jO1xuICAgIHRoaXMucHVzaFNvdXJjZSgnJyk7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICh0aGlzLnN0YWNrU2xvdCB8fCB0aGlzLmlubGluZVN0YWNrLmxlbmd0aCB8fCB0aGlzLmNvbXBpbGVTdGFjay5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0NvbXBpbGUgY29tcGxldGVkIHdpdGggY29udGVudCBsZWZ0IG9uIHN0YWNrJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmRlY29yYXRvcnMuaXNFbXB0eSgpKSB7XG4gICAgICB0aGlzLnVzZURlY29yYXRvcnMgPSB0cnVlO1xuXG4gICAgICB0aGlzLmRlY29yYXRvcnMucHJlcGVuZCgndmFyIGRlY29yYXRvcnMgPSBjb250YWluZXIuZGVjb3JhdG9ycztcXG4nKTtcbiAgICAgIHRoaXMuZGVjb3JhdG9ycy5wdXNoKCdyZXR1cm4gZm47Jyk7XG5cbiAgICAgIGlmIChhc09iamVjdCkge1xuICAgICAgICB0aGlzLmRlY29yYXRvcnMgPSBGdW5jdGlvbi5hcHBseSh0aGlzLCBbJ2ZuJywgJ3Byb3BzJywgJ2NvbnRhaW5lcicsICdkZXB0aDAnLCAnZGF0YScsICdibG9ja1BhcmFtcycsICdkZXB0aHMnLCB0aGlzLmRlY29yYXRvcnMubWVyZ2UoKV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzLnByZXBlbmQoJ2Z1bmN0aW9uKGZuLCBwcm9wcywgY29udGFpbmVyLCBkZXB0aDAsIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcXG4nKTtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzLnB1c2goJ31cXG4nKTtcbiAgICAgICAgdGhpcy5kZWNvcmF0b3JzID0gdGhpcy5kZWNvcmF0b3JzLm1lcmdlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVjb3JhdG9ycyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBsZXQgZm4gPSB0aGlzLmNyZWF0ZUZ1bmN0aW9uQ29udGV4dChhc09iamVjdCk7XG4gICAgaWYgKCF0aGlzLmlzQ2hpbGQpIHtcbiAgICAgIGxldCByZXQgPSB7XG4gICAgICAgIGNvbXBpbGVyOiB0aGlzLmNvbXBpbGVySW5mbygpLFxuICAgICAgICBtYWluOiBmblxuICAgICAgfTtcblxuICAgICAgaWYgKHRoaXMuZGVjb3JhdG9ycykge1xuICAgICAgICByZXQubWFpbl9kID0gdGhpcy5kZWNvcmF0b3JzOyAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY2FtZWxjYXNlXG4gICAgICAgIHJldC51c2VEZWNvcmF0b3JzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgbGV0IHtwcm9ncmFtcywgZGVjb3JhdG9yc30gPSB0aGlzLmNvbnRleHQ7XG4gICAgICBmb3IgKGkgPSAwLCBsID0gcHJvZ3JhbXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIGlmIChwcm9ncmFtc1tpXSkge1xuICAgICAgICAgIHJldFtpXSA9IHByb2dyYW1zW2ldO1xuICAgICAgICAgIGlmIChkZWNvcmF0b3JzW2ldKSB7XG4gICAgICAgICAgICByZXRbaSArICdfZCddID0gZGVjb3JhdG9yc1tpXTtcbiAgICAgICAgICAgIHJldC51c2VEZWNvcmF0b3JzID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQudXNlUGFydGlhbCkge1xuICAgICAgICByZXQudXNlUGFydGlhbCA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmRhdGEpIHtcbiAgICAgICAgcmV0LnVzZURhdGEgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudXNlRGVwdGhzKSB7XG4gICAgICAgIHJldC51c2VEZXB0aHMgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudXNlQmxvY2tQYXJhbXMpIHtcbiAgICAgICAgcmV0LnVzZUJsb2NrUGFyYW1zID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuY29tcGF0KSB7XG4gICAgICAgIHJldC5jb21wYXQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWFzT2JqZWN0KSB7XG4gICAgICAgIHJldC5jb21waWxlciA9IEpTT04uc3RyaW5naWZ5KHJldC5jb21waWxlcik7XG5cbiAgICAgICAgdGhpcy5zb3VyY2UuY3VycmVudExvY2F0aW9uID0ge3N0YXJ0OiB7bGluZTogMSwgY29sdW1uOiAwfX07XG4gICAgICAgIHJldCA9IHRoaXMub2JqZWN0TGl0ZXJhbChyZXQpO1xuXG4gICAgICAgIGlmIChvcHRpb25zLnNyY05hbWUpIHtcbiAgICAgICAgICByZXQgPSByZXQudG9TdHJpbmdXaXRoU291cmNlTWFwKHtmaWxlOiBvcHRpb25zLmRlc3ROYW1lfSk7XG4gICAgICAgICAgcmV0Lm1hcCA9IHJldC5tYXAgJiYgcmV0Lm1hcC50b1N0cmluZygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldCA9IHJldC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXQuY29tcGlsZXJPcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZm47XG4gICAgfVxuICB9LFxuXG4gIHByZWFtYmxlOiBmdW5jdGlvbigpIHtcbiAgICAvLyB0cmFjayB0aGUgbGFzdCBjb250ZXh0IHB1c2hlZCBpbnRvIHBsYWNlIHRvIGFsbG93IHNraXBwaW5nIHRoZVxuICAgIC8vIGdldENvbnRleHQgb3Bjb2RlIHdoZW4gaXQgd291bGQgYmUgYSBub29wXG4gICAgdGhpcy5sYXN0Q29udGV4dCA9IDA7XG4gICAgdGhpcy5zb3VyY2UgPSBuZXcgQ29kZUdlbih0aGlzLm9wdGlvbnMuc3JjTmFtZSk7XG4gICAgdGhpcy5kZWNvcmF0b3JzID0gbmV3IENvZGVHZW4odGhpcy5vcHRpb25zLnNyY05hbWUpO1xuICB9LFxuXG4gIGNyZWF0ZUZ1bmN0aW9uQ29udGV4dDogZnVuY3Rpb24oYXNPYmplY3QpIHtcbiAgICBsZXQgdmFyRGVjbGFyYXRpb25zID0gJyc7XG5cbiAgICBsZXQgbG9jYWxzID0gdGhpcy5zdGFja1ZhcnMuY29uY2F0KHRoaXMucmVnaXN0ZXJzLmxpc3QpO1xuICAgIGlmIChsb2NhbHMubGVuZ3RoID4gMCkge1xuICAgICAgdmFyRGVjbGFyYXRpb25zICs9ICcsICcgKyBsb2NhbHMuam9pbignLCAnKTtcbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZSBtaW5pbWl6ZXIgYWxpYXMgbWFwcGluZ3NcbiAgICAvL1xuICAgIC8vIFdoZW4gdXNpbmcgdHJ1ZSBTb3VyY2VOb2RlcywgdGhpcyB3aWxsIHVwZGF0ZSBhbGwgcmVmZXJlbmNlcyB0byB0aGUgZ2l2ZW4gYWxpYXNcbiAgICAvLyBhcyB0aGUgc291cmNlIG5vZGVzIGFyZSByZXVzZWQgaW4gc2l0dS4gRm9yIHRoZSBub24tc291cmNlIG5vZGUgY29tcGlsYXRpb24gbW9kZSxcbiAgICAvLyBhbGlhc2VzIHdpbGwgbm90IGJlIHVzZWQsIGJ1dCB0aGlzIGNhc2UgaXMgYWxyZWFkeSBiZWluZyBydW4gb24gdGhlIGNsaWVudCBhbmRcbiAgICAvLyB3ZSBhcmVuJ3QgY29uY2VybiBhYm91dCBtaW5pbWl6aW5nIHRoZSB0ZW1wbGF0ZSBzaXplLlxuICAgIGxldCBhbGlhc0NvdW50ID0gMDtcbiAgICBmb3IgKGxldCBhbGlhcyBpbiB0aGlzLmFsaWFzZXMpIHsgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBndWFyZC1mb3ItaW5cbiAgICAgIGxldCBub2RlID0gdGhpcy5hbGlhc2VzW2FsaWFzXTtcblxuICAgICAgaWYgKHRoaXMuYWxpYXNlcy5oYXNPd25Qcm9wZXJ0eShhbGlhcykgJiYgbm9kZS5jaGlsZHJlbiAmJiBub2RlLnJlZmVyZW5jZUNvdW50ID4gMSkge1xuICAgICAgICB2YXJEZWNsYXJhdGlvbnMgKz0gJywgYWxpYXMnICsgKCsrYWxpYXNDb3VudCkgKyAnPScgKyBhbGlhcztcbiAgICAgICAgbm9kZS5jaGlsZHJlblswXSA9ICdhbGlhcycgKyBhbGlhc0NvdW50O1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBwYXJhbXMgPSBbJ2NvbnRhaW5lcicsICdkZXB0aDAnLCAnaGVscGVycycsICdwYXJ0aWFscycsICdkYXRhJ107XG5cbiAgICBpZiAodGhpcy51c2VCbG9ja1BhcmFtcyB8fCB0aGlzLnVzZURlcHRocykge1xuICAgICAgcGFyYW1zLnB1c2goJ2Jsb2NrUGFyYW1zJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnVzZURlcHRocykge1xuICAgICAgcGFyYW1zLnB1c2goJ2RlcHRocycpO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gYSBzZWNvbmQgcGFzcyBvdmVyIHRoZSBvdXRwdXQgdG8gbWVyZ2UgY29udGVudCB3aGVuIHBvc3NpYmxlXG4gICAgbGV0IHNvdXJjZSA9IHRoaXMubWVyZ2VTb3VyY2UodmFyRGVjbGFyYXRpb25zKTtcblxuICAgIGlmIChhc09iamVjdCkge1xuICAgICAgcGFyYW1zLnB1c2goc291cmNlKTtcblxuICAgICAgcmV0dXJuIEZ1bmN0aW9uLmFwcGx5KHRoaXMsIHBhcmFtcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnNvdXJjZS53cmFwKFsnZnVuY3Rpb24oJywgcGFyYW1zLmpvaW4oJywnKSwgJykge1xcbiAgJywgc291cmNlLCAnfSddKTtcbiAgICB9XG4gIH0sXG4gIG1lcmdlU291cmNlOiBmdW5jdGlvbih2YXJEZWNsYXJhdGlvbnMpIHtcbiAgICBsZXQgaXNTaW1wbGUgPSB0aGlzLmVudmlyb25tZW50LmlzU2ltcGxlLFxuICAgICAgICBhcHBlbmRPbmx5ID0gIXRoaXMuZm9yY2VCdWZmZXIsXG4gICAgICAgIGFwcGVuZEZpcnN0LFxuXG4gICAgICAgIHNvdXJjZVNlZW4sXG4gICAgICAgIGJ1ZmZlclN0YXJ0LFxuICAgICAgICBidWZmZXJFbmQ7XG4gICAgdGhpcy5zb3VyY2UuZWFjaCgobGluZSkgPT4ge1xuICAgICAgaWYgKGxpbmUuYXBwZW5kVG9CdWZmZXIpIHtcbiAgICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgICAgbGluZS5wcmVwZW5kKCcgICsgJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVmZmVyU3RhcnQgPSBsaW5lO1xuICAgICAgICB9XG4gICAgICAgIGJ1ZmZlckVuZCA9IGxpbmU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoYnVmZmVyU3RhcnQpIHtcbiAgICAgICAgICBpZiAoIXNvdXJjZVNlZW4pIHtcbiAgICAgICAgICAgIGFwcGVuZEZpcnN0ID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZmVyU3RhcnQucHJlcGVuZCgnYnVmZmVyICs9ICcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBidWZmZXJFbmQuYWRkKCc7Jyk7XG4gICAgICAgICAgYnVmZmVyU3RhcnQgPSBidWZmZXJFbmQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBzb3VyY2VTZWVuID0gdHJ1ZTtcbiAgICAgICAgaWYgKCFpc1NpbXBsZSkge1xuICAgICAgICAgIGFwcGVuZE9ubHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG5cbiAgICBpZiAoYXBwZW5kT25seSkge1xuICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgIGJ1ZmZlclN0YXJ0LnByZXBlbmQoJ3JldHVybiAnKTtcbiAgICAgICAgYnVmZmVyRW5kLmFkZCgnOycpO1xuICAgICAgfSBlbHNlIGlmICghc291cmNlU2Vlbikge1xuICAgICAgICB0aGlzLnNvdXJjZS5wdXNoKCdyZXR1cm4gXCJcIjsnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyRGVjbGFyYXRpb25zICs9ICcsIGJ1ZmZlciA9ICcgKyAoYXBwZW5kRmlyc3QgPyAnJyA6IHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcigpKTtcblxuICAgICAgaWYgKGJ1ZmZlclN0YXJ0KSB7XG4gICAgICAgIGJ1ZmZlclN0YXJ0LnByZXBlbmQoJ3JldHVybiBidWZmZXIgKyAnKTtcbiAgICAgICAgYnVmZmVyRW5kLmFkZCgnOycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zb3VyY2UucHVzaCgncmV0dXJuIGJ1ZmZlcjsnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodmFyRGVjbGFyYXRpb25zKSB7XG4gICAgICB0aGlzLnNvdXJjZS5wcmVwZW5kKCd2YXIgJyArIHZhckRlY2xhcmF0aW9ucy5zdWJzdHJpbmcoMikgKyAoYXBwZW5kRmlyc3QgPyAnJyA6ICc7XFxuJykpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNvdXJjZS5tZXJnZSgpO1xuICB9LFxuXG4gIC8vIFtibG9ja1ZhbHVlXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCB2YWx1ZVxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJldHVybiB2YWx1ZSBvZiBibG9ja0hlbHBlck1pc3NpbmdcbiAgLy9cbiAgLy8gVGhlIHB1cnBvc2Ugb2YgdGhpcyBvcGNvZGUgaXMgdG8gdGFrZSBhIGJsb2NrIG9mIHRoZSBmb3JtXG4gIC8vIGB7eyN0aGlzLmZvb319Li4ue3svdGhpcy5mb299fWAsIHJlc29sdmUgdGhlIHZhbHVlIG9mIGBmb29gLCBhbmRcbiAgLy8gcmVwbGFjZSBpdCBvbiB0aGUgc3RhY2sgd2l0aCB0aGUgcmVzdWx0IG9mIHByb3Blcmx5XG4gIC8vIGludm9raW5nIGJsb2NrSGVscGVyTWlzc2luZy5cbiAgYmxvY2tWYWx1ZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGxldCBibG9ja0hlbHBlck1pc3NpbmcgPSB0aGlzLmFsaWFzYWJsZSgnaGVscGVycy5ibG9ja0hlbHBlck1pc3NpbmcnKSxcbiAgICAgICAgcGFyYW1zID0gW3RoaXMuY29udGV4dE5hbWUoMCldO1xuICAgIHRoaXMuc2V0dXBIZWxwZXJBcmdzKG5hbWUsIDAsIHBhcmFtcyk7XG5cbiAgICBsZXQgYmxvY2tOYW1lID0gdGhpcy5wb3BTdGFjaygpO1xuICAgIHBhcmFtcy5zcGxpY2UoMSwgMCwgYmxvY2tOYW1lKTtcblxuICAgIHRoaXMucHVzaCh0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwoYmxvY2tIZWxwZXJNaXNzaW5nLCAnY2FsbCcsIHBhcmFtcykpO1xuICB9LFxuXG4gIC8vIFthbWJpZ3VvdXNCbG9ja1ZhbHVlXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCB2YWx1ZVxuICAvLyBDb21waWxlciB2YWx1ZSwgYmVmb3JlOiBsYXN0SGVscGVyPXZhbHVlIG9mIGxhc3QgZm91bmQgaGVscGVyLCBpZiBhbnlcbiAgLy8gT24gc3RhY2ssIGFmdGVyLCBpZiBubyBsYXN0SGVscGVyOiBzYW1lIGFzIFtibG9ja1ZhbHVlXVxuICAvLyBPbiBzdGFjaywgYWZ0ZXIsIGlmIGxhc3RIZWxwZXI6IHZhbHVlXG4gIGFtYmlndW91c0Jsb2NrVmFsdWU6IGZ1bmN0aW9uKCkge1xuICAgIC8vIFdlJ3JlIGJlaW5nIGEgYml0IGNoZWVreSBhbmQgcmV1c2luZyB0aGUgb3B0aW9ucyB2YWx1ZSBmcm9tIHRoZSBwcmlvciBleGVjXG4gICAgbGV0IGJsb2NrSGVscGVyTWlzc2luZyA9IHRoaXMuYWxpYXNhYmxlKCdoZWxwZXJzLmJsb2NrSGVscGVyTWlzc2luZycpLFxuICAgICAgICBwYXJhbXMgPSBbdGhpcy5jb250ZXh0TmFtZSgwKV07XG4gICAgdGhpcy5zZXR1cEhlbHBlckFyZ3MoJycsIDAsIHBhcmFtcywgdHJ1ZSk7XG5cbiAgICB0aGlzLmZsdXNoSW5saW5lKCk7XG5cbiAgICBsZXQgY3VycmVudCA9IHRoaXMudG9wU3RhY2soKTtcbiAgICBwYXJhbXMuc3BsaWNlKDEsIDAsIGN1cnJlbnQpO1xuXG4gICAgdGhpcy5wdXNoU291cmNlKFtcbiAgICAgICAgJ2lmICghJywgdGhpcy5sYXN0SGVscGVyLCAnKSB7ICcsXG4gICAgICAgICAgY3VycmVudCwgJyA9ICcsIHRoaXMuc291cmNlLmZ1bmN0aW9uQ2FsbChibG9ja0hlbHBlck1pc3NpbmcsICdjYWxsJywgcGFyYW1zKSxcbiAgICAgICAgJ30nXSk7XG4gIH0sXG5cbiAgLy8gW2FwcGVuZENvbnRlbnRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBBcHBlbmRzIHRoZSBzdHJpbmcgdmFsdWUgb2YgYGNvbnRlbnRgIHRvIHRoZSBjdXJyZW50IGJ1ZmZlclxuICBhcHBlbmRDb250ZW50OiBmdW5jdGlvbihjb250ZW50KSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIGNvbnRlbnQgPSB0aGlzLnBlbmRpbmdDb250ZW50ICsgY29udGVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wZW5kaW5nTG9jYXRpb24gPSB0aGlzLnNvdXJjZS5jdXJyZW50TG9jYXRpb247XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nQ29udGVudCA9IGNvbnRlbnQ7XG4gIH0sXG5cbiAgLy8gW2FwcGVuZF1cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogdmFsdWUsIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBDb2VyY2VzIGB2YWx1ZWAgdG8gYSBTdHJpbmcgYW5kIGFwcGVuZHMgaXQgdG8gdGhlIGN1cnJlbnQgYnVmZmVyLlxuICAvL1xuICAvLyBJZiBgdmFsdWVgIGlzIHRydXRoeSwgb3IgMCwgaXQgaXMgY29lcmNlZCBpbnRvIGEgc3RyaW5nIGFuZCBhcHBlbmRlZFxuICAvLyBPdGhlcndpc2UsIHRoZSBlbXB0eSBzdHJpbmcgaXMgYXBwZW5kZWRcbiAgYXBwZW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5pc0lubGluZSgpKSB7XG4gICAgICB0aGlzLnJlcGxhY2VTdGFjaygoY3VycmVudCkgPT4gWycgIT0gbnVsbCA/ICcsIGN1cnJlbnQsICcgOiBcIlwiJ10pO1xuXG4gICAgICB0aGlzLnB1c2hTb3VyY2UodGhpcy5hcHBlbmRUb0J1ZmZlcih0aGlzLnBvcFN0YWNrKCkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGxvY2FsID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgdGhpcy5wdXNoU291cmNlKFsnaWYgKCcsIGxvY2FsLCAnICE9IG51bGwpIHsgJywgdGhpcy5hcHBlbmRUb0J1ZmZlcihsb2NhbCwgdW5kZWZpbmVkLCB0cnVlKSwgJyB9J10pO1xuICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQuaXNTaW1wbGUpIHtcbiAgICAgICAgdGhpcy5wdXNoU291cmNlKFsnZWxzZSB7ICcsIHRoaXMuYXBwZW5kVG9CdWZmZXIoXCInJ1wiLCB1bmRlZmluZWQsIHRydWUpLCAnIH0nXSk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8vIFthcHBlbmRFc2NhcGVkXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiB2YWx1ZSwgLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogLi4uXG4gIC8vXG4gIC8vIEVzY2FwZSBgdmFsdWVgIGFuZCBhcHBlbmQgaXQgdG8gdGhlIGJ1ZmZlclxuICBhcHBlbmRFc2NhcGVkOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2hTb3VyY2UodGhpcy5hcHBlbmRUb0J1ZmZlcihcbiAgICAgICAgW3RoaXMuYWxpYXNhYmxlKCdjb250YWluZXIuZXNjYXBlRXhwcmVzc2lvbicpLCAnKCcsIHRoaXMucG9wU3RhY2soKSwgJyknXSkpO1xuICB9LFxuXG4gIC8vIFtnZXRDb250ZXh0XVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiAuLi5cbiAgLy8gQ29tcGlsZXIgdmFsdWUsIGFmdGVyOiBsYXN0Q29udGV4dD1kZXB0aFxuICAvL1xuICAvLyBTZXQgdGhlIHZhbHVlIG9mIHRoZSBgbGFzdENvbnRleHRgIGNvbXBpbGVyIHZhbHVlIHRvIHRoZSBkZXB0aFxuICBnZXRDb250ZXh0OiBmdW5jdGlvbihkZXB0aCkge1xuICAgIHRoaXMubGFzdENvbnRleHQgPSBkZXB0aDtcbiAgfSxcblxuICAvLyBbcHVzaENvbnRleHRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IGN1cnJlbnRDb250ZXh0LCAuLi5cbiAgLy9cbiAgLy8gUHVzaGVzIHRoZSB2YWx1ZSBvZiB0aGUgY3VycmVudCBjb250ZXh0IG9udG8gdGhlIHN0YWNrLlxuICBwdXNoQ29udGV4dDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHRoaXMuY29udGV4dE5hbWUodGhpcy5sYXN0Q29udGV4dCkpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBPbkNvbnRleHRdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IGN1cnJlbnRDb250ZXh0W25hbWVdLCAuLi5cbiAgLy9cbiAgLy8gTG9va3MgdXAgdGhlIHZhbHVlIG9mIGBuYW1lYCBvbiB0aGUgY3VycmVudCBjb250ZXh0IGFuZCBwdXNoZXNcbiAgLy8gaXQgb250byB0aGUgc3RhY2suXG4gIGxvb2t1cE9uQ29udGV4dDogZnVuY3Rpb24ocGFydHMsIGZhbHN5LCBzdHJpY3QsIHNjb3BlZCkge1xuICAgIGxldCBpID0gMDtcblxuICAgIGlmICghc2NvcGVkICYmIHRoaXMub3B0aW9ucy5jb21wYXQgJiYgIXRoaXMubGFzdENvbnRleHQpIHtcbiAgICAgIC8vIFRoZSBkZXB0aGVkIHF1ZXJ5IGlzIGV4cGVjdGVkIHRvIGhhbmRsZSB0aGUgdW5kZWZpbmVkIGxvZ2ljIGZvciB0aGUgcm9vdCBsZXZlbCB0aGF0XG4gICAgICAvLyBpcyBpbXBsZW1lbnRlZCBiZWxvdywgc28gd2UgZXZhbHVhdGUgdGhhdCBkaXJlY3RseSBpbiBjb21wYXQgbW9kZVxuICAgICAgdGhpcy5wdXNoKHRoaXMuZGVwdGhlZExvb2t1cChwYXJ0c1tpKytdKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaENvbnRleHQoKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlc29sdmVQYXRoKCdjb250ZXh0JywgcGFydHMsIGksIGZhbHN5LCBzdHJpY3QpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBCbG9ja1BhcmFtXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBibG9ja1BhcmFtW25hbWVdLCAuLi5cbiAgLy9cbiAgLy8gTG9va3MgdXAgdGhlIHZhbHVlIG9mIGBwYXJ0c2Agb24gdGhlIGdpdmVuIGJsb2NrIHBhcmFtIGFuZCBwdXNoZXNcbiAgLy8gaXQgb250byB0aGUgc3RhY2suXG4gIGxvb2t1cEJsb2NrUGFyYW06IGZ1bmN0aW9uKGJsb2NrUGFyYW1JZCwgcGFydHMpIHtcbiAgICB0aGlzLnVzZUJsb2NrUGFyYW1zID0gdHJ1ZTtcblxuICAgIHRoaXMucHVzaChbJ2Jsb2NrUGFyYW1zWycsIGJsb2NrUGFyYW1JZFswXSwgJ11bJywgYmxvY2tQYXJhbUlkWzFdLCAnXSddKTtcbiAgICB0aGlzLnJlc29sdmVQYXRoKCdjb250ZXh0JywgcGFydHMsIDEpO1xuICB9LFxuXG4gIC8vIFtsb29rdXBEYXRhXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBkYXRhLCAuLi5cbiAgLy9cbiAgLy8gUHVzaCB0aGUgZGF0YSBsb29rdXAgb3BlcmF0b3JcbiAgbG9va3VwRGF0YTogZnVuY3Rpb24oZGVwdGgsIHBhcnRzLCBzdHJpY3QpIHtcbiAgICBpZiAoIWRlcHRoKSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwoJ2RhdGEnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKCdjb250YWluZXIuZGF0YShkYXRhLCAnICsgZGVwdGggKyAnKScpO1xuICAgIH1cblxuICAgIHRoaXMucmVzb2x2ZVBhdGgoJ2RhdGEnLCBwYXJ0cywgMCwgdHJ1ZSwgc3RyaWN0KTtcbiAgfSxcblxuICByZXNvbHZlUGF0aDogZnVuY3Rpb24odHlwZSwgcGFydHMsIGksIGZhbHN5LCBzdHJpY3QpIHtcbiAgICBpZiAodGhpcy5vcHRpb25zLnN0cmljdCB8fCB0aGlzLm9wdGlvbnMuYXNzdW1lT2JqZWN0cykge1xuICAgICAgdGhpcy5wdXNoKHN0cmljdExvb2t1cCh0aGlzLm9wdGlvbnMuc3RyaWN0ICYmIHN0cmljdCwgdGhpcywgcGFydHMsIHR5cGUpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgbGVuID0gcGFydHMubGVuZ3RoO1xuICAgIGZvciAoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWxvb3AtZnVuYyAqL1xuICAgICAgdGhpcy5yZXBsYWNlU3RhY2soKGN1cnJlbnQpID0+IHtcbiAgICAgICAgbGV0IGxvb2t1cCA9IHRoaXMubmFtZUxvb2t1cChjdXJyZW50LCBwYXJ0c1tpXSwgdHlwZSk7XG4gICAgICAgIC8vIFdlIHdhbnQgdG8gZW5zdXJlIHRoYXQgemVybyBhbmQgZmFsc2UgYXJlIGhhbmRsZWQgcHJvcGVybHkgaWYgdGhlIGNvbnRleHQgKGZhbHN5IGZsYWcpXG4gICAgICAgIC8vIG5lZWRzIHRvIGhhdmUgdGhlIHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRoZXNlIHZhbHVlcy5cbiAgICAgICAgaWYgKCFmYWxzeSkge1xuICAgICAgICAgIHJldHVybiBbJyAhPSBudWxsID8gJywgbG9va3VwLCAnIDogJywgY3VycmVudF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlIHdlIGNhbiB1c2UgZ2VuZXJpYyBmYWxzeSBoYW5kbGluZ1xuICAgICAgICAgIHJldHVybiBbJyAmJiAnLCBsb29rdXBdO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG4gICAgfVxuICB9LFxuXG4gIC8vIFtyZXNvbHZlUG9zc2libGVMYW1iZGFdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IHZhbHVlLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiByZXNvbHZlZCB2YWx1ZSwgLi4uXG4gIC8vXG4gIC8vIElmIHRoZSBgdmFsdWVgIGlzIGEgbGFtYmRhLCByZXBsYWNlIGl0IG9uIHRoZSBzdGFjayBieVxuICAvLyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBsYW1iZGFcbiAgcmVzb2x2ZVBvc3NpYmxlTGFtYmRhOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2goW3RoaXMuYWxpYXNhYmxlKCdjb250YWluZXIubGFtYmRhJyksICcoJywgdGhpcy5wb3BTdGFjaygpLCAnLCAnLCB0aGlzLmNvbnRleHROYW1lKDApLCAnKSddKTtcbiAgfSxcblxuICAvLyBbcHVzaFN0cmluZ1BhcmFtXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiBzdHJpbmcsIGN1cnJlbnRDb250ZXh0LCAuLi5cbiAgLy9cbiAgLy8gVGhpcyBvcGNvZGUgaXMgZGVzaWduZWQgZm9yIHVzZSBpbiBzdHJpbmcgbW9kZSwgd2hpY2hcbiAgLy8gcHJvdmlkZXMgdGhlIHN0cmluZyB2YWx1ZSBvZiBhIHBhcmFtZXRlciBhbG9uZyB3aXRoIGl0c1xuICAvLyBkZXB0aCByYXRoZXIgdGhhbiByZXNvbHZpbmcgaXQgaW1tZWRpYXRlbHkuXG4gIHB1c2hTdHJpbmdQYXJhbTogZnVuY3Rpb24oc3RyaW5nLCB0eXBlKSB7XG4gICAgdGhpcy5wdXNoQ29udGV4dCgpO1xuICAgIHRoaXMucHVzaFN0cmluZyh0eXBlKTtcblxuICAgIC8vIElmIGl0J3MgYSBzdWJleHByZXNzaW9uLCB0aGUgc3RyaW5nIHJlc3VsdFxuICAgIC8vIHdpbGwgYmUgcHVzaGVkIGFmdGVyIHRoaXMgb3Bjb2RlLlxuICAgIGlmICh0eXBlICE9PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgIGlmICh0eXBlb2Ygc3RyaW5nID09PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLnB1c2hTdHJpbmcoc3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChzdHJpbmcpO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBlbXB0eUhhc2g6IGZ1bmN0aW9uKG9taXRFbXB0eSkge1xuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICB0aGlzLnB1c2goJ3t9Jyk7IC8vIGhhc2hJZHNcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0aGlzLnB1c2goJ3t9Jyk7IC8vIGhhc2hDb250ZXh0c1xuICAgICAgdGhpcy5wdXNoKCd7fScpOyAvLyBoYXNoVHlwZXNcbiAgICB9XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKG9taXRFbXB0eSA/ICd1bmRlZmluZWQnIDogJ3t9Jyk7XG4gIH0sXG4gIHB1c2hIYXNoOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5oYXNoKSB7XG4gICAgICB0aGlzLmhhc2hlcy5wdXNoKHRoaXMuaGFzaCk7XG4gICAgfVxuICAgIHRoaXMuaGFzaCA9IHt2YWx1ZXM6IFtdLCB0eXBlczogW10sIGNvbnRleHRzOiBbXSwgaWRzOiBbXX07XG4gIH0sXG4gIHBvcEhhc2g6IGZ1bmN0aW9uKCkge1xuICAgIGxldCBoYXNoID0gdGhpcy5oYXNoO1xuICAgIHRoaXMuaGFzaCA9IHRoaXMuaGFzaGVzLnBvcCgpO1xuXG4gICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC5pZHMpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0aGlzLnB1c2godGhpcy5vYmplY3RMaXRlcmFsKGhhc2guY29udGV4dHMpKTtcbiAgICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC50eXBlcykpO1xuICAgIH1cblxuICAgIHRoaXMucHVzaCh0aGlzLm9iamVjdExpdGVyYWwoaGFzaC52YWx1ZXMpKTtcbiAgfSxcblxuICAvLyBbcHVzaFN0cmluZ11cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogcXVvdGVkU3RyaW5nKHN0cmluZyksIC4uLlxuICAvL1xuICAvLyBQdXNoIGEgcXVvdGVkIHZlcnNpb24gb2YgYHN0cmluZ2Agb250byB0aGUgc3RhY2tcbiAgcHVzaFN0cmluZzogZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHRoaXMucXVvdGVkU3RyaW5nKHN0cmluZykpO1xuICB9LFxuXG4gIC8vIFtwdXNoTGl0ZXJhbF1cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogLi4uXG4gIC8vIE9uIHN0YWNrLCBhZnRlcjogdmFsdWUsIC4uLlxuICAvL1xuICAvLyBQdXNoZXMgYSB2YWx1ZSBvbnRvIHRoZSBzdGFjay4gVGhpcyBvcGVyYXRpb24gcHJldmVudHNcbiAgLy8gdGhlIGNvbXBpbGVyIGZyb20gY3JlYXRpbmcgYSB0ZW1wb3JhcnkgdmFyaWFibGUgdG8gaG9sZFxuICAvLyBpdC5cbiAgcHVzaExpdGVyYWw6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgdGhpcy5wdXNoU3RhY2tMaXRlcmFsKHZhbHVlKTtcbiAgfSxcblxuICAvLyBbcHVzaFByb2dyYW1dXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHByb2dyYW0oZ3VpZCksIC4uLlxuICAvL1xuICAvLyBQdXNoIGEgcHJvZ3JhbSBleHByZXNzaW9uIG9udG8gdGhlIHN0YWNrLiBUaGlzIHRha2VzXG4gIC8vIGEgY29tcGlsZS10aW1lIGd1aWQgYW5kIGNvbnZlcnRzIGl0IGludG8gYSBydW50aW1lLWFjY2Vzc2libGVcbiAgLy8gZXhwcmVzc2lvbi5cbiAgcHVzaFByb2dyYW06IGZ1bmN0aW9uKGd1aWQpIHtcbiAgICBpZiAoZ3VpZCAhPSBudWxsKSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwodGhpcy5wcm9ncmFtRXhwcmVzc2lvbihndWlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChudWxsKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gW3JlZ2lzdGVyRGVjb3JhdG9yXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IC4uLlxuICAvL1xuICAvLyBQb3BzIG9mZiB0aGUgZGVjb3JhdG9yJ3MgcGFyYW1ldGVycywgaW52b2tlcyB0aGUgZGVjb3JhdG9yLFxuICAvLyBhbmQgaW5zZXJ0cyB0aGUgZGVjb3JhdG9yIGludG8gdGhlIGRlY29yYXRvcnMgbGlzdC5cbiAgcmVnaXN0ZXJEZWNvcmF0b3IocGFyYW1TaXplLCBuYW1lKSB7XG4gICAgbGV0IGZvdW5kRGVjb3JhdG9yID0gdGhpcy5uYW1lTG9va3VwKCdkZWNvcmF0b3JzJywgbmFtZSwgJ2RlY29yYXRvcicpLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5zZXR1cEhlbHBlckFyZ3MobmFtZSwgcGFyYW1TaXplKTtcblxuICAgIHRoaXMuZGVjb3JhdG9ycy5wdXNoKFtcbiAgICAgICdmbiA9ICcsXG4gICAgICB0aGlzLmRlY29yYXRvcnMuZnVuY3Rpb25DYWxsKGZvdW5kRGVjb3JhdG9yLCAnJywgWydmbicsICdwcm9wcycsICdjb250YWluZXInLCBvcHRpb25zXSksXG4gICAgICAnIHx8IGZuOydcbiAgICBdKTtcbiAgfSxcblxuICAvLyBbaW52b2tlSGVscGVyXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJlc3VsdCBvZiBoZWxwZXIgaW52b2NhdGlvblxuICAvL1xuICAvLyBQb3BzIG9mZiB0aGUgaGVscGVyJ3MgcGFyYW1ldGVycywgaW52b2tlcyB0aGUgaGVscGVyLFxuICAvLyBhbmQgcHVzaGVzIHRoZSBoZWxwZXIncyByZXR1cm4gdmFsdWUgb250byB0aGUgc3RhY2suXG4gIC8vXG4gIC8vIElmIHRoZSBoZWxwZXIgaXMgbm90IGZvdW5kLCBgaGVscGVyTWlzc2luZ2AgaXMgY2FsbGVkLlxuICBpbnZva2VIZWxwZXI6IGZ1bmN0aW9uKHBhcmFtU2l6ZSwgbmFtZSwgaXNTaW1wbGUpIHtcbiAgICBsZXQgbm9uSGVscGVyID0gdGhpcy5wb3BTdGFjaygpLFxuICAgICAgICBoZWxwZXIgPSB0aGlzLnNldHVwSGVscGVyKHBhcmFtU2l6ZSwgbmFtZSksXG4gICAgICAgIHNpbXBsZSA9IGlzU2ltcGxlID8gW2hlbHBlci5uYW1lLCAnIHx8ICddIDogJyc7XG5cbiAgICBsZXQgbG9va3VwID0gWycoJ10uY29uY2F0KHNpbXBsZSwgbm9uSGVscGVyKTtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5zdHJpY3QpIHtcbiAgICAgIGxvb2t1cC5wdXNoKCcgfHwgJywgdGhpcy5hbGlhc2FibGUoJ2hlbHBlcnMuaGVscGVyTWlzc2luZycpKTtcbiAgICB9XG4gICAgbG9va3VwLnB1c2goJyknKTtcblxuICAgIHRoaXMucHVzaCh0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwobG9va3VwLCAnY2FsbCcsIGhlbHBlci5jYWxsUGFyYW1zKSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZUtub3duSGVscGVyXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiBoYXNoLCBpbnZlcnNlLCBwcm9ncmFtLCBwYXJhbXMuLi4sIC4uLlxuICAvLyBPbiBzdGFjaywgYWZ0ZXI6IHJlc3VsdCBvZiBoZWxwZXIgaW52b2NhdGlvblxuICAvL1xuICAvLyBUaGlzIG9wZXJhdGlvbiBpcyB1c2VkIHdoZW4gdGhlIGhlbHBlciBpcyBrbm93biB0byBleGlzdCxcbiAgLy8gc28gYSBgaGVscGVyTWlzc2luZ2AgZmFsbGJhY2sgaXMgbm90IHJlcXVpcmVkLlxuICBpbnZva2VLbm93bkhlbHBlcjogZnVuY3Rpb24ocGFyYW1TaXplLCBuYW1lKSB7XG4gICAgbGV0IGhlbHBlciA9IHRoaXMuc2V0dXBIZWxwZXIocGFyYW1TaXplLCBuYW1lKTtcbiAgICB0aGlzLnB1c2godGhpcy5zb3VyY2UuZnVuY3Rpb25DYWxsKGhlbHBlci5uYW1lLCAnY2FsbCcsIGhlbHBlci5jYWxsUGFyYW1zKSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZUFtYmlndW91c11cbiAgLy9cbiAgLy8gT24gc3RhY2ssIGJlZm9yZTogaGFzaCwgaW52ZXJzZSwgcHJvZ3JhbSwgcGFyYW1zLi4uLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiByZXN1bHQgb2YgZGlzYW1iaWd1YXRpb25cbiAgLy9cbiAgLy8gVGhpcyBvcGVyYXRpb24gaXMgdXNlZCB3aGVuIGFuIGV4cHJlc3Npb24gbGlrZSBge3tmb299fWBcbiAgLy8gaXMgcHJvdmlkZWQsIGJ1dCB3ZSBkb24ndCBrbm93IGF0IGNvbXBpbGUtdGltZSB3aGV0aGVyIGl0XG4gIC8vIGlzIGEgaGVscGVyIG9yIGEgcGF0aC5cbiAgLy9cbiAgLy8gVGhpcyBvcGVyYXRpb24gZW1pdHMgbW9yZSBjb2RlIHRoYW4gdGhlIG90aGVyIG9wdGlvbnMsXG4gIC8vIGFuZCBjYW4gYmUgYXZvaWRlZCBieSBwYXNzaW5nIHRoZSBga25vd25IZWxwZXJzYCBhbmRcbiAgLy8gYGtub3duSGVscGVyc09ubHlgIGZsYWdzIGF0IGNvbXBpbGUtdGltZS5cbiAgaW52b2tlQW1iaWd1b3VzOiBmdW5jdGlvbihuYW1lLCBoZWxwZXJDYWxsKSB7XG4gICAgdGhpcy51c2VSZWdpc3RlcignaGVscGVyJyk7XG5cbiAgICBsZXQgbm9uSGVscGVyID0gdGhpcy5wb3BTdGFjaygpO1xuXG4gICAgdGhpcy5lbXB0eUhhc2goKTtcbiAgICBsZXQgaGVscGVyID0gdGhpcy5zZXR1cEhlbHBlcigwLCBuYW1lLCBoZWxwZXJDYWxsKTtcblxuICAgIGxldCBoZWxwZXJOYW1lID0gdGhpcy5sYXN0SGVscGVyID0gdGhpcy5uYW1lTG9va3VwKCdoZWxwZXJzJywgbmFtZSwgJ2hlbHBlcicpO1xuXG4gICAgbGV0IGxvb2t1cCA9IFsnKCcsICcoaGVscGVyID0gJywgaGVscGVyTmFtZSwgJyB8fCAnLCBub25IZWxwZXIsICcpJ107XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICBsb29rdXBbMF0gPSAnKGhlbHBlciA9ICc7XG4gICAgICBsb29rdXAucHVzaChcbiAgICAgICAgJyAhPSBudWxsID8gaGVscGVyIDogJyxcbiAgICAgICAgdGhpcy5hbGlhc2FibGUoJ2hlbHBlcnMuaGVscGVyTWlzc2luZycpXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMucHVzaChbXG4gICAgICAgICcoJywgbG9va3VwLFxuICAgICAgICAoaGVscGVyLnBhcmFtc0luaXQgPyBbJyksKCcsIGhlbHBlci5wYXJhbXNJbml0XSA6IFtdKSwgJyksJyxcbiAgICAgICAgJyh0eXBlb2YgaGVscGVyID09PSAnLCB0aGlzLmFsaWFzYWJsZSgnXCJmdW5jdGlvblwiJyksICcgPyAnLFxuICAgICAgICB0aGlzLnNvdXJjZS5mdW5jdGlvbkNhbGwoJ2hlbHBlcicsICdjYWxsJywgaGVscGVyLmNhbGxQYXJhbXMpLCAnIDogaGVscGVyKSknXG4gICAgXSk7XG4gIH0sXG5cbiAgLy8gW2ludm9rZVBhcnRpYWxdXG4gIC8vXG4gIC8vIE9uIHN0YWNrLCBiZWZvcmU6IGNvbnRleHQsIC4uLlxuICAvLyBPbiBzdGFjayBhZnRlcjogcmVzdWx0IG9mIHBhcnRpYWwgaW52b2NhdGlvblxuICAvL1xuICAvLyBUaGlzIG9wZXJhdGlvbiBwb3BzIG9mZiBhIGNvbnRleHQsIGludm9rZXMgYSBwYXJ0aWFsIHdpdGggdGhhdCBjb250ZXh0LFxuICAvLyBhbmQgcHVzaGVzIHRoZSByZXN1bHQgb2YgdGhlIGludm9jYXRpb24gYmFjay5cbiAgaW52b2tlUGFydGlhbDogZnVuY3Rpb24oaXNEeW5hbWljLCBuYW1lLCBpbmRlbnQpIHtcbiAgICBsZXQgcGFyYW1zID0gW10sXG4gICAgICAgIG9wdGlvbnMgPSB0aGlzLnNldHVwUGFyYW1zKG5hbWUsIDEsIHBhcmFtcyk7XG5cbiAgICBpZiAoaXNEeW5hbWljKSB7XG4gICAgICBuYW1lID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgZGVsZXRlIG9wdGlvbnMubmFtZTtcbiAgICB9XG5cbiAgICBpZiAoaW5kZW50KSB7XG4gICAgICBvcHRpb25zLmluZGVudCA9IEpTT04uc3RyaW5naWZ5KGluZGVudCk7XG4gICAgfVxuICAgIG9wdGlvbnMuaGVscGVycyA9ICdoZWxwZXJzJztcbiAgICBvcHRpb25zLnBhcnRpYWxzID0gJ3BhcnRpYWxzJztcbiAgICBvcHRpb25zLmRlY29yYXRvcnMgPSAnY29udGFpbmVyLmRlY29yYXRvcnMnO1xuXG4gICAgaWYgKCFpc0R5bmFtaWMpIHtcbiAgICAgIHBhcmFtcy51bnNoaWZ0KHRoaXMubmFtZUxvb2t1cCgncGFydGlhbHMnLCBuYW1lLCAncGFydGlhbCcpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFyYW1zLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5jb21wYXQpIHtcbiAgICAgIG9wdGlvbnMuZGVwdGhzID0gJ2RlcHRocyc7XG4gICAgfVxuICAgIG9wdGlvbnMgPSB0aGlzLm9iamVjdExpdGVyYWwob3B0aW9ucyk7XG4gICAgcGFyYW1zLnB1c2gob3B0aW9ucyk7XG5cbiAgICB0aGlzLnB1c2godGhpcy5zb3VyY2UuZnVuY3Rpb25DYWxsKCdjb250YWluZXIuaW52b2tlUGFydGlhbCcsICcnLCBwYXJhbXMpKTtcbiAgfSxcblxuICAvLyBbYXNzaWduVG9IYXNoXVxuICAvL1xuICAvLyBPbiBzdGFjaywgYmVmb3JlOiB2YWx1ZSwgLi4uLCBoYXNoLCAuLi5cbiAgLy8gT24gc3RhY2ssIGFmdGVyOiAuLi4sIGhhc2gsIC4uLlxuICAvL1xuICAvLyBQb3BzIGEgdmFsdWUgb2ZmIHRoZSBzdGFjayBhbmQgYXNzaWducyBpdCB0byB0aGUgY3VycmVudCBoYXNoXG4gIGFzc2lnblRvSGFzaDogZnVuY3Rpb24oa2V5KSB7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5wb3BTdGFjaygpLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICB0eXBlLFxuICAgICAgICBpZDtcblxuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICBpZCA9IHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICB0eXBlID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgY29udGV4dCA9IHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG5cbiAgICBsZXQgaGFzaCA9IHRoaXMuaGFzaDtcbiAgICBpZiAoY29udGV4dCkge1xuICAgICAgaGFzaC5jb250ZXh0c1trZXldID0gY29udGV4dDtcbiAgICB9XG4gICAgaWYgKHR5cGUpIHtcbiAgICAgIGhhc2gudHlwZXNba2V5XSA9IHR5cGU7XG4gICAgfVxuICAgIGlmIChpZCkge1xuICAgICAgaGFzaC5pZHNba2V5XSA9IGlkO1xuICAgIH1cbiAgICBoYXNoLnZhbHVlc1trZXldID0gdmFsdWU7XG4gIH0sXG5cbiAgcHVzaElkOiBmdW5jdGlvbih0eXBlLCBuYW1lLCBjaGlsZCkge1xuICAgIGlmICh0eXBlID09PSAnQmxvY2tQYXJhbScpIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbChcbiAgICAgICAgICAnYmxvY2tQYXJhbXNbJyArIG5hbWVbMF0gKyAnXS5wYXRoWycgKyBuYW1lWzFdICsgJ10nXG4gICAgICAgICAgKyAoY2hpbGQgPyAnICsgJyArIEpTT04uc3RyaW5naWZ5KCcuJyArIGNoaWxkKSA6ICcnKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnUGF0aEV4cHJlc3Npb24nKSB7XG4gICAgICB0aGlzLnB1c2hTdHJpbmcobmFtZSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAgICAgIHRoaXMucHVzaFN0YWNrTGl0ZXJhbCgndHJ1ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnB1c2hTdGFja0xpdGVyYWwoJ251bGwnKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gSEVMUEVSU1xuXG4gIGNvbXBpbGVyOiBKYXZhU2NyaXB0Q29tcGlsZXIsXG5cbiAgY29tcGlsZUNoaWxkcmVuOiBmdW5jdGlvbihlbnZpcm9ubWVudCwgb3B0aW9ucykge1xuICAgIGxldCBjaGlsZHJlbiA9IGVudmlyb25tZW50LmNoaWxkcmVuLCBjaGlsZCwgY29tcGlsZXI7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IGNoaWxkcmVuLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgIGNvbXBpbGVyID0gbmV3IHRoaXMuY29tcGlsZXIoKTsgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuZXctY2FwXG5cbiAgICAgIGxldCBleGlzdGluZyA9IHRoaXMubWF0Y2hFeGlzdGluZ1Byb2dyYW0oY2hpbGQpO1xuXG4gICAgICBpZiAoZXhpc3RpbmcgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmNvbnRleHQucHJvZ3JhbXMucHVzaCgnJyk7ICAgICAvLyBQbGFjZWhvbGRlciB0byBwcmV2ZW50IG5hbWUgY29uZmxpY3RzIGZvciBuZXN0ZWQgY2hpbGRyZW5cbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5jb250ZXh0LnByb2dyYW1zLmxlbmd0aDtcbiAgICAgICAgY2hpbGQuaW5kZXggPSBpbmRleDtcbiAgICAgICAgY2hpbGQubmFtZSA9ICdwcm9ncmFtJyArIGluZGV4O1xuICAgICAgICB0aGlzLmNvbnRleHQucHJvZ3JhbXNbaW5kZXhdID0gY29tcGlsZXIuY29tcGlsZShjaGlsZCwgb3B0aW9ucywgdGhpcy5jb250ZXh0LCAhdGhpcy5wcmVjb21waWxlKTtcbiAgICAgICAgdGhpcy5jb250ZXh0LmRlY29yYXRvcnNbaW5kZXhdID0gY29tcGlsZXIuZGVjb3JhdG9ycztcbiAgICAgICAgdGhpcy5jb250ZXh0LmVudmlyb25tZW50c1tpbmRleF0gPSBjaGlsZDtcblxuICAgICAgICB0aGlzLnVzZURlcHRocyA9IHRoaXMudXNlRGVwdGhzIHx8IGNvbXBpbGVyLnVzZURlcHRocztcbiAgICAgICAgdGhpcy51c2VCbG9ja1BhcmFtcyA9IHRoaXMudXNlQmxvY2tQYXJhbXMgfHwgY29tcGlsZXIudXNlQmxvY2tQYXJhbXM7XG4gICAgICAgIGNoaWxkLnVzZURlcHRocyA9IHRoaXMudXNlRGVwdGhzO1xuICAgICAgICBjaGlsZC51c2VCbG9ja1BhcmFtcyA9IHRoaXMudXNlQmxvY2tQYXJhbXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGlsZC5pbmRleCA9IGV4aXN0aW5nLmluZGV4O1xuICAgICAgICBjaGlsZC5uYW1lID0gJ3Byb2dyYW0nICsgZXhpc3RpbmcuaW5kZXg7XG5cbiAgICAgICAgdGhpcy51c2VEZXB0aHMgPSB0aGlzLnVzZURlcHRocyB8fCBleGlzdGluZy51c2VEZXB0aHM7XG4gICAgICAgIHRoaXMudXNlQmxvY2tQYXJhbXMgPSB0aGlzLnVzZUJsb2NrUGFyYW1zIHx8IGV4aXN0aW5nLnVzZUJsb2NrUGFyYW1zO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgbWF0Y2hFeGlzdGluZ1Byb2dyYW06IGZ1bmN0aW9uKGNoaWxkKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHRoaXMuY29udGV4dC5lbnZpcm9ubWVudHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGxldCBlbnZpcm9ubWVudCA9IHRoaXMuY29udGV4dC5lbnZpcm9ubWVudHNbaV07XG4gICAgICBpZiAoZW52aXJvbm1lbnQgJiYgZW52aXJvbm1lbnQuZXF1YWxzKGNoaWxkKSkge1xuICAgICAgICByZXR1cm4gZW52aXJvbm1lbnQ7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIHByb2dyYW1FeHByZXNzaW9uOiBmdW5jdGlvbihndWlkKSB7XG4gICAgbGV0IGNoaWxkID0gdGhpcy5lbnZpcm9ubWVudC5jaGlsZHJlbltndWlkXSxcbiAgICAgICAgcHJvZ3JhbVBhcmFtcyA9IFtjaGlsZC5pbmRleCwgJ2RhdGEnLCBjaGlsZC5ibG9ja1BhcmFtc107XG5cbiAgICBpZiAodGhpcy51c2VCbG9ja1BhcmFtcyB8fCB0aGlzLnVzZURlcHRocykge1xuICAgICAgcHJvZ3JhbVBhcmFtcy5wdXNoKCdibG9ja1BhcmFtcycpO1xuICAgIH1cbiAgICBpZiAodGhpcy51c2VEZXB0aHMpIHtcbiAgICAgIHByb2dyYW1QYXJhbXMucHVzaCgnZGVwdGhzJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICdjb250YWluZXIucHJvZ3JhbSgnICsgcHJvZ3JhbVBhcmFtcy5qb2luKCcsICcpICsgJyknO1xuICB9LFxuXG4gIHVzZVJlZ2lzdGVyOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLnJlZ2lzdGVyc1tuYW1lXSkge1xuICAgICAgdGhpcy5yZWdpc3RlcnNbbmFtZV0gPSB0cnVlO1xuICAgICAgdGhpcy5yZWdpc3RlcnMubGlzdC5wdXNoKG5hbWUpO1xuICAgIH1cbiAgfSxcblxuICBwdXNoOiBmdW5jdGlvbihleHByKSB7XG4gICAgaWYgKCEoZXhwciBpbnN0YW5jZW9mIExpdGVyYWwpKSB7XG4gICAgICBleHByID0gdGhpcy5zb3VyY2Uud3JhcChleHByKTtcbiAgICB9XG5cbiAgICB0aGlzLmlubGluZVN0YWNrLnB1c2goZXhwcik7XG4gICAgcmV0dXJuIGV4cHI7XG4gIH0sXG5cbiAgcHVzaFN0YWNrTGl0ZXJhbDogZnVuY3Rpb24oaXRlbSkge1xuICAgIHRoaXMucHVzaChuZXcgTGl0ZXJhbChpdGVtKSk7XG4gIH0sXG5cbiAgcHVzaFNvdXJjZTogZnVuY3Rpb24oc291cmNlKSB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIHRoaXMuc291cmNlLnB1c2goXG4gICAgICAgICAgdGhpcy5hcHBlbmRUb0J1ZmZlcih0aGlzLnNvdXJjZS5xdW90ZWRTdHJpbmcodGhpcy5wZW5kaW5nQ29udGVudCksIHRoaXMucGVuZGluZ0xvY2F0aW9uKSk7XG4gICAgICB0aGlzLnBlbmRpbmdDb250ZW50ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgIHRoaXMuc291cmNlLnB1c2goc291cmNlKTtcbiAgICB9XG4gIH0sXG5cbiAgcmVwbGFjZVN0YWNrOiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIGxldCBwcmVmaXggPSBbJygnXSxcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIGNyZWF0ZWRTdGFjayxcbiAgICAgICAgdXNlZExpdGVyYWw7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICghdGhpcy5pc0lubGluZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdyZXBsYWNlU3RhY2sgb24gbm9uLWlubGluZScpO1xuICAgIH1cblxuICAgIC8vIFdlIHdhbnQgdG8gbWVyZ2UgdGhlIGlubGluZSBzdGF0ZW1lbnQgaW50byB0aGUgcmVwbGFjZW1lbnQgc3RhdGVtZW50IHZpYSAnLCdcbiAgICBsZXQgdG9wID0gdGhpcy5wb3BTdGFjayh0cnVlKTtcblxuICAgIGlmICh0b3AgaW5zdGFuY2VvZiBMaXRlcmFsKSB7XG4gICAgICAvLyBMaXRlcmFscyBkbyBub3QgbmVlZCB0byBiZSBpbmxpbmVkXG4gICAgICBzdGFjayA9IFt0b3AudmFsdWVdO1xuICAgICAgcHJlZml4ID0gWycoJywgc3RhY2tdO1xuICAgICAgdXNlZExpdGVyYWwgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBHZXQgb3IgY3JlYXRlIHRoZSBjdXJyZW50IHN0YWNrIG5hbWUgZm9yIHVzZSBieSB0aGUgaW5saW5lXG4gICAgICBjcmVhdGVkU3RhY2sgPSB0cnVlO1xuICAgICAgbGV0IG5hbWUgPSB0aGlzLmluY3JTdGFjaygpO1xuXG4gICAgICBwcmVmaXggPSBbJygoJywgdGhpcy5wdXNoKG5hbWUpLCAnID0gJywgdG9wLCAnKSddO1xuICAgICAgc3RhY2sgPSB0aGlzLnRvcFN0YWNrKCk7XG4gICAgfVxuXG4gICAgbGV0IGl0ZW0gPSBjYWxsYmFjay5jYWxsKHRoaXMsIHN0YWNrKTtcblxuICAgIGlmICghdXNlZExpdGVyYWwpIHtcbiAgICAgIHRoaXMucG9wU3RhY2soKTtcbiAgICB9XG4gICAgaWYgKGNyZWF0ZWRTdGFjaykge1xuICAgICAgdGhpcy5zdGFja1Nsb3QtLTtcbiAgICB9XG4gICAgdGhpcy5wdXNoKHByZWZpeC5jb25jYXQoaXRlbSwgJyknKSk7XG4gIH0sXG5cbiAgaW5jclN0YWNrOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnN0YWNrU2xvdCsrO1xuICAgIGlmICh0aGlzLnN0YWNrU2xvdCA+IHRoaXMuc3RhY2tWYXJzLmxlbmd0aCkgeyB0aGlzLnN0YWNrVmFycy5wdXNoKCdzdGFjaycgKyB0aGlzLnN0YWNrU2xvdCk7IH1cbiAgICByZXR1cm4gdGhpcy50b3BTdGFja05hbWUoKTtcbiAgfSxcbiAgdG9wU3RhY2tOYW1lOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gJ3N0YWNrJyArIHRoaXMuc3RhY2tTbG90O1xuICB9LFxuICBmbHVzaElubGluZTogZnVuY3Rpb24oKSB7XG4gICAgbGV0IGlubGluZVN0YWNrID0gdGhpcy5pbmxpbmVTdGFjaztcbiAgICB0aGlzLmlubGluZVN0YWNrID0gW107XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGlubGluZVN0YWNrLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBsZXQgZW50cnkgPSBpbmxpbmVTdGFja1tpXTtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgTGl0ZXJhbCkge1xuICAgICAgICB0aGlzLmNvbXBpbGVTdGFjay5wdXNoKGVudHJ5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBzdGFjayA9IHRoaXMuaW5jclN0YWNrKCk7XG4gICAgICAgIHRoaXMucHVzaFNvdXJjZShbc3RhY2ssICcgPSAnLCBlbnRyeSwgJzsnXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVN0YWNrLnB1c2goc3RhY2spO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgaXNJbmxpbmU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmlubGluZVN0YWNrLmxlbmd0aDtcbiAgfSxcblxuICBwb3BTdGFjazogZnVuY3Rpb24od3JhcHBlZCkge1xuICAgIGxldCBpbmxpbmUgPSB0aGlzLmlzSW5saW5lKCksXG4gICAgICAgIGl0ZW0gPSAoaW5saW5lID8gdGhpcy5pbmxpbmVTdGFjayA6IHRoaXMuY29tcGlsZVN0YWNrKS5wb3AoKTtcblxuICAgIGlmICghd3JhcHBlZCAmJiAoaXRlbSBpbnN0YW5jZW9mIExpdGVyYWwpKSB7XG4gICAgICByZXR1cm4gaXRlbS52YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFpbmxpbmUpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgaWYgKCF0aGlzLnN0YWNrU2xvdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ0ludmFsaWQgc3RhY2sgcG9wJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGFja1Nsb3QtLTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgfSxcblxuICB0b3BTdGFjazogZnVuY3Rpb24oKSB7XG4gICAgbGV0IHN0YWNrID0gKHRoaXMuaXNJbmxpbmUoKSA/IHRoaXMuaW5saW5lU3RhY2sgOiB0aGlzLmNvbXBpbGVTdGFjayksXG4gICAgICAgIGl0ZW0gPSBzdGFja1tzdGFjay5sZW5ndGggLSAxXTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChpdGVtIGluc3RhbmNlb2YgTGl0ZXJhbCkge1xuICAgICAgcmV0dXJuIGl0ZW0udmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgfSxcblxuICBjb250ZXh0TmFtZTogZnVuY3Rpb24oY29udGV4dCkge1xuICAgIGlmICh0aGlzLnVzZURlcHRocyAmJiBjb250ZXh0KSB7XG4gICAgICByZXR1cm4gJ2RlcHRoc1snICsgY29udGV4dCArICddJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICdkZXB0aCcgKyBjb250ZXh0O1xuICAgIH1cbiAgfSxcblxuICBxdW90ZWRTdHJpbmc6IGZ1bmN0aW9uKHN0cikge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZS5xdW90ZWRTdHJpbmcoc3RyKTtcbiAgfSxcblxuICBvYmplY3RMaXRlcmFsOiBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdGhpcy5zb3VyY2Uub2JqZWN0TGl0ZXJhbChvYmopO1xuICB9LFxuXG4gIGFsaWFzYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGxldCByZXQgPSB0aGlzLmFsaWFzZXNbbmFtZV07XG4gICAgaWYgKHJldCkge1xuICAgICAgcmV0LnJlZmVyZW5jZUNvdW50Kys7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIHJldCA9IHRoaXMuYWxpYXNlc1tuYW1lXSA9IHRoaXMuc291cmNlLndyYXAobmFtZSk7XG4gICAgcmV0LmFsaWFzYWJsZSA9IHRydWU7XG4gICAgcmV0LnJlZmVyZW5jZUNvdW50ID0gMTtcblxuICAgIHJldHVybiByZXQ7XG4gIH0sXG5cbiAgc2V0dXBIZWxwZXI6IGZ1bmN0aW9uKHBhcmFtU2l6ZSwgbmFtZSwgYmxvY2tIZWxwZXIpIHtcbiAgICBsZXQgcGFyYW1zID0gW10sXG4gICAgICAgIHBhcmFtc0luaXQgPSB0aGlzLnNldHVwSGVscGVyQXJncyhuYW1lLCBwYXJhbVNpemUsIHBhcmFtcywgYmxvY2tIZWxwZXIpO1xuICAgIGxldCBmb3VuZEhlbHBlciA9IHRoaXMubmFtZUxvb2t1cCgnaGVscGVycycsIG5hbWUsICdoZWxwZXInKSxcbiAgICAgICAgY2FsbENvbnRleHQgPSB0aGlzLmFsaWFzYWJsZShgJHt0aGlzLmNvbnRleHROYW1lKDApfSAhPSBudWxsID8gJHt0aGlzLmNvbnRleHROYW1lKDApfSA6IHt9YCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFyYW1zOiBwYXJhbXMsXG4gICAgICBwYXJhbXNJbml0OiBwYXJhbXNJbml0LFxuICAgICAgbmFtZTogZm91bmRIZWxwZXIsXG4gICAgICBjYWxsUGFyYW1zOiBbY2FsbENvbnRleHRdLmNvbmNhdChwYXJhbXMpXG4gICAgfTtcbiAgfSxcblxuICBzZXR1cFBhcmFtczogZnVuY3Rpb24oaGVscGVyLCBwYXJhbVNpemUsIHBhcmFtcykge1xuICAgIGxldCBvcHRpb25zID0ge30sXG4gICAgICAgIGNvbnRleHRzID0gW10sXG4gICAgICAgIHR5cGVzID0gW10sXG4gICAgICAgIGlkcyA9IFtdLFxuICAgICAgICBvYmplY3RBcmdzID0gIXBhcmFtcyxcbiAgICAgICAgcGFyYW07XG5cbiAgICBpZiAob2JqZWN0QXJncykge1xuICAgICAgcGFyYW1zID0gW107XG4gICAgfVxuXG4gICAgb3B0aW9ucy5uYW1lID0gdGhpcy5xdW90ZWRTdHJpbmcoaGVscGVyKTtcbiAgICBvcHRpb25zLmhhc2ggPSB0aGlzLnBvcFN0YWNrKCk7XG5cbiAgICBpZiAodGhpcy50cmFja0lkcykge1xuICAgICAgb3B0aW9ucy5oYXNoSWRzID0gdGhpcy5wb3BTdGFjaygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdHJpbmdQYXJhbXMpIHtcbiAgICAgIG9wdGlvbnMuaGFzaFR5cGVzID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgb3B0aW9ucy5oYXNoQ29udGV4dHMgPSB0aGlzLnBvcFN0YWNrKCk7XG4gICAgfVxuXG4gICAgbGV0IGludmVyc2UgPSB0aGlzLnBvcFN0YWNrKCksXG4gICAgICAgIHByb2dyYW0gPSB0aGlzLnBvcFN0YWNrKCk7XG5cbiAgICAvLyBBdm9pZCBzZXR0aW5nIGZuIGFuZCBpbnZlcnNlIGlmIG5laXRoZXIgYXJlIHNldC4gVGhpcyBhbGxvd3NcbiAgICAvLyBoZWxwZXJzIHRvIGRvIGEgY2hlY2sgZm9yIGBpZiAob3B0aW9ucy5mbilgXG4gICAgaWYgKHByb2dyYW0gfHwgaW52ZXJzZSkge1xuICAgICAgb3B0aW9ucy5mbiA9IHByb2dyYW0gfHwgJ2NvbnRhaW5lci5ub29wJztcbiAgICAgIG9wdGlvbnMuaW52ZXJzZSA9IGludmVyc2UgfHwgJ2NvbnRhaW5lci5ub29wJztcbiAgICB9XG5cbiAgICAvLyBUaGUgcGFyYW1ldGVycyBnbyBvbiB0byB0aGUgc3RhY2sgaW4gb3JkZXIgKG1ha2luZyBzdXJlIHRoYXQgdGhleSBhcmUgZXZhbHVhdGVkIGluIG9yZGVyKVxuICAgIC8vIHNvIHdlIG5lZWQgdG8gcG9wIHRoZW0gb2ZmIHRoZSBzdGFjayBpbiByZXZlcnNlIG9yZGVyXG4gICAgbGV0IGkgPSBwYXJhbVNpemU7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgcGFyYW0gPSB0aGlzLnBvcFN0YWNrKCk7XG4gICAgICBwYXJhbXNbaV0gPSBwYXJhbTtcblxuICAgICAgaWYgKHRoaXMudHJhY2tJZHMpIHtcbiAgICAgICAgaWRzW2ldID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICAgIHR5cGVzW2ldID0gdGhpcy5wb3BTdGFjaygpO1xuICAgICAgICBjb250ZXh0c1tpXSA9IHRoaXMucG9wU3RhY2soKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob2JqZWN0QXJncykge1xuICAgICAgb3B0aW9ucy5hcmdzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheShwYXJhbXMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRyYWNrSWRzKSB7XG4gICAgICBvcHRpb25zLmlkcyA9IHRoaXMuc291cmNlLmdlbmVyYXRlQXJyYXkoaWRzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc3RyaW5nUGFyYW1zKSB7XG4gICAgICBvcHRpb25zLnR5cGVzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheSh0eXBlcyk7XG4gICAgICBvcHRpb25zLmNvbnRleHRzID0gdGhpcy5zb3VyY2UuZ2VuZXJhdGVBcnJheShjb250ZXh0cyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kYXRhKSB7XG4gICAgICBvcHRpb25zLmRhdGEgPSAnZGF0YSc7XG4gICAgfVxuICAgIGlmICh0aGlzLnVzZUJsb2NrUGFyYW1zKSB7XG4gICAgICBvcHRpb25zLmJsb2NrUGFyYW1zID0gJ2Jsb2NrUGFyYW1zJztcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH0sXG5cbiAgc2V0dXBIZWxwZXJBcmdzOiBmdW5jdGlvbihoZWxwZXIsIHBhcmFtU2l6ZSwgcGFyYW1zLCB1c2VSZWdpc3Rlcikge1xuICAgIGxldCBvcHRpb25zID0gdGhpcy5zZXR1cFBhcmFtcyhoZWxwZXIsIHBhcmFtU2l6ZSwgcGFyYW1zKTtcbiAgICBvcHRpb25zID0gdGhpcy5vYmplY3RMaXRlcmFsKG9wdGlvbnMpO1xuICAgIGlmICh1c2VSZWdpc3Rlcikge1xuICAgICAgdGhpcy51c2VSZWdpc3Rlcignb3B0aW9ucycpO1xuICAgICAgcGFyYW1zLnB1c2goJ29wdGlvbnMnKTtcbiAgICAgIHJldHVybiBbJ29wdGlvbnM9Jywgb3B0aW9uc107XG4gICAgfSBlbHNlIGlmIChwYXJhbXMpIHtcbiAgICAgIHBhcmFtcy5wdXNoKG9wdGlvbnMpO1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9XG4gIH1cbn07XG5cblxuKGZ1bmN0aW9uKCkge1xuICBjb25zdCByZXNlcnZlZFdvcmRzID0gKFxuICAgICdicmVhayBlbHNlIG5ldyB2YXInICtcbiAgICAnIGNhc2UgZmluYWxseSByZXR1cm4gdm9pZCcgK1xuICAgICcgY2F0Y2ggZm9yIHN3aXRjaCB3aGlsZScgK1xuICAgICcgY29udGludWUgZnVuY3Rpb24gdGhpcyB3aXRoJyArXG4gICAgJyBkZWZhdWx0IGlmIHRocm93JyArXG4gICAgJyBkZWxldGUgaW4gdHJ5JyArXG4gICAgJyBkbyBpbnN0YW5jZW9mIHR5cGVvZicgK1xuICAgICcgYWJzdHJhY3QgZW51bSBpbnQgc2hvcnQnICtcbiAgICAnIGJvb2xlYW4gZXhwb3J0IGludGVyZmFjZSBzdGF0aWMnICtcbiAgICAnIGJ5dGUgZXh0ZW5kcyBsb25nIHN1cGVyJyArXG4gICAgJyBjaGFyIGZpbmFsIG5hdGl2ZSBzeW5jaHJvbml6ZWQnICtcbiAgICAnIGNsYXNzIGZsb2F0IHBhY2thZ2UgdGhyb3dzJyArXG4gICAgJyBjb25zdCBnb3RvIHByaXZhdGUgdHJhbnNpZW50JyArXG4gICAgJyBkZWJ1Z2dlciBpbXBsZW1lbnRzIHByb3RlY3RlZCB2b2xhdGlsZScgK1xuICAgICcgZG91YmxlIGltcG9ydCBwdWJsaWMgbGV0IHlpZWxkIGF3YWl0JyArXG4gICAgJyBudWxsIHRydWUgZmFsc2UnXG4gICkuc3BsaXQoJyAnKTtcblxuICBjb25zdCBjb21waWxlcldvcmRzID0gSmF2YVNjcmlwdENvbXBpbGVyLlJFU0VSVkVEX1dPUkRTID0ge307XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSByZXNlcnZlZFdvcmRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGNvbXBpbGVyV29yZHNbcmVzZXJ2ZWRXb3Jkc1tpXV0gPSB0cnVlO1xuICB9XG59KCkpO1xuXG5KYXZhU2NyaXB0Q29tcGlsZXIuaXNWYWxpZEphdmFTY3JpcHRWYXJpYWJsZU5hbWUgPSBmdW5jdGlvbihuYW1lKSB7XG4gIHJldHVybiAhSmF2YVNjcmlwdENvbXBpbGVyLlJFU0VSVkVEX1dPUkRTW25hbWVdICYmICgvXlthLXpBLVpfJF1bMC05YS16QS1aXyRdKiQvKS50ZXN0KG5hbWUpO1xufTtcblxuZnVuY3Rpb24gc3RyaWN0TG9va3VwKHJlcXVpcmVUZXJtaW5hbCwgY29tcGlsZXIsIHBhcnRzLCB0eXBlKSB7XG4gIGxldCBzdGFjayA9IGNvbXBpbGVyLnBvcFN0YWNrKCksXG4gICAgICBpID0gMCxcbiAgICAgIGxlbiA9IHBhcnRzLmxlbmd0aDtcbiAgaWYgKHJlcXVpcmVUZXJtaW5hbCkge1xuICAgIGxlbi0tO1xuICB9XG5cbiAgZm9yICg7IGkgPCBsZW47IGkrKykge1xuICAgIHN0YWNrID0gY29tcGlsZXIubmFtZUxvb2t1cChzdGFjaywgcGFydHNbaV0sIHR5cGUpO1xuICB9XG5cbiAgaWYgKHJlcXVpcmVUZXJtaW5hbCkge1xuICAgIHJldHVybiBbY29tcGlsZXIuYWxpYXNhYmxlKCdjb250YWluZXIuc3RyaWN0JyksICcoJywgc3RhY2ssICcsICcsIGNvbXBpbGVyLnF1b3RlZFN0cmluZyhwYXJ0c1tpXSksICcpJ107XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0YWNrO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEphdmFTY3JpcHRDb21waWxlcjtcbiJdfQ== +; +define('handlebars',['exports', 'module', './handlebars.runtime', './handlebars/compiler/ast', './handlebars/compiler/base', './handlebars/compiler/compiler', './handlebars/compiler/javascript-compiler', './handlebars/compiler/visitor', './handlebars/no-conflict'], function (exports, module, _handlebarsRuntime, _handlebarsCompilerAst, _handlebarsCompilerBase, _handlebarsCompilerCompiler, _handlebarsCompilerJavascriptCompiler, _handlebarsCompilerVisitor, _handlebarsNoConflict) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _runtime = _interopRequireDefault(_handlebarsRuntime); + + // Compiler imports + + var _AST = _interopRequireDefault(_handlebarsCompilerAst); + + var _JavaScriptCompiler = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler); + + var _Visitor = _interopRequireDefault(_handlebarsCompilerVisitor); + + var _noConflict = _interopRequireDefault(_handlebarsNoConflict); + + var _create = _runtime['default'].create; + function create() { + var hb = _create(); + + hb.compile = function (input, options) { + return _handlebarsCompilerCompiler.compile(input, options, hb); + }; + hb.precompile = function (input, options) { + return _handlebarsCompilerCompiler.precompile(input, options, hb); + }; + + hb.AST = _AST['default']; + hb.Compiler = _handlebarsCompilerCompiler.Compiler; + hb.JavaScriptCompiler = _JavaScriptCompiler['default']; + hb.Parser = _handlebarsCompilerBase.parser; + hb.parse = _handlebarsCompilerBase.parse; + + return hb; + } + + var inst = create(); + inst.create = create; + + _noConflict['default'](inst); + + inst.Visitor = _Visitor['default']; + + inst['default'] = inst; + + module.exports = inst; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFXQSxNQUFJLE9BQU8sR0FBRyxvQkFBUSxNQUFNLENBQUM7QUFDN0IsV0FBUyxNQUFNLEdBQUc7QUFDaEIsUUFBSSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7O0FBRW5CLE1BQUUsQ0FBQyxPQUFPLEdBQUcsVUFBUyxLQUFLLEVBQUUsT0FBTyxFQUFFO0FBQ3BDLGFBQU8sNEJBWFEsT0FBTyxDQVdQLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDcEMsQ0FBQztBQUNGLE1BQUUsQ0FBQyxVQUFVLEdBQUcsVUFBUyxLQUFLLEVBQUUsT0FBTyxFQUFFO0FBQ3ZDLGFBQU8sNEJBZGlCLFVBQVUsQ0FjaEIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztLQUN2QyxDQUFDOztBQUVGLE1BQUUsQ0FBQyxHQUFHLGtCQUFNLENBQUM7QUFDYixNQUFFLENBQUMsUUFBUSwrQkFsQkosUUFBUSxBQWtCTyxDQUFDO0FBQ3ZCLE1BQUUsQ0FBQyxrQkFBa0IsaUNBQXFCLENBQUM7QUFDM0MsTUFBRSxDQUFDLE1BQU0sMkJBckJGLE1BQU0sQUFxQkssQ0FBQztBQUNuQixNQUFFLENBQUMsS0FBSywyQkF0QmlCLEtBQUssQUFzQmQsQ0FBQzs7QUFFakIsV0FBTyxFQUFFLENBQUM7R0FDWDs7QUFFRCxNQUFJLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQztBQUNwQixNQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7QUFFckIseUJBQVcsSUFBSSxDQUFDLENBQUM7O0FBRWpCLE1BQUksQ0FBQyxPQUFPLHNCQUFVLENBQUM7O0FBRXZCLE1BQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7O21CQUVSLElBQUkiLCJmaWxlIjoiaGFuZGxlYmFycy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBydW50aW1lIGZyb20gJy4vaGFuZGxlYmFycy5ydW50aW1lJztcblxuLy8gQ29tcGlsZXIgaW1wb3J0c1xuaW1wb3J0IEFTVCBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvYXN0JztcbmltcG9ydCB7IHBhcnNlciBhcyBQYXJzZXIsIHBhcnNlIH0gZnJvbSAnLi9oYW5kbGViYXJzL2NvbXBpbGVyL2Jhc2UnO1xuaW1wb3J0IHsgQ29tcGlsZXIsIGNvbXBpbGUsIHByZWNvbXBpbGUgfSBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvY29tcGlsZXInO1xuaW1wb3J0IEphdmFTY3JpcHRDb21waWxlciBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvamF2YXNjcmlwdC1jb21waWxlcic7XG5pbXBvcnQgVmlzaXRvciBmcm9tICcuL2hhbmRsZWJhcnMvY29tcGlsZXIvdmlzaXRvcic7XG5cbmltcG9ydCBub0NvbmZsaWN0IGZyb20gJy4vaGFuZGxlYmFycy9uby1jb25mbGljdCc7XG5cbmxldCBfY3JlYXRlID0gcnVudGltZS5jcmVhdGU7XG5mdW5jdGlvbiBjcmVhdGUoKSB7XG4gIGxldCBoYiA9IF9jcmVhdGUoKTtcblxuICBoYi5jb21waWxlID0gZnVuY3Rpb24oaW5wdXQsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gY29tcGlsZShpbnB1dCwgb3B0aW9ucywgaGIpO1xuICB9O1xuICBoYi5wcmVjb21waWxlID0gZnVuY3Rpb24oaW5wdXQsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gcHJlY29tcGlsZShpbnB1dCwgb3B0aW9ucywgaGIpO1xuICB9O1xuXG4gIGhiLkFTVCA9IEFTVDtcbiAgaGIuQ29tcGlsZXIgPSBDb21waWxlcjtcbiAgaGIuSmF2YVNjcmlwdENvbXBpbGVyID0gSmF2YVNjcmlwdENvbXBpbGVyO1xuICBoYi5QYXJzZXIgPSBQYXJzZXI7XG4gIGhiLnBhcnNlID0gcGFyc2U7XG5cbiAgcmV0dXJuIGhiO1xufVxuXG5sZXQgaW5zdCA9IGNyZWF0ZSgpO1xuaW5zdC5jcmVhdGUgPSBjcmVhdGU7XG5cbm5vQ29uZmxpY3QoaW5zdCk7XG5cbmluc3QuVmlzaXRvciA9IFZpc2l0b3I7XG5cbmluc3RbJ2RlZmF1bHQnXSA9IGluc3Q7XG5cbmV4cG9ydCBkZWZhdWx0IGluc3Q7XG4iXX0= +; diff --git a/hm_sunwell/node_modules/handlebars/dist/handlebars.amd.min.js b/hm_sunwell/node_modules/handlebars/dist/handlebars.amd.min.js new file mode 100644 index 0000000..ed48300 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/handlebars.amd.min.js @@ -0,0 +1,29 @@ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +define("handlebars/utils",["exports"],function(a){"use strict";function b(a){return j[a]}function c(a){for(var b=1;b":">",'"':""","'":"'","`":"`","=":"="},k=/[&<>"'`=]/g,l=/[&<>"'`=]/,m=Object.prototype.toString;a.toString=m;var n=function(a){return"function"==typeof a};n(/x/)&&(a.isFunction=n=function(a){return"function"==typeof a&&"[object Function]"===m.call(a)}),a.isFunction=n;var o=Array.isArray||function(a){return!(!a||"object"!=typeof a)&&"[object Array]"===m.call(a)};a.isArray=o}),define("handlebars/exception",["exports","module"],function(a,b){"use strict";function c(a,b){var e=b&&b.loc,f=void 0,g=void 0;e&&(f=e.start.line,g=e.start.column,a+=" - "+f+":"+g);for(var h=Error.prototype.constructor.call(this,a),i=0;i0?(d.ids&&(d.ids=[d.name]),a.helpers.each(b,d)):e(this);if(d.data&&d.ids){var g=c.createFrame(d.data);g.contextPath=c.appendContextPath(d.data.contextPath,d.name),d={data:g}}return f(b,d)})}}),define("handlebars/helpers/each",["exports","module","../utils","../exception"],function(a,b,c,d){"use strict";function e(a){return a&&a.__esModule?a:{"default":a}}var f=e(d);b.exports=function(a){a.registerHelper("each",function(a,b){function d(b,d,f){j&&(j.key=b,j.index=d,j.first=0===d,j.last=!!f,k&&(j.contextPath=k+b)),i+=e(a[b],{data:j,blockParams:c.blockParams([a[b],b],[k+b,null])})}if(!b)throw new f["default"]("Must pass iterator to #each");var e=b.fn,g=b.inverse,h=0,i="",j=void 0,k=void 0;if(b.data&&b.ids&&(k=c.appendContextPath(b.data.contextPath,b.ids[0])+"."),c.isFunction(a)&&(a=a.call(this)),b.data&&(j=c.createFrame(b.data)),a&&"object"==typeof a)if(c.isArray(a))for(var l=a.length;h=0?b:parseInt(a,10)}return a},log:function(a){if(a=d.lookupLevel(a),"undefined"!=typeof console&&d.lookupLevel(d.level)<=a){var b=d.methodMap[a];console[b]||(b="log");for(var c=arguments.length,e=Array(c>1?c-1:0),f=1;f= 2.0.0-beta.1",7:">= 4.0.0"};a.REVISION_CHANGES=m;var n="[object Object]";h.prototype={constructor:h,logger:j["default"],log:j["default"].log,registerHelper:function(a,c){if(b.toString.call(a)===n){if(c)throw new i["default"]("Arg not supported with multiple helpers");b.extend(this.helpers,a)}else this.helpers[a]=c},unregisterHelper:function(a){delete this.helpers[a]},registerPartial:function(a,c){if(b.toString.call(a)===n)b.extend(this.partials,a);else{if("undefined"==typeof c)throw new i["default"]('Attempting to register a partial called "'+a+'" as undefined');this.partials[a]=c}},unregisterPartial:function(a){delete this.partials[a]},registerDecorator:function(a,c){if(b.toString.call(a)===n){if(c)throw new i["default"]("Arg not supported with multiple decorators");b.extend(this.decorators,a)}else this.decorators[a]=c},unregisterDecorator:function(a){delete this.decorators[a]}};var o=j["default"].log;a.log=o,a.createFrame=b.createFrame,a.logger=j["default"]}),define("handlebars/safe-string",["exports","module"],function(a,b){"use strict";function c(a){this.string=a}c.prototype.toString=c.prototype.toHTML=function(){return""+this.string},b.exports=c}),define("handlebars/runtime",["exports","./utils","./exception","./base"],function(a,b,c,d){"use strict";function e(a){return a&&a.__esModule?a:{"default":a}}function f(a){var b=a&&a[0]||1,c=d.COMPILER_REVISION;if(b!==c){if(b2&&v.push("'"+this.terminals_[s]+"'");x=this.lexer.showPosition?"Parse error on line "+(i+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+v.join(", ")+", got '"+(this.terminals_[n]||n)+"'":"Parse error on line "+(i+1)+": Unexpected "+(1==n?"end of input":"'"+(this.terminals_[n]||n)+"'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[n]||n,line:this.lexer.yylineno,loc:l,expected:v})}}if(q[0]instanceof Array&&q.length>1)throw new Error("Parse Error: multiple actions possible at state: "+p+", token: "+n);switch(q[0]){case 1:d.push(n),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(q[1]),n=null,o?(n=o,o=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,l=this.lexer.yylloc,k>0&&k--);break;case 2:if(t=this.productions_[q[1]][1],w.$=e[e.length-t],w._$={first_line:f[f.length-(t||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(t||1)].first_column,last_column:f[f.length-1].last_column},m&&(w._$.range=[f[f.length-(t||1)].range[0],f[f.length-1].range[1]]),r=this.performAction.call(w,h,j,i,this.yy,q[1],e,f),"undefined"!=typeof r)return r;t&&(d=d.slice(0,-1*t*2),e=e.slice(0,-1*t),f=f.slice(0,-1*t)),d.push(this.productions_[q[1]][0]),e.push(w.$),f.push(w._$),u=g[d[d.length-2]][d[d.length-1]],d.push(u);break;case 3:return!0}}return!0}},c=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a){return this._input=a,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\r\n?|\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b-1),this.offset-=b;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this},more:function(){return this._more=!0,this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d,e;this._more||(this.yytext="",this.match="");for(var f=this._currentRules(),g=0;gb[0].length)||(b=c,d=g,this.options.flex));g++);return b?(e=b[0].match(/(?:\r\n?|\n).*/g),e&&(this.yylineno+=e.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:e?e[e.length-1].length-e[e.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],a=this.performAction.call(this,this.yy,this,f[d],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),a?a:void 0):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return"undefined"!=typeof a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(a){this.begin(a)}};return a.options={},a.performAction=function(a,b,c,d){function e(a,c){return b.yytext=b.yytext.substr(a,b.yyleng-c)}switch(c){case 0:if("\\\\"===b.yytext.slice(-2)?(e(0,1),this.begin("mu")):"\\"===b.yytext.slice(-1)?(e(0,1),this.begin("emu")):this.begin("mu"),b.yytext)return 15;break;case 1:return 15;case 2:return this.popState(),15;case 3:return this.begin("raw"),15;case 4:return this.popState(),"raw"===this.conditionStack[this.conditionStack.length-1]?15:(b.yytext=b.yytext.substr(5,b.yyleng-9),"END_RAW_BLOCK");case 5:return 15;case 6:return this.popState(),14;case 7:return 65;case 8:return 68;case 9:return 19;case 10:return this.popState(),this.begin("raw"),23;case 11:return 55;case 12:return 60;case 13:return 29;case 14:return 47;case 15:return this.popState(),44;case 16:return this.popState(),44;case 17:return 34;case 18:return 39;case 19:return 51;case 20:return 48;case 21:this.unput(b.yytext),this.popState(),this.begin("com");break;case 22:return this.popState(),14;case 23:return 48;case 24:return 73;case 25:return 72;case 26:return 72;case 27:return 87;case 28:break;case 29:return this.popState(),54;case 30:return this.popState(),33;case 31:return b.yytext=e(1,2).replace(/\\"/g,'"'),80;case 32:return b.yytext=e(1,2).replace(/\\'/g,"'"),80;case 33:return 85;case 34:return 82;case 35:return 82;case 36:return 83;case 37:return 84;case 38:return 81;case 39:return 75;case 40:return 77;case 41:return 72;case 42:return b.yytext=b.yytext.replace(/\\([\\\]])/g,"$1"),72;case 43:return"INVALID";case 44:return 5}},a.rules=[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{(?=[^\/]))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#>)/,/^(?:\{\{(~)?#\*?)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?\*?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:undefined(?=([~}\s)])))/,/^(?:null(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[(\\\]|[^\]])*\])/,/^(?:.)/,/^(?:$)/],a.conditions={mu:{rules:[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[6],inclusive:!1},raw:{rules:[3,4,5],inclusive:!1},INITIAL:{rules:[0,1,44],inclusive:!0}},a}();return b.lexer=c,a.prototype=b,b.Parser=a,new a}();a.__esModule=!0,a["default"]=b}),define("handlebars/compiler/visitor",["exports","module","../exception"],function(a,b,c){"use strict";function d(a){return a&&a.__esModule?a:{"default":a}}function e(){this.parents=[]}function f(a){this.acceptRequired(a,"path"),this.acceptArray(a.params),this.acceptKey(a,"hash")}function g(a){f.call(this,a),this.acceptKey(a,"program"),this.acceptKey(a,"inverse")}function h(a){this.acceptRequired(a,"name"),this.acceptArray(a.params),this.acceptKey(a,"hash")}var i=d(c);e.prototype={constructor:e,mutating:!1,acceptKey:function(a,b){var c=this.accept(a[b]);if(this.mutating){if(c&&!e.prototype[c.type])throw new i["default"]('Unexpected node type "'+c.type+'" found when accepting '+b+" on "+a.type);a[b]=c}},acceptRequired:function(a,b){if(this.acceptKey(a,b),!a[b])throw new i["default"](a.type+" requires "+b)},acceptArray:function(a){for(var b=0,c=a.length;b0)throw new o["default"]("Invalid path: "+d,{loc:c});".."===j&&(f++,g+="../")}}return{type:"PathExpression",data:a,depth:f,parts:e,original:d,loc:c}}function j(a,b,c,d,e,f){var g=d.charAt(3)||d.charAt(2),h="{"!==g&&"&"!==g,i=/\*/.test(d);return{type:i?"Decorator":"MustacheStatement",path:a,params:b,hash:c,escaped:h,strip:e,loc:this.locInfo(f)}}function k(a,b,c,e){d(a,c),e=this.locInfo(e);var f={type:"Program",body:b,strip:{},loc:e};return{type:"BlockStatement",path:a.path,params:a.params,hash:a.hash,program:f,openStrip:{},inverseStrip:{},closeStrip:{},loc:e}}function l(a,b,c,e,f,g){e&&e.path&&d(a,e);var h=/\*/.test(a.open);b.blockParams=a.blockParams;var i=void 0,j=void 0;if(c){if(h)throw new o["default"]("Unexpected inverse block on decorator",c);c.chain&&(c.program.body[0].closeStrip=e.strip),j=c.strip,i=c.program}return f&&(f=i,i=b,b=f),{type:h?"DecoratorBlock":"BlockStatement",path:a.path,params:a.params,hash:a.hash,program:b,inverse:i,openStrip:a.strip,inverseStrip:j,closeStrip:e&&e.strip,loc:this.locInfo(g)}}function m(a,b){if(!b&&a.length){var c=a[0].loc,d=a[a.length-1].loc;c&&d&&(b={source:c.source,start:{line:c.start.line,column:c.start.column},end:{line:d.end.line,column:d.end.column}})}return{type:"Program",body:a,strip:{},loc:b}}function n(a,b,c,e){return d(a,c),{type:"PartialBlockStatement",name:a.path,params:a.params,hash:a.hash,program:b,openStrip:a.strip,closeStrip:c&&c.strip,loc:this.locInfo(e)}}a.__esModule=!0,a.SourceLocation=e,a.id=f,a.stripFlags=g,a.stripComment=h,a.preparePath=i,a.prepareMustache=j,a.prepareRawBlock=k,a.prepareBlock=l,a.prepareProgram=m,a.preparePartialBlock=n;var o=c(b)}),define("handlebars/compiler/base",["exports","./parser","./whitespace-control","./helpers","../utils"],function(a,b,c,d,e){"use strict";function f(a){return a&&a.__esModule?a:{"default":a}}function g(a,b){if("Program"===a.type)return a;h["default"].yy=j,j.locInfo=function(a){return new j.SourceLocation(b&&b.srcName,a)};var c=new i["default"](b);return c.accept(h["default"].parse(a))}a.__esModule=!0,a.parse=g;var h=f(b),i=f(c);a.parser=h["default"];var j={};e.extend(j,d)}),define("handlebars/compiler/compiler",["exports","../exception","../utils","./ast"],function(a,b,c,d){"use strict";function e(a){return a&&a.__esModule?a:{"default":a}}function f(){}function g(a,b,c){if(null==a||"string"!=typeof a&&"Program"!==a.type)throw new k["default"]("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+a);b=b||{},"data"in b||(b.data=!0),b.compat&&(b.useDepths=!0);var d=c.parse(a,b),e=(new c.Compiler).compile(d,b);return(new c.JavaScriptCompiler).compile(e,b)}function h(a,b,c){function d(){var d=c.parse(a,b),e=(new c.Compiler).compile(d,b),f=(new c.JavaScriptCompiler).compile(e,b,void 0,!0);return c.template(f)}function e(a,b){return f||(f=d()),f.call(this,a,b)}if(void 0===b&&(b={}),null==a||"string"!=typeof a&&"Program"!==a.type)throw new k["default"]("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+a);"data"in b||(b.data=!0),b.compat&&(b.useDepths=!0);var f=void 0;return e._setup=function(a){return f||(f=d()),f._setup(a)},e._child=function(a,b,c,e){return f||(f=d()),f._child(a,b,c,e)},e}function i(a,b){if(a===b)return!0;if(c.isArray(a)&&c.isArray(b)&&a.length===b.length){for(var d=0;d1)throw new k["default"]("Unsupported number of partial arguments: "+c.length,a);c.length||(this.options.explicitPartialContext?this.opcode("pushLiteral","undefined"):c.push({type:"PathExpression",parts:[],depth:0}));var d=a.name.original,e="SubExpression"===a.name.type;e&&this.accept(a.name),this.setupFullMustacheParams(a,b,void 0,!0);var f=a.indent||"";this.options.preventIndent&&f&&(this.opcode("appendContent",f),f=""),this.opcode("invokePartial",e,d,f),this.opcode("append")},PartialBlockStatement:function(a){this.PartialStatement(a)},MustacheStatement:function(a){this.SubExpression(a),a.escaped&&!this.options.noEscape?this.opcode("appendEscaped"):this.opcode("append")},Decorator:function(a){this.DecoratorBlock(a)},ContentStatement:function(a){a.value&&this.opcode("appendContent",a.value)},CommentStatement:function(){},SubExpression:function(a){j(a);var b=this.classifySexpr(a);"simple"===b?this.simpleSexpr(a):"helper"===b?this.helperSexpr(a):this.ambiguousSexpr(a)},ambiguousSexpr:function(a,b,c){var d=a.path,e=d.parts[0],f=null!=b||null!=c;this.opcode("getContext",d.depth),this.opcode("pushProgram",b),this.opcode("pushProgram",c),d.strict=!0,this.accept(d),this.opcode("invokeAmbiguous",e,f)},simpleSexpr:function(a){var b=a.path;b.strict=!0,this.accept(b),this.opcode("resolvePossibleLambda")},helperSexpr:function(a,b,c){var d=this.setupFullMustacheParams(a,b,c),e=a.path,f=e.parts[0];if(this.options.knownHelpers[f])this.opcode("invokeKnownHelper",d.length,f);else{if(this.options.knownHelpersOnly)throw new k["default"]("You specified knownHelpersOnly, but used the unknown helper "+f,a);e.strict=!0,e.falsy=!0,this.accept(e),this.opcode("invokeHelper",d.length,e.original,l["default"].helpers.simpleId(e))}},PathExpression:function(a){this.addDepth(a.depth),this.opcode("getContext",a.depth);var b=a.parts[0],c=l["default"].helpers.scopedId(a),d=!a.depth&&!c&&this.blockParamIndex(b);d?this.opcode("lookupBlockParam",d,a.parts):b?a.data?(this.options.data=!0,this.opcode("lookupData",a.depth,a.parts,a.strict)):this.opcode("lookupOnContext",a.parts,a.falsy,a.strict,c):this.opcode("pushContext")},StringLiteral:function(a){this.opcode("pushString",a.value)},NumberLiteral:function(a){this.opcode("pushLiteral",a.value)},BooleanLiteral:function(a){this.opcode("pushLiteral",a.value)},UndefinedLiteral:function(){this.opcode("pushLiteral","undefined")},NullLiteral:function(){this.opcode("pushLiteral","null")},Hash:function(a){var b=a.pairs,c=0,d=b.length;for(this.opcode("pushHash");c=0)return[b,f]}}}}),define("handlebars/compiler/code-gen",["exports","module","../utils"],function(a,b,c){"use strict";function d(a,b,d){if(c.isArray(a)){for(var e=[],f=0,g=a.length;f0&&(b+=", "+c.join(", "));var d=0;for(var e in this.aliases){var f=this.aliases[e];this.aliases.hasOwnProperty(e)&&f.children&&f.referenceCount>1&&(b+=", alias"+ ++d+"="+e,f.children[0]="alias"+d)}var g=["container","depth0","helpers","partials","data"];(this.useBlockParams||this.useDepths)&&g.push("blockParams"),this.useDepths&&g.push("depths");var h=this.mergeSource(b);return a?(g.push(h),Function.apply(this,g)):this.source.wrap(["function(",g.join(","),") {\n ",h,"}"])},mergeSource:function(a){var b=this.environment.isSimple,c=!this.forceBuffer,d=void 0,e=void 0,f=void 0,g=void 0;return this.source.each(function(a){a.appendToBuffer?(f?a.prepend(" + "):f=a,g=a):(f&&(e?f.prepend("buffer += "):d=!0,g.add(";"),f=g=void 0),e=!0,b||(c=!1))}),c?f?(f.prepend("return "),g.add(";")):e||this.source.push('return "";'):(a+=", buffer = "+(d?"":this.initializeBuffer()),f?(f.prepend("return buffer + "),g.add(";")):this.source.push("return buffer;")),a&&this.source.prepend("var "+a.substring(2)+(d?"":";\n")),this.source.merge()},blockValue:function(a){var b=this.aliasable("helpers.blockHelperMissing"),c=[this.contextName(0)];this.setupHelperArgs(a,0,c);var d=this.popStack();c.splice(1,0,d),this.push(this.source.functionCall(b,"call",c))},ambiguousBlockValue:function(){var a=this.aliasable("helpers.blockHelperMissing"),b=[this.contextName(0)];this.setupHelperArgs("",0,b,!0),this.flushInline();var c=this.topStack();b.splice(1,0,c),this.pushSource(["if (!",this.lastHelper,") { ",c," = ",this.source.functionCall(a,"call",b),"}"])},appendContent:function(a){this.pendingContent?a=this.pendingContent+a:this.pendingLocation=this.source.currentLocation,this.pendingContent=a},append:function(){if(this.isInline())this.replaceStack(function(a){return[" != null ? ",a,' : ""']}),this.pushSource(this.appendToBuffer(this.popStack()));else{var a=this.popStack();this.pushSource(["if (",a," != null) { ",this.appendToBuffer(a,void 0,!0)," }"]),this.environment.isSimple&&this.pushSource(["else { ",this.appendToBuffer("''",void 0,!0)," }"])}},appendEscaped:function(){this.pushSource(this.appendToBuffer([this.aliasable("container.escapeExpression"),"(",this.popStack(),")"]))},getContext:function(a){this.lastContext=a},pushContext:function(){this.pushStackLiteral(this.contextName(this.lastContext))},lookupOnContext:function(a,b,c,d){var e=0;d||!this.options.compat||this.lastContext?this.pushContext():this.push(this.depthedLookup(a[e++])),this.resolvePath("context",a,e,b,c)},lookupBlockParam:function(a,b){this.useBlockParams=!0,this.push(["blockParams[",a[0],"][",a[1],"]"]),this.resolvePath("context",b,1)},lookupData:function(a,b,c){a?this.pushStackLiteral("container.data(data, "+a+")"):this.pushStackLiteral("data"),this.resolvePath("data",b,0,!0,c)},resolvePath:function(a,b,c,d,e){var f=this;if(this.options.strict||this.options.assumeObjects)return void this.push(j(this.options.strict&&e,this,b,a));for(var g=b.length;cthis.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var a=this.inlineStack;this.inlineStack=[];for(var b=0,c=a.length;b= 2.0.0-beta.1', + 7: '>= 4.0.0' + }; + + exports.REVISION_CHANGES = REVISION_CHANGES; + var objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + _helpers.registerDefaultHelpers(this); + _decorators.registerDefaultDecorators(this); + } + + HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: _logger2['default'], + log: _logger2['default'].log, + + registerHelper: function registerHelper(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _exception2['default']('Arg not supported with multiple helpers'); + } + _utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function unregisterHelper(name) { + delete this.helpers[name]; + }, + + registerPartial: function registerPartial(name, partial) { + if (_utils.toString.call(name) === objectType) { + _utils.extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined'); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function unregisterPartial(name) { + delete this.partials[name]; + }, + + registerDecorator: function registerDecorator(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _exception2['default']('Arg not supported with multiple decorators'); + } + _utils.extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function unregisterDecorator(name) { + delete this.decorators[name]; + } + }; + + var log = _logger2['default'].log; + + exports.log = log; + exports.createFrame = _utils.createFrame; + exports.logger = _logger2['default']; + +/***/ }, +/* 5 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + exports.extend = extend; + exports.indexOf = indexOf; + exports.escapeExpression = escapeExpression; + exports.isEmpty = isEmpty; + exports.createFrame = createFrame; + exports.blockParams = blockParams; + exports.appendContextPath = appendContextPath; + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' + }; + + var badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + + function escapeChar(chr) { + return escape[chr]; + } + + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; + } + + var toString = Object.prototype.toString; + + exports.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + /* eslint-disable func-style */ + var isFunction = function isFunction(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + exports.isFunction = isFunction = function (value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + exports.isFunction = isFunction; + + /* eslint-enable func-style */ + + /* istanbul ignore next */ + var isArray = Array.isArray || function (value) { + return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; + }; + + exports.isArray = isArray; + // Older IE versions do not directly support indexOf so we must implement our own, sadly. + + function indexOf(array, value) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; + } + + function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); + } + + function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + function createFrame(object) { + var frame = extend({}, object); + frame._parent = object; + return frame; + } + + function blockParams(params, ids) { + params.path = ids; + return params; + } + + function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; + } + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _Object$defineProperty = __webpack_require__(7)['default']; + + exports.__esModule = true; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var loc = node && node.loc, + line = undefined, + column = undefined; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (_Object$defineProperty) { + Object.defineProperty(this, 'column', { value: column }); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } + } + + Exception.prototype = new Error(); + + exports['default'] = Exception; + module.exports = exports['default']; + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = { "default": __webpack_require__(8), __esModule: true }; + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + var $ = __webpack_require__(9); + module.exports = function defineProperty(it, key, desc){ + return $.setDesc(it, key, desc); + }; + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + var $Object = Object; + module.exports = { + create: $Object.create, + getProto: $Object.getPrototypeOf, + isEnum: {}.propertyIsEnumerable, + getDesc: $Object.getOwnPropertyDescriptor, + setDesc: $Object.defineProperty, + setDescs: $Object.defineProperties, + getKeys: $Object.keys, + getNames: $Object.getOwnPropertyNames, + getSymbols: $Object.getOwnPropertySymbols, + each: [].forEach + }; + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + exports.registerDefaultHelpers = registerDefaultHelpers; + + var _helpersBlockHelperMissing = __webpack_require__(11); + + var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing); + + var _helpersEach = __webpack_require__(12); + + var _helpersEach2 = _interopRequireDefault(_helpersEach); + + var _helpersHelperMissing = __webpack_require__(13); + + var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing); + + var _helpersIf = __webpack_require__(14); + + var _helpersIf2 = _interopRequireDefault(_helpersIf); + + var _helpersLog = __webpack_require__(15); + + var _helpersLog2 = _interopRequireDefault(_helpersLog); + + var _helpersLookup = __webpack_require__(16); + + var _helpersLookup2 = _interopRequireDefault(_helpersLookup); + + var _helpersWith = __webpack_require__(17); + + var _helpersWith2 = _interopRequireDefault(_helpersWith); + + function registerDefaultHelpers(instance) { + _helpersBlockHelperMissing2['default'](instance); + _helpersEach2['default'](instance); + _helpersHelperMissing2['default'](instance); + _helpersIf2['default'](instance); + _helpersLog2['default'](instance); + _helpersLookup2['default'](instance); + _helpersWith2['default'](instance); + } + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + exports['default'] = function (instance) { + instance.registerHelper('blockHelperMissing', function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + exports['default'] = function (instance) { + instance.registerHelper('each', function (context, options) { + if (!options) { + throw new _exception2['default']('Must pass iterator to #each'); + } + + var fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data = undefined, + contextPath = undefined; + + if (options.data && options.ids) { + contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (_utils.isFunction(context)) { + context = context.call(this); + } + + if (options.data) { + data = _utils.createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (_utils.isArray(context)) { + for (var j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + var priorKey = undefined; + + for (var key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + exports['default'] = function (instance) { + instance.registerHelper('helperMissing', function () /* [args, ]options */{ + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + exports['default'] = function (instance) { + instance.registerHelper('if', function (conditional, options) { + if (_utils.isFunction(conditional)) { + conditional = conditional.call(this); + } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function (conditional, options) { + return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 15 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + + exports['default'] = function (instance) { + instance.registerHelper('log', function () /* message, options */{ + var args = [undefined], + options = arguments[arguments.length - 1]; + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + var level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log.apply(instance, args); + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 16 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + + exports['default'] = function (instance) { + instance.registerHelper('lookup', function (obj, field) { + return obj && obj[field]; + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + exports['default'] = function (instance) { + instance.registerHelper('with', function (context, options) { + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + exports.registerDefaultDecorators = registerDefaultDecorators; + + var _decoratorsInline = __webpack_require__(19); + + var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline); + + function registerDefaultDecorators(instance) { + _decoratorsInline2['default'](instance); + } + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + exports['default'] = function (instance) { + instance.registerDecorator('inline', function (fn, props, container, options) { + var ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function (context, options) { + // Create a new partials stack frame prior to exec. + var original = container.partials; + container.partials = _utils.extend({}, original, props.partials); + var ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + var logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function lookupLevel(level) { + if (typeof level === 'string') { + var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function log(level) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + var method = logger.methodMap[level]; + if (!console[method]) { + // eslint-disable-line no-console + method = 'log'; + } + + for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + message[_key - 1] = arguments[_key]; + } + + console[method].apply(console, message); // eslint-disable-line no-console + } + } + }; + + exports['default'] = logger; + module.exports = exports['default']; + +/***/ }, +/* 21 */ +/***/ function(module, exports) { + + // Build out our basic SafeString type + 'use strict'; + + exports.__esModule = true; + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = SafeString.prototype.toHTML = function () { + return '' + this.string; + }; + + exports['default'] = SafeString; + module.exports = exports['default']; + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireWildcard = __webpack_require__(3)['default']; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + exports.checkRevision = checkRevision; + exports.template = template; + exports.wrapProgram = wrapProgram; + exports.resolvePartial = resolvePartial; + exports.invokePartial = invokePartial; + exports.noop = noop; + + var _utils = __webpack_require__(5); + + var Utils = _interopRequireWildcard(_utils); + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + var _base = __webpack_require__(4); + + function checkRevision(compilerInfo) { + var compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = _base.COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = _base.REVISION_CHANGES[currentRevision], + compilerVersions = _base.REVISION_CHANGES[compilerRevision]; + throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } + } + + function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new _exception2['default']('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new _exception2['default']('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = Utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + var result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + var lines = result.split('\n'); + for (var i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + var container = { + strict: function strict(obj, name) { + if (!(name in obj)) { + throw new _exception2['default']('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function lookup(depths, name) { + var len = depths.length; + for (var i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function lambda(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: Utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function fn(i) { + var ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function program(i, data, declaredBlockParams, blockParams, depths) { + var programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function data(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function merge(param, common) { + var obj = param || common; + + if (param && common && param !== common) { + obj = Utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function (options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function (i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new _exception2['default']('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new _exception2['default']('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; + } + + function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; + } + + function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + var data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; + } + + function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + var partialBlock = undefined; + if (options.fn && options.fn !== noop) { + options.data = _base.createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = Utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new _exception2['default']('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } + } + + function noop() { + return ''; + } + + function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? _base.createFrame(data) : {}; + data.root = context; + } + return data; + } + + function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + var props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + Utils.extend(prog, props); + } + return prog; + } + +/***/ }, +/* 23 */ +/***/ function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/* global window */ + 'use strict'; + + exports.__esModule = true; + + exports['default'] = function (Handlebars) { + /* istanbul ignore next */ + var root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function () { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; + }; + + module.exports = exports['default']; + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 24 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + var AST = { + // Public API used to evaluate derived attributes regarding AST nodes + helpers: { + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + helperExpression: function helperExpression(node) { + return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash); + }, + + scopedId: function scopedId(path) { + return (/^\.|this\b/.test(path.original) + ); + }, + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + simpleId: function simpleId(path) { + return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; + } + } + }; + + // Must be exported as an object rather than the root of the module as the jison lexer + // must modify the object to operate properly. + exports['default'] = AST; + module.exports = exports['default']; + +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + var _interopRequireWildcard = __webpack_require__(3)['default']; + + exports.__esModule = true; + exports.parse = parse; + + var _parser = __webpack_require__(26); + + var _parser2 = _interopRequireDefault(_parser); + + var _whitespaceControl = __webpack_require__(27); + + var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl); + + var _helpers = __webpack_require__(29); + + var Helpers = _interopRequireWildcard(_helpers); + + var _utils = __webpack_require__(5); + + exports.parser = _parser2['default']; + + var yy = {}; + _utils.extend(yy, Helpers); + + function parse(input, options) { + // Just return if an already-compiled AST was passed in. + if (input.type === 'Program') { + return input; + } + + _parser2['default'].yy = yy; + + // Altering the shared object here, but this is ok as parser is a sync operation + yy.locInfo = function (locInfo) { + return new yy.SourceLocation(options && options.srcName, locInfo); + }; + + var strip = new _whitespaceControl2['default'](options); + return strip.accept(_parser2['default'].parse(input)); + } + +/***/ }, +/* 26 */ +/***/ function(module, exports) { + + /* istanbul ignore next */ + /* Jison generated parser */ + "use strict"; + + var handlebars = (function () { + var parser = { trace: function trace() {}, + yy: {}, + symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 }, + terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" }, + productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$ + /**/) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: + return $$[$0 - 1]; + break; + case 2: + this.$ = yy.prepareProgram($$[$0]); + break; + case 3: + this.$ = $$[$0]; + break; + case 4: + this.$ = $$[$0]; + break; + case 5: + this.$ = $$[$0]; + break; + case 6: + this.$ = $$[$0]; + break; + case 7: + this.$ = $$[$0]; + break; + case 8: + this.$ = $$[$0]; + break; + case 9: + this.$ = { + type: 'CommentStatement', + value: yy.stripComment($$[$0]), + strip: yy.stripFlags($$[$0], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 10: + this.$ = { + type: 'ContentStatement', + original: $$[$0], + value: $$[$0], + loc: yy.locInfo(this._$) + }; + + break; + case 11: + this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 12: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] }; + break; + case 13: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$); + break; + case 14: + this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$); + break; + case 15: + this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 16: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 17: + this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; + break; + case 18: + this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] }; + break; + case 19: + var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$), + program = yy.prepareProgram([inverse], $$[$0 - 1].loc); + program.chained = true; + + this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true }; + + break; + case 20: + this.$ = $$[$0]; + break; + case 21: + this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) }; + break; + case 22: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 23: + this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); + break; + case 24: + this.$ = { + type: 'PartialStatement', + name: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + indent: '', + strip: yy.stripFlags($$[$0 - 4], $$[$0]), + loc: yy.locInfo(this._$) + }; + + break; + case 25: + this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); + break; + case 26: + this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) }; + break; + case 27: + this.$ = $$[$0]; + break; + case 28: + this.$ = $$[$0]; + break; + case 29: + this.$ = { + type: 'SubExpression', + path: $$[$0 - 3], + params: $$[$0 - 2], + hash: $$[$0 - 1], + loc: yy.locInfo(this._$) + }; + + break; + case 30: + this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 31: + this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 32: + this.$ = yy.id($$[$0 - 1]); + break; + case 33: + this.$ = $$[$0]; + break; + case 34: + this.$ = $$[$0]; + break; + case 35: + this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) }; + break; + case 36: + this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) }; + break; + case 37: + this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) }; + break; + case 38: + this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) }; + break; + case 39: + this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) }; + break; + case 40: + this.$ = $$[$0]; + break; + case 41: + this.$ = $$[$0]; + break; + case 42: + this.$ = yy.preparePath(true, $$[$0], this._$); + break; + case 43: + this.$ = yy.preparePath(false, $$[$0], this._$); + break; + case 44: + $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2]; + break; + case 45: + this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }]; + break; + case 46: + this.$ = []; + break; + case 47: + $$[$0 - 1].push($$[$0]); + break; + case 48: + this.$ = [$$[$0]]; + break; + case 49: + $$[$0 - 1].push($$[$0]); + break; + case 50: + this.$ = []; + break; + case 51: + $$[$0 - 1].push($$[$0]); + break; + case 58: + this.$ = []; + break; + case 59: + $$[$0 - 1].push($$[$0]); + break; + case 64: + this.$ = []; + break; + case 65: + $$[$0 - 1].push($$[$0]); + break; + case 70: + this.$ = []; + break; + case 71: + $$[$0 - 1].push($$[$0]); + break; + case 78: + this.$ = []; + break; + case 79: + $$[$0 - 1].push($$[$0]); + break; + case 82: + this.$ = []; + break; + case 83: + $$[$0 - 1].push($$[$0]); + break; + case 86: + this.$ = []; + break; + case 87: + $$[$0 - 1].push($$[$0]); + break; + case 90: + this.$ = []; + break; + case 91: + $$[$0 - 1].push($$[$0]); + break; + case 94: + this.$ = []; + break; + case 95: + $$[$0 - 1].push($$[$0]); + break; + case 98: + this.$ = [$$[$0]]; + break; + case 99: + $$[$0 - 1].push($$[$0]); + break; + case 100: + this.$ = [$$[$0]]; + break; + case 101: + $$[$0 - 1].push($$[$0]); + break; + } + }, + table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }], + defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137: [2, 32] }, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], + lstack = [], + table = this.table, + yytext = "", + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, + preErrorSymbol, + state, + action, + a, + r, + yyval = {}, + p, + len, + newState, + expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected }); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; + } + }; + /* Jison generated lexer */ + var lexer = (function () { + var lexer = { EOF: 1, + parseError: function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput: function setInput(input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; + if (this.options.ranges) this.yylloc.range = [0, 0]; + this.offset = 0; + return this; + }, + input: function input() { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, + unput: function unput(ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); + + if (lines.length - 1) this.yylineno -= lines.length - 1; + var r = this.yylloc.range; + + this.yylloc = { first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, + more: function more() { + this._more = true; + return this; + }, + less: function less(n) { + this.unput(this.match.slice(n)); + }, + pastInput: function pastInput() { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput: function upcomingInput() { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20 - next.length); + } + return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, + showPosition: function showPosition() { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, + next: function next() { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, match, tempMatch, index, col, lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = { first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) this.done = false; + if (token) return token;else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); + } + }, + lex: function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin: function begin(condition) { + this.conditionStack.push(condition); + }, + popState: function popState() { + return this.conditionStack.pop(); + }, + _currentRules: function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + }, + topState: function topState() { + return this.conditionStack[this.conditionStack.length - 2]; + }, + pushState: function begin(condition) { + this.begin(condition); + } }; + lexer.options = {}; + lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START + /**/) { + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end); + } + + var YYSTATE = YY_START; + switch ($avoiding_name_collisions) { + case 0: + if (yy_.yytext.slice(-2) === "\\\\") { + strip(0, 1); + this.begin("mu"); + } else if (yy_.yytext.slice(-1) === "\\") { + strip(0, 1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if (yy_.yytext) return 15; + + break; + case 1: + return 15; + break; + case 2: + this.popState(); + return 15; + + break; + case 3: + this.begin('raw');return 15; + break; + case 4: + this.popState(); + // Should be using `this.topState()` below, but it currently + // returns the second top instead of the first top. Opened an + // issue about it at https://github.com/zaach/jison/issues/291 + if (this.conditionStack[this.conditionStack.length - 1] === 'raw') { + return 15; + } else { + yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9); + return 'END_RAW_BLOCK'; + } + + break; + case 5: + return 15; + break; + case 6: + this.popState(); + return 14; + + break; + case 7: + return 65; + break; + case 8: + return 68; + break; + case 9: + return 19; + break; + case 10: + this.popState(); + this.begin('raw'); + return 23; + + break; + case 11: + return 55; + break; + case 12: + return 60; + break; + case 13: + return 29; + break; + case 14: + return 47; + break; + case 15: + this.popState();return 44; + break; + case 16: + this.popState();return 44; + break; + case 17: + return 34; + break; + case 18: + return 39; + break; + case 19: + return 51; + break; + case 20: + return 48; + break; + case 21: + this.unput(yy_.yytext); + this.popState(); + this.begin('com'); + + break; + case 22: + this.popState(); + return 14; + + break; + case 23: + return 48; + break; + case 24: + return 73; + break; + case 25: + return 72; + break; + case 26: + return 72; + break; + case 27: + return 87; + break; + case 28: + // ignore whitespace + break; + case 29: + this.popState();return 54; + break; + case 30: + this.popState();return 33; + break; + case 31: + yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80; + break; + case 32: + yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80; + break; + case 33: + return 85; + break; + case 34: + return 82; + break; + case 35: + return 82; + break; + case 36: + return 83; + break; + case 37: + return 84; + break; + case 38: + return 81; + break; + case 39: + return 75; + break; + case 40: + return 77; + break; + case 41: + return 72; + break; + case 42: + yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72; + break; + case 43: + return 'INVALID'; + break; + case 44: + return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/]; + lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } }; + return lexer; + })(); + parser.lexer = lexer; + function Parser() { + this.yy = {}; + }Parser.prototype = parser;parser.Parser = Parser; + return new Parser(); + })();exports.__esModule = true; + exports['default'] = handlebars; + +/***/ }, +/* 27 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + + var _visitor = __webpack_require__(28); + + var _visitor2 = _interopRequireDefault(_visitor); + + function WhitespaceControl() { + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + this.options = options; + } + WhitespaceControl.prototype = new _visitor2['default'](); + + WhitespaceControl.prototype.Program = function (program) { + var doStandalone = !this.options.ignoreStandalone; + + var isRoot = !this.isRootSeen; + this.isRootSeen = true; + + var body = program.body; + for (var i = 0, l = body.length; i < l; i++) { + var current = body[i], + strip = this.accept(current); + + if (!strip) { + continue; + } + + var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), + _isNextWhitespace = isNextWhitespace(body, i, isRoot), + openStandalone = strip.openStandalone && _isPrevWhitespace, + closeStandalone = strip.closeStandalone && _isNextWhitespace, + inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; + + if (strip.close) { + omitRight(body, i, true); + } + if (strip.open) { + omitLeft(body, i, true); + } + + if (doStandalone && inlineStandalone) { + omitRight(body, i); + + if (omitLeft(body, i)) { + // If we are on a standalone node, save the indent info for partials + if (current.type === 'PartialStatement') { + // Pull out the whitespace from the final line + current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1]; + } + } + } + if (doStandalone && openStandalone) { + omitRight((current.program || current.inverse).body); + + // Strip out the previous content node if it's whitespace only + omitLeft(body, i); + } + if (doStandalone && closeStandalone) { + // Always strip the next node + omitRight(body, i); + + omitLeft((current.inverse || current.program).body); + } + } + + return program; + }; + + WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) { + this.accept(block.program); + this.accept(block.inverse); + + // Find the inverse program that is involed with whitespace stripping. + var program = block.program || block.inverse, + inverse = block.program && block.inverse, + firstInverse = inverse, + lastInverse = inverse; + + if (inverse && inverse.chained) { + firstInverse = inverse.body[0].program; + + // Walk the inverse chain to find the last inverse that is actually in the chain. + while (lastInverse.chained) { + lastInverse = lastInverse.body[lastInverse.body.length - 1].program; + } + } + + var strip = { + open: block.openStrip.open, + close: block.closeStrip.close, + + // Determine the standalone candiacy. Basically flag our content as being possibly standalone + // so our parent can determine if we actually are standalone + openStandalone: isNextWhitespace(program.body), + closeStandalone: isPrevWhitespace((firstInverse || program).body) + }; + + if (block.openStrip.close) { + omitRight(program.body, null, true); + } + + if (inverse) { + var inverseStrip = block.inverseStrip; + + if (inverseStrip.open) { + omitLeft(program.body, null, true); + } + + if (inverseStrip.close) { + omitRight(firstInverse.body, null, true); + } + if (block.closeStrip.open) { + omitLeft(lastInverse.body, null, true); + } + + // Find standalone else statments + if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) { + omitLeft(program.body); + omitRight(firstInverse.body); + } + } else if (block.closeStrip.open) { + omitLeft(program.body, null, true); + } + + return strip; + }; + + WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) { + return mustache.strip; + }; + + WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) { + /* istanbul ignore next */ + var strip = node.strip || {}; + return { + inlineStandalone: true, + open: strip.open, + close: strip.close + }; + }; + + function isPrevWhitespace(body, i, isRoot) { + if (i === undefined) { + i = body.length; + } + + // Nodes that end with newlines are considered whitespace (but are special + // cased for strip operations) + var prev = body[i - 1], + sibling = body[i - 2]; + if (!prev) { + return isRoot; + } + + if (prev.type === 'ContentStatement') { + return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original); + } + } + function isNextWhitespace(body, i, isRoot) { + if (i === undefined) { + i = -1; + } + + var next = body[i + 1], + sibling = body[i + 2]; + if (!next) { + return isRoot; + } + + if (next.type === 'ContentStatement') { + return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original); + } + } + + // Marks the node to the right of the position as omitted. + // I.e. {{foo}}' ' will mark the ' ' node as omitted. + // + // If i is undefined, then the first child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitRight(body, i, multiple) { + var current = body[i == null ? 0 : i + 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) { + return; + } + + var original = current.value; + current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, ''); + current.rightStripped = current.value !== original; + } + + // Marks the node to the left of the position as omitted. + // I.e. ' '{{foo}} will mark the ' ' node as omitted. + // + // If i is undefined then the last child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitLeft(body, i, multiple) { + var current = body[i == null ? body.length - 1 : i - 1]; + if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) { + return; + } + + // We omit the last node if it's whitespace only and not preceeded by a non-content node. + var original = current.value; + current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, ''); + current.leftStripped = current.value !== original; + return current.leftStripped; + } + + exports['default'] = WhitespaceControl; + module.exports = exports['default']; + +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + function Visitor() { + this.parents = []; + } + + Visitor.prototype = { + constructor: Visitor, + mutating: false, + + // Visits a given value. If mutating, will replace the value if necessary. + acceptKey: function acceptKey(node, name) { + var value = this.accept(node[name]); + if (this.mutating) { + // Hacky sanity check: This may have a few false positives for type for the helper + // methods but will generally do the right thing without a lot of overhead. + if (value && !Visitor.prototype[value.type]) { + throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); + } + node[name] = value; + } + }, + + // Performs an accept operation with added sanity check to ensure + // required keys are not removed. + acceptRequired: function acceptRequired(node, name) { + this.acceptKey(node, name); + + if (!node[name]) { + throw new _exception2['default'](node.type + ' requires ' + name); + } + }, + + // Traverses a given array. If mutating, empty respnses will be removed + // for child elements. + acceptArray: function acceptArray(array) { + for (var i = 0, l = array.length; i < l; i++) { + this.acceptKey(array, i); + + if (!array[i]) { + array.splice(i, 1); + i--; + l--; + } + } + }, + + accept: function accept(object) { + if (!object) { + return; + } + + /* istanbul ignore next: Sanity code */ + if (!this[object.type]) { + throw new _exception2['default']('Unknown type: ' + object.type, object); + } + + if (this.current) { + this.parents.unshift(this.current); + } + this.current = object; + + var ret = this[object.type](object); + + this.current = this.parents.shift(); + + if (!this.mutating || ret) { + return ret; + } else if (ret !== false) { + return object; + } + }, + + Program: function Program(program) { + this.acceptArray(program.body); + }, + + MustacheStatement: visitSubExpression, + Decorator: visitSubExpression, + + BlockStatement: visitBlock, + DecoratorBlock: visitBlock, + + PartialStatement: visitPartial, + PartialBlockStatement: function PartialBlockStatement(partial) { + visitPartial.call(this, partial); + + this.acceptKey(partial, 'program'); + }, + + ContentStatement: function ContentStatement() /* content */{}, + CommentStatement: function CommentStatement() /* comment */{}, + + SubExpression: visitSubExpression, + + PathExpression: function PathExpression() /* path */{}, + + StringLiteral: function StringLiteral() /* string */{}, + NumberLiteral: function NumberLiteral() /* number */{}, + BooleanLiteral: function BooleanLiteral() /* bool */{}, + UndefinedLiteral: function UndefinedLiteral() /* literal */{}, + NullLiteral: function NullLiteral() /* literal */{}, + + Hash: function Hash(hash) { + this.acceptArray(hash.pairs); + }, + HashPair: function HashPair(pair) { + this.acceptRequired(pair, 'value'); + } + }; + + function visitSubExpression(mustache) { + this.acceptRequired(mustache, 'path'); + this.acceptArray(mustache.params); + this.acceptKey(mustache, 'hash'); + } + function visitBlock(block) { + visitSubExpression.call(this, block); + + this.acceptKey(block, 'program'); + this.acceptKey(block, 'inverse'); + } + function visitPartial(partial) { + this.acceptRequired(partial, 'name'); + this.acceptArray(partial.params); + this.acceptKey(partial, 'hash'); + } + + exports['default'] = Visitor; + module.exports = exports['default']; + +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + exports.SourceLocation = SourceLocation; + exports.id = id; + exports.stripFlags = stripFlags; + exports.stripComment = stripComment; + exports.preparePath = preparePath; + exports.prepareMustache = prepareMustache; + exports.prepareRawBlock = prepareRawBlock; + exports.prepareBlock = prepareBlock; + exports.prepareProgram = prepareProgram; + exports.preparePartialBlock = preparePartialBlock; + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + function validateClose(open, close) { + close = close.path ? close.path.original : close; + + if (open.path.original !== close) { + var errorNode = { loc: open.path.loc }; + + throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode); + } + } + + function SourceLocation(source, locInfo) { + this.source = source; + this.start = { + line: locInfo.first_line, + column: locInfo.first_column + }; + this.end = { + line: locInfo.last_line, + column: locInfo.last_column + }; + } + + function id(token) { + if (/^\[.*\]$/.test(token)) { + return token.substr(1, token.length - 2); + } else { + return token; + } + } + + function stripFlags(open, close) { + return { + open: open.charAt(2) === '~', + close: close.charAt(close.length - 3) === '~' + }; + } + + function stripComment(comment) { + return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, ''); + } + + function preparePath(data, parts, loc) { + loc = this.locInfo(loc); + + var original = data ? '@' : '', + dig = [], + depth = 0, + depthString = ''; + + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i].part, + + // If we have [] syntax then we do not treat path references as operators, + // i.e. foo.[this] resolves to approximately context.foo['this'] + isLiteral = parts[i].original !== part; + original += (parts[i].separator || '') + part; + + if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { + if (dig.length > 0) { + throw new _exception2['default']('Invalid path: ' + original, { loc: loc }); + } else if (part === '..') { + depth++; + depthString += '../'; + } + } else { + dig.push(part); + } + } + + return { + type: 'PathExpression', + data: data, + depth: depth, + parts: dig, + original: original, + loc: loc + }; + } + + function prepareMustache(path, params, hash, open, strip, locInfo) { + // Must use charAt to support IE pre-10 + var escapeFlag = open.charAt(3) || open.charAt(2), + escaped = escapeFlag !== '{' && escapeFlag !== '&'; + + var decorator = /\*/.test(open); + return { + type: decorator ? 'Decorator' : 'MustacheStatement', + path: path, + params: params, + hash: hash, + escaped: escaped, + strip: strip, + loc: this.locInfo(locInfo) + }; + } + + function prepareRawBlock(openRawBlock, contents, close, locInfo) { + validateClose(openRawBlock, close); + + locInfo = this.locInfo(locInfo); + var program = { + type: 'Program', + body: contents, + strip: {}, + loc: locInfo + }; + + return { + type: 'BlockStatement', + path: openRawBlock.path, + params: openRawBlock.params, + hash: openRawBlock.hash, + program: program, + openStrip: {}, + inverseStrip: {}, + closeStrip: {}, + loc: locInfo + }; + } + + function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { + if (close && close.path) { + validateClose(openBlock, close); + } + + var decorator = /\*/.test(openBlock.open); + + program.blockParams = openBlock.blockParams; + + var inverse = undefined, + inverseStrip = undefined; + + if (inverseAndProgram) { + if (decorator) { + throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram); + } + + if (inverseAndProgram.chain) { + inverseAndProgram.program.body[0].closeStrip = close.strip; + } + + inverseStrip = inverseAndProgram.strip; + inverse = inverseAndProgram.program; + } + + if (inverted) { + inverted = inverse; + inverse = program; + program = inverted; + } + + return { + type: decorator ? 'DecoratorBlock' : 'BlockStatement', + path: openBlock.path, + params: openBlock.params, + hash: openBlock.hash, + program: program, + inverse: inverse, + openStrip: openBlock.strip, + inverseStrip: inverseStrip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; + } + + function prepareProgram(statements, loc) { + if (!loc && statements.length) { + var firstLoc = statements[0].loc, + lastLoc = statements[statements.length - 1].loc; + + /* istanbul ignore else */ + if (firstLoc && lastLoc) { + loc = { + source: firstLoc.source, + start: { + line: firstLoc.start.line, + column: firstLoc.start.column + }, + end: { + line: lastLoc.end.line, + column: lastLoc.end.column + } + }; + } + } + + return { + type: 'Program', + body: statements, + strip: {}, + loc: loc + }; + } + + function preparePartialBlock(open, program, close, locInfo) { + validateClose(open, close); + + return { + type: 'PartialBlockStatement', + name: open.path, + params: open.params, + hash: open.hash, + program: program, + openStrip: open.strip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; + } + +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { + + /* eslint-disable new-cap */ + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + exports.Compiler = Compiler; + exports.precompile = precompile; + exports.compile = compile; + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + var _utils = __webpack_require__(5); + + var _ast = __webpack_require__(24); + + var _ast2 = _interopRequireDefault(_ast); + + var slice = [].slice; + + function Compiler() {} + + // the foundHelper register will disambiguate helper lookup from finding a + // function in a context. This is necessary for mustache compatibility, which + // requires that context functions in blocks are evaluated by blockHelperMissing, + // and then proceed as if the resulting value was provided to blockHelperMissing. + + Compiler.prototype = { + compiler: Compiler, + + equals: function equals(other) { + var len = this.opcodes.length; + if (other.opcodes.length !== len) { + return false; + } + + for (var i = 0; i < len; i++) { + var opcode = this.opcodes[i], + otherOpcode = other.opcodes[i]; + if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { + return false; + } + } + + // We know that length is the same between the two arrays because they are directly tied + // to the opcode behavior above. + len = this.children.length; + for (var i = 0; i < len; i++) { + if (!this.children[i].equals(other.children[i])) { + return false; + } + } + + return true; + }, + + guid: 0, + + compile: function compile(program, options) { + this.sourceNode = []; + this.opcodes = []; + this.children = []; + this.options = options; + this.stringParams = options.stringParams; + this.trackIds = options.trackIds; + + options.blockParams = options.blockParams || []; + + // These changes will propagate to the other compiler components + var knownHelpers = options.knownHelpers; + options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true, + 'lookup': true + }; + if (knownHelpers) { + for (var _name in knownHelpers) { + /* istanbul ignore else */ + if (_name in knownHelpers) { + options.knownHelpers[_name] = knownHelpers[_name]; + } + } + } + + return this.accept(program); + }, + + compileProgram: function compileProgram(program) { + var childCompiler = new this.compiler(), + // eslint-disable-line new-cap + result = childCompiler.compile(program, this.options), + guid = this.guid++; + + this.usePartial = this.usePartial || result.usePartial; + + this.children[guid] = result; + this.useDepths = this.useDepths || result.useDepths; + + return guid; + }, + + accept: function accept(node) { + /* istanbul ignore next: Sanity code */ + if (!this[node.type]) { + throw new _exception2['default']('Unknown type: ' + node.type, node); + } + + this.sourceNode.unshift(node); + var ret = this[node.type](node); + this.sourceNode.shift(); + return ret; + }, + + Program: function Program(program) { + this.options.blockParams.unshift(program.blockParams); + + var body = program.body, + bodyLength = body.length; + for (var i = 0; i < bodyLength; i++) { + this.accept(body[i]); + } + + this.options.blockParams.shift(); + + this.isSimple = bodyLength === 1; + this.blockParams = program.blockParams ? program.blockParams.length : 0; + + return this; + }, + + BlockStatement: function BlockStatement(block) { + transformLiteralToPath(block); + + var program = block.program, + inverse = block.inverse; + + program = program && this.compileProgram(program); + inverse = inverse && this.compileProgram(inverse); + + var type = this.classifySexpr(block); + + if (type === 'helper') { + this.helperSexpr(block, program, inverse); + } else if (type === 'simple') { + this.simpleSexpr(block); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('blockValue', block.path.original); + } else { + this.ambiguousSexpr(block, program, inverse); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('ambiguousBlockValue'); + } + + this.opcode('append'); + }, + + DecoratorBlock: function DecoratorBlock(decorator) { + var program = decorator.program && this.compileProgram(decorator.program); + var params = this.setupFullMustacheParams(decorator, program, undefined), + path = decorator.path; + + this.useDecorators = true; + this.opcode('registerDecorator', params.length, path.original); + }, + + PartialStatement: function PartialStatement(partial) { + this.usePartial = true; + + var program = partial.program; + if (program) { + program = this.compileProgram(partial.program); + } + + var params = partial.params; + if (params.length > 1) { + throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial); + } else if (!params.length) { + if (this.options.explicitPartialContext) { + this.opcode('pushLiteral', 'undefined'); + } else { + params.push({ type: 'PathExpression', parts: [], depth: 0 }); + } + } + + var partialName = partial.name.original, + isDynamic = partial.name.type === 'SubExpression'; + if (isDynamic) { + this.accept(partial.name); + } + + this.setupFullMustacheParams(partial, program, undefined, true); + + var indent = partial.indent || ''; + if (this.options.preventIndent && indent) { + this.opcode('appendContent', indent); + indent = ''; + } + + this.opcode('invokePartial', isDynamic, partialName, indent); + this.opcode('append'); + }, + PartialBlockStatement: function PartialBlockStatement(partialBlock) { + this.PartialStatement(partialBlock); + }, + + MustacheStatement: function MustacheStatement(mustache) { + this.SubExpression(mustache); + + if (mustache.escaped && !this.options.noEscape) { + this.opcode('appendEscaped'); + } else { + this.opcode('append'); + } + }, + Decorator: function Decorator(decorator) { + this.DecoratorBlock(decorator); + }, + + ContentStatement: function ContentStatement(content) { + if (content.value) { + this.opcode('appendContent', content.value); + } + }, + + CommentStatement: function CommentStatement() {}, + + SubExpression: function SubExpression(sexpr) { + transformLiteralToPath(sexpr); + var type = this.classifySexpr(sexpr); + + if (type === 'simple') { + this.simpleSexpr(sexpr); + } else if (type === 'helper') { + this.helperSexpr(sexpr); + } else { + this.ambiguousSexpr(sexpr); + } + }, + ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) { + var path = sexpr.path, + name = path.parts[0], + isBlock = program != null || inverse != null; + + this.opcode('getContext', path.depth); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + path.strict = true; + this.accept(path); + + this.opcode('invokeAmbiguous', name, isBlock); + }, + + simpleSexpr: function simpleSexpr(sexpr) { + var path = sexpr.path; + path.strict = true; + this.accept(path); + this.opcode('resolvePossibleLambda'); + }, + + helperSexpr: function helperSexpr(sexpr, program, inverse) { + var params = this.setupFullMustacheParams(sexpr, program, inverse), + path = sexpr.path, + name = path.parts[0]; + + if (this.options.knownHelpers[name]) { + this.opcode('invokeKnownHelper', params.length, name); + } else if (this.options.knownHelpersOnly) { + throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); + } else { + path.strict = true; + path.falsy = true; + + this.accept(path); + this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path)); + } + }, + + PathExpression: function PathExpression(path) { + this.addDepth(path.depth); + this.opcode('getContext', path.depth); + + var name = path.parts[0], + scoped = _ast2['default'].helpers.scopedId(path), + blockParamId = !path.depth && !scoped && this.blockParamIndex(name); + + if (blockParamId) { + this.opcode('lookupBlockParam', blockParamId, path.parts); + } else if (!name) { + // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` + this.opcode('pushContext'); + } else if (path.data) { + this.options.data = true; + this.opcode('lookupData', path.depth, path.parts, path.strict); + } else { + this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); + } + }, + + StringLiteral: function StringLiteral(string) { + this.opcode('pushString', string.value); + }, + + NumberLiteral: function NumberLiteral(number) { + this.opcode('pushLiteral', number.value); + }, + + BooleanLiteral: function BooleanLiteral(bool) { + this.opcode('pushLiteral', bool.value); + }, + + UndefinedLiteral: function UndefinedLiteral() { + this.opcode('pushLiteral', 'undefined'); + }, + + NullLiteral: function NullLiteral() { + this.opcode('pushLiteral', 'null'); + }, + + Hash: function Hash(hash) { + var pairs = hash.pairs, + i = 0, + l = pairs.length; + + this.opcode('pushHash'); + + for (; i < l; i++) { + this.pushParam(pairs[i].value); + } + while (i--) { + this.opcode('assignToHash', pairs[i].key); + } + this.opcode('popHash'); + }, + + // HELPERS + opcode: function opcode(name) { + this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc }); + }, + + addDepth: function addDepth(depth) { + if (!depth) { + return; + } + + this.useDepths = true; + }, + + classifySexpr: function classifySexpr(sexpr) { + var isSimple = _ast2['default'].helpers.simpleId(sexpr.path); + + var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + var isEligible = !isBlockParam && (isHelper || isSimple); + + // if ambiguous, we can possibly resolve the ambiguity now + // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. + if (isEligible && !isHelper) { + var _name2 = sexpr.path.parts[0], + options = this.options; + + if (options.knownHelpers[_name2]) { + isHelper = true; + } else if (options.knownHelpersOnly) { + isEligible = false; + } + } + + if (isHelper) { + return 'helper'; + } else if (isEligible) { + return 'ambiguous'; + } else { + return 'simple'; + } + }, + + pushParams: function pushParams(params) { + for (var i = 0, l = params.length; i < l; i++) { + this.pushParam(params[i]); + } + }, + + pushParam: function pushParam(val) { + var value = val.value != null ? val.value : val.original || ''; + + if (this.stringParams) { + if (value.replace) { + value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.'); + } + + if (val.depth) { + this.addDepth(val.depth); + } + this.opcode('getContext', val.depth || 0); + this.opcode('pushStringParam', value, val.type); + + if (val.type === 'SubExpression') { + // SubExpressions get evaluated and passed in + // in string params mode. + this.accept(val); + } + } else { + if (this.trackIds) { + var blockParamIndex = undefined; + if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) { + blockParamIndex = this.blockParamIndex(val.parts[0]); + } + if (blockParamIndex) { + var blockParamChild = val.parts.slice(1).join('.'); + this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); + } else { + value = val.original || value; + if (value.replace) { + value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, ''); + } + + this.opcode('pushId', val.type, value); + } + } + this.accept(val); + } + }, + + setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) { + var params = sexpr.params; + this.pushParams(params); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + if (sexpr.hash) { + this.accept(sexpr.hash); + } else { + this.opcode('emptyHash', omitEmpty); + } + + return params; + }, + + blockParamIndex: function blockParamIndex(name) { + for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { + var blockParams = this.options.blockParams[depth], + param = blockParams && _utils.indexOf(blockParams, name); + if (blockParams && param >= 0) { + return [depth, param]; + } + } + } + }; + + function precompile(input, options, env) { + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); + } + + options = options || {}; + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options); + return new env.JavaScriptCompiler().compile(environment, options); + } + + function compile(input, options, env) { + if (options === undefined) options = {}; + + if (input == null || typeof input !== 'string' && input.type !== 'Program') { + throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); + } + + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + var compiled = undefined; + + function compileInput() { + var ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options), + templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); + return env.template(templateSpec); + } + + // Template is only compiled on first use and cached after that point. + function ret(context, execOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled.call(this, context, execOptions); + } + ret._setup = function (setupOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._setup(setupOptions); + }; + ret._child = function (i, data, blockParams, depths) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._child(i, data, blockParams, depths); + }; + return ret; + } + + function argEquals(a, b) { + if (a === b) { + return true; + } + + if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) { + for (var i = 0; i < a.length; i++) { + if (!argEquals(a[i], b[i])) { + return false; + } + } + return true; + } + } + + function transformLiteralToPath(sexpr) { + if (!sexpr.path.parts) { + var literal = sexpr.path; + // Casting to string here to make false and 0 literal values play nicely with the rest + // of the system. + sexpr.path = { + type: 'PathExpression', + data: false, + depth: 0, + parts: [literal.original + ''], + original: literal.original + '', + loc: literal.loc + }; + } + } + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(1)['default']; + + exports.__esModule = true; + + var _base = __webpack_require__(4); + + var _exception = __webpack_require__(6); + + var _exception2 = _interopRequireDefault(_exception); + + var _utils = __webpack_require__(5); + + var _codeGen = __webpack_require__(32); + + var _codeGen2 = _interopRequireDefault(_codeGen); + + function Literal(value) { + this.value = value; + } + + function JavaScriptCompiler() {} + + JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function nameLookup(parent, name /* , type*/) { + if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + return [parent, '.', name]; + } else { + return [parent, '[', JSON.stringify(name), ']']; + } + }, + depthedLookup: function depthedLookup(name) { + return [this.aliasable('container.lookup'), '(depths, "', name, '")']; + }, + + compilerInfo: function compilerInfo() { + var revision = _base.COMPILER_REVISION, + versions = _base.REVISION_CHANGES[revision]; + return [revision, versions]; + }, + + appendToBuffer: function appendToBuffer(source, location, explicit) { + // Force a source as this simplifies the merge logic. + if (!_utils.isArray(source)) { + source = [source]; + } + source = this.source.wrap(source, location); + + if (this.environment.isSimple) { + return ['return ', source, ';']; + } else if (explicit) { + // This is a case where the buffer operation occurs as a child of another + // construct, generally braces. We have to explicitly output these buffer + // operations to ensure that the emitted code goes in the correct location. + return ['buffer += ', source, ';']; + } else { + source.appendToBuffer = true; + return source; + } + }, + + initializeBuffer: function initializeBuffer() { + return this.quotedString(''); + }, + // END PUBLIC API + + compile: function compile(environment, options, context, asObject) { + this.environment = environment; + this.options = options; + this.stringParams = this.options.stringParams; + this.trackIds = this.options.trackIds; + this.precompile = !asObject; + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + decorators: [], + programs: [], + environments: [] + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.aliases = {}; + this.registers = { list: [] }; + this.hashes = []; + this.compileStack = []; + this.inlineStack = []; + this.blockParams = []; + + this.compileChildren(environment, options); + + this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; + this.useBlockParams = this.useBlockParams || environment.useBlockParams; + + var opcodes = environment.opcodes, + opcode = undefined, + firstLoc = undefined, + i = undefined, + l = undefined; + + for (i = 0, l = opcodes.length; i < l; i++) { + opcode = opcodes[i]; + + this.source.currentLocation = opcode.loc; + firstLoc = firstLoc || opcode.loc; + this[opcode.opcode].apply(this, opcode.args); + } + + // Flush any trailing content that might be pending. + this.source.currentLocation = firstLoc; + this.pushSource(''); + + /* istanbul ignore next */ + if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { + throw new _exception2['default']('Compile completed with content left on stack'); + } + + if (!this.decorators.isEmpty()) { + this.useDecorators = true; + + this.decorators.prepend('var decorators = container.decorators;\n'); + this.decorators.push('return fn;'); + + if (asObject) { + this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); + } else { + this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); + this.decorators.push('}\n'); + this.decorators = this.decorators.merge(); + } + } else { + this.decorators = undefined; + } + + var fn = this.createFunctionContext(asObject); + if (!this.isChild) { + var ret = { + compiler: this.compilerInfo(), + main: fn + }; + + if (this.decorators) { + ret.main_d = this.decorators; // eslint-disable-line camelcase + ret.useDecorators = true; + } + + var _context = this.context; + var programs = _context.programs; + var decorators = _context.decorators; + + for (i = 0, l = programs.length; i < l; i++) { + if (programs[i]) { + ret[i] = programs[i]; + if (decorators[i]) { + ret[i + '_d'] = decorators[i]; + ret.useDecorators = true; + } + } + } + + if (this.environment.usePartial) { + ret.usePartial = true; + } + if (this.options.data) { + ret.useData = true; + } + if (this.useDepths) { + ret.useDepths = true; + } + if (this.useBlockParams) { + ret.useBlockParams = true; + } + if (this.options.compat) { + ret.compat = true; + } + + if (!asObject) { + ret.compiler = JSON.stringify(ret.compiler); + + this.source.currentLocation = { start: { line: 1, column: 0 } }; + ret = this.objectLiteral(ret); + + if (options.srcName) { + ret = ret.toStringWithSourceMap({ file: options.destName }); + ret.map = ret.map && ret.map.toString(); + } else { + ret = ret.toString(); + } + } else { + ret.compilerOptions = this.options; + } + + return ret; + } else { + return fn; + } + }, + + preamble: function preamble() { + // track the last context pushed into place to allow skipping the + // getContext opcode when it would be a noop + this.lastContext = 0; + this.source = new _codeGen2['default'](this.options.srcName); + this.decorators = new _codeGen2['default'](this.options.srcName); + }, + + createFunctionContext: function createFunctionContext(asObject) { + var varDeclarations = ''; + + var locals = this.stackVars.concat(this.registers.list); + if (locals.length > 0) { + varDeclarations += ', ' + locals.join(', '); + } + + // Generate minimizer alias mappings + // + // When using true SourceNodes, this will update all references to the given alias + // as the source nodes are reused in situ. For the non-source node compilation mode, + // aliases will not be used, but this case is already being run on the client and + // we aren't concern about minimizing the template size. + var aliasCount = 0; + for (var alias in this.aliases) { + // eslint-disable-line guard-for-in + var node = this.aliases[alias]; + + if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { + varDeclarations += ', alias' + ++aliasCount + '=' + alias; + node.children[0] = 'alias' + aliasCount; + } + } + + var params = ['container', 'depth0', 'helpers', 'partials', 'data']; + + if (this.useBlockParams || this.useDepths) { + params.push('blockParams'); + } + if (this.useDepths) { + params.push('depths'); + } + + // Perform a second pass over the output to merge content when possible + var source = this.mergeSource(varDeclarations); + + if (asObject) { + params.push(source); + + return Function.apply(this, params); + } else { + return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); + } + }, + mergeSource: function mergeSource(varDeclarations) { + var isSimple = this.environment.isSimple, + appendOnly = !this.forceBuffer, + appendFirst = undefined, + sourceSeen = undefined, + bufferStart = undefined, + bufferEnd = undefined; + this.source.each(function (line) { + if (line.appendToBuffer) { + if (bufferStart) { + line.prepend(' + '); + } else { + bufferStart = line; + } + bufferEnd = line; + } else { + if (bufferStart) { + if (!sourceSeen) { + appendFirst = true; + } else { + bufferStart.prepend('buffer += '); + } + bufferEnd.add(';'); + bufferStart = bufferEnd = undefined; + } + + sourceSeen = true; + if (!isSimple) { + appendOnly = false; + } + } + }); + + if (appendOnly) { + if (bufferStart) { + bufferStart.prepend('return '); + bufferEnd.add(';'); + } else if (!sourceSeen) { + this.source.push('return "";'); + } + } else { + varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); + + if (bufferStart) { + bufferStart.prepend('return buffer + '); + bufferEnd.add(';'); + } else { + this.source.push('return buffer;'); + } + } + + if (varDeclarations) { + this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); + } + + return this.source.merge(); + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function blockValue(name) { + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs(name, 0, params); + + var blockName = this.popStack(); + params.splice(1, 0, blockName); + + this.push(this.source.functionCall(blockHelperMissing, 'call', params)); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function ambiguousBlockValue() { + // We're being a bit cheeky and reusing the options value from the prior exec + var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs('', 0, params, true); + + this.flushInline(); + + var current = this.topStack(); + params.splice(1, 0, current); + + this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function appendContent(content) { + if (this.pendingContent) { + content = this.pendingContent + content; + } else { + this.pendingLocation = this.source.currentLocation; + } + + this.pendingContent = content; + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function append() { + if (this.isInline()) { + this.replaceStack(function (current) { + return [' != null ? ', current, ' : ""']; + }); + + this.pushSource(this.appendToBuffer(this.popStack())); + } else { + var local = this.popStack(); + this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); + if (this.environment.isSimple) { + this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); + } + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function appendEscaped() { + this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function getContext(depth) { + this.lastContext = depth; + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function pushContext() { + this.pushStackLiteral(this.contextName(this.lastContext)); + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) { + var i = 0; + + if (!scoped && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.push(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); + } + + this.resolvePath('context', parts, i, falsy, strict); + }, + + // [lookupBlockParam] + // + // On stack, before: ... + // On stack, after: blockParam[name], ... + // + // Looks up the value of `parts` on the given block param and pushes + // it onto the stack. + lookupBlockParam: function lookupBlockParam(blockParamId, parts) { + this.useBlockParams = true; + + this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); + this.resolvePath('context', parts, 1); + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data, ... + // + // Push the data lookup operator + lookupData: function lookupData(depth, parts, strict) { + if (!depth) { + this.pushStackLiteral('data'); + } else { + this.pushStackLiteral('container.data(data, ' + depth + ')'); + } + + this.resolvePath('data', parts, 0, true, strict); + }, + + resolvePath: function resolvePath(type, parts, i, falsy, strict) { + // istanbul ignore next + + var _this = this; + + if (this.options.strict || this.options.assumeObjects) { + this.push(strictLookup(this.options.strict && strict, this, parts, type)); + return; + } + + var len = parts.length; + for (; i < len; i++) { + /* eslint-disable no-loop-func */ + this.replaceStack(function (current) { + var lookup = _this.nameLookup(current, parts[i], type); + // We want to ensure that zero and false are handled properly if the context (falsy flag) + // needs to have the special handling for these values. + if (!falsy) { + return [' != null ? ', lookup, ' : ', current]; + } else { + // Otherwise we can use generic falsy handling + return [' && ', lookup]; + } + }); + /* eslint-enable no-loop-func */ + } + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function resolvePossibleLambda() { + this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function pushStringParam(string, type) { + this.pushContext(); + this.pushString(type); + + // If it's a subexpression, the string result + // will be pushed after this opcode. + if (type !== 'SubExpression') { + if (typeof string === 'string') { + this.pushString(string); + } else { + this.pushStackLiteral(string); + } + } + }, + + emptyHash: function emptyHash(omitEmpty) { + if (this.trackIds) { + this.push('{}'); // hashIds + } + if (this.stringParams) { + this.push('{}'); // hashContexts + this.push('{}'); // hashTypes + } + this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); + }, + pushHash: function pushHash() { + if (this.hash) { + this.hashes.push(this.hash); + } + this.hash = { values: [], types: [], contexts: [], ids: [] }; + }, + popHash: function popHash() { + var hash = this.hash; + this.hash = this.hashes.pop(); + + if (this.trackIds) { + this.push(this.objectLiteral(hash.ids)); + } + if (this.stringParams) { + this.push(this.objectLiteral(hash.contexts)); + this.push(this.objectLiteral(hash.types)); + } + + this.push(this.objectLiteral(hash.values)); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function pushString(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function pushLiteral(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function pushProgram(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [registerDecorator] + // + // On stack, before: hash, program, params..., ... + // On stack, after: ... + // + // Pops off the decorator's parameters, invokes the decorator, + // and inserts the decorator into the decorators list. + registerDecorator: function registerDecorator(paramSize, name) { + var foundDecorator = this.nameLookup('decorators', name, 'decorator'), + options = this.setupHelperArgs(name, paramSize); + + this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']); + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function invokeHelper(paramSize, name, isSimple) { + var nonHelper = this.popStack(), + helper = this.setupHelper(paramSize, name), + simple = isSimple ? [helper.name, ' || '] : ''; + + var lookup = ['('].concat(simple, nonHelper); + if (!this.options.strict) { + lookup.push(' || ', this.aliasable('helpers.helperMissing')); + } + lookup.push(')'); + + this.push(this.source.functionCall(lookup, 'call', helper.callParams)); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function invokeKnownHelper(paramSize, name) { + var helper = this.setupHelper(paramSize, name); + this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function invokeAmbiguous(name, helperCall) { + this.useRegister('helper'); + + var nonHelper = this.popStack(); + + this.emptyHash(); + var helper = this.setupHelper(0, name, helperCall); + + var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + + var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; + if (!this.options.strict) { + lookup[0] = '(helper = '; + lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing')); + } + + this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function invokePartial(isDynamic, name, indent) { + var params = [], + options = this.setupParams(name, 1, params); + + if (isDynamic) { + name = this.popStack(); + delete options.name; + } + + if (indent) { + options.indent = JSON.stringify(indent); + } + options.helpers = 'helpers'; + options.partials = 'partials'; + options.decorators = 'container.decorators'; + + if (!isDynamic) { + params.unshift(this.nameLookup('partials', name, 'partial')); + } else { + params.unshift(name); + } + + if (this.options.compat) { + options.depths = 'depths'; + } + options = this.objectLiteral(options); + params.push(options); + + this.push(this.source.functionCall('container.invokePartial', '', params)); + }, + + // [assignToHash] + // + // On stack, before: value, ..., hash, ... + // On stack, after: ..., hash, ... + // + // Pops a value off the stack and assigns it to the current hash + assignToHash: function assignToHash(key) { + var value = this.popStack(), + context = undefined, + type = undefined, + id = undefined; + + if (this.trackIds) { + id = this.popStack(); + } + if (this.stringParams) { + type = this.popStack(); + context = this.popStack(); + } + + var hash = this.hash; + if (context) { + hash.contexts[key] = context; + } + if (type) { + hash.types[key] = type; + } + if (id) { + hash.ids[key] = id; + } + hash.values[key] = value; + }, + + pushId: function pushId(type, name, child) { + if (type === 'BlockParam') { + this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : '')); + } else if (type === 'PathExpression') { + this.pushString(name); + } else if (type === 'SubExpression') { + this.pushStackLiteral('true'); + } else { + this.pushStackLiteral('null'); + } + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function compileChildren(environment, options) { + var children = environment.children, + child = undefined, + compiler = undefined; + + for (var i = 0, l = children.length; i < l; i++) { + child = children[i]; + compiler = new this.compiler(); // eslint-disable-line new-cap + + var existing = this.matchExistingProgram(child); + + if (existing == null) { + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + var index = this.context.programs.length; + child.index = index; + child.name = 'program' + index; + this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); + this.context.decorators[index] = compiler.decorators; + this.context.environments[index] = child; + + this.useDepths = this.useDepths || compiler.useDepths; + this.useBlockParams = this.useBlockParams || compiler.useBlockParams; + child.useDepths = this.useDepths; + child.useBlockParams = this.useBlockParams; + } else { + child.index = existing.index; + child.name = 'program' + existing.index; + + this.useDepths = this.useDepths || existing.useDepths; + this.useBlockParams = this.useBlockParams || existing.useBlockParams; + } + } + }, + matchExistingProgram: function matchExistingProgram(child) { + for (var i = 0, len = this.context.environments.length; i < len; i++) { + var environment = this.context.environments[i]; + if (environment && environment.equals(child)) { + return environment; + } + } + }, + + programExpression: function programExpression(guid) { + var child = this.environment.children[guid], + programParams = [child.index, 'data', child.blockParams]; + + if (this.useBlockParams || this.useDepths) { + programParams.push('blockParams'); + } + if (this.useDepths) { + programParams.push('depths'); + } + + return 'container.program(' + programParams.join(', ') + ')'; + }, + + useRegister: function useRegister(name) { + if (!this.registers[name]) { + this.registers[name] = true; + this.registers.list.push(name); + } + }, + + push: function push(expr) { + if (!(expr instanceof Literal)) { + expr = this.source.wrap(expr); + } + + this.inlineStack.push(expr); + return expr; + }, + + pushStackLiteral: function pushStackLiteral(item) { + this.push(new Literal(item)); + }, + + pushSource: function pushSource(source) { + if (this.pendingContent) { + this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); + this.pendingContent = undefined; + } + + if (source) { + this.source.push(source); + } + }, + + replaceStack: function replaceStack(callback) { + var prefix = ['('], + stack = undefined, + createdStack = undefined, + usedLiteral = undefined; + + /* istanbul ignore next */ + if (!this.isInline()) { + throw new _exception2['default']('replaceStack on non-inline'); + } + + // We want to merge the inline statement into the replacement statement via ',' + var top = this.popStack(true); + + if (top instanceof Literal) { + // Literals do not need to be inlined + stack = [top.value]; + prefix = ['(', stack]; + usedLiteral = true; + } else { + // Get or create the current stack name for use by the inline + createdStack = true; + var _name = this.incrStack(); + + prefix = ['((', this.push(_name), ' = ', top, ')']; + stack = this.topStack(); + } + + var item = callback.call(this, stack); + + if (!usedLiteral) { + this.popStack(); + } + if (createdStack) { + this.stackSlot--; + } + this.push(prefix.concat(item, ')')); + }, + + incrStack: function incrStack() { + this.stackSlot++; + if (this.stackSlot > this.stackVars.length) { + this.stackVars.push('stack' + this.stackSlot); + } + return this.topStackName(); + }, + topStackName: function topStackName() { + return 'stack' + this.stackSlot; + }, + flushInline: function flushInline() { + var inlineStack = this.inlineStack; + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + /* istanbul ignore if */ + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + var stack = this.incrStack(); + this.pushSource([stack, ' = ', entry, ';']); + this.compileStack.push(stack); + } + } + }, + isInline: function isInline() { + return this.inlineStack.length; + }, + + popStack: function popStack(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && item instanceof Literal) { + return item.value; + } else { + if (!inline) { + /* istanbul ignore next */ + if (!this.stackSlot) { + throw new _exception2['default']('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function topStack() { + var stack = this.isInline() ? this.inlineStack : this.compileStack, + item = stack[stack.length - 1]; + + /* istanbul ignore if */ + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + contextName: function contextName(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + + quotedString: function quotedString(str) { + return this.source.quotedString(str); + }, + + objectLiteral: function objectLiteral(obj) { + return this.source.objectLiteral(obj); + }, + + aliasable: function aliasable(name) { + var ret = this.aliases[name]; + if (ret) { + ret.referenceCount++; + return ret; + } + + ret = this.aliases[name] = this.source.wrap(name); + ret.aliasable = true; + ret.referenceCount = 1; + + return ret; + }, + + setupHelper: function setupHelper(paramSize, name, blockHelper) { + var params = [], + paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); + var foundHelper = this.nameLookup('helpers', name, 'helper'), + callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : {}'); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: [callContext].concat(params) + }; + }, + + setupParams: function setupParams(helper, paramSize, params) { + var options = {}, + contexts = [], + types = [], + ids = [], + objectArgs = !params, + param = undefined; + + if (objectArgs) { + params = []; + } + + options.name = this.quotedString(helper); + options.hash = this.popStack(); + + if (this.trackIds) { + options.hashIds = this.popStack(); + } + if (this.stringParams) { + options.hashTypes = this.popStack(); + options.hashContexts = this.popStack(); + } + + var inverse = this.popStack(), + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + options.fn = program || 'container.noop'; + options.inverse = inverse || 'container.noop'; + } + + // The parameters go on to the stack in order (making sure that they are evaluated in order) + // so we need to pop them off the stack in reverse order + var i = paramSize; + while (i--) { + param = this.popStack(); + params[i] = param; + + if (this.trackIds) { + ids[i] = this.popStack(); + } + if (this.stringParams) { + types[i] = this.popStack(); + contexts[i] = this.popStack(); + } + } + + if (objectArgs) { + options.args = this.source.generateArray(params); + } + + if (this.trackIds) { + options.ids = this.source.generateArray(ids); + } + if (this.stringParams) { + options.types = this.source.generateArray(types); + options.contexts = this.source.generateArray(contexts); + } + + if (this.options.data) { + options.data = 'data'; + } + if (this.useBlockParams) { + options.blockParams = 'blockParams'; + } + return options; + }, + + setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) { + var options = this.setupParams(helper, paramSize, params); + options = this.objectLiteral(options); + if (useRegister) { + this.useRegister('options'); + params.push('options'); + return ['options=', options]; + } else if (params) { + params.push(options); + return ''; + } else { + return options; + } + } + }; + + (function () { + var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' '); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for (var i = 0, l = reservedWords.length; i < l; i++) { + compilerWords[reservedWords[i]] = true; + } + })(); + + JavaScriptCompiler.isValidJavaScriptVariableName = function (name) { + return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); + }; + + function strictLookup(requireTerminal, compiler, parts, type) { + var stack = compiler.popStack(), + i = 0, + len = parts.length; + if (requireTerminal) { + len--; + } + + for (; i < len; i++) { + stack = compiler.nameLookup(stack, parts[i], type); + } + + if (requireTerminal) { + return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')']; + } else { + return stack; + } + } + + exports['default'] = JavaScriptCompiler; + module.exports = exports['default']; + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + /* global define */ + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(5); + + var SourceNode = undefined; + + try { + /* istanbul ignore next */ + if (false) { + // We don't support this in AMD environments. For these environments, we asusme that + // they are running on the browser and thus have no need for the source-map library. + var SourceMap = require('source-map'); + SourceNode = SourceMap.SourceNode; + } + } catch (err) {} + /* NOP */ + + /* istanbul ignore if: tested but not covered in istanbul due to dist build */ + if (!SourceNode) { + SourceNode = function (line, column, srcFile, chunks) { + this.src = ''; + if (chunks) { + this.add(chunks); + } + }; + /* istanbul ignore next */ + SourceNode.prototype = { + add: function add(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src += chunks; + }, + prepend: function prepend(chunks) { + if (_utils.isArray(chunks)) { + chunks = chunks.join(''); + } + this.src = chunks + this.src; + }, + toStringWithSourceMap: function toStringWithSourceMap() { + return { code: this.toString() }; + }, + toString: function toString() { + return this.src; + } + }; + } + + function castChunk(chunk, codeGen, loc) { + if (_utils.isArray(chunk)) { + var ret = []; + + for (var i = 0, len = chunk.length; i < len; i++) { + ret.push(codeGen.wrap(chunk[i], loc)); + } + return ret; + } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { + // Handle primitives that the SourceNode will throw up on + return chunk + ''; + } + return chunk; + } + + function CodeGen(srcFile) { + this.srcFile = srcFile; + this.source = []; + } + + CodeGen.prototype = { + isEmpty: function isEmpty() { + return !this.source.length; + }, + prepend: function prepend(source, loc) { + this.source.unshift(this.wrap(source, loc)); + }, + push: function push(source, loc) { + this.source.push(this.wrap(source, loc)); + }, + + merge: function merge() { + var source = this.empty(); + this.each(function (line) { + source.add([' ', line, '\n']); + }); + return source; + }, + + each: function each(iter) { + for (var i = 0, len = this.source.length; i < len; i++) { + iter(this.source[i]); + } + }, + + empty: function empty() { + var loc = this.currentLocation || { start: {} }; + return new SourceNode(loc.start.line, loc.start.column, this.srcFile); + }, + wrap: function wrap(chunk) { + var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1]; + + if (chunk instanceof SourceNode) { + return chunk; + } + + chunk = castChunk(chunk, this, loc); + + return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); + }, + + functionCall: function functionCall(fn, type, params) { + params = this.generateList(params); + return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); + }, + + quotedString: function quotedString(str) { + return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + objectLiteral: function objectLiteral(obj) { + var pairs = []; + + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var value = castChunk(obj[key], this); + if (value !== 'undefined') { + pairs.push([this.quotedString(key), ':', value]); + } + } + } + + var ret = this.generateList(pairs); + ret.prepend('{'); + ret.add('}'); + return ret; + }, + + generateList: function generateList(entries) { + var ret = this.empty(); + + for (var i = 0, len = entries.length; i < len; i++) { + if (i) { + ret.add(','); + } + + ret.add(castChunk(entries[i], this)); + } + + return ret; + }, + + generateArray: function generateArray(entries) { + var ret = this.generateList(entries); + ret.prepend('['); + ret.add(']'); + + return ret; + } + }; + + exports['default'] = CodeGen; + module.exports = exports['default']; + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/hm_sunwell/node_modules/handlebars/dist/handlebars.min.js b/hm_sunwell/node_modules/handlebars/dist/handlebars.min.js new file mode 100644 index 0000000..cfcd63e --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/handlebars.min.js @@ -0,0 +1,81 @@ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +!function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?exports.Handlebars=b():a.Handlebars=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){"use strict";function d(){var a=r();return a.compile=function(b,c){return k.compile(b,c,a)},a.precompile=function(b,c){return k.precompile(b,c,a)},a.AST=i["default"],a.Compiler=k.Compiler,a.JavaScriptCompiler=m["default"],a.Parser=j.parser,a.parse=j.parse,a}var e=c(1)["default"];b.__esModule=!0;var f=c(2),g=e(f),h=c(24),i=e(h),j=c(25),k=c(30),l=c(31),m=e(l),n=c(28),o=e(n),p=c(23),q=e(p),r=g["default"].create,s=d();s.create=d,q["default"](s),s.Visitor=o["default"],s["default"]=s,b["default"]=s,a.exports=b["default"]},function(a,b){"use strict";b["default"]=function(a){return a&&a.__esModule?a:{"default":a}},b.__esModule=!0},function(a,b,c){"use strict";function d(){var a=new h.HandlebarsEnvironment;return n.extend(a,h),a.SafeString=j["default"],a.Exception=l["default"],a.Utils=n,a.escapeExpression=n.escapeExpression,a.VM=p,a.template=function(b){return p.template(b,a)},a}var e=c(3)["default"],f=c(1)["default"];b.__esModule=!0;var g=c(4),h=e(g),i=c(21),j=f(i),k=c(6),l=f(k),m=c(5),n=e(m),o=c(22),p=e(o),q=c(23),r=f(q),s=d();s.create=d,r["default"](s),s["default"]=s,b["default"]=s,a.exports=b["default"]},function(a,b){"use strict";b["default"]=function(a){if(a&&a.__esModule)return a;var b={};if(null!=a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]=a[c]);return b["default"]=a,b},b.__esModule=!0},function(a,b,c){"use strict";function d(a,b,c){this.helpers=a||{},this.partials=b||{},this.decorators=c||{},i.registerDefaultHelpers(this),j.registerDefaultDecorators(this)}var e=c(1)["default"];b.__esModule=!0,b.HandlebarsEnvironment=d;var f=c(5),g=c(6),h=e(g),i=c(10),j=c(18),k=c(20),l=e(k),m="4.0.5";b.VERSION=m;var n=7;b.COMPILER_REVISION=n;var o={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0"};b.REVISION_CHANGES=o;var p="[object Object]";d.prototype={constructor:d,logger:l["default"],log:l["default"].log,registerHelper:function(a,b){if(f.toString.call(a)===p){if(b)throw new h["default"]("Arg not supported with multiple helpers");f.extend(this.helpers,a)}else this.helpers[a]=b},unregisterHelper:function(a){delete this.helpers[a]},registerPartial:function(a,b){if(f.toString.call(a)===p)f.extend(this.partials,a);else{if("undefined"==typeof b)throw new h["default"]('Attempting to register a partial called "'+a+'" as undefined');this.partials[a]=b}},unregisterPartial:function(a){delete this.partials[a]},registerDecorator:function(a,b){if(f.toString.call(a)===p){if(b)throw new h["default"]("Arg not supported with multiple decorators");f.extend(this.decorators,a)}else this.decorators[a]=b},unregisterDecorator:function(a){delete this.decorators[a]}};var q=l["default"].log;b.log=q,b.createFrame=f.createFrame,b.logger=l["default"]},function(a,b){"use strict";function c(a){return k[a]}function d(a){for(var b=1;b":">",'"':""","'":"'","`":"`","=":"="},l=/[&<>"'`=]/g,m=/[&<>"'`=]/,n=Object.prototype.toString;b.toString=n;var o=function(a){return"function"==typeof a};o(/x/)&&(b.isFunction=o=function(a){return"function"==typeof a&&"[object Function]"===n.call(a)}),b.isFunction=o;var p=Array.isArray||function(a){return!(!a||"object"!=typeof a)&&"[object Array]"===n.call(a)};b.isArray=p},function(a,b,c){"use strict";function d(a,b){var c=b&&b.loc,g=void 0,h=void 0;c&&(g=c.start.line,h=c.start.column,a+=" - "+g+":"+h);for(var i=Error.prototype.constructor.call(this,a),j=0;j0?(c.ids&&(c.ids=[c.name]),a.helpers.each(b,c)):e(this);if(c.data&&c.ids){var g=d.createFrame(c.data);g.contextPath=d.appendContextPath(c.data.contextPath,c.name),c={data:g}}return f(b,c)})},a.exports=b["default"]},function(a,b,c){"use strict";var d=c(1)["default"];b.__esModule=!0;var e=c(5),f=c(6),g=d(f);b["default"]=function(a){a.registerHelper("each",function(a,b){function c(b,c,f){j&&(j.key=b,j.index=c,j.first=0===c,j.last=!!f,k&&(j.contextPath=k+b)),i+=d(a[b],{data:j,blockParams:e.blockParams([a[b],b],[k+b,null])})}if(!b)throw new g["default"]("Must pass iterator to #each");var d=b.fn,f=b.inverse,h=0,i="",j=void 0,k=void 0;if(b.data&&b.ids&&(k=e.appendContextPath(b.data.contextPath,b.ids[0])+"."),e.isFunction(a)&&(a=a.call(this)),b.data&&(j=e.createFrame(b.data)),a&&"object"==typeof a)if(e.isArray(a))for(var l=a.length;h=0?b:parseInt(a,10)}return a},log:function(a){if(a=e.lookupLevel(a),"undefined"!=typeof console&&e.lookupLevel(e.level)<=a){var b=e.methodMap[a];console[b]||(b="log");for(var c=arguments.length,d=Array(c>1?c-1:0),f=1;f2&&v.push("'"+this.terminals_[s]+"'");x=this.lexer.showPosition?"Parse error on line "+(i+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+v.join(", ")+", got '"+(this.terminals_[n]||n)+"'":"Parse error on line "+(i+1)+": Unexpected "+(1==n?"end of input":"'"+(this.terminals_[n]||n)+"'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[n]||n,line:this.lexer.yylineno,loc:l,expected:v})}}if(q[0]instanceof Array&&q.length>1)throw new Error("Parse Error: multiple actions possible at state: "+p+", token: "+n);switch(q[0]){case 1:d.push(n),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(q[1]),n=null,o?(n=o,o=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,l=this.lexer.yylloc,k>0&&k--);break;case 2:if(t=this.productions_[q[1]][1],w.$=e[e.length-t],w._$={first_line:f[f.length-(t||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(t||1)].first_column,last_column:f[f.length-1].last_column},m&&(w._$.range=[f[f.length-(t||1)].range[0],f[f.length-1].range[1]]),r=this.performAction.call(w,h,j,i,this.yy,q[1],e,f),"undefined"!=typeof r)return r;t&&(d=d.slice(0,-1*t*2),e=e.slice(0,-1*t),f=f.slice(0,-1*t)),d.push(this.productions_[q[1]][0]),e.push(w.$),f.push(w._$),u=g[d[d.length-2]][d[d.length-1]],d.push(u);break;case 3:return!0}}return!0}},c=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a){return this._input=a,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\r\n?|\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b-1),this.offset-=b;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this},more:function(){return this._more=!0,this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d,e;this._more||(this.yytext="",this.match="");for(var f=this._currentRules(),g=0;gb[0].length)||(b=c,d=g,this.options.flex));g++);return b?(e=b[0].match(/(?:\r\n?|\n).*/g),e&&(this.yylineno+=e.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:e?e[e.length-1].length-e[e.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],a=this.performAction.call(this,this.yy,this,f[d],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),a?a:void 0):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return"undefined"!=typeof a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(a){this.begin(a)}};return a.options={},a.performAction=function(a,b,c,d){function e(a,c){return b.yytext=b.yytext.substr(a,b.yyleng-c)}switch(c){case 0:if("\\\\"===b.yytext.slice(-2)?(e(0,1),this.begin("mu")):"\\"===b.yytext.slice(-1)?(e(0,1),this.begin("emu")):this.begin("mu"),b.yytext)return 15;break;case 1:return 15;case 2:return this.popState(),15;case 3:return this.begin("raw"),15;case 4:return this.popState(),"raw"===this.conditionStack[this.conditionStack.length-1]?15:(b.yytext=b.yytext.substr(5,b.yyleng-9),"END_RAW_BLOCK");case 5:return 15;case 6:return this.popState(),14;case 7:return 65;case 8:return 68;case 9:return 19;case 10:return this.popState(),this.begin("raw"),23;case 11:return 55;case 12:return 60;case 13:return 29;case 14:return 47;case 15:return this.popState(),44;case 16:return this.popState(),44;case 17:return 34;case 18:return 39;case 19:return 51;case 20:return 48;case 21:this.unput(b.yytext),this.popState(),this.begin("com");break;case 22:return this.popState(),14;case 23:return 48;case 24:return 73;case 25:return 72;case 26:return 72;case 27:return 87;case 28:break;case 29:return this.popState(),54;case 30:return this.popState(),33;case 31:return b.yytext=e(1,2).replace(/\\"/g,'"'),80;case 32:return b.yytext=e(1,2).replace(/\\'/g,"'"),80;case 33:return 85;case 34:return 82;case 35:return 82;case 36:return 83;case 37:return 84;case 38:return 81;case 39:return 75;case 40:return 77;case 41:return 72;case 42:return b.yytext=b.yytext.replace(/\\([\\\]])/g,"$1"),72;case 43:return"INVALID";case 44:return 5}},a.rules=[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{(?=[^\/]))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#>)/,/^(?:\{\{(~)?#\*?)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?\*?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:undefined(?=([~}\s)])))/,/^(?:null(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[(\\\]|[^\]])*\])/,/^(?:.)/,/^(?:$)/],a.conditions={mu:{rules:[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[6],inclusive:!1},raw:{rules:[3,4,5],inclusive:!1},INITIAL:{rules:[0,1,44],inclusive:!0}},a}();return b.lexer=c,a.prototype=b,b.Parser=a,new a}();b.__esModule=!0,b["default"]=c},function(a,b,c){"use strict";function d(){var a=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.options=a}function e(a,b,c){void 0===b&&(b=a.length);var d=a[b-1],e=a[b-2];return d?"ContentStatement"===d.type?(e||!c?/\r?\n\s*?$/:/(^|\r?\n)\s*?$/).test(d.original):void 0:c}function f(a,b,c){void 0===b&&(b=-1);var d=a[b+1],e=a[b+2];return d?"ContentStatement"===d.type?(e||!c?/^\s*?\r?\n/:/^\s*?(\r?\n|$)/).test(d.original):void 0:c}function g(a,b,c){var d=a[null==b?0:b+1];if(d&&"ContentStatement"===d.type&&(c||!d.rightStripped)){var e=d.value;d.value=d.value.replace(c?/^\s+/:/^[ \t]*\r?\n?/,""),d.rightStripped=d.value!==e}}function h(a,b,c){var d=a[null==b?a.length-1:b-1];if(d&&"ContentStatement"===d.type&&(c||!d.leftStripped)){var e=d.value;return d.value=d.value.replace(c?/\s+$/:/[ \t]+$/,""),d.leftStripped=d.value!==e,d.leftStripped}}var i=c(1)["default"];b.__esModule=!0;var j=c(28),k=i(j);d.prototype=new k["default"],d.prototype.Program=function(a){var b=!this.options.ignoreStandalone,c=!this.isRootSeen;this.isRootSeen=!0;for(var d=a.body,i=0,j=d.length;i0)throw new q["default"]("Invalid path: "+d,{loc:c});".."===j&&(f++,g+="../")}}return{type:"PathExpression",data:a,depth:f,parts:e,original:d,loc:c}}function j(a,b,c,d,e,f){var g=d.charAt(3)||d.charAt(2),h="{"!==g&&"&"!==g,i=/\*/.test(d);return{type:i?"Decorator":"MustacheStatement",path:a,params:b,hash:c,escaped:h,strip:e,loc:this.locInfo(f)}}function k(a,b,c,e){d(a,c),e=this.locInfo(e);var f={type:"Program",body:b,strip:{},loc:e};return{type:"BlockStatement",path:a.path,params:a.params,hash:a.hash,program:f,openStrip:{},inverseStrip:{},closeStrip:{},loc:e}}function l(a,b,c,e,f,g){e&&e.path&&d(a,e);var h=/\*/.test(a.open);b.blockParams=a.blockParams;var i=void 0,j=void 0;if(c){if(h)throw new q["default"]("Unexpected inverse block on decorator",c);c.chain&&(c.program.body[0].closeStrip=e.strip),j=c.strip,i=c.program}return f&&(f=i,i=b,b=f),{type:h?"DecoratorBlock":"BlockStatement",path:a.path,params:a.params,hash:a.hash,program:b,inverse:i,openStrip:a.strip,inverseStrip:j,closeStrip:e&&e.strip,loc:this.locInfo(g)}}function m(a,b){if(!b&&a.length){var c=a[0].loc,d=a[a.length-1].loc;c&&d&&(b={source:c.source,start:{line:c.start.line,column:c.start.column},end:{line:d.end.line,column:d.end.column}})}return{type:"Program",body:a,strip:{},loc:b}}function n(a,b,c,e){return d(a,c),{type:"PartialBlockStatement",name:a.path,params:a.params,hash:a.hash,program:b,openStrip:a.strip,closeStrip:c&&c.strip,loc:this.locInfo(e)}}var o=c(1)["default"];b.__esModule=!0,b.SourceLocation=e,b.id=f,b.stripFlags=g,b.stripComment=h,b.preparePath=i,b.prepareMustache=j,b.prepareRawBlock=k,b.prepareBlock=l,b.prepareProgram=m,b.preparePartialBlock=n;var p=c(6),q=o(p)},function(a,b,c){"use strict";function d(){}function e(a,b,c){if(null==a||"string"!=typeof a&&"Program"!==a.type)throw new k["default"]("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+a);b=b||{},"data"in b||(b.data=!0),b.compat&&(b.useDepths=!0);var d=c.parse(a,b),e=(new c.Compiler).compile(d,b);return(new c.JavaScriptCompiler).compile(e,b)}function f(a,b,c){function d(){var d=c.parse(a,b),e=(new c.Compiler).compile(d,b),f=(new c.JavaScriptCompiler).compile(e,b,void 0,!0);return c.template(f)}function e(a,b){return f||(f=d()),f.call(this,a,b)}if(void 0===b&&(b={}),null==a||"string"!=typeof a&&"Program"!==a.type)throw new k["default"]("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+a);"data"in b||(b.data=!0),b.compat&&(b.useDepths=!0);var f=void 0;return e._setup=function(a){return f||(f=d()),f._setup(a)},e._child=function(a,b,c,e){return f||(f=d()),f._child(a,b,c,e)},e}function g(a,b){if(a===b)return!0;if(l.isArray(a)&&l.isArray(b)&&a.length===b.length){for(var c=0;c1)throw new k["default"]("Unsupported number of partial arguments: "+c.length,a);c.length||(this.options.explicitPartialContext?this.opcode("pushLiteral","undefined"):c.push({type:"PathExpression",parts:[],depth:0}));var d=a.name.original,e="SubExpression"===a.name.type;e&&this.accept(a.name),this.setupFullMustacheParams(a,b,void 0,!0);var f=a.indent||"";this.options.preventIndent&&f&&(this.opcode("appendContent",f),f=""),this.opcode("invokePartial",e,d,f),this.opcode("append")},PartialBlockStatement:function(a){this.PartialStatement(a)},MustacheStatement:function(a){this.SubExpression(a),a.escaped&&!this.options.noEscape?this.opcode("appendEscaped"):this.opcode("append")},Decorator:function(a){this.DecoratorBlock(a)},ContentStatement:function(a){a.value&&this.opcode("appendContent",a.value)},CommentStatement:function(){},SubExpression:function(a){h(a);var b=this.classifySexpr(a);"simple"===b?this.simpleSexpr(a):"helper"===b?this.helperSexpr(a):this.ambiguousSexpr(a)},ambiguousSexpr:function(a,b,c){var d=a.path,e=d.parts[0],f=null!=b||null!=c;this.opcode("getContext",d.depth),this.opcode("pushProgram",b),this.opcode("pushProgram",c),d.strict=!0,this.accept(d),this.opcode("invokeAmbiguous",e,f)},simpleSexpr:function(a){var b=a.path;b.strict=!0,this.accept(b),this.opcode("resolvePossibleLambda")},helperSexpr:function(a,b,c){var d=this.setupFullMustacheParams(a,b,c),e=a.path,f=e.parts[0];if(this.options.knownHelpers[f])this.opcode("invokeKnownHelper",d.length,f);else{if(this.options.knownHelpersOnly)throw new k["default"]("You specified knownHelpersOnly, but used the unknown helper "+f,a);e.strict=!0,e.falsy=!0,this.accept(e),this.opcode("invokeHelper",d.length,e.original,n["default"].helpers.simpleId(e))}},PathExpression:function(a){this.addDepth(a.depth),this.opcode("getContext",a.depth);var b=a.parts[0],c=n["default"].helpers.scopedId(a),d=!a.depth&&!c&&this.blockParamIndex(b);d?this.opcode("lookupBlockParam",d,a.parts):b?a.data?(this.options.data=!0,this.opcode("lookupData",a.depth,a.parts,a.strict)):this.opcode("lookupOnContext",a.parts,a.falsy,a.strict,c):this.opcode("pushContext")},StringLiteral:function(a){this.opcode("pushString",a.value)},NumberLiteral:function(a){this.opcode("pushLiteral",a.value)},BooleanLiteral:function(a){this.opcode("pushLiteral",a.value)},UndefinedLiteral:function(){this.opcode("pushLiteral","undefined")},NullLiteral:function(){this.opcode("pushLiteral","null")},Hash:function(a){var b=a.pairs,c=0,d=b.length;for(this.opcode("pushHash");c=0)return[b,e]}}}},function(a,b,c){"use strict";function d(a){this.value=a}function e(){}function f(a,b,c,d){var e=b.popStack(),f=0,g=c.length;for(a&&g--;f0&&(b+=", "+c.join(", "));var d=0;for(var e in this.aliases){var f=this.aliases[e];this.aliases.hasOwnProperty(e)&&f.children&&f.referenceCount>1&&(b+=", alias"+ ++d+"="+e,f.children[0]="alias"+d)}var g=["container","depth0","helpers","partials","data"];(this.useBlockParams||this.useDepths)&&g.push("blockParams"),this.useDepths&&g.push("depths");var h=this.mergeSource(b);return a?(g.push(h),Function.apply(this,g)):this.source.wrap(["function(",g.join(","),") {\n ",h,"}"])},mergeSource:function(a){var b=this.environment.isSimple,c=!this.forceBuffer,d=void 0,e=void 0,f=void 0,g=void 0;return this.source.each(function(a){a.appendToBuffer?(f?a.prepend(" + "):f=a,g=a):(f&&(e?f.prepend("buffer += "):d=!0,g.add(";"),f=g=void 0),e=!0,b||(c=!1))}),c?f?(f.prepend("return "),g.add(";")):e||this.source.push('return "";'):(a+=", buffer = "+(d?"":this.initializeBuffer()),f?(f.prepend("return buffer + "),g.add(";")):this.source.push("return buffer;")),a&&this.source.prepend("var "+a.substring(2)+(d?"":";\n")),this.source.merge()},blockValue:function(a){var b=this.aliasable("helpers.blockHelperMissing"),c=[this.contextName(0)];this.setupHelperArgs(a,0,c);var d=this.popStack();c.splice(1,0,d),this.push(this.source.functionCall(b,"call",c))},ambiguousBlockValue:function(){var a=this.aliasable("helpers.blockHelperMissing"),b=[this.contextName(0)];this.setupHelperArgs("",0,b,!0),this.flushInline();var c=this.topStack();b.splice(1,0,c),this.pushSource(["if (!",this.lastHelper,") { ",c," = ",this.source.functionCall(a,"call",b),"}"])},appendContent:function(a){this.pendingContent?a=this.pendingContent+a:this.pendingLocation=this.source.currentLocation,this.pendingContent=a},append:function(){if(this.isInline())this.replaceStack(function(a){return[" != null ? ",a,' : ""']}),this.pushSource(this.appendToBuffer(this.popStack()));else{var a=this.popStack();this.pushSource(["if (",a," != null) { ",this.appendToBuffer(a,void 0,!0)," }"]),this.environment.isSimple&&this.pushSource(["else { ",this.appendToBuffer("''",void 0,!0)," }"])}},appendEscaped:function(){this.pushSource(this.appendToBuffer([this.aliasable("container.escapeExpression"),"(",this.popStack(),")"]))},getContext:function(a){this.lastContext=a},pushContext:function(){this.pushStackLiteral(this.contextName(this.lastContext))},lookupOnContext:function(a,b,c,d){var e=0;d||!this.options.compat||this.lastContext?this.pushContext():this.push(this.depthedLookup(a[e++])),this.resolvePath("context",a,e,b,c)},lookupBlockParam:function(a,b){this.useBlockParams=!0,this.push(["blockParams[",a[0],"][",a[1],"]"]),this.resolvePath("context",b,1)},lookupData:function(a,b,c){a?this.pushStackLiteral("container.data(data, "+a+")"):this.pushStackLiteral("data"),this.resolvePath("data",b,0,!0,c)},resolvePath:function(a,b,c,d,e){var g=this;if(this.options.strict||this.options.assumeObjects)return void this.push(f(this.options.strict&&e,this,b,a));for(var h=b.length;cthis.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var a=this.inlineStack;this.inlineStack=[];for(var b=0,c=a.length;b': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' + }; + + var badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + + function escapeChar(chr) { + return escape[chr]; + } + + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; + } + + var toString = Object.prototype.toString; + + exports.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + /* eslint-disable func-style */ + var isFunction = function isFunction(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + exports.isFunction = isFunction = function (value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + exports.isFunction = isFunction; + + /* eslint-enable func-style */ + + /* istanbul ignore next */ + var isArray = Array.isArray || function (value) { + return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; + }; + + exports.isArray = isArray; + // Older IE versions do not directly support indexOf so we must implement our own, sadly. + + function indexOf(array, value) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; + } + + function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); + } + + function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + function createFrame(object) { + var frame = extend({}, object); + frame._parent = object; + return frame; + } + + function blockParams(params, ids) { + params.path = ids; + return params; + } + + function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3V0aWxzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQUEsTUFBTSxNQUFNLEdBQUc7QUFDYixPQUFHLEVBQUUsT0FBTztBQUNaLE9BQUcsRUFBRSxNQUFNO0FBQ1gsT0FBRyxFQUFFLE1BQU07QUFDWCxPQUFHLEVBQUUsUUFBUTtBQUNiLE9BQUcsRUFBRSxRQUFRO0FBQ2IsT0FBRyxFQUFFLFFBQVE7QUFDYixPQUFHLEVBQUUsUUFBUTtHQUNkLENBQUM7O0FBRUYsTUFBTSxRQUFRLEdBQUcsWUFBWTtNQUN2QixRQUFRLEdBQUcsV0FBVyxDQUFDOztBQUU3QixXQUFTLFVBQVUsQ0FBQyxHQUFHLEVBQUU7QUFDdkIsV0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7R0FDcEI7O0FBRU0sV0FBUyxNQUFNLENBQUMsR0FBRyxvQkFBbUI7QUFDM0MsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDekMsV0FBSyxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7QUFDNUIsWUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFO0FBQzNELGFBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDOUI7T0FDRjtLQUNGOztBQUVELFdBQU8sR0FBRyxDQUFDO0dBQ1o7O0FBRU0sTUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7Ozs7OztBQUtoRCxNQUFJLFVBQVUsR0FBRyxvQkFBUyxLQUFLLEVBQUU7QUFDL0IsV0FBTyxPQUFPLEtBQUssS0FBSyxVQUFVLENBQUM7R0FDcEMsQ0FBQzs7O0FBR0YsTUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7QUFDbkIsWUFJTSxVQUFVLEdBSmhCLFVBQVUsR0FBRyxVQUFTLEtBQUssRUFBRTtBQUMzQixhQUFPLE9BQU8sS0FBSyxLQUFLLFVBQVUsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLG1CQUFtQixDQUFDO0tBQ3BGLENBQUM7R0FDSDtVQUNPLFVBQVUsR0FBVixVQUFVOzs7OztBQUlYLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLElBQUksVUFBUyxLQUFLLEVBQUU7QUFDdEQsV0FBTyxBQUFDLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEdBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7R0FDakcsQ0FBQzs7Ozs7QUFHSyxXQUFTLE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQ3BDLFNBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDaEQsVUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxFQUFFO0FBQ3RCLGVBQU8sQ0FBQyxDQUFDO09BQ1Y7S0FDRjtBQUNELFdBQU8sQ0FBQyxDQUFDLENBQUM7R0FDWDs7QUFHTSxXQUFTLGdCQUFnQixDQUFDLE1BQU0sRUFBRTtBQUN2QyxRQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsRUFBRTs7QUFFOUIsVUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtBQUMzQixlQUFPLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztPQUN4QixNQUFNLElBQUksTUFBTSxJQUFJLElBQUksRUFBRTtBQUN6QixlQUFPLEVBQUUsQ0FBQztPQUNYLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRTtBQUNsQixlQUFPLE1BQU0sR0FBRyxFQUFFLENBQUM7T0FDcEI7Ozs7O0FBS0QsWUFBTSxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUM7S0FDdEI7O0FBRUQsUUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7QUFBRSxhQUFPLE1BQU0sQ0FBQztLQUFFO0FBQzlDLFdBQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7R0FDN0M7O0FBRU0sV0FBUyxPQUFPLENBQUMsS0FBSyxFQUFFO0FBQzdCLFFBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxLQUFLLENBQUMsRUFBRTtBQUN6QixhQUFPLElBQUksQ0FBQztLQUNiLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7QUFDL0MsYUFBTyxJQUFJLENBQUM7S0FDYixNQUFNO0FBQ0wsYUFBTyxLQUFLLENBQUM7S0FDZDtHQUNGOztBQUVNLFdBQVMsV0FBVyxDQUFDLE1BQU0sRUFBRTtBQUNsQyxRQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQy9CLFNBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO0FBQ3ZCLFdBQU8sS0FBSyxDQUFDO0dBQ2Q7O0FBRU0sV0FBUyxXQUFXLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtBQUN2QyxVQUFNLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztBQUNsQixXQUFPLE1BQU0sQ0FBQztHQUNmOztBQUVNLFdBQVMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEVBQUUsRUFBRTtBQUNqRCxXQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFBLEdBQUksRUFBRSxDQUFDO0dBQ3BEIiwiZmlsZSI6InV0aWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgZXNjYXBlID0ge1xuICAnJic6ICcmYW1wOycsXG4gICc8JzogJyZsdDsnLFxuICAnPic6ICcmZ3Q7JyxcbiAgJ1wiJzogJyZxdW90OycsXG4gIFwiJ1wiOiAnJiN4Mjc7JyxcbiAgJ2AnOiAnJiN4NjA7JyxcbiAgJz0nOiAnJiN4M0Q7J1xufTtcblxuY29uc3QgYmFkQ2hhcnMgPSAvWyY8PlwiJ2A9XS9nLFxuICAgICAgcG9zc2libGUgPSAvWyY8PlwiJ2A9XS87XG5cbmZ1bmN0aW9uIGVzY2FwZUNoYXIoY2hyKSB7XG4gIHJldHVybiBlc2NhcGVbY2hyXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZChvYmovKiAsIC4uLnNvdXJjZSAqLykge1xuICBmb3IgKGxldCBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIGZvciAobGV0IGtleSBpbiBhcmd1bWVudHNbaV0pIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYXJndW1lbnRzW2ldLCBrZXkpKSB7XG4gICAgICAgIG9ialtrZXldID0gYXJndW1lbnRzW2ldW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZXhwb3J0IGxldCB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8vIFNvdXJjZWQgZnJvbSBsb2Rhc2hcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iZXN0aWVqcy9sb2Rhc2gvYmxvYi9tYXN0ZXIvTElDRU5TRS50eHRcbi8qIGVzbGludC1kaXNhYmxlIGZ1bmMtc3R5bGUgKi9cbmxldCBpc0Z1bmN0aW9uID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcbn07XG4vLyBmYWxsYmFjayBmb3Igb2xkZXIgdmVyc2lvbnMgb2YgQ2hyb21lIGFuZCBTYWZhcmlcbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5pZiAoaXNGdW5jdGlvbigveC8pKSB7XG4gIGlzRnVuY3Rpb24gPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicgJiYgdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG4gIH07XG59XG5leHBvcnQge2lzRnVuY3Rpb259O1xuLyogZXNsaW50LWVuYWJsZSBmdW5jLXN0eWxlICovXG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5leHBvcnQgY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSA/IHRvU3RyaW5nLmNhbGwodmFsdWUpID09PSAnW29iamVjdCBBcnJheV0nIDogZmFsc2U7XG59O1xuXG4vLyBPbGRlciBJRSB2ZXJzaW9ucyBkbyBub3QgZGlyZWN0bHkgc3VwcG9ydCBpbmRleE9mIHNvIHdlIG11c3QgaW1wbGVtZW50IG91ciBvd24sIHNhZGx5LlxuZXhwb3J0IGZ1bmN0aW9uIGluZGV4T2YoYXJyYXksIHZhbHVlKSB7XG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBhcnJheS5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGlmIChhcnJheVtpXSA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gLTE7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZUV4cHJlc3Npb24oc3RyaW5nKSB7XG4gIGlmICh0eXBlb2Ygc3RyaW5nICE9PSAnc3RyaW5nJykge1xuICAgIC8vIGRvbid0IGVzY2FwZSBTYWZlU3RyaW5ncywgc2luY2UgdGhleSdyZSBhbHJlYWR5IHNhZmVcbiAgICBpZiAoc3RyaW5nICYmIHN0cmluZy50b0hUTUwpIHtcbiAgICAgIHJldHVybiBzdHJpbmcudG9IVE1MKCk7XG4gICAgfSBlbHNlIGlmIChzdHJpbmcgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0gZWxzZSBpZiAoIXN0cmluZykge1xuICAgICAgcmV0dXJuIHN0cmluZyArICcnO1xuICAgIH1cblxuICAgIC8vIEZvcmNlIGEgc3RyaW5nIGNvbnZlcnNpb24gYXMgdGhpcyB3aWxsIGJlIGRvbmUgYnkgdGhlIGFwcGVuZCByZWdhcmRsZXNzIGFuZFxuICAgIC8vIHRoZSByZWdleCB0ZXN0IHdpbGwgZG8gdGhpcyB0cmFuc3BhcmVudGx5IGJlaGluZCB0aGUgc2NlbmVzLCBjYXVzaW5nIGlzc3VlcyBpZlxuICAgIC8vIGFuIG9iamVjdCdzIHRvIHN0cmluZyBoYXMgZXNjYXBlZCBjaGFyYWN0ZXJzIGluIGl0LlxuICAgIHN0cmluZyA9ICcnICsgc3RyaW5nO1xuICB9XG5cbiAgaWYgKCFwb3NzaWJsZS50ZXN0KHN0cmluZykpIHsgcmV0dXJuIHN0cmluZzsgfVxuICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoYmFkQ2hhcnMsIGVzY2FwZUNoYXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSkge1xuICBpZiAoIXZhbHVlICYmIHZhbHVlICE9PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAoaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVGcmFtZShvYmplY3QpIHtcbiAgbGV0IGZyYW1lID0gZXh0ZW5kKHt9LCBvYmplY3QpO1xuICBmcmFtZS5fcGFyZW50ID0gb2JqZWN0O1xuICByZXR1cm4gZnJhbWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBibG9ja1BhcmFtcyhwYXJhbXMsIGlkcykge1xuICBwYXJhbXMucGF0aCA9IGlkcztcbiAgcmV0dXJuIHBhcmFtcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZENvbnRleHRQYXRoKGNvbnRleHRQYXRoLCBpZCkge1xuICByZXR1cm4gKGNvbnRleHRQYXRoID8gY29udGV4dFBhdGggKyAnLicgOiAnJykgKyBpZDtcbn1cbiJdfQ== +; +define('handlebars/exception',['exports', 'module'], function (exports, module) { + 'use strict'; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var loc = node && node.loc, + line = undefined, + column = undefined; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (Object.defineProperty) { + Object.defineProperty(this, 'column', { value: column }); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } + } + + Exception.prototype = new Error(); + + module.exports = Exception; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2V4Y2VwdGlvbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxNQUFNLFVBQVUsR0FBRyxDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDOztBQUVuRyxXQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQ2hDLFFBQUksR0FBRyxHQUFHLElBQUksSUFBSSxJQUFJLENBQUMsR0FBRztRQUN0QixJQUFJLFlBQUE7UUFDSixNQUFNLFlBQUEsQ0FBQztBQUNYLFFBQUksR0FBRyxFQUFFO0FBQ1AsVUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO0FBQ3RCLFlBQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQzs7QUFFMUIsYUFBTyxJQUFJLEtBQUssR0FBRyxJQUFJLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztLQUN4Qzs7QUFFRCxRQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDOzs7QUFHMUQsU0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUU7QUFDaEQsVUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztLQUM5Qzs7O0FBR0QsUUFBSSxLQUFLLENBQUMsaUJBQWlCLEVBQUU7QUFDM0IsV0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztLQUMxQzs7QUFFRCxRQUFJO0FBQ0YsVUFBSSxHQUFHLEVBQUU7QUFDUCxZQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQzs7OztBQUl2QixZQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUU7QUFDekIsZ0JBQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFDO1NBQ3hELE1BQU07QUFDTCxjQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztTQUN0QjtPQUNGO0tBQ0YsQ0FBQyxPQUFPLEdBQUcsRUFBRTs7S0FFYjtHQUNGOztBQUVELFdBQVMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQzs7bUJBRW5CLFNBQVMiLCJmaWxlIjoiZXhjZXB0aW9uLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5jb25zdCBlcnJvclByb3BzID0gWydkZXNjcmlwdGlvbicsICdmaWxlTmFtZScsICdsaW5lTnVtYmVyJywgJ21lc3NhZ2UnLCAnbmFtZScsICdudW1iZXInLCAnc3RhY2snXTtcblxuZnVuY3Rpb24gRXhjZXB0aW9uKG1lc3NhZ2UsIG5vZGUpIHtcbiAgbGV0IGxvYyA9IG5vZGUgJiYgbm9kZS5sb2MsXG4gICAgICBsaW5lLFxuICAgICAgY29sdW1uO1xuICBpZiAobG9jKSB7XG4gICAgbGluZSA9IGxvYy5zdGFydC5saW5lO1xuICAgIGNvbHVtbiA9IGxvYy5zdGFydC5jb2x1bW47XG5cbiAgICBtZXNzYWdlICs9ICcgLSAnICsgbGluZSArICc6JyArIGNvbHVtbjtcbiAgfVxuXG4gIGxldCB0bXAgPSBFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IuY2FsbCh0aGlzLCBtZXNzYWdlKTtcblxuICAvLyBVbmZvcnR1bmF0ZWx5IGVycm9ycyBhcmUgbm90IGVudW1lcmFibGUgaW4gQ2hyb21lIChhdCBsZWFzdCksIHNvIGBmb3IgcHJvcCBpbiB0bXBgIGRvZXNuJ3Qgd29yay5cbiAgZm9yIChsZXQgaWR4ID0gMDsgaWR4IDwgZXJyb3JQcm9wcy5sZW5ndGg7IGlkeCsrKSB7XG4gICAgdGhpc1tlcnJvclByb3BzW2lkeF1dID0gdG1wW2Vycm9yUHJvcHNbaWR4XV07XG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBFeGNlcHRpb24pO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAobG9jKSB7XG4gICAgICB0aGlzLmxpbmVOdW1iZXIgPSBsaW5lO1xuXG4gICAgICAvLyBXb3JrIGFyb3VuZCBpc3N1ZSB1bmRlciBzYWZhcmkgd2hlcmUgd2UgY2FuJ3QgZGlyZWN0bHkgc2V0IHRoZSBjb2x1bW4gdmFsdWVcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnY29sdW1uJywge3ZhbHVlOiBjb2x1bW59KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY29sdW1uID0gY29sdW1uO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAobm9wKSB7XG4gICAgLyogSWdub3JlIGlmIHRoZSBicm93c2VyIGlzIHZlcnkgcGFydGljdWxhciAqL1xuICB9XG59XG5cbkV4Y2VwdGlvbi5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTtcblxuZXhwb3J0IGRlZmF1bHQgRXhjZXB0aW9uO1xuIl19 +; +define('handlebars/helpers/block-helper-missing',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('blockHelperMissing', function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvYmxvY2staGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3ZFLFVBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPO1VBQ3pCLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDOztBQUVwQixVQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUU7QUFDcEIsZUFBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDakIsTUFBTSxJQUFJLE9BQU8sS0FBSyxLQUFLLElBQUksT0FBTyxJQUFJLElBQUksRUFBRTtBQUMvQyxlQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUN0QixNQUFNLElBQUksT0FYeUIsT0FBTyxDQVd4QixPQUFPLENBQUMsRUFBRTtBQUMzQixZQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0FBQ3RCLGNBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUNmLG1CQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1dBQzlCOztBQUVELGlCQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztTQUNoRCxNQUFNO0FBQ0wsaUJBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3RCO09BQ0YsTUFBTTtBQUNMLFlBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO0FBQy9CLGNBQUksSUFBSSxHQUFHLE9BdkJRLFdBQVcsQ0F1QlAsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JDLGNBQUksQ0FBQyxXQUFXLEdBQUcsT0F4Qm5CLGlCQUFpQixDQXdCb0IsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzdFLGlCQUFPLEdBQUcsRUFBQyxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUM7U0FDeEI7O0FBRUQsZUFBTyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO09BQzdCO0tBQ0YsQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiYmxvY2staGVscGVyLW1pc3NpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBjcmVhdGVGcmFtZSwgaXNBcnJheX0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignYmxvY2tIZWxwZXJNaXNzaW5nJywgZnVuY3Rpb24oY29udGV4dCwgb3B0aW9ucykge1xuICAgIGxldCBpbnZlcnNlID0gb3B0aW9ucy5pbnZlcnNlLFxuICAgICAgICBmbiA9IG9wdGlvbnMuZm47XG5cbiAgICBpZiAoY29udGV4dCA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIGZuKHRoaXMpO1xuICAgIH0gZWxzZSBpZiAoY29udGV4dCA9PT0gZmFsc2UgfHwgY29udGV4dCA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gaW52ZXJzZSh0aGlzKTtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkoY29udGV4dCkpIHtcbiAgICAgIGlmIChjb250ZXh0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgICAgICAgb3B0aW9ucy5pZHMgPSBbb3B0aW9ucy5uYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbnN0YW5jZS5oZWxwZXJzLmVhY2goY29udGV4dCwgb3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gaW52ZXJzZSh0aGlzKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLmlkcykge1xuICAgICAgICBsZXQgZGF0YSA9IGNyZWF0ZUZyYW1lKG9wdGlvbnMuZGF0YSk7XG4gICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBhcHBlbmRDb250ZXh0UGF0aChvcHRpb25zLmRhdGEuY29udGV4dFBhdGgsIG9wdGlvbnMubmFtZSk7XG4gICAgICAgIG9wdGlvbnMgPSB7ZGF0YTogZGF0YX07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCBvcHRpb25zKTtcbiAgICB9XG4gIH0pO1xufVxuIl19 +; +define('handlebars/helpers/each',['exports', 'module', '../utils', '../exception'], function (exports, module, _utils, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + module.exports = function (instance) { + instance.registerHelper('each', function (context, options) { + if (!options) { + throw new _Exception['default']('Must pass iterator to #each'); + } + + var fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data = undefined, + contextPath = undefined; + + if (options.data && options.ids) { + contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (_utils.isFunction(context)) { + context = context.call(this); + } + + if (options.data) { + data = _utils.createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (_utils.isArray(context)) { + for (var j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + var priorKey = undefined; + + for (var key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvZWFjaC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7bUJBR2UsVUFBUyxRQUFRLEVBQUU7QUFDaEMsWUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFVBQUksQ0FBQyxPQUFPLEVBQUU7QUFDWixjQUFNLDBCQUFjLDZCQUE2QixDQUFDLENBQUM7T0FDcEQ7O0FBRUQsVUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUU7VUFDZixPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU87VUFDekIsQ0FBQyxHQUFHLENBQUM7VUFDTCxHQUFHLEdBQUcsRUFBRTtVQUNSLElBQUksWUFBQTtVQUNKLFdBQVcsWUFBQSxDQUFDOztBQUVoQixVQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtBQUMvQixtQkFBVyxHQUFHLE9BakJaLGlCQUFpQixDQWlCYSxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO09BQ2pGOztBQUVELFVBQUksT0FwQnNELFVBQVUsQ0FvQnJELE9BQU8sQ0FBQyxFQUFFO0FBQUUsZUFBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7T0FBRTs7QUFFMUQsVUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFO0FBQ2hCLFlBQUksR0FBRyxPQXZCMkIsV0FBVyxDQXVCMUIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ2xDOztBQUVELGVBQVMsYUFBYSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO0FBQ3pDLFlBQUksSUFBSSxFQUFFO0FBQ1IsY0FBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFDakIsY0FBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7QUFDbkIsY0FBSSxDQUFDLEtBQUssR0FBRyxLQUFLLEtBQUssQ0FBQyxDQUFDO0FBQ3pCLGNBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQzs7QUFFbkIsY0FBSSxXQUFXLEVBQUU7QUFDZixnQkFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLEdBQUcsS0FBSyxDQUFDO1dBQ3hDO1NBQ0Y7O0FBRUQsV0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO0FBQzdCLGNBQUksRUFBRSxJQUFJO0FBQ1YscUJBQVcsRUFBRSxPQXhDTSxXQUFXLENBd0NMLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxHQUFHLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUMvRSxDQUFDLENBQUM7T0FDSjs7QUFFRCxVQUFJLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7QUFDMUMsWUFBSSxPQTdDMkMsT0FBTyxDQTZDMUMsT0FBTyxDQUFDLEVBQUU7QUFDcEIsZUFBSyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDdkMsZ0JBQUksQ0FBQyxJQUFJLE9BQU8sRUFBRTtBQUNoQiwyQkFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7YUFDL0M7V0FDRjtTQUNGLE1BQU07QUFDTCxjQUFJLFFBQVEsWUFBQSxDQUFDOztBQUViLGVBQUssSUFBSSxHQUFHLElBQUksT0FBTyxFQUFFO0FBQ3ZCLGdCQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUU7Ozs7QUFJL0Isa0JBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQiw2QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7ZUFDaEM7QUFDRCxzQkFBUSxHQUFHLEdBQUcsQ0FBQztBQUNmLGVBQUMsRUFBRSxDQUFDO2FBQ0w7V0FDRjtBQUNELGNBQUksUUFBUSxLQUFLLFNBQVMsRUFBRTtBQUMxQix5QkFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1dBQ3RDO1NBQ0Y7T0FDRjs7QUFFRCxVQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7QUFDWCxXQUFHLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQ3JCOztBQUVELGFBQU8sR0FBRyxDQUFDO0tBQ1osQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiZWFjaC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXBwZW5kQ29udGV4dFBhdGgsIGJsb2NrUGFyYW1zLCBjcmVhdGVGcmFtZSwgaXNBcnJheSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuLi9leGNlcHRpb24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignZWFjaCcsIGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ011c3QgcGFzcyBpdGVyYXRvciB0byAjZWFjaCcpO1xuICAgIH1cblxuICAgIGxldCBmbiA9IG9wdGlvbnMuZm4sXG4gICAgICAgIGludmVyc2UgPSBvcHRpb25zLmludmVyc2UsXG4gICAgICAgIGkgPSAwLFxuICAgICAgICByZXQgPSAnJyxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29udGV4dFBhdGg7XG5cbiAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICBjb250ZXh0UGF0aCA9IGFwcGVuZENvbnRleHRQYXRoKG9wdGlvbnMuZGF0YS5jb250ZXh0UGF0aCwgb3B0aW9ucy5pZHNbMF0pICsgJy4nO1xuICAgIH1cblxuICAgIGlmIChpc0Z1bmN0aW9uKGNvbnRleHQpKSB7IGNvbnRleHQgPSBjb250ZXh0LmNhbGwodGhpcyk7IH1cblxuICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4ZWNJdGVyYXRpb24oZmllbGQsIGluZGV4LCBsYXN0KSB7XG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICBkYXRhLmtleSA9IGZpZWxkO1xuICAgICAgICBkYXRhLmluZGV4ID0gaW5kZXg7XG4gICAgICAgIGRhdGEuZmlyc3QgPSBpbmRleCA9PT0gMDtcbiAgICAgICAgZGF0YS5sYXN0ID0gISFsYXN0O1xuXG4gICAgICAgIGlmIChjb250ZXh0UGF0aCkge1xuICAgICAgICAgIGRhdGEuY29udGV4dFBhdGggPSBjb250ZXh0UGF0aCArIGZpZWxkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldCA9IHJldCArIGZuKGNvbnRleHRbZmllbGRdLCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dFtmaWVsZF0sIGZpZWxkXSwgW2NvbnRleHRQYXRoICsgZmllbGQsIG51bGxdKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoaXNBcnJheShjb250ZXh0KSkge1xuICAgICAgICBmb3IgKGxldCBqID0gY29udGV4dC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcbiAgICAgICAgICBpZiAoaSBpbiBjb250ZXh0KSB7XG4gICAgICAgICAgICBleGVjSXRlcmF0aW9uKGksIGksIGkgPT09IGNvbnRleHQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcHJpb3JLZXk7XG5cbiAgICAgICAgZm9yIChsZXQga2V5IGluIGNvbnRleHQpIHtcbiAgICAgICAgICBpZiAoY29udGV4dC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBydW5uaW5nIHRoZSBpdGVyYXRpb25zIG9uZSBzdGVwIG91dCBvZiBzeW5jIHNvIHdlIGNhbiBkZXRlY3RcbiAgICAgICAgICAgIC8vIHRoZSBsYXN0IGl0ZXJhdGlvbiB3aXRob3V0IGhhdmUgdG8gc2NhbiB0aGUgb2JqZWN0IHR3aWNlIGFuZCBjcmVhdGVcbiAgICAgICAgICAgIC8vIGFuIGl0ZXJtZWRpYXRlIGtleXMgYXJyYXkuXG4gICAgICAgICAgICBpZiAocHJpb3JLZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmlvcktleSA9IGtleTtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByaW9yS2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBleGVjSXRlcmF0aW9uKHByaW9yS2V5LCBpIC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgcmV0ID0gaW52ZXJzZSh0aGlzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/helper-missing',['exports', 'module', '../exception'], function (exports, module, _exception) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + module.exports = function (instance) { + instance.registerHelper('helperMissing', function () /* [args, ]options */{ + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new _Exception['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsZUFBZSxFQUFFLGlDQUFnQztBQUN2RSxVQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFOztBQUUxQixlQUFPLFNBQVMsQ0FBQztPQUNsQixNQUFNOztBQUVMLGNBQU0sMEJBQWMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO09BQ3ZGO0tBQ0YsQ0FBQyxDQUFDO0dBQ0oiLCJmaWxlIjoiaGVscGVyLW1pc3NpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRXhjZXB0aW9uIGZyb20gJy4uL2V4Y2VwdGlvbic7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdoZWxwZXJNaXNzaW5nJywgZnVuY3Rpb24oLyogW2FyZ3MsIF1vcHRpb25zICovKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIC8vIEEgbWlzc2luZyBmaWVsZCBpbiBhIHt7Zm9vfX0gY29uc3RydWN0LlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU29tZW9uZSBpcyBhY3R1YWxseSB0cnlpbmcgdG8gY2FsbCBzb21ldGhpbmcsIGJsb3cgdXAuXG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdNaXNzaW5nIGhlbHBlcjogXCInICsgYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXS5uYW1lICsgJ1wiJyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/if',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('if', function (conditional, options) { + if (_utils.isFunction(conditional)) { + conditional = conditional.call(this); + } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function (conditional, options) { + return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvaWYuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O21CQUVlLFVBQVMsUUFBUSxFQUFFO0FBQ2hDLFlBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVMsV0FBVyxFQUFFLE9BQU8sRUFBRTtBQUMzRCxVQUFJLE9BSlMsVUFBVSxDQUlSLFdBQVcsQ0FBQyxFQUFFO0FBQUUsbUJBQVcsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQUU7Ozs7O0FBS3RFLFVBQUksQUFBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxJQUFLLE9BVC9DLE9BQU8sQ0FTZ0QsV0FBVyxDQUFDLEVBQUU7QUFDdkUsZUFBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO09BQzlCLE1BQU07QUFDTCxlQUFPLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDekI7S0FDRixDQUFDLENBQUM7O0FBRUgsWUFBUSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsVUFBUyxXQUFXLEVBQUUsT0FBTyxFQUFFO0FBQy9ELGFBQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQztLQUN2SCxDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJpZi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aXNFbXB0eSwgaXNGdW5jdGlvbn0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignaWYnLCBmdW5jdGlvbihjb25kaXRpb25hbCwgb3B0aW9ucykge1xuICAgIGlmIChpc0Z1bmN0aW9uKGNvbmRpdGlvbmFsKSkgeyBjb25kaXRpb25hbCA9IGNvbmRpdGlvbmFsLmNhbGwodGhpcyk7IH1cblxuICAgIC8vIERlZmF1bHQgYmVoYXZpb3IgaXMgdG8gcmVuZGVyIHRoZSBwb3NpdGl2ZSBwYXRoIGlmIHRoZSB2YWx1ZSBpcyB0cnV0aHkgYW5kIG5vdCBlbXB0eS5cbiAgICAvLyBUaGUgYGluY2x1ZGVaZXJvYCBvcHRpb24gbWF5IGJlIHNldCB0byB0cmVhdCB0aGUgY29uZHRpb25hbCBhcyBwdXJlbHkgbm90IGVtcHR5IGJhc2VkIG9uIHRoZVxuICAgIC8vIGJlaGF2aW9yIG9mIGlzRW1wdHkuIEVmZmVjdGl2ZWx5IHRoaXMgZGV0ZXJtaW5lcyBpZiAwIGlzIGhhbmRsZWQgYnkgdGhlIHBvc2l0aXZlIHBhdGggb3IgbmVnYXRpdmUuXG4gICAgaWYgKCghb3B0aW9ucy5oYXNoLmluY2x1ZGVaZXJvICYmICFjb25kaXRpb25hbCkgfHwgaXNFbXB0eShjb25kaXRpb25hbCkpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmZuKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3VubGVzcycsIGZ1bmN0aW9uKGNvbmRpdGlvbmFsLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGluc3RhbmNlLmhlbHBlcnNbJ2lmJ10uY2FsbCh0aGlzLCBjb25kaXRpb25hbCwge2ZuOiBvcHRpb25zLmludmVyc2UsIGludmVyc2U6IG9wdGlvbnMuZm4sIGhhc2g6IG9wdGlvbnMuaGFzaH0pO1xuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/log',['exports', 'module'], function (exports, module) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('log', function () /* message, options */{ + var args = [undefined], + options = arguments[arguments.length - 1]; + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + var level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log.apply(instance, args); + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFBZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxrQ0FBaUM7QUFDOUQsVUFBSSxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUM7VUFDbEIsT0FBTyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQzlDLFdBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM3QyxZQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO09BQ3pCOztBQUVELFVBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztBQUNkLFVBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFO0FBQzlCLGFBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztPQUM1QixNQUFNLElBQUksT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUU7QUFDckQsYUFBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO09BQzVCO0FBQ0QsVUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQzs7QUFFaEIsY0FBUSxDQUFDLEdBQUcsTUFBQSxDQUFaLFFBQVEsRUFBUyxJQUFJLENBQUMsQ0FBQztLQUN4QixDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJsb2cuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckhlbHBlcignbG9nJywgZnVuY3Rpb24oLyogbWVzc2FnZSwgb3B0aW9ucyAqLykge1xuICAgIGxldCBhcmdzID0gW3VuZGVmaW5lZF0sXG4gICAgICAgIG9wdGlvbnMgPSBhcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aCAtIDFdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgYXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gICAgfVxuXG4gICAgbGV0IGxldmVsID0gMTtcbiAgICBpZiAob3B0aW9ucy5oYXNoLmxldmVsICE9IG51bGwpIHtcbiAgICAgIGxldmVsID0gb3B0aW9ucy5oYXNoLmxldmVsO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuZGF0YS5sZXZlbCAhPSBudWxsKSB7XG4gICAgICBsZXZlbCA9IG9wdGlvbnMuZGF0YS5sZXZlbDtcbiAgICB9XG4gICAgYXJnc1swXSA9IGxldmVsO1xuXG4gICAgaW5zdGFuY2UubG9nKC4uLiBhcmdzKTtcbiAgfSk7XG59XG4iXX0= +; +define('handlebars/helpers/lookup',['exports', 'module'], function (exports, module) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('lookup', function (obj, field) { + return obj && obj[field]; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvbG9va3VwLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFBZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxVQUFTLEdBQUcsRUFBRSxLQUFLLEVBQUU7QUFDckQsYUFBTyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQzFCLENBQUMsQ0FBQztHQUNKIiwiZmlsZSI6Imxvb2t1cC5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGluc3RhbmNlKSB7XG4gIGluc3RhbmNlLnJlZ2lzdGVySGVscGVyKCdsb29rdXAnLCBmdW5jdGlvbihvYmosIGZpZWxkKSB7XG4gICAgcmV0dXJuIG9iaiAmJiBvYmpbZmllbGRdO1xuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers/with',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerHelper('with', function (context, options) { + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMvd2l0aC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7bUJBRWUsVUFBUyxRQUFRLEVBQUU7QUFDaEMsWUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBUyxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pELFVBQUksT0FKc0QsVUFBVSxDQUlyRCxPQUFPLENBQUMsRUFBRTtBQUFFLGVBQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO09BQUU7O0FBRTFELFVBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUM7O0FBRXBCLFVBQUksQ0FBQyxPQVI0QyxPQUFPLENBUTNDLE9BQU8sQ0FBQyxFQUFFO0FBQ3JCLFlBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUFDeEIsWUFBSSxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7QUFDL0IsY0FBSSxHQUFHLE9BWHlCLFdBQVcsQ0FXeEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2pDLGNBQUksQ0FBQyxXQUFXLEdBQUcsT0FabkIsaUJBQWlCLENBWW9CLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoRjs7QUFFRCxlQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUU7QUFDakIsY0FBSSxFQUFFLElBQUk7QUFDVixxQkFBVyxFQUFFLE9BakJNLFdBQVcsQ0FpQkwsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDaEUsQ0FBQyxDQUFDO09BQ0osTUFBTTtBQUNMLGVBQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztPQUM5QjtLQUNGLENBQUMsQ0FBQztHQUNKIiwiZmlsZSI6IndpdGguanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FwcGVuZENvbnRleHRQYXRoLCBibG9ja1BhcmFtcywgY3JlYXRlRnJhbWUsIGlzRW1wdHksIGlzRnVuY3Rpb259IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oaW5zdGFuY2UpIHtcbiAgaW5zdGFuY2UucmVnaXN0ZXJIZWxwZXIoJ3dpdGgnLCBmdW5jdGlvbihjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24oY29udGV4dCkpIHsgY29udGV4dCA9IGNvbnRleHQuY2FsbCh0aGlzKTsgfVxuXG4gICAgbGV0IGZuID0gb3B0aW9ucy5mbjtcblxuICAgIGlmICghaXNFbXB0eShjb250ZXh0KSkge1xuICAgICAgbGV0IGRhdGEgPSBvcHRpb25zLmRhdGE7XG4gICAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMuaWRzKSB7XG4gICAgICAgIGRhdGEgPSBjcmVhdGVGcmFtZShvcHRpb25zLmRhdGEpO1xuICAgICAgICBkYXRhLmNvbnRleHRQYXRoID0gYXBwZW5kQ29udGV4dFBhdGgob3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoLCBvcHRpb25zLmlkc1swXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmbihjb250ZXh0LCB7XG4gICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIGJsb2NrUGFyYW1zOiBibG9ja1BhcmFtcyhbY29udGV4dF0sIFtkYXRhICYmIGRhdGEuY29udGV4dFBhdGhdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ== +; +define('handlebars/helpers',['exports', './helpers/block-helper-missing', './helpers/each', './helpers/helper-missing', './helpers/if', './helpers/log', './helpers/lookup', './helpers/with'], function (exports, _helpersBlockHelperMissing, _helpersEach, _helpersHelperMissing, _helpersIf, _helpersLog, _helpersLookup, _helpersWith) { + 'use strict'; + + exports.__esModule = true; + exports.registerDefaultHelpers = registerDefaultHelpers; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _registerBlockHelperMissing = _interopRequireDefault(_helpersBlockHelperMissing); + + var _registerEach = _interopRequireDefault(_helpersEach); + + var _registerHelperMissing = _interopRequireDefault(_helpersHelperMissing); + + var _registerIf = _interopRequireDefault(_helpersIf); + + var _registerLog = _interopRequireDefault(_helpersLog); + + var _registerLookup = _interopRequireDefault(_helpersLookup); + + var _registerWith = _interopRequireDefault(_helpersWith); + + function registerDefaultHelpers(instance) { + _registerBlockHelperMissing['default'](instance); + _registerEach['default'](instance); + _registerHelperMissing['default'](instance); + _registerIf['default'](instance); + _registerLog['default'](instance); + _registerLookup['default'](instance); + _registerWith['default'](instance); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2hlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRTyxXQUFTLHNCQUFzQixDQUFDLFFBQVEsRUFBRTtBQUMvQywyQ0FBMkIsUUFBUSxDQUFDLENBQUM7QUFDckMsNkJBQWEsUUFBUSxDQUFDLENBQUM7QUFDdkIsc0NBQXNCLFFBQVEsQ0FBQyxDQUFDO0FBQ2hDLDJCQUFXLFFBQVEsQ0FBQyxDQUFDO0FBQ3JCLDRCQUFZLFFBQVEsQ0FBQyxDQUFDO0FBQ3RCLCtCQUFlLFFBQVEsQ0FBQyxDQUFDO0FBQ3pCLDZCQUFhLFFBQVEsQ0FBQyxDQUFDO0dBQ3hCIiwiZmlsZSI6ImhlbHBlcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcmVnaXN0ZXJCbG9ja0hlbHBlck1pc3NpbmcgZnJvbSAnLi9oZWxwZXJzL2Jsb2NrLWhlbHBlci1taXNzaW5nJztcbmltcG9ydCByZWdpc3RlckVhY2ggZnJvbSAnLi9oZWxwZXJzL2VhY2gnO1xuaW1wb3J0IHJlZ2lzdGVySGVscGVyTWlzc2luZyBmcm9tICcuL2hlbHBlcnMvaGVscGVyLW1pc3NpbmcnO1xuaW1wb3J0IHJlZ2lzdGVySWYgZnJvbSAnLi9oZWxwZXJzL2lmJztcbmltcG9ydCByZWdpc3RlckxvZyBmcm9tICcuL2hlbHBlcnMvbG9nJztcbmltcG9ydCByZWdpc3Rlckxvb2t1cCBmcm9tICcuL2hlbHBlcnMvbG9va3VwJztcbmltcG9ydCByZWdpc3RlcldpdGggZnJvbSAnLi9oZWxwZXJzL3dpdGgnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0SGVscGVycyhpbnN0YW5jZSkge1xuICByZWdpc3RlckJsb2NrSGVscGVyTWlzc2luZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyRWFjaChpbnN0YW5jZSk7XG4gIHJlZ2lzdGVySGVscGVyTWlzc2luZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVySWYoaW5zdGFuY2UpO1xuICByZWdpc3RlckxvZyhpbnN0YW5jZSk7XG4gIHJlZ2lzdGVyTG9va3VwKGluc3RhbmNlKTtcbiAgcmVnaXN0ZXJXaXRoKGluc3RhbmNlKTtcbn1cbiJdfQ== +; +define('handlebars/decorators/inline',['exports', 'module', '../utils'], function (exports, module, _utils) { + 'use strict'; + + module.exports = function (instance) { + instance.registerDecorator('inline', function (fn, props, container, options) { + var ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function (context, options) { + // Create a new partials stack frame prior to exec. + var original = container.partials; + container.partials = _utils.extend({}, original, props.partials); + var ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMvaW5saW5lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OzttQkFFZSxVQUFTLFFBQVEsRUFBRTtBQUNoQyxZQUFRLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFVBQVMsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFO0FBQzNFLFVBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNiLFVBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFO0FBQ25CLGFBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLFdBQUcsR0FBRyxVQUFTLE9BQU8sRUFBRSxPQUFPLEVBQUU7O0FBRS9CLGNBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUM7QUFDbEMsbUJBQVMsQ0FBQyxRQUFRLEdBQUcsT0FWckIsTUFBTSxDQVVzQixFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMxRCxjQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9CLG1CQUFTLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUM5QixpQkFBTyxHQUFHLENBQUM7U0FDWixDQUFDO09BQ0g7O0FBRUQsV0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsQ0FBQzs7QUFFN0MsYUFBTyxHQUFHLENBQUM7S0FDWixDQUFDLENBQUM7R0FDSiIsImZpbGUiOiJpbmxpbmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2V4dGVuZH0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnN0YW5jZSkge1xuICBpbnN0YW5jZS5yZWdpc3RlckRlY29yYXRvcignaW5saW5lJywgZnVuY3Rpb24oZm4sIHByb3BzLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICBsZXQgcmV0ID0gZm47XG4gICAgaWYgKCFwcm9wcy5wYXJ0aWFscykge1xuICAgICAgcHJvcHMucGFydGlhbHMgPSB7fTtcbiAgICAgIHJldCA9IGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHBhcnRpYWxzIHN0YWNrIGZyYW1lIHByaW9yIHRvIGV4ZWMuXG4gICAgICAgIGxldCBvcmlnaW5hbCA9IGNvbnRhaW5lci5wYXJ0aWFscztcbiAgICAgICAgY29udGFpbmVyLnBhcnRpYWxzID0gZXh0ZW5kKHt9LCBvcmlnaW5hbCwgcHJvcHMucGFydGlhbHMpO1xuICAgICAgICBsZXQgcmV0ID0gZm4oY29udGV4dCwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IG9yaWdpbmFsO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBwcm9wcy5wYXJ0aWFsc1tvcHRpb25zLmFyZ3NbMF1dID0gb3B0aW9ucy5mbjtcblxuICAgIHJldHVybiByZXQ7XG4gIH0pO1xufVxuIl19 +; +define('handlebars/decorators',['exports', './decorators/inline'], function (exports, _decoratorsInline) { + 'use strict'; + + exports.__esModule = true; + exports.registerDefaultDecorators = registerDefaultDecorators; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _registerInline = _interopRequireDefault(_decoratorsInline); + + function registerDefaultDecorators(instance) { + _registerInline['default'](instance); + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2RlY29yYXRvcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFFTyxXQUFTLHlCQUF5QixDQUFDLFFBQVEsRUFBRTtBQUNsRCwrQkFBZSxRQUFRLENBQUMsQ0FBQztHQUMxQiIsImZpbGUiOiJkZWNvcmF0b3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZ2lzdGVySW5saW5lIGZyb20gJy4vZGVjb3JhdG9ycy9pbmxpbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0RGVjb3JhdG9ycyhpbnN0YW5jZSkge1xuICByZWdpc3RlcklubGluZShpbnN0YW5jZSk7XG59XG5cbiJdfQ== +; +define('handlebars/logger',['exports', 'module', './utils'], function (exports, module, _utils) { + 'use strict'; + + var logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function lookupLevel(level) { + if (typeof level === 'string') { + var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function log(level) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + var method = logger.methodMap[level]; + if (!console[method]) { + // eslint-disable-line no-console + method = 'log'; + } + + for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + message[_key - 1] = arguments[_key]; + } + + console[method].apply(console, message); // eslint-disable-line no-console + } + } + }; + + module.exports = logger; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2xvZ2dlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxNQUFJLE1BQU0sR0FBRztBQUNYLGFBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQztBQUM3QyxTQUFLLEVBQUUsTUFBTTs7O0FBR2IsZUFBVyxFQUFFLHFCQUFTLEtBQUssRUFBRTtBQUMzQixVQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtBQUM3QixZQUFJLFFBQVEsR0FBRyxPQVRiLE9BQU8sQ0FTYyxNQUFNLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzlELFlBQUksUUFBUSxJQUFJLENBQUMsRUFBRTtBQUNqQixlQUFLLEdBQUcsUUFBUSxDQUFDO1NBQ2xCLE1BQU07QUFDTCxlQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztTQUM3QjtPQUNGOztBQUVELGFBQU8sS0FBSyxDQUFDO0tBQ2Q7OztBQUdELE9BQUcsRUFBRSxhQUFTLEtBQUssRUFBYztBQUMvQixXQUFLLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQzs7QUFFbEMsVUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxFQUFFO0FBQy9FLFlBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDckMsWUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTs7QUFDcEIsZ0JBQU0sR0FBRyxLQUFLLENBQUM7U0FDaEI7OzBDQVBtQixPQUFPO0FBQVAsaUJBQU87OztBQVEzQixlQUFPLENBQUMsTUFBTSxPQUFDLENBQWYsT0FBTyxFQUFZLE9BQU8sQ0FBQyxDQUFDO09BQzdCO0tBQ0Y7R0FDRixDQUFDOzttQkFFYSxNQUFNIiwiZmlsZSI6ImxvZ2dlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7aW5kZXhPZn0gZnJvbSAnLi91dGlscyc7XG5cbmxldCBsb2dnZXIgPSB7XG4gIG1ldGhvZE1hcDogWydkZWJ1ZycsICdpbmZvJywgJ3dhcm4nLCAnZXJyb3InXSxcbiAgbGV2ZWw6ICdpbmZvJyxcblxuICAvLyBNYXBzIGEgZ2l2ZW4gbGV2ZWwgdmFsdWUgdG8gdGhlIGBtZXRob2RNYXBgIGluZGV4ZXMgYWJvdmUuXG4gIGxvb2t1cExldmVsOiBmdW5jdGlvbihsZXZlbCkge1xuICAgIGlmICh0eXBlb2YgbGV2ZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBsZXQgbGV2ZWxNYXAgPSBpbmRleE9mKGxvZ2dlci5tZXRob2RNYXAsIGxldmVsLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgaWYgKGxldmVsTWFwID49IDApIHtcbiAgICAgICAgbGV2ZWwgPSBsZXZlbE1hcDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldmVsID0gcGFyc2VJbnQobGV2ZWwsIDEwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGV2ZWw7XG4gIH0sXG5cbiAgLy8gQ2FuIGJlIG92ZXJyaWRkZW4gaW4gdGhlIGhvc3QgZW52aXJvbm1lbnRcbiAgbG9nOiBmdW5jdGlvbihsZXZlbCwgLi4ubWVzc2FnZSkge1xuICAgIGxldmVsID0gbG9nZ2VyLmxvb2t1cExldmVsKGxldmVsKTtcblxuICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbG9nZ2VyLmxvb2t1cExldmVsKGxvZ2dlci5sZXZlbCkgPD0gbGV2ZWwpIHtcbiAgICAgIGxldCBtZXRob2QgPSBsb2dnZXIubWV0aG9kTWFwW2xldmVsXTtcbiAgICAgIGlmICghY29uc29sZVttZXRob2RdKSB7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG4gICAgICAgIG1ldGhvZCA9ICdsb2cnO1xuICAgICAgfVxuICAgICAgY29uc29sZVttZXRob2RdKC4uLm1lc3NhZ2UpOyAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGVcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IGxvZ2dlcjtcbiJdfQ== +; +define('handlebars/base',['exports', './utils', './exception', './helpers', './decorators', './logger'], function (exports, _utils, _exception, _helpers, _decorators, _logger) { + 'use strict'; + + exports.__esModule = true; + exports.HandlebarsEnvironment = HandlebarsEnvironment; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + var _logger2 = _interopRequireDefault(_logger); + + var VERSION = '4.0.6'; + exports.VERSION = VERSION; + var COMPILER_REVISION = 7; + + exports.COMPILER_REVISION = COMPILER_REVISION; + var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '== 1.x.x', + 5: '== 2.0.0-alpha.x', + 6: '>= 2.0.0-beta.1', + 7: '>= 4.0.0' + }; + + exports.REVISION_CHANGES = REVISION_CHANGES; + var objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + _helpers.registerDefaultHelpers(this); + _decorators.registerDefaultDecorators(this); + } + + HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: _logger2['default'], + log: _logger2['default'].log, + + registerHelper: function registerHelper(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _Exception['default']('Arg not supported with multiple helpers'); + } + _utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function unregisterHelper(name) { + delete this.helpers[name]; + }, + + registerPartial: function registerPartial(name, partial) { + if (_utils.toString.call(name) === objectType) { + _utils.extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new _Exception['default']('Attempting to register a partial called "' + name + '" as undefined'); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function unregisterPartial(name) { + delete this.partials[name]; + }, + + registerDecorator: function registerDecorator(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _Exception['default']('Arg not supported with multiple decorators'); + } + _utils.extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function unregisterDecorator(name) { + delete this.decorators[name]; + } + }; + + var log = _logger2['default'].log; + + exports.log = log; + exports.createFrame = _utils.createFrame; + exports.logger = _logger2['default']; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQU1PLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQzs7QUFDeEIsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7OztBQUU1QixNQUFNLGdCQUFnQixHQUFHO0FBQzlCLEtBQUMsRUFBRSxhQUFhO0FBQ2hCLEtBQUMsRUFBRSxlQUFlO0FBQ2xCLEtBQUMsRUFBRSxlQUFlO0FBQ2xCLEtBQUMsRUFBRSxVQUFVO0FBQ2IsS0FBQyxFQUFFLGtCQUFrQjtBQUNyQixLQUFDLEVBQUUsaUJBQWlCO0FBQ3BCLEtBQUMsRUFBRSxVQUFVO0dBQ2QsQ0FBQzs7O0FBRUYsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUM7O0FBRTlCLFdBQVMscUJBQXFCLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUU7QUFDbkUsUUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO0FBQzdCLFFBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLEVBQUUsQ0FBQztBQUMvQixRQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsSUFBSSxFQUFFLENBQUM7O0FBRW5DLGFBeEJNLHNCQUFzQixDQXdCTCxJQUFJLENBQUMsQ0FBQztBQUM3QixnQkF4Qk0seUJBQXlCLENBd0JMLElBQUksQ0FBQyxDQUFDO0dBQ2pDOztBQUVELHVCQUFxQixDQUFDLFNBQVMsR0FBRztBQUNoQyxlQUFXLEVBQUUscUJBQXFCOztBQUVsQyxVQUFNLHFCQUFRO0FBQ2QsT0FBRyxFQUFFLG9CQUFPLEdBQUc7O0FBRWYsa0JBQWMsRUFBRSx3QkFBUyxJQUFJLEVBQUUsRUFBRSxFQUFFO0FBQ2pDLFVBQUksT0FyQ3FCLFFBQVEsQ0FxQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxVQUFVLEVBQUU7QUFDdEMsWUFBSSxFQUFFLEVBQUU7QUFBRSxnQkFBTSwwQkFBYyx5Q0FBeUMsQ0FBQyxDQUFDO1NBQUU7QUFDM0UsZUF2Q2UsTUFBTSxDQXVDZCxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO09BQzVCLE1BQU07QUFDTCxZQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztPQUN6QjtLQUNGO0FBQ0Qsb0JBQWdCLEVBQUUsMEJBQVMsSUFBSSxFQUFFO0FBQy9CLGFBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUMzQjs7QUFFRCxtQkFBZSxFQUFFLHlCQUFTLElBQUksRUFBRSxPQUFPLEVBQUU7QUFDdkMsVUFBSSxPQWpEcUIsUUFBUSxDQWlEcEIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLFVBQVUsRUFBRTtBQUN0QyxlQWxEZSxNQUFNLENBa0RkLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7T0FDN0IsTUFBTTtBQUNMLFlBQUksT0FBTyxPQUFPLEtBQUssV0FBVyxFQUFFO0FBQ2xDLGdCQUFNLHdFQUEwRCxJQUFJLG9CQUFpQixDQUFDO1NBQ3ZGO0FBQ0QsWUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUM7T0FDL0I7S0FDRjtBQUNELHFCQUFpQixFQUFFLDJCQUFTLElBQUksRUFBRTtBQUNoQyxhQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDNUI7O0FBRUQscUJBQWlCLEVBQUUsMkJBQVMsSUFBSSxFQUFFLEVBQUUsRUFBRTtBQUNwQyxVQUFJLE9BL0RxQixRQUFRLENBK0RwQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssVUFBVSxFQUFFO0FBQ3RDLFlBQUksRUFBRSxFQUFFO0FBQUUsZ0JBQU0sMEJBQWMsNENBQTRDLENBQUMsQ0FBQztTQUFFO0FBQzlFLGVBakVlLE1BQU0sQ0FpRWQsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztPQUMvQixNQUFNO0FBQ0wsWUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7T0FDNUI7S0FDRjtBQUNELHVCQUFtQixFQUFFLDZCQUFTLElBQUksRUFBRTtBQUNsQyxhQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDOUI7R0FDRixDQUFDOztBQUVLLE1BQUksR0FBRyxHQUFHLG9CQUFPLEdBQUcsQ0FBQzs7O1VBRXBCLFdBQVcsVUE3RVgsV0FBVztVQTZFRSxNQUFNIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2NyZWF0ZUZyYW1lLCBleHRlbmQsIHRvU3RyaW5nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi9leGNlcHRpb24nO1xuaW1wb3J0IHtyZWdpc3RlckRlZmF1bHRIZWxwZXJzfSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtyZWdpc3RlckRlZmF1bHREZWNvcmF0b3JzfSBmcm9tICcuL2RlY29yYXRvcnMnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuL2xvZ2dlcic7XG5cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gJzQuMC42JztcbmV4cG9ydCBjb25zdCBDT01QSUxFUl9SRVZJU0lPTiA9IDc7XG5cbmV4cG9ydCBjb25zdCBSRVZJU0lPTl9DSEFOR0VTID0ge1xuICAxOiAnPD0gMS4wLnJjLjInLCAvLyAxLjAucmMuMiBpcyBhY3R1YWxseSByZXYyIGJ1dCBkb2Vzbid0IHJlcG9ydCBpdFxuICAyOiAnPT0gMS4wLjAtcmMuMycsXG4gIDM6ICc9PSAxLjAuMC1yYy40JyxcbiAgNDogJz09IDEueC54JyxcbiAgNTogJz09IDIuMC4wLWFscGhhLngnLFxuICA2OiAnPj0gMi4wLjAtYmV0YS4xJyxcbiAgNzogJz49IDQuMC4wJ1xufTtcblxuY29uc3Qgb2JqZWN0VHlwZSA9ICdbb2JqZWN0IE9iamVjdF0nO1xuXG5leHBvcnQgZnVuY3Rpb24gSGFuZGxlYmFyc0Vudmlyb25tZW50KGhlbHBlcnMsIHBhcnRpYWxzLCBkZWNvcmF0b3JzKSB7XG4gIHRoaXMuaGVscGVycyA9IGhlbHBlcnMgfHwge307XG4gIHRoaXMucGFydGlhbHMgPSBwYXJ0aWFscyB8fCB7fTtcbiAgdGhpcy5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycyB8fCB7fTtcblxuICByZWdpc3RlckRlZmF1bHRIZWxwZXJzKHRoaXMpO1xuICByZWdpc3RlckRlZmF1bHREZWNvcmF0b3JzKHRoaXMpO1xufVxuXG5IYW5kbGViYXJzRW52aXJvbm1lbnQucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogSGFuZGxlYmFyc0Vudmlyb25tZW50LFxuXG4gIGxvZ2dlcjogbG9nZ2VyLFxuICBsb2c6IGxvZ2dlci5sb2csXG5cbiAgcmVnaXN0ZXJIZWxwZXI6IGZ1bmN0aW9uKG5hbWUsIGZuKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGlmIChmbikgeyB0aHJvdyBuZXcgRXhjZXB0aW9uKCdBcmcgbm90IHN1cHBvcnRlZCB3aXRoIG11bHRpcGxlIGhlbHBlcnMnKTsgfVxuICAgICAgZXh0ZW5kKHRoaXMuaGVscGVycywgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGVscGVyc1tuYW1lXSA9IGZuO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlckhlbHBlcjogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLmhlbHBlcnNbbmFtZV07XG4gIH0sXG5cbiAgcmVnaXN0ZXJQYXJ0aWFsOiBmdW5jdGlvbihuYW1lLCBwYXJ0aWFsKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGV4dGVuZCh0aGlzLnBhcnRpYWxzLCBuYW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGVvZiBwYXJ0aWFsID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKGBBdHRlbXB0aW5nIHRvIHJlZ2lzdGVyIGEgcGFydGlhbCBjYWxsZWQgXCIke25hbWV9XCIgYXMgdW5kZWZpbmVkYCk7XG4gICAgICB9XG4gICAgICB0aGlzLnBhcnRpYWxzW25hbWVdID0gcGFydGlhbDtcbiAgICB9XG4gIH0sXG4gIHVucmVnaXN0ZXJQYXJ0aWFsOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMucGFydGlhbHNbbmFtZV07XG4gIH0sXG5cbiAgcmVnaXN0ZXJEZWNvcmF0b3I6IGZ1bmN0aW9uKG5hbWUsIGZuKSB7XG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobmFtZSkgPT09IG9iamVjdFR5cGUpIHtcbiAgICAgIGlmIChmbikgeyB0aHJvdyBuZXcgRXhjZXB0aW9uKCdBcmcgbm90IHN1cHBvcnRlZCB3aXRoIG11bHRpcGxlIGRlY29yYXRvcnMnKTsgfVxuICAgICAgZXh0ZW5kKHRoaXMuZGVjb3JhdG9ycywgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVjb3JhdG9yc1tuYW1lXSA9IGZuO1xuICAgIH1cbiAgfSxcbiAgdW5yZWdpc3RlckRlY29yYXRvcjogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLmRlY29yYXRvcnNbbmFtZV07XG4gIH1cbn07XG5cbmV4cG9ydCBsZXQgbG9nID0gbG9nZ2VyLmxvZztcblxuZXhwb3J0IHtjcmVhdGVGcmFtZSwgbG9nZ2VyfTtcbiJdfQ== +; +define('handlebars/safe-string',['exports', 'module'], function (exports, module) { + // Build out our basic SafeString type + 'use strict'; + + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = SafeString.prototype.toHTML = function () { + return '' + this.string; + }; + + module.exports = SafeString; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3NhZmUtc3RyaW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFDQSxXQUFTLFVBQVUsQ0FBQyxNQUFNLEVBQUU7QUFDMUIsUUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7R0FDdEI7O0FBRUQsWUFBVSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsWUFBVztBQUN2RSxXQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0dBQ3pCLENBQUM7O21CQUVhLFVBQVUiLCJmaWxlIjoic2FmZS1zdHJpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBCdWlsZCBvdXQgb3VyIGJhc2ljIFNhZmVTdHJpbmcgdHlwZVxuZnVuY3Rpb24gU2FmZVN0cmluZyhzdHJpbmcpIHtcbiAgdGhpcy5zdHJpbmcgPSBzdHJpbmc7XG59XG5cblNhZmVTdHJpbmcucHJvdG90eXBlLnRvU3RyaW5nID0gU2FmZVN0cmluZy5wcm90b3R5cGUudG9IVE1MID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAnJyArIHRoaXMuc3RyaW5nO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgU2FmZVN0cmluZztcbiJdfQ== +; +define('handlebars/runtime',['exports', './utils', './exception', './base'], function (exports, _utils, _exception, _base) { + 'use strict'; + + exports.__esModule = true; + exports.checkRevision = checkRevision; + exports.template = template; + exports.wrapProgram = wrapProgram; + exports.resolvePartial = resolvePartial; + exports.invokePartial = invokePartial; + exports.noop = noop; + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _Exception = _interopRequireDefault(_exception); + + function checkRevision(compilerInfo) { + var compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = _base.COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = _base.REVISION_CHANGES[currentRevision], + compilerVersions = _base.REVISION_CHANGES[compilerRevision]; + throw new _Exception['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new _Exception['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } + } + + function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new _Exception['default']('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new _Exception['default']('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = _utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + var result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + var lines = result.split('\n'); + for (var i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new _Exception['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + var container = { + strict: function strict(obj, name) { + if (!(name in obj)) { + throw new _Exception['default']('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function lookup(depths, name) { + var len = depths.length; + for (var i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function lambda(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: _utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function fn(i) { + var ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function program(i, data, declaredBlockParams, blockParams, depths) { + var programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function data(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function merge(param, common) { + var obj = param || common; + + if (param && common && param !== common) { + obj = _utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function (options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function (i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new _Exception['default']('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new _Exception['default']('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; + } + + function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; + } + + function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + var data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; + } + + function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + var partialBlock = undefined; + if (options.fn && options.fn !== noop) { + options.data = _base.createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = _utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new _Exception['default']('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } + } + + function noop() { + return ''; + } + + function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? _base.createFrame(data) : {}; + data.root = context; + } + return data; + } + + function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + var props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + _utils.extend(prog, props); + } + return prog; + } +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL3J1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUlPLFdBQVMsYUFBYSxDQUFDLFlBQVksRUFBRTtBQUMxQyxRQUFNLGdCQUFnQixHQUFHLFlBQVksSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUN2RCxlQUFlLFNBSmQsaUJBQWlCLEFBSWlCLENBQUM7O0FBRTFDLFFBQUksZ0JBQWdCLEtBQUssZUFBZSxFQUFFO0FBQ3hDLFVBQUksZ0JBQWdCLEdBQUcsZUFBZSxFQUFFO0FBQ3RDLFlBQU0sZUFBZSxHQUFHLE1BUkYsZ0JBQWdCLENBUUcsZUFBZSxDQUFDO1lBQ25ELGdCQUFnQixHQUFHLE1BVEgsZ0JBQWdCLENBU0ksZ0JBQWdCLENBQUMsQ0FBQztBQUM1RCxjQUFNLDBCQUFjLHlGQUF5RixHQUN2RyxxREFBcUQsR0FBRyxlQUFlLEdBQUcsbURBQW1ELEdBQUcsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDaEssTUFBTTs7QUFFTCxjQUFNLDBCQUFjLHdGQUF3RixHQUN0RyxpREFBaUQsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDbkY7S0FDRjtHQUNGOztBQUVNLFdBQVMsUUFBUSxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7O0FBRTFDLFFBQUksQ0FBQyxHQUFHLEVBQUU7QUFDUixZQUFNLDBCQUFjLG1DQUFtQyxDQUFDLENBQUM7S0FDMUQ7QUFDRCxRQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRTtBQUN2QyxZQUFNLDBCQUFjLDJCQUEyQixHQUFHLE9BQU8sWUFBWSxDQUFDLENBQUM7S0FDeEU7O0FBRUQsZ0JBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUM7Ozs7QUFJbEQsT0FBRyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENB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R0FBRyxPQUFPLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDLENBQUM7S0FDNUUsTUFBTSxJQUFJLE9BQU8sWUFBWSxRQUFRLEVBQUU7QUFDdEMsYUFBTyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0tBQ2xDO0dBQ0Y7O0FBRU0sV0FBUyxJQUFJLEdBQUc7QUFBRSxXQUFPLEVBQUUsQ0FBQztHQUFFOztBQUVyQyxXQUFTLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO0FBQy9CLFFBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxNQUFNLElBQUksSUFBSSxDQUFBLEFBQUMsRUFBRTtBQUM5QixVQUFJLEdBQUcsSUFBSSxHQUFHLE1BbFE0QixXQUFXLENBa1EzQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDckMsVUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7S0FDckI7QUFDRCxXQUFPLElBQUksQ0FBQztHQUNiOztBQUVELFdBQVMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7QUFDekUsUUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFO0FBQ2hCLFVBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztBQUNmLFVBQUksR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUM1RixhQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDM0I7QUFDRCxXQUFPLElBQUksQ0FBQztHQUNiIiwiZmlsZSI6InJ1bnRpbWUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBVdGlscyBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBFeGNlcHRpb24gZnJvbSAnLi9leGNlcHRpb24nO1xuaW1wb3J0IHsgQ09NUElMRVJfUkVWSVNJT04sIFJFVklTSU9OX0NIQU5HRVMsIGNyZWF0ZUZyYW1lIH0gZnJvbSAnLi9iYXNlJztcblxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrUmV2aXNpb24oY29tcGlsZXJJbmZvKSB7XG4gIGNvbnN0IGNvbXBpbGVyUmV2aXNpb24gPSBjb21waWxlckluZm8gJiYgY29tcGlsZXJJbmZvWzBdIHx8IDEsXG4gICAgICAgIGN1cnJlbnRSZXZpc2lvbiA9IENPTVBJTEVSX1JFVklTSU9OO1xuXG4gIGlmIChjb21waWxlclJldmlzaW9uICE9PSBjdXJyZW50UmV2aXNpb24pIHtcbiAgICBpZiAoY29tcGlsZXJSZXZpc2lvbiA8IGN1cnJlbnRSZXZpc2lvbikge1xuICAgICAgY29uc3QgcnVudGltZVZlcnNpb25zID0gUkVWSVNJT05fQ0hBTkdFU1tjdXJyZW50UmV2aXNpb25dLFxuICAgICAgICAgICAgY29tcGlsZXJWZXJzaW9ucyA9IFJFVklTSU9OX0NIQU5HRVNbY29tcGlsZXJSZXZpc2lvbl07XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUZW1wbGF0ZSB3YXMgcHJlY29tcGlsZWQgd2l0aCBhbiBvbGRlciB2ZXJzaW9uIG9mIEhhbmRsZWJhcnMgdGhhbiB0aGUgY3VycmVudCBydW50aW1lLiAnICtcbiAgICAgICAgICAgICdQbGVhc2UgdXBkYXRlIHlvdXIgcHJlY29tcGlsZXIgdG8gYSBuZXdlciB2ZXJzaW9uICgnICsgcnVudGltZVZlcnNpb25zICsgJykgb3IgZG93bmdyYWRlIHlvdXIgcnVudGltZSB0byBhbiBvbGRlciB2ZXJzaW9uICgnICsgY29tcGlsZXJWZXJzaW9ucyArICcpLicpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBVc2UgdGhlIGVtYmVkZGVkIHZlcnNpb24gaW5mbyBzaW5jZSB0aGUgcnVudGltZSBkb2Vzbid0IGtub3cgYWJvdXQgdGhpcyByZXZpc2lvbiB5ZXRcbiAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1RlbXBsYXRlIHdhcyBwcmVjb21waWxlZCB3aXRoIGEgbmV3ZXIgdmVyc2lvbiBvZiBIYW5kbGViYXJzIHRoYW4gdGhlIGN1cnJlbnQgcnVudGltZS4gJyArXG4gICAgICAgICAgICAnUGxlYXNlIHVwZGF0ZSB5b3VyIHJ1bnRpbWUgdG8gYSBuZXdlciB2ZXJzaW9uICgnICsgY29tcGlsZXJJbmZvWzFdICsgJykuJyk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0ZW1wbGF0ZSh0ZW1wbGF0ZVNwZWMsIGVudikge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAoIWVudikge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ05vIGVudmlyb25tZW50IHBhc3NlZCB0byB0ZW1wbGF0ZScpO1xuICB9XG4gIGlmICghdGVtcGxhdGVTcGVjIHx8ICF0ZW1wbGF0ZVNwZWMubWFpbikge1xuICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1Vua25vd24gdGVtcGxhdGUgb2JqZWN0OiAnICsgdHlwZW9mIHRlbXBsYXRlU3BlYyk7XG4gIH1cblxuICB0ZW1wbGF0ZVNwZWMubWFpbi5kZWNvcmF0b3IgPSB0ZW1wbGF0ZVNwZWMubWFpbl9kO1xuXG4gIC8vIE5vdGU6IFVzaW5nIGVudi5WTSByZWZlcmVuY2VzIHJhdGhlciB0aGFuIGxvY2FsIHZhciByZWZlcmVuY2VzIHRocm91Z2hvdXQgdGhpcyBzZWN0aW9uIHRvIGFsbG93XG4gIC8vIGZvciBleHRlcm5hbCB1c2VycyB0byBvdmVycmlkZSB0aGVzZSBhcyBwc3VlZG8tc3VwcG9ydGVkIEFQSXMuXG4gIGVudi5WTS5jaGVja1JldmlzaW9uKHRlbXBsYXRlU3BlYy5jb21waWxlcik7XG5cbiAgZnVuY3Rpb24gaW52b2tlUGFydGlhbFdyYXBwZXIocGFydGlhbCwgY29udGV4dCwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmhhc2gpIHtcbiAgICAgIGNvbnRleHQgPSBVdGlscy5leHRlbmQoe30sIGNvbnRleHQsIG9wdGlvbnMuaGFzaCk7XG4gICAgICBpZiAob3B0aW9ucy5pZHMpIHtcbiAgICAgICAgb3B0aW9ucy5pZHNbMF0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHBhcnRpYWwgPSBlbnYuVk0ucmVzb2x2ZVBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKTtcbiAgICBsZXQgcmVzdWx0ID0gZW52LlZNLmludm9rZVBhcnRpYWwuY2FsbCh0aGlzLCBwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKTtcblxuICAgIGlmIChyZXN1bHQgPT0gbnVsbCAmJiBlbnYuY29tcGlsZSkge1xuICAgICAgb3B0aW9ucy5wYXJ0aWFsc1tvcHRpb25zLm5hbWVdID0gZW52LmNvbXBpbGUocGFydGlhbCwgdGVtcGxhdGVTcGVjLmNvbXBpbGVyT3B0aW9ucywgZW52KTtcbiAgICAgIHJlc3VsdCA9IG9wdGlvbnMucGFydGlhbHNbb3B0aW9ucy5uYW1lXShjb250ZXh0LCBvcHRpb25zKTtcbiAgICB9XG4gICAgaWYgKHJlc3VsdCAhPSBudWxsKSB7XG4gICAgICBpZiAob3B0aW9ucy5pbmRlbnQpIHtcbiAgICAgICAgbGV0IGxpbmVzID0gcmVzdWx0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBsaW5lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICBpZiAoIWxpbmVzW2ldICYmIGkgKyAxID09PSBsKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsaW5lc1tpXSA9IG9wdGlvbnMuaW5kZW50ICsgbGluZXNbaV07XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0ID0gbGluZXMuam9pbignXFxuJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdUaGUgcGFydGlhbCAnICsgb3B0aW9ucy5uYW1lICsgJyBjb3VsZCBub3QgYmUgY29tcGlsZWQgd2hlbiBydW5uaW5nIGluIHJ1bnRpbWUtb25seSBtb2RlJyk7XG4gICAgfVxuICB9XG5cbiAgLy8gSnVzdCBhZGQgd2F0ZXJcbiAgbGV0IGNvbnRhaW5lciA9IHtcbiAgICBzdHJpY3Q6IGZ1bmN0aW9uKG9iaiwgbmFtZSkge1xuICAgICAgaWYgKCEobmFtZSBpbiBvYmopKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oJ1wiJyArIG5hbWUgKyAnXCIgbm90IGRlZmluZWQgaW4gJyArIG9iaik7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqW25hbWVdO1xuICAgIH0sXG4gICAgbG9va3VwOiBmdW5jdGlvbihkZXB0aHMsIG5hbWUpIHtcbiAgICAgIGNvbnN0IGxlbiA9IGRlcHRocy5sZW5ndGg7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmIChkZXB0aHNbaV0gJiYgZGVwdGhzW2ldW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gZGVwdGhzW2ldW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBsYW1iZGE6IGZ1bmN0aW9uKGN1cnJlbnQsIGNvbnRleHQpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgY3VycmVudCA9PT0gJ2Z1bmN0aW9uJyA/IGN1cnJlbnQuY2FsbChjb250ZXh0KSA6IGN1cnJlbnQ7XG4gICAgfSxcblxuICAgIGVzY2FwZUV4cHJlc3Npb246IFV0aWxzLmVzY2FwZUV4cHJlc3Npb24sXG4gICAgaW52b2tlUGFydGlhbDogaW52b2tlUGFydGlhbFdyYXBwZXIsXG5cbiAgICBmbjogZnVuY3Rpb24oaSkge1xuICAgICAgbGV0IHJldCA9IHRlbXBsYXRlU3BlY1tpXTtcbiAgICAgIHJldC5kZWNvcmF0b3IgPSB0ZW1wbGF0ZVNwZWNbaSArICdfZCddO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9LFxuXG4gICAgcHJvZ3JhbXM6IFtdLFxuICAgIHByb2dyYW06IGZ1bmN0aW9uKGksIGRhdGEsIGRlY2xhcmVkQmxvY2tQYXJhbXMsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcbiAgICAgIGxldCBwcm9ncmFtV3JhcHBlciA9IHRoaXMucHJvZ3JhbXNbaV0sXG4gICAgICAgICAgZm4gPSB0aGlzLmZuKGkpO1xuICAgICAgaWYgKGRhdGEgfHwgZGVwdGhzIHx8IGJsb2NrUGFyYW1zIHx8IGRlY2xhcmVkQmxvY2tQYXJhbXMpIHtcbiAgICAgICAgcHJvZ3JhbVdyYXBwZXIgPSB3cmFwUHJvZ3JhbSh0aGlzLCBpLCBmbiwgZGF0YSwgZGVjbGFyZWRCbG9ja1BhcmFtcywgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gICAgICB9IGVsc2UgaWYgKCFwcm9ncmFtV3JhcHBlcikge1xuICAgICAgICBwcm9ncmFtV3JhcHBlciA9IHRoaXMucHJvZ3JhbXNbaV0gPSB3cmFwUHJvZ3JhbSh0aGlzLCBpLCBmbik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvZ3JhbVdyYXBwZXI7XG4gICAgfSxcblxuICAgIGRhdGE6IGZ1bmN0aW9uKHZhbHVlLCBkZXB0aCkge1xuICAgICAgd2hpbGUgKHZhbHVlICYmIGRlcHRoLS0pIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5fcGFyZW50O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sXG4gICAgbWVyZ2U6IGZ1bmN0aW9uKHBhcmFtLCBjb21tb24pIHtcbiAgICAgIGxldCBvYmogPSBwYXJhbSB8fCBjb21tb247XG5cbiAgICAgIGlmIChwYXJhbSAmJiBjb21tb24gJiYgKHBhcmFtICE9PSBjb21tb24pKSB7XG4gICAgICAgIG9iaiA9IFV0aWxzLmV4dGVuZCh7fSwgY29tbW9uLCBwYXJhbSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmo7XG4gICAgfSxcblxuICAgIG5vb3A6IGVudi5WTS5ub29wLFxuICAgIGNvbXBpbGVySW5mbzogdGVtcGxhdGVTcGVjLmNvbXBpbGVyXG4gIH07XG5cbiAgZnVuY3Rpb24gcmV0KGNvbnRleHQsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBkYXRhID0gb3B0aW9ucy5kYXRhO1xuXG4gICAgcmV0Ll9zZXR1cChvcHRpb25zKTtcbiAgICBpZiAoIW9wdGlvbnMucGFydGlhbCAmJiB0ZW1wbGF0ZVNwZWMudXNlRGF0YSkge1xuICAgICAgZGF0YSA9IGluaXREYXRhKGNvbnRleHQsIGRhdGEpO1xuICAgIH1cbiAgICBsZXQgZGVwdGhzLFxuICAgICAgICBibG9ja1BhcmFtcyA9IHRlbXBsYXRlU3BlYy51c2VCbG9ja1BhcmFtcyA/IFtdIDogdW5kZWZpbmVkO1xuICAgIGlmICh0ZW1wbGF0ZVNwZWMudXNlRGVwdGhzKSB7XG4gICAgICBpZiAob3B0aW9ucy5kZXB0aHMpIHtcbiAgICAgICAgZGVwdGhzID0gY29udGV4dCAhPSBvcHRpb25zLmRlcHRoc1swXSA/IFtjb250ZXh0XS5jb25jYXQob3B0aW9ucy5kZXB0aHMpIDogb3B0aW9ucy5kZXB0aHM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZXB0aHMgPSBbY29udGV4dF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFpbihjb250ZXh0LyosIG9wdGlvbnMqLykge1xuICAgICAgcmV0dXJuICcnICsgdGVtcGxhdGVTcGVjLm1haW4oY29udGFpbmVyLCBjb250ZXh0LCBjb250YWluZXIuaGVscGVycywgY29udGFpbmVyLnBhcnRpYWxzLCBkYXRhLCBibG9ja1BhcmFtcywgZGVwdGhzKTtcbiAgICB9XG4gICAgbWFpbiA9IGV4ZWN1dGVEZWNvcmF0b3JzKHRlbXBsYXRlU3BlYy5tYWluLCBtYWluLCBjb250YWluZXIsIG9wdGlvbnMuZGVwdGhzIHx8IFtdLCBkYXRhLCBibG9ja1BhcmFtcyk7XG4gICAgcmV0dXJuIG1haW4oY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cbiAgcmV0LmlzVG9wID0gdHJ1ZTtcblxuICByZXQuX3NldHVwID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucy5wYXJ0aWFsKSB7XG4gICAgICBjb250YWluZXIuaGVscGVycyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLmhlbHBlcnMsIGVudi5oZWxwZXJzKTtcblxuICAgICAgaWYgKHRlbXBsYXRlU3BlYy51c2VQYXJ0aWFsKSB7XG4gICAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IGNvbnRhaW5lci5tZXJnZShvcHRpb25zLnBhcnRpYWxzLCBlbnYucGFydGlhbHMpO1xuICAgICAgfVxuICAgICAgaWYgKHRlbXBsYXRlU3BlYy51c2VQYXJ0aWFsIHx8IHRlbXBsYXRlU3BlYy51c2VEZWNvcmF0b3JzKSB7XG4gICAgICAgIGNvbnRhaW5lci5kZWNvcmF0b3JzID0gY29udGFpbmVyLm1lcmdlKG9wdGlvbnMuZGVjb3JhdG9ycywgZW52LmRlY29yYXRvcnMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb250YWluZXIuaGVscGVycyA9IG9wdGlvbnMuaGVscGVycztcbiAgICAgIGNvbnRhaW5lci5wYXJ0aWFscyA9IG9wdGlvbnMucGFydGlhbHM7XG4gICAgICBjb250YWluZXIuZGVjb3JhdG9ycyA9IG9wdGlvbnMuZGVjb3JhdG9ycztcbiAgICB9XG4gIH07XG5cbiAgcmV0Ll9jaGlsZCA9IGZ1bmN0aW9uKGksIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpIHtcbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZUJsb2NrUGFyYW1zICYmICFibG9ja1BhcmFtcykge1xuICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignbXVzdCBwYXNzIGJsb2NrIHBhcmFtcycpO1xuICAgIH1cbiAgICBpZiAodGVtcGxhdGVTcGVjLnVzZURlcHRocyAmJiAhZGVwdGhzKSB7XG4gICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCdtdXN0IHBhc3MgcGFyZW50IGRlcHRocycpO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwUHJvZ3JhbShjb250YWluZXIsIGksIHRlbXBsYXRlU3BlY1tpXSwgZGF0YSwgMCwgYmxvY2tQYXJhbXMsIGRlcHRocyk7XG4gIH07XG4gIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cmFwUHJvZ3JhbShjb250YWluZXIsIGksIGZuLCBkYXRhLCBkZWNsYXJlZEJsb2NrUGFyYW1zLCBibG9ja1BhcmFtcywgZGVwdGhzKSB7XG4gIGZ1bmN0aW9uIHByb2coY29udGV4dCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgbGV0IGN1cnJlbnREZXB0aHMgPSBkZXB0aHM7XG4gICAgaWYgKGRlcHRocyAmJiBjb250ZXh0ICE9IGRlcHRoc1swXSkge1xuICAgICAgY3VycmVudERlcHRocyA9IFtjb250ZXh0XS5jb25jYXQoZGVwdGhzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZm4oY29udGFpbmVyLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICBjb250YWluZXIuaGVscGVycywgY29udGFpbmVyLnBhcnRpYWxzLFxuICAgICAgICBvcHRpb25zLmRhdGEgfHwgZGF0YSxcbiAgICAgICAgYmxvY2tQYXJhbXMgJiYgW29wdGlvbnMuYmxvY2tQYXJhbXNdLmNvbmNhdChibG9ja1BhcmFtcyksXG4gICAgICAgIGN1cnJlbnREZXB0aHMpO1xuICB9XG5cbiAgcHJvZyA9IGV4ZWN1dGVEZWNvcmF0b3JzKGZuLCBwcm9nLCBjb250YWluZXIsIGRlcHRocywgZGF0YSwgYmxvY2tQYXJhbXMpO1xuXG4gIHByb2cucHJvZ3JhbSA9IGk7XG4gIHByb2cuZGVwdGggPSBkZXB0aHMgPyBkZXB0aHMubGVuZ3RoIDogMDtcbiAgcHJvZy5ibG9ja1BhcmFtcyA9IGRlY2xhcmVkQmxvY2tQYXJhbXMgfHwgMDtcbiAgcmV0dXJuIHByb2c7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUGFydGlhbChwYXJ0aWFsLCBjb250ZXh0LCBvcHRpb25zKSB7XG4gIGlmICghcGFydGlhbCkge1xuICAgIGlmIChvcHRpb25zLm5hbWUgPT09ICdAcGFydGlhbC1ibG9jaycpIHtcbiAgICAgIGxldCBkYXRhID0gb3B0aW9ucy5kYXRhO1xuICAgICAgd2hpbGUgKGRhdGFbJ3BhcnRpYWwtYmxvY2snXSA9PT0gbm9vcCkge1xuICAgICAgICBkYXRhID0gZGF0YS5fcGFyZW50O1xuICAgICAgfVxuICAgICAgcGFydGlhbCA9IGRhdGFbJ3BhcnRpYWwtYmxvY2snXTtcbiAgICAgIGRhdGFbJ3BhcnRpYWwtYmxvY2snXSA9IG5vb3A7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcnRpYWwgPSBvcHRpb25zLnBhcnRpYWxzW29wdGlvbnMubmFtZV07XG4gICAgfVxuICB9IGVsc2UgaWYgKCFwYXJ0aWFsLmNhbGwgJiYgIW9wdGlvbnMubmFtZSkge1xuICAgIC8vIFRoaXMgaXMgYSBkeW5hbWljIHBhcnRpYWwgdGhhdCByZXR1cm5lZCBhIHN0cmluZ1xuICAgIG9wdGlvbnMubmFtZSA9IHBhcnRpYWw7XG4gICAgcGFydGlhbCA9IG9wdGlvbnMucGFydGlhbHNbcGFydGlhbF07XG4gIH1cbiAgcmV0dXJuIHBhcnRpYWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZva2VQYXJ0aWFsKHBhcnRpYWwsIGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucy5wYXJ0aWFsID0gdHJ1ZTtcbiAgaWYgKG9wdGlvbnMuaWRzKSB7XG4gICAgb3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoID0gb3B0aW9ucy5pZHNbMF0gfHwgb3B0aW9ucy5kYXRhLmNvbnRleHRQYXRoO1xuICB9XG5cbiAgbGV0IHBhcnRpYWxCbG9jaztcbiAgaWYgKG9wdGlvbnMuZm4gJiYgb3B0aW9ucy5mbiAhPT0gbm9vcCkge1xuICAgIG9wdGlvbnMuZGF0YSA9IGNyZWF0ZUZyYW1lKG9wdGlvbnMuZGF0YSk7XG4gICAgcGFydGlhbEJsb2NrID0gb3B0aW9ucy5kYXRhWydwYXJ0aWFsLWJsb2NrJ10gPSBvcHRpb25zLmZuO1xuXG4gICAgaWYgKHBhcnRpYWxCbG9jay5wYXJ0aWFscykge1xuICAgICAgb3B0aW9ucy5wYXJ0aWFscyA9IFV0aWxzLmV4dGVuZCh7fSwgb3B0aW9ucy5wYXJ0aWFscywgcGFydGlhbEJsb2NrLnBhcnRpYWxzKTtcbiAgICB9XG4gIH1cblxuICBpZiAocGFydGlhbCA9PT0gdW5kZWZpbmVkICYmIHBhcnRpYWxCbG9jaykge1xuICAgIHBhcnRpYWwgPSBwYXJ0aWFsQmxvY2s7XG4gIH1cblxuICBpZiAocGFydGlhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEV4Y2VwdGlvbignVGhlIHBhcnRpYWwgJyArIG9wdGlvbnMubmFtZSArICcgY291bGQgbm90IGJlIGZvdW5kJyk7XG4gIH0gZWxzZSBpZiAocGFydGlhbCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIHBhcnRpYWwoY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5vb3AoKSB7IHJldHVybiAnJzsgfVxuXG5mdW5jdGlvbiBpbml0RGF0YShjb250ZXh0LCBkYXRhKSB7XG4gIGlmICghZGF0YSB8fCAhKCdyb290JyBpbiBkYXRhKSkge1xuICAgIGRhdGEgPSBkYXRhID8gY3JlYXRlRnJhbWUoZGF0YSkgOiB7fTtcbiAgICBkYXRhLnJvb3QgPSBjb250ZXh0O1xuICB9XG4gIHJldHVybiBkYXRhO1xufVxuXG5mdW5jdGlvbiBleGVjdXRlRGVjb3JhdG9ycyhmbiwgcHJvZywgY29udGFpbmVyLCBkZXB0aHMsIGRhdGEsIGJsb2NrUGFyYW1zKSB7XG4gIGlmIChmbi5kZWNvcmF0b3IpIHtcbiAgICBsZXQgcHJvcHMgPSB7fTtcbiAgICBwcm9nID0gZm4uZGVjb3JhdG9yKHByb2csIHByb3BzLCBjb250YWluZXIsIGRlcHRocyAmJiBkZXB0aHNbMF0sIGRhdGEsIGJsb2NrUGFyYW1zLCBkZXB0aHMpO1xuICAgIFV0aWxzLmV4dGVuZChwcm9nLCBwcm9wcyk7XG4gIH1cbiAgcmV0dXJuIHByb2c7XG59XG4iXX0= +; +define('handlebars/no-conflict',['exports', 'module'], function (exports, module) { + /* global window */ + 'use strict'; + + module.exports = function (Handlebars) { + /* istanbul ignore next */ + var root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function () { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; + }; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9oYW5kbGViYXJzL25vLWNvbmZsaWN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7bUJBQ2UsVUFBUyxVQUFVLEVBQUU7O0FBRWxDLFFBQUksSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsR0FBRyxNQUFNLEdBQUcsTUFBTTtRQUN0RCxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQzs7QUFFbEMsY0FBVSxDQUFDLFVBQVUsR0FBRyxZQUFXO0FBQ2pDLFVBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUU7QUFDbEMsWUFBSSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUM7T0FDL0I7QUFDRCxhQUFPLFVBQVUsQ0FBQztLQUNuQixDQUFDO0dBQ0giLCJmaWxlIjoibm8tY29uZmxpY3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBnbG9iYWwgd2luZG93ICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihIYW5kbGViYXJzKSB7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGxldCByb290ID0gdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3csXG4gICAgICAkSGFuZGxlYmFycyA9IHJvb3QuSGFuZGxlYmFycztcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgSGFuZGxlYmFycy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHJvb3QuSGFuZGxlYmFycyA9PT0gSGFuZGxlYmFycykge1xuICAgICAgcm9vdC5IYW5kbGViYXJzID0gJEhhbmRsZWJhcnM7XG4gICAgfVxuICAgIHJldHVybiBIYW5kbGViYXJzO1xuICB9O1xufVxuIl19 +; +define('handlebars.runtime',['exports', 'module', './handlebars/base', './handlebars/safe-string', './handlebars/exception', './handlebars/utils', './handlebars/runtime', './handlebars/no-conflict'], function (exports, module, _handlebarsBase, _handlebarsSafeString, _handlebarsException, _handlebarsUtils, _handlebarsRuntime, _handlebarsNoConflict) { + 'use strict'; + + // istanbul ignore next + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + // Each of these augment the Handlebars object. No need to setup here. + // (This is done to easily share code between commonjs and browse envs) + + var _SafeString = _interopRequireDefault(_handlebarsSafeString); + + var _Exception = _interopRequireDefault(_handlebarsException); + + var _noConflict = _interopRequireDefault(_handlebarsNoConflict); + + // For compatibility and usage outside of module systems, make the Handlebars object a namespace + function create() { + var hb = new _handlebarsBase.HandlebarsEnvironment(); + + _handlebarsUtils.extend(hb, _handlebarsBase); + hb.SafeString = _SafeString['default']; + hb.Exception = _Exception['default']; + hb.Utils = _handlebarsUtils; + hb.escapeExpression = _handlebarsUtils.escapeExpression; + + hb.VM = _handlebarsRuntime; + hb.template = function (spec) { + return _handlebarsRuntime.template(spec, hb); + }; + + return hb; + } + + var inst = create(); + inst.create = create; + + _noConflict['default'](inst); + + inst['default'] = inst; + + module.exports = inst; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9oYW5kbGViYXJzLnJ1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFZQSxXQUFTLE1BQU0sR0FBRztBQUNoQixRQUFJLEVBQUUsR0FBRyxJQUFJLGdCQUFLLHFCQUFxQixFQUFFLENBQUM7O0FBRTFDLHFCQUFNLE1BQU0sQ0FBQyxFQUFFLGtCQUFPLENBQUM7QUFDdkIsTUFBRSxDQUFDLFVBQVUseUJBQWEsQ0FBQztBQUMzQixNQUFFLENBQUMsU0FBUyx3QkFBWSxDQUFDO0FBQ3pCLE1BQUUsQ0FBQyxLQUFLLG1CQUFRLENBQUM7QUFDakIsTUFBRSxDQUFDLGdCQUFnQixHQUFHLGlCQUFNLGdCQUFnQixDQUFDOztBQUU3QyxNQUFFLENBQUMsRUFBRSxxQkFBVSxDQUFDO0FBQ2hCLE1BQUUsQ0FBQyxRQUFRLEdBQUcsVUFBUyxJQUFJLEVBQUU7QUFDM0IsYUFBTyxtQkFBUSxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ25DLENBQUM7O0FBRUYsV0FBTyxFQUFFLENBQUM7R0FDWDs7QUFFRCxNQUFJLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQztBQUNwQixNQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7QUFFckIseUJBQVcsSUFBSSxDQUFDLENBQUM7O0FBRWpCLE1BQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7O21CQUVSLElBQUkiLCJmaWxlIjoiaGFuZGxlYmFycy5ydW50aW1lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYmFzZSBmcm9tICcuL2hhbmRsZWJhcnMvYmFzZSc7XG5cbi8vIEVhY2ggb2YgdGhlc2UgYXVnbWVudCB0aGUgSGFuZGxlYmFycyBvYmplY3QuIE5vIG5lZWQgdG8gc2V0dXAgaGVyZS5cbi8vIChUaGlzIGlzIGRvbmUgdG8gZWFzaWx5IHNoYXJlIGNvZGUgYmV0d2VlbiBjb21tb25qcyBhbmQgYnJvd3NlIGVudnMpXG5pbXBvcnQgU2FmZVN0cmluZyBmcm9tICcuL2hhbmRsZWJhcnMvc2FmZS1zdHJpbmcnO1xuaW1wb3J0IEV4Y2VwdGlvbiBmcm9tICcuL2hhbmRsZWJhcnMvZXhjZXB0aW9uJztcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gJy4vaGFuZGxlYmFycy91dGlscyc7XG5pbXBvcnQgKiBhcyBydW50aW1lIGZyb20gJy4vaGFuZGxlYmFycy9ydW50aW1lJztcblxuaW1wb3J0IG5vQ29uZmxpY3QgZnJvbSAnLi9oYW5kbGViYXJzL25vLWNvbmZsaWN0JztcblxuLy8gRm9yIGNvbXBhdGliaWxpdHkgYW5kIHVzYWdlIG91dHNpZGUgb2YgbW9kdWxlIHN5c3RlbXMsIG1ha2UgdGhlIEhhbmRsZWJhcnMgb2JqZWN0IGEgbmFtZXNwYWNlXG5mdW5jdGlvbiBjcmVhdGUoKSB7XG4gIGxldCBoYiA9IG5ldyBiYXNlLkhhbmRsZWJhcnNFbnZpcm9ubWVudCgpO1xuXG4gIFV0aWxzLmV4dGVuZChoYiwgYmFzZSk7XG4gIGhiLlNhZmVTdHJpbmcgPSBTYWZlU3RyaW5nO1xuICBoYi5FeGNlcHRpb24gPSBFeGNlcHRpb247XG4gIGhiLlV0aWxzID0gVXRpbHM7XG4gIGhiLmVzY2FwZUV4cHJlc3Npb24gPSBVdGlscy5lc2NhcGVFeHByZXNzaW9uO1xuXG4gIGhiLlZNID0gcnVudGltZTtcbiAgaGIudGVtcGxhdGUgPSBmdW5jdGlvbihzcGVjKSB7XG4gICAgcmV0dXJuIHJ1bnRpbWUudGVtcGxhdGUoc3BlYywgaGIpO1xuICB9O1xuXG4gIHJldHVybiBoYjtcbn1cblxubGV0IGluc3QgPSBjcmVhdGUoKTtcbmluc3QuY3JlYXRlID0gY3JlYXRlO1xuXG5ub0NvbmZsaWN0KGluc3QpO1xuXG5pbnN0WydkZWZhdWx0J10gPSBpbnN0O1xuXG5leHBvcnQgZGVmYXVsdCBpbnN0O1xuIl19 +; diff --git a/hm_sunwell/node_modules/handlebars/dist/handlebars.runtime.amd.min.js b/hm_sunwell/node_modules/handlebars/dist/handlebars.runtime.amd.min.js new file mode 100644 index 0000000..e1370cf --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/handlebars.runtime.amd.min.js @@ -0,0 +1,27 @@ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +define("handlebars/utils",["exports"],function(a){"use strict";function b(a){return j[a]}function c(a){for(var b=1;b":">",'"':""","'":"'","`":"`","=":"="},k=/[&<>"'`=]/g,l=/[&<>"'`=]/,m=Object.prototype.toString;a.toString=m;var n=function(a){return"function"==typeof a};n(/x/)&&(a.isFunction=n=function(a){return"function"==typeof a&&"[object Function]"===m.call(a)}),a.isFunction=n;var o=Array.isArray||function(a){return!(!a||"object"!=typeof a)&&"[object Array]"===m.call(a)};a.isArray=o}),define("handlebars/exception",["exports","module"],function(a,b){"use strict";function c(a,b){var e=b&&b.loc,f=void 0,g=void 0;e&&(f=e.start.line,g=e.start.column,a+=" - "+f+":"+g);for(var h=Error.prototype.constructor.call(this,a),i=0;i0?(d.ids&&(d.ids=[d.name]),a.helpers.each(b,d)):e(this);if(d.data&&d.ids){var g=c.createFrame(d.data);g.contextPath=c.appendContextPath(d.data.contextPath,d.name),d={data:g}}return f(b,d)})}}),define("handlebars/helpers/each",["exports","module","../utils","../exception"],function(a,b,c,d){"use strict";function e(a){return a&&a.__esModule?a:{"default":a}}var f=e(d);b.exports=function(a){a.registerHelper("each",function(a,b){function d(b,d,f){j&&(j.key=b,j.index=d,j.first=0===d,j.last=!!f,k&&(j.contextPath=k+b)),i+=e(a[b],{data:j,blockParams:c.blockParams([a[b],b],[k+b,null])})}if(!b)throw new f["default"]("Must pass iterator to #each");var e=b.fn,g=b.inverse,h=0,i="",j=void 0,k=void 0;if(b.data&&b.ids&&(k=c.appendContextPath(b.data.contextPath,b.ids[0])+"."),c.isFunction(a)&&(a=a.call(this)),b.data&&(j=c.createFrame(b.data)),a&&"object"==typeof a)if(c.isArray(a))for(var l=a.length;h=0?b:parseInt(a,10)}return a},log:function(a){if(a=d.lookupLevel(a),"undefined"!=typeof console&&d.lookupLevel(d.level)<=a){var b=d.methodMap[a];console[b]||(b="log");for(var c=arguments.length,e=Array(c>1?c-1:0),f=1;f= 2.0.0-beta.1",7:">= 4.0.0"};a.REVISION_CHANGES=m;var n="[object Object]";h.prototype={constructor:h,logger:j["default"],log:j["default"].log,registerHelper:function(a,c){if(b.toString.call(a)===n){if(c)throw new i["default"]("Arg not supported with multiple helpers");b.extend(this.helpers,a)}else this.helpers[a]=c},unregisterHelper:function(a){delete this.helpers[a]},registerPartial:function(a,c){if(b.toString.call(a)===n)b.extend(this.partials,a);else{if("undefined"==typeof c)throw new i["default"]('Attempting to register a partial called "'+a+'" as undefined');this.partials[a]=c}},unregisterPartial:function(a){delete this.partials[a]},registerDecorator:function(a,c){if(b.toString.call(a)===n){if(c)throw new i["default"]("Arg not supported with multiple decorators");b.extend(this.decorators,a)}else this.decorators[a]=c},unregisterDecorator:function(a){delete this.decorators[a]}};var o=j["default"].log;a.log=o,a.createFrame=b.createFrame,a.logger=j["default"]}),define("handlebars/safe-string",["exports","module"],function(a,b){"use strict";function c(a){this.string=a}c.prototype.toString=c.prototype.toHTML=function(){return""+this.string},b.exports=c}),define("handlebars/runtime",["exports","./utils","./exception","./base"],function(a,b,c,d){"use strict";function e(a){return a&&a.__esModule?a:{"default":a}}function f(a){var b=a&&a[0]||1,c=d.COMPILER_REVISION;if(b!==c){if(b= 2.0.0-beta.1', + 7: '>= 4.0.0' + }; + + exports.REVISION_CHANGES = REVISION_CHANGES; + var objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + _helpers.registerDefaultHelpers(this); + _decorators.registerDefaultDecorators(this); + } + + HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: _logger2['default'], + log: _logger2['default'].log, + + registerHelper: function registerHelper(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _exception2['default']('Arg not supported with multiple helpers'); + } + _utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function unregisterHelper(name) { + delete this.helpers[name]; + }, + + registerPartial: function registerPartial(name, partial) { + if (_utils.toString.call(name) === objectType) { + _utils.extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined'); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function unregisterPartial(name) { + delete this.partials[name]; + }, + + registerDecorator: function registerDecorator(name, fn) { + if (_utils.toString.call(name) === objectType) { + if (fn) { + throw new _exception2['default']('Arg not supported with multiple decorators'); + } + _utils.extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function unregisterDecorator(name) { + delete this.decorators[name]; + } + }; + + var log = _logger2['default'].log; + + exports.log = log; + exports.createFrame = _utils.createFrame; + exports.logger = _logger2['default']; + +/***/ }, +/* 4 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + exports.extend = extend; + exports.indexOf = indexOf; + exports.escapeExpression = escapeExpression; + exports.isEmpty = isEmpty; + exports.createFrame = createFrame; + exports.blockParams = blockParams; + exports.appendContextPath = appendContextPath; + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' + }; + + var badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + + function escapeChar(chr) { + return escape[chr]; + } + + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; + } + + var toString = Object.prototype.toString; + + exports.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + /* eslint-disable func-style */ + var isFunction = function isFunction(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + exports.isFunction = isFunction = function (value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + exports.isFunction = isFunction; + + /* eslint-enable func-style */ + + /* istanbul ignore next */ + var isArray = Array.isArray || function (value) { + return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; + }; + + exports.isArray = isArray; + // Older IE versions do not directly support indexOf so we must implement our own, sadly. + + function indexOf(array, value) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; + } + + function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); + } + + function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + function createFrame(object) { + var frame = extend({}, object); + frame._parent = object; + return frame; + } + + function blockParams(params, ids) { + params.path = ids; + return params; + } + + function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; + } + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _Object$defineProperty = __webpack_require__(6)['default']; + + exports.__esModule = true; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var loc = node && node.loc, + line = undefined, + column = undefined; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (_Object$defineProperty) { + Object.defineProperty(this, 'column', { value: column }); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } + } + + Exception.prototype = new Error(); + + exports['default'] = Exception; + module.exports = exports['default']; + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = { "default": __webpack_require__(7), __esModule: true }; + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + var $ = __webpack_require__(8); + module.exports = function defineProperty(it, key, desc){ + return $.setDesc(it, key, desc); + }; + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + + var $Object = Object; + module.exports = { + create: $Object.create, + getProto: $Object.getPrototypeOf, + isEnum: {}.propertyIsEnumerable, + getDesc: $Object.getOwnPropertyDescriptor, + setDesc: $Object.defineProperty, + setDescs: $Object.defineProperties, + getKeys: $Object.keys, + getNames: $Object.getOwnPropertyNames, + getSymbols: $Object.getOwnPropertySymbols, + each: [].forEach + }; + +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(2)['default']; + + exports.__esModule = true; + exports.registerDefaultHelpers = registerDefaultHelpers; + + var _helpersBlockHelperMissing = __webpack_require__(10); + + var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing); + + var _helpersEach = __webpack_require__(11); + + var _helpersEach2 = _interopRequireDefault(_helpersEach); + + var _helpersHelperMissing = __webpack_require__(12); + + var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing); + + var _helpersIf = __webpack_require__(13); + + var _helpersIf2 = _interopRequireDefault(_helpersIf); + + var _helpersLog = __webpack_require__(14); + + var _helpersLog2 = _interopRequireDefault(_helpersLog); + + var _helpersLookup = __webpack_require__(15); + + var _helpersLookup2 = _interopRequireDefault(_helpersLookup); + + var _helpersWith = __webpack_require__(16); + + var _helpersWith2 = _interopRequireDefault(_helpersWith); + + function registerDefaultHelpers(instance) { + _helpersBlockHelperMissing2['default'](instance); + _helpersEach2['default'](instance); + _helpersHelperMissing2['default'](instance); + _helpersIf2['default'](instance); + _helpersLog2['default'](instance); + _helpersLookup2['default'](instance); + _helpersWith2['default'](instance); + } + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(4); + + exports['default'] = function (instance) { + instance.registerHelper('blockHelperMissing', function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(2)['default']; + + exports.__esModule = true; + + var _utils = __webpack_require__(4); + + var _exception = __webpack_require__(5); + + var _exception2 = _interopRequireDefault(_exception); + + exports['default'] = function (instance) { + instance.registerHelper('each', function (context, options) { + if (!options) { + throw new _exception2['default']('Must pass iterator to #each'); + } + + var fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data = undefined, + contextPath = undefined; + + if (options.data && options.ids) { + contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (_utils.isFunction(context)) { + context = context.call(this); + } + + if (options.data) { + data = _utils.createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (_utils.isArray(context)) { + for (var j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + var priorKey = undefined; + + for (var key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(2)['default']; + + exports.__esModule = true; + + var _exception = __webpack_require__(5); + + var _exception2 = _interopRequireDefault(_exception); + + exports['default'] = function (instance) { + instance.registerHelper('helperMissing', function () /* [args, ]options */{ + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(4); + + exports['default'] = function (instance) { + instance.registerHelper('if', function (conditional, options) { + if (_utils.isFunction(conditional)) { + conditional = conditional.call(this); + } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function (conditional, options) { + return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 14 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + + exports['default'] = function (instance) { + instance.registerHelper('log', function () /* message, options */{ + var args = [undefined], + options = arguments[arguments.length - 1]; + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + var level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log.apply(instance, args); + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 15 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + + exports['default'] = function (instance) { + instance.registerHelper('lookup', function (obj, field) { + return obj && obj[field]; + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(4); + + exports['default'] = function (instance) { + instance.registerHelper('with', function (context, options) { + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireDefault = __webpack_require__(2)['default']; + + exports.__esModule = true; + exports.registerDefaultDecorators = registerDefaultDecorators; + + var _decoratorsInline = __webpack_require__(18); + + var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline); + + function registerDefaultDecorators(instance) { + _decoratorsInline2['default'](instance); + } + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(4); + + exports['default'] = function (instance) { + instance.registerDecorator('inline', function (fn, props, container, options) { + var ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function (context, options) { + // Create a new partials stack frame prior to exec. + var original = container.partials; + container.partials = _utils.extend({}, original, props.partials); + var ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); + }; + + module.exports = exports['default']; + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _utils = __webpack_require__(4); + + var logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function lookupLevel(level) { + if (typeof level === 'string') { + var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function log(level) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + var method = logger.methodMap[level]; + if (!console[method]) { + // eslint-disable-line no-console + method = 'log'; + } + + for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + message[_key - 1] = arguments[_key]; + } + + console[method].apply(console, message); // eslint-disable-line no-console + } + } + }; + + exports['default'] = logger; + module.exports = exports['default']; + +/***/ }, +/* 20 */ +/***/ function(module, exports) { + + // Build out our basic SafeString type + 'use strict'; + + exports.__esModule = true; + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = SafeString.prototype.toHTML = function () { + return '' + this.string; + }; + + exports['default'] = SafeString; + module.exports = exports['default']; + +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireWildcard = __webpack_require__(1)['default']; + + var _interopRequireDefault = __webpack_require__(2)['default']; + + exports.__esModule = true; + exports.checkRevision = checkRevision; + exports.template = template; + exports.wrapProgram = wrapProgram; + exports.resolvePartial = resolvePartial; + exports.invokePartial = invokePartial; + exports.noop = noop; + + var _utils = __webpack_require__(4); + + var Utils = _interopRequireWildcard(_utils); + + var _exception = __webpack_require__(5); + + var _exception2 = _interopRequireDefault(_exception); + + var _base = __webpack_require__(3); + + function checkRevision(compilerInfo) { + var compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = _base.COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = _base.REVISION_CHANGES[currentRevision], + compilerVersions = _base.REVISION_CHANGES[compilerRevision]; + throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } + } + + function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new _exception2['default']('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new _exception2['default']('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = Utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + var result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + var lines = result.split('\n'); + for (var i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + var container = { + strict: function strict(obj, name) { + if (!(name in obj)) { + throw new _exception2['default']('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function lookup(depths, name) { + var len = depths.length; + for (var i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function lambda(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: Utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function fn(i) { + var ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function program(i, data, declaredBlockParams, blockParams, depths) { + var programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function data(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function merge(param, common) { + var obj = param || common; + + if (param && common && param !== common) { + obj = Utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function (options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function (i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new _exception2['default']('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new _exception2['default']('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; + } + + function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; + } + + function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + var data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; + } + + function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + var partialBlock = undefined; + if (options.fn && options.fn !== noop) { + options.data = _base.createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = Utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new _exception2['default']('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } + } + + function noop() { + return ''; + } + + function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? _base.createFrame(data) : {}; + data.root = context; + } + return data; + } + + function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + var props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + Utils.extend(prog, props); + } + return prog; + } + +/***/ }, +/* 22 */ +/***/ function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/* global window */ + 'use strict'; + + exports.__esModule = true; + + exports['default'] = function (Handlebars) { + /* istanbul ignore next */ + var root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function () { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; + }; + + module.exports = exports['default']; + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/hm_sunwell/node_modules/handlebars/dist/handlebars.runtime.min.js b/hm_sunwell/node_modules/handlebars/dist/handlebars.runtime.min.js new file mode 100644 index 0000000..bb16b55 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/dist/handlebars.runtime.min.js @@ -0,0 +1,79 @@ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +/**! + + @license + handlebars v4.0.6 + +Copyright (C) 2011-2016 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +!function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?exports.Handlebars=b():a.Handlebars=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){"use strict";function d(){var a=new h.HandlebarsEnvironment;return n.extend(a,h),a.SafeString=j["default"],a.Exception=l["default"],a.Utils=n,a.escapeExpression=n.escapeExpression,a.VM=p,a.template=function(b){return p.template(b,a)},a}var e=c(1)["default"],f=c(2)["default"];b.__esModule=!0;var g=c(3),h=e(g),i=c(20),j=f(i),k=c(5),l=f(k),m=c(4),n=e(m),o=c(21),p=e(o),q=c(22),r=f(q),s=d();s.create=d,r["default"](s),s["default"]=s,b["default"]=s,a.exports=b["default"]},function(a,b){"use strict";b["default"]=function(a){if(a&&a.__esModule)return a;var b={};if(null!=a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]=a[c]);return b["default"]=a,b},b.__esModule=!0},function(a,b){"use strict";b["default"]=function(a){return a&&a.__esModule?a:{"default":a}},b.__esModule=!0},function(a,b,c){"use strict";function d(a,b,c){this.helpers=a||{},this.partials=b||{},this.decorators=c||{},i.registerDefaultHelpers(this),j.registerDefaultDecorators(this)}var e=c(2)["default"];b.__esModule=!0,b.HandlebarsEnvironment=d;var f=c(4),g=c(5),h=e(g),i=c(9),j=c(17),k=c(19),l=e(k),m="4.0.5";b.VERSION=m;var n=7;b.COMPILER_REVISION=n;var o={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0"};b.REVISION_CHANGES=o;var p="[object Object]";d.prototype={constructor:d,logger:l["default"],log:l["default"].log,registerHelper:function(a,b){if(f.toString.call(a)===p){if(b)throw new h["default"]("Arg not supported with multiple helpers");f.extend(this.helpers,a)}else this.helpers[a]=b},unregisterHelper:function(a){delete this.helpers[a]},registerPartial:function(a,b){if(f.toString.call(a)===p)f.extend(this.partials,a);else{if("undefined"==typeof b)throw new h["default"]('Attempting to register a partial called "'+a+'" as undefined');this.partials[a]=b}},unregisterPartial:function(a){delete this.partials[a]},registerDecorator:function(a,b){if(f.toString.call(a)===p){if(b)throw new h["default"]("Arg not supported with multiple decorators");f.extend(this.decorators,a)}else this.decorators[a]=b},unregisterDecorator:function(a){delete this.decorators[a]}};var q=l["default"].log;b.log=q,b.createFrame=f.createFrame,b.logger=l["default"]},function(a,b){"use strict";function c(a){return k[a]}function d(a){for(var b=1;b":">",'"':""","'":"'","`":"`","=":"="},l=/[&<>"'`=]/g,m=/[&<>"'`=]/,n=Object.prototype.toString;b.toString=n;var o=function(a){return"function"==typeof a};o(/x/)&&(b.isFunction=o=function(a){return"function"==typeof a&&"[object Function]"===n.call(a)}),b.isFunction=o;var p=Array.isArray||function(a){return!(!a||"object"!=typeof a)&&"[object Array]"===n.call(a)};b.isArray=p},function(a,b,c){"use strict";function d(a,b){var c=b&&b.loc,g=void 0,h=void 0;c&&(g=c.start.line,h=c.start.column,a+=" - "+g+":"+h);for(var i=Error.prototype.constructor.call(this,a),j=0;j0?(c.ids&&(c.ids=[c.name]),a.helpers.each(b,c)):e(this);if(c.data&&c.ids){var g=d.createFrame(c.data);g.contextPath=d.appendContextPath(c.data.contextPath,c.name),c={data:g}}return f(b,c)})},a.exports=b["default"]},function(a,b,c){"use strict";var d=c(2)["default"];b.__esModule=!0;var e=c(4),f=c(5),g=d(f);b["default"]=function(a){a.registerHelper("each",function(a,b){function c(b,c,f){j&&(j.key=b,j.index=c,j.first=0===c,j.last=!!f,k&&(j.contextPath=k+b)),i+=d(a[b],{data:j,blockParams:e.blockParams([a[b],b],[k+b,null])})}if(!b)throw new g["default"]("Must pass iterator to #each");var d=b.fn,f=b.inverse,h=0,i="",j=void 0,k=void 0;if(b.data&&b.ids&&(k=e.appendContextPath(b.data.contextPath,b.ids[0])+"."),e.isFunction(a)&&(a=a.call(this)),b.data&&(j=e.createFrame(b.data)),a&&"object"==typeof a)if(e.isArray(a))for(var l=a.length;h=0?b:parseInt(a,10)}return a},log:function(a){if(a=e.lookupLevel(a),"undefined"!=typeof console&&e.lookupLevel(e.level)<=a){var b=e.methodMap[a];console[b]||(b="log");for(var c=arguments.length,d=Array(c>1?c-1:0),f=1;f= 1; + column: uint >= 0; +} +``` + +### Programs + +```java +interface Program <: Node { + type: "Program"; + body: [ Statement ]; + + blockParams: [ string ]; +} +``` + +### Statements + +```java +interface Statement <: Node { } + +interface MustacheStatement <: Statement { + type: "MustacheStatement"; + + path: PathExpression | Literal; + params: [ Expression ]; + hash: Hash; + + escaped: boolean; + strip: StripFlags | null; +} + +interface BlockStatement <: Statement { + type: "BlockStatement"; + path: PathExpression; + params: [ Expression ]; + hash: Hash; + + program: Program | null; + inverse: Program | null; + + openStrip: StripFlags | null; + inverseStrip: StripFlags | null; + closeStrip: StripFlags | null; +} + +interface PartialStatement <: Statement { + type: "PartialStatement"; + name: PathExpression | SubExpression; + params: [ Expression ]; + hash: Hash; + + indent: string; + strip: StripFlags | null; +} + +interface PartialBlockStatement <: Statement { + type: "PartialBlockStatement"; + name: PathExpression | SubExpression; + params: [ Expression ]; + hash: Hash; + + program: Program | null; + + indent: string; + openStrip: StripFlags | null; + closeStrip: StripFlags | null; +} +``` + +`name` will be a `SubExpression` when tied to a dynamic partial, i.e. `{{> (foo) }}`, otherwise this is a path or literal whose `original` value is used to lookup the desired partial. + + +```java +interface ContentStatement <: Statement { + type: "ContentStatement"; + value: string; + original: string; +} + +interface CommentStatement <: Statement { + type: "CommentStatement"; + value: string; + + strip: StripFlags | null; +} +``` + + +```java +interface Decorator <: Statement { + type: "Decorator"; + + path: PathExpression | Literal; + params: [ Expression ]; + hash: Hash; + + strip: StripFlags | null; +} + +interface DecoratorBlock <: Statement { + type: "DecoratorBlock"; + path: PathExpression | Literal; + params: [ Expression ]; + hash: Hash; + + program: Program | null; + + openStrip: StripFlags | null; + closeStrip: StripFlags | null; +} +``` + +Decorator paths only utilize the `path.original` value and as a consequence do not support depthed evaluation. + +### Expressions + +```java +interface Expression <: Node { } +``` + +##### SubExpressions + +```java +interface SubExpression <: Expression { + type: "SubExpression"; + path: PathExpression; + params: [ Expression ]; + hash: Hash; +} +``` + +##### Paths + +```java +interface PathExpression <: Expression { + type: "PathExpression"; + data: boolean; + depth: uint >= 0; + parts: [ string ]; + original: string; +} +``` + +- `data` is true when the given expression is a `@data` reference. +- `depth` is an integer representation of which context the expression references. `0` represents the current context, `1` would be `../`, etc. +- `parts` is an array of the names in the path. `foo.bar` would be `['foo', 'bar']`. Scope references, `.`, `..`, and `this` should be omitted from this array. +- `original` is the path as entered by the user. Separator and scope references are left untouched. + + +##### Literals + +```java +interface Literal <: Expression { } + +interface StringLiteral <: Literal { + type: "StringLiteral"; + value: string; + original: string; +} + +interface BooleanLiteral <: Literal { + type: "BooleanLiteral"; + value: boolean; + original: boolean; +} + +interface NumberLiteral <: Literal { + type: "NumberLiteral"; + value: number; + original: number; +} + +interface UndefinedLiteral <: Literal { + type: "UndefinedLiteral"; +} + +interface NullLiteral <: Literal { + type: "NullLiteral"; +} +``` + + +### Miscellaneous + +```java +interface Hash <: Node { + type: "Hash"; + pairs: [ HashPair ]; +} + +interface HashPair <: Node { + type: "HashPair"; + key: string; + value: Expression; +} + +interface StripFlags { + open: boolean; + close: boolean; +} +``` + +`StripFlags` are used to signify whitespace control character that may have been entered on a given statement. + +## AST Visitor + +`Handlebars.Visitor` is available as a base class for general interaction with AST structures. This will by default traverse the entire tree and individual methods may be overridden to provide specific responses to particular nodes. + +Recording all referenced partial names: + +```javascript +var Visitor = Handlebars.Visitor; + +function ImportScanner() { + this.partials = []; +} +ImportScanner.prototype = new Visitor(); + +ImportScanner.prototype.PartialStatement = function(partial) { + this.partials.push({request: partial.name.original}); + + Visitor.prototype.PartialStatement.call(this, partial); +}; + +var scanner = new ImportScanner(); +scanner.accept(ast); +``` + +The current node's ancestors will be maintained in the `parents` array, with the most recent parent listed first. + +The visitor may also be configured to operate in mutation mode by setting the `mutation` field to true. When in this mode, handler methods may return any valid AST node and it will replace the one they are currently operating on. Returning `false` will remove the given value (if valid) and returning `undefined` will leave the node in tact. This return structure only apply to mutation mode and non-mutation mode visitors are free to return whatever values they wish. + +Implementors that may need to support mutation mode are encouraged to utilize the `acceptKey`, `acceptRequired` and `acceptArray` helpers which provide the conditional overwrite behavior as well as implement sanity checks where pertinent. + +## JavaScript Compiler + +The `Handlebars.JavaScriptCompiler` object has a number of methods that may be customized to alter the output of the compiler: + +- `nameLookup(parent, name, type)` + Used to generate the code to resolve a give path component. + + - `parent` is the existing code in the path resolution + - `name` is the current path component + - `type` is the type of name being evaluated. May be one of `context`, `data`, `helper`, `decorator`, or `partial`. + + Note that this does not impact dynamic partials, which implementors need to be aware of. Overriding `VM.resolvePartial` may be required to support dynamic cases. + +- `depthedLookup(name)` + Used to generate code that resolves parameters within any context in the stack. Is only used in `compat` mode. + +- `compilerInfo()` + Allows for custom compiler flags used in the runtime version checking logic. + +- `appendToBuffer(source, location, explicit)` + Allows for code buffer emitting code. Defaults behavior is string concatenation. + + - `source` is the source code whose result is to be appending + - `location` is the location of the source in the source map. + - `explicit` is a flag signaling that the emit operation must occur, vs. the lazy evaled options otherwise. + +- `initializeBuffer()` + Allows for buffers other than the default string buffer to be used. Generally needs to be paired with a custom `appendToBuffer` implementation. + +```javascript +function MyCompiler() { + Handlebars.JavaScriptCompiler.apply(this, arguments); +} +MyCompiler.prototype = Object.create(Handlebars.JavaScriptCompiler); + +MyCompiler.nameLookup = function(parent, name, type) { + if (type === 'partial') { + return 'MyPartialList[' + JSON.stringify(name) ']'; + } else { + return Handlebars.JavaScriptCompiler.prototype.nameLookup.call(this, parent, name, type); + } +}; + +var env = Handlebars.create(); +env.JavaScriptCompiler = MyCompiler; +env.compile('my template'); +``` diff --git a/hm_sunwell/node_modules/handlebars/docs/decorators-api.md b/hm_sunwell/node_modules/handlebars/docs/decorators-api.md new file mode 100644 index 0000000..566c7eb --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/docs/decorators-api.md @@ -0,0 +1,19 @@ +# Decorators + +Decorators allow for blocks to be annotated with metadata or wrapped in functionality prior to execution of the block. This may be used to communicate with the containing helper or to setup a particular state in the system prior to running the block. + +Decorators are registered through similar methods as helpers, `registerDecorators` and `unregisterDecorators`. These can then be referenced via the friendly name in the template using the `{{* decorator}}` and `{{#* decorator}}{/decorator}}` syntaxes. These syntaxes are derivatives of the normal mustache syntax and as such have all of the same argument and whitespace behaviors. + +Decorators are executed when the block program is instantiated and are passed `(program, props, container, context, data, blockParams, depths)`. + +- `program`: The block to wrap +- `props`: Object used to set metadata on the final function. Any values set on this object will be set on the function, regardless of if the original function is replaced or not. Metadata should be applied using this object as values applied to `program` may be masked by subsequent decorators that may wrap `program`. +- `container`: The current runtime container +- `context`: The current context. Since the decorator is run before the block that contains it, this is the parent context. +- `data`: The current `@data` values +- `blockParams`: The current block parameters stack +- `depths`: The current context stack + +Decorators may set values on `props` or return a modified function that wraps `program` in particular behaviors. If the decorator returns nothing, then `program` is left unaltered. + +The [inline partial](https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/decorators/inline.js) implementation provides an example of decorators being used for both metadata and wrapping behaviors. diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars.js b/hm_sunwell/node_modules/handlebars/lib/handlebars.js new file mode 100644 index 0000000..f114959 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars.js @@ -0,0 +1,41 @@ +import runtime from './handlebars.runtime'; + +// Compiler imports +import AST from './handlebars/compiler/ast'; +import { parser as Parser, parse } from './handlebars/compiler/base'; +import { Compiler, compile, precompile } from './handlebars/compiler/compiler'; +import JavaScriptCompiler from './handlebars/compiler/javascript-compiler'; +import Visitor from './handlebars/compiler/visitor'; + +import noConflict from './handlebars/no-conflict'; + +let _create = runtime.create; +function create() { + let hb = _create(); + + hb.compile = function(input, options) { + return compile(input, options, hb); + }; + hb.precompile = function(input, options) { + return precompile(input, options, hb); + }; + + hb.AST = AST; + hb.Compiler = Compiler; + hb.JavaScriptCompiler = JavaScriptCompiler; + hb.Parser = Parser; + hb.parse = parse; + + return hb; +} + +let inst = create(); +inst.create = create; + +noConflict(inst); + +inst.Visitor = Visitor; + +inst['default'] = inst; + +export default inst; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars.runtime.js b/hm_sunwell/node_modules/handlebars/lib/handlebars.runtime.js new file mode 100644 index 0000000..3d05b54 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars.runtime.js @@ -0,0 +1,37 @@ +import * as base from './handlebars/base'; + +// Each of these augment the Handlebars object. No need to setup here. +// (This is done to easily share code between commonjs and browse envs) +import SafeString from './handlebars/safe-string'; +import Exception from './handlebars/exception'; +import * as Utils from './handlebars/utils'; +import * as runtime from './handlebars/runtime'; + +import noConflict from './handlebars/no-conflict'; + +// For compatibility and usage outside of module systems, make the Handlebars object a namespace +function create() { + let hb = new base.HandlebarsEnvironment(); + + Utils.extend(hb, base); + hb.SafeString = SafeString; + hb.Exception = Exception; + hb.Utils = Utils; + hb.escapeExpression = Utils.escapeExpression; + + hb.VM = runtime; + hb.template = function(spec) { + return runtime.template(spec, hb); + }; + + return hb; +} + +let inst = create(); +inst.create = create; + +noConflict(inst); + +inst['default'] = inst; + +export default inst; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/base.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/base.js new file mode 100644 index 0000000..155e7ca --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/base.js @@ -0,0 +1,78 @@ +import {createFrame, extend, toString} from './utils'; +import Exception from './exception'; +import {registerDefaultHelpers} from './helpers'; +import {registerDefaultDecorators} from './decorators'; +import logger from './logger'; + +export const VERSION = '4.0.6'; +export const COMPILER_REVISION = 7; + +export const REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '== 1.x.x', + 5: '== 2.0.0-alpha.x', + 6: '>= 2.0.0-beta.1', + 7: '>= 4.0.0' +}; + +const objectType = '[object Object]'; + +export function HandlebarsEnvironment(helpers, partials, decorators) { + this.helpers = helpers || {}; + this.partials = partials || {}; + this.decorators = decorators || {}; + + registerDefaultHelpers(this); + registerDefaultDecorators(this); +} + +HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: logger, + log: logger.log, + + registerHelper: function(name, fn) { + if (toString.call(name) === objectType) { + if (fn) { throw new Exception('Arg not supported with multiple helpers'); } + extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function(name) { + delete this.helpers[name]; + }, + + registerPartial: function(name, partial) { + if (toString.call(name) === objectType) { + extend(this.partials, name); + } else { + if (typeof partial === 'undefined') { + throw new Exception(`Attempting to register a partial called "${name}" as undefined`); + } + this.partials[name] = partial; + } + }, + unregisterPartial: function(name) { + delete this.partials[name]; + }, + + registerDecorator: function(name, fn) { + if (toString.call(name) === objectType) { + if (fn) { throw new Exception('Arg not supported with multiple decorators'); } + extend(this.decorators, name); + } else { + this.decorators[name] = fn; + } + }, + unregisterDecorator: function(name) { + delete this.decorators[name]; + } +}; + +export let log = logger.log; + +export {createFrame, logger}; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/ast.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/ast.js new file mode 100644 index 0000000..1699569 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/ast.js @@ -0,0 +1,28 @@ +let AST = { + // Public API used to evaluate derived attributes regarding AST nodes + helpers: { + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + helperExpression: function(node) { + return (node.type === 'SubExpression') + || ((node.type === 'MustacheStatement' || node.type === 'BlockStatement') + && !!((node.params && node.params.length) || node.hash)); + }, + + scopedId: function(path) { + return (/^\.|this\b/).test(path.original); + }, + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + simpleId: function(path) { + return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; + } + } +}; + + +// Must be exported as an object rather than the root of the module as the jison lexer +// must modify the object to operate properly. +export default AST; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/base.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/base.js new file mode 100644 index 0000000..c6871d3 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/base.js @@ -0,0 +1,24 @@ +import parser from './parser'; +import WhitespaceControl from './whitespace-control'; +import * as Helpers from './helpers'; +import { extend } from '../utils'; + +export { parser }; + +let yy = {}; +extend(yy, Helpers); + +export function parse(input, options) { + // Just return if an already-compiled AST was passed in. + if (input.type === 'Program') { return input; } + + parser.yy = yy; + + // Altering the shared object here, but this is ok as parser is a sync operation + yy.locInfo = function(locInfo) { + return new yy.SourceLocation(options && options.srcName, locInfo); + }; + + let strip = new WhitespaceControl(options); + return strip.accept(parser.parse(input)); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/code-gen.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/code-gen.js new file mode 100644 index 0000000..5ec052f --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/code-gen.js @@ -0,0 +1,168 @@ +/* global define */ +import {isArray} from '../utils'; + +let SourceNode; + +try { + /* istanbul ignore next */ + if (typeof define !== 'function' || !define.amd) { + // We don't support this in AMD environments. For these environments, we asusme that + // they are running on the browser and thus have no need for the source-map library. + let SourceMap = require('source-map'); + SourceNode = SourceMap.SourceNode; + } +} catch (err) { + /* NOP */ +} + +/* istanbul ignore if: tested but not covered in istanbul due to dist build */ +if (!SourceNode) { + SourceNode = function(line, column, srcFile, chunks) { + this.src = ''; + if (chunks) { + this.add(chunks); + } + }; + /* istanbul ignore next */ + SourceNode.prototype = { + add: function(chunks) { + if (isArray(chunks)) { + chunks = chunks.join(''); + } + this.src += chunks; + }, + prepend: function(chunks) { + if (isArray(chunks)) { + chunks = chunks.join(''); + } + this.src = chunks + this.src; + }, + toStringWithSourceMap: function() { + return {code: this.toString()}; + }, + toString: function() { + return this.src; + } + }; +} + + +function castChunk(chunk, codeGen, loc) { + if (isArray(chunk)) { + let ret = []; + + for (let i = 0, len = chunk.length; i < len; i++) { + ret.push(codeGen.wrap(chunk[i], loc)); + } + return ret; + } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { + // Handle primitives that the SourceNode will throw up on + return chunk + ''; + } + return chunk; +} + + +function CodeGen(srcFile) { + this.srcFile = srcFile; + this.source = []; +} + +CodeGen.prototype = { + isEmpty() { + return !this.source.length; + }, + prepend: function(source, loc) { + this.source.unshift(this.wrap(source, loc)); + }, + push: function(source, loc) { + this.source.push(this.wrap(source, loc)); + }, + + merge: function() { + let source = this.empty(); + this.each(function(line) { + source.add([' ', line, '\n']); + }); + return source; + }, + + each: function(iter) { + for (let i = 0, len = this.source.length; i < len; i++) { + iter(this.source[i]); + } + }, + + empty: function() { + let loc = this.currentLocation || {start: {}}; + return new SourceNode(loc.start.line, loc.start.column, this.srcFile); + }, + wrap: function(chunk, loc = this.currentLocation || {start: {}}) { + if (chunk instanceof SourceNode) { + return chunk; + } + + chunk = castChunk(chunk, this, loc); + + return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); + }, + + functionCall: function(fn, type, params) { + params = this.generateList(params); + return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); + }, + + quotedString: function(str) { + return '"' + (str + '') + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + objectLiteral: function(obj) { + let pairs = []; + + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + let value = castChunk(obj[key], this); + if (value !== 'undefined') { + pairs.push([this.quotedString(key), ':', value]); + } + } + } + + let ret = this.generateList(pairs); + ret.prepend('{'); + ret.add('}'); + return ret; + }, + + + generateList: function(entries) { + let ret = this.empty(); + + for (let i = 0, len = entries.length; i < len; i++) { + if (i) { + ret.add(','); + } + + ret.add(castChunk(entries[i], this)); + } + + return ret; + }, + + generateArray: function(entries) { + let ret = this.generateList(entries); + ret.prepend('['); + ret.add(']'); + + return ret; + } +}; + +export default CodeGen; + diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/compiler.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/compiler.js new file mode 100644 index 0000000..987d0d4 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/compiler.js @@ -0,0 +1,558 @@ +/* eslint-disable new-cap */ + +import Exception from '../exception'; +import {isArray, indexOf} from '../utils'; +import AST from './ast'; + +const slice = [].slice; + +export function Compiler() {} + +// the foundHelper register will disambiguate helper lookup from finding a +// function in a context. This is necessary for mustache compatibility, which +// requires that context functions in blocks are evaluated by blockHelperMissing, +// and then proceed as if the resulting value was provided to blockHelperMissing. + +Compiler.prototype = { + compiler: Compiler, + + equals: function(other) { + let len = this.opcodes.length; + if (other.opcodes.length !== len) { + return false; + } + + for (let i = 0; i < len; i++) { + let opcode = this.opcodes[i], + otherOpcode = other.opcodes[i]; + if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { + return false; + } + } + + // We know that length is the same between the two arrays because they are directly tied + // to the opcode behavior above. + len = this.children.length; + for (let i = 0; i < len; i++) { + if (!this.children[i].equals(other.children[i])) { + return false; + } + } + + return true; + }, + + guid: 0, + + compile: function(program, options) { + this.sourceNode = []; + this.opcodes = []; + this.children = []; + this.options = options; + this.stringParams = options.stringParams; + this.trackIds = options.trackIds; + + options.blockParams = options.blockParams || []; + + // These changes will propagate to the other compiler components + let knownHelpers = options.knownHelpers; + options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true, + 'lookup': true + }; + if (knownHelpers) { + for (let name in knownHelpers) { + /* istanbul ignore else */ + if (name in knownHelpers) { + options.knownHelpers[name] = knownHelpers[name]; + } + } + } + + return this.accept(program); + }, + + compileProgram: function(program) { + let childCompiler = new this.compiler(), // eslint-disable-line new-cap + result = childCompiler.compile(program, this.options), + guid = this.guid++; + + this.usePartial = this.usePartial || result.usePartial; + + this.children[guid] = result; + this.useDepths = this.useDepths || result.useDepths; + + return guid; + }, + + accept: function(node) { + /* istanbul ignore next: Sanity code */ + if (!this[node.type]) { + throw new Exception('Unknown type: ' + node.type, node); + } + + this.sourceNode.unshift(node); + let ret = this[node.type](node); + this.sourceNode.shift(); + return ret; + }, + + Program: function(program) { + this.options.blockParams.unshift(program.blockParams); + + let body = program.body, + bodyLength = body.length; + for (let i = 0; i < bodyLength; i++) { + this.accept(body[i]); + } + + this.options.blockParams.shift(); + + this.isSimple = bodyLength === 1; + this.blockParams = program.blockParams ? program.blockParams.length : 0; + + return this; + }, + + BlockStatement: function(block) { + transformLiteralToPath(block); + + let program = block.program, + inverse = block.inverse; + + program = program && this.compileProgram(program); + inverse = inverse && this.compileProgram(inverse); + + let type = this.classifySexpr(block); + + if (type === 'helper') { + this.helperSexpr(block, program, inverse); + } else if (type === 'simple') { + this.simpleSexpr(block); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('blockValue', block.path.original); + } else { + this.ambiguousSexpr(block, program, inverse); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('emptyHash'); + this.opcode('ambiguousBlockValue'); + } + + this.opcode('append'); + }, + + DecoratorBlock(decorator) { + let program = decorator.program && this.compileProgram(decorator.program); + let params = this.setupFullMustacheParams(decorator, program, undefined), + path = decorator.path; + + this.useDecorators = true; + this.opcode('registerDecorator', params.length, path.original); + }, + + PartialStatement: function(partial) { + this.usePartial = true; + + let program = partial.program; + if (program) { + program = this.compileProgram(partial.program); + } + + let params = partial.params; + if (params.length > 1) { + throw new Exception('Unsupported number of partial arguments: ' + params.length, partial); + } else if (!params.length) { + if (this.options.explicitPartialContext) { + this.opcode('pushLiteral', 'undefined'); + } else { + params.push({type: 'PathExpression', parts: [], depth: 0}); + } + } + + let partialName = partial.name.original, + isDynamic = partial.name.type === 'SubExpression'; + if (isDynamic) { + this.accept(partial.name); + } + + this.setupFullMustacheParams(partial, program, undefined, true); + + let indent = partial.indent || ''; + if (this.options.preventIndent && indent) { + this.opcode('appendContent', indent); + indent = ''; + } + + this.opcode('invokePartial', isDynamic, partialName, indent); + this.opcode('append'); + }, + PartialBlockStatement: function(partialBlock) { + this.PartialStatement(partialBlock); + }, + + MustacheStatement: function(mustache) { + this.SubExpression(mustache); + + if (mustache.escaped && !this.options.noEscape) { + this.opcode('appendEscaped'); + } else { + this.opcode('append'); + } + }, + Decorator(decorator) { + this.DecoratorBlock(decorator); + }, + + + ContentStatement: function(content) { + if (content.value) { + this.opcode('appendContent', content.value); + } + }, + + CommentStatement: function() {}, + + SubExpression: function(sexpr) { + transformLiteralToPath(sexpr); + let type = this.classifySexpr(sexpr); + + if (type === 'simple') { + this.simpleSexpr(sexpr); + } else if (type === 'helper') { + this.helperSexpr(sexpr); + } else { + this.ambiguousSexpr(sexpr); + } + }, + ambiguousSexpr: function(sexpr, program, inverse) { + let path = sexpr.path, + name = path.parts[0], + isBlock = program != null || inverse != null; + + this.opcode('getContext', path.depth); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + path.strict = true; + this.accept(path); + + this.opcode('invokeAmbiguous', name, isBlock); + }, + + simpleSexpr: function(sexpr) { + let path = sexpr.path; + path.strict = true; + this.accept(path); + this.opcode('resolvePossibleLambda'); + }, + + helperSexpr: function(sexpr, program, inverse) { + let params = this.setupFullMustacheParams(sexpr, program, inverse), + path = sexpr.path, + name = path.parts[0]; + + if (this.options.knownHelpers[name]) { + this.opcode('invokeKnownHelper', params.length, name); + } else if (this.options.knownHelpersOnly) { + throw new Exception('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); + } else { + path.strict = true; + path.falsy = true; + + this.accept(path); + this.opcode('invokeHelper', params.length, path.original, AST.helpers.simpleId(path)); + } + }, + + PathExpression: function(path) { + this.addDepth(path.depth); + this.opcode('getContext', path.depth); + + let name = path.parts[0], + scoped = AST.helpers.scopedId(path), + blockParamId = !path.depth && !scoped && this.blockParamIndex(name); + + if (blockParamId) { + this.opcode('lookupBlockParam', blockParamId, path.parts); + } else if (!name) { + // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` + this.opcode('pushContext'); + } else if (path.data) { + this.options.data = true; + this.opcode('lookupData', path.depth, path.parts, path.strict); + } else { + this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); + } + }, + + StringLiteral: function(string) { + this.opcode('pushString', string.value); + }, + + NumberLiteral: function(number) { + this.opcode('pushLiteral', number.value); + }, + + BooleanLiteral: function(bool) { + this.opcode('pushLiteral', bool.value); + }, + + UndefinedLiteral: function() { + this.opcode('pushLiteral', 'undefined'); + }, + + NullLiteral: function() { + this.opcode('pushLiteral', 'null'); + }, + + Hash: function(hash) { + let pairs = hash.pairs, + i = 0, + l = pairs.length; + + this.opcode('pushHash'); + + for (; i < l; i++) { + this.pushParam(pairs[i].value); + } + while (i--) { + this.opcode('assignToHash', pairs[i].key); + } + this.opcode('popHash'); + }, + + // HELPERS + opcode: function(name) { + this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc }); + }, + + addDepth: function(depth) { + if (!depth) { + return; + } + + this.useDepths = true; + }, + + classifySexpr: function(sexpr) { + let isSimple = AST.helpers.simpleId(sexpr.path); + + let isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + let isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + let isEligible = !isBlockParam && (isHelper || isSimple); + + // if ambiguous, we can possibly resolve the ambiguity now + // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. + if (isEligible && !isHelper) { + let name = sexpr.path.parts[0], + options = this.options; + + if (options.knownHelpers[name]) { + isHelper = true; + } else if (options.knownHelpersOnly) { + isEligible = false; + } + } + + if (isHelper) { + return 'helper'; + } else if (isEligible) { + return 'ambiguous'; + } else { + return 'simple'; + } + }, + + pushParams: function(params) { + for (let i = 0, l = params.length; i < l; i++) { + this.pushParam(params[i]); + } + }, + + pushParam: function(val) { + let value = val.value != null ? val.value : val.original || ''; + + if (this.stringParams) { + if (value.replace) { + value = value + .replace(/^(\.?\.\/)*/g, '') + .replace(/\//g, '.'); + } + + if (val.depth) { + this.addDepth(val.depth); + } + this.opcode('getContext', val.depth || 0); + this.opcode('pushStringParam', value, val.type); + + if (val.type === 'SubExpression') { + // SubExpressions get evaluated and passed in + // in string params mode. + this.accept(val); + } + } else { + if (this.trackIds) { + let blockParamIndex; + if (val.parts && !AST.helpers.scopedId(val) && !val.depth) { + blockParamIndex = this.blockParamIndex(val.parts[0]); + } + if (blockParamIndex) { + let blockParamChild = val.parts.slice(1).join('.'); + this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); + } else { + value = val.original || value; + if (value.replace) { + value = value + .replace(/^this(?:\.|$)/, '') + .replace(/^\.\//, '') + .replace(/^\.$/, ''); + } + + this.opcode('pushId', val.type, value); + } + } + this.accept(val); + } + }, + + setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) { + let params = sexpr.params; + this.pushParams(params); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + if (sexpr.hash) { + this.accept(sexpr.hash); + } else { + this.opcode('emptyHash', omitEmpty); + } + + return params; + }, + + blockParamIndex: function(name) { + for (let depth = 0, len = this.options.blockParams.length; depth < len; depth++) { + let blockParams = this.options.blockParams[depth], + param = blockParams && indexOf(blockParams, name); + if (blockParams && param >= 0) { + return [depth, param]; + } + } + } +}; + +export function precompile(input, options, env) { + if (input == null || (typeof input !== 'string' && input.type !== 'Program')) { + throw new Exception('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); + } + + options = options || {}; + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + let ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options); + return new env.JavaScriptCompiler().compile(environment, options); +} + +export function compile(input, options = {}, env) { + if (input == null || (typeof input !== 'string' && input.type !== 'Program')) { + throw new Exception('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); + } + + if (!('data' in options)) { + options.data = true; + } + if (options.compat) { + options.useDepths = true; + } + + let compiled; + + function compileInput() { + let ast = env.parse(input, options), + environment = new env.Compiler().compile(ast, options), + templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); + return env.template(templateSpec); + } + + // Template is only compiled on first use and cached after that point. + function ret(context, execOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled.call(this, context, execOptions); + } + ret._setup = function(setupOptions) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._setup(setupOptions); + }; + ret._child = function(i, data, blockParams, depths) { + if (!compiled) { + compiled = compileInput(); + } + return compiled._child(i, data, blockParams, depths); + }; + return ret; +} + +function argEquals(a, b) { + if (a === b) { + return true; + } + + if (isArray(a) && isArray(b) && a.length === b.length) { + for (let i = 0; i < a.length; i++) { + if (!argEquals(a[i], b[i])) { + return false; + } + } + return true; + } +} + +function transformLiteralToPath(sexpr) { + if (!sexpr.path.parts) { + let literal = sexpr.path; + // Casting to string here to make false and 0 literal values play nicely with the rest + // of the system. + sexpr.path = { + type: 'PathExpression', + data: false, + depth: 0, + parts: [literal.original + ''], + original: literal.original + '', + loc: literal.loc + }; + } +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/helpers.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/helpers.js new file mode 100644 index 0000000..e09a08d --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/helpers.js @@ -0,0 +1,212 @@ +import Exception from '../exception'; + +function validateClose(open, close) { + close = close.path ? close.path.original : close; + + if (open.path.original !== close) { + let errorNode = {loc: open.path.loc}; + + throw new Exception(open.path.original + " doesn't match " + close, errorNode); + } +} + +export function SourceLocation(source, locInfo) { + this.source = source; + this.start = { + line: locInfo.first_line, + column: locInfo.first_column + }; + this.end = { + line: locInfo.last_line, + column: locInfo.last_column + }; +} + +export function id(token) { + if (/^\[.*\]$/.test(token)) { + return token.substr(1, token.length - 2); + } else { + return token; + } +} + +export function stripFlags(open, close) { + return { + open: open.charAt(2) === '~', + close: close.charAt(close.length - 3) === '~' + }; +} + +export function stripComment(comment) { + return comment.replace(/^\{\{~?\!-?-?/, '') + .replace(/-?-?~?\}\}$/, ''); +} + +export function preparePath(data, parts, loc) { + loc = this.locInfo(loc); + + let original = data ? '@' : '', + dig = [], + depth = 0, + depthString = ''; + + for (let i = 0, l = parts.length; i < l; i++) { + let part = parts[i].part, + // If we have [] syntax then we do not treat path references as operators, + // i.e. foo.[this] resolves to approximately context.foo['this'] + isLiteral = parts[i].original !== part; + original += (parts[i].separator || '') + part; + + if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { + if (dig.length > 0) { + throw new Exception('Invalid path: ' + original, {loc}); + } else if (part === '..') { + depth++; + depthString += '../'; + } + } else { + dig.push(part); + } + } + + return { + type: 'PathExpression', + data, + depth, + parts: dig, + original, + loc + }; +} + +export function prepareMustache(path, params, hash, open, strip, locInfo) { + // Must use charAt to support IE pre-10 + let escapeFlag = open.charAt(3) || open.charAt(2), + escaped = escapeFlag !== '{' && escapeFlag !== '&'; + + let decorator = (/\*/.test(open)); + return { + type: decorator ? 'Decorator' : 'MustacheStatement', + path, + params, + hash, + escaped, + strip, + loc: this.locInfo(locInfo) + }; +} + +export function prepareRawBlock(openRawBlock, contents, close, locInfo) { + validateClose(openRawBlock, close); + + locInfo = this.locInfo(locInfo); + let program = { + type: 'Program', + body: contents, + strip: {}, + loc: locInfo + }; + + return { + type: 'BlockStatement', + path: openRawBlock.path, + params: openRawBlock.params, + hash: openRawBlock.hash, + program, + openStrip: {}, + inverseStrip: {}, + closeStrip: {}, + loc: locInfo + }; +} + +export function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { + if (close && close.path) { + validateClose(openBlock, close); + } + + let decorator = (/\*/.test(openBlock.open)); + + program.blockParams = openBlock.blockParams; + + let inverse, + inverseStrip; + + if (inverseAndProgram) { + if (decorator) { + throw new Exception('Unexpected inverse block on decorator', inverseAndProgram); + } + + if (inverseAndProgram.chain) { + inverseAndProgram.program.body[0].closeStrip = close.strip; + } + + inverseStrip = inverseAndProgram.strip; + inverse = inverseAndProgram.program; + } + + if (inverted) { + inverted = inverse; + inverse = program; + program = inverted; + } + + return { + type: decorator ? 'DecoratorBlock' : 'BlockStatement', + path: openBlock.path, + params: openBlock.params, + hash: openBlock.hash, + program, + inverse, + openStrip: openBlock.strip, + inverseStrip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; +} + +export function prepareProgram(statements, loc) { + if (!loc && statements.length) { + const firstLoc = statements[0].loc, + lastLoc = statements[statements.length - 1].loc; + + /* istanbul ignore else */ + if (firstLoc && lastLoc) { + loc = { + source: firstLoc.source, + start: { + line: firstLoc.start.line, + column: firstLoc.start.column + }, + end: { + line: lastLoc.end.line, + column: lastLoc.end.column + } + }; + } + } + + return { + type: 'Program', + body: statements, + strip: {}, + loc: loc + }; +} + + +export function preparePartialBlock(open, program, close, locInfo) { + validateClose(open, close); + + return { + type: 'PartialBlockStatement', + name: open.path, + params: open.params, + hash: open.hash, + program, + openStrip: open.strip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; +} + diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/javascript-compiler.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/javascript-compiler.js new file mode 100644 index 0000000..ec89117 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/javascript-compiler.js @@ -0,0 +1,1137 @@ +import { COMPILER_REVISION, REVISION_CHANGES } from '../base'; +import Exception from '../exception'; +import {isArray} from '../utils'; +import CodeGen from './code-gen'; + +function Literal(value) { + this.value = value; +} + +function JavaScriptCompiler() {} + +JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function(parent, name/* , type*/) { + if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + return [parent, '.', name]; + } else { + return [parent, '[', JSON.stringify(name), ']']; + } + }, + depthedLookup: function(name) { + return [this.aliasable('container.lookup'), '(depths, "', name, '")']; + }, + + compilerInfo: function() { + const revision = COMPILER_REVISION, + versions = REVISION_CHANGES[revision]; + return [revision, versions]; + }, + + appendToBuffer: function(source, location, explicit) { + // Force a source as this simplifies the merge logic. + if (!isArray(source)) { + source = [source]; + } + source = this.source.wrap(source, location); + + if (this.environment.isSimple) { + return ['return ', source, ';']; + } else if (explicit) { + // This is a case where the buffer operation occurs as a child of another + // construct, generally braces. We have to explicitly output these buffer + // operations to ensure that the emitted code goes in the correct location. + return ['buffer += ', source, ';']; + } else { + source.appendToBuffer = true; + return source; + } + }, + + initializeBuffer: function() { + return this.quotedString(''); + }, + // END PUBLIC API + + compile: function(environment, options, context, asObject) { + this.environment = environment; + this.options = options; + this.stringParams = this.options.stringParams; + this.trackIds = this.options.trackIds; + this.precompile = !asObject; + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + decorators: [], + programs: [], + environments: [] + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.aliases = {}; + this.registers = { list: [] }; + this.hashes = []; + this.compileStack = []; + this.inlineStack = []; + this.blockParams = []; + + this.compileChildren(environment, options); + + this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; + this.useBlockParams = this.useBlockParams || environment.useBlockParams; + + let opcodes = environment.opcodes, + opcode, + firstLoc, + i, + l; + + for (i = 0, l = opcodes.length; i < l; i++) { + opcode = opcodes[i]; + + this.source.currentLocation = opcode.loc; + firstLoc = firstLoc || opcode.loc; + this[opcode.opcode].apply(this, opcode.args); + } + + // Flush any trailing content that might be pending. + this.source.currentLocation = firstLoc; + this.pushSource(''); + + /* istanbul ignore next */ + if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { + throw new Exception('Compile completed with content left on stack'); + } + + if (!this.decorators.isEmpty()) { + this.useDecorators = true; + + this.decorators.prepend('var decorators = container.decorators;\n'); + this.decorators.push('return fn;'); + + if (asObject) { + this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); + } else { + this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); + this.decorators.push('}\n'); + this.decorators = this.decorators.merge(); + } + } else { + this.decorators = undefined; + } + + let fn = this.createFunctionContext(asObject); + if (!this.isChild) { + let ret = { + compiler: this.compilerInfo(), + main: fn + }; + + if (this.decorators) { + ret.main_d = this.decorators; // eslint-disable-line camelcase + ret.useDecorators = true; + } + + let {programs, decorators} = this.context; + for (i = 0, l = programs.length; i < l; i++) { + if (programs[i]) { + ret[i] = programs[i]; + if (decorators[i]) { + ret[i + '_d'] = decorators[i]; + ret.useDecorators = true; + } + } + } + + if (this.environment.usePartial) { + ret.usePartial = true; + } + if (this.options.data) { + ret.useData = true; + } + if (this.useDepths) { + ret.useDepths = true; + } + if (this.useBlockParams) { + ret.useBlockParams = true; + } + if (this.options.compat) { + ret.compat = true; + } + + if (!asObject) { + ret.compiler = JSON.stringify(ret.compiler); + + this.source.currentLocation = {start: {line: 1, column: 0}}; + ret = this.objectLiteral(ret); + + if (options.srcName) { + ret = ret.toStringWithSourceMap({file: options.destName}); + ret.map = ret.map && ret.map.toString(); + } else { + ret = ret.toString(); + } + } else { + ret.compilerOptions = this.options; + } + + return ret; + } else { + return fn; + } + }, + + preamble: function() { + // track the last context pushed into place to allow skipping the + // getContext opcode when it would be a noop + this.lastContext = 0; + this.source = new CodeGen(this.options.srcName); + this.decorators = new CodeGen(this.options.srcName); + }, + + createFunctionContext: function(asObject) { + let varDeclarations = ''; + + let locals = this.stackVars.concat(this.registers.list); + if (locals.length > 0) { + varDeclarations += ', ' + locals.join(', '); + } + + // Generate minimizer alias mappings + // + // When using true SourceNodes, this will update all references to the given alias + // as the source nodes are reused in situ. For the non-source node compilation mode, + // aliases will not be used, but this case is already being run on the client and + // we aren't concern about minimizing the template size. + let aliasCount = 0; + for (let alias in this.aliases) { // eslint-disable-line guard-for-in + let node = this.aliases[alias]; + + if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { + varDeclarations += ', alias' + (++aliasCount) + '=' + alias; + node.children[0] = 'alias' + aliasCount; + } + } + + let params = ['container', 'depth0', 'helpers', 'partials', 'data']; + + if (this.useBlockParams || this.useDepths) { + params.push('blockParams'); + } + if (this.useDepths) { + params.push('depths'); + } + + // Perform a second pass over the output to merge content when possible + let source = this.mergeSource(varDeclarations); + + if (asObject) { + params.push(source); + + return Function.apply(this, params); + } else { + return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); + } + }, + mergeSource: function(varDeclarations) { + let isSimple = this.environment.isSimple, + appendOnly = !this.forceBuffer, + appendFirst, + + sourceSeen, + bufferStart, + bufferEnd; + this.source.each((line) => { + if (line.appendToBuffer) { + if (bufferStart) { + line.prepend(' + '); + } else { + bufferStart = line; + } + bufferEnd = line; + } else { + if (bufferStart) { + if (!sourceSeen) { + appendFirst = true; + } else { + bufferStart.prepend('buffer += '); + } + bufferEnd.add(';'); + bufferStart = bufferEnd = undefined; + } + + sourceSeen = true; + if (!isSimple) { + appendOnly = false; + } + } + }); + + + if (appendOnly) { + if (bufferStart) { + bufferStart.prepend('return '); + bufferEnd.add(';'); + } else if (!sourceSeen) { + this.source.push('return "";'); + } + } else { + varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); + + if (bufferStart) { + bufferStart.prepend('return buffer + '); + bufferEnd.add(';'); + } else { + this.source.push('return buffer;'); + } + } + + if (varDeclarations) { + this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); + } + + return this.source.merge(); + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function(name) { + let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs(name, 0, params); + + let blockName = this.popStack(); + params.splice(1, 0, blockName); + + this.push(this.source.functionCall(blockHelperMissing, 'call', params)); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function() { + // We're being a bit cheeky and reusing the options value from the prior exec + let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), + params = [this.contextName(0)]; + this.setupHelperArgs('', 0, params, true); + + this.flushInline(); + + let current = this.topStack(); + params.splice(1, 0, current); + + this.pushSource([ + 'if (!', this.lastHelper, ') { ', + current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), + '}']); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function(content) { + if (this.pendingContent) { + content = this.pendingContent + content; + } else { + this.pendingLocation = this.source.currentLocation; + } + + this.pendingContent = content; + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function() { + if (this.isInline()) { + this.replaceStack((current) => [' != null ? ', current, ' : ""']); + + this.pushSource(this.appendToBuffer(this.popStack())); + } else { + let local = this.popStack(); + this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); + if (this.environment.isSimple) { + this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); + } + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function() { + this.pushSource(this.appendToBuffer( + [this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function(depth) { + this.lastContext = depth; + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function() { + this.pushStackLiteral(this.contextName(this.lastContext)); + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function(parts, falsy, strict, scoped) { + let i = 0; + + if (!scoped && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.push(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); + } + + this.resolvePath('context', parts, i, falsy, strict); + }, + + // [lookupBlockParam] + // + // On stack, before: ... + // On stack, after: blockParam[name], ... + // + // Looks up the value of `parts` on the given block param and pushes + // it onto the stack. + lookupBlockParam: function(blockParamId, parts) { + this.useBlockParams = true; + + this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); + this.resolvePath('context', parts, 1); + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data, ... + // + // Push the data lookup operator + lookupData: function(depth, parts, strict) { + if (!depth) { + this.pushStackLiteral('data'); + } else { + this.pushStackLiteral('container.data(data, ' + depth + ')'); + } + + this.resolvePath('data', parts, 0, true, strict); + }, + + resolvePath: function(type, parts, i, falsy, strict) { + if (this.options.strict || this.options.assumeObjects) { + this.push(strictLookup(this.options.strict && strict, this, parts, type)); + return; + } + + let len = parts.length; + for (; i < len; i++) { + /* eslint-disable no-loop-func */ + this.replaceStack((current) => { + let lookup = this.nameLookup(current, parts[i], type); + // We want to ensure that zero and false are handled properly if the context (falsy flag) + // needs to have the special handling for these values. + if (!falsy) { + return [' != null ? ', lookup, ' : ', current]; + } else { + // Otherwise we can use generic falsy handling + return [' && ', lookup]; + } + }); + /* eslint-enable no-loop-func */ + } + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function() { + this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function(string, type) { + this.pushContext(); + this.pushString(type); + + // If it's a subexpression, the string result + // will be pushed after this opcode. + if (type !== 'SubExpression') { + if (typeof string === 'string') { + this.pushString(string); + } else { + this.pushStackLiteral(string); + } + } + }, + + emptyHash: function(omitEmpty) { + if (this.trackIds) { + this.push('{}'); // hashIds + } + if (this.stringParams) { + this.push('{}'); // hashContexts + this.push('{}'); // hashTypes + } + this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); + }, + pushHash: function() { + if (this.hash) { + this.hashes.push(this.hash); + } + this.hash = {values: [], types: [], contexts: [], ids: []}; + }, + popHash: function() { + let hash = this.hash; + this.hash = this.hashes.pop(); + + if (this.trackIds) { + this.push(this.objectLiteral(hash.ids)); + } + if (this.stringParams) { + this.push(this.objectLiteral(hash.contexts)); + this.push(this.objectLiteral(hash.types)); + } + + this.push(this.objectLiteral(hash.values)); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [registerDecorator] + // + // On stack, before: hash, program, params..., ... + // On stack, after: ... + // + // Pops off the decorator's parameters, invokes the decorator, + // and inserts the decorator into the decorators list. + registerDecorator(paramSize, name) { + let foundDecorator = this.nameLookup('decorators', name, 'decorator'), + options = this.setupHelperArgs(name, paramSize); + + this.decorators.push([ + 'fn = ', + this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), + ' || fn;' + ]); + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function(paramSize, name, isSimple) { + let nonHelper = this.popStack(), + helper = this.setupHelper(paramSize, name), + simple = isSimple ? [helper.name, ' || '] : ''; + + let lookup = ['('].concat(simple, nonHelper); + if (!this.options.strict) { + lookup.push(' || ', this.aliasable('helpers.helperMissing')); + } + lookup.push(')'); + + this.push(this.source.functionCall(lookup, 'call', helper.callParams)); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function(paramSize, name) { + let helper = this.setupHelper(paramSize, name); + this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function(name, helperCall) { + this.useRegister('helper'); + + let nonHelper = this.popStack(); + + this.emptyHash(); + let helper = this.setupHelper(0, name, helperCall); + + let helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + + let lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; + if (!this.options.strict) { + lookup[0] = '(helper = '; + lookup.push( + ' != null ? helper : ', + this.aliasable('helpers.helperMissing') + ); + } + + this.push([ + '(', lookup, + (helper.paramsInit ? ['),(', helper.paramsInit] : []), '),', + '(typeof helper === ', this.aliasable('"function"'), ' ? ', + this.source.functionCall('helper', 'call', helper.callParams), ' : helper))' + ]); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function(isDynamic, name, indent) { + let params = [], + options = this.setupParams(name, 1, params); + + if (isDynamic) { + name = this.popStack(); + delete options.name; + } + + if (indent) { + options.indent = JSON.stringify(indent); + } + options.helpers = 'helpers'; + options.partials = 'partials'; + options.decorators = 'container.decorators'; + + if (!isDynamic) { + params.unshift(this.nameLookup('partials', name, 'partial')); + } else { + params.unshift(name); + } + + if (this.options.compat) { + options.depths = 'depths'; + } + options = this.objectLiteral(options); + params.push(options); + + this.push(this.source.functionCall('container.invokePartial', '', params)); + }, + + // [assignToHash] + // + // On stack, before: value, ..., hash, ... + // On stack, after: ..., hash, ... + // + // Pops a value off the stack and assigns it to the current hash + assignToHash: function(key) { + let value = this.popStack(), + context, + type, + id; + + if (this.trackIds) { + id = this.popStack(); + } + if (this.stringParams) { + type = this.popStack(); + context = this.popStack(); + } + + let hash = this.hash; + if (context) { + hash.contexts[key] = context; + } + if (type) { + hash.types[key] = type; + } + if (id) { + hash.ids[key] = id; + } + hash.values[key] = value; + }, + + pushId: function(type, name, child) { + if (type === 'BlockParam') { + this.pushStackLiteral( + 'blockParams[' + name[0] + '].path[' + name[1] + ']' + + (child ? ' + ' + JSON.stringify('.' + child) : '')); + } else if (type === 'PathExpression') { + this.pushString(name); + } else if (type === 'SubExpression') { + this.pushStackLiteral('true'); + } else { + this.pushStackLiteral('null'); + } + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function(environment, options) { + let children = environment.children, child, compiler; + + for (let i = 0, l = children.length; i < l; i++) { + child = children[i]; + compiler = new this.compiler(); // eslint-disable-line new-cap + + let existing = this.matchExistingProgram(child); + + if (existing == null) { + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + let index = this.context.programs.length; + child.index = index; + child.name = 'program' + index; + this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); + this.context.decorators[index] = compiler.decorators; + this.context.environments[index] = child; + + this.useDepths = this.useDepths || compiler.useDepths; + this.useBlockParams = this.useBlockParams || compiler.useBlockParams; + child.useDepths = this.useDepths; + child.useBlockParams = this.useBlockParams; + } else { + child.index = existing.index; + child.name = 'program' + existing.index; + + this.useDepths = this.useDepths || existing.useDepths; + this.useBlockParams = this.useBlockParams || existing.useBlockParams; + } + } + }, + matchExistingProgram: function(child) { + for (let i = 0, len = this.context.environments.length; i < len; i++) { + let environment = this.context.environments[i]; + if (environment && environment.equals(child)) { + return environment; + } + } + }, + + programExpression: function(guid) { + let child = this.environment.children[guid], + programParams = [child.index, 'data', child.blockParams]; + + if (this.useBlockParams || this.useDepths) { + programParams.push('blockParams'); + } + if (this.useDepths) { + programParams.push('depths'); + } + + return 'container.program(' + programParams.join(', ') + ')'; + }, + + useRegister: function(name) { + if (!this.registers[name]) { + this.registers[name] = true; + this.registers.list.push(name); + } + }, + + push: function(expr) { + if (!(expr instanceof Literal)) { + expr = this.source.wrap(expr); + } + + this.inlineStack.push(expr); + return expr; + }, + + pushStackLiteral: function(item) { + this.push(new Literal(item)); + }, + + pushSource: function(source) { + if (this.pendingContent) { + this.source.push( + this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); + this.pendingContent = undefined; + } + + if (source) { + this.source.push(source); + } + }, + + replaceStack: function(callback) { + let prefix = ['('], + stack, + createdStack, + usedLiteral; + + /* istanbul ignore next */ + if (!this.isInline()) { + throw new Exception('replaceStack on non-inline'); + } + + // We want to merge the inline statement into the replacement statement via ',' + let top = this.popStack(true); + + if (top instanceof Literal) { + // Literals do not need to be inlined + stack = [top.value]; + prefix = ['(', stack]; + usedLiteral = true; + } else { + // Get or create the current stack name for use by the inline + createdStack = true; + let name = this.incrStack(); + + prefix = ['((', this.push(name), ' = ', top, ')']; + stack = this.topStack(); + } + + let item = callback.call(this, stack); + + if (!usedLiteral) { + this.popStack(); + } + if (createdStack) { + this.stackSlot--; + } + this.push(prefix.concat(item, ')')); + }, + + incrStack: function() { + this.stackSlot++; + if (this.stackSlot > this.stackVars.length) { this.stackVars.push('stack' + this.stackSlot); } + return this.topStackName(); + }, + topStackName: function() { + return 'stack' + this.stackSlot; + }, + flushInline: function() { + let inlineStack = this.inlineStack; + this.inlineStack = []; + for (let i = 0, len = inlineStack.length; i < len; i++) { + let entry = inlineStack[i]; + /* istanbul ignore if */ + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + let stack = this.incrStack(); + this.pushSource([stack, ' = ', entry, ';']); + this.compileStack.push(stack); + } + } + }, + isInline: function() { + return this.inlineStack.length; + }, + + popStack: function(wrapped) { + let inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + if (!inline) { + /* istanbul ignore next */ + if (!this.stackSlot) { + throw new Exception('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function() { + let stack = (this.isInline() ? this.inlineStack : this.compileStack), + item = stack[stack.length - 1]; + + /* istanbul ignore if */ + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + contextName: function(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + + quotedString: function(str) { + return this.source.quotedString(str); + }, + + objectLiteral: function(obj) { + return this.source.objectLiteral(obj); + }, + + aliasable: function(name) { + let ret = this.aliases[name]; + if (ret) { + ret.referenceCount++; + return ret; + } + + ret = this.aliases[name] = this.source.wrap(name); + ret.aliasable = true; + ret.referenceCount = 1; + + return ret; + }, + + setupHelper: function(paramSize, name, blockHelper) { + let params = [], + paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); + let foundHelper = this.nameLookup('helpers', name, 'helper'), + callContext = this.aliasable(`${this.contextName(0)} != null ? ${this.contextName(0)} : {}`); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: [callContext].concat(params) + }; + }, + + setupParams: function(helper, paramSize, params) { + let options = {}, + contexts = [], + types = [], + ids = [], + objectArgs = !params, + param; + + if (objectArgs) { + params = []; + } + + options.name = this.quotedString(helper); + options.hash = this.popStack(); + + if (this.trackIds) { + options.hashIds = this.popStack(); + } + if (this.stringParams) { + options.hashTypes = this.popStack(); + options.hashContexts = this.popStack(); + } + + let inverse = this.popStack(), + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + options.fn = program || 'container.noop'; + options.inverse = inverse || 'container.noop'; + } + + // The parameters go on to the stack in order (making sure that they are evaluated in order) + // so we need to pop them off the stack in reverse order + let i = paramSize; + while (i--) { + param = this.popStack(); + params[i] = param; + + if (this.trackIds) { + ids[i] = this.popStack(); + } + if (this.stringParams) { + types[i] = this.popStack(); + contexts[i] = this.popStack(); + } + } + + if (objectArgs) { + options.args = this.source.generateArray(params); + } + + if (this.trackIds) { + options.ids = this.source.generateArray(ids); + } + if (this.stringParams) { + options.types = this.source.generateArray(types); + options.contexts = this.source.generateArray(contexts); + } + + if (this.options.data) { + options.data = 'data'; + } + if (this.useBlockParams) { + options.blockParams = 'blockParams'; + } + return options; + }, + + setupHelperArgs: function(helper, paramSize, params, useRegister) { + let options = this.setupParams(helper, paramSize, params); + options = this.objectLiteral(options); + if (useRegister) { + this.useRegister('options'); + params.push('options'); + return ['options=', options]; + } else if (params) { + params.push(options); + return ''; + } else { + return options; + } + } +}; + + +(function() { + const reservedWords = ( + 'break else new var' + + ' case finally return void' + + ' catch for switch while' + + ' continue function this with' + + ' default if throw' + + ' delete in try' + + ' do instanceof typeof' + + ' abstract enum int short' + + ' boolean export interface static' + + ' byte extends long super' + + ' char final native synchronized' + + ' class float package throws' + + ' const goto private transient' + + ' debugger implements protected volatile' + + ' double import public let yield await' + + ' null true false' + ).split(' '); + + const compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for (let i = 0, l = reservedWords.length; i < l; i++) { + compilerWords[reservedWords[i]] = true; + } +}()); + +JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { + return !JavaScriptCompiler.RESERVED_WORDS[name] && (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/).test(name); +}; + +function strictLookup(requireTerminal, compiler, parts, type) { + let stack = compiler.popStack(), + i = 0, + len = parts.length; + if (requireTerminal) { + len--; + } + + for (; i < len; i++) { + stack = compiler.nameLookup(stack, parts[i], type); + } + + if (requireTerminal) { + return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')']; + } else { + return stack; + } +} + +export default JavaScriptCompiler; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/parser.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/parser.js new file mode 100644 index 0000000..04fe6ae --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/parser.js @@ -0,0 +1,623 @@ +/* istanbul ignore next */ +/* Jison generated parser */ +var handlebars = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"root":3,"program":4,"EOF":5,"program_repetition0":6,"statement":7,"mustache":8,"block":9,"rawBlock":10,"partial":11,"partialBlock":12,"content":13,"COMMENT":14,"CONTENT":15,"openRawBlock":16,"rawBlock_repetition_plus0":17,"END_RAW_BLOCK":18,"OPEN_RAW_BLOCK":19,"helperName":20,"openRawBlock_repetition0":21,"openRawBlock_option0":22,"CLOSE_RAW_BLOCK":23,"openBlock":24,"block_option0":25,"closeBlock":26,"openInverse":27,"block_option1":28,"OPEN_BLOCK":29,"openBlock_repetition0":30,"openBlock_option0":31,"openBlock_option1":32,"CLOSE":33,"OPEN_INVERSE":34,"openInverse_repetition0":35,"openInverse_option0":36,"openInverse_option1":37,"openInverseChain":38,"OPEN_INVERSE_CHAIN":39,"openInverseChain_repetition0":40,"openInverseChain_option0":41,"openInverseChain_option1":42,"inverseAndProgram":43,"INVERSE":44,"inverseChain":45,"inverseChain_option0":46,"OPEN_ENDBLOCK":47,"OPEN":48,"mustache_repetition0":49,"mustache_option0":50,"OPEN_UNESCAPED":51,"mustache_repetition1":52,"mustache_option1":53,"CLOSE_UNESCAPED":54,"OPEN_PARTIAL":55,"partialName":56,"partial_repetition0":57,"partial_option0":58,"openPartialBlock":59,"OPEN_PARTIAL_BLOCK":60,"openPartialBlock_repetition0":61,"openPartialBlock_option0":62,"param":63,"sexpr":64,"OPEN_SEXPR":65,"sexpr_repetition0":66,"sexpr_option0":67,"CLOSE_SEXPR":68,"hash":69,"hash_repetition_plus0":70,"hashSegment":71,"ID":72,"EQUALS":73,"blockParams":74,"OPEN_BLOCK_PARAMS":75,"blockParams_repetition_plus0":76,"CLOSE_BLOCK_PARAMS":77,"path":78,"dataName":79,"STRING":80,"NUMBER":81,"BOOLEAN":82,"UNDEFINED":83,"NULL":84,"DATA":85,"pathSegments":86,"SEP":87,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOF",14:"COMMENT",15:"CONTENT",18:"END_RAW_BLOCK",19:"OPEN_RAW_BLOCK",23:"CLOSE_RAW_BLOCK",29:"OPEN_BLOCK",33:"CLOSE",34:"OPEN_INVERSE",39:"OPEN_INVERSE_CHAIN",44:"INVERSE",47:"OPEN_ENDBLOCK",48:"OPEN",51:"OPEN_UNESCAPED",54:"CLOSE_UNESCAPED",55:"OPEN_PARTIAL",60:"OPEN_PARTIAL_BLOCK",65:"OPEN_SEXPR",68:"CLOSE_SEXPR",72:"ID",73:"EQUALS",75:"OPEN_BLOCK_PARAMS",77:"CLOSE_BLOCK_PARAMS",80:"STRING",81:"NUMBER",82:"BOOLEAN",83:"UNDEFINED",84:"NULL",85:"DATA",87:"SEP"}, +productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[13,1],[10,3],[16,5],[9,4],[9,4],[24,6],[27,6],[38,6],[43,2],[45,3],[45,1],[26,3],[8,5],[8,5],[11,5],[12,3],[59,5],[63,1],[63,1],[64,5],[69,1],[71,3],[74,3],[20,1],[20,1],[20,1],[20,1],[20,1],[20,1],[20,1],[56,1],[56,1],[79,2],[78,1],[86,3],[86,1],[6,0],[6,2],[17,1],[17,2],[21,0],[21,2],[22,0],[22,1],[25,0],[25,1],[28,0],[28,1],[30,0],[30,2],[31,0],[31,1],[32,0],[32,1],[35,0],[35,2],[36,0],[36,1],[37,0],[37,1],[40,0],[40,2],[41,0],[41,1],[42,0],[42,1],[46,0],[46,1],[49,0],[49,2],[50,0],[50,1],[52,0],[52,2],[53,0],[53,1],[57,0],[57,2],[58,0],[58,1],[61,0],[61,2],[62,0],[62,1],[66,0],[66,2],[67,0],[67,1],[70,1],[70,2],[76,1],[76,2]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$ +/**/) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1: return $$[$0-1]; +break; +case 2:this.$ = yy.prepareProgram($$[$0]); +break; +case 3:this.$ = $$[$0]; +break; +case 4:this.$ = $$[$0]; +break; +case 5:this.$ = $$[$0]; +break; +case 6:this.$ = $$[$0]; +break; +case 7:this.$ = $$[$0]; +break; +case 8:this.$ = $$[$0]; +break; +case 9: + this.$ = { + type: 'CommentStatement', + value: yy.stripComment($$[$0]), + strip: yy.stripFlags($$[$0], $$[$0]), + loc: yy.locInfo(this._$) + }; + +break; +case 10: + this.$ = { + type: 'ContentStatement', + original: $$[$0], + value: $$[$0], + loc: yy.locInfo(this._$) + }; + +break; +case 11:this.$ = yy.prepareRawBlock($$[$0-2], $$[$0-1], $$[$0], this._$); +break; +case 12:this.$ = { path: $$[$0-3], params: $$[$0-2], hash: $$[$0-1] }; +break; +case 13:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], false, this._$); +break; +case 14:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], true, this._$); +break; +case 15:this.$ = { open: $$[$0-5], path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) }; +break; +case 16:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) }; +break; +case 17:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) }; +break; +case 18:this.$ = { strip: yy.stripFlags($$[$0-1], $$[$0-1]), program: $$[$0] }; +break; +case 19: + var inverse = yy.prepareBlock($$[$0-2], $$[$0-1], $$[$0], $$[$0], false, this._$), + program = yy.prepareProgram([inverse], $$[$0-1].loc); + program.chained = true; + + this.$ = { strip: $$[$0-2].strip, program: program, chain: true }; + +break; +case 20:this.$ = $$[$0]; +break; +case 21:this.$ = {path: $$[$0-1], strip: yy.stripFlags($$[$0-2], $$[$0])}; +break; +case 22:this.$ = yy.prepareMustache($$[$0-3], $$[$0-2], $$[$0-1], $$[$0-4], yy.stripFlags($$[$0-4], $$[$0]), this._$); +break; +case 23:this.$ = yy.prepareMustache($$[$0-3], $$[$0-2], $$[$0-1], $$[$0-4], yy.stripFlags($$[$0-4], $$[$0]), this._$); +break; +case 24: + this.$ = { + type: 'PartialStatement', + name: $$[$0-3], + params: $$[$0-2], + hash: $$[$0-1], + indent: '', + strip: yy.stripFlags($$[$0-4], $$[$0]), + loc: yy.locInfo(this._$) + }; + +break; +case 25:this.$ = yy.preparePartialBlock($$[$0-2], $$[$0-1], $$[$0], this._$); +break; +case 26:this.$ = { path: $$[$0-3], params: $$[$0-2], hash: $$[$0-1], strip: yy.stripFlags($$[$0-4], $$[$0]) }; +break; +case 27:this.$ = $$[$0]; +break; +case 28:this.$ = $$[$0]; +break; +case 29: + this.$ = { + type: 'SubExpression', + path: $$[$0-3], + params: $$[$0-2], + hash: $$[$0-1], + loc: yy.locInfo(this._$) + }; + +break; +case 30:this.$ = {type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$)}; +break; +case 31:this.$ = {type: 'HashPair', key: yy.id($$[$0-2]), value: $$[$0], loc: yy.locInfo(this._$)}; +break; +case 32:this.$ = yy.id($$[$0-1]); +break; +case 33:this.$ = $$[$0]; +break; +case 34:this.$ = $$[$0]; +break; +case 35:this.$ = {type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$)}; +break; +case 36:this.$ = {type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$)}; +break; +case 37:this.$ = {type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$)}; +break; +case 38:this.$ = {type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$)}; +break; +case 39:this.$ = {type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$)}; +break; +case 40:this.$ = $$[$0]; +break; +case 41:this.$ = $$[$0]; +break; +case 42:this.$ = yy.preparePath(true, $$[$0], this._$); +break; +case 43:this.$ = yy.preparePath(false, $$[$0], this._$); +break; +case 44: $$[$0-2].push({part: yy.id($$[$0]), original: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; +break; +case 45:this.$ = [{part: yy.id($$[$0]), original: $$[$0]}]; +break; +case 46:this.$ = []; +break; +case 47:$$[$0-1].push($$[$0]); +break; +case 48:this.$ = [$$[$0]]; +break; +case 49:$$[$0-1].push($$[$0]); +break; +case 50:this.$ = []; +break; +case 51:$$[$0-1].push($$[$0]); +break; +case 58:this.$ = []; +break; +case 59:$$[$0-1].push($$[$0]); +break; +case 64:this.$ = []; +break; +case 65:$$[$0-1].push($$[$0]); +break; +case 70:this.$ = []; +break; +case 71:$$[$0-1].push($$[$0]); +break; +case 78:this.$ = []; +break; +case 79:$$[$0-1].push($$[$0]); +break; +case 82:this.$ = []; +break; +case 83:$$[$0-1].push($$[$0]); +break; +case 86:this.$ = []; +break; +case 87:$$[$0-1].push($$[$0]); +break; +case 90:this.$ = []; +break; +case 91:$$[$0-1].push($$[$0]); +break; +case 94:this.$ = []; +break; +case 95:$$[$0-1].push($$[$0]); +break; +case 98:this.$ = [$$[$0]]; +break; +case 99:$$[$0-1].push($$[$0]); +break; +case 100:this.$ = [$$[$0]]; +break; +case 101:$$[$0-1].push($$[$0]); +break; +} +}, +table: [{3:1,4:2,5:[2,46],6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{1:[3]},{5:[1,4]},{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:10,13:11,14:[1,12],15:[1,20],16:17,19:[1,23],24:15,27:16,29:[1,21],34:[1,22],39:[2,2],44:[2,2],47:[2,2],48:[1,13],51:[1,14],55:[1,18],59:19,60:[1,24]},{1:[2,1]},{5:[2,47],14:[2,47],15:[2,47],19:[2,47],29:[2,47],34:[2,47],39:[2,47],44:[2,47],47:[2,47],48:[2,47],51:[2,47],55:[2,47],60:[2,47]},{5:[2,3],14:[2,3],15:[2,3],19:[2,3],29:[2,3],34:[2,3],39:[2,3],44:[2,3],47:[2,3],48:[2,3],51:[2,3],55:[2,3],60:[2,3]},{5:[2,4],14:[2,4],15:[2,4],19:[2,4],29:[2,4],34:[2,4],39:[2,4],44:[2,4],47:[2,4],48:[2,4],51:[2,4],55:[2,4],60:[2,4]},{5:[2,5],14:[2,5],15:[2,5],19:[2,5],29:[2,5],34:[2,5],39:[2,5],44:[2,5],47:[2,5],48:[2,5],51:[2,5],55:[2,5],60:[2,5]},{5:[2,6],14:[2,6],15:[2,6],19:[2,6],29:[2,6],34:[2,6],39:[2,6],44:[2,6],47:[2,6],48:[2,6],51:[2,6],55:[2,6],60:[2,6]},{5:[2,7],14:[2,7],15:[2,7],19:[2,7],29:[2,7],34:[2,7],39:[2,7],44:[2,7],47:[2,7],48:[2,7],51:[2,7],55:[2,7],60:[2,7]},{5:[2,8],14:[2,8],15:[2,8],19:[2,8],29:[2,8],34:[2,8],39:[2,8],44:[2,8],47:[2,8],48:[2,8],51:[2,8],55:[2,8],60:[2,8]},{5:[2,9],14:[2,9],15:[2,9],19:[2,9],29:[2,9],34:[2,9],39:[2,9],44:[2,9],47:[2,9],48:[2,9],51:[2,9],55:[2,9],60:[2,9]},{20:25,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:36,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{4:37,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],39:[2,46],44:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{4:38,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],44:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{13:40,15:[1,20],17:39},{20:42,56:41,64:43,65:[1,44],72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{4:45,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{5:[2,10],14:[2,10],15:[2,10],18:[2,10],19:[2,10],29:[2,10],34:[2,10],39:[2,10],44:[2,10],47:[2,10],48:[2,10],51:[2,10],55:[2,10],60:[2,10]},{20:46,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:47,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:48,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:42,56:49,64:43,65:[1,44],72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{33:[2,78],49:50,65:[2,78],72:[2,78],80:[2,78],81:[2,78],82:[2,78],83:[2,78],84:[2,78],85:[2,78]},{23:[2,33],33:[2,33],54:[2,33],65:[2,33],68:[2,33],72:[2,33],75:[2,33],80:[2,33],81:[2,33],82:[2,33],83:[2,33],84:[2,33],85:[2,33]},{23:[2,34],33:[2,34],54:[2,34],65:[2,34],68:[2,34],72:[2,34],75:[2,34],80:[2,34],81:[2,34],82:[2,34],83:[2,34],84:[2,34],85:[2,34]},{23:[2,35],33:[2,35],54:[2,35],65:[2,35],68:[2,35],72:[2,35],75:[2,35],80:[2,35],81:[2,35],82:[2,35],83:[2,35],84:[2,35],85:[2,35]},{23:[2,36],33:[2,36],54:[2,36],65:[2,36],68:[2,36],72:[2,36],75:[2,36],80:[2,36],81:[2,36],82:[2,36],83:[2,36],84:[2,36],85:[2,36]},{23:[2,37],33:[2,37],54:[2,37],65:[2,37],68:[2,37],72:[2,37],75:[2,37],80:[2,37],81:[2,37],82:[2,37],83:[2,37],84:[2,37],85:[2,37]},{23:[2,38],33:[2,38],54:[2,38],65:[2,38],68:[2,38],72:[2,38],75:[2,38],80:[2,38],81:[2,38],82:[2,38],83:[2,38],84:[2,38],85:[2,38]},{23:[2,39],33:[2,39],54:[2,39],65:[2,39],68:[2,39],72:[2,39],75:[2,39],80:[2,39],81:[2,39],82:[2,39],83:[2,39],84:[2,39],85:[2,39]},{23:[2,43],33:[2,43],54:[2,43],65:[2,43],68:[2,43],72:[2,43],75:[2,43],80:[2,43],81:[2,43],82:[2,43],83:[2,43],84:[2,43],85:[2,43],87:[1,51]},{72:[1,35],86:52},{23:[2,45],33:[2,45],54:[2,45],65:[2,45],68:[2,45],72:[2,45],75:[2,45],80:[2,45],81:[2,45],82:[2,45],83:[2,45],84:[2,45],85:[2,45],87:[2,45]},{52:53,54:[2,82],65:[2,82],72:[2,82],80:[2,82],81:[2,82],82:[2,82],83:[2,82],84:[2,82],85:[2,82]},{25:54,38:56,39:[1,58],43:57,44:[1,59],45:55,47:[2,54]},{28:60,43:61,44:[1,59],47:[2,56]},{13:63,15:[1,20],18:[1,62]},{15:[2,48],18:[2,48]},{33:[2,86],57:64,65:[2,86],72:[2,86],80:[2,86],81:[2,86],82:[2,86],83:[2,86],84:[2,86],85:[2,86]},{33:[2,40],65:[2,40],72:[2,40],80:[2,40],81:[2,40],82:[2,40],83:[2,40],84:[2,40],85:[2,40]},{33:[2,41],65:[2,41],72:[2,41],80:[2,41],81:[2,41],82:[2,41],83:[2,41],84:[2,41],85:[2,41]},{20:65,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{26:66,47:[1,67]},{30:68,33:[2,58],65:[2,58],72:[2,58],75:[2,58],80:[2,58],81:[2,58],82:[2,58],83:[2,58],84:[2,58],85:[2,58]},{33:[2,64],35:69,65:[2,64],72:[2,64],75:[2,64],80:[2,64],81:[2,64],82:[2,64],83:[2,64],84:[2,64],85:[2,64]},{21:70,23:[2,50],65:[2,50],72:[2,50],80:[2,50],81:[2,50],82:[2,50],83:[2,50],84:[2,50],85:[2,50]},{33:[2,90],61:71,65:[2,90],72:[2,90],80:[2,90],81:[2,90],82:[2,90],83:[2,90],84:[2,90],85:[2,90]},{20:75,33:[2,80],50:72,63:73,64:76,65:[1,44],69:74,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{72:[1,80]},{23:[2,42],33:[2,42],54:[2,42],65:[2,42],68:[2,42],72:[2,42],75:[2,42],80:[2,42],81:[2,42],82:[2,42],83:[2,42],84:[2,42],85:[2,42],87:[1,51]},{20:75,53:81,54:[2,84],63:82,64:76,65:[1,44],69:83,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{26:84,47:[1,67]},{47:[2,55]},{4:85,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],39:[2,46],44:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{47:[2,20]},{20:86,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{4:87,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{26:88,47:[1,67]},{47:[2,57]},{5:[2,11],14:[2,11],15:[2,11],19:[2,11],29:[2,11],34:[2,11],39:[2,11],44:[2,11],47:[2,11],48:[2,11],51:[2,11],55:[2,11],60:[2,11]},{15:[2,49],18:[2,49]},{20:75,33:[2,88],58:89,63:90,64:76,65:[1,44],69:91,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{65:[2,94],66:92,68:[2,94],72:[2,94],80:[2,94],81:[2,94],82:[2,94],83:[2,94],84:[2,94],85:[2,94]},{5:[2,25],14:[2,25],15:[2,25],19:[2,25],29:[2,25],34:[2,25],39:[2,25],44:[2,25],47:[2,25],48:[2,25],51:[2,25],55:[2,25],60:[2,25]},{20:93,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,31:94,33:[2,60],63:95,64:76,65:[1,44],69:96,70:77,71:78,72:[1,79],75:[2,60],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,33:[2,66],36:97,63:98,64:76,65:[1,44],69:99,70:77,71:78,72:[1,79],75:[2,66],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,22:100,23:[2,52],63:101,64:76,65:[1,44],69:102,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,33:[2,92],62:103,63:104,64:76,65:[1,44],69:105,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{33:[1,106]},{33:[2,79],65:[2,79],72:[2,79],80:[2,79],81:[2,79],82:[2,79],83:[2,79],84:[2,79],85:[2,79]},{33:[2,81]},{23:[2,27],33:[2,27],54:[2,27],65:[2,27],68:[2,27],72:[2,27],75:[2,27],80:[2,27],81:[2,27],82:[2,27],83:[2,27],84:[2,27],85:[2,27]},{23:[2,28],33:[2,28],54:[2,28],65:[2,28],68:[2,28],72:[2,28],75:[2,28],80:[2,28],81:[2,28],82:[2,28],83:[2,28],84:[2,28],85:[2,28]},{23:[2,30],33:[2,30],54:[2,30],68:[2,30],71:107,72:[1,108],75:[2,30]},{23:[2,98],33:[2,98],54:[2,98],68:[2,98],72:[2,98],75:[2,98]},{23:[2,45],33:[2,45],54:[2,45],65:[2,45],68:[2,45],72:[2,45],73:[1,109],75:[2,45],80:[2,45],81:[2,45],82:[2,45],83:[2,45],84:[2,45],85:[2,45],87:[2,45]},{23:[2,44],33:[2,44],54:[2,44],65:[2,44],68:[2,44],72:[2,44],75:[2,44],80:[2,44],81:[2,44],82:[2,44],83:[2,44],84:[2,44],85:[2,44],87:[2,44]},{54:[1,110]},{54:[2,83],65:[2,83],72:[2,83],80:[2,83],81:[2,83],82:[2,83],83:[2,83],84:[2,83],85:[2,83]},{54:[2,85]},{5:[2,13],14:[2,13],15:[2,13],19:[2,13],29:[2,13],34:[2,13],39:[2,13],44:[2,13],47:[2,13],48:[2,13],51:[2,13],55:[2,13],60:[2,13]},{38:56,39:[1,58],43:57,44:[1,59],45:112,46:111,47:[2,76]},{33:[2,70],40:113,65:[2,70],72:[2,70],75:[2,70],80:[2,70],81:[2,70],82:[2,70],83:[2,70],84:[2,70],85:[2,70]},{47:[2,18]},{5:[2,14],14:[2,14],15:[2,14],19:[2,14],29:[2,14],34:[2,14],39:[2,14],44:[2,14],47:[2,14],48:[2,14],51:[2,14],55:[2,14],60:[2,14]},{33:[1,114]},{33:[2,87],65:[2,87],72:[2,87],80:[2,87],81:[2,87],82:[2,87],83:[2,87],84:[2,87],85:[2,87]},{33:[2,89]},{20:75,63:116,64:76,65:[1,44],67:115,68:[2,96],69:117,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{33:[1,118]},{32:119,33:[2,62],74:120,75:[1,121]},{33:[2,59],65:[2,59],72:[2,59],75:[2,59],80:[2,59],81:[2,59],82:[2,59],83:[2,59],84:[2,59],85:[2,59]},{33:[2,61],75:[2,61]},{33:[2,68],37:122,74:123,75:[1,121]},{33:[2,65],65:[2,65],72:[2,65],75:[2,65],80:[2,65],81:[2,65],82:[2,65],83:[2,65],84:[2,65],85:[2,65]},{33:[2,67],75:[2,67]},{23:[1,124]},{23:[2,51],65:[2,51],72:[2,51],80:[2,51],81:[2,51],82:[2,51],83:[2,51],84:[2,51],85:[2,51]},{23:[2,53]},{33:[1,125]},{33:[2,91],65:[2,91],72:[2,91],80:[2,91],81:[2,91],82:[2,91],83:[2,91],84:[2,91],85:[2,91]},{33:[2,93]},{5:[2,22],14:[2,22],15:[2,22],19:[2,22],29:[2,22],34:[2,22],39:[2,22],44:[2,22],47:[2,22],48:[2,22],51:[2,22],55:[2,22],60:[2,22]},{23:[2,99],33:[2,99],54:[2,99],68:[2,99],72:[2,99],75:[2,99]},{73:[1,109]},{20:75,63:126,64:76,65:[1,44],72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{5:[2,23],14:[2,23],15:[2,23],19:[2,23],29:[2,23],34:[2,23],39:[2,23],44:[2,23],47:[2,23],48:[2,23],51:[2,23],55:[2,23],60:[2,23]},{47:[2,19]},{47:[2,77]},{20:75,33:[2,72],41:127,63:128,64:76,65:[1,44],69:129,70:77,71:78,72:[1,79],75:[2,72],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{5:[2,24],14:[2,24],15:[2,24],19:[2,24],29:[2,24],34:[2,24],39:[2,24],44:[2,24],47:[2,24],48:[2,24],51:[2,24],55:[2,24],60:[2,24]},{68:[1,130]},{65:[2,95],68:[2,95],72:[2,95],80:[2,95],81:[2,95],82:[2,95],83:[2,95],84:[2,95],85:[2,95]},{68:[2,97]},{5:[2,21],14:[2,21],15:[2,21],19:[2,21],29:[2,21],34:[2,21],39:[2,21],44:[2,21],47:[2,21],48:[2,21],51:[2,21],55:[2,21],60:[2,21]},{33:[1,131]},{33:[2,63]},{72:[1,133],76:132},{33:[1,134]},{33:[2,69]},{15:[2,12]},{14:[2,26],15:[2,26],19:[2,26],29:[2,26],34:[2,26],47:[2,26],48:[2,26],51:[2,26],55:[2,26],60:[2,26]},{23:[2,31],33:[2,31],54:[2,31],68:[2,31],72:[2,31],75:[2,31]},{33:[2,74],42:135,74:136,75:[1,121]},{33:[2,71],65:[2,71],72:[2,71],75:[2,71],80:[2,71],81:[2,71],82:[2,71],83:[2,71],84:[2,71],85:[2,71]},{33:[2,73],75:[2,73]},{23:[2,29],33:[2,29],54:[2,29],65:[2,29],68:[2,29],72:[2,29],75:[2,29],80:[2,29],81:[2,29],82:[2,29],83:[2,29],84:[2,29],85:[2,29]},{14:[2,15],15:[2,15],19:[2,15],29:[2,15],34:[2,15],39:[2,15],44:[2,15],47:[2,15],48:[2,15],51:[2,15],55:[2,15],60:[2,15]},{72:[1,138],77:[1,137]},{72:[2,100],77:[2,100]},{14:[2,16],15:[2,16],19:[2,16],29:[2,16],34:[2,16],44:[2,16],47:[2,16],48:[2,16],51:[2,16],55:[2,16],60:[2,16]},{33:[1,139]},{33:[2,75]},{33:[2,32]},{72:[2,101],77:[2,101]},{14:[2,17],15:[2,17],19:[2,17],29:[2,17],34:[2,17],39:[2,17],44:[2,17],47:[2,17],48:[2,17],51:[2,17],55:[2,17],60:[2,17]}], +defaultActions: {4:[2,1],55:[2,55],57:[2,20],61:[2,57],74:[2,81],83:[2,85],87:[2,18],91:[2,89],102:[2,53],105:[2,93],111:[2,19],112:[2,77],117:[2,97],120:[2,63],123:[2,69],124:[2,12],136:[2,75],137:[2,32]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") + this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) + if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; +} +}; +/* Jison generated lexer */ +var lexer = (function(){ +var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + if (this.options.ranges) this.yylloc.range = [0,0]; + this.offset = 0; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length-len-1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length-1); + this.matched = this.matched.substr(0, this.matched.length-1); + + if (lines.length-1) this.yylineno -= lines.length-1; + var r = this.yylloc.range; + + this.yylloc = {first_line: this.yylloc.first_line, + last_line: this.yylineno+1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, +more:function () { + this._more = true; + return this; + }, +less:function (n) { + this.unput(this.match.slice(n)); + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); + }}); +lexer.options = {}; +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START +/**/) { + + +function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end); +} + + +var YYSTATE=YY_START +switch($avoiding_name_collisions) { +case 0: + if(yy_.yytext.slice(-2) === "\\\\") { + strip(0,1); + this.begin("mu"); + } else if(yy_.yytext.slice(-1) === "\\") { + strip(0,1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if(yy_.yytext) return 15; + +break; +case 1:return 15; +break; +case 2: + this.popState(); + return 15; + +break; +case 3:this.begin('raw'); return 15; +break; +case 4: + this.popState(); + // Should be using `this.topState()` below, but it currently + // returns the second top instead of the first top. Opened an + // issue about it at https://github.com/zaach/jison/issues/291 + if (this.conditionStack[this.conditionStack.length-1] === 'raw') { + return 15; + } else { + yy_.yytext = yy_.yytext.substr(5, yy_.yyleng-9); + return 'END_RAW_BLOCK'; + } + +break; +case 5: return 15; +break; +case 6: + this.popState(); + return 14; + +break; +case 7:return 65; +break; +case 8:return 68; +break; +case 9: return 19; +break; +case 10: + this.popState(); + this.begin('raw'); + return 23; + +break; +case 11:return 55; +break; +case 12:return 60; +break; +case 13:return 29; +break; +case 14:return 47; +break; +case 15:this.popState(); return 44; +break; +case 16:this.popState(); return 44; +break; +case 17:return 34; +break; +case 18:return 39; +break; +case 19:return 51; +break; +case 20:return 48; +break; +case 21: + this.unput(yy_.yytext); + this.popState(); + this.begin('com'); + +break; +case 22: + this.popState(); + return 14; + +break; +case 23:return 48; +break; +case 24:return 73; +break; +case 25:return 72; +break; +case 26:return 72; +break; +case 27:return 87; +break; +case 28:// ignore whitespace +break; +case 29:this.popState(); return 54; +break; +case 30:this.popState(); return 33; +break; +case 31:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 80; +break; +case 32:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 80; +break; +case 33:return 85; +break; +case 34:return 82; +break; +case 35:return 82; +break; +case 36:return 83; +break; +case 37:return 84; +break; +case 38:return 81; +break; +case 39:return 75; +break; +case 40:return 77; +break; +case 41:return 72; +break; +case 42:yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g,'$1'); return 72; +break; +case 43:return 'INVALID'; +break; +case 44:return 5; +break; +} +}; +lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{(?=[^\/]))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#>)/,/^(?:\{\{(~)?#\*?)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?\*?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:undefined(?=([~}\s)])))/,/^(?:null(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[(\\\]|[^\]])*\])/,/^(?:.)/,/^(?:$)/]; +lexer.conditions = {"mu":{"rules":[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[6],"inclusive":false},"raw":{"rules":[3,4,5],"inclusive":false},"INITIAL":{"rules":[0,1,44],"inclusive":true}}; +return lexer;})() +parser.lexer = lexer; +function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; +return new Parser; +})();exports.__esModule = true; +exports['default'] = handlebars; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/printer.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/printer.js new file mode 100644 index 0000000..6ad43ba --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/printer.js @@ -0,0 +1,171 @@ +/* eslint-disable new-cap */ +import Visitor from './visitor'; + +export function print(ast) { + return new PrintVisitor().accept(ast); +} + +export function PrintVisitor() { + this.padding = 0; +} + +PrintVisitor.prototype = new Visitor(); + +PrintVisitor.prototype.pad = function(string) { + let out = ''; + + for (let i = 0, l = this.padding; i < l; i++) { + out += ' '; + } + + out += string + '\n'; + return out; +}; + +PrintVisitor.prototype.Program = function(program) { + let out = '', + body = program.body, + i, l; + + if (program.blockParams) { + let blockParams = 'BLOCK PARAMS: ['; + for (i = 0, l = program.blockParams.length; i < l; i++) { + blockParams += ' ' + program.blockParams[i]; + } + blockParams += ' ]'; + out += this.pad(blockParams); + } + + for (i = 0, l = body.length; i < l; i++) { + out += this.accept(body[i]); + } + + this.padding--; + + return out; +}; + +PrintVisitor.prototype.MustacheStatement = function(mustache) { + return this.pad('{{ ' + this.SubExpression(mustache) + ' }}'); +}; +PrintVisitor.prototype.Decorator = function(mustache) { + return this.pad('{{ DIRECTIVE ' + this.SubExpression(mustache) + ' }}'); +}; + +PrintVisitor.prototype.BlockStatement = +PrintVisitor.prototype.DecoratorBlock = function(block) { + let out = ''; + + out += this.pad((block.type === 'DecoratorBlock' ? 'DIRECTIVE ' : '') + 'BLOCK:'); + this.padding++; + out += this.pad(this.SubExpression(block)); + if (block.program) { + out += this.pad('PROGRAM:'); + this.padding++; + out += this.accept(block.program); + this.padding--; + } + if (block.inverse) { + if (block.program) { this.padding++; } + out += this.pad('{{^}}'); + this.padding++; + out += this.accept(block.inverse); + this.padding--; + if (block.program) { this.padding--; } + } + this.padding--; + + return out; +}; + +PrintVisitor.prototype.PartialStatement = function(partial) { + let content = 'PARTIAL:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + return this.pad('{{> ' + content + ' }}'); +}; +PrintVisitor.prototype.PartialBlockStatement = function(partial) { + let content = 'PARTIAL BLOCK:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + + content += ' ' + this.pad('PROGRAM:'); + this.padding++; + content += this.accept(partial.program); + this.padding--; + + return this.pad('{{> ' + content + ' }}'); +}; + +PrintVisitor.prototype.ContentStatement = function(content) { + return this.pad("CONTENT[ '" + content.value + "' ]"); +}; + +PrintVisitor.prototype.CommentStatement = function(comment) { + return this.pad("{{! '" + comment.value + "' }}"); +}; + +PrintVisitor.prototype.SubExpression = function(sexpr) { + let params = sexpr.params, + paramStrings = [], + hash; + + for (let i = 0, l = params.length; i < l; i++) { + paramStrings.push(this.accept(params[i])); + } + + params = '[' + paramStrings.join(', ') + ']'; + + hash = sexpr.hash ? ' ' + this.accept(sexpr.hash) : ''; + + return this.accept(sexpr.path) + ' ' + params + hash; +}; + +PrintVisitor.prototype.PathExpression = function(id) { + let path = id.parts.join('/'); + return (id.data ? '@' : '') + 'PATH:' + path; +}; + + +PrintVisitor.prototype.StringLiteral = function(string) { + return '"' + string.value + '"'; +}; + +PrintVisitor.prototype.NumberLiteral = function(number) { + return 'NUMBER{' + number.value + '}'; +}; + +PrintVisitor.prototype.BooleanLiteral = function(bool) { + return 'BOOLEAN{' + bool.value + '}'; +}; + +PrintVisitor.prototype.UndefinedLiteral = function() { + return 'UNDEFINED'; +}; + +PrintVisitor.prototype.NullLiteral = function() { + return 'NULL'; +}; + +PrintVisitor.prototype.Hash = function(hash) { + let pairs = hash.pairs, + joinedPairs = []; + + for (let i = 0, l = pairs.length; i < l; i++) { + joinedPairs.push(this.accept(pairs[i])); + } + + return 'HASH{' + joinedPairs.join(', ') + '}'; +}; +PrintVisitor.prototype.HashPair = function(pair) { + return pair.key + '=' + this.accept(pair.value); +}; +/* eslint-enable new-cap */ diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/visitor.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/visitor.js new file mode 100644 index 0000000..2c504d1 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/visitor.js @@ -0,0 +1,129 @@ +import Exception from '../exception'; + +function Visitor() { + this.parents = []; +} + +Visitor.prototype = { + constructor: Visitor, + mutating: false, + + // Visits a given value. If mutating, will replace the value if necessary. + acceptKey: function(node, name) { + let value = this.accept(node[name]); + if (this.mutating) { + // Hacky sanity check: This may have a few false positives for type for the helper + // methods but will generally do the right thing without a lot of overhead. + if (value && !Visitor.prototype[value.type]) { + throw new Exception('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); + } + node[name] = value; + } + }, + + // Performs an accept operation with added sanity check to ensure + // required keys are not removed. + acceptRequired: function(node, name) { + this.acceptKey(node, name); + + if (!node[name]) { + throw new Exception(node.type + ' requires ' + name); + } + }, + + // Traverses a given array. If mutating, empty respnses will be removed + // for child elements. + acceptArray: function(array) { + for (let i = 0, l = array.length; i < l; i++) { + this.acceptKey(array, i); + + if (!array[i]) { + array.splice(i, 1); + i--; + l--; + } + } + }, + + accept: function(object) { + if (!object) { + return; + } + + /* istanbul ignore next: Sanity code */ + if (!this[object.type]) { + throw new Exception('Unknown type: ' + object.type, object); + } + + if (this.current) { + this.parents.unshift(this.current); + } + this.current = object; + + let ret = this[object.type](object); + + this.current = this.parents.shift(); + + if (!this.mutating || ret) { + return ret; + } else if (ret !== false) { + return object; + } + }, + + Program: function(program) { + this.acceptArray(program.body); + }, + + MustacheStatement: visitSubExpression, + Decorator: visitSubExpression, + + BlockStatement: visitBlock, + DecoratorBlock: visitBlock, + + PartialStatement: visitPartial, + PartialBlockStatement: function(partial) { + visitPartial.call(this, partial); + + this.acceptKey(partial, 'program'); + }, + + ContentStatement: function(/* content */) {}, + CommentStatement: function(/* comment */) {}, + + SubExpression: visitSubExpression, + + PathExpression: function(/* path */) {}, + + StringLiteral: function(/* string */) {}, + NumberLiteral: function(/* number */) {}, + BooleanLiteral: function(/* bool */) {}, + UndefinedLiteral: function(/* literal */) {}, + NullLiteral: function(/* literal */) {}, + + Hash: function(hash) { + this.acceptArray(hash.pairs); + }, + HashPair: function(pair) { + this.acceptRequired(pair, 'value'); + } +}; + +function visitSubExpression(mustache) { + this.acceptRequired(mustache, 'path'); + this.acceptArray(mustache.params); + this.acceptKey(mustache, 'hash'); +} +function visitBlock(block) { + visitSubExpression.call(this, block); + + this.acceptKey(block, 'program'); + this.acceptKey(block, 'inverse'); +} +function visitPartial(partial) { + this.acceptRequired(partial, 'name'); + this.acceptArray(partial.params); + this.acceptKey(partial, 'hash'); +} + +export default Visitor; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/whitespace-control.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/whitespace-control.js new file mode 100644 index 0000000..e11483c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/compiler/whitespace-control.js @@ -0,0 +1,216 @@ +import Visitor from './visitor'; + +function WhitespaceControl(options = {}) { + this.options = options; +} +WhitespaceControl.prototype = new Visitor(); + +WhitespaceControl.prototype.Program = function(program) { + const doStandalone = !this.options.ignoreStandalone; + + let isRoot = !this.isRootSeen; + this.isRootSeen = true; + + let body = program.body; + for (let i = 0, l = body.length; i < l; i++) { + let current = body[i], + strip = this.accept(current); + + if (!strip) { + continue; + } + + let _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), + _isNextWhitespace = isNextWhitespace(body, i, isRoot), + + openStandalone = strip.openStandalone && _isPrevWhitespace, + closeStandalone = strip.closeStandalone && _isNextWhitespace, + inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; + + if (strip.close) { + omitRight(body, i, true); + } + if (strip.open) { + omitLeft(body, i, true); + } + + if (doStandalone && inlineStandalone) { + omitRight(body, i); + + if (omitLeft(body, i)) { + // If we are on a standalone node, save the indent info for partials + if (current.type === 'PartialStatement') { + // Pull out the whitespace from the final line + current.indent = (/([ \t]+$)/).exec(body[i - 1].original)[1]; + } + } + } + if (doStandalone && openStandalone) { + omitRight((current.program || current.inverse).body); + + // Strip out the previous content node if it's whitespace only + omitLeft(body, i); + } + if (doStandalone && closeStandalone) { + // Always strip the next node + omitRight(body, i); + + omitLeft((current.inverse || current.program).body); + } + } + + return program; +}; + +WhitespaceControl.prototype.BlockStatement = +WhitespaceControl.prototype.DecoratorBlock = +WhitespaceControl.prototype.PartialBlockStatement = function(block) { + this.accept(block.program); + this.accept(block.inverse); + + // Find the inverse program that is involed with whitespace stripping. + let program = block.program || block.inverse, + inverse = block.program && block.inverse, + firstInverse = inverse, + lastInverse = inverse; + + if (inverse && inverse.chained) { + firstInverse = inverse.body[0].program; + + // Walk the inverse chain to find the last inverse that is actually in the chain. + while (lastInverse.chained) { + lastInverse = lastInverse.body[lastInverse.body.length - 1].program; + } + } + + let strip = { + open: block.openStrip.open, + close: block.closeStrip.close, + + // Determine the standalone candiacy. Basically flag our content as being possibly standalone + // so our parent can determine if we actually are standalone + openStandalone: isNextWhitespace(program.body), + closeStandalone: isPrevWhitespace((firstInverse || program).body) + }; + + if (block.openStrip.close) { + omitRight(program.body, null, true); + } + + if (inverse) { + let inverseStrip = block.inverseStrip; + + if (inverseStrip.open) { + omitLeft(program.body, null, true); + } + + if (inverseStrip.close) { + omitRight(firstInverse.body, null, true); + } + if (block.closeStrip.open) { + omitLeft(lastInverse.body, null, true); + } + + // Find standalone else statments + if (!this.options.ignoreStandalone + && isPrevWhitespace(program.body) + && isNextWhitespace(firstInverse.body)) { + omitLeft(program.body); + omitRight(firstInverse.body); + } + } else if (block.closeStrip.open) { + omitLeft(program.body, null, true); + } + + return strip; +}; + +WhitespaceControl.prototype.Decorator = +WhitespaceControl.prototype.MustacheStatement = function(mustache) { + return mustache.strip; +}; + +WhitespaceControl.prototype.PartialStatement = + WhitespaceControl.prototype.CommentStatement = function(node) { + /* istanbul ignore next */ + let strip = node.strip || {}; + return { + inlineStandalone: true, + open: strip.open, + close: strip.close + }; +}; + + +function isPrevWhitespace(body, i, isRoot) { + if (i === undefined) { + i = body.length; + } + + // Nodes that end with newlines are considered whitespace (but are special + // cased for strip operations) + let prev = body[i - 1], + sibling = body[i - 2]; + if (!prev) { + return isRoot; + } + + if (prev.type === 'ContentStatement') { + return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original); + } +} +function isNextWhitespace(body, i, isRoot) { + if (i === undefined) { + i = -1; + } + + let next = body[i + 1], + sibling = body[i + 2]; + if (!next) { + return isRoot; + } + + if (next.type === 'ContentStatement') { + return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original); + } +} + +// Marks the node to the right of the position as omitted. +// I.e. {{foo}}' ' will mark the ' ' node as omitted. +// +// If i is undefined, then the first child will be marked as such. +// +// If mulitple is truthy then all whitespace will be stripped out until non-whitespace +// content is met. +function omitRight(body, i, multiple) { + let current = body[i == null ? 0 : i + 1]; + if (!current || current.type !== 'ContentStatement' || (!multiple && current.rightStripped)) { + return; + } + + let original = current.value; + current.value = current.value.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), ''); + current.rightStripped = current.value !== original; +} + +// Marks the node to the left of the position as omitted. +// I.e. ' '{{foo}} will mark the ' ' node as omitted. +// +// If i is undefined then the last child will be marked as such. +// +// If mulitple is truthy then all whitespace will be stripped out until non-whitespace +// content is met. +function omitLeft(body, i, multiple) { + let current = body[i == null ? body.length - 1 : i - 1]; + if (!current || current.type !== 'ContentStatement' || (!multiple && current.leftStripped)) { + return; + } + + // We omit the last node if it's whitespace only and not preceeded by a non-content node. + let original = current.value; + current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), ''); + current.leftStripped = current.value !== original; + return current.leftStripped; +} + +export default WhitespaceControl; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/decorators.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/decorators.js new file mode 100644 index 0000000..6f5a615 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/decorators.js @@ -0,0 +1,6 @@ +import registerInline from './decorators/inline'; + +export function registerDefaultDecorators(instance) { + registerInline(instance); +} + diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/decorators/inline.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/decorators/inline.js new file mode 100644 index 0000000..2142466 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/decorators/inline.js @@ -0,0 +1,22 @@ +import {extend} from '../utils'; + +export default function(instance) { + instance.registerDecorator('inline', function(fn, props, container, options) { + let ret = fn; + if (!props.partials) { + props.partials = {}; + ret = function(context, options) { + // Create a new partials stack frame prior to exec. + let original = container.partials; + container.partials = extend({}, original, props.partials); + let ret = fn(context, options); + container.partials = original; + return ret; + }; + } + + props.partials[options.args[0]] = options.fn; + + return ret; + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/exception.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/exception.js new file mode 100644 index 0000000..08ae531 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/exception.js @@ -0,0 +1,46 @@ + +const errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + +function Exception(message, node) { + let loc = node && node.loc, + line, + column; + if (loc) { + line = loc.start.line; + column = loc.start.column; + + message += ' - ' + line + ':' + column; + } + + let tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (let idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + /* istanbul ignore else */ + if (Error.captureStackTrace) { + Error.captureStackTrace(this, Exception); + } + + try { + if (loc) { + this.lineNumber = line; + + // Work around issue under safari where we can't directly set the column value + /* istanbul ignore next */ + if (Object.defineProperty) { + Object.defineProperty(this, 'column', {value: column}); + } else { + this.column = column; + } + } + } catch (nop) { + /* Ignore if the browser is very particular */ + } +} + +Exception.prototype = new Error(); + +export default Exception; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers.js new file mode 100644 index 0000000..7a4365a --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers.js @@ -0,0 +1,17 @@ +import registerBlockHelperMissing from './helpers/block-helper-missing'; +import registerEach from './helpers/each'; +import registerHelperMissing from './helpers/helper-missing'; +import registerIf from './helpers/if'; +import registerLog from './helpers/log'; +import registerLookup from './helpers/lookup'; +import registerWith from './helpers/with'; + +export function registerDefaultHelpers(instance) { + registerBlockHelperMissing(instance); + registerEach(instance); + registerHelperMissing(instance); + registerIf(instance); + registerLog(instance); + registerLookup(instance); + registerWith(instance); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/block-helper-missing.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/block-helper-missing.js new file mode 100644 index 0000000..6639ddb --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/block-helper-missing.js @@ -0,0 +1,32 @@ +import {appendContextPath, createFrame, isArray} from '../utils'; + +export default function(instance) { + instance.registerHelper('blockHelperMissing', function(context, options) { + let inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + let data = createFrame(options.data); + data.contextPath = appendContextPath(options.data.contextPath, options.name); + options = {data: data}; + } + + return fn(context, options); + } + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/each.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/each.js new file mode 100644 index 0000000..fb11903 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/each.js @@ -0,0 +1,79 @@ +import {appendContextPath, blockParams, createFrame, isArray, isFunction} from '../utils'; +import Exception from '../exception'; + +export default function(instance) { + instance.registerHelper('each', function(context, options) { + if (!options) { + throw new Exception('Must pass iterator to #each'); + } + + let fn = options.fn, + inverse = options.inverse, + i = 0, + ret = '', + data, + contextPath; + + if (options.data && options.ids) { + contextPath = appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (isFunction(context)) { context = context.call(this); } + + if (options.data) { + data = createFrame(options.data); + } + + function execIteration(field, index, last) { + if (data) { + data.key = field; + data.index = index; + data.first = index === 0; + data.last = !!last; + + if (contextPath) { + data.contextPath = contextPath + field; + } + } + + ret = ret + fn(context[field], { + data: data, + blockParams: blockParams([context[field], field], [contextPath + field, null]) + }); + } + + if (context && typeof context === 'object') { + if (isArray(context)) { + for (let j = context.length; i < j; i++) { + if (i in context) { + execIteration(i, i, i === context.length - 1); + } + } + } else { + let priorKey; + + for (let key in context) { + if (context.hasOwnProperty(key)) { + // We're running the iterations one step out of sync so we can detect + // the last iteration without have to scan the object twice and create + // an itermediate keys array. + if (priorKey !== undefined) { + execIteration(priorKey, i - 1); + } + priorKey = key; + i++; + } + } + if (priorKey !== undefined) { + execIteration(priorKey, i - 1, true); + } + } + } + + if (i === 0) { + ret = inverse(this); + } + + return ret; + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/helper-missing.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/helper-missing.js new file mode 100644 index 0000000..ec32e82 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/helper-missing.js @@ -0,0 +1,13 @@ +import Exception from '../exception'; + +export default function(instance) { + instance.registerHelper('helperMissing', function(/* [args, ]options */) { + if (arguments.length === 1) { + // A missing field in a {{foo}} construct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new Exception('Missing helper: "' + arguments[arguments.length - 1].name + '"'); + } + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/if.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/if.js new file mode 100644 index 0000000..11d08df --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/if.js @@ -0,0 +1,20 @@ +import {isEmpty, isFunction} from '../utils'; + +export default function(instance) { + instance.registerHelper('if', function(conditional, options) { + if (isFunction(conditional)) { conditional = conditional.call(this); } + + // Default behavior is to render the positive path if the value is truthy and not empty. + // The `includeZero` option may be set to treat the condtional as purely not empty based on the + // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. + if ((!options.hash.includeZero && !conditional) || isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + instance.registerHelper('unless', function(conditional, options) { + return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash}); + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/log.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/log.js new file mode 100644 index 0000000..4bde4a1 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/log.js @@ -0,0 +1,19 @@ +export default function(instance) { + instance.registerHelper('log', function(/* message, options */) { + let args = [undefined], + options = arguments[arguments.length - 1]; + for (let i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]); + } + + let level = 1; + if (options.hash.level != null) { + level = options.hash.level; + } else if (options.data && options.data.level != null) { + level = options.data.level; + } + args[0] = level; + + instance.log(... args); + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/lookup.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/lookup.js new file mode 100644 index 0000000..a52e77a --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/lookup.js @@ -0,0 +1,5 @@ +export default function(instance) { + instance.registerHelper('lookup', function(obj, field) { + return obj && obj[field]; + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/with.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/with.js new file mode 100644 index 0000000..7418cd0 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/helpers/with.js @@ -0,0 +1,24 @@ +import {appendContextPath, blockParams, createFrame, isEmpty, isFunction} from '../utils'; + +export default function(instance) { + instance.registerHelper('with', function(context, options) { + if (isFunction(context)) { context = context.call(this); } + + let fn = options.fn; + + if (!isEmpty(context)) { + let data = options.data; + if (options.data && options.ids) { + data = createFrame(options.data); + data.contextPath = appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + }); +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/logger.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/logger.js new file mode 100644 index 0000000..1ab0051 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/logger.js @@ -0,0 +1,35 @@ +import {indexOf} from './utils'; + +let logger = { + methodMap: ['debug', 'info', 'warn', 'error'], + level: 'info', + + // Maps a given level value to the `methodMap` indexes above. + lookupLevel: function(level) { + if (typeof level === 'string') { + let levelMap = indexOf(logger.methodMap, level.toLowerCase()); + if (levelMap >= 0) { + level = levelMap; + } else { + level = parseInt(level, 10); + } + } + + return level; + }, + + // Can be overridden in the host environment + log: function(level, ...message) { + level = logger.lookupLevel(level); + + if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { + let method = logger.methodMap[level]; + if (!console[method]) { // eslint-disable-line no-console + method = 'log'; + } + console[method](...message); // eslint-disable-line no-console + } + } +}; + +export default logger; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/no-conflict.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/no-conflict.js new file mode 100644 index 0000000..40a44d7 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/no-conflict.js @@ -0,0 +1,13 @@ +/* global window */ +export default function(Handlebars) { + /* istanbul ignore next */ + let root = typeof global !== 'undefined' ? global : window, + $Handlebars = root.Handlebars; + /* istanbul ignore next */ + Handlebars.noConflict = function() { + if (root.Handlebars === Handlebars) { + root.Handlebars = $Handlebars; + } + return Handlebars; + }; +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/runtime.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/runtime.js new file mode 100644 index 0000000..103b5af --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/runtime.js @@ -0,0 +1,274 @@ +import * as Utils from './utils'; +import Exception from './exception'; +import { COMPILER_REVISION, REVISION_CHANGES, createFrame } from './base'; + +export function checkRevision(compilerInfo) { + const compilerRevision = compilerInfo && compilerInfo[0] || 1, + currentRevision = COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + const runtimeVersions = REVISION_CHANGES[currentRevision], + compilerVersions = REVISION_CHANGES[compilerRevision]; + throw new Exception('Template was precompiled with an older version of Handlebars than the current runtime. ' + + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); + } else { + // Use the embedded version info since the runtime doesn't know about this revision yet + throw new Exception('Template was precompiled with a newer version of Handlebars than the current runtime. ' + + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); + } + } +} + +export function template(templateSpec, env) { + /* istanbul ignore next */ + if (!env) { + throw new Exception('No environment passed to template'); + } + if (!templateSpec || !templateSpec.main) { + throw new Exception('Unknown template object: ' + typeof templateSpec); + } + + templateSpec.main.decorator = templateSpec.main_d; + + // Note: Using env.VM references rather than local var references throughout this section to allow + // for external users to override these as psuedo-supported APIs. + env.VM.checkRevision(templateSpec.compiler); + + function invokePartialWrapper(partial, context, options) { + if (options.hash) { + context = Utils.extend({}, context, options.hash); + if (options.ids) { + options.ids[0] = true; + } + } + + partial = env.VM.resolvePartial.call(this, partial, context, options); + let result = env.VM.invokePartial.call(this, partial, context, options); + + if (result == null && env.compile) { + options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); + result = options.partials[options.name](context, options); + } + if (result != null) { + if (options.indent) { + let lines = result.split('\n'); + for (let i = 0, l = lines.length; i < l; i++) { + if (!lines[i] && i + 1 === l) { + break; + } + + lines[i] = options.indent + lines[i]; + } + result = lines.join('\n'); + } + return result; + } else { + throw new Exception('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); + } + } + + // Just add water + let container = { + strict: function(obj, name) { + if (!(name in obj)) { + throw new Exception('"' + name + '" not defined in ' + obj); + } + return obj[name]; + }, + lookup: function(depths, name) { + const len = depths.length; + for (let i = 0; i < len; i++) { + if (depths[i] && depths[i][name] != null) { + return depths[i][name]; + } + } + }, + lambda: function(current, context) { + return typeof current === 'function' ? current.call(context) : current; + }, + + escapeExpression: Utils.escapeExpression, + invokePartial: invokePartialWrapper, + + fn: function(i) { + let ret = templateSpec[i]; + ret.decorator = templateSpec[i + '_d']; + return ret; + }, + + programs: [], + program: function(i, data, declaredBlockParams, blockParams, depths) { + let programWrapper = this.programs[i], + fn = this.fn(i); + if (data || depths || blockParams || declaredBlockParams) { + programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); + } else if (!programWrapper) { + programWrapper = this.programs[i] = wrapProgram(this, i, fn); + } + return programWrapper; + }, + + data: function(value, depth) { + while (value && depth--) { + value = value._parent; + } + return value; + }, + merge: function(param, common) { + let obj = param || common; + + if (param && common && (param !== common)) { + obj = Utils.extend({}, common, param); + } + + return obj; + }, + + noop: env.VM.noop, + compilerInfo: templateSpec.compiler + }; + + function ret(context, options = {}) { + let data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + let depths, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context/*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ret.isTop = true; + + ret._setup = function(options) { + if (!options.partial) { + container.helpers = container.merge(options.helpers, env.helpers); + + if (templateSpec.usePartial) { + container.partials = container.merge(options.partials, env.partials); + } + if (templateSpec.usePartial || templateSpec.useDecorators) { + container.decorators = container.merge(options.decorators, env.decorators); + } + } else { + container.helpers = options.helpers; + container.partials = options.partials; + container.decorators = options.decorators; + } + }; + + ret._child = function(i, data, blockParams, depths) { + if (templateSpec.useBlockParams && !blockParams) { + throw new Exception('must pass block params'); + } + if (templateSpec.useDepths && !depths) { + throw new Exception('must pass parent depths'); + } + + return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); + }; + return ret; +} + +export function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { + function prog(context, options = {}) { + let currentDepths = depths; + if (depths && context != depths[0]) { + currentDepths = [context].concat(depths); + } + + return fn(container, + context, + container.helpers, container.partials, + options.data || data, + blockParams && [options.blockParams].concat(blockParams), + currentDepths); + } + + prog = executeDecorators(fn, prog, container, depths, data, blockParams); + + prog.program = i; + prog.depth = depths ? depths.length : 0; + prog.blockParams = declaredBlockParams || 0; + return prog; +} + +export function resolvePartial(partial, context, options) { + if (!partial) { + if (options.name === '@partial-block') { + let data = options.data; + while (data['partial-block'] === noop) { + data = data._parent; + } + partial = data['partial-block']; + data['partial-block'] = noop; + } else { + partial = options.partials[options.name]; + } + } else if (!partial.call && !options.name) { + // This is a dynamic partial that returned a string + options.name = partial; + partial = options.partials[partial]; + } + return partial; +} + +export function invokePartial(partial, context, options) { + options.partial = true; + if (options.ids) { + options.data.contextPath = options.ids[0] || options.data.contextPath; + } + + let partialBlock; + if (options.fn && options.fn !== noop) { + options.data = createFrame(options.data); + partialBlock = options.data['partial-block'] = options.fn; + + if (partialBlock.partials) { + options.partials = Utils.extend({}, options.partials, partialBlock.partials); + } + } + + if (partial === undefined && partialBlock) { + partial = partialBlock; + } + + if (partial === undefined) { + throw new Exception('The partial ' + options.name + ' could not be found'); + } else if (partial instanceof Function) { + return partial(context, options); + } +} + +export function noop() { return ''; } + +function initData(context, data) { + if (!data || !('root' in data)) { + data = data ? createFrame(data) : {}; + data.root = context; + } + return data; +} + +function executeDecorators(fn, prog, container, depths, data, blockParams) { + if (fn.decorator) { + let props = {}; + prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); + Utils.extend(prog, props); + } + return prog; +} diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/safe-string.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/safe-string.js new file mode 100644 index 0000000..4680194 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/safe-string.js @@ -0,0 +1,10 @@ +// Build out our basic SafeString type +function SafeString(string) { + this.string = string; +} + +SafeString.prototype.toString = SafeString.prototype.toHTML = function() { + return '' + this.string; +}; + +export default SafeString; diff --git a/hm_sunwell/node_modules/handlebars/lib/handlebars/utils.js b/hm_sunwell/node_modules/handlebars/lib/handlebars/utils.js new file mode 100644 index 0000000..2584601 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/handlebars/utils.js @@ -0,0 +1,108 @@ +const escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=' +}; + +const badChars = /[&<>"'`=]/g, + possible = /[&<>"'`=]/; + +function escapeChar(chr) { + return escape[chr]; +} + +export function extend(obj/* , ...source */) { + for (let i = 1; i < arguments.length; i++) { + for (let key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; +} + +export let toString = Object.prototype.toString; + +// Sourced from lodash +// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt +/* eslint-disable func-style */ +let isFunction = function(value) { + return typeof value === 'function'; +}; +// fallback for older versions of Chrome and Safari +/* istanbul ignore next */ +if (isFunction(/x/)) { + isFunction = function(value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; +} +export {isFunction}; +/* eslint-enable func-style */ + +/* istanbul ignore next */ +export const isArray = Array.isArray || function(value) { + return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; +}; + +// Older IE versions do not directly support indexOf so we must implement our own, sadly. +export function indexOf(array, value) { + for (let i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + return -1; +} + + +export function escapeExpression(string) { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + } + + if (!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); +} + +export function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } +} + +export function createFrame(object) { + let frame = extend({}, object); + frame._parent = object; + return frame; +} + +export function blockParams(params, ids) { + params.path = ids; + return params; +} + +export function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; +} diff --git a/hm_sunwell/node_modules/handlebars/lib/index.js b/hm_sunwell/node_modules/handlebars/lib/index.js new file mode 100644 index 0000000..0383c02 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/index.js @@ -0,0 +1,25 @@ +// USAGE: +// var handlebars = require('handlebars'); +/* eslint-disable no-var */ + +// var local = handlebars.create(); + +var handlebars = require('../dist/cjs/handlebars')['default']; + +var printer = require('../dist/cjs/handlebars/compiler/printer'); +handlebars.PrintVisitor = printer.PrintVisitor; +handlebars.print = printer.print; + +module.exports = handlebars; + +// Publish a Node.js require() handler for .handlebars and .hbs files +function extension(module, filename) { + var fs = require('fs'); + var templateString = fs.readFileSync(filename, 'utf8'); + module.exports = handlebars.compile(templateString); +} +/* istanbul ignore else */ +if (typeof require !== 'undefined' && require.extensions) { + require.extensions['.handlebars'] = extension; + require.extensions['.hbs'] = extension; +} diff --git a/hm_sunwell/node_modules/handlebars/lib/precompiler.js b/hm_sunwell/node_modules/handlebars/lib/precompiler.js new file mode 100644 index 0000000..a20d141 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/lib/precompiler.js @@ -0,0 +1,276 @@ +/* eslint-disable no-console */ +import Async from 'async'; +import fs from 'fs'; +import * as Handlebars from './handlebars'; +import {basename} from 'path'; +import {SourceMapConsumer, SourceNode} from 'source-map'; +import uglify from 'uglify-js'; + +module.exports.loadTemplates = function(opts, callback) { + loadStrings(opts, function(err, strings) { + if (err) { + callback(err); + } else { + loadFiles(opts, function(err, files) { + if (err) { + callback(err); + } else { + opts.templates = strings.concat(files); + callback(undefined, opts); + } + }); + } + }); +}; + +function loadStrings(opts, callback) { + let strings = arrayCast(opts.string), + names = arrayCast(opts.name); + + if (names.length !== strings.length + && strings.length > 1) { + return callback(new Handlebars.Exception('Number of names did not match the number of string inputs')); + } + + Async.map(strings, function(string, callback) { + if (string !== '-') { + callback(undefined, string); + } else { + // Load from stdin + let buffer = ''; + process.stdin.setEncoding('utf8'); + + process.stdin.on('data', function(chunk) { + buffer += chunk; + }); + process.stdin.on('end', function() { + callback(undefined, buffer); + }); + } + }, + function(err, strings) { + strings = strings.map((string, index) => ({ + name: names[index], + path: names[index], + source: string + })); + callback(err, strings); + }); +} + +function loadFiles(opts, callback) { + // Build file extension pattern + let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; }); + extension = new RegExp('\\.' + extension + '$'); + + let ret = [], + queue = (opts.files || []).map((template) => ({template, root: opts.root})); + Async.whilst(() => queue.length, function(callback) { + let {template: path, root} = queue.shift(); + + fs.stat(path, function(err, stat) { + if (err) { + return callback(new Handlebars.Exception(`Unable to open template file "${path}"`)); + } + + if (stat.isDirectory()) { + opts.hasDirectory = true; + + fs.readdir(path, function(err, children) { + /* istanbul ignore next : Race condition that being too lazy to test */ + if (err) { + return callback(err); + } + children.forEach(function(file) { + let childPath = path + '/' + file; + + if (extension.test(childPath) || fs.statSync(childPath).isDirectory()) { + queue.push({template: childPath, root: root || path}); + } + }); + + callback(); + }); + } else { + fs.readFile(path, 'utf8', function(err, data) { + /* istanbul ignore next : Race condition that being too lazy to test */ + if (err) { + return callback(err); + } + + if (opts.bom && data.indexOf('\uFEFF') === 0) { + data = data.substring(1); + } + + // Clean the template name + let name = path; + if (!root) { + name = basename(name); + } else if (name.indexOf(root) === 0) { + name = name.substring(root.length + 1); + } + name = name.replace(extension, ''); + + ret.push({ + path: path, + name: name, + source: data + }); + + callback(); + }); + } + }); + }, + function(err) { + if (err) { + callback(err); + } else { + callback(undefined, ret); + } + }); +} + +module.exports.cli = function(opts) { + if (opts.version) { + console.log(Handlebars.VERSION); + return; + } + + if (!opts.templates.length && !opts.hasDirectory) { + throw new Handlebars.Exception('Must define at least one template or directory.'); + } + + if (opts.simple && opts.min) { + throw new Handlebars.Exception('Unable to minimize simple output'); + } + + const multiple = opts.templates.length !== 1 || opts.hasDirectory; + if (opts.simple && multiple) { + throw new Handlebars.Exception('Unable to output multiple templates in simple mode'); + } + + // Force simple mode if we have only one template and it's unnamed. + if (!opts.amd && !opts.commonjs && opts.templates.length === 1 + && !opts.templates[0].name) { + opts.simple = true; + } + + // Convert the known list into a hash + let known = {}; + if (opts.known && !Array.isArray(opts.known)) { + opts.known = [opts.known]; + } + if (opts.known) { + for (let i = 0, len = opts.known.length; i < len; i++) { + known[opts.known[i]] = true; + } + } + + const objectName = opts.partial ? 'Handlebars.partials' : 'templates'; + + let output = new SourceNode(); + if (!opts.simple) { + if (opts.amd) { + output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];'); + } else if (opts.commonjs) { + output.add('var Handlebars = require("' + opts.commonjs + '");'); + } else { + output.add('(function() {\n'); + } + output.add(' var template = Handlebars.template, templates = '); + if (opts.namespace) { + output.add(opts.namespace); + output.add(' = '); + output.add(opts.namespace); + output.add(' || '); + } + output.add('{};\n'); + } + + opts.templates.forEach(function(template) { + let options = { + knownHelpers: known, + knownHelpersOnly: opts.o + }; + + if (opts.map) { + options.srcName = template.path; + } + if (opts.data) { + options.data = true; + } + + let precompiled = Handlebars.precompile(template.source, options); + + // If we are generating a source map, we have to reconstruct the SourceNode object + if (opts.map) { + let consumer = new SourceMapConsumer(precompiled.map); + precompiled = SourceNode.fromStringWithSourceMap(precompiled.code, consumer); + } + + if (opts.simple) { + output.add([precompiled, '\n']); + } else { + if (!template.name) { + throw new Handlebars.Exception('Name missing for template'); + } + + if (opts.amd && !multiple) { + output.add('return '); + } + output.add([objectName, '[\'', template.name, '\'] = template(', precompiled, ');\n']); + } + }); + + // Output the content + if (!opts.simple) { + if (opts.amd) { + if (multiple) { + output.add(['return ', objectName, ';\n']); + } + output.add('});'); + } else if (!opts.commonjs) { + output.add('})();'); + } + } + + + if (opts.map) { + output.add('\n//# sourceMappingURL=' + opts.map + '\n'); + } + + output = output.toStringWithSourceMap(); + output.map = output.map + ''; + + if (opts.min) { + output = uglify.minify(output.code, { + fromString: true, + + outSourceMap: opts.map, + inSourceMap: JSON.parse(output.map) + }); + if (opts.map) { + output.code += '\n//# sourceMappingURL=' + opts.map + '\n'; + } + } + + if (opts.map) { + fs.writeFileSync(opts.map, output.map, 'utf8'); + } + output = output.code; + + if (opts.output) { + fs.writeFileSync(opts.output, output, 'utf8'); + } else { + console.log(output); + } +}; + +function arrayCast(value) { + value = value != null ? value : []; + if (!Array.isArray(value)) { + value = [value]; + } + return value; +} diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/README.md b/hm_sunwell/node_modules/handlebars/node_modules/source-map/README.md new file mode 100644 index 0000000..b7c6786 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/README.md @@ -0,0 +1,510 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +This library is written in the Asynchronous Module Definition format, and works +in the following environments: + +* Modern Browsers supporting ECMAScript 5 (either after the build, or with an + AMD loader such as RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Node + + $ npm install source-map + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should spew a bunch of stuff to stdout, and create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source. + +## Examples + +### Consuming a source map + +```js +var rawSourceMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: 'http://example.com/www/js/', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; + +var smc = new SourceMapConsumer(rawSourceMap); + +console.log(smc.sources); +// [ 'http://example.com/www/js/one.js', +// 'http://example.com/www/js/two.js' ] + +console.log(smc.originalPositionFor({ + line: 2, + column: 28 +})); +// { source: 'http://example.com/www/js/two.js', +// line: 2, +// column: 10, +// name: 'n' } + +console.log(smc.generatedPositionFor({ + source: 'http://example.com/www/js/two.js', + line: 2, + column: 10 +})); +// { line: 2, column: 28 } + +smc.eachMapping(function (m) { + // ... +}); +``` + +### Generating a source map + +In depth guide: +[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) + +#### With SourceNode (high level API) + +```js +function compile(ast) { + switch (ast.type) { + case 'BinaryExpression': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + [compile(ast.left), " + ", compile(ast.right)] + ); + case 'Literal': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + String(ast.value) + ); + // ... + default: + throw new Error("Bad AST"); + } +} + +var ast = parse("40 + 2", "add.js"); +console.log(compile(ast).toStringWithSourceMap({ + file: 'add.js' +})); +// { code: '40 + 2', +// map: [object SourceMapGenerator] } +``` + +#### With SourceMapGenerator (low level API) + +```js +var map = new SourceMapGenerator({ + file: "source-mapped.js" +}); + +map.addMapping({ + generated: { + line: 10, + column: 35 + }, + source: "foo.js", + original: { + line: 33, + column: 2 + }, + name: "christopher" +}); + +console.log(map.toString()); +// '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' +``` + +## API + +Get a reference to the module: + +```js +// NodeJS +var sourceMap = require('source-map'); + +// Browser builds +var sourceMap = window.sourceMap; + +// Inside Firefox +let sourceMap = {}; +Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); +``` + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: Optional. The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.computeColumnSpans() + +Compute the last column for each generated mapping. The last column is +inclusive. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +* `bias`: Either `SourceMapConsumer.GREATEST_LOWER_BOUND` or + `SourceMapConsumer.LEAST_UPPER_BOUND`. Specifies whether to return the closest + element that is smaller than or greater than the one we are searching for, + respectively, if the exact element cannot be found. Defaults to + `SourceMapConsumer.GREATEST_LOWER_BOUND`. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition) + +Returns all generated line and column information for the original source, line, +and column provided. If no column is provided, returns all mappings +corresponding to a either the line we are searching for or the next closest line +that has any mappings. Otherwise, returns all mappings corresponding to the +given line and either the column we are searching for or the next closest column +that has any offsets. + +The only argument is an object with the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: Optional. The column number in the original source. + +and an array of objects is returned, each with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.hasContentsOfAllSources() + +Return true if we have the embedded source content for every source listed in +the source map, false otherwise. + +In other words, if this method returns `true`, then `smc.sourceContentFor(s)` +will succeed for every source `s` in `smc.sources`. + +#### SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing]) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +If the source content for the given source is not found, then an error is +thrown. Optionally, pass `true` as the second param to have `null` returned +instead. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. Mappings have the + form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, + name }` + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator([startOfSourceMap]) + +You may pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: A root for all relative URLs in this source map. + +* `skipValidation`: Optional. When `true`, disables validation of mappings as + they are added. This can improve performance but should be used with + discretion, as a last resort. Even then, one should avoid using this flag when + running tests, if possible. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used, if it exists. + Otherwise an error will be thrown. + +* `sourceMapPath`: Optional. The dirname of the path to the SourceMap + to be applied. If relative, it is relative to the SourceMap. + + This parameter is needed when the two SourceMaps aren't in the same + directory, and the SourceMap to be applied contains relative source + paths. If so, those relative source paths need to be rewritten + relative to the SourceMap. + + If omitted, it is assumed that both SourceMaps are in the same directory, + thus not needing any rewriting. (Supplying `'.'` has the same effect.) + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode([line, column, source[, chunk[, name]]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename; null if no filename is provided. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath]) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +* `relativePath` The optional path that relative sources in `sourceMapConsumer` + should be relative to. + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap]) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + +```js +exports["test doing the foo bar"] = function (assert, util) { + ... +}; +``` + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/assert-shim.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/assert-shim.js new file mode 100644 index 0000000..daa1a62 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/mini-require.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/mini-require.js new file mode 100644 index 0000000..0daf453 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/prefix-source-map.jsm b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 0000000..209dbd7 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import("resource://gre/modules/devtools/Console.jsm"); +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/prefix-utils.jsm b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 0000000..80341d4 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-browser.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 0000000..fb29ff5 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-source-map.jsm b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 0000000..cf3c2d8 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-utils.jsm b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 0000000..b31b84c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/test-prefix.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/test-prefix.js new file mode 100644 index 0000000..1b13f30 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/test-suffix.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/test-suffix.js new file mode 100644 index 0000000..bec2de3 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map.js new file mode 100644 index 0000000..121ad24 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/array-set.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 0000000..19cb841 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,107 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ + ArraySet.prototype.size = function ArraySet_size() { + return Object.getOwnPropertyNames(this._set).length; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/base64-vlq.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 0000000..bbe9a58 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,146 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; + }; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/base64.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 0000000..35adbc1 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,73 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ + exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; + }; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/binary-search.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 0000000..7936f7e --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,117 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + exports.GREATEST_LOWER_BOUND = 1; + exports.LEAST_UPPER_BOUND = 2; + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } + + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } + + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ + exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } + + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } + + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } + + return index; + }; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/mapping-list.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/mapping-list.js new file mode 100644 index 0000000..01aff22 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/mapping-list.js @@ -0,0 +1,86 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + var mapping; + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/quick-sort.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/quick-sort.js new file mode 100644 index 0000000..e0551ed --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/quick-sort.js @@ -0,0 +1,120 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + // It turns out that some (most?) JavaScript engines don't self-host + // `Array.prototype.sort`. This makes sense because C++ will likely remain + // faster than JS when doing raw CPU-intensive sorting. However, when using a + // custom comparator function, calling back and forth between the VM's C++ and + // JIT'd JS is rather slow *and* loses JIT type information, resulting in + // worse generated code for the comparator function than would be optimal. In + // fact, when sorting with a comparator, these costs outweigh the benefits of + // sorting in C++. By using our own JS-implemented Quick Sort (below), we get + // a ~3500ms mean speed-up in `bench/bench.html`. + + /** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ + function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; + } + + /** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ + function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); + } + + /** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ + function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. + + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. + + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; + + swap(ary, pivotIndex, r); + var pivot = ary[r]; + + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); + } + } + + swap(ary, i + 1, j); + var q = i + 1; + + // (2) Recurse on each half. + + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } + } + + /** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ + exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); + }; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-map-consumer.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 0000000..cbdc467 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,1077 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + var quickSort = require('./quick-sort').quickSort; + + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); + } + + SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + SourceMapConsumer.GREATEST_LOWER_BOUND = 1; + SourceMapConsumer.LEAST_UPPER_BOUND = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; + + /** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; + } + needle.source = this._sources.indexOf(needle.source); + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } + } + + return mappings; + }; + + exports.SourceMapConsumer = SourceMapConsumer; + + /** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + sources = sources.map(util.normalize); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; + + /** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer + */ + BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); + } + + destGeneratedMappings.push(destMapping); + } + + quickSort(smc.__originalMappings, util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + BasicSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Provide the JIT with a nice shape / hidden class. + */ + function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; + } + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; + } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + str = aStr.slice(index, end); + + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + cachedSegments[str] = segment; + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } + } + } + + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; + + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); + } + if (!this._sources.has(source)) { + return { + line: null, + column: null, + lastColumn: null + }; + } + source = this._sources.indexOf(source); + + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + + /** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ + function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); + + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); + } + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); + + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) + } + }); + } + + IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; + + /** + * The version of the source mapping spec that we are consuming. + */ + IndexedSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); + } + }; + return sources; + } + }); + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[i]; + + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); + } + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.column + + (section.generatedOffset.generatedLine === mapping.generatedLine) + ? section.generatedOffset.generatedColumn - 1 + : 0, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; + + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } + }; + }; + + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; + + exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-map-generator.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 0000000..d8a9025 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,399 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + var MappingList = require('./mapping-list').MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name != null && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-node.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 0000000..9ee90bd --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,414 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are removed from this array, by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var shiftNextLine = function() { + var lineContents = remainingLines.shift(); + // The last line of a file might not have a newline. + var newLine = remainingLines.shift() || ""; + return lineContents + newLine; + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLines.length > 0) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/util.js b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 0000000..0b9d75d --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,370 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consequtive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = (path.charAt(0) === '/'); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; + } + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; + } + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); + } + exports.relative = relative; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + }; + exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + + function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; + } + + /** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ + function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; + +}); diff --git a/hm_sunwell/node_modules/handlebars/node_modules/source-map/package.json b/hm_sunwell/node_modules/handlebars/node_modules/source-map/package.json new file mode 100644 index 0000000..bef4547 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/node_modules/source-map/package.json @@ -0,0 +1,226 @@ +{ + "_args": [ + [ + "source-map@^0.4.4", + "/home/xor/shared_vm/git/node-sunwell/node_modules/handlebars" + ] + ], + "_from": "source-map@>=0.4.4 <0.5.0", + "_id": "source-map@0.4.4", + "_inCache": true, + "_installable": true, + "_location": "/handlebars/source-map", + "_npmUser": { + "email": "fitzgen@gmail.com", + "name": "nickfitzgerald" + }, + "_npmVersion": "1.4.9", + "_phantomChildren": {}, + "_requested": { + "name": "source-map", + "raw": "source-map@^0.4.4", + "rawSpec": "^0.4.4", + "scope": null, + "spec": ">=0.4.4 <0.5.0", + "type": "range" + }, + "_requiredBy": [ + "/handlebars" + ], + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "_shasum": "eba4f5da9c0dc999de68032d8b4f76173652036b", + "_shrinkwrap": null, + "_spec": "source-map@^0.4.4", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/handlebars", + "author": { + "email": "nfitzgerald@mozilla.com", + "name": "Nick Fitzgerald" + }, + "bugs": { + "url": "https://github.com/mozilla/source-map/issues" + }, + "contributors": [ + { + "name": "Hugh Kennedy", + "email": "hughskennedy@gmail.com" + }, + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + }, + { + "name": "Chase Douglas", + "email": "chase@newrelic.com" + }, + { + "name": "Evan Wallace", + "email": "evan.exe@gmail.com" + }, + { + "name": "Heather Arthur", + "email": "fayearthur@gmail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + }, + { + "name": "Simon Lydell", + "email": "simon.lydell@gmail.com" + }, + { + "name": "Jmeas Smith", + "email": "jellyes2@gmail.com" + }, + { + "name": "Michael Z Goddard", + "email": "mzgoddard@gmail.com" + }, + { + "name": "azu", + "email": "azu@users.noreply.github.com" + }, + { + "name": "John Gozde", + "email": "john@gozde.ca" + }, + { + "name": "Adam Kirkton", + "email": "akirkton@truefitinnovation.com" + }, + { + "name": "Chris Montgomery", + "email": "christopher.montgomery@dowjones.com" + }, + { + "name": "J. Ryan Stinnett", + "email": "jryans@gmail.com" + }, + { + "name": "Jack Herrington", + "email": "jherrington@walmartlabs.com" + }, + { + "name": "Chris Truter", + "email": "jeffpalentine@gmail.com" + }, + { + "name": "Daniel Espeset", + "email": "daniel@danielespeset.com" + }, + { + "name": "Jamie Wong", + "email": "jamie.lf.wong@gmail.com" + }, + { + "name": "Eddy Bruël", + "email": "ejpbruel@mozilla.com" + }, + { + "name": "Hawken Rives", + "email": "hawkrives@gmail.com" + }, + { + "name": "Gilad Peleg", + "email": "giladp007@gmail.com" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "description": "Generates and consumes source maps", + "devDependencies": { + "dryice": ">=0.4.8" + }, + "directories": { + "lib": "./lib" + }, + "dist": { + "shasum": "eba4f5da9c0dc999de68032d8b4f76173652036b", + "tarball": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" + }, + "engines": { + "node": ">=0.8.0" + }, + "files": [ + "build/", + "lib/" + ], + "homepage": "https://github.com/mozilla/source-map", + "license": "BSD-3-Clause", + "main": "./lib/source-map.js", + "maintainers": [ + { + "name": "mozilla-devtools", + "email": "mozilla-developer-tools@googlegroups.com" + }, + { + "name": "mozilla", + "email": "dherman@mozilla.com" + }, + { + "name": "nickfitzgerald", + "email": "fitzgen@gmail.com" + } + ], + "name": "source-map", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/mozilla/source-map.git" + }, + "scripts": { + "build": "node Makefile.dryice.js", + "test": "node test/run-tests.js" + }, + "version": "0.4.4" +} diff --git a/hm_sunwell/node_modules/handlebars/package.json b/hm_sunwell/node_modules/handlebars/package.json new file mode 100644 index 0000000..307b242 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/package.json @@ -0,0 +1,147 @@ +{ + "_args": [ + [ + "handlebars@^4.0.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul" + ] + ], + "_from": "handlebars@>=4.0.1 <5.0.0", + "_id": "handlebars@4.0.6", + "_inCache": true, + "_installable": true, + "_location": "/handlebars", + "_nodeVersion": "4.6.1", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/handlebars-4.0.6.tgz_1479000463304_0.9163416035007685" + }, + "_npmUser": { + "email": "lawnsea@gmail.com", + "name": "lawnsea" + }, + "_npmVersion": "2.15.9", + "_phantomChildren": { + "amdefine": "1.0.1" + }, + "_requested": { + "name": "handlebars", + "raw": "handlebars@^4.0.1", + "rawSpec": "^4.0.1", + "scope": null, + "spec": ">=4.0.1 <5.0.0", + "type": "range" + }, + "_requiredBy": [ + "/istanbul" + ], + "_resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.6.tgz", + "_shasum": "2ce4484850537f9c97a8026d5399b935c4ed4ed7", + "_shrinkwrap": null, + "_spec": "handlebars@^4.0.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul", + "author": { + "name": "Yehuda Katz" + }, + "barename": "handlebars", + "bin": { + "handlebars": "bin/handlebars" + }, + "bugs": { + "url": "https://github.com/wycats/handlebars.js/issues" + }, + "dependencies": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, + "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration", + "devDependencies": { + "aws-sdk": "^2.1.49", + "babel-loader": "^5.0.0", + "babel-runtime": "^5.1.10", + "benchmark": "~1.0", + "dustjs-linkedin": "^2.0.2", + "eco": "~1.1.0-rc-3", + "grunt": "~0.4.1", + "grunt-babel": "^5.0.0", + "grunt-cli": "~0.1.10", + "grunt-contrib-clean": "0.x", + "grunt-contrib-concat": "0.x", + "grunt-contrib-connect": "0.x", + "grunt-contrib-copy": "0.x", + "grunt-contrib-requirejs": "0.x", + "grunt-contrib-uglify": "0.x", + "grunt-contrib-watch": "0.x", + "grunt-eslint": "^17.1.0", + "grunt-saucelabs": "8.x", + "grunt-webpack": "^1.0.8", + "istanbul": "^0.3.0", + "jison": "~0.3.0", + "mocha": "~1.20.0", + "mock-stdin": "^0.3.0", + "mustache": "^2.1.3", + "semver": "^5.0.1", + "underscore": "^1.5.1", + "webpack": "^1.12.6", + "webpack-dev-server": "^1.12.1" + }, + "directories": {}, + "dist": { + "shasum": "2ce4484850537f9c97a8026d5399b935c4ed4ed7", + "tarball": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.6.tgz" + }, + "engines": { + "node": ">=0.4.7" + }, + "gitHead": "ad3037cf54132fc5f589134d3bef961a5f751973", + "homepage": "http://www.handlebarsjs.com/", + "jspm": { + "buildConfig": { + "minify": true + }, + "directories": { + "lib": "dist/amd" + }, + "main": "handlebars" + }, + "keywords": [ + "handlebars", + "html", + "mustache", + "template" + ], + "license": "MIT", + "main": "lib/index.js", + "maintainers": [ + { + "name": "erisds", + "email": "erisds@gmail.com" + }, + { + "name": "kpdecker", + "email": "kpdecker@gmail.com" + }, + { + "name": "lawnsea", + "email": "lawnsea@gmail.com" + }, + { + "name": "wycats", + "email": "wycats@gmail.com" + } + ], + "name": "handlebars", + "optionalDependencies": { + "uglify-js": "^2.6" + }, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/wycats/handlebars.js.git" + }, + "scripts": { + "test": "grunt" + }, + "version": "4.0.6" +} diff --git a/hm_sunwell/node_modules/handlebars/print-script b/hm_sunwell/node_modules/handlebars/print-script new file mode 100644 index 0000000..046b99c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/print-script @@ -0,0 +1,95 @@ +#! /usr/bin/env node +/* eslint-disable no-console, no-var */ +// Util script for debugging source code generation issues + +var script = process.argv[2].replace(/\\n/g, '\n'), + verbose = process.argv[3] === '-v'; + +var Handlebars = require('./lib'), + SourceMap = require('source-map'), + SourceMapConsumer = SourceMap.SourceMapConsumer; + +var template = Handlebars.precompile(script, { + srcName: 'input.hbs', + destName: 'output.js', + + assumeObjects: true, + compat: false, + strict: true, + trackIds: true, + knownHelpersOnly: false + }); + +if (!verbose) { + console.log(template); +} else { + var consumer = new SourceMapConsumer(template.map), + lines = template.code.split('\n'), + srcLines = script.split('\n'); + + console.log(); + console.log('Source:'); + srcLines.forEach(function(source, index) { + console.log(index + 1, source); + }); + console.log(); + console.log('Generated:'); + console.log(template.code); + lines.forEach(function(source, index) { + console.log(index + 1, source); + }); + console.log(); + console.log('Map:'); + console.log(template.map); + console.log(); + + function collectSource(lines, lineName, colName, order) { + var ret = {}, + ordered = [], + last; + + function collect(current) { + if (last) { + var mapLines = lines.slice(last[lineName] - 1, current && current[lineName]); + if (mapLines.length) { + if (current) { + mapLines[mapLines.length - 1] = mapLines[mapLines.length - 1].slice(0, current[colName]); + } + mapLines[0] = mapLines[0].slice(last[colName]); + } + ret[last[lineName] + ':' + last[colName]] = mapLines.join('\n'); + ordered.push({ + startLine: last[lineName], + startCol: last[colName], + endLine: current && current[lineName] + }); + } + last = current; + } + + consumer.eachMapping(collect, undefined, order); + collect(); + + return ret; + } + + srcLines = collectSource(srcLines, 'originalLine', 'originalColumn', SourceMapConsumer.ORIGINAL_ORDER); + lines = collectSource(lines, 'generatedLine', 'generatedColumn'); + + consumer.eachMapping(function(mapping) { + var originalSrc = srcLines[mapping.originalLine + ':' + mapping.originalColumn], + generatedSrc = lines[mapping.generatedLine + ':' + mapping.generatedColumn]; + + if (!mapping.originalLine) { + console.log('generated', mapping.generatedLine + ':' + mapping.generatedColumn, generatedSrc); + } else { + console.log('map', + mapping.source, + mapping.originalLine + ':' + mapping.originalColumn, + originalSrc, + '->', + mapping.generatedLine + ':' + mapping.generatedColumn, + generatedSrc); + } + }); +} diff --git a/hm_sunwell/node_modules/handlebars/release-notes.md b/hm_sunwell/node_modules/handlebars/release-notes.md new file mode 100644 index 0000000..8b073d5 --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/release-notes.md @@ -0,0 +1,483 @@ +# Release Notes + +## Development + +[Commits](https://github.com/lawnsea/handlebars.js/compare/v4.0.6...master) + +## v4.0.6 - November 12th, 2016 +- [#1243](https://github.com/wycats/handlebars.js/pull/1243) - Walk up data frames for nested @partial-block ([@lawnsea](https://github.com/lawnsea)) +- [#1210](https://github.com/wycats/handlebars.js/pull/1210) - Add a new lightweight package based on handlebars in the README ([@kabirbaidhya](https://github.com/kabirbaidhya)) +- [#1187](https://github.com/wycats/handlebars.js/pull/1187) - Ensure that existing blockParams and depths are respected on dupe programs ([@charleso](https://github.com/charleso)) +- [#1191](https://github.com/wycats/handlebars.js/pull/1191) - Added cory ([@leo](https://github.com/leo)) +- [#1177](https://github.com/wycats/handlebars.js/pull/1177) - Preserve License info in Closure Compiler ([@gennadiylitvinyuk](https://github.com/gennadiylitvinyuk)) +- [#1171](https://github.com/wycats/handlebars.js/pull/1171) - Contributing doc fix: failing thats -> failing tests ([@paulfalgout](https://github.com/paulfalgout)) +- [#1166](https://github.com/wycats/handlebars.js/pull/1166) - Update license date ([@timwangdev](https://github.com/timwangdev)) +- Update jsfiddle to point to latest - 959ee55 (originally dfc7554 by [@kpdecker](https://github.com/kpdecker)) +- [#1163](https://github.com/wycats/handlebars.js/pull/1163) - Fix typos on decorators-api.md. ([@adjohnson916](https://github.com/adjohnson916)) +- Drop extra Error params - 8c19874 (originally 63fdb92 by [@kpdecker](https://github.com/kpdecker)) +- [#1153](https://github.com/wycats/handlebars.js/pull/1153) - Add documentation for running tests to contributing.md ([@ryanmurakami](https://github.com/ryanmurakami)) +- Avoid error in older browsers in test - 400916c (originally a6121ca by [@kpdecker](https://github.com/kpdecker)) +- Update target browser test versions - fee2334 (originally 871c32a by [@kpdecker](https://github.com/kpdecker)) +- Exclude coverage check in exception conditional - 32d6363 (originally 326734b by [@kpdecker](https://github.com/kpdecker)) +- Fix throw when creating exception object in Safari - 20c965c (originally 2ea6119 by [@kpdecker](https://github.com/kpdecker)) +- Update build for modern node versions - 6c9f98c (originally 8289c0b by [@kpdecker](https://github.com/kpdecker)) +- [#1135](https://github.com/wycats/handlebars.js/issues/1135) - Relax depth check for context push - c393c81 (originally 25458fd by [@kpdecker](https://github.com/kpdecker)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.5...v4.0.6) + +## v4.0.5 - November 19th, 2015 +- [#1132](https://github.com/wycats/handlebars.js/pull/1132) - Update uglify-js to avoid vulnerability ([@plynchnlm](https://api.github.com/users/plynchnlm)) +- [#1129](https://github.com/wycats/handlebars.js/issues/1129) - Minified lib returns an empty string ([@bricss](https://api.github.com/users/bricss)) +- Return current handlebars instance from noConflict - 685cf92 +- Add webpack to dev dependency to support npm 3 - 7a6c228 +- Further relax uglify dependency - 0a3b3c2 +- Include tests for minimized artifacts - c21118d +- Fix lint errors under latest eslint - 9f59de9 +- Add print-script helper script - 98a6717 + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.4...v4.0.5) + +## v4.0.4 - October 29th, 2015 +- [#1121](https://github.com/wycats/handlebars.js/pull/1121) - Include partial name in 'undefined partial' exception message ([@shinypb](https://api.github.com/users/shinypb)) +- [#1125](https://github.com/wycats/handlebars.js/pull/1125) - Add promised-handlebars to "in-the-wild"-list ([@nknapp](https://api.github.com/users/nknapp)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.3...v4.0.4) + +## v4.0.3 - September 23rd, 2015 +- [#1099](https://github.com/wycats/handlebars.js/issues/1099) - @partial-block is overridden ([@btmorex](https://api.github.com/users/btmorex)) +- [#1093](https://github.com/wycats/handlebars.js/issues/1093) - #each skips iteration on undefined values ([@florianpilz](https://api.github.com/users/florianpilz)) +- [#1092](https://github.com/wycats/handlebars.js/issues/1092) - Square braces in key name ([@distantnative](https://api.github.com/users/distantnative)) +- [#1091](https://github.com/wycats/handlebars.js/pull/1091) - fix typo in release notes ([@nikolas](https://api.github.com/users/nikolas)) +- [#1090](https://github.com/wycats/handlebars.js/pull/1090) - grammar fixes in 4.0.0 release notes ([@nikolas](https://api.github.com/users/nikolas)) + +Compatibility notes: +- `each` iteration with `undefined` values has been restored to the 3.0 behaviors. Helper calls with undefined context values will now execute against an arbitrary empty object to avoid executing against global object in non-strict mode. +- `]` can now be included in `[]` wrapped identifiers by escaping with `\`. Any `[]` identifiers that include `\` will now have to properly escape these values. + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.2...v4.0.3) + +## v4.0.2 - September 4th, 2015 +- [#1089](https://github.com/wycats/handlebars.js/issues/1089) - "Failover content" not working in multiple levels of inline partials ([@michaellopez](https://api.github.com/users/michaellopez)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.1...v4.0.2) + +## v4.0.1 - September 2nd, 2015 +- Fix failure when using decorators in partials - 05b82a2 + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.0...v4.0.1) + +## v4.0.0 - September 1st, 2015 +- [#1082](https://github.com/wycats/handlebars.js/pull/1082) - Decorators and Inline Partials ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#1076](https://github.com/wycats/handlebars.js/pull/1076) - Implement partial blocks ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#1087](https://github.com/wycats/handlebars.js/pull/1087) - Fix #each when last object entry has empty key ([@denniskuczynski](https://api.github.com/users/denniskuczynski)) +- [#1084](https://github.com/wycats/handlebars.js/pull/1084) - Bump uglify version to fix vulnerability ([@John-Steidley](https://api.github.com/users/John-Steidley)) +- [#1068](https://github.com/wycats/handlebars.js/pull/1068) - Fix typo ([@0xack13](https://api.github.com/users/0xack13)) +- [#1060](https://github.com/wycats/handlebars.js/pull/1060) - #1056 Fixed grammar for nested raw blocks ([@ericbn](https://api.github.com/users/ericbn)) +- [#1052](https://github.com/wycats/handlebars.js/pull/1052) - Updated year in License ([@maqnouch](https://api.github.com/users/maqnouch)) +- [#1037](https://github.com/wycats/handlebars.js/pull/1037) - Fix minor typos in README ([@tomxtobin](https://api.github.com/users/tomxtobin)) +- [#1032](https://github.com/wycats/handlebars.js/issues/1032) - Is it possible to render a partial without the parent scope? ([@aputinski](https://api.github.com/users/aputinski)) +- [#1019](https://github.com/wycats/handlebars.js/pull/1019) - Fixes typo in tests ([@aymerick](https://api.github.com/users/aymerick)) +- [#1016](https://github.com/wycats/handlebars.js/issues/1016) - Version mis-match ([@mayankdedhia](https://api.github.com/users/mayankdedhia)) +- [#1023](https://github.com/wycats/handlebars.js/issues/1023) - is it possible for nested custom helpers to communicate between each other? +- [#893](https://github.com/wycats/handlebars.js/issues/893) - [Proposal] Section blocks. +- [#792](https://github.com/wycats/handlebars.js/issues/792) - feature request: inline partial definitions +- [#583](https://github.com/wycats/handlebars.js/issues/583) - Parent path continues to drill down depth with multiple conditionals +- [#404](https://github.com/wycats/handlebars.js/issues/404) - Add named child helpers that can be referenced by block helpers +- Escape = in HTML content - [83b8e84](https://github.com/wycats/handlebars.js/commit/83b8e84) +- Drop AST constructors in favor of JSON - [95d84ba](https://github.com/wycats/handlebars.js/commit/95d84ba) +- Pass container rather than exec as context - [9a2d1d6](https://github.com/wycats/handlebars.js/commit/9a2d1d6) +- Add ignoreStandalone compiler option - [ea3a5a1](https://github.com/wycats/handlebars.js/commit/ea3a5a1) +- Ignore empty when iterating on sparse arrays - [06d515a](https://github.com/wycats/handlebars.js/commit/06d515a) +- Add support for string and stdin precompilation - [0de8dac](https://github.com/wycats/handlebars.js/commit/0de8dac) +- Simplify object assignment generation logic - [77e6bfc](https://github.com/wycats/handlebars.js/commit/77e6bfc) +- Bulletproof AST.helpers.helperExpression - [93b0760](https://github.com/wycats/handlebars.js/commit/93b0760) +- Always return string responses - [8e868ab](https://github.com/wycats/handlebars.js/commit/8e868ab) +- Pass undefined fields to helpers in strict mode - [5d4b8da](https://github.com/wycats/handlebars.js/commit/5d4b8da) +- Avoid depth creation when context remains the same - [279e038](https://github.com/wycats/handlebars.js/commit/279e038) +- Improve logging API - [9a49d35](https://github.com/wycats/handlebars.js/commit/9a49d35) +- Fix with operator in no @data mode - [231a8d7](https://github.com/wycats/handlebars.js/commit/231a8d7) +- Allow empty key name in each iteration - [1bb640b](https://github.com/wycats/handlebars.js/commit/1bb640b) +- Add with block parameter support - [2a85106](https://github.com/wycats/handlebars.js/commit/2a85106) +- Fix escaping of non-javascript identifiers - [410141c](https://github.com/wycats/handlebars.js/commit/410141c) +- Fix location information for programs - [93faffa](https://github.com/wycats/handlebars.js/commit/93faffa) + +Compatibility notes: +- Depthed paths are now conditionally pushed on to the stack. If the helper uses the same context, then a new stack is not created. This leads to behavior that better matches expectations for helpers like `if` that do not seem to alter the context. Any instances of `../` in templates will need to be checked for the correct behavior under 4.0.0. In general templates will either reduce the number of `../` instances or leave them as is. See [#1028](https://github.com/wycats/handlebars.js/issues/1028). +- The `=` character is now HTML escaped. This closes a potential exploit case when using unquoted attributes, i.e. `
`. In general it's recommended that attributes always be quoted when their values are generated from a mustache to avoid any potential exploit surfaces. +- AST constructors have been dropped in favor of plain old javascript objects +- The runtime version has been increased. Precompiled templates will need to use runtime of at least 4.0.0. + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.3...v4.0.0) + +## v3.0.3 - April 28th, 2015 +- [#1004](https://github.com/wycats/handlebars.js/issues/1004) - Latest version breaks with RequireJS (global is undefined) ([@boskee](https://api.github.com/users/boskee)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.2...v3.0.3) + +## v3.0.2 - April 20th, 2015 +- [#998](https://github.com/wycats/handlebars.js/pull/998) - Add full support for es6 ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#994](https://github.com/wycats/handlebars.js/issues/994) - Access Handlebars.Visitor in browser ([@tamlyn](https://api.github.com/users/tamlyn)) +- [#990](https://github.com/wycats/handlebars.js/issues/990) - Allow passing null/undefined literals subexpressions ([@blimmer](https://api.github.com/users/blimmer)) +- [#989](https://github.com/wycats/handlebars.js/issues/989) - Source-map error with requirejs ([@SteppeEagle](https://api.github.com/users/SteppeEagle)) +- [#967](https://github.com/wycats/handlebars.js/issues/967) - can't access "this" property ([@75lb](https://api.github.com/users/75lb)) +- Use captureStackTrace for error handler - a009a97 +- Ignore branches tested without coverage monitoring - 37a664b + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.1...v3.0.2) + +## v3.0.1 - March 24th, 2015 +- [#984](https://github.com/wycats/handlebars.js/pull/984) - Adding documentation for passing arguments into partials ([@johneke](https://api.github.com/users/johneke)) +- [#973](https://github.com/wycats/handlebars.js/issues/973) - version 3 is slower than version 2 ([@elover](https://api.github.com/users/elover)) +- [#966](https://github.com/wycats/handlebars.js/issues/966) - "handlebars --version" does not work with v3.0.0 ([@abloomston](https://api.github.com/users/abloomston)) +- [#964](https://github.com/wycats/handlebars.js/pull/964) - default is a reserved word ([@grassick](https://api.github.com/users/grassick)) +- [#962](https://github.com/wycats/handlebars.js/pull/962) - Add dashbars' link on README. ([@pismute](https://api.github.com/users/pismute)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.0...v3.0.1) + +## v3.0.0 - February 10th, 2015 +- [#941](https://github.com/wycats/handlebars.js/pull/941) - Add support for dynamic partial names ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#940](https://github.com/wycats/handlebars.js/pull/940) - Add missing reserved words so compiler knows to use array syntax: ([@mattflaschen](https://api.github.com/users/mattflaschen)) +- [#938](https://github.com/wycats/handlebars.js/pull/938) - Fix example using #with helper ([@diwo](https://api.github.com/users/diwo)) +- [#930](https://github.com/wycats/handlebars.js/pull/930) - Add parent tracking and mutation to AST visitors ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#926](https://github.com/wycats/handlebars.js/issues/926) - Depthed lookups fail when program duplicator runs ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#918](https://github.com/wycats/handlebars.js/pull/918) - Add instructions for 'spec/mustache' to CONTRIBUTING.md, fix a few typos ([@oneeman](https://api.github.com/users/oneeman)) +- [#915](https://github.com/wycats/handlebars.js/pull/915) - Ast update ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#910](https://github.com/wycats/handlebars.js/issues/910) - Different behavior of {{@last}} when {{#each}} in {{#each}} ([@zordius](https://api.github.com/users/zordius)) +- [#907](https://github.com/wycats/handlebars.js/issues/907) - Implement named helper variable references ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#906](https://github.com/wycats/handlebars.js/pull/906) - Add parser support for block params ([@mmun](https://api.github.com/users/mmun)) +- [#903](https://github.com/wycats/handlebars.js/issues/903) - Only provide aliases for multiple use calls ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#902](https://github.com/wycats/handlebars.js/pull/902) - Generate Source Maps ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#901](https://github.com/wycats/handlebars.js/issues/901) - Still escapes with noEscape enabled on isolated Handlebars environment ([@zedknight](https://api.github.com/users/zedknight)) +- [#896](https://github.com/wycats/handlebars.js/pull/896) - Simplify BlockNode by removing intermediate MustacheNode ([@mmun](https://api.github.com/users/mmun)) +- [#892](https://github.com/wycats/handlebars.js/pull/892) - Implement parser for else chaining of helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#889](https://github.com/wycats/handlebars.js/issues/889) - Consider extensible parser API ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#887](https://github.com/wycats/handlebars.js/issues/887) - Handlebars.noConflict() option? ([@bradvogel](https://api.github.com/users/bradvogel)) +- [#886](https://github.com/wycats/handlebars.js/issues/886) - Add SafeString to context (or use duck-typing) ([@dominicbarnes](https://api.github.com/users/dominicbarnes)) +- [#870](https://github.com/wycats/handlebars.js/pull/870) - Registering undefined partial throws exception. ([@max-b](https://api.github.com/users/max-b)) +- [#866](https://github.com/wycats/handlebars.js/issues/866) - comments don't respect whitespace control ([@75lb](https://api.github.com/users/75lb)) +- [#863](https://github.com/wycats/handlebars.js/pull/863) - + jsDelivr CDN info ([@tomByrer](https://api.github.com/users/tomByrer)) +- [#858](https://github.com/wycats/handlebars.js/issues/858) - Disable new default auto-indent at included partials ([@majodev](https://api.github.com/users/majodev)) +- [#856](https://github.com/wycats/handlebars.js/pull/856) - jspm compatibility ([@MajorBreakfast](https://api.github.com/users/MajorBreakfast)) +- [#805](https://github.com/wycats/handlebars.js/issues/805) - Request: "strict" lookups ([@nzakas](https://api.github.com/users/nzakas)) + +- Export the default object for handlebars/runtime - 5594416 +- Lookup partials when undefined - 617dd57 + +Compatibility notes: +- Runtime breaking changes. Must match 3.x runtime and precompiler. +- The AST has been upgraded to a public API. + - There are a number of changes to this, but the format is now documented in docs/compiler-api.md + - The Visitor API has been expanded to support mutation and provide a base implementation +- The `JavaScriptCompiler` APIs have been formalized and documented. As part of the sourcemap handling these should be updated to return arrays for concatenation. +- `JavaScriptCompiler.namespace` has been removed as it was unused. +- `SafeString` is now duck typed on `toHTML` + +New Features: +- noConflict +- Source Maps +- Block Params +- Strict Mode +- @last and other each changes +- Chained else blocks +- @data methods can now have helper parameters passed to them +- Dynamic partials + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0...v3.0.0) + +## v2.0.0 - September 1st, 2014 +- Update jsfiddle to 2.0.0-beta.1 - 0670f65 +- Add contrib note regarding handlebarsjs.com docs - 4d17e3c +- Play nice with gemspec version numbers - 64d5481 + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-beta.1...v2.0.0) + +## v2.0.0-beta.1 - August 26th, 2014 +- [#787](https://github.com/wycats/handlebars.js/pull/787) - Remove whitespace surrounding standalone statements ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#827](https://github.com/wycats/handlebars.js/issues/827) - Render false literal as “false” ([@scoot557](https://api.github.com/users/scoot557)) +- [#767](https://github.com/wycats/handlebars.js/issues/767) - Subexpressions bug with hash and context ([@evensoul](https://api.github.com/users/evensoul)) +- Changes to 0/undefined handling + - [#731](https://github.com/wycats/handlebars.js/pull/731) - Strange behavior for {{#foo}} {{bar}} {{/foo}} when foo is 0 ([@kpdecker](https://api.github.com/users/kpdecker)) + - [#820](https://github.com/wycats/handlebars.js/issues/820) - strange behavior for {{foo.bar}} when foo is 0 or null or false ([@zordius](https://api.github.com/users/zordius)) + - [#837](https://github.com/wycats/handlebars.js/issues/837) - Strange input for custom helper ( foo.bar == false when foo is undefined ) ([@zordius](https://api.github.com/users/zordius)) +- [#819](https://github.com/wycats/handlebars.js/pull/819) - Implement recursive field lookup ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#764](https://github.com/wycats/handlebars.js/issues/764) - This reference not working for helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#773](https://github.com/wycats/handlebars.js/issues/773) - Implicit parameters in {{#each}} introduces a peculiarity in helpers calling convention ([@Bertrand](https://api.github.com/users/Bertrand)) +- [#783](https://github.com/wycats/handlebars.js/issues/783) - helperMissing and consistency for different expression types ([@ErisDS](https://api.github.com/users/ErisDS)) +- [#795](https://github.com/wycats/handlebars.js/pull/795) - Turn the precompile script into a wrapper around a module. ([@jwietelmann](https://api.github.com/users/jwietelmann)) +- [#823](https://github.com/wycats/handlebars.js/pull/823) - Support inverse sections on the with helper ([@dan-manges](https://api.github.com/users/dan-manges)) +- [#834](https://github.com/wycats/handlebars.js/pull/834) - Refactor blocks, programs and inverses ([@mmun](https://api.github.com/users/mmun)) +- [#852](https://github.com/wycats/handlebars.js/issues/852) - {{foo~}} space control behavior is different from older version ([@zordius](https://api.github.com/users/zordius)) +- [#835](https://github.com/wycats/handlebars.js/issues/835) - Templates overwritten if file is loaded twice + +- Expose escapeExpression on the root object - 980c38c +- Remove nested function eval in blockHelperMissing - 6f22ec1 +- Fix compiler program de-duping - 9e3f824 + +Compatibility notes: +- The default build now outputs a generic UMD wrapper. This should be transparent change but may cause issues in some environments. +- Runtime compatibility breaks in both directions. Ensure that both compiler and client are upgraded to 2.0.0-beta.1 or higher at the same time. + - `programWithDepth` has been removed an instead an array of context values is passed to fields needing depth lookups. +- `false` values are now printed to output rather than silently dropped +- Lines containing only block statements and whitespace are now removed. This matches the Mustache spec but may cause issues with code that expects whitespace to exist but would not otherwise. +- Partials that are standalone will now indent their rendered content +- `AST.ProgramNode`'s signature has changed. +- Numerious methods/features removed from psuedo-API classes + - `JavaScriptCompiler.register` + - `JavaScriptCompiler.replaceStack` no longer supports non-inline replace + - `Compiler.disassemble` + - `DECLARE` opcode + - `strip` opcode + - `lookup` opcode + - Content nodes may have their `string` values mutated over time. `original` field provides the unmodified value. +- Removed unused `Handlebars.registerHelper` `inverse` parameter +- `each` helper requires iterator parameter + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.4...v2.0.0-beta.1) + +## v2.0.0-alpha.4 - May 19th, 2014 +- Expose setup wrappers for compiled templates - 3638874 + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.3...v2.0.0-alpha.4) + +## v2.0.0-alpha.3 - May 19th, 2014 +- [#797](https://github.com/wycats/handlebars.js/pull/797) - Pass full helper ID to helperMissing when options are provided ([@tomdale](https://api.github.com/users/tomdale)) +- [#793](https://github.com/wycats/handlebars.js/pull/793) - Ensure isHelper is coerced to a boolean ([@mmun](https://api.github.com/users/mmun)) +- Refactor template init logic - 085e5e1 + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.2...v2.0.0-alpha.3) + +## v2.0.0-alpha.2 - March 6th, 2014 +- [#756](https://github.com/wycats/handlebars.js/pull/756) - fix bug in IE<=8 (no Array::map), closes #751 ([@jenseng](https://api.github.com/users/jenseng)) +- [#749](https://github.com/wycats/handlebars.js/pull/749) - properly handle multiple subexpressions in the same hash, fixes #748 ([@jenseng](https://api.github.com/users/jenseng)) +- [#743](https://github.com/wycats/handlebars.js/issues/743) - subexpression confusion/problem? ([@waynedpj](https://api.github.com/users/waynedpj)) +- [#746](https://github.com/wycats/handlebars.js/issues/746) - [CLI] support `handlebars --version` ([@apfelbox](https://api.github.com/users/apfelbox)) +- [#747](https://github.com/wycats/handlebars.js/pull/747) - updated grunt-saucelabs, failing tests revealed ([@Jonahss](https://api.github.com/users/Jonahss)) +- Make JSON a requirement for the compiler. - 058c0fb +- Temporarily kill the AWS publish CI step - 8347ee2 + +Compatibility notes: +- A JSON polyfill is required to run the compiler under IE8 and below. It's recommended that the precompiler be used in lieu of running the compiler on these legacy environments. + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.1...v2.0.0-alpha.2) + +## v2.0.0-alpha.1 - February 10th, 2014 +- [#182](https://github.com/wycats/handlebars.js/pull/182) - Allow passing hash parameters to partials ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#392](https://github.com/wycats/handlebars.js/pull/392) - Access to root context in partials and helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#472](https://github.com/wycats/handlebars.js/issues/472) - Helpers cannot have decimal parameters ([@kayleg](https://api.github.com/users/kayleg)) +- [#569](https://github.com/wycats/handlebars.js/pull/569) - Unable to lookup array values using @index ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#491](https://github.com/wycats/handlebars.js/pull/491) - For nested helpers: get the @ variables of the outer helper from the inner one ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#669](https://github.com/wycats/handlebars.js/issues/669) - Ability to unregister a helper ([@dbachrach](https://api.github.com/users/dbachrach)) +- [#730](https://github.com/wycats/handlebars.js/pull/730) - Raw block helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#634](https://github.com/wycats/handlebars.js/pull/634) - It would be great to have the helper name passed to `blockHelperMissing` ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#729](https://github.com/wycats/handlebars.js/pull/729) - Convert template spec to object literal ([@kpdecker](https://api.github.com/users/kpdecker)) + +- [#658](https://github.com/wycats/handlebars.js/issues/658) - Depthed helpers do not work after an upgrade from 1.0.0 ([@xibxor](https://api.github.com/users/xibxor)) +- [#671](https://github.com/wycats/handlebars.js/issues/671) - Crashes on no-parameter {{#each}} ([@stepancheg](https://api.github.com/users/stepancheg)) +- [#689](https://github.com/wycats/handlebars.js/issues/689) - broken template precompilation ([@AAS](https://api.github.com/users/AAS)) +- [#698](https://github.com/wycats/handlebars.js/pull/698) - Fix parser generation under windows ([@osiris43](https://api.github.com/users/osiris43)) +- [#699](https://github.com/wycats/handlebars.js/issues/699) - @DATA not compiles to invalid JS in stringParams mode ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#705](https://github.com/wycats/handlebars.js/issues/705) - 1.3.0 can not be wrapped in an IIFE ([@craigteegarden](https://api.github.com/users/craigteegarden)) +- [#706](https://github.com/wycats/handlebars.js/pull/706) - README: Use with helper instead of relying on blockHelperMissing ([@scottgonzalez](https://api.github.com/users/scottgonzalez)) + +- [#700](https://github.com/wycats/handlebars.js/pull/700) - Remove redundant conditions ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#704](https://github.com/wycats/handlebars.js/pull/704) - JavaScript Compiler Cleanup ([@blakeembrey](https://api.github.com/users/blakeembrey)) + +Compatibility notes: +- `helperMissing` helper no longer has the indexed name argument. Helper name is now available via `options.name`. +- Precompiler output has changed, which breaks compatibility with prior versions of the runtime and precompiled output. +- `JavaScriptCompiler.compilerInfo` now returns generic objects rather than javascript source. +- AST changes + - INTEGER -> NUMBER + - Additional PartialNode hash parameter + - New RawBlockNode type +- Data frames now have a `_parent` field. This is internal but is enumerable for performance/compatibility reasons. + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.3.0...v2.0.0-alpha.1) + +## v1.3.0 - January 1st, 2014 +- [#690](https://github.com/wycats/handlebars.js/pull/690) - Added support for subexpressions ([@machty](https://api.github.com/users/machty)) +- [#696](https://github.com/wycats/handlebars.js/pull/696) - Fix for reserved keyword "default" ([@nateirwin](https://api.github.com/users/nateirwin)) +- [#692](https://github.com/wycats/handlebars.js/pull/692) - add line numbers to nodes when parsing ([@fivetanley](https://api.github.com/users/fivetanley)) +- [#695](https://github.com/wycats/handlebars.js/pull/695) - Pull options out from param setup to allow easier extension ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#694](https://github.com/wycats/handlebars.js/pull/694) - Make the environment reusable ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#636](https://github.com/wycats/handlebars.js/issues/636) - Print line and column of errors ([@sgronblo](https://api.github.com/users/sgronblo)) +- Use literal for data lookup - c1a93d3 +- Add stack handling sanity checks - cd885bf +- Fix stack id "leak" on replaceStack - ddfe457 +- Fix incorrect stack pop when replacing literals - f4d337d + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.2.1...v1.3.0) + +## v1.2.1 - December 26th, 2013 +- [#684](https://github.com/wycats/handlebars.js/pull/684) - Allow any number of trailing characters for valid JavaScript variable ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#686](https://github.com/wycats/handlebars.js/pull/686) - Falsy AMD module names in version 1.2.0 ([@kpdecker](https://api.github.com/users/kpdecker)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.2.0...v1.2.1) + +## v1.2.0 - December 23rd, 2013 +- [#675](https://github.com/wycats/handlebars.js/issues/675) - Cannot compile empty template for partial ([@erwinw](https://api.github.com/users/erwinw)) +- [#677](https://github.com/wycats/handlebars.js/issues/677) - Triple brace statements fail under IE ([@hamzaCM](https://api.github.com/users/hamzaCM)) +- [#655](https://github.com/wycats/handlebars.js/issues/655) - Loading Handlebars using bower ([@niki4810](https://api.github.com/users/niki4810)) +- [#657](https://github.com/wycats/handlebars.js/pull/657) - Fixes issue where cli compiles non handlebars templates ([@chrishoage](https://api.github.com/users/chrishoage)) +- [#681](https://github.com/wycats/handlebars.js/pull/681) - Adds in-browser testing and Saucelabs CI ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#661](https://github.com/wycats/handlebars.js/pull/661) - Add @first and @index to #each object iteration ([@cgp](https://api.github.com/users/cgp)) +- [#650](https://github.com/wycats/handlebars.js/pull/650) - Handlebars is MIT-licensed ([@thomasboyt](https://api.github.com/users/thomasboyt)) +- [#641](https://github.com/wycats/handlebars.js/pull/641) - Document ember testing process ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#662](https://github.com/wycats/handlebars.js/issues/662) - handlebars-source 1.1.2 is missing from RubyGems. +- [#656](https://github.com/wycats/handlebars.js/issues/656) - Expose COMPILER_REVISION checks as a hook ([@machty](https://api.github.com/users/machty)) +- [#668](https://github.com/wycats/handlebars.js/issues/668) - Consider publishing handlebars-runtime as a separate module on npm ([@dlmanning](https://api.github.com/users/dlmanning)) +- [#679](https://github.com/wycats/handlebars.js/issues/679) - Unable to override invokePartial ([@mattbrailsford](https://api.github.com/users/mattbrailsford)) +- [#646](https://github.com/wycats/handlebars.js/pull/646) - Fix "\\{{" immediately following "\{{" ([@dmarcotte](https://api.github.com/users/dmarcotte)) +- Allow extend to work with non-prototyped objects - eb53f2e +- Add JavascriptCompiler public API tests - 1a751b2 +- Add AST test coverage for more complex paths - ddea5be +- Fix handling of boolean escape in MustacheNode - b4968bb + +Compatibility notes: +- `@index` and `@first` are now supported for `each` iteration on objects +- `Handlebars.VM.checkRevision` and `Handlebars.JavaScriptCompiler.prototype.compilerInfo` now available to modify the version checking behavior. +- Browserify users may link to the runtime library via `require('handlebars/runtime')` + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.2...v1.2.0) + +## v1.1.2 - November 5th, 2013 + +- [#645](https://github.com/wycats/handlebars.js/issues/645) - 1.1.1 fails under IE8 ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#644](https://github.com/wycats/handlebars.js/issues/644) - Using precompiled templates (AMD mode) with handlebars.runtime 1.1.1 ([@fddima](https://api.github.com/users/fddima)) + +- Add simple binary utility tests - 96a45a4 +- Fix empty string compilation - eea708a + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.1...v1.1.2) + +## v1.1.1 - November 4th, 2013 + +- [#642](https://github.com/wycats/handlebars.js/issues/642) - handlebars 1.1.0 are broken with nodejs + +- Fix release notes link - 17ba258 + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.0...v1.1.1) + +## v1.1.0 - November 3rd, 2013 + +- [#628](https://github.com/wycats/handlebars.js/pull/628) - Convert code to ES6 modules ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#336](https://github.com/wycats/handlebars.js/pull/336) - Add whitespace control syntax ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#535](https://github.com/wycats/handlebars.js/pull/535) - Fix for probable JIT error under Safari ([@sorentwo](https://api.github.com/users/sorentwo)) +- [#483](https://github.com/wycats/handlebars.js/issues/483) - Add first and last @ vars to each helper ([@denniskuczynski](https://api.github.com/users/denniskuczynski)) +- [#557](https://github.com/wycats/handlebars.js/pull/557) - `\\{{foo}}` escaping only works in some situations ([@dmarcotte](https://api.github.com/users/dmarcotte)) +- [#552](https://github.com/wycats/handlebars.js/pull/552) - Added BOM removal flag. ([@blessenm](https://api.github.com/users/blessenm)) +- [#543](https://github.com/wycats/handlebars.js/pull/543) - publish passing master builds to s3 ([@fivetanley](https://api.github.com/users/fivetanley)) + +- [#608](https://github.com/wycats/handlebars.js/issues/608) - Add `includeZero` flag to `if` conditional +- [#498](https://github.com/wycats/handlebars.js/issues/498) - `Handlebars.compile` fails on empty string although a single blank works fine +- [#599](https://github.com/wycats/handlebars.js/issues/599) - lambda helpers only receive options if used with arguments +- [#592](https://github.com/wycats/handlebars.js/issues/592) - Optimize array and subprogram performance +- [#571](https://github.com/wycats/handlebars.js/issues/571) - uglify upgrade breaks compatibility with older versions of node +- [#587](https://github.com/wycats/handlebars.js/issues/587) - Partial inside partial breaks? + + +Compatibility notes: +- The project now includes separate artifacts for AMD, CommonJS, and global objects. + - AMD: Users may load the bundled `handlebars.amd.js` or `handlebars.runtime.amd.js` files or load individual modules directly. AMD users should also note that the handlebars object is exposed via the `default` field on the imported object. This [gist](https://gist.github.com/wycats/7417be0dc361a69d5916) provides some discussion of possible compatibility shims. + - CommonJS/Node: Node loading occurs as normal via `require` + - Globals: The `handlebars.js` and `handlebars.runtime.js` files should behave in the same manner as the v1.0.12 / 1.0.0 release. +- Build artifacts have been removed from the repository. [npm][npm], [components/handlebars.js][components], [cdnjs][cdnjs], or the [builds page][builds-page] should now be used as the source of built artifacts. +- Context-stored helpers are now always passed the `options` hash. Previously no-argument helpers did not have this argument. + + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.12...v1.1.0) + +## v1.0.12 / 1.0.0 - May 31 2013 + +- [#515](https://github.com/wycats/handlebars.js/issues/515) - Add node require extensions support ([@jjclark1982](https://github.com/jjclark1982)) +- [#517](https://github.com/wycats/handlebars.js/issues/517) - Fix amd precompiler output with directories ([@blessenm](https://github.com/blessenm)) +- [#433](https://github.com/wycats/handlebars.js/issues/433) - Add support for unicode ids +- [#469](https://github.com/wycats/handlebars.js/issues/469) - Add support for `?` in ids +- [#534](https://github.com/wycats/handlebars.js/issues/534) - Protect from object prototype modifications +- [#519](https://github.com/wycats/handlebars.js/issues/519) - Fix partials with . name ([@jamesgorrie](https://github.com/jamesgorrie)) +- [#519](https://github.com/wycats/handlebars.js/issues/519) - Allow ID or strings in partial names +- [#437](https://github.com/wycats/handlebars.js/issues/437) - Require matching brace counts in escaped expressions +- Merge passed partials and helpers with global namespace values +- Add support for complex ids in @data references +- Docs updates + +Compatibility notes: +- The parser is now stricter on `{{{`, requiring that the end token be `}}}`. Templates that do not + follow this convention should add the additional brace value. +- Code that relies on global the namespace being muted when custom helpers or partials are passed will need to explicitly pass an `undefined` value for any helpers that should not be available. +- The compiler version has changed. Precompiled templates with 1.0.12 or higher must use the 1.0.0 or higher runtime. + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.11...v1.0.12) + +## v1.0.11 / 1.0.0-rc4 - May 13 2013 + +- [#458](https://github.com/wycats/handlebars.js/issues/458) - Fix `./foo` syntax ([@jpfiset](https://github.com/jpfiset)) +- [#460](https://github.com/wycats/handlebars.js/issues/460) - Allow `:` in unescaped identifers ([@jpfiset](https://github.com/jpfiset)) +- [#471](https://github.com/wycats/handlebars.js/issues/471) - Create release notes (These!) +- [#456](https://github.com/wycats/handlebars.js/issues/456) - Allow escaping of `\\` +- [#211](https://github.com/wycats/handlebars.js/issues/211) - Fix exception in `escapeExpression` +- [#375](https://github.com/wycats/handlebars.js/issues/375) - Escape unicode newlines +- [#461](https://github.com/wycats/handlebars.js/issues/461) - Do not fail when compiling `""` +- [#302](https://github.com/wycats/handlebars.js/issues/302) - Fix sanity check in knownHelpersOnly mode +- [#369](https://github.com/wycats/handlebars.js/issues/369) - Allow registration of multiple helpers and partial by passing definition object +- Add bower package declaration ([@DevinClark](https://github.com/DevinClark)) +- Add NuSpec package declaration ([@MikeMayer](https://github.com/MikeMayer)) +- Handle empty context in `with` ([@thejohnfreeman](https://github.com/thejohnfreeman)) +- Support custom template extensions in CLI ([@matteoagosti](https://github.com/matteoagosti)) +- Fix Rhino support ([@broady](https://github.com/broady)) +- Include contexts in string mode ([@leshill](https://github.com/leshill)) +- Return precompiled scripts when compiling to AMD ([@JamesMaroney](https://github.com/JamesMaroney)) +- Docs updates ([@iangreenleaf](https://github.com/iangreenleaf), [@gilesbowkett](https://github.com/gilesbowkett), [@utkarsh2012](https://github.com/utkarsh2012)) +- Fix `toString` handling under IE and browserify ([@tommydudebreaux](https://github.com/tommydudebreaux)) +- Add program metadata + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.10...v1.0.11) + +## v1.0.10 - Node - Feb 27 2013 + +- [#428](https://github.com/wycats/handlebars.js/issues/428) - Fix incorrect rendering of nested programs +- Fix exception message ([@tricknotes](https://github.com/tricknotes)) +- Added negative number literal support +- Concert library to single IIFE +- Add handlebars-source gemspec ([@machty](https://github.com/machty)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.9...v1.0.10) + +## v1.0.9 - Node - Feb 15 2013 + +- Added `Handlebars.create` API in node module for sandboxed instances ([@tommydudebreaux](https://github.com/tommydudebreaux)) + +[Commits](https://github.com/wycats/handlebars.js/compare/1.0.0-rc.3...v1.0.9) + +## 1.0.0-rc3 - Browser - Feb 14 2013 + +- Prevent use of `this` or `..` in illogical place ([@leshill](https://github.com/leshill)) +- Allow AST passing for `parse`/`compile`/`precompile` ([@machty](https://github.com/machty)) +- Optimize generated output by inlining statements where possible +- Check compiler version when evaluating templates +- Package browser dist in npm package + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.8...1.0.0-rc.3) + +## Prior Versions + +When upgrading from the Handlebars 0.9 series, be aware that the +signature for passing custom helpers or partials to templates has +changed. + +Instead of: + +```js +template(context, helpers, partials, [data]) +``` + +Use: + +```js +template(context, {helpers: helpers, partials: partials, data: data}) +``` + +[builds-page]: http://builds.handlebarsjs.com.s3.amazonaws.com/index.html +[cdnjs]: http://cdnjs.com/libraries/handlebars.js/ +[components]: https://github.com/components/handlebars.js +[npm]: https://npmjs.org/package/handlebars diff --git a/hm_sunwell/node_modules/handlebars/runtime.js b/hm_sunwell/node_modules/handlebars/runtime.js new file mode 100644 index 0000000..306207c --- /dev/null +++ b/hm_sunwell/node_modules/handlebars/runtime.js @@ -0,0 +1,3 @@ +// Create a simple path alias to allow browserify to resolve +// the runtime on a supported path. +module.exports = require('./dist/cjs/handlebars.runtime')['default']; diff --git a/hm_sunwell/node_modules/har-validator/LICENSE b/hm_sunwell/node_modules/har-validator/LICENSE new file mode 100644 index 0000000..ca55c91 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Ahmad Nassri + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/hm_sunwell/node_modules/har-validator/README.md b/hm_sunwell/node_modules/har-validator/README.md new file mode 100644 index 0000000..91526e6 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/README.md @@ -0,0 +1,309 @@ +# HAR Validator [![version][npm-version]][npm-url] [![License][npm-license]][license-url] + +Extremely fast HTTP Archive ([HAR](http://www.softwareishard.com/blog/har-12-spec/)) validator using JSON Schema. + +[![Build Status][travis-image]][travis-url] +[![Downloads][npm-downloads]][npm-url] +[![Code Climate][codeclimate-quality]][codeclimate-url] +[![Coverage Status][codeclimate-coverage]][codeclimate-url] +[![Dependencies][david-image]][david-url] + +## Install + +```shell +# to use in cli +npm install --global har-validator + +# to use as a module +npm install --save har-validator +``` + +## Usage + +``` + + Usage: har-validator [options] + + Options: + + -h, --help output usage information + -V, --version output the version number + -s, --schema [name] validate schema name (log, request, response, etc ...) + +``` + +###### Example + +```shell +har-validator har.json + +har-validator --schema request request.json +``` + +## API + +**Note**: as of [`v2.0.0`](https://github.com/ahmadnassri/har-validator/releases/tag/v2.0.0) this module defaults to Promise based API. *For backward comptability with `v1.x` an [async/callback API](#callback-api) is provided* + +### Validate(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a full [HAR](http://www.softwareishard.com/blog/har-12-spec/) object + +```js +validate(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.log(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [log](http://www.softwareishard.com/blog/har-12-spec/#log) object + +```js +validate.log(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.cache(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [cache](http://www.softwareishard.com/blog/har-12-spec/#cache) object + +```js +validate.cache(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.cacheEntry(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a ["beforeRequest" or "afterRequest"](http://www.softwareishard.com/blog/har-12-spec/#cache) objects + +```js +validate.cacheEntry(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.content(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [content](http://www.softwareishard.com/blog/har-12-spec/#content) object + +```js +validate.content(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.cookie(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [cookie](http://www.softwareishard.com/blog/har-12-spec/#cookies) object + +```js +validate.cookie(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.creator(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [creator](http://www.softwareishard.com/blog/har-12-spec/#creator) object + +```js +validate.creator(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.entry(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + an [entry](http://www.softwareishard.com/blog/har-12-spec/#entries) object + +```js +validate.entry(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.log(data) + +alias of [`Validate(data)`](#validate-data-callback-) + +### Validate.page(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [page](http://www.softwareishard.com/blog/har-12-spec/#pages) object + +```js +validate.page(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.pageTimings(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [pageTimings](http://www.softwareishard.com/blog/har-12-spec/#pageTimings) object + +```js +validate.pageTimings(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.postData(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [postData](http://www.softwareishard.com/blog/har-12-spec/#postData) object + +```js +validate.postData(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.record(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [record](http://www.softwareishard.com/blog/har-12-spec/#headers) object + +```js +validate.record(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.request(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [request](http://www.softwareishard.com/blog/har-12-spec/#request) object + +```js +validate.request(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.response(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [response](http://www.softwareishard.com/blog/har-12-spec/#response) object + +```js +validate.cacheEntry(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +### Validate.timings(data) + +> Returns a promise that resolves to the valid object. + +- **data**: `Object` *(Required)* + a [timings](http://www.softwareishard.com/blog/har-12-spec/#timings) object + +```js +validate.timings(data) + .then(data => console.log('horray!')) + .catch(console.error) +``` + +---- + +## Callback API + +### Validate(data [, callback]) + +> Returns `true` or `false`. + +```js +var HAR = require('./har.json'); +var validate = require('har-validator/lib/async'); + +validate(HAR, function (e, valid) { + if (e) console.log(e.errors) + + if (valid) console.log('horray!'); +}); + +``` +The async API provides exactly the same methods as the [Promise API](#promise-api) + +---- + +## Support + +Donations are welcome to help support the continuous development of this project. + +[![Gratipay][gratipay-image]][gratipay-url] +[![PayPal][paypal-image]][paypal-url] +[![Flattr][flattr-image]][flattr-url] +[![Bitcoin][bitcoin-image]][bitcoin-url] + +## License + +[ISC License](LICENSE) © [Ahmad Nassri](https://www.ahmadnassri.com/) + +[license-url]: https://github.com/ahmadnassri/har-validator/blob/master/LICENSE + +[travis-url]: https://travis-ci.org/ahmadnassri/har-validator +[travis-image]: https://img.shields.io/travis/ahmadnassri/har-validator.svg?style=flat-square + +[npm-url]: https://www.npmjs.com/package/har-validator +[npm-license]: https://img.shields.io/npm/l/har-validator.svg?style=flat-square +[npm-version]: https://img.shields.io/npm/v/har-validator.svg?style=flat-square +[npm-downloads]: https://img.shields.io/npm/dm/har-validator.svg?style=flat-square + +[codeclimate-url]: https://codeclimate.com/github/ahmadnassri/har-validator +[codeclimate-quality]: https://img.shields.io/codeclimate/github/ahmadnassri/har-validator.svg?style=flat-square +[codeclimate-coverage]: https://img.shields.io/codeclimate/coverage/github/ahmadnassri/har-validator.svg?style=flat-square + +[david-url]: https://david-dm.org/ahmadnassri/har-validator +[david-image]: https://img.shields.io/david/ahmadnassri/har-validator.svg?style=flat-square + +[gratipay-url]: https://www.gratipay.com/ahmadnassri/ +[gratipay-image]: https://img.shields.io/gratipay/ahmadnassri.svg?style=flat-square + +[paypal-url]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UJ2B2BTK9VLRS&on0=project&os0=har-validator +[paypal-image]: http://img.shields.io/badge/paypal-donate-green.svg?style=flat-square + +[flattr-url]: https://flattr.com/submit/auto?user_id=ahmadnassri&url=https://github.com/ahmadnassri/har-validator&title=har-validator&language=&tags=github&category=software +[flattr-image]: http://img.shields.io/badge/flattr-donate-green.svg?style=flat-square + +[bitcoin-image]: http://img.shields.io/badge/bitcoin-1Nb46sZRVG3or7pNaDjthcGJpWhvoPpCxy-green.svg?style=flat-square +[bitcoin-url]: https://www.coinbase.com/checkouts/ae383ae6bb931a2fa5ad11cec115191e?name=har-validator diff --git a/hm_sunwell/node_modules/har-validator/bin/har-validator b/hm_sunwell/node_modules/har-validator/bin/har-validator new file mode 100644 index 0000000..fd7cc0d --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/bin/har-validator @@ -0,0 +1,56 @@ +#!/usr/bin/env node + +'use strict' + +var chalk = require('chalk') +var cmd = require('commander') +var fs = require('fs') +var path = require('path') +var pkg = require('../package.json') +var Promise = require('pinkie-promise') +var validate = require('..') +var ValidationError = require('../lib/error') + +cmd + .version(pkg.version) + .usage('[options] ') + .option('-s, --schema [name]', 'validate schema name (log, request, response, etc ...)') + .parse(process.argv) + +if (!cmd.args.length) { + cmd.help() +} + +cmd.args.map(function (fileName) { + var file = chalk.yellow.italic(path.basename(fileName)) + + new Promise(function (resolve, reject) { + fs.readFile(fileName, function (err, data) { + return err === null ? resolve(data) : reject(err) + }) + }) + + .then(JSON.parse) + + .then(cmd.schema ? validate[cmd.schema] : validate) + + .then(function (data) { + console.log('%s [%s] is valid', chalk.green('✓'), file) + }) + + .catch(function (err) { + if (err instanceof SyntaxError) { + return console.error('%s [%s] failed to read JSON: %s', chalk.red('✖'), file, chalk.red(err.message)) + } + + if (err instanceof ValidationError) { + err.errors.forEach(function (details) { + console.error('%s [%s] failed validation: (%s: %s) %s', chalk.red('✖'), file, chalk.cyan.italic(details.field), chalk.magenta.italic(details.value), chalk.red(details.message)) + }) + + return + } + + console.error('%s [%s] an unknown error has occured: %s', chalk.red('✖'), file, chalk.red(err.message)) + }) +}) diff --git a/hm_sunwell/node_modules/har-validator/lib/async.js b/hm_sunwell/node_modules/har-validator/lib/async.js new file mode 100644 index 0000000..77b99a7 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/async.js @@ -0,0 +1,14 @@ +'use strict' + +var runner = require('./runner') +var schemas = require('./schemas') + +module.exports = function (data, cb) { + return runner(schemas.har, data, cb) +} + +Object.keys(schemas).map(function (name) { + module.exports[name] = function (data, cb) { + return runner(schemas[name], data, cb) + } +}) diff --git a/hm_sunwell/node_modules/har-validator/lib/error.js b/hm_sunwell/node_modules/har-validator/lib/error.js new file mode 100644 index 0000000..fc08a87 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/error.js @@ -0,0 +1,10 @@ +'use strict' + +function ValidationError (errors) { + this.name = 'ValidationError' + this.errors = errors +} + +ValidationError.prototype = Error.prototype + +module.exports = ValidationError diff --git a/hm_sunwell/node_modules/har-validator/lib/index.js b/hm_sunwell/node_modules/har-validator/lib/index.js new file mode 100644 index 0000000..e8351b8 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/index.js @@ -0,0 +1,22 @@ +'use strict' + +var Promise = require('pinkie-promise') +var runner = require('./runner') +var schemas = require('./schemas') + +var promisify = function (schema) { + return function (data) { + return new Promise(function (resolve, reject) { + runner(schema, data, function (err, valid) { + return err === null ? resolve(data) : reject(err) + }) + }) + } +} + +module.exports = promisify(schemas.har) + +// utility methods for all parts of the schema +Object.keys(schemas).map(function (name) { + module.exports[name] = promisify(schemas[name]) +}) diff --git a/hm_sunwell/node_modules/har-validator/lib/runner.js b/hm_sunwell/node_modules/har-validator/lib/runner.js new file mode 100644 index 0000000..f0ed484 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/runner.js @@ -0,0 +1,29 @@ +'use strict' + +var schemas = require('./schemas') +var ValidationError = require('./error') +var validator = require('is-my-json-valid') + +module.exports = function (schema, data, cb) { + // default value + var valid = false + + // validator config + var validate = validator(schema, { + greedy: true, + verbose: true, + schemas: schemas + }) + + // execute is-my-json-valid + if (data !== undefined) { + valid = validate(data) + } + + // callback? + if (typeof cb === 'function') { + return cb(validate.errors ? new ValidationError(validate.errors) : null, valid) + } + + return valid +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/cache.json b/hm_sunwell/node_modules/har-validator/lib/schemas/cache.json new file mode 100644 index 0000000..a3ab682 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/cache.json @@ -0,0 +1,13 @@ +{ + "properties": { + "beforeRequest": { + "$ref": "#cacheEntry" + }, + "afterRequest": { + "$ref": "#cacheEntry" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/cacheEntry.json b/hm_sunwell/node_modules/har-validator/lib/schemas/cacheEntry.json new file mode 100644 index 0000000..a397439 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/cacheEntry.json @@ -0,0 +1,31 @@ +{ + "oneOf": [{ + "type": "object", + "optional": true, + "required": [ + "lastAccess", + "eTag", + "hitCount" + ], + "properties": { + "expires": { + "type": "string" + }, + "lastAccess": { + "type": "string" + }, + "eTag": { + "type": "string" + }, + "hitCount": { + "type": "integer" + }, + "comment": { + "type": "string" + } + } + }, { + "type": null, + "additionalProperties": false + }] +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/content.json b/hm_sunwell/node_modules/har-validator/lib/schemas/content.json new file mode 100644 index 0000000..3710d79 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/content.json @@ -0,0 +1,27 @@ +{ + "type": "object", + "required": [ + "size", + "mimeType" + ], + "properties": { + "size": { + "type": "integer" + }, + "compression": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "text": { + "type": "string" + }, + "encoding": { + "type": "string" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/cookie.json b/hm_sunwell/node_modules/har-validator/lib/schemas/cookie.json new file mode 100644 index 0000000..5768181 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/cookie.json @@ -0,0 +1,34 @@ +{ + "type": "object", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "path": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "expires": { + "type": ["string", "null"], + "format": "date-time" + }, + "httpOnly": { + "type": "boolean" + }, + "secure": { + "type": "boolean" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/creator.json b/hm_sunwell/node_modules/har-validator/lib/schemas/creator.json new file mode 100644 index 0000000..5058600 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/creator.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/entry.json b/hm_sunwell/node_modules/har-validator/lib/schemas/entry.json new file mode 100644 index 0000000..8a9c022 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/entry.json @@ -0,0 +1,51 @@ +{ + "type": "object", + "optional": true, + "required": [ + "startedDateTime", + "time", + "request", + "response", + "cache", + "timings" + ], + "properties": { + "pageref": { + "type": "string" + }, + "startedDateTime": { + "type": "string", + "format": "date-time", + "pattern": "^(\\d{4})(-)?(\\d\\d)(-)?(\\d\\d)(T)?(\\d\\d)(:)?(\\d\\d)(:)?(\\d\\d)(\\.\\d+)?(Z|([+-])(\\d\\d)(:)?(\\d\\d))" + }, + "time": { + "type": "number", + "min": 0 + }, + "request": { + "$ref": "#request" + }, + "response": { + "$ref": "#response" + }, + "cache": { + "$ref": "#cache" + }, + "timings": { + "$ref": "#timings" + }, + "serverIPAddress": { + "type": "string", + "oneOf": [ + { "format": "ipv4" }, + { "format": "ipv6" } + ] + }, + "connection": { + "type": "string" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/har.json b/hm_sunwell/node_modules/har-validator/lib/schemas/har.json new file mode 100644 index 0000000..b542782 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/har.json @@ -0,0 +1,11 @@ +{ + "type": "object", + "required": [ + "log" + ], + "properties": { + "log": { + "$ref": "#log" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/index.js b/hm_sunwell/node_modules/har-validator/lib/schemas/index.js new file mode 100644 index 0000000..7b6db7d --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/index.js @@ -0,0 +1,49 @@ +'use strict' + +var schemas = { + cache: require('./cache.json'), + cacheEntry: require('./cacheEntry.json'), + content: require('./content.json'), + cookie: require('./cookie.json'), + creator: require('./creator.json'), + entry: require('./entry.json'), + har: require('./har.json'), + log: require('./log.json'), + page: require('./page.json'), + pageTimings: require('./pageTimings.json'), + postData: require('./postData.json'), + record: require('./record.json'), + request: require('./request.json'), + response: require('./response.json'), + timings: require('./timings.json') +} + +// is-my-json-valid does not provide meaningful error messages for external schemas +// this is a workaround +schemas.cache.properties.beforeRequest = schemas.cacheEntry +schemas.cache.properties.afterRequest = schemas.cacheEntry + +schemas.page.properties.pageTimings = schemas.pageTimings + +schemas.request.properties.cookies.items = schemas.cookie +schemas.request.properties.headers.items = schemas.record +schemas.request.properties.queryString.items = schemas.record +schemas.request.properties.postData = schemas.postData + +schemas.response.properties.cookies.items = schemas.cookie +schemas.response.properties.headers.items = schemas.record +schemas.response.properties.content = schemas.content + +schemas.entry.properties.request = schemas.request +schemas.entry.properties.response = schemas.response +schemas.entry.properties.cache = schemas.cache +schemas.entry.properties.timings = schemas.timings + +schemas.log.properties.creator = schemas.creator +schemas.log.properties.browser = schemas.creator +schemas.log.properties.pages.items = schemas.page +schemas.log.properties.entries.items = schemas.entry + +schemas.har.properties.log = schemas.log + +module.exports = schemas diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/log.json b/hm_sunwell/node_modules/har-validator/lib/schemas/log.json new file mode 100644 index 0000000..0c91d38 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/log.json @@ -0,0 +1,34 @@ +{ + "type": "object", + "required": [ + "version", + "creator", + "entries" + ], + "properties": { + "version": { + "type": "string" + }, + "creator": { + "$ref": "#creator" + }, + "browser": { + "$ref": "#creator" + }, + "pages": { + "type": "array", + "items": { + "$ref": "#page" + } + }, + "entries": { + "type": "array", + "items": { + "$ref": "#entry" + } + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/page.json b/hm_sunwell/node_modules/har-validator/lib/schemas/page.json new file mode 100644 index 0000000..ef64abe --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/page.json @@ -0,0 +1,30 @@ +{ + "type": "object", + "optional": true, + "required": [ + "startedDateTime", + "id", + "title", + "pageTimings" + ], + "properties": { + "startedDateTime": { + "type": "string", + "format": "date-time", + "pattern": "^(\\d{4})(-)?(\\d\\d)(-)?(\\d\\d)(T)?(\\d\\d)(:)?(\\d\\d)(:)?(\\d\\d)(\\.\\d+)?(Z|([+-])(\\d\\d)(:)?(\\d\\d))" + }, + "id": { + "type": "string", + "unique": true + }, + "title": { + "type": "string" + }, + "pageTimings": { + "$ref": "#pageTimings" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/pageTimings.json b/hm_sunwell/node_modules/har-validator/lib/schemas/pageTimings.json new file mode 100644 index 0000000..adc83cc --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/pageTimings.json @@ -0,0 +1,16 @@ +{ + "type": "object", + "properties": { + "onContentLoad": { + "type": "number", + "min": -1 + }, + "onLoad": { + "type": "number", + "min": -1 + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/postData.json b/hm_sunwell/node_modules/har-validator/lib/schemas/postData.json new file mode 100644 index 0000000..91958b6 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/postData.json @@ -0,0 +1,41 @@ +{ + "type": "object", + "optional": true, + "required": [ + "mimeType" + ], + "properties": { + "mimeType": { + "type": "string" + }, + "text": { + "type": "string" + }, + "params": { + "type": "array", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "fileName": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "comment": { + "type": "string" + } + } + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/record.json b/hm_sunwell/node_modules/har-validator/lib/schemas/record.json new file mode 100644 index 0000000..04acd51 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/record.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/request.json b/hm_sunwell/node_modules/har-validator/lib/schemas/request.json new file mode 100644 index 0000000..639af06 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/request.json @@ -0,0 +1,55 @@ +{ + "type": "object", + "required": [ + "method", + "url", + "httpVersion", + "cookies", + "headers", + "queryString", + "headersSize", + "bodySize" + ], + "properties": { + "method": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + }, + "httpVersion": { + "type": "string" + }, + "cookies": { + "type": "array", + "items": { + "$ref": "#cookie" + } + }, + "headers": { + "type": "array", + "items": { + "$ref": "#record" + } + }, + "queryString": { + "type": "array", + "items": { + "$ref": "#record" + } + }, + "postData": { + "$ref": "#postData" + }, + "headersSize": { + "type": "integer" + }, + "bodySize": { + "type": "integer" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/response.json b/hm_sunwell/node_modules/har-validator/lib/schemas/response.json new file mode 100644 index 0000000..de99c55 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/response.json @@ -0,0 +1,52 @@ +{ + "type": "object", + "required": [ + "status", + "statusText", + "httpVersion", + "cookies", + "headers", + "content", + "redirectURL", + "headersSize", + "bodySize" + ], + "properties": { + "status": { + "type": "integer" + }, + "statusText": { + "type": "string" + }, + "httpVersion": { + "type": "string" + }, + "cookies": { + "type": "array", + "items": { + "$ref": "#cookie" + } + }, + "headers": { + "type": "array", + "items": { + "$ref": "#record" + } + }, + "content": { + "$ref": "#content" + }, + "redirectURL": { + "type": "string" + }, + "headersSize": { + "type": "integer" + }, + "bodySize": { + "type": "integer" + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/lib/schemas/timings.json b/hm_sunwell/node_modules/har-validator/lib/schemas/timings.json new file mode 100644 index 0000000..066ef71 --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/lib/schemas/timings.json @@ -0,0 +1,40 @@ +{ + "required": [ + "send", + "wait", + "receive" + ], + "properties": { + "dns": { + "type": "number", + "min": -1 + }, + "connect": { + "type": "number", + "min": -1 + }, + "blocked": { + "type": "number", + "min": -1 + }, + "send": { + "type": "number", + "min": -1 + }, + "wait": { + "type": "number", + "min": -1 + }, + "receive": { + "type": "number", + "min": -1 + }, + "ssl": { + "type": "number", + "min": -1 + }, + "comment": { + "type": "string" + } + } +} diff --git a/hm_sunwell/node_modules/har-validator/package.json b/hm_sunwell/node_modules/har-validator/package.json new file mode 100644 index 0000000..76371dc --- /dev/null +++ b/hm_sunwell/node_modules/har-validator/package.json @@ -0,0 +1,112 @@ +{ + "_args": [ + [ + "har-validator@~2.0.6", + "/home/xor/shared_vm/git/node-sunwell/node_modules/request" + ] + ], + "_from": "har-validator@>=2.0.6 <2.1.0", + "_id": "har-validator@2.0.6", + "_inCache": true, + "_installable": true, + "_location": "/har-validator", + "_nodeVersion": "5.2.0", + "_npmUser": { + "email": "ahmad@ahmadnassri.com", + "name": "ahmadnassri" + }, + "_npmVersion": "3.3.12", + "_phantomChildren": {}, + "_requested": { + "name": "har-validator", + "raw": "har-validator@~2.0.6", + "rawSpec": "~2.0.6", + "scope": null, + "spec": ">=2.0.6 <2.1.0", + "type": "range" + }, + "_requiredBy": [ + "/request" + ], + "_resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "_shasum": "cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d", + "_shrinkwrap": null, + "_spec": "har-validator@~2.0.6", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/request", + "author": { + "email": "ahmad@ahmadnassri.com", + "name": "Ahmad Nassri", + "url": "https://www.ahmadnassri.com/" + }, + "bin": { + "har-validator": "bin/har-validator" + }, + "bugs": { + "url": "https://github.com/ahmadnassri/har-validator/issues" + }, + "dependencies": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + }, + "description": "Extremely fast HTTP Archive (HAR) validator using JSON Schema", + "devDependencies": { + "codeclimate-test-reporter": "0.2.1", + "echint": "^1.5.1", + "istanbul": "^0.4.2", + "mocha": "^2.3.4", + "require-directory": "^2.1.1", + "should": "^8.1.1", + "standard": "^5.4.1" + }, + "directories": {}, + "dist": { + "shasum": "cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d", + "tarball": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz" + }, + "echint": { + "ignore": [ + "coverage/**" + ] + }, + "engines": { + "node": ">=0.10" + }, + "files": [ + "bin", + "lib" + ], + "gitHead": "92ccddad2e5d13e6e32c764e06c347d67805b211", + "homepage": "https://github.com/ahmadnassri/har-validator", + "keywords": [ + "archive", + "har", + "http", + "validate", + "validator" + ], + "license": "ISC", + "main": "lib/index", + "maintainers": [ + { + "name": "ahmadnassri", + "email": "ahmad@ahmadnassri.com" + } + ], + "name": "har-validator", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/ahmadnassri/har-validator.git" + }, + "scripts": { + "codeclimate": "codeclimate < coverage/lcov.info", + "coverage": "istanbul cover --dir coverage _mocha -- -R dot", + "posttest": "npm run coverage", + "pretest": "standard && echint", + "test": "mocha" + }, + "version": "2.0.6" +} diff --git a/hm_sunwell/node_modules/has-ansi/index.js b/hm_sunwell/node_modules/has-ansi/index.js new file mode 100644 index 0000000..98fae06 --- /dev/null +++ b/hm_sunwell/node_modules/has-ansi/index.js @@ -0,0 +1,4 @@ +'use strict'; +var ansiRegex = require('ansi-regex'); +var re = new RegExp(ansiRegex().source); // remove the `g` flag +module.exports = re.test.bind(re); diff --git a/hm_sunwell/node_modules/has-ansi/license b/hm_sunwell/node_modules/has-ansi/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/hm_sunwell/node_modules/has-ansi/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/has-ansi/package.json b/hm_sunwell/node_modules/has-ansi/package.json new file mode 100644 index 0000000..30b78ce --- /dev/null +++ b/hm_sunwell/node_modules/has-ansi/package.json @@ -0,0 +1,110 @@ +{ + "_args": [ + [ + "has-ansi@^2.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/chalk" + ] + ], + "_from": "has-ansi@>=2.0.0 <3.0.0", + "_id": "has-ansi@2.0.0", + "_inCache": true, + "_installable": true, + "_location": "/has-ansi", + "_nodeVersion": "0.12.5", + "_npmUser": { + "email": "sindresorhus@gmail.com", + "name": "sindresorhus" + }, + "_npmVersion": "2.11.2", + "_phantomChildren": {}, + "_requested": { + "name": "has-ansi", + "raw": "has-ansi@^2.0.0", + "rawSpec": "^2.0.0", + "scope": null, + "spec": ">=2.0.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/chalk" + ], + "_resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "_shasum": "34f5049ce1ecdf2b0649af3ef24e45ed35416d91", + "_shrinkwrap": null, + "_spec": "has-ansi@^2.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/chalk", + "author": { + "email": "sindresorhus@gmail.com", + "name": "Sindre Sorhus", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/has-ansi/issues" + }, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "description": "Check if a string has ANSI escape codes", + "devDependencies": { + "ava": "0.0.4" + }, + "directories": {}, + "dist": { + "shasum": "34f5049ce1ecdf2b0649af3ef24e45ed35416d91", + "tarball": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "0722275e1bef139fcd09137da6e5550c3cd368b9", + "homepage": "https://github.com/sindresorhus/has-ansi", + "keywords": [ + "ansi", + "color", + "colors", + "colour", + "command-line", + "console", + "escape", + "find", + "has", + "match", + "pattern", + "re", + "regex", + "regexp", + "shell", + "string", + "styles", + "terminal", + "test", + "text", + "tty", + "xterm" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + } + ], + "name": "has-ansi", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/has-ansi.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "2.0.0" +} diff --git a/hm_sunwell/node_modules/has-ansi/readme.md b/hm_sunwell/node_modules/has-ansi/readme.md new file mode 100644 index 0000000..02bc7c2 --- /dev/null +++ b/hm_sunwell/node_modules/has-ansi/readme.md @@ -0,0 +1,36 @@ +# has-ansi [![Build Status](https://travis-ci.org/sindresorhus/has-ansi.svg?branch=master)](https://travis-ci.org/sindresorhus/has-ansi) + +> Check if a string has [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code) + + +## Install + +``` +$ npm install --save has-ansi +``` + + +## Usage + +```js +var hasAnsi = require('has-ansi'); + +hasAnsi('\u001b[4mcake\u001b[0m'); +//=> true + +hasAnsi('cake'); +//=> false +``` + + +## Related + +- [has-ansi-cli](https://github.com/sindresorhus/has-ansi-cli) - CLI for this module +- [strip-ansi](https://github.com/sindresorhus/strip-ansi) - Strip ANSI escape codes +- [ansi-regex](https://github.com/sindresorhus/ansi-regex) - Regular expression for matching ANSI escape codes +- [chalk](https://github.com/sindresorhus/chalk) - Terminal string styling done right + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/hm_sunwell/node_modules/has-flag/index.js b/hm_sunwell/node_modules/has-flag/index.js new file mode 100644 index 0000000..fdcb342 --- /dev/null +++ b/hm_sunwell/node_modules/has-flag/index.js @@ -0,0 +1,10 @@ +'use strict'; +module.exports = function (flag, argv) { + argv = argv || process.argv; + + var terminatorPos = argv.indexOf('--'); + var prefix = /^--/.test(flag) ? '' : '--'; + var pos = argv.indexOf(prefix + flag); + + return pos !== -1 && (terminatorPos !== -1 ? pos < terminatorPos : true); +}; diff --git a/hm_sunwell/node_modules/has-flag/license b/hm_sunwell/node_modules/has-flag/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/hm_sunwell/node_modules/has-flag/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/has-flag/package.json b/hm_sunwell/node_modules/has-flag/package.json new file mode 100644 index 0000000..fd09dd8 --- /dev/null +++ b/hm_sunwell/node_modules/has-flag/package.json @@ -0,0 +1,110 @@ +{ + "_args": [ + [ + "has-flag@^1.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul/node_modules/supports-color" + ] + ], + "_from": "has-flag@>=1.0.0 <2.0.0", + "_id": "has-flag@1.0.0", + "_inCache": true, + "_installable": true, + "_location": "/has-flag", + "_nodeVersion": "0.12.5", + "_npmUser": { + "email": "sindresorhus@gmail.com", + "name": "sindresorhus" + }, + "_npmVersion": "2.11.2", + "_phantomChildren": {}, + "_requested": { + "name": "has-flag", + "raw": "has-flag@^1.0.0", + "rawSpec": "^1.0.0", + "scope": null, + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/istanbul/supports-color" + ], + "_resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "_shasum": "9d9e793165ce017a00f00418c43f942a7b1d11fa", + "_shrinkwrap": null, + "_spec": "has-flag@^1.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul/node_modules/supports-color", + "author": { + "email": "sindresorhus@gmail.com", + "name": "Sindre Sorhus", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/has-flag/issues" + }, + "dependencies": {}, + "description": "Check if argv has a specific flag", + "devDependencies": { + "ava": "0.0.4" + }, + "directories": {}, + "dist": { + "shasum": "9d9e793165ce017a00f00418c43f942a7b1d11fa", + "tarball": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "621de2782d538f28f99f0bb85b158799cb3ae5cf", + "homepage": "https://github.com/sindresorhus/has-flag#readme", + "keywords": [ + "arg", + "args", + "argument", + "arguments", + "argv", + "check", + "cli", + "command-line", + "contains", + "detect", + "find", + "flag", + "getopt", + "has", + "minimist", + "optimist", + "process" + ], + "license": "MIT", + "maintainers": [ + { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + { + "name": "Joshua Appelman", + "email": "jappelman@xebia.com", + "url": "jbnicolai.com" + }, + { + "name": "JD Ballard", + "email": "i.am.qix@gmail.com", + "url": "github.com/qix-" + } + ], + "name": "has-flag", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/has-flag.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "1.0.0" +} diff --git a/hm_sunwell/node_modules/has-flag/readme.md b/hm_sunwell/node_modules/has-flag/readme.md new file mode 100644 index 0000000..ea5c817 --- /dev/null +++ b/hm_sunwell/node_modules/has-flag/readme.md @@ -0,0 +1,64 @@ +# has-flag [![Build Status](https://travis-ci.org/sindresorhus/has-flag.svg?branch=master)](https://travis-ci.org/sindresorhus/has-flag) + +> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag + +Correctly stops looking after an `--` argument terminator. + + +## Install + +``` +$ npm install --save has-flag +``` + + +## Usage + +```js +// foo.js +var hasFlag = require('has-flag'); + +hasFlag('unicorn'); +//=> true + +hasFlag('--unicorn'); +//=> true + +hasFlag('foo=bar'); +//=> true + +hasFlag('foo'); +//=> false + +hasFlag('rainbow'); +//=> false +``` + +``` +$ node foo.js --unicorn --foo=bar -- --rainbow +``` + + +## API + +### hasFlag(flag, [argv]) + +Returns a boolean whether the flag exists. + +#### flag + +Type: `string` + +CLI flag to look for. The `--` prefix is optional. + +#### argv + +Type: `array` +Default: `process.argv` + +CLI arguments. + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/hm_sunwell/node_modules/hawk/.npmignore b/hm_sunwell/node_modules/hawk/.npmignore new file mode 100644 index 0000000..70febc0 --- /dev/null +++ b/hm_sunwell/node_modules/hawk/.npmignore @@ -0,0 +1,20 @@ +.idea +*.iml +npm-debug.log +dump.rdb +node_modules +components +build +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov + diff --git a/hm_sunwell/node_modules/hawk/.travis.yml b/hm_sunwell/node_modules/hawk/.travis.yml new file mode 100644 index 0000000..047f7e3 --- /dev/null +++ b/hm_sunwell/node_modules/hawk/.travis.yml @@ -0,0 +1,5 @@ +language: node_js + +node_js: + - 0.10 + diff --git a/hm_sunwell/node_modules/hawk/LICENSE b/hm_sunwell/node_modules/hawk/LICENSE new file mode 100644 index 0000000..7880936 --- /dev/null +++ b/hm_sunwell/node_modules/hawk/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012-2014, Eran Hammer and other contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hueniverse/hawk/graphs/contributors diff --git a/hm_sunwell/node_modules/hawk/README.md b/hm_sunwell/node_modules/hawk/README.md new file mode 100644 index 0000000..4aff23f --- /dev/null +++ b/hm_sunwell/node_modules/hawk/README.md @@ -0,0 +1,634 @@ +![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png) + + **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial +HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz). + +Current version: **3.x** + +Note: 3.x and 2.x are the same exact protocol as 1.1. The version increments reflect changes in the node API. + +[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk) + +# Table of Content + +- [**Introduction**](#introduction) + - [Replay Protection](#replay-protection) + - [Usage Example](#usage-example) + - [Protocol Example](#protocol-example) + - [Payload Validation](#payload-validation) + - [Response Payload Validation](#response-payload-validation) + - [Browser Support and Considerations](#browser-support-and-considerations) +

+- [**Single URI Authorization**](#single-uri-authorization) + - [Usage Example](#bewit-usage-example) +

+- [**Security Considerations**](#security-considerations) + - [MAC Keys Transmission](#mac-keys-transmission) + - [Confidentiality of Requests](#confidentiality-of-requests) + - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers) + - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials) + - [Entropy of Keys](#entropy-of-keys) + - [Coverage Limitations](#coverage-limitations) + - [Future Time Manipulation](#future-time-manipulation) + - [Client Clock Poisoning](#client-clock-poisoning) + - [Bewit Limitations](#bewit-limitations) + - [Host Header Forgery](#host-header-forgery) +

+- [**Frequently Asked Questions**](#frequently-asked-questions) +

+- [**Implementations**](#implementations) +- [**Acknowledgements**](#acknowledgements) + +# Introduction + +**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with +partial cryptographic verification of the request and response, covering the HTTP method, request URI, host, +and optionally the request payload. + +Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of +client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme, +the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is +included in its place. + +However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of +replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less +"chattiness" (interaction with the server). + +Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because +the client and server must both have access to the key material in the clear. + +The primary design goals of this scheme are to: +* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources, +* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where + to send an authenticated request), and +* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client + failure to validate the server's identity as part of its TLS handshake. + +In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using +a query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk). + +The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server, +which is beyond the scope of this module. Typically, the shared credentials are established via an initial +TLS-protected phase or derived from some other shared confidential information available to both the client +and the server. + + +## Replay Protection + +Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more +than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when +making requests. This gives the server enough information to prevent replay attacks. + +The nonce is generated by the client, and is a string unique across all requests with the same timestamp and +key identifier combination. + +The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards +are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks. +By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in +practice translates to a maximum of 2 minutes as the skew can be positive or negative). + +Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client +clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types +(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response +to a bad timestamp. + +There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a +potential attack vector). Instead, the client only uses the server's time to calculate an offset used only +for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing +the number of round trips required to authenticate the first request. + + +## Usage Example + +Server code: + +```javascript +var Http = require('http'); +var Hawk = require('hawk'); + + +// Credentials lookup function + +var credentialsFunc = function (id, callback) { + + var credentials = { + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'Steve' + }; + + return callback(null, credentials); +}; + +// Create HTTP server + +var handler = function (req, res) { + + // Authenticate incoming request + + Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) { + + // Prepare response + + var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!'); + var headers = { 'Content-Type': 'text/plain' }; + + // Generate Server-Authorization response header + + var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] }); + headers['Server-Authorization'] = header; + + // Send the response back + + res.writeHead(!err ? 200 : 401, headers); + res.end(payload); + }); +}; + +// Start server + +Http.createServer(handler).listen(8000, 'example.com'); +``` + +Client code: + +```javascript +var Request = require('request'); +var Hawk = require('hawk'); + + +// Client credentials + +var credentials = { + id: 'dh37fgj492je', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256' +} + +// Request options + +var requestOptions = { + uri: 'http://example.com:8000/resource/1?b=1&a=2', + method: 'GET', + headers: {} +}; + +// Generate Authorization request header + +var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' }); +requestOptions.headers.Authorization = header.field; + +// Send authenticated request + +Request(requestOptions, function (error, response, body) { + + // Authenticate the server's response + + var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body }); + + // Output results + + console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)')); +}); +``` + +**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local +machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method. + +```javascript +Hawk.sntp.start(); +``` + + +## Protocol Example + +The client attempts to access a protected resource without authentication, sending the following HTTP request to +the resource server: + +``` +GET /resource/1?b=1&a=2 HTTP/1.1 +Host: example.com:8000 +``` + +The resource server returns an authentication challenge. + +``` +HTTP/1.1 401 Unauthorized +WWW-Authenticate: Hawk +``` + +The client has previously obtained a set of **Hawk** credentials for accessing resources on the "http://example.com/" +server. The **Hawk** credentials issued to the client include the following attributes: + +* Key identifier: dh37fgj492je +* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn +* Algorithm: sha256 + +The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1, +1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline +character): + +``` +hawk.1.header +1353832234 +j4h3g2 +GET +/resource/1?b=1&a=2 +example.com +8000 + +some-app-ext-data + +``` + +The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string. +The result is base64-encoded to produce the request MAC: + +``` +6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE= +``` + +The client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using +the HTTP `Authorization` request header field: + +``` +GET /resource/1?b=1&a=2 HTTP/1.1 +Host: example.com:8000 +Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=" +``` + +The server validates the request by calculating the request MAC again based on the request received and verifies the validity +and scope of the **Hawk** credentials. If valid, the server responds with the requested resource. + + +### Payload Validation + +**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash +using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character): +* `hawk.1.payload` +* the content-type in lowercase, without any parameters (e.g. `application/json`) +* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability) + +For example: + +* Payload: `Thank you for flying Hawk` +* Content Type: `text/plain` +* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=` + +Results in the following input to the payload hash function (newline terminated values): + +``` +hawk.1.payload +text/plain +Thank you for flying Hawk + +``` + +Which produces the following hash value: + +``` +Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY= +``` + +The client constructs the normalized request string (newline terminated values): + +``` +hawk.1.header +1353832234 +j4h3g2 +POST +/resource/1?a=1&b=2 +example.com +8000 +Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY= +some-app-ext-data + +``` + +Then calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data, +and request MAC, with the request using the HTTP `Authorization` request header field: + +``` +POST /resource/1?a=1&b=2 HTTP/1.1 +Host: example.com:8000 +Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw=" +``` + +It is up to the server if and when it validates the payload for any given request, based solely on it's security policy +and the nature of the data included. + +If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct +the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value +with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash. + +However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed +at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value +provided by the client after validating the MAC. + +It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value +included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided +by the client, the payload may be modified by an attacker. + + +## Response Payload Validation + +**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the +client to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header +as a response header using the exact same syntax as the `Authorization` request header field. + +The header is contructed using the same process as the client's request header. The server uses the same credentials and other +artifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with +new values based on the server response. The rest as identical to those used by the client. + +The result MAC digest is included with the optional `hash` and `ext` values: + +``` +Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific" +``` + + +## Browser Support and Considerations + +A browser script is provided for including using a `'); + expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); + done(); + }); + + it('encodes \' characters', function (done) { + + var encoded = Hoek.escapeJavaScript('something(\'param\')'); + expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); + done(); + }); + + it('encodes large unicode characters with the correct padding', function (done) { + + var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); + expect(encoded).to.equal('\\u0500\\u1000'); + done(); + }); + + it('doesn\'t throw an exception when passed null', function (done) { + + var encoded = Hoek.escapeJavaScript(null); + expect(encoded).to.equal(''); + done(); + }); +}); + +describe('escapeHtml()', function () { + + it('encodes / characters', function (done) { + + var encoded = Hoek.escapeHtml(''); + expect(encoded).to.equal('<script>alert(1)</script>'); + done(); + }); + + it('encodes < and > as named characters', function (done) { + + var encoded = Hoek.escapeHtml(' + +{{/if}} + + + diff --git a/hm_sunwell/node_modules/istanbul/lib/report/templates/head.txt b/hm_sunwell/node_modules/istanbul/lib/report/templates/head.txt new file mode 100644 index 0000000..f98094e --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/report/templates/head.txt @@ -0,0 +1,60 @@ + + + + Code coverage report for {{entity}} + +{{#if prettify}} + +{{/if}} + + + + + +
+
+

+ {{{pathHtml}}} +

+
+ {{#with metrics.statements}} +
+ {{pct}}% + Statements + {{covered}}/{{total}} +
+ {{/with}} + {{#with metrics.branches}} +
+ {{pct}}% + Branches + {{covered}}/{{total}} +
+ {{/with}} + {{#with metrics.functions}} +
+ {{pct}}% + Functions + {{covered}}/{{total}} +
+ {{/with}} + {{#with metrics.lines}} +
+ {{pct}}% + Lines + {{covered}}/{{total}} +
+ {{/with}} + {{#if_has_ignores metrics}} +
+ {{#show_ignores metrics}}{{/show_ignores}} + Ignored      +
+ {{/if_has_ignores}} +
+
+
diff --git a/hm_sunwell/node_modules/istanbul/lib/report/text-lcov.js b/hm_sunwell/node_modules/istanbul/lib/report/text-lcov.js new file mode 100644 index 0000000..15e1a48 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/report/text-lcov.js @@ -0,0 +1,50 @@ +var LcovOnly = require('./lcovonly'), + util = require('util'); + +/** + * a `Report` implementation that produces an LCOV coverage and prints it + * to standard out. + * + * Usage + * ----- + * + * var report = require('istanbul').Report.create('text-lcov'); + * + * @class TextLcov + * @module report + * @extends LcovOnly + * @constructor + * @param {Object} opts optional + * @param {String} [opts.log] the method used to log to console. + */ +function TextLcov(opts) { + var that = this; + + LcovOnly.call(this); + + this.opts = opts || {}; + this.opts.log = this.opts.log || console.log; + this.opts.writer = { + println: function (ln) { + that.opts.log(ln); + } + }; +} + +TextLcov.TYPE = 'text-lcov'; +util.inherits(TextLcov, LcovOnly); + +LcovOnly.super_.mix(TextLcov, { + writeReport: function (collector) { + var that = this, + writer = this.opts.writer; + + collector.files().forEach(function (key) { + that.writeFileCoverage(writer, collector.fileCoverageFor(key)); + }); + + this.emit('done'); + } +}); + +module.exports = TextLcov; diff --git a/hm_sunwell/node_modules/istanbul/lib/report/text-summary.js b/hm_sunwell/node_modules/istanbul/lib/report/text-summary.js new file mode 100644 index 0000000..9537cbe --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/report/text-summary.js @@ -0,0 +1,93 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var path = require('path'), + util = require('util'), + mkdirp = require('mkdirp'), + defaults = require('./common/defaults'), + fs = require('fs'), + utils = require('../object-utils'), + Report = require('./index'); + +/** + * a `Report` implementation that produces text output for overall coverage in summary format. + * + * Usage + * ----- + * + * var report = require('istanbul').Report.create('text-summary'); + * + * @class TextSummaryReport + * @extends Report + * @module report + * @constructor + * @param {Object} opts optional + * @param {String} [opts.dir] the directory in which to the text coverage report will be written, when writing to a file + * @param {String} [opts.file] the filename for the report. When omitted, the report is written to console + */ +function TextSummaryReport(opts) { + Report.call(this); + opts = opts || {}; + this.dir = opts.dir || process.cwd(); + this.file = opts.file; + this.watermarks = opts.watermarks || defaults.watermarks(); +} + +TextSummaryReport.TYPE = 'text-summary'; +util.inherits(TextSummaryReport, Report); + +function lineForKey(summary, key, watermarks) { + var metrics = summary[key], + skipped, + result, + clazz = defaults.classFor(key, summary, watermarks); + key = key.substring(0, 1).toUpperCase() + key.substring(1); + if (key.length < 12) { key += ' '.substring(0, 12 - key.length); } + result = [ key , ':', metrics.pct + '%', '(', metrics.covered + '/' + metrics.total, ')'].join(' '); + skipped = metrics.skipped; + if (skipped > 0) { + result += ', ' + skipped + ' ignored'; + } + return defaults.colorize(result, clazz); +} + +Report.mix(TextSummaryReport, { + synopsis: function () { + return 'text report that prints a coverage summary across all files, typically to console'; + }, + getDefaultConfig: function () { + return { file: null }; + }, + writeReport: function (collector /*, sync */) { + var summaries = [], + finalSummary, + lines = [], + watermarks = this.watermarks, + text; + collector.files().forEach(function (file) { + summaries.push(utils.summarizeFileCoverage(collector.fileCoverageFor(file))); + }); + finalSummary = utils.mergeSummaryObjects.apply(null, summaries); + lines.push(''); + lines.push('=============================== Coverage summary ==============================='); + lines.push.apply(lines, [ + lineForKey(finalSummary, 'statements', watermarks), + lineForKey(finalSummary, 'branches', watermarks), + lineForKey(finalSummary, 'functions', watermarks), + lineForKey(finalSummary, 'lines', watermarks) + ]); + lines.push('================================================================================'); + text = lines.join('\n'); + if (this.file) { + mkdirp.sync(this.dir); + fs.writeFileSync(path.join(this.dir, this.file), text, 'utf8'); + } else { + console.log(text); + } + this.emit('done'); + } +}); + +module.exports = TextSummaryReport; diff --git a/hm_sunwell/node_modules/istanbul/lib/report/text.js b/hm_sunwell/node_modules/istanbul/lib/report/text.js new file mode 100644 index 0000000..8ab2b7d --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/report/text.js @@ -0,0 +1,234 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var path = require('path'), + mkdirp = require('mkdirp'), + util = require('util'), + fs = require('fs'), + defaults = require('./common/defaults'), + Report = require('./index'), + TreeSummarizer = require('../util/tree-summarizer'), + utils = require('../object-utils'), + PCT_COLS = 9, + MISSING_COL = 15, + TAB_SIZE = 1, + DELIM = ' |', + COL_DELIM = '-|'; + +/** + * a `Report` implementation that produces text output in a detailed table. + * + * Usage + * ----- + * + * var report = require('istanbul').Report.create('text'); + * + * @class TextReport + * @extends Report + * @module report + * @constructor + * @param {Object} opts optional + * @param {String} [opts.dir] the directory in which to the text coverage report will be written, when writing to a file + * @param {String} [opts.file] the filename for the report. When omitted, the report is written to console + * @param {Number} [opts.maxCols] the max column width of the report. By default, the width of the report is adjusted based on the length of the paths + * to be reported. + */ +function TextReport(opts) { + Report.call(this); + opts = opts || {}; + this.dir = opts.dir || process.cwd(); + this.file = opts.file; + this.summary = opts.summary; + this.maxCols = opts.maxCols || 0; + this.watermarks = opts.watermarks || defaults.watermarks(); +} + +TextReport.TYPE = 'text'; +util.inherits(TextReport, Report); + +function padding(num, ch) { + var str = '', + i; + ch = ch || ' '; + for (i = 0; i < num; i += 1) { + str += ch; + } + return str; +} + +function fill(str, width, right, tabs, clazz) { + tabs = tabs || 0; + str = String(str); + + var leadingSpaces = tabs * TAB_SIZE, + remaining = width - leadingSpaces, + leader = padding(leadingSpaces), + fmtStr = '', + fillStr, + strlen = str.length; + + if (remaining > 0) { + if (remaining >= strlen) { + fillStr = padding(remaining - strlen); + fmtStr = right ? fillStr + str : str + fillStr; + } else { + fmtStr = str.substring(strlen - remaining); + fmtStr = '... ' + fmtStr.substring(4); + } + } + + fmtStr = defaults.colorize(fmtStr, clazz); + return leader + fmtStr; +} + +function formatName(name, maxCols, level, clazz) { + return fill(name, maxCols, false, level, clazz); +} + +function formatPct(pct, clazz, width) { + return fill(pct, width || PCT_COLS, true, 0, clazz); +} + +function nodeName(node) { + return node.displayShortName() || 'All files'; +} + +function tableHeader(maxNameCols) { + var elements = []; + elements.push(formatName('File', maxNameCols, 0)); + elements.push(formatPct('% Stmts')); + elements.push(formatPct('% Branch')); + elements.push(formatPct('% Funcs')); + elements.push(formatPct('% Lines')); + elements.push(formatPct('Uncovered Lines', undefined, MISSING_COL)); + return elements.join(' |') + ' |'; +} + +function collectMissingLines(kind, linesCovered) { + var missingLines = []; + + if (kind !== 'file') { + return []; + } + + Object.keys(linesCovered).forEach(function (key) { + if (!linesCovered[key]) { + missingLines.push(key); + } + }); + + return missingLines; +} + +function tableRow(node, maxNameCols, level, watermarks) { + var name = nodeName(node), + statements = node.metrics.statements.pct, + branches = node.metrics.branches.pct, + functions = node.metrics.functions.pct, + lines = node.metrics.lines.pct, + missingLines = collectMissingLines(node.kind, node.metrics.linesCovered), + elements = []; + + elements.push(formatName(name, maxNameCols, level, defaults.classFor('statements', node.metrics, watermarks))); + elements.push(formatPct(statements, defaults.classFor('statements', node.metrics, watermarks))); + elements.push(formatPct(branches, defaults.classFor('branches', node.metrics, watermarks))); + elements.push(formatPct(functions, defaults.classFor('functions', node.metrics, watermarks))); + elements.push(formatPct(lines, defaults.classFor('lines', node.metrics, watermarks))); + elements.push(formatPct(missingLines.join(','), 'low', MISSING_COL)); + + return elements.join(DELIM) + DELIM; +} + +function findNameWidth(node, level, last) { + last = last || 0; + level = level || 0; + var idealWidth = TAB_SIZE * level + nodeName(node).length; + if (idealWidth > last) { + last = idealWidth; + } + node.children.forEach(function (child) { + last = findNameWidth(child, level + 1, last); + }); + return last; +} + +function makeLine(nameWidth) { + var name = padding(nameWidth, '-'), + pct = padding(PCT_COLS, '-'), + elements = []; + + elements.push(name); + elements.push(pct); + elements.push(pct); + elements.push(pct); + elements.push(pct); + elements.push(padding(MISSING_COL, '-')); + return elements.join(COL_DELIM) + COL_DELIM; +} + +function walk(node, nameWidth, array, level, watermarks) { + var line; + if (level === 0) { + line = makeLine(nameWidth); + array.push(line); + array.push(tableHeader(nameWidth)); + array.push(line); + } else { + array.push(tableRow(node, nameWidth, level, watermarks)); + } + node.children.forEach(function (child) { + walk(child, nameWidth, array, level + 1, watermarks); + }); + if (level === 0) { + array.push(line); + array.push(tableRow(node, nameWidth, level, watermarks)); + array.push(line); + } +} + +Report.mix(TextReport, { + synopsis: function () { + return 'text report that prints a coverage line for every file, typically to console'; + }, + getDefaultConfig: function () { + return { file: null, maxCols: 0 }; + }, + writeReport: function (collector /*, sync */) { + var summarizer = new TreeSummarizer(), + tree, + root, + nameWidth, + statsWidth = 4 * (PCT_COLS + 2) + MISSING_COL, + maxRemaining, + strings = [], + text; + + collector.files().forEach(function (key) { + summarizer.addFileCoverageSummary(key, utils.summarizeFileCoverage( + collector.fileCoverageFor(key) + )); + }); + tree = summarizer.getTreeSummary(); + root = tree.root; + nameWidth = findNameWidth(root); + if (this.maxCols > 0) { + maxRemaining = this.maxCols - statsWidth - 2; + if (nameWidth > maxRemaining) { + nameWidth = maxRemaining; + } + } + walk(root, nameWidth, strings, 0, this.watermarks); + text = strings.join('\n') + '\n'; + if (this.file) { + mkdirp.sync(this.dir); + fs.writeFileSync(path.join(this.dir, this.file), text, 'utf8'); + } else { + console.log(text); + } + this.emit('done'); + } +}); + +module.exports = TextReport; diff --git a/hm_sunwell/node_modules/istanbul/lib/reporter.js b/hm_sunwell/node_modules/istanbul/lib/reporter.js new file mode 100644 index 0000000..c7000d5 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/reporter.js @@ -0,0 +1,111 @@ +/* + Copyright (c) 2014, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +var Report = require('./report'), + configuration = require('./config'), + inputError = require('./util/input-error'); + +/** + * convenience mechanism to write one or more reports ensuring that config + * options are respected. + * Usage + * ----- + * + * var fs = require('fs'), + * reporter = new require('istanbul').Reporter(), + * collector = new require('istanbul').Collector(), + * sync = true; + * + * collector.add(JSON.parse(fs.readFileSync('coverage.json', 'utf8'))); + * reporter.add('lcovonly'); + * reporter.addAll(['clover', 'cobertura']); + * reporter.write(collector, sync, function () { console.log('done'); }); + * + * @class Reporter + * @param {Configuration} cfg the config object, a falsy value will load the + * default configuration instead + * @param {String} dir the directory in which to write the reports, may be falsy + * to use config or global defaults + * @constructor + * @module main + */ +function Reporter(cfg, dir) { + this.config = cfg || configuration.loadFile(); + this.dir = dir || this.config.reporting.dir(); + this.reports = {}; +} + +Reporter.prototype = { + /** + * adds a report to be generated. Must be one of the entries returned + * by `Report.getReportList()` + * @method add + * @param {String} fmt the format of the report to generate + */ + add: function (fmt) { + if (this.reports[fmt]) { // already added + return; + } + var config = this.config, + rptConfig = config.reporting.reportConfig()[fmt] || {}; + rptConfig.verbose = config.verbose; + rptConfig.dir = this.dir; + rptConfig.watermarks = config.reporting.watermarks(); + try { + this.reports[fmt] = Report.create(fmt, rptConfig); + } catch (ex) { + throw inputError.create('Invalid report format [' + fmt + ']'); + } + }, + /** + * adds an array of report formats to be generated + * @method addAll + * @param {Array} fmts an array of report formats + */ + addAll: function (fmts) { + var that = this; + fmts.forEach(function (f) { + that.add(f); + }); + }, + /** + * writes all reports added and calls the callback when done + * @method write + * @param {Collector} collector the collector having the coverage data + * @param {Boolean} sync true to write reports synchronously + * @param {Function} callback the callback to call when done. When `sync` + * is true, the callback will be called in the same process tick. + */ + write: function (collector, sync, callback) { + var reports = this.reports, + verbose = this.config.verbose, + handler = this.handleDone.bind(this, callback); + + this.inProgress = Object.keys(reports).length; + + Object.keys(reports).forEach(function (name) { + var report = reports[name]; + if (verbose) { + console.error('Write report: ' + name); + } + report.on('done', handler); + report.writeReport(collector, sync); + }); + }, + /* + * handles listening on all reports to be completed before calling the callback + * @method handleDone + * @private + * @param {Function} callback the callback to call when all reports are + * written + */ + handleDone: function (callback) { + this.inProgress -= 1; + if (this.inProgress === 0) { + return callback(); + } + } +}; + +module.exports = Reporter; diff --git a/hm_sunwell/node_modules/istanbul/lib/store/fslookup.js b/hm_sunwell/node_modules/istanbul/lib/store/fslookup.js new file mode 100644 index 0000000..b00cc17 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/store/fslookup.js @@ -0,0 +1,61 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var util = require('util'), + fs = require('fs'), + Store = require('./index'); + +/** + * a `Store` implementation that doesn't actually store anything. It assumes that keys + * are absolute file paths, and contents are contents of those files. + * Thus, `set` for this store is no-op, `get` returns the + * contents of the filename that the key represents, `hasKey` returns true if the key + * supplied is a valid file path and `keys` always returns an empty array. + * + * Usage + * ----- + * + * var store = require('istanbul').Store.create('fslookup'); + * + * + * @class LookupStore + * @extends Store + * @module store + * @constructor + */ +function LookupStore(opts) { + Store.call(this, opts); +} + +LookupStore.TYPE = 'fslookup'; +util.inherits(LookupStore, Store); + +Store.mix(LookupStore, { + keys: function () { + return []; + }, + get: function (key) { + return fs.readFileSync(key, 'utf8'); + }, + hasKey: function (key) { + var stats; + try { + stats = fs.statSync(key); + return stats.isFile(); + } catch (ex) { + return false; + } + }, + set: function (key /*, contents */) { + if (!this.hasKey(key)) { + throw new Error('Attempt to set contents for non-existent file [' + key + '] on a fslookup store'); + } + return key; + } +}); + + +module.exports = LookupStore; + diff --git a/hm_sunwell/node_modules/istanbul/lib/store/index.js b/hm_sunwell/node_modules/istanbul/lib/store/index.js new file mode 100644 index 0000000..85ffc4f --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/store/index.js @@ -0,0 +1,123 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var Factory = require('../util/factory'), + factory = new Factory('store', __dirname, false); +/** + * An abstraction for keeping track of content against some keys (e.g. + * original source, instrumented source, coverage objects against file names). + * This class is both the base class as well as a factory for `Store` implementations. + * + * Usage + * ----- + * + * var Store = require('istanbul').Store, + * store = Store.create('memory'); + * + * //basic use + * store.set('foo', 'foo-content'); + * var content = store.get('foo'); + * + * //keys and values + * store.keys().forEach(function (key) { + * console.log(key + ':\n' + store.get(key); + * }); + * if (store.hasKey('bar') { console.log(store.get('bar'); } + * + * + * //syntactic sugar + * store.setObject('foo', { foo: true }); + * console.log(store.getObject('foo').foo); + * + * store.dispose(); + * + * @class Store + * @constructor + * @module store + * @param {Object} options Optional. The options supported by a specific store implementation. + * @main store + */ +function Store(/* options */) {} + +//add register, create, mix, loadAll, getStoreList as class methods +factory.bindClassMethods(Store); + +/** + * registers a new store implementation. + * @method register + * @static + * @param {Function} constructor the constructor function for the store. This function must have a + * `TYPE` property of type String, that will be used in `Store.create()` + */ +/** + * returns a store implementation of the specified type. + * @method create + * @static + * @param {String} type the type of store to create + * @param {Object} opts Optional. Options specific to the store implementation + * @return {Store} a new store of the specified type + */ + +Store.prototype = { + /** + * sets some content associated with a specific key. The manner in which + * duplicate keys are handled for multiple `set()` calls with the same + * key is implementation-specific. + * + * @method set + * @param {String} key the key for the content + * @param {String} contents the contents for the key + */ + set: function (/* key, contents */) { throw new Error("set: must be overridden"); }, + /** + * returns the content associated to a specific key or throws if the key + * was not `set` + * @method get + * @param {String} key the key for which to get the content + * @return {String} the content for the specified key + */ + get: function (/* key */) { throw new Error("get: must be overridden"); }, + /** + * returns a list of all known keys + * @method keys + * @return {Array} an array of seen keys + */ + keys: function () { throw new Error("keys: must be overridden"); }, + /** + * returns true if the key is one for which a `get()` call would work. + * @method hasKey + * @param {String} key + * @return true if the key is valid for this store, false otherwise + */ + hasKey: function (/* key */) { throw new Error("hasKey: must be overridden"); }, + /** + * lifecycle method to dispose temporary resources associated with the store + * @method dispose + */ + dispose: function () {}, + /** + * sugar method to return an object associated with a specific key. Throws + * if the content set against the key was not a valid JSON string. + * @method getObject + * @param {String} key the key for which to return the associated object + * @return {Object} the object corresponding to the key + */ + getObject: function (key) { + return JSON.parse(this.get(key)); + }, + /** + * sugar method to set an object against a specific key. + * @method setObject + * @param {String} key the key for the object + * @param {Object} object the object to be stored + */ + setObject: function (key, object) { + return this.set(key, JSON.stringify(object)); + } +}; + +module.exports = Store; + + diff --git a/hm_sunwell/node_modules/istanbul/lib/store/memory.js b/hm_sunwell/node_modules/istanbul/lib/store/memory.js new file mode 100644 index 0000000..ff96fbd --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/store/memory.js @@ -0,0 +1,56 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var util = require('util'), + Store = require('./index'); + +/** + * a `Store` implementation using an in-memory object. + * + * Usage + * ----- + * + * var store = require('istanbul').Store.create('memory'); + * + * + * @class MemoryStore + * @extends Store + * @module store + * @constructor + */ +function MemoryStore() { + Store.call(this); + this.map = {}; +} + +MemoryStore.TYPE = 'memory'; +util.inherits(MemoryStore, Store); + +Store.mix(MemoryStore, { + set: function (key, contents) { + this.map[key] = contents; + }, + + get: function (key) { + if (!this.hasKey(key)) { + throw new Error('Unable to find entry for [' + key + ']'); + } + return this.map[key]; + }, + + hasKey: function (key) { + return this.map.hasOwnProperty(key); + }, + + keys: function () { + return Object.keys(this.map); + }, + + dispose: function () { + this.map = {}; + } +}); + +module.exports = MemoryStore; diff --git a/hm_sunwell/node_modules/istanbul/lib/store/tmp.js b/hm_sunwell/node_modules/istanbul/lib/store/tmp.js new file mode 100644 index 0000000..31789c8 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/store/tmp.js @@ -0,0 +1,81 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var util = require('util'), + path = require('path'), + os = require('os'), + fs = require('fs'), + mkdirp = require('mkdirp'), + Store = require('./index'); + +function makeTempDir() { + var dir = path.join(os.tmpdir ? os.tmpdir() : /* istanbul ignore next */ (process.env.TMPDIR || '/tmp'), 'ts' + new Date().getTime()); + mkdirp.sync(dir); + return dir; +} +/** + * a `Store` implementation using temporary files. + * + * Usage + * ----- + * + * var store = require('istanbul').Store.create('tmp'); + * + * + * @class TmpStore + * @extends Store + * @module store + * @param {Object} opts Optional. + * @param {String} [opts.tmp] a pre-existing directory to use as the `tmp` directory. When not specified, a random directory + * is created under `os.tmpdir()` + * @constructor + */ +function TmpStore(opts) { + opts = opts || {}; + this.tmp = opts.tmp || makeTempDir(); + this.map = {}; + this.seq = 0; + this.prefix = 't' + new Date().getTime() + '-'; +} + +TmpStore.TYPE = 'tmp'; +util.inherits(TmpStore, Store); + +Store.mix(TmpStore, { + generateTmpFileName: function () { + this.seq += 1; + return path.join(this.tmp, this.prefix + this.seq + '.tmp'); + }, + + set: function (key, contents) { + var tmpFile = this.generateTmpFileName(); + fs.writeFileSync(tmpFile, contents, 'utf8'); + this.map[key] = tmpFile; + }, + + get: function (key) { + var tmpFile = this.map[key]; + if (!tmpFile) { throw new Error('Unable to find tmp entry for [' + tmpFile + ']'); } + return fs.readFileSync(tmpFile, 'utf8'); + }, + + hasKey: function (key) { + return !!this.map[key]; + }, + + keys: function () { + return Object.keys(this.map); + }, + + dispose: function () { + var map = this.map; + Object.keys(map).forEach(function (key) { + fs.unlinkSync(map[key]); + }); + this.map = {}; + } +}); + +module.exports = TmpStore; diff --git a/hm_sunwell/node_modules/istanbul/lib/util/factory.js b/hm_sunwell/node_modules/istanbul/lib/util/factory.js new file mode 100644 index 0000000..9f3d6f3 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/factory.js @@ -0,0 +1,88 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var util = require('util'), + path = require('path'), + fs = require('fs'), + abbrev = require('abbrev'); + +function Factory(kind, dir, allowAbbreviations) { + this.kind = kind; + this.dir = dir; + this.allowAbbreviations = allowAbbreviations; + this.classMap = {}; + this.abbreviations = null; +} + +Factory.prototype = { + + knownTypes: function () { + var keys = Object.keys(this.classMap); + keys.sort(); + return keys; + }, + + resolve: function (abbreviatedType) { + if (!this.abbreviations) { + this.abbreviations = abbrev(this.knownTypes()); + } + return this.abbreviations[abbreviatedType]; + }, + + register: function (constructor) { + var type = constructor.TYPE; + if (!type) { throw new Error('Could not register ' + this.kind + ' constructor [no TYPE property]: ' + util.inspect(constructor)); } + this.classMap[type] = constructor; + this.abbreviations = null; + }, + + create: function (type, opts) { + var allowAbbrev = this.allowAbbreviations, + realType = allowAbbrev ? this.resolve(type) : type, + Cons; + + Cons = realType ? this.classMap[realType] : null; + if (!Cons) { throw new Error('Invalid ' + this.kind + ' [' + type + '], allowed values are ' + this.knownTypes().join(', ')); } + return new Cons(opts); + }, + + loadStandard: function (dir) { + var that = this; + fs.readdirSync(dir).forEach(function (file) { + if (file !== 'index.js' && file.indexOf('.js') === file.length - 3) { + try { + that.register(require(path.resolve(dir, file))); + } catch (ex) { + console.error(ex.message); + console.error(ex.stack); + throw new Error('Could not register ' + that.kind + ' from file ' + file); + } + } + }); + }, + + bindClassMethods: function (Cons) { + var tmpKind = this.kind.charAt(0).toUpperCase() + this.kind.substring(1), //ucfirst + allowAbbrev = this.allowAbbreviations; + + Cons.mix = Factory.mix; + Cons.register = this.register.bind(this); + Cons.create = this.create.bind(this); + Cons.loadAll = this.loadStandard.bind(this, this.dir); + Cons['get' + tmpKind + 'List'] = this.knownTypes.bind(this); + if (allowAbbrev) { + Cons['resolve' + tmpKind + 'Name'] = this.resolve.bind(this); + } + } +}; + +Factory.mix = function (cons, proto) { + Object.keys(proto).forEach(function (key) { + cons.prototype[key] = proto[key]; + }); +}; + +module.exports = Factory; + diff --git a/hm_sunwell/node_modules/istanbul/lib/util/file-matcher.js b/hm_sunwell/node_modules/istanbul/lib/util/file-matcher.js new file mode 100644 index 0000000..9860642 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/file-matcher.js @@ -0,0 +1,76 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var async = require('async'), + glob = require('glob'), + fs = require('fs'), + path = require('path'), + seq = 0; + +function filesFor(options, callback) { + if (!callback && typeof options === 'function') { + callback = options; + options = null; + } + options = options || {}; + + var root = options.root, + includes = options.includes, + excludes = options.excludes, + realpath = options.realpath, + relative = options.relative, + opts; + + root = root || process.cwd(); + includes = includes && Array.isArray(includes) ? includes : [ '**/*.js' ]; + excludes = excludes && Array.isArray(excludes) ? excludes : [ '**/node_modules/**' ]; + + opts = { cwd: root, nodir: true, ignore: excludes }; + seq += 1; + opts['x' + seq + new Date().getTime()] = true; //cache buster for minimatch cache bug + glob(includes.join(' '), opts, function (err, files) { + if (err) { return callback(err); } + if (relative) { return callback(err, files); } + + if (!realpath) { + files = files.map(function (file) { return path.resolve(root, file); }); + return callback(err, files); + } + + var realPathCache = module.constructor._realpathCache || {}; + + async.map(files, function (file, done) { + fs.realpath(path.resolve(root, file), realPathCache, done); + }, callback); + }); +} + +function matcherFor(options, callback) { + + if (!callback && typeof options === 'function') { + callback = options; + options = null; + } + options = options || {}; + options.relative = false; //force absolute paths + options.realpath = true; //force real paths (to match Node.js module paths) + + filesFor(options, function (err, files) { + var fileMap = {}, + matchFn; + if (err) { return callback(err); } + files.forEach(function (file) { fileMap[file] = true; }); + + matchFn = function (file) { return fileMap[file]; }; + matchFn.files = Object.keys(fileMap); + return callback(null, matchFn); + }); +} + +module.exports = { + filesFor: filesFor, + matcherFor: matcherFor +}; + diff --git a/hm_sunwell/node_modules/istanbul/lib/util/file-writer.js b/hm_sunwell/node_modules/istanbul/lib/util/file-writer.js new file mode 100644 index 0000000..3367dcc --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/file-writer.js @@ -0,0 +1,154 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var path = require('path'), + util = require('util'), + fs = require('fs'), + async = require('async'), + mkdirp = require('mkdirp'), + writer = require('./writer'), + Writer = writer.Writer, + ContentWriter = writer.ContentWriter; + +function extend(cons, proto) { + Object.keys(proto).forEach(function (k) { + cons.prototype[k] = proto[k]; + }); +} + +function BufferedContentWriter() { + ContentWriter.call(this); + this.content = ''; +} +util.inherits(BufferedContentWriter, ContentWriter); + +extend(BufferedContentWriter, { + write: function (str) { + this.content += str; + }, + getContent: function () { + return this.content; + } +}); + +function StreamContentWriter(stream) { + ContentWriter.call(this); + this.stream = stream; +} +util.inherits(StreamContentWriter, ContentWriter); + +extend(StreamContentWriter, { + write: function (str) { + this.stream.write(str); + } +}); + +function SyncFileWriter() { + Writer.call(this); +} +util.inherits(SyncFileWriter, Writer); + +extend(SyncFileWriter, { + writeFile: function (file, callback) { + mkdirp.sync(path.dirname(file)); + var cw = new BufferedContentWriter(); + callback(cw); + fs.writeFileSync(file, cw.getContent(), 'utf8'); + }, + done: function () { + this.emit('done'); //everything already done + } +}); + +function AsyncFileWriter() { + this.queue = async.queue(this.processFile.bind(this), 20); + this.openFileMap = {}; +} + +util.inherits(AsyncFileWriter, Writer); + +extend(AsyncFileWriter, { + writeFile: function (file, callback) { + this.openFileMap[file] = true; + this.queue.push({ file: file, callback: callback }); + }, + processFile: function (task, cb) { + var file = task.file, + userCallback = task.callback, + that = this, + stream, + contentWriter; + + mkdirp.sync(path.dirname(file)); + stream = fs.createWriteStream(file); + stream.on('close', function () { + delete that.openFileMap[file]; + cb(); + that.checkDone(); + }); + stream.on('error', function (err) { that.emit('error', err); }); + contentWriter = new StreamContentWriter(stream); + userCallback(contentWriter); + stream.end(); + }, + done: function () { + this.doneCalled = true; + this.checkDone(); + }, + checkDone: function () { + if (!this.doneCalled) { return; } + if (Object.keys(this.openFileMap).length === 0) { + this.emit('done'); + } + } +}); +/** + * a concrete writer implementation that can write files synchronously or + * asynchronously based on the constructor argument passed to it. + * + * Usage + * ----- + * + * var sync = true, + * fileWriter = new require('istanbul').FileWriter(sync); + * + * fileWriter.on('done', function () { console.log('done'); }); + * fileWriter.copyFile('/foo/bar.jpg', '/baz/bar.jpg'); + * fileWriter.writeFile('/foo/index.html', function (contentWriter) { + * contentWriter.println(''); + * contentWriter.println(''); + * }); + * fileWriter.done(); // will emit the `done` event when all files are written + * + * @class FileWriter + * @extends Writer + * @module io + * @param sync + * @constructor + */ +function FileWriter(sync) { + Writer.call(this); + var that = this; + this.delegate = sync ? new SyncFileWriter() : new AsyncFileWriter(); + this.delegate.on('error', function (err) { that.emit('error', err); }); + this.delegate.on('done', function () { that.emit('done'); }); +} + +util.inherits(FileWriter, Writer); + +extend(FileWriter, { + copyFile: function (source, dest) { + mkdirp.sync(path.dirname(dest)); + fs.writeFileSync(dest, fs.readFileSync(source)); + }, + writeFile: function (file, callback) { + this.delegate.writeFile(file, callback); + }, + done: function () { + this.delegate.done(); + } +}); + +module.exports = FileWriter; \ No newline at end of file diff --git a/hm_sunwell/node_modules/istanbul/lib/util/help-formatter.js b/hm_sunwell/node_modules/istanbul/lib/util/help-formatter.js new file mode 100644 index 0000000..8d9136a --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/help-formatter.js @@ -0,0 +1,30 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var OPT_PREFIX = " ", + OPT_START = OPT_PREFIX.length, + TEXT_START = 14, + STOP = 80, + wrap = require('wordwrap')(TEXT_START, STOP), + paraWrap = require('wordwrap')(1, STOP); + +function formatPara(text) { + return paraWrap(text); +} + +function formatOption(option, helpText) { + var formattedText = wrap(helpText); + + if (option.length > TEXT_START - OPT_START - 2) { + return OPT_PREFIX + option + '\n' + formattedText; + } else { + return OPT_PREFIX + option + formattedText.substring((OPT_PREFIX + option).length); + } +} + +module.exports = { + formatPara: formatPara, + formatOption: formatOption +}; \ No newline at end of file diff --git a/hm_sunwell/node_modules/istanbul/lib/util/input-error.js b/hm_sunwell/node_modules/istanbul/lib/util/input-error.js new file mode 100644 index 0000000..488b71a --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/input-error.js @@ -0,0 +1,12 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +module.exports.create = function (message) { + var err = new Error(message); + err.inputError = true; + return err; +}; + + diff --git a/hm_sunwell/node_modules/istanbul/lib/util/insertion-text.js b/hm_sunwell/node_modules/istanbul/lib/util/insertion-text.js new file mode 100644 index 0000000..d257643 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/insertion-text.js @@ -0,0 +1,109 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +function InsertionText(text, consumeBlanks) { + this.text = text; + this.origLength = text.length; + this.offsets = []; + this.consumeBlanks = consumeBlanks; + this.startPos = this.findFirstNonBlank(); + this.endPos = this.findLastNonBlank(); +} + +var WHITE_RE = /[ \f\n\r\t\v\u00A0\u2028\u2029]/; + +InsertionText.prototype = { + + findFirstNonBlank: function () { + var pos = -1, + text = this.text, + len = text.length, + i; + for (i = 0; i < len; i += 1) { + if (!text.charAt(i).match(WHITE_RE)) { + pos = i; + break; + } + } + return pos; + }, + findLastNonBlank: function () { + var text = this.text, + len = text.length, + pos = text.length + 1, + i; + for (i = len - 1; i >= 0; i -= 1) { + if (!text.charAt(i).match(WHITE_RE)) { + pos = i; + break; + } + } + return pos; + }, + originalLength: function () { + return this.origLength; + }, + + insertAt: function (col, str, insertBefore, consumeBlanks) { + consumeBlanks = typeof consumeBlanks === 'undefined' ? this.consumeBlanks : consumeBlanks; + col = col > this.originalLength() ? this.originalLength() : col; + col = col < 0 ? 0 : col; + + if (consumeBlanks) { + if (col <= this.startPos) { + col = 0; + } + if (col > this.endPos) { + col = this.origLength; + } + } + + var len = str.length, + offset = this.findOffset(col, len, insertBefore), + realPos = col + offset, + text = this.text; + this.text = text.substring(0, realPos) + str + text.substring(realPos); + return this; + }, + + findOffset: function (pos, len, insertBefore) { + var offsets = this.offsets, + offsetObj, + cumulativeOffset = 0, + i; + + for (i = 0; i < offsets.length; i += 1) { + offsetObj = offsets[i]; + if (offsetObj.pos < pos || (offsetObj.pos === pos && !insertBefore)) { + cumulativeOffset += offsetObj.len; + } + if (offsetObj.pos >= pos) { + break; + } + } + if (offsetObj && offsetObj.pos === pos) { + offsetObj.len += len; + } else { + offsets.splice(i, 0, { pos: pos, len: len }); + } + return cumulativeOffset; + }, + + wrap: function (startPos, startText, endPos, endText, consumeBlanks) { + this.insertAt(startPos, startText, true, consumeBlanks); + this.insertAt(endPos, endText, false, consumeBlanks); + return this; + }, + + wrapLine: function (startText, endText) { + this.wrap(0, startText, this.originalLength(), endText); + }, + + toString: function () { + return this.text; + } +}; + +module.exports = InsertionText; \ No newline at end of file diff --git a/hm_sunwell/node_modules/istanbul/lib/util/meta.js b/hm_sunwell/node_modules/istanbul/lib/util/meta.js new file mode 100644 index 0000000..0384459 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/meta.js @@ -0,0 +1,13 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +var path = require('path'), + fs = require('fs'), + pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json'), 'utf8')); + +module.exports = { + NAME: pkg.name, + VERSION: pkg.version +}; + diff --git a/hm_sunwell/node_modules/istanbul/lib/util/tree-summarizer.js b/hm_sunwell/node_modules/istanbul/lib/util/tree-summarizer.js new file mode 100644 index 0000000..df350f5 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/tree-summarizer.js @@ -0,0 +1,213 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var path = require('path'), + SEP = path.sep || '/', + utils = require('../object-utils'); + +function commonArrayPrefix(first, second) { + var len = first.length < second.length ? first.length : second.length, + i, + ret = []; + for (i = 0; i < len; i += 1) { + if (first[i] === second[i]) { + ret.push(first[i]); + } else { + break; + } + } + return ret; +} + +function findCommonArrayPrefix(args) { + if (args.length === 0) { + return []; + } + + var separated = args.map(function (arg) { return arg.split(SEP); }), + ret = separated.pop(); + + if (separated.length === 0) { + return ret.slice(0, ret.length - 1); + } else { + return separated.reduce(commonArrayPrefix, ret); + } +} + +function Node(fullName, kind, metrics) { + this.name = fullName; + this.fullName = fullName; + this.kind = kind; + this.metrics = metrics || null; + this.parent = null; + this.children = []; +} + +Node.prototype = { + displayShortName: function () { + return this.relativeName; + }, + fullPath: function () { + return this.fullName; + }, + addChild: function (child) { + this.children.push(child); + child.parent = this; + }, + toJSON: function () { + return { + name: this.name, + relativeName: this.relativeName, + fullName: this.fullName, + kind: this.kind, + metrics: this.metrics, + parent: this.parent === null ? null : this.parent.name, + children: this.children.map(function (node) { return node.toJSON(); }) + }; + } +}; + +function TreeSummary(summaryMap, commonPrefix) { + this.prefix = commonPrefix; + this.convertToTree(summaryMap, commonPrefix); +} + +TreeSummary.prototype = { + getNode: function (shortName) { + return this.map[shortName]; + }, + convertToTree: function (summaryMap, arrayPrefix) { + var nodes = [], + rootPath = arrayPrefix.join(SEP) + SEP, + root = new Node(rootPath, 'dir'), + tmp, + tmpChildren, + seen = {}, + filesUnderRoot = false; + + seen[rootPath] = root; + Object.keys(summaryMap).forEach(function (key) { + var metrics = summaryMap[key], + node, + parentPath, + parent; + node = new Node(key, 'file', metrics); + seen[key] = node; + nodes.push(node); + parentPath = path.dirname(key) + SEP; + if (parentPath === SEP + SEP || parentPath === '.' + SEP) { + parentPath = SEP + '__root__' + SEP; + } + parent = seen[parentPath]; + if (!parent) { + parent = new Node(parentPath, 'dir'); + root.addChild(parent); + seen[parentPath] = parent; + } + parent.addChild(node); + if (parent === root) { filesUnderRoot = true; } + }); + + if (filesUnderRoot && arrayPrefix.length > 0) { + arrayPrefix.pop(); //start at one level above + tmp = root; + tmpChildren = tmp.children; + tmp.children = []; + root = new Node(arrayPrefix.join(SEP) + SEP, 'dir'); + root.addChild(tmp); + tmpChildren.forEach(function (child) { + if (child.kind === 'dir') { + root.addChild(child); + } else { + tmp.addChild(child); + } + }); + } + this.fixupNodes(root, arrayPrefix.join(SEP) + SEP); + this.calculateMetrics(root); + this.root = root; + this.map = {}; + this.indexAndSortTree(root, this.map); + }, + + fixupNodes: function (node, prefix, parent) { + var that = this; + if (node.name.indexOf(prefix) === 0) { + node.name = node.name.substring(prefix.length); + } + if (node.name.charAt(0) === SEP) { + node.name = node.name.substring(1); + } + if (parent) { + if (parent.name !== '__root__' + SEP) { + node.relativeName = node.name.substring(parent.name.length); + } else { + node.relativeName = node.name; + } + } else { + node.relativeName = node.name.substring(prefix.length); + } + node.children.forEach(function (child) { + that.fixupNodes(child, prefix, node); + }); + }, + calculateMetrics: function (entry) { + var that = this, + fileChildren; + if (entry.kind !== 'dir') {return; } + entry.children.forEach(function (child) { + that.calculateMetrics(child); + }); + entry.metrics = utils.mergeSummaryObjects.apply( + null, + entry.children.map(function (child) { return child.metrics; }) + ); + // calclulate "java-style" package metrics where there is no hierarchy + // across packages + fileChildren = entry.children.filter(function (n) { return n.kind !== 'dir'; }); + if (fileChildren.length > 0) { + entry.packageMetrics = utils.mergeSummaryObjects.apply( + null, + fileChildren.map(function (child) { return child.metrics; }) + ); + } else { + entry.packageMetrics = null; + } + }, + indexAndSortTree: function (node, map) { + var that = this; + map[node.name] = node; + node.children.sort(function (a, b) { + a = a.relativeName; + b = b.relativeName; + return a < b ? -1 : a > b ? 1 : 0; + }); + node.children.forEach(function (child) { + that.indexAndSortTree(child, map); + }); + }, + toJSON: function () { + return { + prefix: this.prefix, + root: this.root.toJSON() + }; + } +}; + +function TreeSummarizer() { + this.summaryMap = {}; +} + +TreeSummarizer.prototype = { + addFileCoverageSummary: function (filePath, metrics) { + this.summaryMap[filePath] = metrics; + }, + getTreeSummary: function () { + var commonArrayPrefix = findCommonArrayPrefix(Object.keys(this.summaryMap)); + return new TreeSummary(this.summaryMap, commonArrayPrefix); + } +}; + +module.exports = TreeSummarizer; diff --git a/hm_sunwell/node_modules/istanbul/lib/util/writer.js b/hm_sunwell/node_modules/istanbul/lib/util/writer.js new file mode 100644 index 0000000..f5e6829 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/writer.js @@ -0,0 +1,92 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +var util = require('util'), + EventEmitter = require('events').EventEmitter; + +function extend(cons, proto) { + Object.keys(proto).forEach(function (k) { + cons.prototype[k] = proto[k]; + }); +} + +/** + * abstract interfaces for writing content + * @class ContentWriter + * @module io + * @main io + * @constructor + */ +//abstract interface for writing content +function ContentWriter() { +} + +ContentWriter.prototype = { + /** + * writes the specified string as-is + * @method write + * @param {String} str the string to write + */ + write: /* istanbul ignore next: abstract method */ function (/* str */) { + throw new Error('write: must be overridden'); + }, + /** + * writes the specified string with a newline at the end + * @method println + * @param {String} str the string to write + */ + println: function (str) { this.write(str + '\n'); } +}; + +/** + * abstract interface for writing files and assets. The caller is expected to + * call `done` on the writer after it has finished writing all the required + * files. The writer is an event-emitter that emits a `done` event when `done` + * is called on it *and* all files have successfully been written. + * + * @class Writer + * @constructor + */ +function Writer() { + EventEmitter.call(this); +} + +util.inherits(Writer, EventEmitter); + +extend(Writer, { + /** + * allows writing content to a file using a callback that is passed a content writer + * @method writeFile + * @param {String} file the name of the file to write + * @param {Function} callback the callback that is called as `callback(contentWriter)` + */ + writeFile: /* istanbul ignore next: abstract method */ function (/* file, callback */) { + throw new Error('writeFile: must be overridden'); + }, + /** + * copies a file from source to destination + * @method copyFile + * @param {String} source the file to copy, found on the file system + * @param {String} dest the destination path + */ + copyFile: /* istanbul ignore next: abstract method */ function (/* source, dest */) { + throw new Error('copyFile: must be overridden'); + }, + /** + * marker method to indicate that the caller is done with this writer object + * The writer is expected to emit a `done` event only after this method is called + * and it is truly done. + * @method done + */ + done: /* istanbul ignore next: abstract method */ function () { + throw new Error('done: must be overridden'); + } +}); + +module.exports = { + Writer: Writer, + ContentWriter: ContentWriter +}; + diff --git a/hm_sunwell/node_modules/istanbul/lib/util/yui-load-hook.js b/hm_sunwell/node_modules/istanbul/lib/util/yui-load-hook.js new file mode 100644 index 0000000..9b1365d --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/lib/util/yui-load-hook.js @@ -0,0 +1,49 @@ +/* + Copyright (c) 2012, Yahoo! Inc. All rights reserved. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + +//EXPERIMENTAL code: do not rely on this in anyway until the docs say it is allowed + +var path = require('path'), + yuiRegexp = /yui-nodejs\.js$/; + +module.exports = function (matchFn, transformFn, verbose) { + return function (file) { + if (!file.match(yuiRegexp)) { + return; + } + var YMain = require(file), + YUI, + loaderFn, + origGet; + + if (YMain.YUI) { + YUI = YMain.YUI; + loaderFn = YUI.Env && YUI.Env.mods && YUI.Env.mods['loader-base'] ? YUI.Env.mods['loader-base'].fn : null; + if (!loaderFn) { return; } + if (verbose) { console.log('Applying YUI load post-hook'); } + YUI.Env.mods['loader-base'].fn = function (Y) { + loaderFn.call(null, Y); + origGet = Y.Get._exec; + Y.Get._exec = function (data, url, cb) { + if (matchFn(url) || matchFn(path.resolve(url))) { //allow for relative paths as well + if (verbose) { + console.log('Transforming [' + url + ']'); + } + try { + data = transformFn(data, url); + } catch (ex) { + console.error('Error transforming: ' + url + ' return original code'); + console.error(ex.message || ex); + if (ex.stack) { console.error(ex.stack); } + } + } + return origGet.call(Y, data, url, cb); + }; + return Y; + }; + } + }; +}; + diff --git a/hm_sunwell/node_modules/istanbul/node_modules/supports-color/browser.js b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/browser.js new file mode 100644 index 0000000..ae7c87b --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/browser.js @@ -0,0 +1,2 @@ +'use strict'; +module.exports = false; diff --git a/hm_sunwell/node_modules/istanbul/node_modules/supports-color/index.js b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/index.js new file mode 100644 index 0000000..113040d --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/index.js @@ -0,0 +1,72 @@ +'use strict'; +var hasFlag = require('has-flag'); + +var support = function (level) { + if (level === 0) { + return false; + } + + return { + level: level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +}; + +var supportLevel = (function () { + if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + return 1; + } + + if (process.stdout && !process.stdout.isTTY) { + return 0; + } + + if (process.platform === 'win32') { + return 1; + } + + if ('COLORTERM' in process.env) { + return 1; + } + + if (process.env.TERM === 'dumb') { + return 0; + } + + if (/^xterm-256(?:color)?/.test(process.env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return 1; + } + + return 0; +})(); + +if (supportLevel === 0 && 'FORCE_COLOR' in process.env) { + supportLevel = 1; +} + +module.exports = process && support(supportLevel); diff --git a/hm_sunwell/node_modules/istanbul/node_modules/supports-color/license b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/istanbul/node_modules/supports-color/package.json b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/package.json new file mode 100644 index 0000000..9838976 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/package.json @@ -0,0 +1,120 @@ +{ + "_args": [ + [ + "supports-color@^3.1.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul" + ] + ], + "_from": "supports-color@>=3.1.0 <4.0.0", + "_id": "supports-color@3.1.2", + "_inCache": true, + "_installable": true, + "_location": "/istanbul/supports-color", + "_nodeVersion": "4.1.1", + "_npmUser": { + "email": "sindresorhus@gmail.com", + "name": "sindresorhus" + }, + "_npmVersion": "2.14.4", + "_phantomChildren": {}, + "_requested": { + "name": "supports-color", + "raw": "supports-color@^3.1.0", + "rawSpec": "^3.1.0", + "scope": null, + "spec": ">=3.1.0 <4.0.0", + "type": "range" + }, + "_requiredBy": [ + "/istanbul" + ], + "_resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "_shasum": "72a262894d9d408b956ca05ff37b2ed8a6e2a2d5", + "_shrinkwrap": null, + "_spec": "supports-color@^3.1.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/istanbul", + "author": { + "email": "sindresorhus@gmail.com", + "name": "Sindre Sorhus", + "url": "sindresorhus.com" + }, + "browser": "browser.js", + "bugs": { + "url": "https://github.com/chalk/supports-color/issues" + }, + "dependencies": { + "has-flag": "^1.0.0" + }, + "description": "Detect whether a terminal supports color", + "devDependencies": { + "mocha": "*", + "require-uncached": "^1.0.2", + "xo": "*" + }, + "directories": {}, + "dist": { + "shasum": "72a262894d9d408b956ca05ff37b2ed8a6e2a2d5", + "tarball": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz" + }, + "engines": { + "node": ">=0.8.0" + }, + "files": [ + "browser.js", + "index.js" + ], + "gitHead": "d9e363732f48ad2bc6b936357246b55e136aa989", + "homepage": "https://github.com/chalk/supports-color", + "keywords": [ + "16m", + "256", + "ansi", + "capability", + "cli", + "color", + "colors", + "colour", + "command-line", + "console", + "detect", + "million", + "rgb", + "shell", + "styles", + "support", + "supports", + "terminal", + "truecolor", + "tty", + "xterm" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + } + ], + "name": "supports-color", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/supports-color.git" + }, + "scripts": { + "test": "xo && mocha", + "travis": "mocha" + }, + "version": "3.1.2", + "xo": { + "envs": [ + "mocha", + "node" + ] + } +} diff --git a/hm_sunwell/node_modules/istanbul/node_modules/supports-color/readme.md b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/readme.md new file mode 100644 index 0000000..f7bae4c --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/node_modules/supports-color/readme.md @@ -0,0 +1,60 @@ +# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color) + +> Detect whether a terminal supports color + + +## Install + +``` +$ npm install --save supports-color +``` + + +## Usage + +```js +var supportsColor = require('supports-color'); + +if (supportsColor) { + console.log('Terminal supports color'); +} + +if (supportsColor.has256) { + console.log('Terminal supports 256 colors'); +} + +if (supportsColor.has16m) { + console.log('Terminal supports 16 million colors (truecolor)'); +} +``` + + +## API + +Returns an `object`, or `false` if color is not supported. + +The returned object specifies a level of support for color through a `.level` property and a corresponding flag: + +- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors) +- `.level = 2` and `.has256 = true`: 256 color support +- `.level = 3` and `.has16m = true`: 16 million (truecolor) support + + +## Info + +It obeys the `--color` and `--no-color` CLI flags. + +For situations where using `--color` is not possible, add an environment variable `FORCE_COLOR` with any value to force color. Trumps `--no-color`. + +Explicit 256/truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively. + + +## Related + +- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module +- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/hm_sunwell/node_modules/istanbul/package.json b/hm_sunwell/node_modules/istanbul/package.json new file mode 100644 index 0000000..28a1146 --- /dev/null +++ b/hm_sunwell/node_modules/istanbul/package.json @@ -0,0 +1,400 @@ +{ + "_args": [ + [ + "istanbul@^0.4.3", + "/home/xor/shared_vm/git/node-sunwell" + ] + ], + "_from": "istanbul@>=0.4.3 <0.5.0", + "_id": "istanbul@0.4.5", + "_inCache": true, + "_installable": true, + "_location": "/istanbul", + "_nodeVersion": "0.12.7", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/istanbul-0.4.5.tgz_1471809726773_0.4557724657934159" + }, + "_npmUser": { + "email": "kananthmail-github@yahoo.com", + "name": "gotwarlost" + }, + "_npmVersion": "2.11.3", + "_phantomChildren": { + "has-flag": "1.0.0" + }, + "_requested": { + "name": "istanbul", + "raw": "istanbul@^0.4.3", + "rawSpec": "^0.4.3", + "scope": null, + "spec": ">=0.4.3 <0.5.0", + "type": "range" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "_shasum": "65c7d73d4c4da84d4f3ac310b918fb0b8033733b", + "_shrinkwrap": null, + "_spec": "istanbul@^0.4.3", + "_where": "/home/xor/shared_vm/git/node-sunwell", + "author": { + "email": "kananthmail-github@yahoo.com", + "name": "Krishnan Anantheswaran" + }, + "bin": { + "istanbul": "./lib/cli.js" + }, + "bugs": { + "url": "https://github.com/gotwarlost/istanbul/issues" + }, + "contributors": [ + { + "name": "Ron Korving @ronkorving" + }, + { + "name": "Reid Burke", + "email": "me@reidburke.com" + }, + { + "name": "Dav Glass", + "email": "davglass@gmail.com" + }, + { + "name": "nowamasa", + "email": "nowamasa@gmail.com" + }, + { + "name": "Miller Medeiros @millermedeiros", + "email": "contact@millermedeiros.com" + }, + { + "name": "Daniel Perez Alvarez @unindented", + "email": "unindented@gmail.com" + }, + { + "name": "Mathias Bynens @mathiasbynens", + "email": "mathias@qiwi.be" + }, + { + "name": "Nathan Brown @nbrownus", + "email": "nate@betable.com" + }, + { + "name": "Brian Ng @existentialism", + "email": "bng412@gmail.com" + }, + { + "name": "John Morrison @jrgm" + }, + { + "name": "Tomaz Muraus @kami", + "email": "tomaz+github@tomaz.me" + }, + { + "name": "Joe @jhansche", + "email": "jhansche@meetme.com" + }, + { + "name": "Vojta Jina @vojtajina", + "email": "vojta.jina@gmail.com" + }, + { + "name": "Dmitry Shirokov @runk", + "email": "deadrunk@gmail.com" + }, + { + "name": "Chris Gladd @chrisgladd" + }, + { + "name": "Sergey Belov", + "email": "peimei@ya.ru" + }, + { + "name": "porneL @pornel", + "email": "pornel@pornel.net" + }, + { + "name": "@asifrc" + }, + { + "name": "Gergely Nemeth @gergelyke" + }, + { + "name": "@bixdeng" + }, + { + "name": "@mpderbec" + }, + { + "name": "@jxiaodev" + }, + { + "name": "Arpad Borsos @Swatinem", + "email": "arpad.borsos@googlemail.com" + }, + { + "name": "Ariya Hidayat @ariya" + }, + { + "name": "@markyen" + }, + { + "name": "Sam Saccone @samccone", + "email": "sam@samx.it" + }, + { + "name": "Jason Cheatham @jason0x43" + }, + { + "name": "@smikes" + }, + { + "name": "Yasyf Mohamedali @yasyf", + "email": "yasyfm@gmail.com" + }, + { + "name": "Fabio Crisci @piuccio", + "email": "piuccio@gmail.com" + }, + { + "name": "Ryan Roemer @ryan-roemer", + "email": "ryan@loose-bits.com" + }, + { + "name": "Douglas Christopher Wilson @dougwilson" + }, + { + "name": "Gustav Nikolaj @gustavnikolaj", + "email": "gustavnikolaj@gmail.com" + }, + { + "name": "Denis Sokolov @denis-sokolov", + "email": "denis@sokolov.cc" + }, + { + "name": "Yann Mainier @ymainier" + }, + { + "name": "Yiyu He @dead-horse", + "email": "heyiyu.deadhorse@gmail.com" + }, + { + "name": "Andrew Kelley @andrewrk", + "email": "superjoe30@gmail.com" + }, + { + "name": "Will LaBranche @wlabranche", + "email": "will@labranche.io" + }, + { + "name": "Mathieu Naouache @math-nao", + "email": "math.nao@outlook.com" + }, + { + "name": "Martin Cooper", + "email": "mfncooper@gmail.com" + }, + { + "name": "Rob McGuire-Dale @robatron", + "email": "rob.mcguiredale@gmail.com" + }, + { + "name": "Justin Johnson @booleangate" + }, + { + "name": "Juan Gabriel Jiménez @juangabreil", + "email": "juangabreil@gmail.com" + }, + { + "name": "Daniel Sabelnikov @dragn", + "email": "dsabelnikov@gmail.com" + }, + { + "name": "Tony Lukasavage @tonylukasavage", + "email": "anthony.lukasavage@gmail.com" + }, + { + "name": "Simon Ramsay @nexus-uw" + }, + { + "name": "Dominykas Blyžė @dominykas" + }, + { + "name": "Seth Pollack @sethpollack" + }, + { + "name": "Benjamin E. Coe @bcoe", + "email": "ben@npmjs.com" + }, + { + "name": "Yuren Ju", + "email": "yurenju@gmail.com" + }, + { + "name": "Aleksey Verkholantsev", + "email": "alex-vee@yandex-team.ru" + }, + { + "name": "Ed S", + "email": "ejsanders@gmail.com" + }, + { + "name": "Mordy Tikotzky", + "email": "mordytk@gmail.com" + }, + { + "name": "Haoliang Gao @popomore", + "email": "sakura9515@gmail.com" + }, + { + "name": "Roderick Hsiao @roderickhsiao" + }, + { + "name": "Nikita Gusakov @nkt" + }, + { + "name": "Alex Dunphy @alexdunphy", + "email": "alexanderdunphy@gmail.com" + }, + { + "name": "Artemy Tregubenko @arty-name", + "email": "me@arty.name" + }, + { + "name": "Arye Lukashevski @aryelu" + }, + { + "name": "@sterlinghw" + }, + { + "name": "Gord Tanner", + "email": "gord@bithound.io" + }, + { + "name": "Tom MacWright @tmcw", + "email": "tom@macwright.org" + }, + { + "name": "Kitson Kelly @kitsonk" + }, + { + "name": "@asa-git" + }, + { + "name": "@RoCat" + }, + { + "name": "Ian Page Hands @iphands", + "email": "iphands@gmail.com" + }, + { + "name": "Eddie Gurnee @pegurnee" + }, + { + "name": "Kevin Decker @kpdecker", + "email": "kpdecker@gmail.com" + }, + { + "name": "isaacs @isaacs", + "email": "i@izs.me" + }, + { + "name": "Steve Gray @steve-gray" + }, + { + "name": "Prayag Verma @pra85", + "email": "prayag.verma@gmail.com" + }, + { + "name": "Abe Fehr @abejfehr", + "email": "abe.fehr@gmail.com" + }, + { + "name": "Brian Woodward @doowb", + "email": "brian.woodward@gmail.com" + }, + { + "name": "@Victorystick" + }, + { + "name": "@inversion" + }, + { + "name": "@JamesMGreene" + }, + { + "name": "@ChALkeR" + }, + { + "name": "@graingert" + } + ], + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "description": "Yet another JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests ", + "devDependencies": { + "coveralls": "2.x", + "jshint": "^2.8.0", + "nodeunit": "0.9.x", + "requirejs": "2.x", + "rimraf": "^2.4.3" + }, + "directories": {}, + "dist": { + "shasum": "65c7d73d4c4da84d4f3ac310b918fb0b8033733b", + "tarball": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz" + }, + "files": [ + "index.js", + "lib/" + ], + "gitHead": "89e338fcb1c8a7dea3b9e8f851aa55de2bc3abee", + "homepage": "https://github.com/gotwarlost/istanbul#readme", + "keywords": [ + "JS code coverage", + "JS coverage", + "code coverage", + "coverage" + ], + "license": "BSD-3-Clause", + "maintainers": [ + { + "name": "gotwarlost", + "email": "kananthmail-github@yahoo.com" + }, + { + "name": "davglass", + "email": "davglass@gmail.com" + } + ], + "name": "istanbul", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/gotwarlost/istanbul.git" + }, + "scripts": { + "docs": "npm install yuidocjs && node node_modules/yuidocjs/lib/cli.js .", + "posttest": "node ./lib/cli.js check-coverage --statements 95 --branches 80", + "pretest": "jshint index.js lib/ test/ && ./download-escodegen-browser.sh", + "test": "node --harmony test/run.js" + }, + "version": "0.4.5" +} diff --git a/hm_sunwell/node_modules/jade/.npmignore b/hm_sunwell/node_modules/jade/.npmignore new file mode 100644 index 0000000..b9af3d4 --- /dev/null +++ b/hm_sunwell/node_modules/jade/.npmignore @@ -0,0 +1,15 @@ +test +support +benchmarks +examples +lib-cov +coverage.html +.gitmodules +.travis.yml +History.md +Readme.md +Makefile +test/ +support/ +benchmarks/ +examples/ diff --git a/hm_sunwell/node_modules/jade/LICENSE b/hm_sunwell/node_modules/jade/LICENSE new file mode 100644 index 0000000..8ad0e0d --- /dev/null +++ b/hm_sunwell/node_modules/jade/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2009-2010 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/bin/jade b/hm_sunwell/node_modules/jade/bin/jade new file mode 100644 index 0000000..7e6002f --- /dev/null +++ b/hm_sunwell/node_modules/jade/bin/jade @@ -0,0 +1,147 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var fs = require('fs') + , program = require('commander') + , path = require('path') + , basename = path.basename + , dirname = path.dirname + , resolve = path.resolve + , join = path.join + , mkdirp = require('mkdirp') + , jade = require('../'); + +// jade options + +var options = {}; + +// options + +program + .version(jade.version) + .usage('[options] [dir|file ...]') + .option('-o, --obj ', 'javascript options object') + .option('-O, --out ', 'output the compiled html to ') + .option('-p, --path ', 'filename used to resolve includes') + .option('-P, --pretty', 'compile pretty html output') + .option('-c, --client', 'compile for client-side runtime.js') + .option('-D, --no-debug', 'compile without debugging (smaller functions)') + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' # translate jade the templates dir'); + console.log(' $ jade templates'); + console.log(''); + console.log(' # create {foo,bar}.html'); + console.log(' $ jade {foo,bar}.jade'); + console.log(''); + console.log(' # jade over stdio'); + console.log(' $ jade < my.jade > my.html'); + console.log(''); + console.log(' # jade over stdio'); + console.log(' $ echo "h1 Jade!" | jade'); + console.log(''); + console.log(' # foo, bar dirs rendering to /tmp'); + console.log(' $ jade foo bar --out /tmp '); + console.log(''); +}); + +program.parse(process.argv); + +// options given, parse them + +if (program.obj) options = eval('(' + program.obj + ')'); + +// --filename + +if (program.path) options.filename = program.path; + +// --no-debug + +options.compileDebug = program.debug; + +// --client + +options.client = program.client; + +// --pretty + +options.pretty = program.pretty; + +// left-over args are file paths + +var files = program.args; + +// compile files + +if (files.length) { + console.log(); + files.forEach(renderFile); + process.on('exit', console.log); +// stdio +} else { + stdin(); +} + +/** + * Compile from stdin. + */ + +function stdin() { + var buf = ''; + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(chunk){ buf += chunk; }); + process.stdin.on('end', function(){ + var fn = jade.compile(buf, options); + var output = options.client + ? fn.toString() + : fn(options); + process.stdout.write(output); + }).resume(); +} + +/** + * Process the given path, compiling the jade files found. + * Always walk the subdirectories. + */ + +function renderFile(path) { + var re = /\.jade$/; + fs.lstat(path, function(err, stat) { + if (err) throw err; + // Found jade file + if (stat.isFile() && re.test(path)) { + fs.readFile(path, 'utf8', function(err, str){ + if (err) throw err; + options.filename = path; + var fn = jade.compile(str, options); + var extname = options.client ? '.js' : '.html'; + path = path.replace(re, extname); + if (program.out) path = join(program.out, basename(path)); + var dir = resolve(dirname(path)); + mkdirp(dir, 0755, function(err){ + if (err) throw err; + var output = options.client + ? fn.toString() + : fn(options); + fs.writeFile(path, output, function(err){ + if (err) throw err; + console.log(' \033[90mrendered \033[36m%s\033[0m', path); + }); + }); + }); + // Found directory + } else if (stat.isDirectory()) { + fs.readdir(path, function(err, files) { + if (err) throw err; + files.map(function(filename) { + return path + '/' + filename; + }).forEach(renderFile); + }); + } + }); +} diff --git a/hm_sunwell/node_modules/jade/index.js b/hm_sunwell/node_modules/jade/index.js new file mode 100644 index 0000000..8ad059f --- /dev/null +++ b/hm_sunwell/node_modules/jade/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.JADE_COV + ? require('./lib-cov/jade') + : require('./lib/jade'); \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/jade.js b/hm_sunwell/node_modules/jade/jade.js new file mode 100644 index 0000000..1983a20 --- /dev/null +++ b/hm_sunwell/node_modules/jade/jade.js @@ -0,0 +1,3586 @@ +(function() { + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.charAt(0)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("compiler.js", function(module, exports, require){ + +/*! + * Jade - Compiler + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var nodes = require('./nodes') + , filters = require('./filters') + , doctypes = require('./doctypes') + , selfClosing = require('./self-closing') + , runtime = require('./runtime') + , utils = require('./utils'); + + + if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } + } + + if (!String.prototype.trimLeft) { + String.prototype.trimLeft = function(){ + return this.replace(/^\s+/, ''); + } + } + + + +/** + * Initialize `Compiler` with the given `node`. + * + * @param {Node} node + * @param {Object} options + * @api public + */ + +var Compiler = module.exports = function Compiler(node, options) { + this.options = options = options || {}; + this.node = node; + this.hasCompiledDoctype = false; + this.hasCompiledTag = false; + this.pp = options.pretty || false; + this.debug = false !== options.compileDebug; + this.indents = 0; + this.parentIndents = 0; + if (options.doctype) this.setDoctype(options.doctype); +}; + +/** + * Compiler prototype. + */ + +Compiler.prototype = { + + /** + * Compile parse tree to JavaScript. + * + * @api public + */ + + compile: function(){ + this.buf = ['var interp;']; + if (this.pp) this.buf.push("var __indent = [];"); + this.lastBufferedIdx = -1; + this.visit(this.node); + return this.buf.join('\n'); + }, + + /** + * Sets the default doctype `name`. Sets terse mode to `true` when + * html 5 is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {string} name + * @api public + */ + + setDoctype: function(name){ + var doctype = doctypes[(name || 'default').toLowerCase()]; + doctype = doctype || ''; + this.doctype = doctype; + this.terse = '5' == name || 'html' == name; + this.xml = 0 == this.doctype.indexOf(' 1 && !escape && block.nodes[0].isText && block.nodes[1].isText) + this.prettyIndent(1, true); + + for (var i = 0; i < len; ++i) { + // Pretty print text + if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText) + this.prettyIndent(1, false); + + this.visit(block.nodes[i]); + // Multiple text nodes are separated by newlines + if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText) + this.buffer('\\n'); + } + }, + + /** + * Visit `doctype`. Sets terse mode to `true` when html 5 + * is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {Doctype} doctype + * @api public + */ + + visitDoctype: function(doctype){ + if (doctype && (doctype.val || !this.doctype)) { + this.setDoctype(doctype.val || 'default'); + } + + if (this.doctype) this.buffer(this.doctype); + this.hasCompiledDoctype = true; + }, + + /** + * Visit `mixin`, generating a function that + * may be called within the template. + * + * @param {Mixin} mixin + * @api public + */ + + visitMixin: function(mixin){ + var name = mixin.name.replace(/-/g, '_') + '_mixin' + , args = mixin.args || '' + , block = mixin.block + , attrs = mixin.attrs + , pp = this.pp; + + if (mixin.call) { + if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');") + if (block || attrs.length) { + + this.buf.push(name + '.call({'); + + if (block) { + this.buf.push('block: function(){'); + + // Render block with no indents, dynamically added when rendered + this.parentIndents++; + var _indents = this.indents; + this.indents = 0; + this.visit(mixin.block); + this.indents = _indents; + this.parentIndents--; + + if (attrs.length) { + this.buf.push('},'); + } else { + this.buf.push('}'); + } + } + + if (attrs.length) { + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push('attributes: merge({' + val.buf + + '}, attributes), escaped: merge(' + val.escaped + ', escaped, true)'); + } else { + this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped); + } + } + + if (args) { + this.buf.push('}, ' + args + ');'); + } else { + this.buf.push('});'); + } + + } else { + this.buf.push(name + '(' + args + ');'); + } + if (pp) this.buf.push("__indent.pop();") + } else { + this.buf.push('var ' + name + ' = function(' + args + '){'); + this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};'); + this.parentIndents++; + this.visit(block); + this.parentIndents--; + this.buf.push('};'); + } + }, + + /** + * Visit `tag` buffering tag markup, generating + * attributes, visiting the `tag`'s code and block. + * + * @param {Tag} tag + * @api public + */ + + visitTag: function(tag){ + this.indents++; + var name = tag.name + , pp = this.pp; + + if (tag.buffer) name = "' + (" + name + ") + '"; + + if (!this.hasCompiledTag) { + if (!this.hasCompiledDoctype && 'html' == name) { + this.visitDoctype(); + } + this.hasCompiledTag = true; + } + + // pretty print + if (pp && !tag.isInline()) + this.prettyIndent(0, true); + + if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) { + this.buffer('<' + name); + this.visitAttributes(tag.attrs); + this.terse + ? this.buffer('>') + : this.buffer('/>'); + } else { + // Optimize attributes buffering + if (tag.attrs.length) { + this.buffer('<' + name); + if (tag.attrs.length) this.visitAttributes(tag.attrs); + this.buffer('>'); + } else { + this.buffer('<' + name + '>'); + } + if (tag.code) this.visitCode(tag.code); + this.escape = 'pre' == tag.name; + this.visit(tag.block); + + // pretty print + if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline()) + this.prettyIndent(0, true); + + this.buffer(''); + } + this.indents--; + }, + + /** + * Visit `filter`, throwing when the filter does not exist. + * + * @param {Filter} filter + * @api public + */ + + visitFilter: function(filter){ + var fn = filters[filter.name]; + + // unknown filter + if (!fn) { + if (filter.isASTFilter) { + throw new Error('unknown ast filter "' + filter.name + ':"'); + } else { + throw new Error('unknown filter ":' + filter.name + '"'); + } + } + + if (filter.isASTFilter) { + this.buf.push(fn(filter.block, this, filter.attrs)); + } else { + var text = filter.block.nodes.map(function(node){ return node.val }).join('\n'); + filter.attrs = filter.attrs || {}; + filter.attrs.filename = this.options.filename; + this.buffer(utils.text(fn(text, filter.attrs))); + } + }, + + /** + * Visit `text` node. + * + * @param {Text} text + * @api public + */ + + visitText: function(text){ + text = utils.text(text.val.replace(/\\/g, '\\\\')); + if (this.escape) text = escape(text); + this.buffer(text); + }, + + /** + * Visit a `comment`, only buffering when the buffer flag is set. + * + * @param {Comment} comment + * @api public + */ + + visitComment: function(comment){ + if (!comment.buffer) return; + if (this.pp) this.prettyIndent(1, true); + this.buffer(''); + }, + + /** + * Visit a `BlockComment`. + * + * @param {Comment} comment + * @api public + */ + + visitBlockComment: function(comment){ + if (!comment.buffer) return; + if (0 == comment.val.trim().indexOf('if')) { + this.buffer(''); + } else { + this.buffer(''); + } + }, + + /** + * Visit `code`, respecting buffer / escape flags. + * If the code is followed by a block, wrap it in + * a self-calling function. + * + * @param {Code} code + * @api public + */ + + visitCode: function(code){ + // Wrap code blocks with {}. + // we only wrap unbuffered code blocks ATM + // since they are usually flow control + + // Buffer code + if (code.buffer) { + var val = code.val.trimLeft(); + this.buf.push('var __val__ = ' + val); + val = 'null == __val__ ? "" : __val__'; + if (code.escape) val = 'escape(' + val + ')'; + this.buf.push("buf.push(" + val + ");"); + } else { + this.buf.push(code.val); + } + + // Block support + if (code.block) { + if (!code.buffer) this.buf.push('{'); + this.visit(code.block); + if (!code.buffer) this.buf.push('}'); + } + }, + + /** + * Visit `each` block. + * + * @param {Each} each + * @api public + */ + + visitEach: function(each){ + this.buf.push('' + + '// iterate ' + each.obj + '\n' + + ';(function(){\n' + + ' if (\'number\' == typeof ' + each.obj + '.length) {\n' + + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push('' + + ' }\n' + + ' } else {\n' + + ' for (var ' + each.key + ' in ' + each.obj + ') {\n' + + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push(' }\n'); + + this.buf.push(' }\n }\n}).call(this);\n'); + }, + + /** + * Visit `attrs`. + * + * @param {Array} attrs + * @api public + */ + + visitAttributes: function(attrs){ + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push("buf.push(attrs(merge({ " + val.buf + + " }, attributes), merge(" + val.escaped + ", escaped, true)));"); + } else if (val.constant) { + eval('var buf={' + val.buf + '};'); + this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true); + } else { + this.buf.push("buf.push(attrs({ " + val.buf + " }, " + val.escaped + "));"); + } + }, + + /** + * Compile attributes. + */ + + attrs: function(attrs){ + var buf = [] + , classes = [] + , escaped = {} + , constant = attrs.every(function(attr){ return isConstant(attr.val) }) + , inherits = false; + + if (this.terse) buf.push('terse: true'); + + attrs.forEach(function(attr){ + if (attr.name == 'attributes') return inherits = true; + escaped[attr.name] = attr.escaped; + if (attr.name == 'class') { + classes.push('(' + attr.val + ')'); + } else { + var pair = "'" + attr.name + "':(" + attr.val + ')'; + buf.push(pair); + } + }); + + if (classes.length) { + classes = classes.join(" + ' ' + "); + buf.push("class: " + classes); + } + + return { + buf: buf.join(', ').replace('class:', '"class":'), + escaped: JSON.stringify(escaped), + inherits: inherits, + constant: constant + }; + } +}; + +/** + * Check if expression can be evaluated to a constant + * + * @param {String} expression + * @return {Boolean} + * @api private + */ + +function isConstant(val){ + // Check strings/literals + if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val)) + return true; + + // Check numbers + if (!isNaN(Number(val))) + return true; + + // Check arrays + var matches; + if (matches = /^ *\[(.*)\] *$/.exec(val)) + return matches[1].split(',').every(isConstant); + + return false; +} + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} +}); // module: compiler.js + +require.register("doctypes.js", function(module, exports, require){ + +/*! + * Jade - doctypes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + '5': '' + , 'default': '' + , 'xml': '' + , 'transitional': '' + , 'strict': '' + , 'frameset': '' + , '1.1': '' + , 'basic': '' + , 'mobile': '' +}; +}); // module: doctypes.js + +require.register("filters.js", function(module, exports, require){ + +/*! + * Jade - filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + + /** + * Wrap text with CDATA block. + */ + + cdata: function(str){ + return ''; + }, + + /** + * Transform sass to css, wrapped in style tags. + */ + + sass: function(str){ + str = str.replace(/\\n/g, '\n'); + var sass = require('sass').render(str).replace(/\n/g, '\\n'); + return ''; + }, + + /** + * Transform stylus to css, wrapped in style tags. + */ + + stylus: function(str, options){ + var ret; + str = str.replace(/\\n/g, '\n'); + var stylus = require('stylus'); + stylus(str, options).render(function(err, css){ + if (err) throw err; + ret = css.replace(/\n/g, '\\n'); + }); + return ''; + }, + + /** + * Transform less to css, wrapped in style tags. + */ + + less: function(str){ + var ret; + str = str.replace(/\\n/g, '\n'); + require('less').render(str, function(err, css){ + if (err) throw err; + ret = ''; + }); + return ret; + }, + + /** + * Transform markdown to html. + */ + + markdown: function(str){ + var md; + + // support markdown / discount + try { + md = require('markdown'); + } catch (err){ + try { + md = require('discount'); + } catch (err) { + try { + md = require('markdown-js'); + } catch (err) { + try { + md = require('marked'); + } catch (err) { + throw new + Error('Cannot find markdown library, install markdown, discount, or marked.'); + } + } + } + } + + str = str.replace(/\\n/g, '\n'); + return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,'''); + }, + + /** + * Transform coffeescript to javascript. + */ + + coffeescript: function(str){ + str = str.replace(/\\n/g, '\n'); + var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); + return ''; + } +}; + +}); // module: filters.js + +require.register("inline-tags.js", function(module, exports, require){ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; +}); // module: inline-tags.js + +require.register("jade.js", function(module, exports, require){ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Parser = require('./parser') + , Lexer = require('./lexer') + , Compiler = require('./compiler') + , runtime = require('./runtime') + +/** + * Library version. + */ + +exports.version = '0.26.1'; + +/** + * Expose self closing tags. + */ + +exports.selfClosing = require('./self-closing'); + +/** + * Default supported doctypes. + */ + +exports.doctypes = require('./doctypes'); + +/** + * Text filters. + */ + +exports.filters = require('./filters'); + +/** + * Utilities. + */ + +exports.utils = require('./utils'); + +/** + * Expose `Compiler`. + */ + +exports.Compiler = Compiler; + +/** + * Expose `Parser`. + */ + +exports.Parser = Parser; + +/** + * Expose `Lexer`. + */ + +exports.Lexer = Lexer; + +/** + * Nodes. + */ + +exports.nodes = require('./nodes'); + +/** + * Jade runtime helpers. + */ + +exports.runtime = runtime; + +/** + * Template function cache. + */ + +exports.cache = {}; + +/** + * Parse the given `str` of jade and return a function body. + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api private + */ + +function parse(str, options){ + try { + // Parse + var parser = new Parser(str, options.filename, options); + + // Compile + var compiler = new (options.compiler || Compiler)(parser.parse(), options) + , js = compiler.compile(); + + // Debug compiler + if (options.debug) { + console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' ')); + } + + return '' + + 'var buf = [];\n' + + (options.self + ? 'var self = locals || {};\n' + js + : 'with (locals || {}) {\n' + js + '\n}\n') + + 'return buf.join("");'; + } catch (err) { + parser = parser.context(); + runtime.rethrow(err, parser.filename, parser.lexer.lineno); + } +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + if (options.compileDebug !== false) { + fn = [ + 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(String(str), options) + , '} catch (err) {' + , ' rethrow(err, __jade[0].filename, __jade[0].lineno);' + , '}' + ].join('\n'); + } else { + fn = parse(String(str), options); + } + + if (client) { + fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn; + } + + fn = new Function('locals, attrs, escape, rethrow, merge', fn); + + if (client) return fn; + + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge); + }; +}; + +/** + * Render the given `str` of jade and invoke + * the callback `fn(err, str)`. + * + * Options: + * + * - `cache` enable template caching + * - `filename` filename required for `include` / `extends` and caching + * + * @param {String} str + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +exports.render = function(str, options, fn){ + // swap args + if ('function' == typeof options) { + fn = options, options = {}; + } + + // cache requires .filename + if (options.cache && !options.filename) { + return fn(new Error('the "filename" option is required for caching')); + } + + try { + var path = options.filename; + var tmpl = options.cache + ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options)) + : exports.compile(str, options); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Render a Jade file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + try { + options.filename = path; + var str = options.cache + ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8')) + : fs.readFileSync(path, 'utf8'); + exports.render(str, options, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Express support. + */ + +exports.__express = exports.renderFile; + +}); // module: jade.js + +require.register("lexer.js", function(module, exports, require){ + +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize `Lexer` with the given `str`. + * + * Options: + * + * - `colons` allow colons for attr delimiters + * + * @param {String} str + * @param {Object} options + * @api private + */ + +var Lexer = module.exports = function Lexer(str, options) { + options = options || {}; + this.input = str.replace(/\r\n|\r/g, '\n'); + this.colons = options.colons; + this.deferredTokens = []; + this.lastIndents = 0; + this.lineno = 1; + this.stash = []; + this.indentStack = []; + this.indentRe = null; + this.pipeless = false; +}; + +/** + * Lexer prototype. + */ + +Lexer.prototype = { + + /** + * Construct a token with the given `type` and `val`. + * + * @param {String} type + * @param {String} val + * @return {Object} + * @api private + */ + + tok: function(type, val){ + return { + type: type + , line: this.lineno + , val: val + } + }, + + /** + * Consume the given `len` of input. + * + * @param {Number} len + * @api private + */ + + consume: function(len){ + this.input = this.input.substr(len); + }, + + /** + * Scan for `type` with the given `regexp`. + * + * @param {String} type + * @param {RegExp} regexp + * @return {Object} + * @api private + */ + + scan: function(regexp, type){ + var captures; + if (captures = regexp.exec(this.input)) { + this.consume(captures[0].length); + return this.tok(type, captures[1]); + } + }, + + /** + * Defer the given `tok`. + * + * @param {Object} tok + * @api private + */ + + defer: function(tok){ + this.deferredTokens.push(tok); + }, + + /** + * Lookahead `n` tokens. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + var fetch = n - this.stash.length; + while (fetch-- > 0) this.stash.push(this.next()); + return this.stash[--n]; + }, + + /** + * Return the indexOf `start` / `end` delimiters. + * + * @param {String} start + * @param {String} end + * @return {Number} + * @api private + */ + + indexOfDelimiters: function(start, end){ + var str = this.input + , nstart = 0 + , nend = 0 + , pos = 0; + for (var i = 0, len = str.length; i < len; ++i) { + if (start == str.charAt(i)) { + ++nstart; + } else if (end == str.charAt(i)) { + if (++nend == nstart) { + pos = i; + break; + } + } + } + return pos; + }, + + /** + * Stashed token. + */ + + stashed: function() { + return this.stash.length + && this.stash.shift(); + }, + + /** + * Deferred token. + */ + + deferred: function() { + return this.deferredTokens.length + && this.deferredTokens.shift(); + }, + + /** + * end-of-source. + */ + + eos: function() { + if (this.input.length) return; + if (this.indentStack.length) { + this.indentStack.shift(); + return this.tok('outdent'); + } else { + return this.tok('eos'); + } + }, + + /** + * Blank line. + */ + + blank: function() { + var captures; + if (captures = /^\n *\n/.exec(this.input)) { + this.consume(captures[0].length - 1); + if (this.pipeless) return this.tok('text', ''); + return this.next(); + } + }, + + /** + * Comment. + */ + + comment: function() { + var captures; + if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('comment', captures[2]); + tok.buffer = '-' != captures[1]; + return tok; + } + }, + + /** + * Interpolated tag. + */ + + interpolation: function() { + var captures; + if (captures = /^#\{(.*?)\}/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('interpolation', captures[1]); + } + }, + + /** + * Tag. + */ + + tag: function() { + var captures; + if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) { + this.consume(captures[0].length); + var tok, name = captures[1]; + if (':' == name[name.length - 1]) { + name = name.slice(0, -1); + tok = this.tok('tag', name); + this.defer(this.tok(':')); + while (' ' == this.input[0]) this.input = this.input.substr(1); + } else { + tok = this.tok('tag', name); + } + tok.selfClosing = !! captures[2]; + return tok; + } + }, + + /** + * Filter. + */ + + filter: function() { + return this.scan(/^:(\w+)/, 'filter'); + }, + + /** + * Doctype. + */ + + doctype: function() { + return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype'); + }, + + /** + * Id. + */ + + id: function() { + return this.scan(/^#([\w-]+)/, 'id'); + }, + + /** + * Class. + */ + + className: function() { + return this.scan(/^\.([\w-]+)/, 'class'); + }, + + /** + * Text. + */ + + text: function() { + return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text'); + }, + + /** + * Extends. + */ + + "extends": function() { + return this.scan(/^extends? +([^\n]+)/, 'extends'); + }, + + /** + * Block prepend. + */ + + prepend: function() { + var captures; + if (captures = /^prepend +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'prepend' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block append. + */ + + append: function() { + var captures; + if (captures = /^append +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'append' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block. + */ + + block: function() { + var captures; + if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = captures[1] || 'replace' + , name = captures[2] + , tok = this.tok('block', name); + + tok.mode = mode; + return tok; + } + }, + + /** + * Yield. + */ + + yield: function() { + return this.scan(/^yield */, 'yield'); + }, + + /** + * Include. + */ + + include: function() { + return this.scan(/^include +([^\n]+)/, 'include'); + }, + + /** + * Case. + */ + + "case": function() { + return this.scan(/^case +([^\n]+)/, 'case'); + }, + + /** + * When. + */ + + when: function() { + return this.scan(/^when +([^:\n]+)/, 'when'); + }, + + /** + * Default. + */ + + "default": function() { + return this.scan(/^default */, 'default'); + }, + + /** + * Assignment. + */ + + assignment: function() { + var captures; + if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) { + this.consume(captures[0].length); + var name = captures[1] + , val = captures[2]; + return this.tok('code', 'var ' + name + ' = (' + val + ');'); + } + }, + + /** + * Call mixin. + */ + + call: function(){ + var captures; + if (captures = /^\+([-\w]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('call', captures[1]); + + // Check for args (not attributes) + if (captures = /^ *\((.*?)\)/.exec(this.input)) { + if (!/^ *[-\w]+ *=/.test(captures[1])) { + this.consume(captures[0].length); + tok.args = captures[1]; + } + } + + return tok; + } + }, + + /** + * Mixin. + */ + + mixin: function(){ + var captures; + if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('mixin', captures[1]); + tok.args = captures[2]; + return tok; + } + }, + + /** + * Conditional. + */ + + conditional: function() { + var captures; + if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var type = captures[1] + , js = captures[2]; + + switch (type) { + case 'if': js = 'if (' + js + ')'; break; + case 'unless': js = 'if (!(' + js + '))'; break; + case 'else if': js = 'else if (' + js + ')'; break; + case 'else': js = 'else'; break; + } + + return this.tok('code', js); + } + }, + + /** + * While. + */ + + "while": function() { + var captures; + if (captures = /^while +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('code', 'while (' + captures[1] + ')'); + } + }, + + /** + * Each. + */ + + each: function() { + var captures; + if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('each', captures[1]); + tok.key = captures[2] || '$index'; + tok.code = captures[3]; + return tok; + } + }, + + /** + * Code. + */ + + code: function() { + var captures; + if (captures = /^(!?=|-)([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var flags = captures[1]; + captures[1] = captures[2]; + var tok = this.tok('code', captures[1]); + tok.escape = flags[0] === '='; + tok.buffer = flags[0] === '=' || flags[1] === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.indexOfDelimiters('(', ')') + , str = this.input.substr(1, index-1) + , tok = this.tok('attrs') + , len = str.length + , colons = this.colons + , states = ['key'] + , escapedAttr + , key = '' + , val = '' + , quote + , c + , p; + + function state(){ + return states[states.length - 1]; + } + + function interpolate(attr) { + return attr.replace(/#\{([^}]+)\}/g, function(_, expr){ + return quote + " + (" + expr + ") + " + quote; + }); + } + + this.consume(index + 1); + tok.attrs = {}; + tok.escaped = {}; + + function parse(c) { + var real = c; + // TODO: remove when people fix ":" + if (colons && ':' == c) c = '='; + switch (c) { + case ',': + case '\n': + switch (state()) { + case 'expr': + case 'array': + case 'string': + case 'object': + val += c; + break; + default: + states.push('key'); + val = val.trim(); + key = key.trim(); + if ('' == key) return; + key = key.replace(/^['"]|['"]$/g, '').replace('!', ''); + tok.escaped[key] = escapedAttr; + tok.attrs[key] = '' == val + ? true + : interpolate(val); + key = val = ''; + } + break; + case '=': + switch (state()) { + case 'key char': + key += real; + break; + case 'val': + case 'expr': + case 'array': + case 'string': + case 'object': + val += real; + break; + default: + escapedAttr = '!' != p; + states.push('val'); + } + break; + case '(': + if ('val' == state() + || 'expr' == state()) states.push('expr'); + val += c; + break; + case ')': + if ('expr' == state() + || 'val' == state()) states.pop(); + val += c; + break; + case '{': + if ('val' == state()) states.push('object'); + val += c; + break; + case '}': + if ('object' == state()) states.pop(); + val += c; + break; + case '[': + if ('val' == state()) states.push('array'); + val += c; + break; + case ']': + if ('array' == state()) states.pop(); + val += c; + break; + case '"': + case "'": + switch (state()) { + case 'key': + states.push('key char'); + break; + case 'key char': + states.pop(); + break; + case 'string': + if (c == quote) states.pop(); + val += c; + break; + default: + states.push('string'); + val += c; + quote = c; + } + break; + case '': + break; + default: + switch (state()) { + case 'key': + case 'key char': + key += c; + break; + default: + val += c; + } + } + p = c; + } + + for (var i = 0; i < len; ++i) { + parse(str.charAt(i)); + } + + parse(','); + + if ('/' == this.input.charAt(0)) { + this.consume(1); + tok.selfClosing = true; + } + + return tok; + } + }, + + /** + * Indent | Outdent | Newline. + */ + + indent: function() { + var captures, re; + + // established regexp + if (this.indentRe) { + captures = this.indentRe.exec(this.input); + // determine regexp + } else { + // tabs + re = /^\n(\t*) */; + captures = re.exec(this.input); + + // spaces + if (captures && !captures[1].length) { + re = /^\n( *)/; + captures = re.exec(this.input); + } + + // established + if (captures && captures[1].length) this.indentRe = re; + } + + if (captures) { + var tok + , indents = captures[1].length; + + ++this.lineno; + this.consume(indents + 1); + + if (' ' == this.input[0] || '\t' == this.input[0]) { + throw new Error('Invalid indentation, you can use tabs or spaces but not both'); + } + + // blank line + if ('\n' == this.input[0]) return this.tok('newline'); + + // outdent + if (this.indentStack.length && indents < this.indentStack[0]) { + while (this.indentStack.length && this.indentStack[0] > indents) { + this.stash.push(this.tok('outdent')); + this.indentStack.shift(); + } + tok = this.stash.pop(); + // indent + } else if (indents && indents != this.indentStack[0]) { + this.indentStack.unshift(indents); + tok = this.tok('indent', indents); + // newline + } else { + tok = this.tok('newline'); + } + + return tok; + } + }, + + /** + * Pipe-less text consumed only when + * pipeless is true; + */ + + pipelessText: function() { + if (this.pipeless) { + if ('\n' == this.input[0]) return; + var i = this.input.indexOf('\n'); + if (-1 == i) i = this.input.length; + var str = this.input.substr(0, i); + this.consume(str.length); + return this.tok('text', str); + } + }, + + /** + * ':' + */ + + colon: function() { + return this.scan(/^: */, ':'); + }, + + /** + * Return the next token object, or those + * previously stashed by lookahead. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.stashed() + || this.next(); + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + next: function() { + return this.deferred() + || this.blank() + || this.eos() + || this.pipelessText() + || this.yield() + || this.doctype() + || this.interpolation() + || this["case"]() + || this.when() + || this["default"]() + || this["extends"]() + || this.append() + || this.prepend() + || this.block() + || this.include() + || this.mixin() + || this.call() + || this.conditional() + || this.each() + || this["while"]() + || this.assignment() + || this.tag() + || this.filter() + || this.code() + || this.id() + || this.className() + || this.attrs() + || this.indent() + || this.comment() + || this.colon() + || this.text(); + } +}; + +}); // module: lexer.js + +require.register("nodes/attrs.js", function(module, exports, require){ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'), + Block = require('./block'); + +/** + * Initialize a `Attrs` node. + * + * @api public + */ + +var Attrs = module.exports = function Attrs() { + this.attrs = []; +}; + +/** + * Inherit from `Node`. + */ + +Attrs.prototype = new Node; +Attrs.prototype.constructor = Attrs; + + +/** + * Set attribute `name` to `val`, keep in mind these become + * part of a raw js object literal, so to quote a value you must + * '"quote me"', otherwise or example 'user.name' is literal JavaScript. + * + * @param {String} name + * @param {String} val + * @param {Boolean} escaped + * @return {Tag} for chaining + * @api public + */ + +Attrs.prototype.setAttribute = function(name, val, escaped){ + this.attrs.push({ name: name, val: val, escaped: escaped }); + return this; +}; + +/** + * Remove attribute `name` when present. + * + * @param {String} name + * @api public + */ + +Attrs.prototype.removeAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + delete this.attrs[i]; + } + } +}; + +/** + * Get attribute value by `name`. + * + * @param {String} name + * @return {String} + * @api public + */ + +Attrs.prototype.getAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + return this.attrs[i].val; + } + } +}; + +}); // module: nodes/attrs.js + +require.register("nodes/block-comment.js", function(module, exports, require){ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `BlockComment` with the given `block`. + * + * @param {String} val + * @param {Block} block + * @param {Boolean} buffer + * @api public + */ + +var BlockComment = module.exports = function BlockComment(val, block, buffer) { + this.block = block; + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +BlockComment.prototype = new Node; +BlockComment.prototype.constructor = BlockComment; + +}); // module: nodes/block-comment.js + +require.register("nodes/block.js", function(module, exports, require){ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Block` with an optional `node`. + * + * @param {Node} node + * @api public + */ + +var Block = module.exports = function Block(node){ + this.nodes = []; + if (node) this.push(node); +}; + +/** + * Inherit from `Node`. + */ + +Block.prototype = new Node; +Block.prototype.constructor = Block; + + +/** + * Block flag. + */ + +Block.prototype.isBlock = true; + +/** + * Replace the nodes in `other` with the nodes + * in `this` block. + * + * @param {Block} other + * @api private + */ + +Block.prototype.replace = function(other){ + other.nodes = this.nodes; +}; + +/** + * Pust the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.push = function(node){ + return this.nodes.push(node); +}; + +/** + * Check if this block is empty. + * + * @return {Boolean} + * @api public + */ + +Block.prototype.isEmpty = function(){ + return 0 == this.nodes.length; +}; + +/** + * Unshift the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.unshift = function(node){ + return this.nodes.unshift(node); +}; + +/** + * Return the "last" block, or the first `yield` node. + * + * @return {Block} + * @api private + */ + +Block.prototype.includeBlock = function(){ + var ret = this + , node; + + for (var i = 0, len = this.nodes.length; i < len; ++i) { + node = this.nodes[i]; + if (node.yield) return node; + else if (node.textOnly) continue; + else if (node.includeBlock) ret = node.includeBlock(); + else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock(); + } + + return ret; +}; + +/** + * Return a clone of this block. + * + * @return {Block} + * @api private + */ + +Block.prototype.clone = function(){ + var clone = new Block; + for (var i = 0, len = this.nodes.length; i < len; ++i) { + clone.push(this.nodes[i].clone()); + } + return clone; +}; + + +}); // module: nodes/block.js + +require.register("nodes/case.js", function(module, exports, require){ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Case` with `expr`. + * + * @param {String} expr + * @api public + */ + +var Case = exports = module.exports = function Case(expr, block){ + this.expr = expr; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Case.prototype = new Node; +Case.prototype.constructor = Case; + + +var When = exports.When = function When(expr, block){ + this.expr = expr; + this.block = block; + this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +When.prototype = new Node; +When.prototype.constructor = When; + + + +}); // module: nodes/case.js + +require.register("nodes/code.js", function(module, exports, require){ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Code` node with the given code `val`. + * Code may also be optionally buffered and escaped. + * + * @param {String} val + * @param {Boolean} buffer + * @param {Boolean} escape + * @api public + */ + +var Code = module.exports = function Code(val, buffer, escape) { + this.val = val; + this.buffer = buffer; + this.escape = escape; + if (val.match(/^ *else/)) this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +Code.prototype = new Node; +Code.prototype.constructor = Code; + +}); // module: nodes/code.js + +require.register("nodes/comment.js", function(module, exports, require){ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Comment` with the given `val`, optionally `buffer`, + * otherwise the comment may render in the output. + * + * @param {String} val + * @param {Boolean} buffer + * @api public + */ + +var Comment = module.exports = function Comment(val, buffer) { + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +Comment.prototype = new Node; +Comment.prototype.constructor = Comment; + +}); // module: nodes/comment.js + +require.register("nodes/doctype.js", function(module, exports, require){ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Doctype` with the given `val`. + * + * @param {String} val + * @api public + */ + +var Doctype = module.exports = function Doctype(val) { + this.val = val; +}; + +/** + * Inherit from `Node`. + */ + +Doctype.prototype = new Node; +Doctype.prototype.constructor = Doctype; + +}); // module: nodes/doctype.js + +require.register("nodes/each.js", function(module, exports, require){ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize an `Each` node, representing iteration + * + * @param {String} obj + * @param {String} val + * @param {String} key + * @param {Block} block + * @api public + */ + +var Each = module.exports = function Each(obj, val, key, block) { + this.obj = obj; + this.val = val; + this.key = key; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Each.prototype = new Node; +Each.prototype.constructor = Each; + +}); // module: nodes/each.js + +require.register("nodes/filter.js", function(module, exports, require){ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node') + , Block = require('./block'); + +/** + * Initialize a `Filter` node with the given + * filter `name` and `block`. + * + * @param {String} name + * @param {Block|Node} block + * @api public + */ + +var Filter = module.exports = function Filter(name, block, attrs) { + this.name = name; + this.block = block; + this.attrs = attrs; + this.isASTFilter = !block.nodes.every(function(node){ return node.isText }); +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype = new Node; +Filter.prototype.constructor = Filter; + +}); // module: nodes/filter.js + +require.register("nodes/index.js", function(module, exports, require){ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +exports.Node = require('./node'); +exports.Tag = require('./tag'); +exports.Code = require('./code'); +exports.Each = require('./each'); +exports.Case = require('./case'); +exports.Text = require('./text'); +exports.Block = require('./block'); +exports.Mixin = require('./mixin'); +exports.Filter = require('./filter'); +exports.Comment = require('./comment'); +exports.Literal = require('./literal'); +exports.BlockComment = require('./block-comment'); +exports.Doctype = require('./doctype'); + +}); // module: nodes/index.js + +require.register("nodes/literal.js", function(module, exports, require){ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Literal` node with the given `str. + * + * @param {String} str + * @api public + */ + +var Literal = module.exports = function Literal(str) { + this.str = str + .replace(/\\/g, "\\\\") + .replace(/\n|\r\n/g, "\\n") + .replace(/'/g, "\\'"); +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype = new Node; +Literal.prototype.constructor = Literal; + + +}); // module: nodes/literal.js + +require.register("nodes/mixin.js", function(module, exports, require){ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'); + +/** + * Initialize a new `Mixin` with `name` and `block`. + * + * @param {String} name + * @param {String} args + * @param {Block} block + * @api public + */ + +var Mixin = module.exports = function Mixin(name, args, block, call){ + this.name = name; + this.args = args; + this.block = block; + this.attrs = []; + this.call = call; +}; + +/** + * Inherit from `Attrs`. + */ + +Mixin.prototype = new Attrs; +Mixin.prototype.constructor = Mixin; + + + +}); // module: nodes/mixin.js + +require.register("nodes/node.js", function(module, exports, require){ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize a `Node`. + * + * @api public + */ + +var Node = module.exports = function Node(){}; + +/** + * Clone this node (return itself) + * + * @return {Node} + * @api private + */ + +Node.prototype.clone = function(){ + return this; +}; + +}); // module: nodes/node.js + +require.register("nodes/tag.js", function(module, exports, require){ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'), + Block = require('./block'), + inlineTags = require('../inline-tags'); + +/** + * Initialize a `Tag` node with the given tag `name` and optional `block`. + * + * @param {String} name + * @param {Block} block + * @api public + */ + +var Tag = module.exports = function Tag(name, block) { + this.name = name; + this.attrs = []; + this.block = block || new Block; +}; + +/** + * Inherit from `Attrs`. + */ + +Tag.prototype = new Attrs; +Tag.prototype.constructor = Tag; + + +/** + * Clone this tag. + * + * @return {Tag} + * @api private + */ + +Tag.prototype.clone = function(){ + var clone = new Tag(this.name, this.block.clone()); + clone.line = this.line; + clone.attrs = this.attrs; + clone.textOnly = this.textOnly; + return clone; +}; + +/** + * Check if this tag is an inline tag. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.isInline = function(){ + return ~inlineTags.indexOf(this.name); +}; + +/** + * Check if this tag's contents can be inlined. Used for pretty printing. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.canInline = function(){ + var nodes = this.block.nodes; + + function isInline(node){ + // Recurse if the node is a block + if (node.isBlock) return node.nodes.every(isInline); + return node.isText || (node.isInline && node.isInline()); + } + + // Empty tag + if (!nodes.length) return true; + + // Text-only or inline-only tag + if (1 == nodes.length) return isInline(nodes[0]); + + // Multi-line inline-only tag + if (this.block.nodes.every(isInline)) { + for (var i = 1, len = nodes.length; i < len; ++i) { + if (nodes[i-1].isText && nodes[i].isText) + return false; + } + return true; + } + + // Mixed tag + return false; +}; +}); // module: nodes/tag.js + +require.register("nodes/text.js", function(module, exports, require){ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Text` node with optional `line`. + * + * @param {String} line + * @api public + */ + +var Text = module.exports = function Text(line) { + this.val = ''; + if ('string' == typeof line) this.val = line; +}; + +/** + * Inherit from `Node`. + */ + +Text.prototype = new Node; +Text.prototype.constructor = Text; + + +/** + * Flag as text. + */ + +Text.prototype.isText = true; +}); // module: nodes/text.js + +require.register("parser.js", function(module, exports, require){ + +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes'); + +/** + * Initialize `Parser` with the given input `str` and `filename`. + * + * @param {String} str + * @param {String} filename + * @param {Object} options + * @api public + */ + +var Parser = exports = module.exports = function Parser(str, filename, options){ + this.input = str; + this.lexer = new Lexer(str, options); + this.filename = filename; + this.blocks = {}; + this.mixins = {}; + this.options = options; + this.contexts = [this]; +}; + +/** + * Tags that may not contain tags. + */ + +var textOnly = exports.textOnly = ['script', 'style']; + +/** + * Parser prototype. + */ + +Parser.prototype = { + + /** + * Push `parser` onto the context stack, + * or pop and return a `Parser`. + */ + + context: function(parser){ + if (parser) { + this.contexts.push(parser); + } else { + return this.contexts.pop(); + } + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.lexer.advance(); + }, + + /** + * Skip `n` tokens. + * + * @param {Number} n + * @api private + */ + + skip: function(n){ + while (n--) this.advance(); + }, + + /** + * Single token lookahead. + * + * @return {Object} + * @api private + */ + + peek: function() { + return this.lookahead(1); + }, + + /** + * Return lexer lineno. + * + * @return {Number} + * @api private + */ + + line: function() { + return this.lexer.lineno; + }, + + /** + * `n` token lookahead. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + return this.lexer.lookahead(n); + }, + + /** + * Parse input returning a string of js for evaluation. + * + * @return {String} + * @api public + */ + + parse: function(){ + var block = new nodes.Block, parser; + block.line = this.line(); + + while ('eos' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + + if (parser = this.extending) { + this.context(parser); + var ast = parser.parse(); + this.context(); + // hoist mixins + for (var name in this.mixins) + ast.unshift(this.mixins[name]); + return ast; + } + + return block; + }, + + /** + * Expect the given type, or throw an exception. + * + * @param {String} type + * @api private + */ + + expect: function(type){ + if (this.peek().type === type) { + return this.advance(); + } else { + throw new Error('expected "' + type + '", but got "' + this.peek().type + '"'); + } + }, + + /** + * Accept the given `type`. + * + * @param {String} type + * @api private + */ + + accept: function(type){ + if (this.peek().type === type) { + return this.advance(); + } + }, + + /** + * tag + * | doctype + * | mixin + * | include + * | filter + * | comment + * | text + * | each + * | code + * | yield + * | id + * | class + * | interpolation + */ + + parseExpr: function(){ + switch (this.peek().type) { + case 'tag': + return this.parseTag(); + case 'mixin': + return this.parseMixin(); + case 'block': + return this.parseBlock(); + case 'case': + return this.parseCase(); + case 'when': + return this.parseWhen(); + case 'default': + return this.parseDefault(); + case 'extends': + return this.parseExtends(); + case 'include': + return this.parseInclude(); + case 'doctype': + return this.parseDoctype(); + case 'filter': + return this.parseFilter(); + case 'comment': + return this.parseComment(); + case 'text': + return this.parseText(); + case 'each': + return this.parseEach(); + case 'code': + return this.parseCode(); + case 'call': + return this.parseCall(); + case 'interpolation': + return this.parseInterpolation(); + case 'yield': + this.advance(); + var block = new nodes.Block; + block.yield = true; + return block; + case 'id': + case 'class': + var tok = this.advance(); + this.lexer.defer(this.lexer.tok('tag', 'div')); + this.lexer.defer(tok); + return this.parseExpr(); + default: + throw new Error('unexpected token "' + this.peek().type + '"'); + } + }, + + /** + * Text + */ + + parseText: function(){ + var tok = this.expect('text') + , node = new nodes.Text(tok.val); + node.line = this.line(); + return node; + }, + + /** + * ':' expr + * | block + */ + + parseBlockExpansion: function(){ + if (':' == this.peek().type) { + this.advance(); + return new nodes.Block(this.parseExpr()); + } else { + return this.block(); + } + }, + + /** + * case + */ + + parseCase: function(){ + var val = this.expect('case').val + , node = new nodes.Case(val); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * when + */ + + parseWhen: function(){ + var val = this.expect('when').val + return new nodes.Case.When(val, this.parseBlockExpansion()); + }, + + /** + * default + */ + + parseDefault: function(){ + this.expect('default'); + return new nodes.Case.When('default', this.parseBlockExpansion()); + }, + + /** + * code + */ + + parseCode: function(){ + var tok = this.expect('code') + , node = new nodes.Code(tok.val, tok.buffer, tok.escape) + , block + , i = 1; + node.line = this.line(); + while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; + block = 'indent' == this.lookahead(i).type; + if (block) { + this.skip(i-1); + node.block = this.block(); + } + return node; + }, + + /** + * comment + */ + + parseComment: function(){ + var tok = this.expect('comment') + , node; + + if ('indent' == this.peek().type) { + node = new nodes.BlockComment(tok.val, this.block(), tok.buffer); + } else { + node = new nodes.Comment(tok.val, tok.buffer); + } + + node.line = this.line(); + return node; + }, + + /** + * doctype + */ + + parseDoctype: function(){ + var tok = this.expect('doctype') + , node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var block + , tok = this.expect('filter') + , attrs = this.accept('attrs'); + + this.lexer.pipeless = true; + block = this.parseTextBlock(); + this.lexer.pipeless = false; + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * tag ':' attrs? block + */ + + parseASTFilter: function(){ + var block + , tok = this.expect('tag') + , attrs = this.accept('attrs'); + + this.expect(':'); + block = this.block(); + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * each block + */ + + parseEach: function(){ + var tok = this.expect('each') + , node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + if (!this.filename) + throw new Error('the "filename" option is required to extend templates'); + + var path = this.expect('extends').val.trim() + , dir = dirname(this.filename); + + var path = join(dir, path + '.jade') + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block') + , mode = block.mode + , name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name]; + + if (prev) { + switch (prev.mode) { + case 'append': + block.nodes = block.nodes.concat(prev.nodes); + prev = block; + break; + case 'prepend': + block.nodes = prev.nodes.concat(block.nodes); + prev = block; + break; + } + } + + block.mode = mode; + return this.blocks[name] = prev || block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + var path = this.expect('include').val.trim() + , dir = dirname(this.filename); + + if (!this.filename) + throw new Error('the "filename" option is required to use includes'); + + // no extension + if (!~basename(path).indexOf('.')) { + path += '.jade'; + } + + // non-jade + if ('.jade' != path.substr(-5)) { + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8'); + return new nodes.Literal(str); + } + + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + parser.blocks = this.blocks; + parser.mixins = this.mixins; + + this.context(parser); + var ast = parser.parse(); + this.context(); + ast.filename = path; + + if ('indent' == this.peek().type) { + ast.includeBlock().push(this.block()); + } + + return ast; + }, + + /** + * call ident block + */ + + parseCall: function(){ + var tok = this.expect('call') + , name = tok.val + , args = tok.args + , mixin = new nodes.Mixin(name, args, new nodes.Block, true); + + this.tag(mixin); + if (mixin.block.isEmpty()) mixin.block = null; + return mixin; + }, + + /** + * mixin block + */ + + parseMixin: function(){ + var tok = this.expect('mixin') + , name = tok.val + , args = tok.args + , mixin; + + // definition + if ('indent' == this.peek().type) { + mixin = new nodes.Mixin(name, args, this.block(), false); + this.mixins[name] = mixin; + return mixin; + // call + } else { + return new nodes.Mixin(name, args, null, true); + } + }, + + /** + * indent (text | newline)* outdent + */ + + parseTextBlock: function(){ + var block = new nodes.Block; + block.line = this.line(); + var spaces = this.expect('indent').val; + if (null == this._spaces) this._spaces = spaces; + var indent = Array(spaces - this._spaces + 1).join(' '); + while ('outdent' != this.peek().type) { + switch (this.peek().type) { + case 'newline': + this.advance(); + break; + case 'indent': + this.parseTextBlock().nodes.forEach(function(node){ + block.push(node); + }); + break; + default: + var text = new nodes.Text(indent + this.advance().val); + text.line = this.line(); + block.push(text); + } + } + + if (spaces == this._spaces) this._spaces = null; + this.expect('outdent'); + return block; + }, + + /** + * indent expr* outdent + */ + + block: function(){ + var block = new nodes.Block; + block.line = this.line(); + this.expect('indent'); + while ('outdent' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + this.expect('outdent'); + return block; + }, + + /** + * interpolation (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseInterpolation: function(){ + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + tag.buffer = true; + return this.tag(tag); + }, + + /** + * tag (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseTag: function(){ + // ast-filter look-ahead + var i = 2; + if ('attrs' == this.lookahead(i).type) ++i; + if (':' == this.lookahead(i).type) { + if ('indent' == this.lookahead(++i).type) { + return this.parseASTFilter(); + } + } + + var tok = this.advance() + , tag = new nodes.Tag(tok.val); + + tag.selfClosing = tok.selfClosing; + + return this.tag(tag); + }, + + /** + * Parse tag. + */ + + tag: function(tag){ + var dot; + + tag.line = this.line(); + + // (attrs | class | id)* + out: + while (true) { + switch (this.peek().type) { + case 'id': + case 'class': + var tok = this.advance(); + tag.setAttribute(tok.type, "'" + tok.val + "'"); + continue; + case 'attrs': + var tok = this.advance() + , obj = tok.attrs + , escaped = tok.escaped + , names = Object.keys(obj); + + if (tok.selfClosing) tag.selfClosing = true; + + for (var i = 0, len = names.length; i < len; ++i) { + var name = names[i] + , val = obj[name]; + tag.setAttribute(name, val, escaped[name]); + } + continue; + default: + break out; + } + } + + // check immediate '.' + if ('.' == this.peek().val) { + dot = tag.textOnly = true; + this.advance(); + } + + // (text | code | ':')? + switch (this.peek().type) { + case 'text': + tag.block.push(this.parseText()); + break; + case 'code': + tag.code = this.parseCode(); + break; + case ':': + this.advance(); + tag.block = new nodes.Block; + tag.block.push(this.parseExpr()); + break; + } + + // newline* + while ('newline' == this.peek().type) this.advance(); + + tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name); + + // script special-case + if ('script' == tag.name) { + var type = tag.getAttribute('type'); + if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { + tag.textOnly = false; + } + } + + // block? + if ('indent' == this.peek().type) { + if (tag.textOnly) { + this.lexer.pipeless = true; + tag.block = this.parseTextBlock(); + this.lexer.pipeless = false; + } else { + var block = this.block(); + if (tag.block) { + for (var i = 0, len = block.nodes.length; i < len; ++i) { + tag.block.push(block.nodes[i]); + } + } else { + tag.block = block; + } + } + } + + return tag; + } +}; + +}); // module: parser.js + +require.register("runtime.js", function(module, exports, require){ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + ac = ac.filter(nulls); + bc = bc.filter(nulls); + a['class'] = ac.concat(bc).join(' '); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function nulls(val) { + return val != null; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!(\w+|\#\d+);)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno){ + if (!filename) throw err; + + var context = 3 + , str = require('fs').readFileSync(filename, 'utf8') + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; + +}); // module: runtime.js + +require.register("self-closing.js", function(module, exports, require){ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; +}); // module: self-closing.js + +require.register("utils.js", function(module, exports, require){ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Convert interpolation in the given string to JavaScript. + * + * @param {String} str + * @return {String} + * @api private + */ + +var interpolate = exports.interpolate = function(str){ + return str.replace(/(\\)?([#!]){(.*?)}/g, function(str, escape, flag, code){ + return escape + ? str + : "' + " + + ('!' == flag ? '' : 'escape') + + "((interp = " + code.replace(/\\'/g, "'") + + ") == null ? '' : interp) + '"; + }); +}; + +/** + * Escape single quotes in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +var escape = exports.escape = function(str) { + return str.replace(/'/g, "\\'"); +}; + +/** + * Interpolate, and escape the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.text = function(str){ + return interpolate(escape(str)); +}; +}); // module: utils.js + +window.jade = require("jade"); +})(); diff --git a/hm_sunwell/node_modules/jade/jade.md b/hm_sunwell/node_modules/jade/jade.md new file mode 100644 index 0000000..051dc03 --- /dev/null +++ b/hm_sunwell/node_modules/jade/jade.md @@ -0,0 +1,510 @@ + +# Jade + + The jade template engine for node.js + +## Synopsis + + jade [-h|--help] [-v|--version] [-o|--obj STR] + [-O|--out DIR] [-p|--path PATH] [-P|--pretty] + [-c|--client] [-D|--no-debug] + +## Examples + + translate jade the templates dir + + $ jade templates + + create {foo,bar}.html + + $ jade {foo,bar}.jade + + jade over stdio + + $ jade < my.jade > my.html + + jade over s + + $ echo "h1 Jade!" | jade + + foo, bar dirs rendering to /tmp + + $ jade foo bar --out /tmp + + compile client-side templates without debugging + instrumentation, making the output javascript + very light-weight. This requires runtime.js + in your projects. + + $ jade --client --no-debug < my.jade + +## Tags + + Tags are simply nested via whitespace, closing + tags defined for you. These indents are called "blocks". + + ul + li + a Foo + li + a Bar + + You may have several tags in one "block": + + ul + li + a Foo + a Bar + a Baz + +## Self-closing Tags + + Some tags are flagged as self-closing by default, such + as `meta`, `link`, and so on. To explicitly self-close + a tag simply append the `/` character: + + foo/ + foo(bar='baz')/ + + Would yield: + + + + +## Attributes + + Tag attributes look similar to HTML, however + the values are regular JavaScript, here are + some examples: + + a(href='google.com') Google + a(class='button', href='google.com') Google + + As mentioned the attribute values are just JavaScript, + this means ternary operations and other JavaScript expressions + work just fine: + + body(class=user.authenticated ? 'authenticated' : 'anonymous') + a(href=user.website || 'http://google.com') + + Multiple lines work too: + + input(type='checkbox', + name='agreement', + checked) + + Multiple lines without the comma work fine: + + input(type='checkbox' + name='agreement' + checked) + + Funky whitespace? fine: + + input( + type='checkbox' + name='agreement' + checked) + +## Boolean attributes + + Boolean attributes are mirrored by Jade, and accept + bools, aka _true_ or _false_. When no value is specified + _true_ is assumed. For example: + + input(type="checkbox", checked) + // => "" + + For example if the checkbox was for an agreement, perhaps `user.agreed` + was _true_ the following would also output 'checked="checked"': + + input(type="checkbox", checked=user.agreed) + +## Class attributes + + The _class_ attribute accepts an array of classes, + this can be handy when generated from a javascript + function etc: + + classes = ['foo', 'bar', 'baz'] + a(class=classes) + // => "" + +## Class literal + + Classes may be defined using a ".CLASSNAME" syntax: + + .button + // => "
" + + Or chained: + + .large.button + // => "
" + + The previous defaulted to divs, however you + may also specify the tag type: + + h1.title My Title + // => "

My Title

" + +## Id literal + + Much like the class literal there's an id literal: + + #user-1 + // => "
" + + Again we may specify the tag as well: + + ul#menu + li: a(href='/home') Home + li: a(href='/store') Store + li: a(href='/contact') Contact + + Finally all of these may be used in any combination, + the following are all valid tags: + + a.button#contact(style: 'color: red') Contact + a.button(style: 'color: red')#contact Contact + a(style: 'color: red').button#contact Contact + +## Block expansion + + Jade supports the concept of "block expansion", in which + using a trailing ":" after a tag will inject a block: + + ul + li: a Foo + li: a Bar + li: a Baz + +## Text + + Arbitrary text may follow tags: + + p Welcome to my site + + yields: + +

Welcome to my site

+ +## Pipe text + + Another form of text is "pipe" text. Pipes act + as the text margin for large bodies of text. + + p + | This is a large + | body of text for + | this tag. + | + | Nothing too + | exciting. + + yields: + +

This is a large + body of text for + this tag. + + Nothing too + exciting. +

+ + Using pipes we can also specify regular Jade tags + within the text: + + p + | Click to visit + a(href='http://google.com') Google + | if you want. + +## Text only tags + + As an alternative to pipe text you may add + a trailing "." to indicate that the block + contains nothing but plain-text, no tags: + + p. + This is a large + body of text for + this tag. + + Nothing too + exciting. + + Some tags are text-only by default, for example + _script_, _textarea_, and _style_ tags do not + contain nested HTML so Jade implies the trailing ".": + + script + if (foo) { + bar(); + } + + style + body { + padding: 50px; + font: 14px Helvetica; + } + +## Template script tags + + Sometimes it's useful to define HTML in script + tags using Jade, typically for client-side templates. + + To do this simply give the _script_ tag an arbitrary + _type_ attribute such as _text/x-template_: + + script(type='text/template') + h1 Look! + p Jade still works in here! + +## Interpolation + + Both plain-text and piped-text support interpolation, + which comes in two forms, escapes and non-escaped. The + following will output the _user.name_ in the paragraph + but HTML within it will be escaped to prevent XSS attacks: + + p Welcome #{user.name} + + The following syntax is identical however it will _not_ escape + HTML, and should only be used with strings that you trust: + + p Welcome !{user.name} + +## Inline HTML + + Sometimes constructing small inline snippets of HTML + in Jade can be annoying, luckily we can add plain + HTML as well: + + p Welcome #{user.name} + +## Code + + To buffer output with Jade simply use _=_ at the beginning + of a line or after a tag. This method escapes any HTML + present in the string. + + p= user.description + + To buffer output unescaped use the _!=_ variant, but again + be careful of XSS. + + p!= user.description + + The final way to mess with JavaScript code in Jade is the unbuffered + _-_, which can be used for conditionals, defining variables etc: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) { + h2 Description + p.description= user.description + - } + + When compiled blocks are wrapped in anonymous functions, so the + following is also valid, without braces: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) + h2 Description + p.description= user.description + + If you really want you could even use `.forEach()` and others: + + - users.forEach(function(user){ + .user + h2= user.name + p User #{user.name} is #{user.age} years old + - }) + + Taking this further Jade provides some syntax for conditionals, + iteration, switch statements etc. Let's look at those next! + +## Assignment + + Jade's first-class assignment is simple, simply use the _=_ + operator and Jade will _var_ it for you. The following are equivalent: + + - var user = { name: 'tobi' } + user = { name: 'tobi' } + +## Conditionals + + Jade's first-class conditional syntax allows for optional + parenthesis, and you may now omit the leading _-_ otherwise + it's identical, still just regular javascript: + + user = { description: 'foo bar baz' } + #user + if user.description + h2 Description + p.description= user.description + + Jade provides the negated version, _unless_ as well, the following + are equivalent: + + - if (!(user.isAnonymous)) + p You're logged in as #{user.name} + + unless user.isAnonymous + p You're logged in as #{user.name} + +## Iteration + + JavaScript's _for_ loops don't look very declarative, so Jade + also provides its own _for_ loop construct, aliased as _each_: + + for user in users + .user + h2= user.name + p user #{user.name} is #{user.age} year old + + As mentioned _each_ is identical: + + each user in users + .user + h2= user.name + + If necessary the index is available as well: + + for user, i in users + .user(class='user-#{i}') + h2= user.name + + Remember, it's just JavaScript: + + ul#letters + for letter in ['a', 'b', 'c'] + li= letter + +## Mixins + + Mixins provide a way to define jade "functions" which "mix in" + their contents when called. This is useful for abstracting + out large fragments of Jade. + + The simplest possible mixin which accepts no arguments might + look like this: + + mixin hello + p Hello + + You use a mixin by placing `+` before the name: + + +hello + + For something a little more dynamic, mixins can take + arguments, the mixin itself is converted to a javascript + function internally: + + mixin hello(user) + p Hello #{user} + + +hello('Tobi') + + Yields: + +

Hello Tobi

+ + Mixins may optionally take blocks, when a block is passed + its contents becomes the implicit `block` argument. For + example here is a mixin passed a block, and also invoked + without passing a block: + + mixin article(title) + .article + .article-wrapper + h1= title + if block + block + else + p No content provided + + +article('Hello world') + + +article('Hello world') + p This is my + p Amazing article + + yields: + +
+
+

Hello world

+

No content provided

+
+
+ +
+
+

Hello world

+

This is my

+

Amazing article

+
+
+ + Mixins can even take attributes, just like a tag. When + attributes are passed they become the implicit `attributes` + argument. Individual attributes can be accessed just like + normal object properties: + + mixin centered + .centered(class=attributes.class) + block + + +centered.bold Hello world + + +centered.red + p This is my + p Amazing article + + yields: + +
Hello world
+
+

This is my

+

Amazing article

+
+ + If you use `attributes` directly, *all* passed attributes + get used: + + mixin link + a.menu(attributes) + block + + +link.highlight(href='#top') Top + +link#sec1.plain(href='#section1') Section 1 + +link#sec2.plain(href='#section2') Section 2 + + yields: + + Top + Section 1 + Section 2 + + If you pass arguments, they must directly follow the mixin: + + mixin list(arr) + if block + .title + block + ul(attributes) + each item in arr + li= item + + +list(['foo', 'bar', 'baz'])(id='myList', class='bold') + + yields: + +
    +
  • foo
  • +
  • bar
  • +
  • baz
  • +
diff --git a/hm_sunwell/node_modules/jade/jade.min.js b/hm_sunwell/node_modules/jade/jade.min.js new file mode 100644 index 0000000..72e4535 --- /dev/null +++ b/hm_sunwell/node_modules/jade/jade.min.js @@ -0,0 +1,2 @@ +(function(){function require(p){var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');return mod.exports||(mod.exports={},mod.call(mod.exports,mod,mod.exports,require.relative(path))),mod.exports}require.modules={},require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig},require.register=function(path,fn){require.modules[path]=fn},require.relative=function(parent){return function(p){if("."!=p.charAt(0))return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i",this.doctype=doctype,this.terse="5"==name||"html"==name,this.xml=0==this.doctype.indexOf("1&&!escape&&block.nodes[0].isText&&block.nodes[1].isText&&this.prettyIndent(1,!0);for(var i=0;i0&&!escape&&block.nodes[i].isText&&block.nodes[i-1].isText&&this.prettyIndent(1,!1),this.visit(block.nodes[i]),block.nodes[i+1]&&block.nodes[i].isText&&block.nodes[i+1].isText&&this.buffer("\\n")},visitDoctype:function(doctype){doctype&&(doctype.val||!this.doctype)&&this.setDoctype(doctype.val||"default"),this.doctype&&this.buffer(this.doctype),this.hasCompiledDoctype=!0},visitMixin:function(mixin){var name=mixin.name.replace(/-/g,"_")+"_mixin",args=mixin.args||"",block=mixin.block,attrs=mixin.attrs,pp=this.pp;if(mixin.call){pp&&this.buf.push("__indent.push('"+Array(this.indents+1).join(" ")+"');");if(block||attrs.length){this.buf.push(name+".call({");if(block){this.buf.push("block: function(){"),this.parentIndents++;var _indents=this.indents;this.indents=0,this.visit(mixin.block),this.indents=_indents,this.parentIndents--,attrs.length?this.buf.push("},"):this.buf.push("}")}if(attrs.length){var val=this.attrs(attrs);val.inherits?this.buf.push("attributes: merge({"+val.buf+"}, attributes), escaped: merge("+val.escaped+", escaped, true)"):this.buf.push("attributes: {"+val.buf+"}, escaped: "+val.escaped)}args?this.buf.push("}, "+args+");"):this.buf.push("});")}else this.buf.push(name+"("+args+");");pp&&this.buf.push("__indent.pop();")}else this.buf.push("var "+name+" = function("+args+"){"),this.buf.push("var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};"),this.parentIndents++,this.visit(block),this.parentIndents--,this.buf.push("};")},visitTag:function(tag){this.indents++;var name=tag.name,pp=this.pp;tag.buffer&&(name="' + ("+name+") + '"),this.hasCompiledTag||(!this.hasCompiledDoctype&&"html"==name&&this.visitDoctype(),this.hasCompiledTag=!0),pp&&!tag.isInline()&&this.prettyIndent(0,!0),(~selfClosing.indexOf(name)||tag.selfClosing)&&!this.xml?(this.buffer("<"+name),this.visitAttributes(tag.attrs),this.terse?this.buffer(">"):this.buffer("/>")):(tag.attrs.length?(this.buffer("<"+name),tag.attrs.length&&this.visitAttributes(tag.attrs),this.buffer(">")):this.buffer("<"+name+">"),tag.code&&this.visitCode(tag.code),this.escape="pre"==tag.name,this.visit(tag.block),pp&&!tag.isInline()&&"pre"!=tag.name&&!tag.canInline()&&this.prettyIndent(0,!0),this.buffer("")),this.indents--},visitFilter:function(filter){var fn=filters[filter.name];if(!fn)throw filter.isASTFilter?new Error('unknown ast filter "'+filter.name+':"'):new Error('unknown filter ":'+filter.name+'"');if(filter.isASTFilter)this.buf.push(fn(filter.block,this,filter.attrs));else{var text=filter.block.nodes.map(function(node){return node.val}).join("\n");filter.attrs=filter.attrs||{},filter.attrs.filename=this.options.filename,this.buffer(utils.text(fn(text,filter.attrs)))}},visitText:function(text){text=utils.text(text.val.replace(/\\/g,"\\\\")),this.escape&&(text=escape(text)),this.buffer(text)},visitComment:function(comment){if(!comment.buffer)return;this.pp&&this.prettyIndent(1,!0),this.buffer("")},visitBlockComment:function(comment){if(!comment.buffer)return;0==comment.val.trim().indexOf("if")?(this.buffer("")):(this.buffer(""))},visitCode:function(code){if(code.buffer){var val=code.val.trimLeft();this.buf.push("var __val__ = "+val),val='null == __val__ ? "" : __val__',code.escape&&(val="escape("+val+")"),this.buf.push("buf.push("+val+");")}else this.buf.push(code.val);code.block&&(code.buffer||this.buf.push("{"),this.visit(code.block),code.buffer||this.buf.push("}"))},visitEach:function(each){this.buf.push("// iterate "+each.obj+"\n"+";(function(){\n"+" if ('number' == typeof "+each.obj+".length) {\n"+" for (var "+each.key+" = 0, $$l = "+each.obj+".length; "+each.key+" < $$l; "+each.key+"++) {\n"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n } else {\n for (var "+each.key+" in "+each.obj+") {\n"+" if ("+each.obj+".hasOwnProperty("+each.key+")){"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n"),this.buf.push(" }\n }\n}).call(this);\n")},visitAttributes:function(attrs){var val=this.attrs(attrs);val.inherits?this.buf.push("buf.push(attrs(merge({ "+val.buf+" }, attributes), merge("+val.escaped+", escaped, true)));"):val.constant?(eval("var buf={"+val.buf+"};"),this.buffer(runtime.attrs(buf,JSON.parse(val.escaped)),!0)):this.buf.push("buf.push(attrs({ "+val.buf+" }, "+val.escaped+"));")},attrs:function(attrs){var buf=[],classes=[],escaped={},constant=attrs.every(function(attr){return isConstant(attr.val)}),inherits=!1;return this.terse&&buf.push("terse: true"),attrs.forEach(function(attr){if(attr.name=="attributes")return inherits=!0;escaped[attr.name]=attr.escaped;if(attr.name=="class")classes.push("("+attr.val+")");else{var pair="'"+attr.name+"':("+attr.val+")";buf.push(pair)}}),classes.length&&(classes=classes.join(" + ' ' + "),buf.push("class: "+classes)),{buf:buf.join(", ").replace("class:",'"class":'),escaped:JSON.stringify(escaped),inherits:inherits,constant:constant}}};function isConstant(val){if(/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val))return!0;if(!isNaN(Number(val)))return!0;var matches;return(matches=/^ *\[(.*)\] *$/.exec(val))?matches[1].split(",").every(isConstant):!1}function escape(html){return String(html).replace(/&(?!\w+;)/g,"&").replace(//g,">").replace(/"/g,""")}}),require.register("doctypes.js",function(module,exports,require){module.exports={5:"","default":"",xml:'',transitional:'',strict:'',frameset:'',1.1:'',basic:'',mobile:''}}),require.register("filters.js",function(module,exports,require){module.exports={cdata:function(str){return""},sass:function(str){str=str.replace(/\\n/g,"\n");var sass=require("sass").render(str).replace(/\n/g,"\\n");return'"},stylus:function(str,options){var ret;str=str.replace(/\\n/g,"\n");var stylus=require("stylus");return stylus(str,options).render(function(err,css){if(err)throw err;ret=css.replace(/\n/g,"\\n")}),'"},less:function(str){var ret;return str=str.replace(/\\n/g,"\n"),require("less").render(str,function(err,css){if(err)throw err;ret='"}),ret},markdown:function(str){var md;try{md=require("markdown")}catch(err){try{md=require("discount")}catch(err){try{md=require("markdown-js")}catch(err){try{md=require("marked")}catch(err){throw new Error("Cannot find markdown library, install markdown, discount, or marked.")}}}}return str=str.replace(/\\n/g,"\n"),md.parse(str).replace(/\n/g,"\\n").replace(/'/g,"'")},coffeescript:function(str){str=str.replace(/\\n/g,"\n");var js=require("coffee-script").compile(str).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");return'"}}}),require.register("inline-tags.js",function(module,exports,require){module.exports=["a","abbr","acronym","b","br","code","em","font","i","img","ins","kbd","map","samp","small","span","strong","sub","sup"]}),require.register("jade.js",function(module,exports,require){var Parser=require("./parser"),Lexer=require("./lexer"),Compiler=require("./compiler"),runtime=require("./runtime");exports.version="0.26.1",exports.selfClosing=require("./self-closing"),exports.doctypes=require("./doctypes"),exports.filters=require("./filters"),exports.utils=require("./utils"),exports.Compiler=Compiler,exports.Parser=Parser,exports.Lexer=Lexer,exports.nodes=require("./nodes"),exports.runtime=runtime,exports.cache={};function parse(str,options){try{var parser=new Parser(str,options.filename,options),compiler=new(options.compiler||Compiler)(parser.parse(),options),js=compiler.compile();return options.debug&&console.error("\nCompiled Function:\n\n%s",js.replace(/^/gm," ")),"var buf = [];\n"+(options.self?"var self = locals || {};\n"+js:"with (locals || {}) {\n"+js+"\n}\n")+'return buf.join("");'}catch(err){parser=parser.context(),runtime.rethrow(err,parser.filename,parser.lexer.lineno)}}exports.compile=function(str,options){var options=options||{},client=options.client,filename=options.filename?JSON.stringify(options.filename):"undefined",fn;return options.compileDebug!==!1?fn=["var __jade = [{ lineno: 1, filename: "+filename+" }];","try {",parse(String(str),options),"} catch (err) {"," rethrow(err, __jade[0].filename, __jade[0].lineno);","}"].join("\n"):fn=parse(String(str),options),client&&(fn="attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n"+fn),fn=new Function("locals, attrs, escape, rethrow, merge",fn),client?fn:function(locals){return fn(locals,runtime.attrs,runtime.escape,runtime.rethrow,runtime.merge)}},exports.render=function(str,options,fn){"function"==typeof options&&(fn=options,options={});if(options.cache&&!options.filename)return fn(new Error('the "filename" option is required for caching'));try{var path=options.filename,tmpl=options.cache?exports.cache[path]||(exports.cache[path]=exports.compile(str,options)):exports.compile(str,options);fn(null,tmpl(options))}catch(err){fn(err)}},exports.renderFile=function(path,options,fn){var key=path+":string";"function"==typeof options&&(fn=options,options={});try{options.filename=path;var str=options.cache?exports.cache[key]||(exports.cache[key]=fs.readFileSync(path,"utf8")):fs.readFileSync(path,"utf8");exports.render(str,options,fn)}catch(err){fn(err)}},exports.__express=exports.renderFile}),require.register("lexer.js",function(module,exports,require){var Lexer=module.exports=function Lexer(str,options){options=options||{},this.input=str.replace(/\r\n|\r/g,"\n"),this.colons=options.colons,this.deferredTokens=[],this.lastIndents=0,this.lineno=1,this.stash=[],this.indentStack=[],this.indentRe=null,this.pipeless=!1};Lexer.prototype={tok:function(type,val){return{type:type,line:this.lineno,val:val}},consume:function(len){this.input=this.input.substr(len)},scan:function(regexp,type){var captures;if(captures=regexp.exec(this.input))return this.consume(captures[0].length),this.tok(type,captures[1])},defer:function(tok){this.deferredTokens.push(tok)},lookahead:function(n){var fetch=n-this.stash.length;while(fetch-->0)this.stash.push(this.next());return this.stash[--n]},indexOfDelimiters:function(start,end){var str=this.input,nstart=0,nend=0,pos=0;for(var i=0,len=str.length;iindents)this.stash.push(this.tok("outdent")),this.indentStack.shift();tok=this.stash.pop()}else indents&&indents!=this.indentStack[0]?(this.indentStack.unshift(indents),tok=this.tok("indent",indents)):tok=this.tok("newline");return tok}},pipelessText:function(){if(this.pipeless){if("\n"==this.input[0])return;var i=this.input.indexOf("\n");-1==i&&(i=this.input.length);var str=this.input.substr(0,i);return this.consume(str.length),this.tok("text",str)}},colon:function(){return this.scan(/^: */,":")},advance:function(){return this.stashed()||this.next()},next:function(){return this.deferred()||this.blank()||this.eos()||this.pipelessText()||this.yield()||this.doctype()||this.interpolation()||this["case"]()||this.when()||this["default"]()||this["extends"]()||this.append()||this.prepend()||this.block()||this.include()||this.mixin()||this.call()||this.conditional()||this.each()||this["while"]()||this.assignment()||this.tag()||this.filter()||this.code()||this.id()||this.className()||this.attrs()||this.indent()||this.comment()||this.colon()||this.text()}}}),require.register("nodes/attrs.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Attrs=module.exports=function Attrs(){this.attrs=[]};Attrs.prototype=new Node,Attrs.prototype.constructor=Attrs,Attrs.prototype.setAttribute=function(name,val,escaped){return this.attrs.push({name:name,val:val,escaped:escaped}),this},Attrs.prototype.removeAttribute=function(name){for(var i=0,len=this.attrs.length;i/g,">").replace(/"/g,""")},exports.rethrow=function rethrow(err,filename,lineno){if(!filename)throw err;var context=3,str=require("fs").readFileSync(filename,"utf8"),lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message,err}}),require.register("self-closing.js",function(module,exports,require){module.exports=["meta","img","link","input","source","area","base","col","br","hr"]}),require.register("utils.js",function(module,exports,require){var interpolate=exports.interpolate=function(str){return str.replace(/(\\)?([#!]){(.*?)}/g,function(str,escape,flag,code){return escape?str:"' + "+("!"==flag?"":"escape")+"((interp = "+code.replace(/\\'/g,"'")+") == null ? '' : interp) + '"})},escape=exports.escape=function(str){return str.replace(/'/g,"\\'")};exports.text=function(str){return interpolate(escape(str))}}),window.jade=require("jade")})(); \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/compiler.js b/hm_sunwell/node_modules/jade/lib/compiler.js new file mode 100644 index 0000000..516ac83 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/compiler.js @@ -0,0 +1,642 @@ + +/*! + * Jade - Compiler + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var nodes = require('./nodes') + , filters = require('./filters') + , doctypes = require('./doctypes') + , selfClosing = require('./self-closing') + , runtime = require('./runtime') + , utils = require('./utils'); + +// if browser +// +// if (!Object.keys) { +// Object.keys = function(obj){ +// var arr = []; +// for (var key in obj) { +// if (obj.hasOwnProperty(key)) { +// arr.push(key); +// } +// } +// return arr; +// } +// } +// +// if (!String.prototype.trimLeft) { +// String.prototype.trimLeft = function(){ +// return this.replace(/^\s+/, ''); +// } +// } +// +// end + + +/** + * Initialize `Compiler` with the given `node`. + * + * @param {Node} node + * @param {Object} options + * @api public + */ + +var Compiler = module.exports = function Compiler(node, options) { + this.options = options = options || {}; + this.node = node; + this.hasCompiledDoctype = false; + this.hasCompiledTag = false; + this.pp = options.pretty || false; + this.debug = false !== options.compileDebug; + this.indents = 0; + this.parentIndents = 0; + if (options.doctype) this.setDoctype(options.doctype); +}; + +/** + * Compiler prototype. + */ + +Compiler.prototype = { + + /** + * Compile parse tree to JavaScript. + * + * @api public + */ + + compile: function(){ + this.buf = ['var interp;']; + if (this.pp) this.buf.push("var __indent = [];"); + this.lastBufferedIdx = -1; + this.visit(this.node); + return this.buf.join('\n'); + }, + + /** + * Sets the default doctype `name`. Sets terse mode to `true` when + * html 5 is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {string} name + * @api public + */ + + setDoctype: function(name){ + var doctype = doctypes[(name || 'default').toLowerCase()]; + doctype = doctype || ''; + this.doctype = doctype; + this.terse = '5' == name || 'html' == name; + this.xml = 0 == this.doctype.indexOf(' 1 && !escape && block.nodes[0].isText && block.nodes[1].isText) + this.prettyIndent(1, true); + + for (var i = 0; i < len; ++i) { + // Pretty print text + if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText) + this.prettyIndent(1, false); + + this.visit(block.nodes[i]); + // Multiple text nodes are separated by newlines + if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText) + this.buffer('\\n'); + } + }, + + /** + * Visit `doctype`. Sets terse mode to `true` when html 5 + * is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {Doctype} doctype + * @api public + */ + + visitDoctype: function(doctype){ + if (doctype && (doctype.val || !this.doctype)) { + this.setDoctype(doctype.val || 'default'); + } + + if (this.doctype) this.buffer(this.doctype); + this.hasCompiledDoctype = true; + }, + + /** + * Visit `mixin`, generating a function that + * may be called within the template. + * + * @param {Mixin} mixin + * @api public + */ + + visitMixin: function(mixin){ + var name = mixin.name.replace(/-/g, '_') + '_mixin' + , args = mixin.args || '' + , block = mixin.block + , attrs = mixin.attrs + , pp = this.pp; + + if (mixin.call) { + if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');") + if (block || attrs.length) { + + this.buf.push(name + '.call({'); + + if (block) { + this.buf.push('block: function(){'); + + // Render block with no indents, dynamically added when rendered + this.parentIndents++; + var _indents = this.indents; + this.indents = 0; + this.visit(mixin.block); + this.indents = _indents; + this.parentIndents--; + + if (attrs.length) { + this.buf.push('},'); + } else { + this.buf.push('}'); + } + } + + if (attrs.length) { + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push('attributes: merge({' + val.buf + + '}, attributes), escaped: merge(' + val.escaped + ', escaped, true)'); + } else { + this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped); + } + } + + if (args) { + this.buf.push('}, ' + args + ');'); + } else { + this.buf.push('});'); + } + + } else { + this.buf.push(name + '(' + args + ');'); + } + if (pp) this.buf.push("__indent.pop();") + } else { + this.buf.push('var ' + name + ' = function(' + args + '){'); + this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};'); + this.parentIndents++; + this.visit(block); + this.parentIndents--; + this.buf.push('};'); + } + }, + + /** + * Visit `tag` buffering tag markup, generating + * attributes, visiting the `tag`'s code and block. + * + * @param {Tag} tag + * @api public + */ + + visitTag: function(tag){ + this.indents++; + var name = tag.name + , pp = this.pp; + + if (tag.buffer) name = "' + (" + name + ") + '"; + + if (!this.hasCompiledTag) { + if (!this.hasCompiledDoctype && 'html' == name) { + this.visitDoctype(); + } + this.hasCompiledTag = true; + } + + // pretty print + if (pp && !tag.isInline()) + this.prettyIndent(0, true); + + if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) { + this.buffer('<' + name); + this.visitAttributes(tag.attrs); + this.terse + ? this.buffer('>') + : this.buffer('/>'); + } else { + // Optimize attributes buffering + if (tag.attrs.length) { + this.buffer('<' + name); + if (tag.attrs.length) this.visitAttributes(tag.attrs); + this.buffer('>'); + } else { + this.buffer('<' + name + '>'); + } + if (tag.code) this.visitCode(tag.code); + this.escape = 'pre' == tag.name; + this.visit(tag.block); + + // pretty print + if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline()) + this.prettyIndent(0, true); + + this.buffer(''); + } + this.indents--; + }, + + /** + * Visit `filter`, throwing when the filter does not exist. + * + * @param {Filter} filter + * @api public + */ + + visitFilter: function(filter){ + var fn = filters[filter.name]; + + // unknown filter + if (!fn) { + if (filter.isASTFilter) { + throw new Error('unknown ast filter "' + filter.name + ':"'); + } else { + throw new Error('unknown filter ":' + filter.name + '"'); + } + } + + if (filter.isASTFilter) { + this.buf.push(fn(filter.block, this, filter.attrs)); + } else { + var text = filter.block.nodes.map(function(node){ return node.val }).join('\n'); + filter.attrs = filter.attrs || {}; + filter.attrs.filename = this.options.filename; + this.buffer(utils.text(fn(text, filter.attrs))); + } + }, + + /** + * Visit `text` node. + * + * @param {Text} text + * @api public + */ + + visitText: function(text){ + text = utils.text(text.val.replace(/\\/g, '\\\\')); + if (this.escape) text = escape(text); + this.buffer(text); + }, + + /** + * Visit a `comment`, only buffering when the buffer flag is set. + * + * @param {Comment} comment + * @api public + */ + + visitComment: function(comment){ + if (!comment.buffer) return; + if (this.pp) this.prettyIndent(1, true); + this.buffer(''); + }, + + /** + * Visit a `BlockComment`. + * + * @param {Comment} comment + * @api public + */ + + visitBlockComment: function(comment){ + if (!comment.buffer) return; + if (0 == comment.val.trim().indexOf('if')) { + this.buffer(''); + } else { + this.buffer(''); + } + }, + + /** + * Visit `code`, respecting buffer / escape flags. + * If the code is followed by a block, wrap it in + * a self-calling function. + * + * @param {Code} code + * @api public + */ + + visitCode: function(code){ + // Wrap code blocks with {}. + // we only wrap unbuffered code blocks ATM + // since they are usually flow control + + // Buffer code + if (code.buffer) { + var val = code.val.trimLeft(); + this.buf.push('var __val__ = ' + val); + val = 'null == __val__ ? "" : __val__'; + if (code.escape) val = 'escape(' + val + ')'; + this.buf.push("buf.push(" + val + ");"); + } else { + this.buf.push(code.val); + } + + // Block support + if (code.block) { + if (!code.buffer) this.buf.push('{'); + this.visit(code.block); + if (!code.buffer) this.buf.push('}'); + } + }, + + /** + * Visit `each` block. + * + * @param {Each} each + * @api public + */ + + visitEach: function(each){ + this.buf.push('' + + '// iterate ' + each.obj + '\n' + + ';(function(){\n' + + ' if (\'number\' == typeof ' + each.obj + '.length) {\n' + + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push('' + + ' }\n' + + ' } else {\n' + + ' for (var ' + each.key + ' in ' + each.obj + ') {\n' + // if browser + // + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){' + // end + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + // if browser + // this.buf.push(' }\n'); + // end + + this.buf.push(' }\n }\n}).call(this);\n'); + }, + + /** + * Visit `attrs`. + * + * @param {Array} attrs + * @api public + */ + + visitAttributes: function(attrs){ + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push("buf.push(attrs(merge({ " + val.buf + + " }, attributes), merge(" + val.escaped + ", escaped, true)));"); + } else if (val.constant) { + eval('var buf={' + val.buf + '};'); + this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true); + } else { + this.buf.push("buf.push(attrs({ " + val.buf + " }, " + val.escaped + "));"); + } + }, + + /** + * Compile attributes. + */ + + attrs: function(attrs){ + var buf = [] + , classes = [] + , escaped = {} + , constant = attrs.every(function(attr){ return isConstant(attr.val) }) + , inherits = false; + + if (this.terse) buf.push('terse: true'); + + attrs.forEach(function(attr){ + if (attr.name == 'attributes') return inherits = true; + escaped[attr.name] = attr.escaped; + if (attr.name == 'class') { + classes.push('(' + attr.val + ')'); + } else { + var pair = "'" + attr.name + "':(" + attr.val + ')'; + buf.push(pair); + } + }); + + if (classes.length) { + classes = classes.join(" + ' ' + "); + buf.push("class: " + classes); + } + + return { + buf: buf.join(', ').replace('class:', '"class":'), + escaped: JSON.stringify(escaped), + inherits: inherits, + constant: constant + }; + } +}; + +/** + * Check if expression can be evaluated to a constant + * + * @param {String} expression + * @return {Boolean} + * @api private + */ + +function isConstant(val){ + // Check strings/literals + if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val)) + return true; + + // Check numbers + if (!isNaN(Number(val))) + return true; + + // Check arrays + var matches; + if (matches = /^ *\[(.*)\] *$/.exec(val)) + return matches[1].split(',').every(isConstant); + + return false; +} + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/doctypes.js b/hm_sunwell/node_modules/jade/lib/doctypes.js new file mode 100644 index 0000000..e87ca1e --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/doctypes.js @@ -0,0 +1,18 @@ + +/*! + * Jade - doctypes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + '5': '' + , 'default': '' + , 'xml': '' + , 'transitional': '' + , 'strict': '' + , 'frameset': '' + , '1.1': '' + , 'basic': '' + , 'mobile': '' +}; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/filters.js b/hm_sunwell/node_modules/jade/lib/filters.js new file mode 100644 index 0000000..fdb634c --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/filters.js @@ -0,0 +1,97 @@ + +/*! + * Jade - filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + + /** + * Wrap text with CDATA block. + */ + + cdata: function(str){ + return ''; + }, + + /** + * Transform sass to css, wrapped in style tags. + */ + + sass: function(str){ + str = str.replace(/\\n/g, '\n'); + var sass = require('sass').render(str).replace(/\n/g, '\\n'); + return ''; + }, + + /** + * Transform stylus to css, wrapped in style tags. + */ + + stylus: function(str, options){ + var ret; + str = str.replace(/\\n/g, '\n'); + var stylus = require('stylus'); + stylus(str, options).render(function(err, css){ + if (err) throw err; + ret = css.replace(/\n/g, '\\n'); + }); + return ''; + }, + + /** + * Transform less to css, wrapped in style tags. + */ + + less: function(str){ + var ret; + str = str.replace(/\\n/g, '\n'); + require('less').render(str, function(err, css){ + if (err) throw err; + ret = ''; + }); + return ret; + }, + + /** + * Transform markdown to html. + */ + + markdown: function(str){ + var md; + + // support markdown / discount + try { + md = require('markdown'); + } catch (err){ + try { + md = require('discount'); + } catch (err) { + try { + md = require('markdown-js'); + } catch (err) { + try { + md = require('marked'); + } catch (err) { + throw new + Error('Cannot find markdown library, install markdown, discount, or marked.'); + } + } + } + } + + str = str.replace(/\\n/g, '\n'); + return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,'''); + }, + + /** + * Transform coffeescript to javascript. + */ + + coffeescript: function(str){ + str = str.replace(/\\n/g, '\n'); + var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); + return ''; + } +}; diff --git a/hm_sunwell/node_modules/jade/lib/inline-tags.js b/hm_sunwell/node_modules/jade/lib/inline-tags.js new file mode 100644 index 0000000..491de0b --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/inline-tags.js @@ -0,0 +1,28 @@ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/jade.js b/hm_sunwell/node_modules/jade/lib/jade.js new file mode 100644 index 0000000..00f0abb --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/jade.js @@ -0,0 +1,237 @@ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Parser = require('./parser') + , Lexer = require('./lexer') + , Compiler = require('./compiler') + , runtime = require('./runtime') +// if node + , fs = require('fs'); +// end + +/** + * Library version. + */ + +exports.version = '0.26.3'; + +/** + * Expose self closing tags. + */ + +exports.selfClosing = require('./self-closing'); + +/** + * Default supported doctypes. + */ + +exports.doctypes = require('./doctypes'); + +/** + * Text filters. + */ + +exports.filters = require('./filters'); + +/** + * Utilities. + */ + +exports.utils = require('./utils'); + +/** + * Expose `Compiler`. + */ + +exports.Compiler = Compiler; + +/** + * Expose `Parser`. + */ + +exports.Parser = Parser; + +/** + * Expose `Lexer`. + */ + +exports.Lexer = Lexer; + +/** + * Nodes. + */ + +exports.nodes = require('./nodes'); + +/** + * Jade runtime helpers. + */ + +exports.runtime = runtime; + +/** + * Template function cache. + */ + +exports.cache = {}; + +/** + * Parse the given `str` of jade and return a function body. + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api private + */ + +function parse(str, options){ + try { + // Parse + var parser = new Parser(str, options.filename, options); + + // Compile + var compiler = new (options.compiler || Compiler)(parser.parse(), options) + , js = compiler.compile(); + + // Debug compiler + if (options.debug) { + console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' ')); + } + + return '' + + 'var buf = [];\n' + + (options.self + ? 'var self = locals || {};\n' + js + : 'with (locals || {}) {\n' + js + '\n}\n') + + 'return buf.join("");'; + } catch (err) { + parser = parser.context(); + runtime.rethrow(err, parser.filename, parser.lexer.lineno); + } +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + if (options.compileDebug !== false) { + fn = [ + 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(String(str), options) + , '} catch (err) {' + , ' rethrow(err, __jade[0].filename, __jade[0].lineno);' + , '}' + ].join('\n'); + } else { + fn = parse(String(str), options); + } + + if (client) { + fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn; + } + + fn = new Function('locals, attrs, escape, rethrow, merge', fn); + + if (client) return fn; + + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge); + }; +}; + +/** + * Render the given `str` of jade and invoke + * the callback `fn(err, str)`. + * + * Options: + * + * - `cache` enable template caching + * - `filename` filename required for `include` / `extends` and caching + * + * @param {String} str + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +exports.render = function(str, options, fn){ + // swap args + if ('function' == typeof options) { + fn = options, options = {}; + } + + // cache requires .filename + if (options.cache && !options.filename) { + return fn(new Error('the "filename" option is required for caching')); + } + + try { + var path = options.filename; + var tmpl = options.cache + ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options)) + : exports.compile(str, options); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Render a Jade file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + try { + options.filename = path; + var str = options.cache + ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8')) + : fs.readFileSync(path, 'utf8'); + exports.render(str, options, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Express support. + */ + +exports.__express = exports.renderFile; diff --git a/hm_sunwell/node_modules/jade/lib/lexer.js b/hm_sunwell/node_modules/jade/lib/lexer.js new file mode 100644 index 0000000..bca314a --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/lexer.js @@ -0,0 +1,771 @@ + +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize `Lexer` with the given `str`. + * + * Options: + * + * - `colons` allow colons for attr delimiters + * + * @param {String} str + * @param {Object} options + * @api private + */ + +var Lexer = module.exports = function Lexer(str, options) { + options = options || {}; + this.input = str.replace(/\r\n|\r/g, '\n'); + this.colons = options.colons; + this.deferredTokens = []; + this.lastIndents = 0; + this.lineno = 1; + this.stash = []; + this.indentStack = []; + this.indentRe = null; + this.pipeless = false; +}; + +/** + * Lexer prototype. + */ + +Lexer.prototype = { + + /** + * Construct a token with the given `type` and `val`. + * + * @param {String} type + * @param {String} val + * @return {Object} + * @api private + */ + + tok: function(type, val){ + return { + type: type + , line: this.lineno + , val: val + } + }, + + /** + * Consume the given `len` of input. + * + * @param {Number} len + * @api private + */ + + consume: function(len){ + this.input = this.input.substr(len); + }, + + /** + * Scan for `type` with the given `regexp`. + * + * @param {String} type + * @param {RegExp} regexp + * @return {Object} + * @api private + */ + + scan: function(regexp, type){ + var captures; + if (captures = regexp.exec(this.input)) { + this.consume(captures[0].length); + return this.tok(type, captures[1]); + } + }, + + /** + * Defer the given `tok`. + * + * @param {Object} tok + * @api private + */ + + defer: function(tok){ + this.deferredTokens.push(tok); + }, + + /** + * Lookahead `n` tokens. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + var fetch = n - this.stash.length; + while (fetch-- > 0) this.stash.push(this.next()); + return this.stash[--n]; + }, + + /** + * Return the indexOf `start` / `end` delimiters. + * + * @param {String} start + * @param {String} end + * @return {Number} + * @api private + */ + + indexOfDelimiters: function(start, end){ + var str = this.input + , nstart = 0 + , nend = 0 + , pos = 0; + for (var i = 0, len = str.length; i < len; ++i) { + if (start == str.charAt(i)) { + ++nstart; + } else if (end == str.charAt(i)) { + if (++nend == nstart) { + pos = i; + break; + } + } + } + return pos; + }, + + /** + * Stashed token. + */ + + stashed: function() { + return this.stash.length + && this.stash.shift(); + }, + + /** + * Deferred token. + */ + + deferred: function() { + return this.deferredTokens.length + && this.deferredTokens.shift(); + }, + + /** + * end-of-source. + */ + + eos: function() { + if (this.input.length) return; + if (this.indentStack.length) { + this.indentStack.shift(); + return this.tok('outdent'); + } else { + return this.tok('eos'); + } + }, + + /** + * Blank line. + */ + + blank: function() { + var captures; + if (captures = /^\n *\n/.exec(this.input)) { + this.consume(captures[0].length - 1); + if (this.pipeless) return this.tok('text', ''); + return this.next(); + } + }, + + /** + * Comment. + */ + + comment: function() { + var captures; + if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('comment', captures[2]); + tok.buffer = '-' != captures[1]; + return tok; + } + }, + + /** + * Interpolated tag. + */ + + interpolation: function() { + var captures; + if (captures = /^#\{(.*?)\}/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('interpolation', captures[1]); + } + }, + + /** + * Tag. + */ + + tag: function() { + var captures; + if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) { + this.consume(captures[0].length); + var tok, name = captures[1]; + if (':' == name[name.length - 1]) { + name = name.slice(0, -1); + tok = this.tok('tag', name); + this.defer(this.tok(':')); + while (' ' == this.input[0]) this.input = this.input.substr(1); + } else { + tok = this.tok('tag', name); + } + tok.selfClosing = !! captures[2]; + return tok; + } + }, + + /** + * Filter. + */ + + filter: function() { + return this.scan(/^:(\w+)/, 'filter'); + }, + + /** + * Doctype. + */ + + doctype: function() { + return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype'); + }, + + /** + * Id. + */ + + id: function() { + return this.scan(/^#([\w-]+)/, 'id'); + }, + + /** + * Class. + */ + + className: function() { + return this.scan(/^\.([\w-]+)/, 'class'); + }, + + /** + * Text. + */ + + text: function() { + return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text'); + }, + + /** + * Extends. + */ + + "extends": function() { + return this.scan(/^extends? +([^\n]+)/, 'extends'); + }, + + /** + * Block prepend. + */ + + prepend: function() { + var captures; + if (captures = /^prepend +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'prepend' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block append. + */ + + append: function() { + var captures; + if (captures = /^append +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'append' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block. + */ + + block: function() { + var captures; + if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = captures[1] || 'replace' + , name = captures[2] + , tok = this.tok('block', name); + + tok.mode = mode; + return tok; + } + }, + + /** + * Yield. + */ + + yield: function() { + return this.scan(/^yield */, 'yield'); + }, + + /** + * Include. + */ + + include: function() { + return this.scan(/^include +([^\n]+)/, 'include'); + }, + + /** + * Case. + */ + + "case": function() { + return this.scan(/^case +([^\n]+)/, 'case'); + }, + + /** + * When. + */ + + when: function() { + return this.scan(/^when +([^:\n]+)/, 'when'); + }, + + /** + * Default. + */ + + "default": function() { + return this.scan(/^default */, 'default'); + }, + + /** + * Assignment. + */ + + assignment: function() { + var captures; + if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) { + this.consume(captures[0].length); + var name = captures[1] + , val = captures[2]; + return this.tok('code', 'var ' + name + ' = (' + val + ');'); + } + }, + + /** + * Call mixin. + */ + + call: function(){ + var captures; + if (captures = /^\+([-\w]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('call', captures[1]); + + // Check for args (not attributes) + if (captures = /^ *\((.*?)\)/.exec(this.input)) { + if (!/^ *[-\w]+ *=/.test(captures[1])) { + this.consume(captures[0].length); + tok.args = captures[1]; + } + } + + return tok; + } + }, + + /** + * Mixin. + */ + + mixin: function(){ + var captures; + if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('mixin', captures[1]); + tok.args = captures[2]; + return tok; + } + }, + + /** + * Conditional. + */ + + conditional: function() { + var captures; + if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var type = captures[1] + , js = captures[2]; + + switch (type) { + case 'if': js = 'if (' + js + ')'; break; + case 'unless': js = 'if (!(' + js + '))'; break; + case 'else if': js = 'else if (' + js + ')'; break; + case 'else': js = 'else'; break; + } + + return this.tok('code', js); + } + }, + + /** + * While. + */ + + "while": function() { + var captures; + if (captures = /^while +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('code', 'while (' + captures[1] + ')'); + } + }, + + /** + * Each. + */ + + each: function() { + var captures; + if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('each', captures[1]); + tok.key = captures[2] || '$index'; + tok.code = captures[3]; + return tok; + } + }, + + /** + * Code. + */ + + code: function() { + var captures; + if (captures = /^(!?=|-)([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var flags = captures[1]; + captures[1] = captures[2]; + var tok = this.tok('code', captures[1]); + tok.escape = flags[0] === '='; + tok.buffer = flags[0] === '=' || flags[1] === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.indexOfDelimiters('(', ')') + , str = this.input.substr(1, index-1) + , tok = this.tok('attrs') + , len = str.length + , colons = this.colons + , states = ['key'] + , escapedAttr + , key = '' + , val = '' + , quote + , c + , p; + + function state(){ + return states[states.length - 1]; + } + + function interpolate(attr) { + return attr.replace(/#\{([^}]+)\}/g, function(_, expr){ + return quote + " + (" + expr + ") + " + quote; + }); + } + + this.consume(index + 1); + tok.attrs = {}; + tok.escaped = {}; + + function parse(c) { + var real = c; + // TODO: remove when people fix ":" + if (colons && ':' == c) c = '='; + switch (c) { + case ',': + case '\n': + switch (state()) { + case 'expr': + case 'array': + case 'string': + case 'object': + val += c; + break; + default: + states.push('key'); + val = val.trim(); + key = key.trim(); + if ('' == key) return; + key = key.replace(/^['"]|['"]$/g, '').replace('!', ''); + tok.escaped[key] = escapedAttr; + tok.attrs[key] = '' == val + ? true + : interpolate(val); + key = val = ''; + } + break; + case '=': + switch (state()) { + case 'key char': + key += real; + break; + case 'val': + case 'expr': + case 'array': + case 'string': + case 'object': + val += real; + break; + default: + escapedAttr = '!' != p; + states.push('val'); + } + break; + case '(': + if ('val' == state() + || 'expr' == state()) states.push('expr'); + val += c; + break; + case ')': + if ('expr' == state() + || 'val' == state()) states.pop(); + val += c; + break; + case '{': + if ('val' == state()) states.push('object'); + val += c; + break; + case '}': + if ('object' == state()) states.pop(); + val += c; + break; + case '[': + if ('val' == state()) states.push('array'); + val += c; + break; + case ']': + if ('array' == state()) states.pop(); + val += c; + break; + case '"': + case "'": + switch (state()) { + case 'key': + states.push('key char'); + break; + case 'key char': + states.pop(); + break; + case 'string': + if (c == quote) states.pop(); + val += c; + break; + default: + states.push('string'); + val += c; + quote = c; + } + break; + case '': + break; + default: + switch (state()) { + case 'key': + case 'key char': + key += c; + break; + default: + val += c; + } + } + p = c; + } + + for (var i = 0; i < len; ++i) { + parse(str.charAt(i)); + } + + parse(','); + + if ('/' == this.input.charAt(0)) { + this.consume(1); + tok.selfClosing = true; + } + + return tok; + } + }, + + /** + * Indent | Outdent | Newline. + */ + + indent: function() { + var captures, re; + + // established regexp + if (this.indentRe) { + captures = this.indentRe.exec(this.input); + // determine regexp + } else { + // tabs + re = /^\n(\t*) */; + captures = re.exec(this.input); + + // spaces + if (captures && !captures[1].length) { + re = /^\n( *)/; + captures = re.exec(this.input); + } + + // established + if (captures && captures[1].length) this.indentRe = re; + } + + if (captures) { + var tok + , indents = captures[1].length; + + ++this.lineno; + this.consume(indents + 1); + + if (' ' == this.input[0] || '\t' == this.input[0]) { + throw new Error('Invalid indentation, you can use tabs or spaces but not both'); + } + + // blank line + if ('\n' == this.input[0]) return this.tok('newline'); + + // outdent + if (this.indentStack.length && indents < this.indentStack[0]) { + while (this.indentStack.length && this.indentStack[0] > indents) { + this.stash.push(this.tok('outdent')); + this.indentStack.shift(); + } + tok = this.stash.pop(); + // indent + } else if (indents && indents != this.indentStack[0]) { + this.indentStack.unshift(indents); + tok = this.tok('indent', indents); + // newline + } else { + tok = this.tok('newline'); + } + + return tok; + } + }, + + /** + * Pipe-less text consumed only when + * pipeless is true; + */ + + pipelessText: function() { + if (this.pipeless) { + if ('\n' == this.input[0]) return; + var i = this.input.indexOf('\n'); + if (-1 == i) i = this.input.length; + var str = this.input.substr(0, i); + this.consume(str.length); + return this.tok('text', str); + } + }, + + /** + * ':' + */ + + colon: function() { + return this.scan(/^: */, ':'); + }, + + /** + * Return the next token object, or those + * previously stashed by lookahead. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.stashed() + || this.next(); + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + next: function() { + return this.deferred() + || this.blank() + || this.eos() + || this.pipelessText() + || this.yield() + || this.doctype() + || this.interpolation() + || this["case"]() + || this.when() + || this["default"]() + || this["extends"]() + || this.append() + || this.prepend() + || this.block() + || this.include() + || this.mixin() + || this.call() + || this.conditional() + || this.each() + || this["while"]() + || this.assignment() + || this.tag() + || this.filter() + || this.code() + || this.id() + || this.className() + || this.attrs() + || this.indent() + || this.comment() + || this.colon() + || this.text(); + } +}; diff --git a/hm_sunwell/node_modules/jade/lib/nodes/attrs.js b/hm_sunwell/node_modules/jade/lib/nodes/attrs.js new file mode 100644 index 0000000..5de9b59 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/attrs.js @@ -0,0 +1,77 @@ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'), + Block = require('./block'); + +/** + * Initialize a `Attrs` node. + * + * @api public + */ + +var Attrs = module.exports = function Attrs() { + this.attrs = []; +}; + +/** + * Inherit from `Node`. + */ + +Attrs.prototype.__proto__ = Node.prototype; + +/** + * Set attribute `name` to `val`, keep in mind these become + * part of a raw js object literal, so to quote a value you must + * '"quote me"', otherwise or example 'user.name' is literal JavaScript. + * + * @param {String} name + * @param {String} val + * @param {Boolean} escaped + * @return {Tag} for chaining + * @api public + */ + +Attrs.prototype.setAttribute = function(name, val, escaped){ + this.attrs.push({ name: name, val: val, escaped: escaped }); + return this; +}; + +/** + * Remove attribute `name` when present. + * + * @param {String} name + * @api public + */ + +Attrs.prototype.removeAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + delete this.attrs[i]; + } + } +}; + +/** + * Get attribute value by `name`. + * + * @param {String} name + * @return {String} + * @api public + */ + +Attrs.prototype.getAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + return this.attrs[i].val; + } + } +}; diff --git a/hm_sunwell/node_modules/jade/lib/nodes/block-comment.js b/hm_sunwell/node_modules/jade/lib/nodes/block-comment.js new file mode 100644 index 0000000..4f41e4a --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/block-comment.js @@ -0,0 +1,33 @@ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `BlockComment` with the given `block`. + * + * @param {String} val + * @param {Block} block + * @param {Boolean} buffer + * @api public + */ + +var BlockComment = module.exports = function BlockComment(val, block, buffer) { + this.block = block; + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +BlockComment.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/block.js b/hm_sunwell/node_modules/jade/lib/nodes/block.js new file mode 100644 index 0000000..bb00a1d --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/block.js @@ -0,0 +1,121 @@ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Block` with an optional `node`. + * + * @param {Node} node + * @api public + */ + +var Block = module.exports = function Block(node){ + this.nodes = []; + if (node) this.push(node); +}; + +/** + * Inherit from `Node`. + */ + +Block.prototype.__proto__ = Node.prototype; + +/** + * Block flag. + */ + +Block.prototype.isBlock = true; + +/** + * Replace the nodes in `other` with the nodes + * in `this` block. + * + * @param {Block} other + * @api private + */ + +Block.prototype.replace = function(other){ + other.nodes = this.nodes; +}; + +/** + * Pust the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.push = function(node){ + return this.nodes.push(node); +}; + +/** + * Check if this block is empty. + * + * @return {Boolean} + * @api public + */ + +Block.prototype.isEmpty = function(){ + return 0 == this.nodes.length; +}; + +/** + * Unshift the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.unshift = function(node){ + return this.nodes.unshift(node); +}; + +/** + * Return the "last" block, or the first `yield` node. + * + * @return {Block} + * @api private + */ + +Block.prototype.includeBlock = function(){ + var ret = this + , node; + + for (var i = 0, len = this.nodes.length; i < len; ++i) { + node = this.nodes[i]; + if (node.yield) return node; + else if (node.textOnly) continue; + else if (node.includeBlock) ret = node.includeBlock(); + else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock(); + } + + return ret; +}; + +/** + * Return a clone of this block. + * + * @return {Block} + * @api private + */ + +Block.prototype.clone = function(){ + var clone = new Block; + for (var i = 0, len = this.nodes.length; i < len; ++i) { + clone.push(this.nodes[i].clone()); + } + return clone; +}; + diff --git a/hm_sunwell/node_modules/jade/lib/nodes/case.js b/hm_sunwell/node_modules/jade/lib/nodes/case.js new file mode 100644 index 0000000..08ff033 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/case.js @@ -0,0 +1,43 @@ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Case` with `expr`. + * + * @param {String} expr + * @api public + */ + +var Case = exports = module.exports = function Case(expr, block){ + this.expr = expr; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Case.prototype.__proto__ = Node.prototype; + +var When = exports.When = function When(expr, block){ + this.expr = expr; + this.block = block; + this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +When.prototype.__proto__ = Node.prototype; + diff --git a/hm_sunwell/node_modules/jade/lib/nodes/code.js b/hm_sunwell/node_modules/jade/lib/nodes/code.js new file mode 100644 index 0000000..babc675 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/code.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Code` node with the given code `val`. + * Code may also be optionally buffered and escaped. + * + * @param {String} val + * @param {Boolean} buffer + * @param {Boolean} escape + * @api public + */ + +var Code = module.exports = function Code(val, buffer, escape) { + this.val = val; + this.buffer = buffer; + this.escape = escape; + if (val.match(/^ *else/)) this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +Code.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/comment.js b/hm_sunwell/node_modules/jade/lib/nodes/comment.js new file mode 100644 index 0000000..2e1469e --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/comment.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Comment` with the given `val`, optionally `buffer`, + * otherwise the comment may render in the output. + * + * @param {String} val + * @param {Boolean} buffer + * @api public + */ + +var Comment = module.exports = function Comment(val, buffer) { + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +Comment.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/doctype.js b/hm_sunwell/node_modules/jade/lib/nodes/doctype.js new file mode 100644 index 0000000..b8f33e5 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/doctype.js @@ -0,0 +1,29 @@ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Doctype` with the given `val`. + * + * @param {String} val + * @api public + */ + +var Doctype = module.exports = function Doctype(val) { + this.val = val; +}; + +/** + * Inherit from `Node`. + */ + +Doctype.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/each.js b/hm_sunwell/node_modules/jade/lib/nodes/each.js new file mode 100644 index 0000000..f54101f --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/each.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize an `Each` node, representing iteration + * + * @param {String} obj + * @param {String} val + * @param {String} key + * @param {Block} block + * @api public + */ + +var Each = module.exports = function Each(obj, val, key, block) { + this.obj = obj; + this.val = val; + this.key = key; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Each.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/filter.js b/hm_sunwell/node_modules/jade/lib/nodes/filter.js new file mode 100644 index 0000000..851a004 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/filter.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node') + , Block = require('./block'); + +/** + * Initialize a `Filter` node with the given + * filter `name` and `block`. + * + * @param {String} name + * @param {Block|Node} block + * @api public + */ + +var Filter = module.exports = function Filter(name, block, attrs) { + this.name = name; + this.block = block; + this.attrs = attrs; + this.isASTFilter = !block.nodes.every(function(node){ return node.isText }); +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/index.js b/hm_sunwell/node_modules/jade/lib/nodes/index.js new file mode 100644 index 0000000..386ad2f --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/index.js @@ -0,0 +1,20 @@ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +exports.Node = require('./node'); +exports.Tag = require('./tag'); +exports.Code = require('./code'); +exports.Each = require('./each'); +exports.Case = require('./case'); +exports.Text = require('./text'); +exports.Block = require('./block'); +exports.Mixin = require('./mixin'); +exports.Filter = require('./filter'); +exports.Comment = require('./comment'); +exports.Literal = require('./literal'); +exports.BlockComment = require('./block-comment'); +exports.Doctype = require('./doctype'); diff --git a/hm_sunwell/node_modules/jade/lib/nodes/literal.js b/hm_sunwell/node_modules/jade/lib/nodes/literal.js new file mode 100644 index 0000000..fde586b --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/literal.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Literal` node with the given `str. + * + * @param {String} str + * @api public + */ + +var Literal = module.exports = function Literal(str) { + this.str = str + .replace(/\\/g, "\\\\") + .replace(/\n|\r\n/g, "\\n") + .replace(/'/g, "\\'"); +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype.__proto__ = Node.prototype; diff --git a/hm_sunwell/node_modules/jade/lib/nodes/mixin.js b/hm_sunwell/node_modules/jade/lib/nodes/mixin.js new file mode 100644 index 0000000..8407bc7 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/mixin.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'); + +/** + * Initialize a new `Mixin` with `name` and `block`. + * + * @param {String} name + * @param {String} args + * @param {Block} block + * @api public + */ + +var Mixin = module.exports = function Mixin(name, args, block, call){ + this.name = name; + this.args = args; + this.block = block; + this.attrs = []; + this.call = call; +}; + +/** + * Inherit from `Attrs`. + */ + +Mixin.prototype.__proto__ = Attrs.prototype; + diff --git a/hm_sunwell/node_modules/jade/lib/nodes/node.js b/hm_sunwell/node_modules/jade/lib/nodes/node.js new file mode 100644 index 0000000..e98f042 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/node.js @@ -0,0 +1,25 @@ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize a `Node`. + * + * @api public + */ + +var Node = module.exports = function Node(){}; + +/** + * Clone this node (return itself) + * + * @return {Node} + * @api private + */ + +Node.prototype.clone = function(){ + return this; +}; diff --git a/hm_sunwell/node_modules/jade/lib/nodes/tag.js b/hm_sunwell/node_modules/jade/lib/nodes/tag.js new file mode 100644 index 0000000..4b6728a --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/tag.js @@ -0,0 +1,95 @@ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'), + Block = require('./block'), + inlineTags = require('../inline-tags'); + +/** + * Initialize a `Tag` node with the given tag `name` and optional `block`. + * + * @param {String} name + * @param {Block} block + * @api public + */ + +var Tag = module.exports = function Tag(name, block) { + this.name = name; + this.attrs = []; + this.block = block || new Block; +}; + +/** + * Inherit from `Attrs`. + */ + +Tag.prototype.__proto__ = Attrs.prototype; + +/** + * Clone this tag. + * + * @return {Tag} + * @api private + */ + +Tag.prototype.clone = function(){ + var clone = new Tag(this.name, this.block.clone()); + clone.line = this.line; + clone.attrs = this.attrs; + clone.textOnly = this.textOnly; + return clone; +}; + +/** + * Check if this tag is an inline tag. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.isInline = function(){ + return ~inlineTags.indexOf(this.name); +}; + +/** + * Check if this tag's contents can be inlined. Used for pretty printing. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.canInline = function(){ + var nodes = this.block.nodes; + + function isInline(node){ + // Recurse if the node is a block + if (node.isBlock) return node.nodes.every(isInline); + return node.isText || (node.isInline && node.isInline()); + } + + // Empty tag + if (!nodes.length) return true; + + // Text-only or inline-only tag + if (1 == nodes.length) return isInline(nodes[0]); + + // Multi-line inline-only tag + if (this.block.nodes.every(isInline)) { + for (var i = 1, len = nodes.length; i < len; ++i) { + if (nodes[i-1].isText && nodes[i].isText) + return false; + } + return true; + } + + // Mixed tag + return false; +}; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/nodes/text.js b/hm_sunwell/node_modules/jade/lib/nodes/text.js new file mode 100644 index 0000000..3b5dd55 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/nodes/text.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Text` node with optional `line`. + * + * @param {String} line + * @api public + */ + +var Text = module.exports = function Text(line) { + this.val = ''; + if ('string' == typeof line) this.val = line; +}; + +/** + * Inherit from `Node`. + */ + +Text.prototype.__proto__ = Node.prototype; + +/** + * Flag as text. + */ + +Text.prototype.isText = true; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/parser.js b/hm_sunwell/node_modules/jade/lib/parser.js new file mode 100644 index 0000000..92f2af0 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/parser.js @@ -0,0 +1,710 @@ + +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes'); + +/** + * Initialize `Parser` with the given input `str` and `filename`. + * + * @param {String} str + * @param {String} filename + * @param {Object} options + * @api public + */ + +var Parser = exports = module.exports = function Parser(str, filename, options){ + this.input = str; + this.lexer = new Lexer(str, options); + this.filename = filename; + this.blocks = {}; + this.mixins = {}; + this.options = options; + this.contexts = [this]; +}; + +/** + * Tags that may not contain tags. + */ + +var textOnly = exports.textOnly = ['script', 'style']; + +/** + * Parser prototype. + */ + +Parser.prototype = { + + /** + * Push `parser` onto the context stack, + * or pop and return a `Parser`. + */ + + context: function(parser){ + if (parser) { + this.contexts.push(parser); + } else { + return this.contexts.pop(); + } + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.lexer.advance(); + }, + + /** + * Skip `n` tokens. + * + * @param {Number} n + * @api private + */ + + skip: function(n){ + while (n--) this.advance(); + }, + + /** + * Single token lookahead. + * + * @return {Object} + * @api private + */ + + peek: function() { + return this.lookahead(1); + }, + + /** + * Return lexer lineno. + * + * @return {Number} + * @api private + */ + + line: function() { + return this.lexer.lineno; + }, + + /** + * `n` token lookahead. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + return this.lexer.lookahead(n); + }, + + /** + * Parse input returning a string of js for evaluation. + * + * @return {String} + * @api public + */ + + parse: function(){ + var block = new nodes.Block, parser; + block.line = this.line(); + + while ('eos' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + + if (parser = this.extending) { + this.context(parser); + var ast = parser.parse(); + this.context(); + // hoist mixins + for (var name in this.mixins) + ast.unshift(this.mixins[name]); + return ast; + } + + return block; + }, + + /** + * Expect the given type, or throw an exception. + * + * @param {String} type + * @api private + */ + + expect: function(type){ + if (this.peek().type === type) { + return this.advance(); + } else { + throw new Error('expected "' + type + '", but got "' + this.peek().type + '"'); + } + }, + + /** + * Accept the given `type`. + * + * @param {String} type + * @api private + */ + + accept: function(type){ + if (this.peek().type === type) { + return this.advance(); + } + }, + + /** + * tag + * | doctype + * | mixin + * | include + * | filter + * | comment + * | text + * | each + * | code + * | yield + * | id + * | class + * | interpolation + */ + + parseExpr: function(){ + switch (this.peek().type) { + case 'tag': + return this.parseTag(); + case 'mixin': + return this.parseMixin(); + case 'block': + return this.parseBlock(); + case 'case': + return this.parseCase(); + case 'when': + return this.parseWhen(); + case 'default': + return this.parseDefault(); + case 'extends': + return this.parseExtends(); + case 'include': + return this.parseInclude(); + case 'doctype': + return this.parseDoctype(); + case 'filter': + return this.parseFilter(); + case 'comment': + return this.parseComment(); + case 'text': + return this.parseText(); + case 'each': + return this.parseEach(); + case 'code': + return this.parseCode(); + case 'call': + return this.parseCall(); + case 'interpolation': + return this.parseInterpolation(); + case 'yield': + this.advance(); + var block = new nodes.Block; + block.yield = true; + return block; + case 'id': + case 'class': + var tok = this.advance(); + this.lexer.defer(this.lexer.tok('tag', 'div')); + this.lexer.defer(tok); + return this.parseExpr(); + default: + throw new Error('unexpected token "' + this.peek().type + '"'); + } + }, + + /** + * Text + */ + + parseText: function(){ + var tok = this.expect('text') + , node = new nodes.Text(tok.val); + node.line = this.line(); + return node; + }, + + /** + * ':' expr + * | block + */ + + parseBlockExpansion: function(){ + if (':' == this.peek().type) { + this.advance(); + return new nodes.Block(this.parseExpr()); + } else { + return this.block(); + } + }, + + /** + * case + */ + + parseCase: function(){ + var val = this.expect('case').val + , node = new nodes.Case(val); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * when + */ + + parseWhen: function(){ + var val = this.expect('when').val + return new nodes.Case.When(val, this.parseBlockExpansion()); + }, + + /** + * default + */ + + parseDefault: function(){ + this.expect('default'); + return new nodes.Case.When('default', this.parseBlockExpansion()); + }, + + /** + * code + */ + + parseCode: function(){ + var tok = this.expect('code') + , node = new nodes.Code(tok.val, tok.buffer, tok.escape) + , block + , i = 1; + node.line = this.line(); + while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; + block = 'indent' == this.lookahead(i).type; + if (block) { + this.skip(i-1); + node.block = this.block(); + } + return node; + }, + + /** + * comment + */ + + parseComment: function(){ + var tok = this.expect('comment') + , node; + + if ('indent' == this.peek().type) { + node = new nodes.BlockComment(tok.val, this.block(), tok.buffer); + } else { + node = new nodes.Comment(tok.val, tok.buffer); + } + + node.line = this.line(); + return node; + }, + + /** + * doctype + */ + + parseDoctype: function(){ + var tok = this.expect('doctype') + , node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var block + , tok = this.expect('filter') + , attrs = this.accept('attrs'); + + this.lexer.pipeless = true; + block = this.parseTextBlock(); + this.lexer.pipeless = false; + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * tag ':' attrs? block + */ + + parseASTFilter: function(){ + var block + , tok = this.expect('tag') + , attrs = this.accept('attrs'); + + this.expect(':'); + block = this.block(); + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * each block + */ + + parseEach: function(){ + var tok = this.expect('each') + , node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + if (!this.filename) + throw new Error('the "filename" option is required to extend templates'); + + var path = this.expect('extends').val.trim() + , dir = dirname(this.filename); + + var path = join(dir, path + '.jade') + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block') + , mode = block.mode + , name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name]; + + if (prev) { + switch (prev.mode) { + case 'append': + block.nodes = block.nodes.concat(prev.nodes); + prev = block; + break; + case 'prepend': + block.nodes = prev.nodes.concat(block.nodes); + prev = block; + break; + } + } + + block.mode = mode; + return this.blocks[name] = prev || block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + var path = this.expect('include').val.trim() + , dir = dirname(this.filename); + + if (!this.filename) + throw new Error('the "filename" option is required to use includes'); + + // no extension + if (!~basename(path).indexOf('.')) { + path += '.jade'; + } + + // non-jade + if ('.jade' != path.substr(-5)) { + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8'); + return new nodes.Literal(str); + } + + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + parser.blocks = this.blocks; + parser.mixins = this.mixins; + + this.context(parser); + var ast = parser.parse(); + this.context(); + ast.filename = path; + + if ('indent' == this.peek().type) { + ast.includeBlock().push(this.block()); + } + + return ast; + }, + + /** + * call ident block + */ + + parseCall: function(){ + var tok = this.expect('call') + , name = tok.val + , args = tok.args + , mixin = new nodes.Mixin(name, args, new nodes.Block, true); + + this.tag(mixin); + if (mixin.block.isEmpty()) mixin.block = null; + return mixin; + }, + + /** + * mixin block + */ + + parseMixin: function(){ + var tok = this.expect('mixin') + , name = tok.val + , args = tok.args + , mixin; + + // definition + if ('indent' == this.peek().type) { + mixin = new nodes.Mixin(name, args, this.block(), false); + this.mixins[name] = mixin; + return mixin; + // call + } else { + return new nodes.Mixin(name, args, null, true); + } + }, + + /** + * indent (text | newline)* outdent + */ + + parseTextBlock: function(){ + var block = new nodes.Block; + block.line = this.line(); + var spaces = this.expect('indent').val; + if (null == this._spaces) this._spaces = spaces; + var indent = Array(spaces - this._spaces + 1).join(' '); + while ('outdent' != this.peek().type) { + switch (this.peek().type) { + case 'newline': + this.advance(); + break; + case 'indent': + this.parseTextBlock().nodes.forEach(function(node){ + block.push(node); + }); + break; + default: + var text = new nodes.Text(indent + this.advance().val); + text.line = this.line(); + block.push(text); + } + } + + if (spaces == this._spaces) this._spaces = null; + this.expect('outdent'); + return block; + }, + + /** + * indent expr* outdent + */ + + block: function(){ + var block = new nodes.Block; + block.line = this.line(); + this.expect('indent'); + while ('outdent' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + this.expect('outdent'); + return block; + }, + + /** + * interpolation (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseInterpolation: function(){ + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + tag.buffer = true; + return this.tag(tag); + }, + + /** + * tag (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseTag: function(){ + // ast-filter look-ahead + var i = 2; + if ('attrs' == this.lookahead(i).type) ++i; + if (':' == this.lookahead(i).type) { + if ('indent' == this.lookahead(++i).type) { + return this.parseASTFilter(); + } + } + + var tok = this.advance() + , tag = new nodes.Tag(tok.val); + + tag.selfClosing = tok.selfClosing; + + return this.tag(tag); + }, + + /** + * Parse tag. + */ + + tag: function(tag){ + var dot; + + tag.line = this.line(); + + // (attrs | class | id)* + out: + while (true) { + switch (this.peek().type) { + case 'id': + case 'class': + var tok = this.advance(); + tag.setAttribute(tok.type, "'" + tok.val + "'"); + continue; + case 'attrs': + var tok = this.advance() + , obj = tok.attrs + , escaped = tok.escaped + , names = Object.keys(obj); + + if (tok.selfClosing) tag.selfClosing = true; + + for (var i = 0, len = names.length; i < len; ++i) { + var name = names[i] + , val = obj[name]; + tag.setAttribute(name, val, escaped[name]); + } + continue; + default: + break out; + } + } + + // check immediate '.' + if ('.' == this.peek().val) { + dot = tag.textOnly = true; + this.advance(); + } + + // (text | code | ':')? + switch (this.peek().type) { + case 'text': + tag.block.push(this.parseText()); + break; + case 'code': + tag.code = this.parseCode(); + break; + case ':': + this.advance(); + tag.block = new nodes.Block; + tag.block.push(this.parseExpr()); + break; + } + + // newline* + while ('newline' == this.peek().type) this.advance(); + + tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name); + + // script special-case + if ('script' == tag.name) { + var type = tag.getAttribute('type'); + if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { + tag.textOnly = false; + } + } + + // block? + if ('indent' == this.peek().type) { + if (tag.textOnly) { + this.lexer.pipeless = true; + tag.block = this.parseTextBlock(); + this.lexer.pipeless = false; + } else { + var block = this.block(); + if (tag.block) { + for (var i = 0, len = block.nodes.length; i < len; ++i) { + tag.block.push(block.nodes[i]); + } + } else { + tag.block = block; + } + } + } + + return tag; + } +}; diff --git a/hm_sunwell/node_modules/jade/lib/runtime.js b/hm_sunwell/node_modules/jade/lib/runtime.js new file mode 100644 index 0000000..fb711f5 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/runtime.js @@ -0,0 +1,174 @@ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + ac = ac.filter(nulls); + bc = bc.filter(nulls); + a['class'] = ac.concat(bc).join(' '); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function nulls(val) { + return val != null; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!(\w+|\#\d+);)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno){ + if (!filename) throw err; + + var context = 3 + , str = require('fs').readFileSync(filename, 'utf8') + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; diff --git a/hm_sunwell/node_modules/jade/lib/self-closing.js b/hm_sunwell/node_modules/jade/lib/self-closing.js new file mode 100644 index 0000000..0548771 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/self-closing.js @@ -0,0 +1,19 @@ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/lib/utils.js b/hm_sunwell/node_modules/jade/lib/utils.js new file mode 100644 index 0000000..ff46d02 --- /dev/null +++ b/hm_sunwell/node_modules/jade/lib/utils.js @@ -0,0 +1,49 @@ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Convert interpolation in the given string to JavaScript. + * + * @param {String} str + * @return {String} + * @api private + */ + +var interpolate = exports.interpolate = function(str){ + return str.replace(/(\\)?([#!]){(.*?)}/g, function(str, escape, flag, code){ + return escape + ? str + : "' + " + + ('!' == flag ? '' : 'escape') + + "((interp = " + code.replace(/\\'/g, "'") + + ") == null ? '' : interp) + '"; + }); +}; + +/** + * Escape single quotes in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +var escape = exports.escape = function(str) { + return str.replace(/'/g, "\\'"); +}; + +/** + * Interpolate, and escape the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.text = function(str){ + return interpolate(escape(str)); +}; \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/.npmignore b/hm_sunwell/node_modules/jade/node_modules/commander/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/.travis.yml b/hm_sunwell/node_modules/jade/node_modules/commander/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/History.md b/hm_sunwell/node_modules/jade/node_modules/commander/History.md new file mode 100644 index 0000000..4961d2e --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/History.md @@ -0,0 +1,107 @@ + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/Makefile b/hm_sunwell/node_modules/jade/node_modules/commander/Makefile new file mode 100644 index 0000000..0074625 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/Makefile @@ -0,0 +1,7 @@ + +TESTS = $(shell find test/test.*.js) + +test: + @./test/run $(TESTS) + +.PHONY: test \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/Readme.md b/hm_sunwell/node_modules/jade/node_modules/commander/Readme.md new file mode 100644 index 0000000..b8328c3 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/Readme.md @@ -0,0 +1,262 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/index.js b/hm_sunwell/node_modules/jade/node_modules/commander/index.js new file mode 100644 index 0000000..06ec1e4 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/commander'); \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/lib/commander.js b/hm_sunwell/node_modules/jade/node_modules/commander/lib/commander.js new file mode 100644 index 0000000..5ba87eb --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/lib/commander.js @@ -0,0 +1,1026 @@ + +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , tty = require('tty') + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this.args = []; + this.name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + return cmd; +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self.args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self.args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this.name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + self.args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self.args.length) { + args[self.args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // store raw args + this.rawArgs = argv; + + // guess name + if (!this.name) this.name = basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + this.args = parsed.args; + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0]) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || '-' == arg[0]) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this.args.length ? ' ' + args : ''); + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return cmd.name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args + + (cmd.description() + ? '\n' + cmd.description() + : ''); + }).join('\n\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this.name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + process.stdin.resume(); + tty.setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.removeAllListeners('keypress'); + tty.setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + process.stdout.write(cmd.helpInformation()); + cmd.emit('--help'); + process.exit(0); + } + } +} diff --git a/hm_sunwell/node_modules/jade/node_modules/commander/package.json b/hm_sunwell/node_modules/jade/node_modules/commander/package.json new file mode 100644 index 0000000..3e56b0b --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/commander/package.json @@ -0,0 +1,84 @@ +{ + "_args": [ + [ + "commander@0.6.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/jade" + ] + ], + "_defaultsLoaded": true, + "_engineSupported": true, + "_from": "commander@0.6.1", + "_id": "commander@0.6.1", + "_inCache": true, + "_installable": true, + "_location": "/jade/commander", + "_nodeVersion": "v0.6.12", + "_npmUser": { + "email": "tj@vision-media.ca", + "name": "tjholowaychuk" + }, + "_npmVersion": "1.1.0-3", + "_phantomChildren": {}, + "_requested": { + "name": "commander", + "raw": "commander@0.6.1", + "rawSpec": "0.6.1", + "scope": null, + "spec": "0.6.1", + "type": "version" + }, + "_requiredBy": [ + "/jade" + ], + "_resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "_shasum": "fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06", + "_shrinkwrap": null, + "_spec": "commander@0.6.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/jade", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk" + }, + "bugs": { + "url": "https://github.com/visionmedia/commander.js/issues" + }, + "dependencies": {}, + "description": "the complete solution for node.js command-line programs", + "devDependencies": { + "should": ">= 0.0.1" + }, + "directories": {}, + "dist": { + "shasum": "fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06", + "tarball": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" + }, + "engines": { + "node": ">= 0.4.x" + }, + "homepage": "https://github.com/visionmedia/commander.js#readme", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "main": "index", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "name": "commander", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/commander.js.git" + }, + "scripts": { + "test": "make test" + }, + "version": "0.6.1" +} diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/.gitignore.orig b/hm_sunwell/node_modules/jade/node_modules/mkdirp/.gitignore.orig new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/.gitignore.orig @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/.gitignore.rej b/hm_sunwell/node_modules/jade/node_modules/mkdirp/.gitignore.rej new file mode 100644 index 0000000..69244ff --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/.gitignore.rej @@ -0,0 +1,5 @@ +--- /dev/null ++++ .gitignore +@@ -0,0 +1,2 @@ ++node_modules/ ++npm-debug.log \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/.npmignore b/hm_sunwell/node_modules/jade/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/LICENSE b/hm_sunwell/node_modules/jade/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/README.markdown b/hm_sunwell/node_modules/jade/node_modules/mkdirp/README.markdown new file mode 100644 index 0000000..b4dd75f --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/README.markdown @@ -0,0 +1,54 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js.orig b/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js.orig new file mode 100644 index 0000000..7741462 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js.orig @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js.rej b/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js.rej new file mode 100644 index 0000000..81e7f43 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/examples/pow.js.rej @@ -0,0 +1,19 @@ +--- examples/pow.js ++++ examples/pow.js +@@ -1,6 +1,15 @@ +-var mkdirp = require('mkdirp').mkdirp; ++var mkdirp = require('../').mkdirp, ++ mkdirpSync = require('../').mkdirpSync; + + mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') + }); ++ ++try { ++ mkdirpSync('/tmp/bar/foo/baz', 0755); ++ console.log('double pow!'); ++} ++catch (ex) { ++ console.log(ex); ++} \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/index.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/index.js new file mode 100644 index 0000000..25f43ad --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/index.js @@ -0,0 +1,79 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) return cb(); + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er) { + if (er) cb(er); + else mkdirP(p, mode, cb); + }); + break; + + case 'EEXIST': + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original EEXIST be the failure reason. + if (er2 || !stat.isDirectory()) cb(er) + else cb(); + }); + break; + + default: + cb(er); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode) + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + var err1 = sync(path.dirname(p), mode) + if (err1) throw err1; + else return sync(p, mode); + break; + + case 'EEXIST' : + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0 + } + if (!stat.isDirectory()) throw err0; + else return null; + break; + default : + throw err0 + break; + } + } + + return null; +}; diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/package.json b/hm_sunwell/node_modules/jade/node_modules/mkdirp/package.json new file mode 100644 index 0000000..da43d16 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/package.json @@ -0,0 +1,83 @@ +{ + "_args": [ + [ + "mkdirp@0.3.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/jade" + ] + ], + "_defaultsLoaded": true, + "_engineSupported": true, + "_from": "mkdirp@0.3.0", + "_id": "mkdirp@0.3.0", + "_inCache": true, + "_installable": true, + "_location": "/jade/mkdirp", + "_nodeVersion": "v0.4.12", + "_npmUser": { + "email": "mail@substack.net", + "name": "substack" + }, + "_npmVersion": "1.0.106", + "_phantomChildren": {}, + "_requested": { + "name": "mkdirp", + "raw": "mkdirp@0.3.0", + "rawSpec": "0.3.0", + "scope": null, + "spec": "0.3.0", + "type": "version" + }, + "_requiredBy": [ + "/jade" + ], + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "_shasum": "1bbf5ab1ba827af23575143490426455f481fe1e", + "_shrinkwrap": null, + "_spec": "mkdirp@0.3.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/jade", + "author": { + "email": "mail@substack.net", + "name": "James Halliday", + "url": "http://substack.net" + }, + "bugs": { + "url": "https://github.com/substack/node-mkdirp/issues" + }, + "dependencies": {}, + "description": "Recursively mkdir, like `mkdir -p`", + "devDependencies": { + "tap": "0.0.x" + }, + "directories": {}, + "dist": { + "shasum": "1bbf5ab1ba827af23575143490426455f481fe1e", + "tarball": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + }, + "engines": { + "node": "*" + }, + "homepage": "https://github.com/substack/node-mkdirp#readme", + "keywords": [ + "directory", + "mkdir" + ], + "license": "MIT/X11", + "main": "./index", + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "name": "mkdirp", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "0.3.0" +} diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/chmod.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/clobber.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/mkdirp.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/perm.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/perm_sync.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/race.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/rel.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/sync.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..e0e389d --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/sync.js @@ -0,0 +1,27 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + var err = mkdirp.sync(file, 0755); + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/umask.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/umask_sync.js b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..83cba56 --- /dev/null +++ b/hm_sunwell/node_modules/jade/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,27 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + var err = mkdirp.sync(file); + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) +}); diff --git a/hm_sunwell/node_modules/jade/package.json b/hm_sunwell/node_modules/jade/package.json new file mode 100644 index 0000000..31bbe6a --- /dev/null +++ b/hm_sunwell/node_modules/jade/package.json @@ -0,0 +1,87 @@ +{ + "_args": [ + [ + "jade@0.26.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha" + ] + ], + "_from": "jade@0.26.3", + "_id": "jade@0.26.3", + "_inCache": true, + "_installable": true, + "_location": "/jade", + "_phantomChildren": {}, + "_requested": { + "name": "jade", + "raw": "jade@0.26.3", + "rawSpec": "0.26.3", + "scope": null, + "spec": "0.26.3", + "type": "version" + }, + "_requiredBy": [ + "/mocha" + ], + "_resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "_shasum": "8f10d7977d8d79f2f6ff862a81b0513ccb25686c", + "_shrinkwrap": null, + "_spec": "jade@0.26.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk" + }, + "bin": { + "jade": "./bin/jade" + }, + "bugs": { + "url": "https://github.com/visionmedia/jade/issues" + }, + "component": { + "scripts": { + "jade": "runtime.js" + } + }, + "dependencies": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "deprecated": "Jade has been renamed to pug, please install the latest version of pug instead of jade", + "description": "Jade template engine", + "devDependencies": { + "less": "*", + "markdown": "*", + "mocha": "*", + "should": "*", + "stylus": "*", + "uglify-js": "*", + "uubench": "*" + }, + "directories": {}, + "dist": { + "shasum": "8f10d7977d8d79f2f6ff862a81b0513ccb25686c", + "tarball": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz" + }, + "homepage": "https://github.com/visionmedia/jade#readme", + "main": "./index.js", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "man": [ + "./jade.1" + ], + "name": "jade", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/jade.git" + }, + "scripts": { + "prepublish": "npm prune" + }, + "version": "0.26.3" +} diff --git a/hm_sunwell/node_modules/jade/runtime.js b/hm_sunwell/node_modules/jade/runtime.js new file mode 100644 index 0000000..0f54907 --- /dev/null +++ b/hm_sunwell/node_modules/jade/runtime.js @@ -0,0 +1,179 @@ + +jade = (function(exports){ +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + ac = ac.filter(nulls); + bc = bc.filter(nulls); + a['class'] = ac.concat(bc).join(' '); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function nulls(val) { + return val != null; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!(\w+|\#\d+);)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno){ + if (!filename) throw err; + + var context = 3 + , str = require('fs').readFileSync(filename, 'utf8') + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; + + return exports; + +})({}); diff --git a/hm_sunwell/node_modules/jade/runtime.min.js b/hm_sunwell/node_modules/jade/runtime.min.js new file mode 100644 index 0000000..1714efb --- /dev/null +++ b/hm_sunwell/node_modules/jade/runtime.min.js @@ -0,0 +1 @@ +jade=function(exports){Array.isArray||(Array.isArray=function(arr){return"[object Array]"==Object.prototype.toString.call(arr)}),Object.keys||(Object.keys=function(obj){var arr=[];for(var key in obj)obj.hasOwnProperty(key)&&arr.push(key);return arr}),exports.merge=function merge(a,b){var ac=a["class"],bc=b["class"];if(ac||bc)ac=ac||[],bc=bc||[],Array.isArray(ac)||(ac=[ac]),Array.isArray(bc)||(bc=[bc]),ac=ac.filter(nulls),bc=bc.filter(nulls),a["class"]=ac.concat(bc).join(" ");for(var key in b)key!="class"&&(a[key]=b[key]);return a};function nulls(val){return val!=null}return exports.attrs=function attrs(obj,escaped){var buf=[],terse=obj.terse;delete obj.terse;var keys=Object.keys(obj),len=keys.length;if(len){buf.push("");for(var i=0;i/g,">").replace(/"/g,""")},exports.rethrow=function rethrow(err,filename,lineno){if(!filename)throw err;var context=3,str=require("fs").readFileSync(filename,"utf8"),lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message,err},exports}({}); \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/test.jade b/hm_sunwell/node_modules/jade/test.jade new file mode 100644 index 0000000..b3a8988 --- /dev/null +++ b/hm_sunwell/node_modules/jade/test.jade @@ -0,0 +1,7 @@ +p. + This is a large + body of text for + this tag. + + Nothing too + exciting. \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/testing/head.jade b/hm_sunwell/node_modules/jade/testing/head.jade new file mode 100644 index 0000000..8515406 --- /dev/null +++ b/hm_sunwell/node_modules/jade/testing/head.jade @@ -0,0 +1,5 @@ +head + script(src='/jquery.js') + yield + if false + script(src='/jquery.ui.js') diff --git a/hm_sunwell/node_modules/jade/testing/index.jade b/hm_sunwell/node_modules/jade/testing/index.jade new file mode 100644 index 0000000..1032c5f --- /dev/null +++ b/hm_sunwell/node_modules/jade/testing/index.jade @@ -0,0 +1,22 @@ + +tag = 'p' +foo = 'bar' + +#{tag} value +#{tag}(foo='bar') value +#{foo ? 'a' : 'li'}(something) here + +mixin item(icon) + li + if attributes.href + a(attributes) + img.icon(src=icon) + block + else + span(attributes) + img.icon(src=icon) + block + +ul + +item('contact') Contact + +item(href='/contact') Contact diff --git a/hm_sunwell/node_modules/jade/testing/index.js b/hm_sunwell/node_modules/jade/testing/index.js new file mode 100644 index 0000000..226e8c0 --- /dev/null +++ b/hm_sunwell/node_modules/jade/testing/index.js @@ -0,0 +1,11 @@ + +/** + * Module dependencies. + */ + +var jade = require('../'); + +jade.renderFile('testing/index.jade', { pretty: true, debug: true, compileDebug: false }, function(err, str){ + if (err) throw err; + console.log(str); +}); \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/testing/layout.jade b/hm_sunwell/node_modules/jade/testing/layout.jade new file mode 100644 index 0000000..6923cf1 --- /dev/null +++ b/hm_sunwell/node_modules/jade/testing/layout.jade @@ -0,0 +1,6 @@ +html + include head + script(src='/caustic.js') + script(src='/app.js') + body + block content \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/testing/user.jade b/hm_sunwell/node_modules/jade/testing/user.jade new file mode 100644 index 0000000..3c636b7 --- /dev/null +++ b/hm_sunwell/node_modules/jade/testing/user.jade @@ -0,0 +1,7 @@ +h1 Tobi +p Is a ferret + +ul + li: a foo + li: a bar + li: a baz \ No newline at end of file diff --git a/hm_sunwell/node_modules/jade/testing/user.js b/hm_sunwell/node_modules/jade/testing/user.js new file mode 100644 index 0000000..2ecc45e --- /dev/null +++ b/hm_sunwell/node_modules/jade/testing/user.js @@ -0,0 +1,27 @@ +function anonymous(locals, attrs, escape, rethrow) { +var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow; +var __jade = [{ lineno: 1, filename: "testing/user.jade" }]; +try { +var buf = []; +with (locals || {}) { +var interp; +__jade.unshift({ lineno: 1, filename: __jade[0].filename }); +__jade.unshift({ lineno: 1, filename: __jade[0].filename }); +buf.push('

Tobi'); +__jade.unshift({ lineno: undefined, filename: __jade[0].filename }); +__jade.shift(); +buf.push('

'); +__jade.shift(); +__jade.unshift({ lineno: 2, filename: __jade[0].filename }); +buf.push('

Is a ferret'); +__jade.unshift({ lineno: undefined, filename: __jade[0].filename }); +__jade.shift(); +buf.push('

'); +__jade.shift(); +__jade.shift(); +} +return buf.join(""); +} catch (err) { + rethrow(err, __jade[0].filename, __jade[0].lineno); +} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/jodid25519/.npmignore b/hm_sunwell/node_modules/jodid25519/.npmignore new file mode 100644 index 0000000..877830c --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/.npmignore @@ -0,0 +1,11 @@ +# Editor, IDE and dev environment stuff +*~ +.project +.settings + +# Build files and directories +/coverage +/doc/api +/build/ +/test/ +/jodid25519-*.tgz diff --git a/hm_sunwell/node_modules/jodid25519/.travis.yml b/hm_sunwell/node_modules/jodid25519/.travis.yml new file mode 100644 index 0000000..92a990f --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.10" + - "0.11" +branches: + only: + - master diff --git a/hm_sunwell/node_modules/jodid25519/AUTHORS.md b/hm_sunwell/node_modules/jodid25519/AUTHORS.md new file mode 100644 index 0000000..0c17097 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/AUTHORS.md @@ -0,0 +1,3 @@ +* Michele Bini (original Curve25519 core code: curve25519.js) +* Ron Garret (original Ed25519 code: fast-djbec.js) +* Guy Kloss (package refactoring, unit testing) diff --git a/hm_sunwell/node_modules/jodid25519/LICENSE b/hm_sunwell/node_modules/jodid25519/LICENSE new file mode 100644 index 0000000..32ee158 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2012 Ron Garret +Copyright (c) 2007, 2013, 2014 Michele Bini +Copyright (c) 2014 Mega Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/hm_sunwell/node_modules/jodid25519/README.md b/hm_sunwell/node_modules/jodid25519/README.md new file mode 100644 index 0000000..5335b2d --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/README.md @@ -0,0 +1,51 @@ +Jodid25519 [![Build Status](https://secure.travis-ci.org/meganz/jodid25519.png)](https://travis-ci.org/meganz/jodid25519) +=================================================================================================================================== + +Javascript implementation of the Curve25519 and Ed25519 elliptic cryptography functions by Daniel J. Bernstein. + +For the API, please consult the generated documentation under doc/ (you can run `make` to generate it). + +To run the tests do the following on the console from the project's root directory: + + $ npm install + $ make test + + +Contributors +------------ + +If you are one of the contributors and want to add yourself or change the information here, please do submit a pull request. Contributors appear in no particular order. + +### For the Curve25519 submodule + +* [Graydon Hoare](https://github.com/graydon): suggested clamping the private key by default for increased safety and uniformity with other implementations. +* [liliakai](https://github.com/liliakai): spotted an unused argument in some of the functions +* [RyanC](https://github.com/ryancdotorg): removed dependency of a function to the Javascript Math library +* [Guy Kloss](https://github.com/pohutukawa): performance improvements through bit-shift operations, performance and conformance testing, documentation, compatibility with the npm package ecosystem, and more +* [Michele Bini](https://github.com/rev22): originally wrote the Javascript implementation + + +Copyright and MIT licensing +--------------------------- + +* Copyright (c) 2012 Ron Garret +* Copyright (c) 2007, 2013, 2014 Michele Bini +* Copyright (c) 2014 Mega Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/jodid25519/almond.0 b/hm_sunwell/node_modules/jodid25519/almond.0 new file mode 100644 index 0000000..55ffcc4 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/almond.0 @@ -0,0 +1,42 @@ +/* + * Curve 25519-based cryptography collection. + * + * EC Diffie-Hellman (ECDH) based on Curve25519 and digital signatures (EdDSA) + * based on Ed25519. + * + * Copyright (c) 2012 Ron Garret + * Copyright (c) 2007, 2013, 2014 Michele Bini + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * You should have received a copy of the license along with this program. + */ +// See https://github.com/jrburke/almond#exporting-a-public-api +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // Allow using this built library as an AMD module + // in another project. That other project will only + // see this AMD call, not the internal modules in + // the closure below. + define([], factory); + } else if (typeof module === 'object' && module.exports) { + // Allow using this built library as a CommonJS module + module.exports = factory(); + } else { + // Browser globals case. Just assign the + // result to a property on the global. + root.jodid25519 = factory(); + } +}(this, function () { + if (typeof module === 'object' && module.exports) { + // If we're running under CommonJS, our dependencies get confused and + // each clobber module.exports which leads to bad behaviour because + // almond does asynchronous loading. So just pretend we're in the + // browser globals case, and make them write to those values instead. + // TODO: ditch requirejs/almond and use browserify or something. + var __oldModule = module; + var __oldExports = exports; + var window = global; + module = undefined; + exports = undefined; + } diff --git a/hm_sunwell/node_modules/jodid25519/almond.1 b/hm_sunwell/node_modules/jodid25519/almond.1 new file mode 100644 index 0000000..cdb5e67 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/almond.1 @@ -0,0 +1,13 @@ + if (typeof module === 'object' && module.exports) { + // Restore CommonJS exports once our dependencies have all finished + // loading. + module = __oldModule; + exports = __oldExports; + } + // The modules for your project will be inlined above + // this snippet. Ask almond to synchronously require the + // module value for 'main' here and return it as the + // value to use for the public API for the built file. + return require('jodid25519'); +})); +// See https://github.com/jrburke/almond#exporting-a-public-api diff --git a/hm_sunwell/node_modules/jodid25519/index.js b/hm_sunwell/node_modules/jodid25519/index.js new file mode 100644 index 0000000..8709839 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/index.js @@ -0,0 +1,35 @@ +"use strict"; + +/* + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * Authors: Guy K. Kloss + * + * You should have received a copy of the license along with this program. + */ + +var dh = require('./lib/dh'); +var eddsa = require('./lib/eddsa'); +var curve255 = require('./lib/curve255'); +var utils = require('./lib/utils'); + + /** + * @exports jodid25519 + * Curve 25519-based cryptography collection. + * + * @description + * EC Diffie-Hellman (ECDH) based on Curve25519 and digital signatures + * (EdDSA) based on Ed25519. + */ + var ns = {}; + + /** Module version indicator as string (format: [major.minor.patch]). */ + ns.VERSION = '0.7.1'; + + ns.dh = dh; + ns.eddsa = eddsa; + ns.curve255 = curve255; + ns.utils = utils; + +module.exports = ns; diff --git a/hm_sunwell/node_modules/jodid25519/jsdoc.json b/hm_sunwell/node_modules/jodid25519/jsdoc.json new file mode 100644 index 0000000..21eba9b --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/jsdoc.json @@ -0,0 +1,19 @@ +{ + "templates": { + "applicationName": "jodid25519 Library", + "disqus": "", + "googleAnalytics": "", + "openGraph": { + "title": "jodid25519 Library", + "type": "website", + "image": "", + "site_name": "", + "url": "" + }, + "meta": { + "title": "jodid25519 Library", + "description": "", + "keyword": "" + } + } +} diff --git a/hm_sunwell/node_modules/jodid25519/lib/core.js b/hm_sunwell/node_modules/jodid25519/lib/core.js new file mode 100644 index 0000000..f78fd74 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/lib/core.js @@ -0,0 +1,481 @@ +"use strict"; +/** + * @fileOverview + * Core operations on curve 25519 required for the higher level modules. + */ + +/* + * Copyright (c) 2007, 2013, 2014 Michele Bini + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * Authors: Guy K. Kloss, Michele Bini + * + * You should have received a copy of the license along with this program. + */ + +var crypto = require('crypto'); + + /** + * @exports jodid25519/core + * Core operations on curve 25519 required for the higher level modules. + * + * @description + * Core operations on curve 25519 required for the higher level modules. + * + *

+ * This core code is extracted from Michele Bini's curve255.js implementation, + * which is used as a base for Curve25519 ECDH and Ed25519 EdDSA operations. + *

+ */ + var ns = {}; + + function _setbit(n, c, v) { + var i = c >> 4; + var a = n[i]; + a = a + (1 << (c & 0xf)) * v; + n[i] = a; + } + + function _getbit(n, c) { + return (n[c >> 4] >> (c & 0xf)) & 1; + } + + function _ZERO() { + return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + function _ONE() { + return [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + // Basepoint. + function _BASE() { + return [9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + // return -1, 0, +1 when a is less than, equal, or greater than b + function _bigintcmp(a, b) { + // The following code is a bit tricky to avoid code branching + var c, abs_r, mask; + var r = 0; + for (c = 15; c >= 0; c--) { + var x = a[c]; + var y = b[c]; + r = r + (x - y) * (1 - r * r); + // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs + // correct for [-294967295, 294967295] + mask = r >> 31; + abs_r = (r + mask) ^ mask; + // http://stackoverflow.com/questions/596467/how-do-i-convert-a-number-to-an-integer-in-javascript + // this rounds towards zero + r = ~~((r << 1) / (abs_r + 1)); + } + return r; + } + + function _bigintadd(a, b) { + var r = []; + var v; + r[0] = (v = a[0] + b[0]) & 0xffff; + r[1] = (v = (v >>> 16) + a[1] + b[1]) & 0xffff; + r[2] = (v = (v >>> 16) + a[2] + b[2]) & 0xffff; + r[3] = (v = (v >>> 16) + a[3] + b[3]) & 0xffff; + r[4] = (v = (v >>> 16) + a[4] + b[4]) & 0xffff; + r[5] = (v = (v >>> 16) + a[5] + b[5]) & 0xffff; + r[6] = (v = (v >>> 16) + a[6] + b[6]) & 0xffff; + r[7] = (v = (v >>> 16) + a[7] + b[7]) & 0xffff; + r[8] = (v = (v >>> 16) + a[8] + b[8]) & 0xffff; + r[9] = (v = (v >>> 16) + a[9] + b[9]) & 0xffff; + r[10] = (v = (v >>> 16) + a[10] + b[10]) & 0xffff; + r[11] = (v = (v >>> 16) + a[11] + b[11]) & 0xffff; + r[12] = (v = (v >>> 16) + a[12] + b[12]) & 0xffff; + r[13] = (v = (v >>> 16) + a[13] + b[13]) & 0xffff; + r[14] = (v = (v >>> 16) + a[14] + b[14]) & 0xffff; + r[15] = (v >>> 16) + a[15] + b[15]; + return r; + } + + function _bigintsub(a, b) { + var r = []; + var v; + r[0] = (v = 0x80000 + a[0] - b[0]) & 0xffff; + r[1] = (v = (v >>> 16) + 0x7fff8 + a[1] - b[1]) & 0xffff; + r[2] = (v = (v >>> 16) + 0x7fff8 + a[2] - b[2]) & 0xffff; + r[3] = (v = (v >>> 16) + 0x7fff8 + a[3] - b[3]) & 0xffff; + r[4] = (v = (v >>> 16) + 0x7fff8 + a[4] - b[4]) & 0xffff; + r[5] = (v = (v >>> 16) + 0x7fff8 + a[5] - b[5]) & 0xffff; + r[6] = (v = (v >>> 16) + 0x7fff8 + a[6] - b[6]) & 0xffff; + r[7] = (v = (v >>> 16) + 0x7fff8 + a[7] - b[7]) & 0xffff; + r[8] = (v = (v >>> 16) + 0x7fff8 + a[8] - b[8]) & 0xffff; + r[9] = (v = (v >>> 16) + 0x7fff8 + a[9] - b[9]) & 0xffff; + r[10] = (v = (v >>> 16) + 0x7fff8 + a[10] - b[10]) & 0xffff; + r[11] = (v = (v >>> 16) + 0x7fff8 + a[11] - b[11]) & 0xffff; + r[12] = (v = (v >>> 16) + 0x7fff8 + a[12] - b[12]) & 0xffff; + r[13] = (v = (v >>> 16) + 0x7fff8 + a[13] - b[13]) & 0xffff; + r[14] = (v = (v >>> 16) + 0x7fff8 + a[14] - b[14]) & 0xffff; + r[15] = (v >>> 16) - 8 + a[15] - b[15]; + return r; + } + + function _sqr8h(a7, a6, a5, a4, a3, a2, a1, a0) { + // 'division by 0x10000' can not be replaced by '>> 16' because + // more than 32 bits of precision are needed similarly + // 'multiplication by 2' cannot be replaced by '<< 1' + var r = []; + var v; + r[0] = (v = a0 * a0) & 0xffff; + r[1] = (v = (0 | (v / 0x10000)) + 2 * a0 * a1) & 0xffff; + r[2] = (v = (0 | (v / 0x10000)) + 2 * a0 * a2 + a1 * a1) & 0xffff; + r[3] = (v = (0 | (v / 0x10000)) + 2 * a0 * a3 + 2 * a1 * a2) & 0xffff; + r[4] = (v = (0 | (v / 0x10000)) + 2 * a0 * a4 + 2 * a1 * a3 + a2 + * a2) & 0xffff; + r[5] = (v = (0 | (v / 0x10000)) + 2 * a0 * a5 + 2 * a1 * a4 + 2 + * a2 * a3) & 0xffff; + r[6] = (v = (0 | (v / 0x10000)) + 2 * a0 * a6 + 2 * a1 * a5 + 2 + * a2 * a4 + a3 * a3) & 0xffff; + r[7] = (v = (0 | (v / 0x10000)) + 2 * a0 * a7 + 2 * a1 * a6 + 2 + * a2 * a5 + 2 * a3 * a4) & 0xffff; + r[8] = (v = (0 | (v / 0x10000)) + 2 * a1 * a7 + 2 * a2 * a6 + 2 + * a3 * a5 + a4 * a4) & 0xffff; + r[9] = (v = (0 | (v / 0x10000)) + 2 * a2 * a7 + 2 * a3 * a6 + 2 + * a4 * a5) & 0xffff; + r[10] = (v = (0 | (v / 0x10000)) + 2 * a3 * a7 + 2 * a4 * a6 + + a5 * a5) & 0xffff; + r[11] = (v = (0 | (v / 0x10000)) + 2 * a4 * a7 + 2 * a5 * a6) & 0xffff; + r[12] = (v = (0 | (v / 0x10000)) + 2 * a5 * a7 + a6 * a6) & 0xffff; + r[13] = (v = (0 | (v / 0x10000)) + 2 * a6 * a7) & 0xffff; + r[14] = (v = (0 | (v / 0x10000)) + a7 * a7) & 0xffff; + r[15] = 0 | (v / 0x10000); + return r; + } + + function _sqrmodp(a) { + var x = _sqr8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9], + a[8]); + var z = _sqr8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]); + var y = _sqr8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12] + + a[4], + a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8] + + a[0]); + var r = []; + var v; + r[0] = (v = 0x800000 + z[0] + (y[8] - x[8] - z[8] + x[0] - 0x80) + * 38) & 0xffff; + r[1] = (v = 0x7fff80 + (v >>> 16) + z[1] + + (y[9] - x[9] - z[9] + x[1]) * 38) & 0xffff; + r[2] = (v = 0x7fff80 + (v >>> 16) + z[2] + + (y[10] - x[10] - z[10] + x[2]) * 38) & 0xffff; + r[3] = (v = 0x7fff80 + (v >>> 16) + z[3] + + (y[11] - x[11] - z[11] + x[3]) * 38) & 0xffff; + r[4] = (v = 0x7fff80 + (v >>> 16) + z[4] + + (y[12] - x[12] - z[12] + x[4]) * 38) & 0xffff; + r[5] = (v = 0x7fff80 + (v >>> 16) + z[5] + + (y[13] - x[13] - z[13] + x[5]) * 38) & 0xffff; + r[6] = (v = 0x7fff80 + (v >>> 16) + z[6] + + (y[14] - x[14] - z[14] + x[6]) * 38) & 0xffff; + r[7] = (v = 0x7fff80 + (v >>> 16) + z[7] + + (y[15] - x[15] - z[15] + x[7]) * 38) & 0xffff; + r[8] = (v = 0x7fff80 + (v >>> 16) + z[8] + y[0] - x[0] - z[0] + + x[8] * 38) & 0xffff; + r[9] = (v = 0x7fff80 + (v >>> 16) + z[9] + y[1] - x[1] - z[1] + + x[9] * 38) & 0xffff; + r[10] = (v = 0x7fff80 + (v >>> 16) + z[10] + y[2] - x[2] - z[2] + + x[10] * 38) & 0xffff; + r[11] = (v = 0x7fff80 + (v >>> 16) + z[11] + y[3] - x[3] - z[3] + + x[11] * 38) & 0xffff; + r[12] = (v = 0x7fff80 + (v >>> 16) + z[12] + y[4] - x[4] - z[4] + + x[12] * 38) & 0xffff; + r[13] = (v = 0x7fff80 + (v >>> 16) + z[13] + y[5] - x[5] - z[5] + + x[13] * 38) & 0xffff; + r[14] = (v = 0x7fff80 + (v >>> 16) + z[14] + y[6] - x[6] - z[6] + + x[14] * 38) & 0xffff; + r[15] = 0x7fff80 + (v >>> 16) + z[15] + y[7] - x[7] - z[7] + + x[15] * 38; + _reduce(r); + return r; + } + + function _mul8h(a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, + b2, b1, b0) { + // 'division by 0x10000' can not be replaced by '>> 16' because + // more than 32 bits of precision are needed + var r = []; + var v; + r[0] = (v = a0 * b0) & 0xffff; + r[1] = (v = (0 | (v / 0x10000)) + a0 * b1 + a1 * b0) & 0xffff; + r[2] = (v = (0 | (v / 0x10000)) + a0 * b2 + a1 * b1 + a2 * b0) & 0xffff; + r[3] = (v = (0 | (v / 0x10000)) + a0 * b3 + a1 * b2 + a2 * b1 + + a3 * b0) & 0xffff; + r[4] = (v = (0 | (v / 0x10000)) + a0 * b4 + a1 * b3 + a2 * b2 + + a3 * b1 + a4 * b0) & 0xffff; + r[5] = (v = (0 | (v / 0x10000)) + a0 * b5 + a1 * b4 + a2 * b3 + + a3 * b2 + a4 * b1 + a5 * b0) & 0xffff; + r[6] = (v = (0 | (v / 0x10000)) + a0 * b6 + a1 * b5 + a2 * b4 + + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0) & 0xffff; + r[7] = (v = (0 | (v / 0x10000)) + a0 * b7 + a1 * b6 + a2 * b5 + + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0) & 0xffff; + r[8] = (v = (0 | (v / 0x10000)) + a1 * b7 + a2 * b6 + a3 * b5 + + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1) & 0xffff; + r[9] = (v = (0 | (v / 0x10000)) + a2 * b7 + a3 * b6 + a4 * b5 + + a5 * b4 + a6 * b3 + a7 * b2) & 0xffff; + r[10] = (v = (0 | (v / 0x10000)) + a3 * b7 + a4 * b6 + a5 * b5 + + a6 * b4 + a7 * b3) & 0xffff; + r[11] = (v = (0 | (v / 0x10000)) + a4 * b7 + a5 * b6 + a6 * b5 + + a7 * b4) & 0xffff; + r[12] = (v = (0 | (v / 0x10000)) + a5 * b7 + a6 * b6 + a7 * b5) & 0xffff; + r[13] = (v = (0 | (v / 0x10000)) + a6 * b7 + a7 * b6) & 0xffff; + r[14] = (v = (0 | (v / 0x10000)) + a7 * b7) & 0xffff; + r[15] = (0 | (v / 0x10000)); + return r; + } + + function _mulmodp(a, b) { + // Karatsuba multiplication scheme: x*y = (b^2+b)*x1*y1 - + // b*(x1-x0)*(y1-y0) + (b+1)*x0*y0 + var x = _mul8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9], + a[8], b[15], b[14], b[13], b[12], b[11], b[10], + b[9], b[8]); + var z = _mul8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0], + b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]); + var y = _mul8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12] + + a[4], + a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8] + + a[0], + b[15] + b[7], b[14] + b[6], b[13] + b[5], b[12] + + b[4], + b[11] + b[3], b[10] + b[2], b[9] + b[1], b[8] + + b[0]); + var r = []; + var v; + r[0] = (v = 0x800000 + z[0] + (y[8] - x[8] - z[8] + x[0] - 0x80) + * 38) & 0xffff; + r[1] = (v = 0x7fff80 + (v >>> 16) + z[1] + + (y[9] - x[9] - z[9] + x[1]) * 38) & 0xffff; + r[2] = (v = 0x7fff80 + (v >>> 16) + z[2] + + (y[10] - x[10] - z[10] + x[2]) * 38) & 0xffff; + r[3] = (v = 0x7fff80 + (v >>> 16) + z[3] + + (y[11] - x[11] - z[11] + x[3]) * 38) & 0xffff; + r[4] = (v = 0x7fff80 + (v >>> 16) + z[4] + + (y[12] - x[12] - z[12] + x[4]) * 38) & 0xffff; + r[5] = (v = 0x7fff80 + (v >>> 16) + z[5] + + (y[13] - x[13] - z[13] + x[5]) * 38) & 0xffff; + r[6] = (v = 0x7fff80 + (v >>> 16) + z[6] + + (y[14] - x[14] - z[14] + x[6]) * 38) & 0xffff; + r[7] = (v = 0x7fff80 + (v >>> 16) + z[7] + + (y[15] - x[15] - z[15] + x[7]) * 38) & 0xffff; + r[8] = (v = 0x7fff80 + (v >>> 16) + z[8] + y[0] - x[0] - z[0] + + x[8] * 38) & 0xffff; + r[9] = (v = 0x7fff80 + (v >>> 16) + z[9] + y[1] - x[1] - z[1] + + x[9] * 38) & 0xffff; + r[10] = (v = 0x7fff80 + (v >>> 16) + z[10] + y[2] - x[2] - z[2] + + x[10] * 38) & 0xffff; + r[11] = (v = 0x7fff80 + (v >>> 16) + z[11] + y[3] - x[3] - z[3] + + x[11] * 38) & 0xffff; + r[12] = (v = 0x7fff80 + (v >>> 16) + z[12] + y[4] - x[4] - z[4] + + x[12] * 38) & 0xffff; + r[13] = (v = 0x7fff80 + (v >>> 16) + z[13] + y[5] - x[5] - z[5] + + x[13] * 38) & 0xffff; + r[14] = (v = 0x7fff80 + (v >>> 16) + z[14] + y[6] - x[6] - z[6] + + x[14] * 38) & 0xffff; + r[15] = 0x7fff80 + (v >>> 16) + z[15] + y[7] - x[7] - z[7] + + x[15] * 38; + _reduce(r); + return r; + } + + function _reduce(arr) { + var aCopy = arr.slice(0); + var choice = [arr, aCopy]; + var v = arr[15]; + // Use the dummy copy instead of just returning to be more constant time. + var a = choice[(v < 0x8000) & 1]; + a[15] = v & 0x7fff; + // >32-bits of precision are required here so '/ 0x8000' can not be + // replaced by the arithmetic equivalent '>>> 15' + v = (0 | (v / 0x8000)) * 19; + a[0] = (v += a[0]) & 0xffff; + v = v >>> 16; + a[1] = (v += a[1]) & 0xffff; + v = v >>> 16; + a[2] = (v += a[2]) & 0xffff; + v = v >>> 16; + a[3] = (v += a[3]) & 0xffff; + v = v >>> 16; + a[4] = (v += a[4]) & 0xffff; + v = v >>> 16; + a[5] = (v += a[5]) & 0xffff; + v = v >>> 16; + a[6] = (v += a[6]) & 0xffff; + v = v >>> 16; + a[7] = (v += a[7]) & 0xffff; + v = v >>> 16; + a[8] = (v += a[8]) & 0xffff; + v = v >>> 16; + a[9] = (v += a[9]) & 0xffff; + v = v >>> 16; + a[10] = (v += a[10]) & 0xffff; + v = v >>> 16; + a[11] = (v += a[11]) & 0xffff; + v = v >>> 16; + a[12] = (v += a[12]) & 0xffff; + v = v >>> 16; + a[13] = (v += a[13]) & 0xffff; + v = v >>> 16; + a[14] = (v += a[14]) & 0xffff; + v = v >>> 16; + a[15] += v; + } + + function _addmodp(a, b) { + var r = []; + var v; + r[0] = (v = ((0 | (a[15] >>> 15)) + (0 | (b[15] >>> 15))) * 19 + + a[0] + b[0]) & 0xffff; + r[1] = (v = (v >>> 16) + a[1] + b[1]) & 0xffff; + r[2] = (v = (v >>> 16) + a[2] + b[2]) & 0xffff; + r[3] = (v = (v >>> 16) + a[3] + b[3]) & 0xffff; + r[4] = (v = (v >>> 16) + a[4] + b[4]) & 0xffff; + r[5] = (v = (v >>> 16) + a[5] + b[5]) & 0xffff; + r[6] = (v = (v >>> 16) + a[6] + b[6]) & 0xffff; + r[7] = (v = (v >>> 16) + a[7] + b[7]) & 0xffff; + r[8] = (v = (v >>> 16) + a[8] + b[8]) & 0xffff; + r[9] = (v = (v >>> 16) + a[9] + b[9]) & 0xffff; + r[10] = (v = (v >>> 16) + a[10] + b[10]) & 0xffff; + r[11] = (v = (v >>> 16) + a[11] + b[11]) & 0xffff; + r[12] = (v = (v >>> 16) + a[12] + b[12]) & 0xffff; + r[13] = (v = (v >>> 16) + a[13] + b[13]) & 0xffff; + r[14] = (v = (v >>> 16) + a[14] + b[14]) & 0xffff; + r[15] = (v >>> 16) + (a[15] & 0x7fff) + (b[15] & 0x7fff); + return r; + } + + function _submodp(a, b) { + var r = []; + var v; + r[0] = (v = 0x80000 + + ((0 | (a[15] >>> 15)) - (0 | (b[15] >>> 15)) - 1) + * 19 + a[0] - b[0]) & 0xffff; + r[1] = (v = (v >>> 16) + 0x7fff8 + a[1] - b[1]) & 0xffff; + r[2] = (v = (v >>> 16) + 0x7fff8 + a[2] - b[2]) & 0xffff; + r[3] = (v = (v >>> 16) + 0x7fff8 + a[3] - b[3]) & 0xffff; + r[4] = (v = (v >>> 16) + 0x7fff8 + a[4] - b[4]) & 0xffff; + r[5] = (v = (v >>> 16) + 0x7fff8 + a[5] - b[5]) & 0xffff; + r[6] = (v = (v >>> 16) + 0x7fff8 + a[6] - b[6]) & 0xffff; + r[7] = (v = (v >>> 16) + 0x7fff8 + a[7] - b[7]) & 0xffff; + r[8] = (v = (v >>> 16) + 0x7fff8 + a[8] - b[8]) & 0xffff; + r[9] = (v = (v >>> 16) + 0x7fff8 + a[9] - b[9]) & 0xffff; + r[10] = (v = (v >>> 16) + 0x7fff8 + a[10] - b[10]) & 0xffff; + r[11] = (v = (v >>> 16) + 0x7fff8 + a[11] - b[11]) & 0xffff; + r[12] = (v = (v >>> 16) + 0x7fff8 + a[12] - b[12]) & 0xffff; + r[13] = (v = (v >>> 16) + 0x7fff8 + a[13] - b[13]) & 0xffff; + r[14] = (v = (v >>> 16) + 0x7fff8 + a[14] - b[14]) & 0xffff; + r[15] = (v >>> 16) + 0x7ff8 + (a[15] & 0x7fff) + - (b[15] & 0x7fff); + return r; + } + + function _invmodp(a) { + var c = a; + var i = 250; + while (--i) { + a = _sqrmodp(a); + a = _mulmodp(a, c); + } + a = _sqrmodp(a); + a = _sqrmodp(a); + a = _mulmodp(a, c); + a = _sqrmodp(a); + a = _sqrmodp(a); + a = _mulmodp(a, c); + a = _sqrmodp(a); + a = _mulmodp(a, c); + return a; + } + + function _mulasmall(a) { + // 'division by 0x10000' can not be replaced by '>> 16' because + // more than 32 bits of precision are needed + var m = 121665; + var r = []; + var v; + r[0] = (v = a[0] * m) & 0xffff; + r[1] = (v = (0 | (v / 0x10000)) + a[1] * m) & 0xffff; + r[2] = (v = (0 | (v / 0x10000)) + a[2] * m) & 0xffff; + r[3] = (v = (0 | (v / 0x10000)) + a[3] * m) & 0xffff; + r[4] = (v = (0 | (v / 0x10000)) + a[4] * m) & 0xffff; + r[5] = (v = (0 | (v / 0x10000)) + a[5] * m) & 0xffff; + r[6] = (v = (0 | (v / 0x10000)) + a[6] * m) & 0xffff; + r[7] = (v = (0 | (v / 0x10000)) + a[7] * m) & 0xffff; + r[8] = (v = (0 | (v / 0x10000)) + a[8] * m) & 0xffff; + r[9] = (v = (0 | (v / 0x10000)) + a[9] * m) & 0xffff; + r[10] = (v = (0 | (v / 0x10000)) + a[10] * m) & 0xffff; + r[11] = (v = (0 | (v / 0x10000)) + a[11] * m) & 0xffff; + r[12] = (v = (0 | (v / 0x10000)) + a[12] * m) & 0xffff; + r[13] = (v = (0 | (v / 0x10000)) + a[13] * m) & 0xffff; + r[14] = (v = (0 | (v / 0x10000)) + a[14] * m) & 0xffff; + r[15] = (0 | (v / 0x10000)) + a[15] * m; + _reduce(r); + return r; + } + + function _dbl(x, z) { + var x_2, z_2, m, n, o; + m = _sqrmodp(_addmodp(x, z)); + n = _sqrmodp(_submodp(x, z)); + o = _submodp(m, n); + x_2 = _mulmodp(n, m); + z_2 = _mulmodp(_addmodp(_mulasmall(o), m), o); + return [x_2, z_2]; + } + + function _sum(x, z, x_p, z_p, x_1) { + var x_3, z_3, p, q; + p = _mulmodp(_submodp(x, z), _addmodp(x_p, z_p)); + q = _mulmodp(_addmodp(x, z), _submodp(x_p, z_p)); + x_3 = _sqrmodp(_addmodp(p, q)); + z_3 = _mulmodp(_sqrmodp(_submodp(p, q)), x_1); + return [x_3, z_3]; + } + + function _generateKey(curve25519) { + var buffer = crypto.randomBytes(32); + + // For Curve25519 DH keys, we need to apply some bit mask on generated + // keys: + // * clear bit 0, 1, 2 of first byte + // * clear bit 7 of last byte + // * set bit 6 of last byte + if (curve25519 === true) { + buffer[0] &= 0xf8; + buffer[31] = (buffer[31] & 0x7f) | 0x40; + } + var result = []; + for (var i = 0; i < buffer.length; i++) { + result.push(String.fromCharCode(buffer[i])); + } + return result.join(''); + } + + // Expose some functions to the outside through this name space. + // Note: This is not part of the public API. + ns.getbit = _getbit; + ns.setbit = _setbit; + ns.addmodp = _addmodp; + ns.invmodp = _invmodp; + ns.mulmodp = _mulmodp; + ns.reduce = _reduce; + ns.dbl = _dbl; + ns.sum = _sum; + ns.ZERO = _ZERO; + ns.ONE = _ONE; + ns.BASE = _BASE; + ns.bigintadd = _bigintadd; + ns.bigintsub = _bigintsub; + ns.bigintcmp = _bigintcmp; + ns.mulmodp = _mulmodp; + ns.sqrmodp = _sqrmodp; + ns.generateKey = _generateKey; + + +module.exports = ns; diff --git a/hm_sunwell/node_modules/jodid25519/lib/curve255.js b/hm_sunwell/node_modules/jodid25519/lib/curve255.js new file mode 100644 index 0000000..3978b46 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/lib/curve255.js @@ -0,0 +1,221 @@ +"use strict"; +/** + * @fileOverview + * Core operations on curve 25519 required for the higher level modules. + */ + +/* + * Copyright (c) 2007, 2013, 2014 Michele Bini + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * Authors: Guy K. Kloss, Michele Bini + * + * You should have received a copy of the license along with this program. + */ + +var core = require('./core'); +var utils = require('./utils'); + + /** + * @exports jodid25519/curve255 + * Legacy compatibility module for Michele Bini's previous curve255.js. + * + * @description + * Legacy compatibility module for Michele Bini's previous curve255.js. + * + *

+ * This code presents an API with all key formats as previously available + * from Michele Bini's curve255.js implementation. + *

+ */ + var ns = {}; + + function curve25519_raw(f, c) { + var a, x_1, q; + + x_1 = c; + a = core.dbl(x_1, core.ONE()); + q = [x_1, core.ONE()]; + + var n = 255; + + while (core.getbit(f, n) == 0) { + n--; + // For correct constant-time operation, bit 255 should always be + // set to 1 so the following 'while' loop is never entered. + if (n < 0) { + return core.ZERO(); + } + } + n--; + + var aq = [a, q]; + + while (n >= 0) { + var r, s; + var b = core.getbit(f, n); + r = core.sum(aq[0][0], aq[0][1], aq[1][0], aq[1][1], x_1); + s = core.dbl(aq[1 - b][0], aq[1 - b][1]); + aq[1 - b] = s; + aq[b] = r; + n--; + } + q = aq[1]; + + q[1] = core.invmodp(q[1]); + q[0] = core.mulmodp(q[0], q[1]); + core.reduce(q[0]); + return q[0]; + } + + function curve25519b32(a, b) { + return _base32encode(curve25519(_base32decode(a), + _base32decode(b))); + } + + function curve25519(f, c) { + if (!c) { + c = core.BASE(); + } + f[0] &= 0xFFF8; + f[15] = (f[15] & 0x7FFF) | 0x4000; + return curve25519_raw(f, c); + } + + function _hexEncodeVector(k) { + var hexKey = utils.hexEncode(k); + // Pad with '0' at the front. + hexKey = new Array(64 + 1 - hexKey.length).join('0') + hexKey; + // Invert bytes. + return hexKey.split(/(..)/).reverse().join(''); + } + + function _hexDecodeVector(v) { + // assert(length(x) == 64); + // Invert bytes. + var hexKey = v.split(/(..)/).reverse().join(''); + return utils.hexDecode(hexKey); + } + + + // Expose some functions to the outside through this name space. + + /** + * Computes the scalar product of a point on the curve 25519. + * + * This function is used for the DH key-exchange protocol. + * + * Before multiplication, some bit operations are applied to the + * private key to ensure it is a valid Curve25519 secret key. + * It is the user's responsibility to make sure that the private + * key is a uniformly random, secret value. + * + * @function + * @param f {array} + * Private key. + * @param c {array} + * Public point on the curve. If not given, the curve's base point is used. + * @returns {array} + * Key point resulting from scalar product. + */ + ns.curve25519 = curve25519; + + /** + * Computes the scalar product of a point on the curve 25519. + * + * This variant does not make sure that the private key is valid. + * The user has the responsibility to ensure the private key is + * valid or that this results in a safe protocol. Unless you know + * exactly what you are doing, you should not use this variant, + * please use 'curve25519' instead. + * + * @function + * @param f {array} + * Private key. + * @param c {array} + * Public point on the curve. If not given, the curve's base point is used. + * @returns {array} + * Key point resulting from scalar product. + */ + ns.curve25519_raw = curve25519_raw; + + /** + * Encodes the internal representation of a key to a canonical hex + * representation. + * + * This is the format commonly used in other libraries and for + * test vectors, and is equivalent to the hex dump of the key in + * little-endian binary format. + * + * @function + * @param n {array} + * Array representation of key. + * @returns {string} + * Hexadecimal string representation of key. + */ + ns.hexEncodeVector = _hexEncodeVector; + + /** + * Decodes a canonical hex representation of a key + * to an internally compatible array representation. + * + * @function + * @param n {string} + * Hexadecimal string representation of key. + * @returns {array} + * Array representation of key. + */ + ns.hexDecodeVector = _hexDecodeVector; + + /** + * Encodes the internal representation of a key into a + * hexadecimal representation. + * + * This is a strict positional notation, most significant digit first. + * + * @function + * @param n {array} + * Array representation of key. + * @returns {string} + * Hexadecimal string representation of key. + */ + ns.hexencode = utils.hexEncode; + + /** + * Decodes a hex representation of a key to an internally + * compatible array representation. + * + * @function + * @param n {string} + * Hexadecimal string representation of key. + * @returns {array} + * Array representation of key. + */ + ns.hexdecode = utils.hexDecode; + + /** + * Encodes the internal representation of a key to a base32 + * representation. + * + * @function + * @param n {array} + * Array representation of key. + * @returns {string} + * Base32 string representation of key. + */ + ns.base32encode = utils.base32encode; + + /** + * Decodes a base32 representation of a key to an internally + * compatible array representation. + * + * @function + * @param n {string} + * Base32 string representation of key. + * @returns {array} + * Array representation of key. + */ + ns.base32decode = utils.base32decode; + +module.exports = ns; diff --git a/hm_sunwell/node_modules/jodid25519/lib/dh.js b/hm_sunwell/node_modules/jodid25519/lib/dh.js new file mode 100644 index 0000000..2f75494 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/lib/dh.js @@ -0,0 +1,111 @@ +"use strict"; +/** + * @fileOverview + * EC Diffie-Hellman operations on Curve25519. + */ + +/* + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * Authors: Guy K. Kloss + * + * You should have received a copy of the license along with this program. + */ + +var core = require('./core'); +var utils = require('./utils'); +var curve255 = require('./curve255'); + + + /** + * @exports jodid25519/dh + * EC Diffie-Hellman operations on Curve25519. + * + * @description + * EC Diffie-Hellman operations on Curve25519. + */ + var ns = {}; + + + function _toString(vector) { + var u = new Uint16Array(vector); + return (new Buffer(new Uint8Array(u.buffer))); + } + + function _fromString(vector) { + if (Buffer.isBuffer(vector)) { + var u = new Uint8Array(vector); + return (new Uint16Array(u.buffer)); + } + + var result = new Array(16); + for (var i = 0, l = 0; i < vector.length; i += 2) { + result[l] = (vector.charCodeAt(i + 1) << 8) | vector.charCodeAt(i); + l++; + } + return result; + } + + + /** + * Computes a key through scalar multiplication of a point on the curve 25519. + * + * This function is used for the DH key-exchange protocol. It computes a + * key based on a secret key with a public component (opponent's public key + * or curve base point if not given) by using scalar multiplication. + * + * Before multiplication, some bit operations are applied to the + * private key to ensure it is a valid Curve25519 secret key. + * It is the user's responsibility to make sure that the private + * key is a uniformly random, secret value. + * + * @function + * @param privateComponent {string} + * Private point as byte string on the curve. + * @param publicComponent {string} + * Public point as byte string on the curve. If not given, the curve's + * base point is used. + * @returns {string} + * Key point as byte string resulting from scalar product. + */ + ns.computeKey = function(privateComponent, publicComponent) { + if (publicComponent) { + return _toString(curve255.curve25519(_fromString(privateComponent), + _fromString(publicComponent))); + } else { + return _toString(curve255.curve25519(_fromString(privateComponent))); + } + }; + + /** + * Computes the public key to a private key on the curve 25519. + * + * Before multiplication, some bit operations are applied to the + * private key to ensure it is a valid Curve25519 secret key. + * It is the user's responsibility to make sure that the private + * key is a uniformly random, secret value. + * + * @function + * @param privateKey {string} + * Private point as byte string on the curve. + * @returns {string} + * Public key point as byte string resulting from scalar product. + */ + ns.publicKey = function(privateKey) { + return _toString(curve255.curve25519(_fromString(privateKey))); + }; + + + /** + * Generates a new random private key of 32 bytes length (256 bit). + * + * @function + * @returns {string} + * Byte string containing a new random private key seed. + */ + ns.generateKey = function() { + return core.generateKey(true); + }; + +module.exports = ns; diff --git a/hm_sunwell/node_modules/jodid25519/lib/eddsa.js b/hm_sunwell/node_modules/jodid25519/lib/eddsa.js new file mode 100644 index 0000000..c384f32 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/lib/eddsa.js @@ -0,0 +1,573 @@ +"use strict"; +/** + * @fileOverview + * Digital signature scheme based on Curve25519 (Ed25519 or EdDSA). + */ + +/* + * Copyright (c) 2011, 2012, 2014 Ron Garret + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * Authors: Guy K. Kloss, Ron Garret + * + * You should have received a copy of the license along with this program. + */ + +var core = require('./core'); +var curve255 = require('./curve255'); +var utils = require('./utils'); +var BigInteger = require('jsbn').BigInteger; +var crypto = require('crypto'); + + /** + * @exports jodid25519/eddsa + * Digital signature scheme based on Curve25519 (Ed25519 or EdDSA). + * + * @description + * Digital signature scheme based on Curve25519 (Ed25519 or EdDSA). + * + *

+ * This code is adapted from fast-djbec.js, a faster but more complicated + * version of the Ed25519 encryption scheme (as compared to djbec.js). + * It uses two different representations for big integers: The jsbn + * BigInteger class, which can represent arbitrary-length numbers, and a + * special fixed-length representation optimised for 256-bit integers. + * The reason both are needed is that the Ed25519 algorithm requires some + * 512-bit numbers.

+ */ + var ns = {}; + + function _bi255(value) { + if (!(this instanceof _bi255)) { + return new _bi255(value); + } + if (typeof value === 'undefined') { + return _ZERO; + } + var c = value.constructor; + if ((c === Array || c === Uint16Array || c === Uint32Array) && (value.length === 16)) { + this.n = value; + } else if ((c === Array) && (value.length === 32)) { + this.n = _bytes2bi255(value).n; + } else if (c === String) { + this.n = utils.hexDecode(value); + } else if (c === Number) { + this.n = [value & 0xffff, + value >> 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } else if (value instanceof _bi255) { + this.n = value.n.slice(0); // Copy constructor + } else { + throw "Bad argument for bignum: " + value; + } + } + + _bi255.prototype = { + 'toString' : function() { + return utils.hexEncode(this.n); + }, + 'toSource' : function() { + return '_' + utils.hexEncode(this.n); + }, + 'plus' : function(n1) { + return _bi255(core.bigintadd(this.n, n1.n)); + }, + 'minus' : function(n1) { + return _bi255(core.bigintsub(this.n, n1.n)).modq(); + }, + 'times' : function(n1) { + return _bi255(core.mulmodp(this.n, n1.n)); + }, + 'divide' : function(n1) { + return this.times(n1.inv()); + }, + 'sqr' : function() { + return _bi255(core.sqrmodp(this.n)); + }, + 'cmp' : function(n1) { + return core.bigintcmp(this.n, n1.n); + }, + 'equals' : function(n1) { + return this.cmp(n1) === 0; + }, + 'isOdd' : function() { + return (this.n[0] & 1) === 1; + }, + 'shiftLeft' : function(cnt) { + _shiftL(this.n, cnt); + return this; + }, + 'shiftRight' : function(cnt) { + _shiftR(this.n, cnt); + return this; + }, + 'inv' : function() { + return _bi255(core.invmodp(this.n)); + }, + 'pow' : function(e) { + return _bi255(_pow(this.n, e.n)); + }, + 'modq' : function() { + return _modq(this); + }, + 'bytes' : function() { + return _bi255_bytes(this); + } + }; + + function _shiftL(n, cnt) { + var lastcarry = 0; + for (var i = 0; i < 16; i++) { + var carry = n[i] >> (16 - cnt); + n[i] = (n[i] << cnt) & 0xffff | lastcarry; + lastcarry = carry; + } + return n; + } + + function _shiftR(n, cnt) { + var lastcarry = 0; + for (var i = 15; i >= 0; i--) { + var carry = n[i] << (16 - cnt) & 0xffff; + n[i] = (n[i] >> cnt) | lastcarry; + lastcarry = carry; + } + return n; + } + + function _bi255_bytes(n) { + n = _bi255(n); // Make a copy because shiftRight is destructive + var a = new Array(32); + for (var i = 31; i >= 0; i--) { + a[i] = n.n[0] & 0xff; + n.shiftRight(8); + } + return a; + } + + function _bytes2bi255(a) { + var n = _ZERO; + for (var i = 0; i < 32; i++) { + n.shiftLeft(8); + n = n.plus(_bi255(a[i])); + } + return n; + } + + function _pow(n, e) { + var result = core.ONE(); + for (var i = 0; i < 256; i++) { + if (core.getbit(e, i) === 1) { + result = core.mulmodp(result, n); + } + n = core.sqrmodp(n); + } + return result; + } + + var _ZERO = _bi255(0); + var _ONE = _bi255(1); + var _TWO = _bi255(2); + // This is the core prime. + var _Q = _bi255([0xffff - 18, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x7fff]); + + function _modq(n) { + core.reduce(n.n); + if (n.cmp(_Q) >= 0) { + return _modq(n.minus(_Q)); + } + if (n.cmp(_ZERO) === -1) { + return _modq(n.plus(_Q)); + } else { + return n; + } + } + + // _RECOVERY_EXPONENT = _Q.plus(_bi255(3)).divide(_bi255(8)); + var _RECOVERY_EXPONENT = _bi255('0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe'); + // _D = _Q.minus(_bi255(121665)).divide(_bi255(121666)); + var _D = _bi255('52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3'); + // _I = _TWO.pow(_Q.minus(_ONE).divide(_bi255(4))); + var _I = _bi255('2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0'); + // _L = _TWO.pow(_bi255(252)).plus(_bi255('14def9dea2f79cd65812631a5cf5d3ed')); + var _L = _bi255('1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed'); + var _L_BI = _bi('1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed', 16); + + + // //////////////////////////////////////////////////////////// + + function _isoncurve(p) { + var x = p[0]; + var y = p[1]; + var xsqr = x.sqr(); + var ysqr = y.sqr(); + var v = _D.times(xsqr).times(ysqr); + return ysqr.minus(xsqr).minus(_ONE).minus(v).modq().equals(_ZERO); + } + + function _xrecover(y) { + var ysquared = y.sqr(); + var xx = ysquared.minus(_ONE).divide(_ONE.plus(_D.times(ysquared))); + var x = xx.pow(_RECOVERY_EXPONENT); + if (!(x.times(x).minus(xx).equals(_ZERO))) { + x = x.times(_I); + } + if (x.isOdd()) { + x = _Q.minus(x); + } + return x; + } + + function _x_pt_add(pt1, pt2) { + var x1 = pt1[0]; + var y1 = pt1[1]; + var z1 = pt1[2]; + var t1 = pt1[3]; + var x2 = pt2[0]; + var y2 = pt2[1]; + var z2 = pt2[2]; + var t2 = pt2[3]; + var A = y1.minus(x1).times(y2.plus(x2)); + var B = y1.plus(x1).times(y2.minus(x2)); + var C = z1.times(_TWO).times(t2); + var D = t1.times(_TWO).times(z2); + var E = D.plus(C); + var F = B.minus(A); + var G = B.plus(A); + var H = D.minus(C); + return [E.times(F), G.times(H), F.times(G), E.times(H)]; + } + + function _xpt_double(pt1) { + var x1 = pt1[0]; + var y1 = pt1[1]; + var z1 = pt1[2]; + var A = x1.times(x1); + var B = y1.times(y1); + var C = _TWO.times(z1).times(z1); + var D = _Q.minus(A); + var J = x1.plus(y1); + var E = J.times(J).minus(A).minus(B); + var G = D.plus(B); + var F = G.minus(C); + var H = D.minus(B); + return [E.times(F), G.times(H), F.times(G), E.times(H)]; + } + + function _xpt_mult(pt, n) { + if (n.equals(_ZERO)) { + return [_ZERO, _ONE, _ONE, _ZERO]; + } + var odd = n.isOdd(); + n.shiftRight(1); + var value = _xpt_double(_xpt_mult(pt, n)); + return odd ? _x_pt_add(value, pt) : value; + } + + function _pt_xform(pt) { + var x = pt[0]; + var y = pt[1]; + return [x, y, _ONE, x.times(y)]; + } + + function _pt_unxform(pt) { + var x = pt[0]; + var y = pt[1]; + var z = pt[2]; + var invz = z.inv(); + return [x.times(invz), y.times(invz)]; + } + + function _scalarmult(pt, n) { + return _pt_unxform(_xpt_mult(_pt_xform(pt), n)); + } + + function _bytesgetbit(bytes, n) { + return (bytes[bytes.length - (n >>> 3) - 1] >> (n & 7)) & 1; + } + + function _xpt_mult_bytes(pt, bytes) { + var r = [_ZERO, _ONE, _ONE, _ZERO]; + for (var i = (bytes.length << 3) - 1; i >= 0; i--) { + r = _xpt_double(r); + if (_bytesgetbit(bytes, i) === 1) { + r = _x_pt_add(r, pt); + } + } + return r; + } + + function _scalarmultBytes(pt, bytes) { + return _pt_unxform(_xpt_mult_bytes(_pt_xform(pt), bytes)); + } + + var _by = _bi255(4).divide(_bi255(5)); + var _bx = _xrecover(_by); + var _bp = [_bx, _by]; + + function _encodeint(n) { + return n.bytes(32).reverse(); + } + function _decodeint(b) { + return _bi255(b.slice(0).reverse()); + } + + function _encodepoint(p) { + var v = _encodeint(p[1]); + if (p[0].isOdd()) { + v[31] |= 0x80; + } + return v; + } + + function _decodepoint(v) { + v = v.slice(0); + var signbit = v[31] >> 7; + v[31] &= 127; + var y = _decodeint(v); + var x = _xrecover(y); + if ((x.n[0] & 1) !== signbit) { + x = _Q.minus(x); + } + var p = [x, y]; + if (!_isoncurve(p)) { + throw ('Point is not on curve'); + } + return p; + } + + // ////////////////////////////////////////////////// + + /** + * Factory function to create a suitable BigInteger. + * + * @param value + * The value for the big integer. + * @param base {integer} + * Base of the conversion of elements in ``value``. + * @returns + * A BigInteger object. + */ + function _bi(value, base) { + if (base !== undefined) { + if (base === 256) { + return _bi(utils.string2bytes(value)); + } + return new BigInteger(value, base); + } else if (typeof value === 'string') { + return new BigInteger(value, 10); + } else if ((value instanceof Array) || (value instanceof Uint8Array) + || Buffer.isBuffer(value)) { + return new BigInteger(value); + } else if (typeof value === 'number') { + return new BigInteger(value.toString(), 10); + } else { + throw "Can't convert " + value + " to BigInteger"; + } + } + + function _bi2bytes(n, cnt) { + if (cnt === undefined) { + cnt = (n.bitLength() + 7) >>> 3; + } + var bytes = new Array(cnt); + for (var i = cnt - 1; i >= 0; i--) { + bytes[i] = n[0] & 255; // n.and(0xff); + n = n.shiftRight(8); + } + return bytes; + } + + BigInteger.prototype.bytes = function(n) { + return _bi2bytes(this, n); + }; + + // ///////////////////////////////////////////////////////// + + function _bytehash(s) { + var sha = crypto.createHash('sha512').update(s).digest(); + return _bi2bytes(_bi(sha), 64).reverse(); + } + + function _stringhash(s) { + var sha = crypto.createHash('sha512').update(s).digest(); + return _map(_chr, _bi2bytes(_bi(sha), 64)).join(''); + } + + function _inthash(s) { + // Need a leading 0 to prevent sign extension + return _bi([0].concat(_bytehash(s))); + } + + function _inthash_lo(s) { + return _bi255(_bytehash(s).slice(32, 64)); + } + + function _inthash_mod_l(s) { + return _inthash(s).mod(_L_BI); + } + + function _get_a(sk) { + var a = _inthash_lo(sk); + a.n[0] &= 0xfff8; + a.n[15] &= 0x3fff; + a.n[15] |= 0x4000; + return a; + } + + function _publickey(sk) { + return _encodepoint(_scalarmult(_bp, _get_a(sk))); + } + + function _map(f, l) { + var result = new Array(l.length); + for (var i = 0; i < l.length; i++) { + result[i] = f(l[i]); + } + return result; + } + + function _chr(n) { + return String.fromCharCode(n); + } + + function _ord(c) { + return c.charCodeAt(0); + } + + function _pt_add(p1, p2) { + return _pt_unxform(_x_pt_add(_pt_xform(p1), _pt_xform(p2))); + } + + + // Exports for the API. + + /** + * Checks whether a point is on the curve. + * + * @function + * @param point {string} + * The point to check for in a byte string representation. + * @returns {boolean} + * true if the point is on the curve, false otherwise. + */ + ns.isOnCurve = function(point) { + try { + _isoncurve(_decodepoint(utils.string2bytes(point))); + } catch(e) { + if (e === 'Point is not on curve') { + return false; + } else { + throw e; + } + } + return true; + }; + + + /** + * Computes the EdDSA public key. + * + *

Note: Seeds should be a byte string, not a unicode string containing + * multi-byte characters.

+ * + * @function + * @param keySeed {string} + * Private key seed in the form of a byte string. + * @returns {string} + * Public key as byte string computed from the private key seed + * (32 bytes). + */ + ns.publicKey = function(keySeed) { + return utils.bytes2string(_publickey(keySeed)); + }; + + + /** + * Computes an EdDSA signature of a message. + * + *

Notes:

+ * + *
    + *
  • Unicode messages need to be converted to a byte representation + * (e. g. UTF-8).
  • + *
  • If `publicKey` is given, and it is *not* a point of the curve, + * the signature will be faulty, but no error will be thrown.
  • + *
+ * + * @function + * @param message {string} + * Message in the form of a byte string. + * @param keySeed {string} + * Private key seed in the form of a byte string. + * @param publicKey {string} + * Public key as byte string (if not present, it will be computed from + * the private key seed). + * @returns {string} + * Detached message signature in the form of a byte string (64 bytes). + */ + ns.sign = function(message, keySeed, publicKey) { + if (publicKey === undefined) { + publicKey = _publickey(keySeed); + } else { + publicKey = utils.string2bytes(publicKey); + } + var a = _bi(_get_a(keySeed).toString(), 16); + var hs = _stringhash(keySeed); + var r = _bytehash(hs.slice(32, 64) + message); + var rp = _scalarmultBytes(_bp, r); + var erp = _encodepoint(rp); + r = _bi(r).mod(_bi(1, 10).shiftLeft(512)); + var s = _map(_chr, erp).join('') + _map(_chr, publicKey).join('') + message; + s = _inthash_mod_l(s).multiply(a).add(r).mod(_L_BI); + return utils.bytes2string(erp.concat(_encodeint(s))); + }; + + + /** + * Verifies an EdDSA signature of a message with the public key. + * + *

Note: Unicode messages need to be converted to a byte representation + * (e. g. UTF-8).

+ * + * @function + * @param signature {string} + * Message signature in the form of a byte string. Can be detached + * (64 bytes), or attached to be sliced off. + * @param message {string} + * Message in the form of a byte string. + * @param publicKey {string} + * Public key as byte string (if not present, it will be computed from + * the private key seed). + * @returns {boolean} + * true, if the signature verifies. + */ + ns.verify = function(signature, message, publicKey) { + signature = utils.string2bytes(signature.slice(0, 64)); + publicKey = utils.string2bytes(publicKey); + var rpe = signature.slice(0, 32); + var rp = _decodepoint(rpe); + var a = _decodepoint(publicKey); + var s = _decodeint(signature.slice(32, 64)); + var h = _inthash(utils.bytes2string(rpe.concat(publicKey)) + message); + var v1 = _scalarmult(_bp, s); + var value = _scalarmultBytes(a, _bi2bytes(h)); + var v2 = _pt_add(rp, value); + return v1[0].equals(v2[0]) && v1[1].equals(v2[1]); + }; + + + /** + * Generates a new random private key seed of 32 bytes length (256 bit). + * + * @function + * @returns {string} + * Byte string containing a new random private key seed. + */ + ns.generateKeySeed = function() { + return core.generateKey(false); + }; + +module.exports = ns; diff --git a/hm_sunwell/node_modules/jodid25519/lib/utils.js b/hm_sunwell/node_modules/jodid25519/lib/utils.js new file mode 100644 index 0000000..c795231 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/lib/utils.js @@ -0,0 +1,198 @@ +"use strict"; +/** + * @fileOverview + * A collection of general utility functions.. + */ + +/* + * Copyright (c) 2011, 2012, 2014 Ron Garret + * Copyright (c) 2007, 2013, 2014 Michele Bini + * Copyright (c) 2014 Mega Limited + * under the MIT License. + * + * Authors: Guy K. Kloss, Michele Bini, Ron Garret + * + * You should have received a copy of the license along with this program. + */ + +var core = require('./core'); + + /** + * @exports jodid25519/utils + * A collection of general utility functions.. + * + * @description + * A collection of general utility functions.. + */ + var ns = {}; + + var _HEXCHARS = "0123456789abcdef"; + + function _hexencode(vector) { + var result = []; + for (var i = vector.length - 1; i >= 0; i--) { + var value = vector[i]; + result.push(_HEXCHARS.substr((value >>> 12) & 0x0f, 1)); + result.push(_HEXCHARS.substr((value >>> 8) & 0x0f, 1)); + result.push(_HEXCHARS.substr((value >>> 4) & 0x0f, 1)); + result.push(_HEXCHARS.substr(value & 0x0f, 1)); + } + return result.join(''); + } + + function _hexdecode(vector) { + var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (var i = vector.length - 1, l = 0; i >= 0; i -= 4) { + result[l] = (_HEXCHARS.indexOf(vector.charAt(i))) + | (_HEXCHARS.indexOf(vector.charAt(i - 1)) << 4) + | (_HEXCHARS.indexOf(vector.charAt(i - 2)) << 8) + | (_HEXCHARS.indexOf(vector.charAt(i - 3)) << 12); + l++; + } + return result; + } + + var _BASE32CHARS = "abcdefghijklmnopqrstuvwxyz234567"; + + var _BASE32VALUES = (function () { + var result = {}; + for (var i = 0; i < _BASE32CHARS.length; i++) { + result[_BASE32CHARS.charAt(i)] = i; + } + return result; + })(); + + function _base32encode(n) { + var c; + var r = ""; + for (c = 0; c < 255; c += 5) { + r = _BASE32CHARS.substr(core.getbit(n, c) + + (core.getbit(n, c + 1) << 1) + + (core.getbit(n, c + 2) << 2) + + (core.getbit(n, c + 3) << 3) + + (core.getbit(n, c + 4) << 4), 1) + + r; + } + return r; + } + + function _base32decode(n) { + var c = 0; + var r = core.ZERO(); + var l = n.length; + for (c = 0; (l > 0) && (c < 255); c += 5) { + l--; + var v = _BASE32VALUES[n.substr(l, 1)]; + core.setbit(r, c, v & 1); + v >>= 1; + core.setbit(r, c + 1, v & 1); + v >>= 1; + core.setbit(r, c + 2, v & 1); + v >>= 1; + core.setbit(r, c + 3, v & 1); + v >>= 1; + core.setbit(r, c + 4, v & 1); + } + return r; + } + + function _map(f, l) { + var result = new Array(l.length); + for (var i = 0; i < l.length; i++) { + result[i] = f(l[i]); + } + return result; + } + + function _chr(n) { + return String.fromCharCode(n); + } + + function _ord(c) { + return c.charCodeAt(0); + } + + function _bytes2string(bytes) { + return _map(_chr, bytes).join(''); + } + + function _string2bytes(s) { + return _map(_ord, s); + } + + + // Expose some functions to the outside through this name space. + + /** + * Encodes an array of unsigned 8-bit integers to a hex string. + * + * @function + * @param vector {array} + * Array containing the byte values. + * @returns {string} + * String containing vector in a hexadecimal representation. + */ + ns.hexEncode = _hexencode; + + + /** + * Decodes a hex string to an array of unsigned 8-bit integers. + * + * @function + * @param vector {string} + * String containing vector in a hexadecimal representation. + * @returns {array} + * Array containing the byte values. + */ + ns.hexDecode = _hexdecode; + + + /** + * Encodes an array of unsigned 8-bit integers using base32 encoding. + * + * @function + * @param vector {array} + * Array containing the byte values. + * @returns {string} + * String containing vector in a hexadecimal representation. + */ + ns.base32encode = _base32encode; + + + /** + * Decodes a base32 encoded string to an array of unsigned 8-bit integers. + * + * @function + * @param vector {string} + * String containing vector in a hexadecimal representation. + * @returns {array} + * Array containing the byte values. + */ + ns.base32decode = _base32decode; + + + /** + * Converts an unsigned 8-bit integer array representation to a byte string. + * + * @function + * @param vector {array} + * Array containing the byte values. + * @returns {string} + * Byte string representation of vector. + */ + ns.bytes2string = _bytes2string; + + + /** + * Converts a byte string representation to an array of unsigned + * 8-bit integers. + * + * @function + * @param vector {array} + * Array containing the byte values. + * @returns {string} + * Byte string representation of vector. + */ + ns.string2bytes = _string2bytes; + +module.exports = ns; diff --git a/hm_sunwell/node_modules/jodid25519/package.json b/hm_sunwell/node_modules/jodid25519/package.json new file mode 100644 index 0000000..5f18398 --- /dev/null +++ b/hm_sunwell/node_modules/jodid25519/package.json @@ -0,0 +1,96 @@ +{ + "_args": [ + [ + "jodid25519@^1.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk" + ] + ], + "_from": "jodid25519@>=1.0.0 <2.0.0", + "_id": "jodid25519@1.0.2", + "_inCache": true, + "_installable": true, + "_location": "/jodid25519", + "_nodeVersion": "4.1.1", + "_npmUser": { + "email": "alex@cooperi.net", + "name": "arekinath" + }, + "_npmVersion": "2.14.4", + "_phantomChildren": {}, + "_requested": { + "name": "jodid25519", + "raw": "jodid25519@^1.0.0", + "rawSpec": "^1.0.0", + "scope": null, + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/sshpk" + ], + "_resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "_shasum": "06d4912255093419477d425633606e0e90782967", + "_shrinkwrap": null, + "_spec": "jodid25519@^1.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk", + "author": { + "name": "Michele Bini, Ron Garret, Guy K. Kloss" + }, + "bugs": { + "url": "https://github.com/meganz/jodid25519/issues" + }, + "dependencies": { + "jsbn": "~0.1.0" + }, + "description": "jodid25519 - Curve 25519-based cryptography", + "devDependencies": { + "almond": "~0.3.1", + "chai": "^3.0.0", + "dateformat": "~1.0.7-1.2.3", + "ibrik": "~2.0.0", + "istanbul": "~0.3.5", + "jsdoc": "<=3.3.0", + "mocha": "~2.0.1", + "sinon": "~1.10.3", + "sinon-chai": "^2.8.0" + }, + "directories": { + "doc": "doc", + "src": "src", + "test": "test" + }, + "dist": { + "shasum": "06d4912255093419477d425633606e0e90782967", + "tarball": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + }, + "gitHead": "a83b9fcf7fd3be4f27cd4a57817aff171c7cd918", + "homepage": "https://github.com/meganz/jodid25519", + "keywords": [ + "Curve25519", + "ECDH", + "ECDSA", + "Ed25519", + "EdDSA", + "encryption", + "signing" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "arekinath", + "email": "alex@cooperi.net" + } + ], + "name": "jodid25519", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/meganz/jodid25519.git" + }, + "scripts": { + "test": "mocha test/*_test.js" + }, + "version": "1.0.2" +} diff --git a/hm_sunwell/node_modules/js-yaml/CHANGELOG.md b/hm_sunwell/node_modules/js-yaml/CHANGELOG.md new file mode 100644 index 0000000..da9facb --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/CHANGELOG.md @@ -0,0 +1,402 @@ +3.6.1 / 2016-05-11 +------------------ + +- Fix output cut on a pipe, #286. + + +3.6.0 / 2016-04-16 +------------------ + +- Dumper rewrite, fix multiple bugs with trailing `\n`. + Big thanks to @aepsilon! +- Loader: fix leading/trailing newlines in block scalars, @aepsilon. + + +3.5.5 / 2016-03-17 +------------------ + +- Date parse fix: don't allow dates with on digit in month and day, #268. + + +3.5.4 / 2016-03-09 +------------------ + +- `noCompatMode` for dumper, to disable quoting YAML 1.1 values. + + +3.5.3 / 2016-02-11 +------------------ + +- Maintenance release. + + +3.5.2 / 2016-01-11 +------------------ + +- Maintenance: missed comma in bower config. + + +3.5.1 / 2016-01-11 +------------------ + +- Removed `inherit` dependency, #239. +- Better browserify workaround for esprima load. +- Demo rewrite. + + +3.5.0 / 2016-01-10 +------------------ + +- Dumper. Fold strings only, #217. +- Dumper. `norefs` option, to clone linked objects, #229. +- Loader. Throw a warning for duplicate keys, #166. +- Improved browserify support (mark `esprima` & `Buffer` excluded). + + +3.4.6 / 2015-11-26 +------------------ + +- Use standalone `inherit` to keep browserified files clear. + + +3.4.5 / 2015-11-23 +------------------ + +- Added `lineWidth` option to dumper. + + +3.4.4 / 2015-11-21 +------------------ + +- Fixed floats dump (missed dot for scientific format), #220. +- Allow non-printable characters inside quoted scalars, #192. + + +3.4.3 / 2015-10-10 +------------------ + +- Maintenance release - deps bump (esprima, argparse). + + +3.4.2 / 2015-09-09 +------------------ + +- Fixed serialization of duplicated entries in sequences, #205. + Thanks to @vogelsgesang. + + +3.4.1 / 2015-09-05 +------------------ + +- Fixed stacktrace handling in generated errors, for browsers (FF/IE). + + +3.4.0 / 2015-08-23 +------------------ + +- Fixed multiline keys dump, #197. Thanks to @tcr. +- Don't throw on warnongs anymore. Use `onWarning` option to catch. +- Throw error on unknown tags (was warning before). +- Fixed heading line breaks in some scalars (regression). +- Reworked internals of error class. + + +3.3.1 / 2015-05-13 +------------------ + +- Added `.sortKeys` dumper option, thanks to @rjmunro. +- Fixed astral characters support, #191. + + +3.3.0 / 2015-04-26 +------------------ + +- Significantly improved long strings formatting in dumper, thanks to @isaacs. +- Strip BOM if exists. + + +3.2.7 / 2015-02-19 +------------------ + +- Maintenance release. +- Updated dependencies. +- HISTORY.md -> CHANGELOG.md + + +3.2.6 / 2015-02-07 +------------------ + +- Fixed encoding of UTF-16 surrogate pairs. (e.g. "\U0001F431" CAT FACE). +- Fixed demo dates dump (#113, thanks to @Hypercubed). + + +3.2.5 / 2014-12-28 +------------------ + +- Fixed resolving of all built-in types on empty nodes. +- Fixed invalid warning on empty lines within quoted scalars and flow collections. +- Fixed bug: Tag on an empty node didn't resolve in some cases. + + +3.2.4 / 2014-12-19 +------------------ + +- Fixed resolving of !!null tag on an empty node. + + +3.2.3 / 2014-11-08 +------------------ + +- Implemented dumping of objects with circular and cross references. +- Partially fixed aliasing of constructed objects. (see issue #141 for details) + + +3.2.2 / 2014-09-07 +------------------ + +- Fixed infinite loop on unindented block scalars. +- Rewritten base64 encode/decode in binary type, to keep code licence clear. + + +3.2.1 / 2014-08-24 +------------------ + +- Nothig new. Just fix npm publish error. + + +3.2.0 / 2014-08-24 +------------------ + +- Added input piping support to CLI. +- Fixed typo, that could cause hand on initial indent (#139). + + +3.1.0 / 2014-07-07 +------------------ + +- 1.5x-2x speed boost. +- Removed deprecated `require('xxx.yml')` support. +- Significant code cleanup and refactoring. +- Internal API changed. If you used custom types - see updated examples. + Others are not affected. +- Even if the input string has no trailing line break character, + it will be parsed as if it has one. +- Added benchmark scripts. +- Moved bower files to /dist folder +- Bugfixes. + + +3.0.2 / 2014-02-27 +------------------ + +- Fixed bug: "constructor" string parsed as `null`. + + +3.0.1 / 2013-12-22 +------------------ + +- Fixed parsing of literal scalars. (issue #108) +- Prevented adding unnecessary spaces in object dumps. (issue #68) +- Fixed dumping of objects with very long (> 1024 in length) keys. + + +3.0.0 / 2013-12-16 +------------------ + +- Refactored code. Changed API for custom types. +- Removed output colors in CLI, dump json by default. +- Removed big dependencies from browser version (esprima, buffer) + - load `esprima` manually, if !!js/function needed + - !!bin now returns Array in browser +- AMD support. +- Don't quote dumped strings because of `-` & `?` (if not first char). +- __Deprecated__ loading yaml files via `require()`, as not recommended + behaviour for node. + + +2.1.3 / 2013-10-16 +------------------ + +- Fix wrong loading of empty block scalars. + + +2.1.2 / 2013-10-07 +------------------ + +- Fix unwanted line breaks in folded scalars. + + +2.1.1 / 2013-10-02 +------------------ + +- Dumper now respects deprecated booleans syntax from YAML 1.0/1.1 +- Fixed reader bug in JSON-like sequences/mappings. + + +2.1.0 / 2013-06-05 +------------------ + +- Add standard YAML schemas: Failsafe (`FAILSAFE_SCHEMA`), + JSON (`JSON_SCHEMA`) and Core (`CORE_SCHEMA`). +- Rename `DEFAULT_SCHEMA` to `DEFAULT_FULL_SCHEMA` + and `SAFE_SCHEMA` to `DEFAULT_SAFE_SCHEMA`. +- Bug fix: export `NIL` constant from the public interface. +- Add `skipInvalid` dumper option. +- Use `safeLoad` for `require` extension. + + +2.0.5 / 2013-04-26 +------------------ + +- Close security issue in !!js/function constructor. + Big thanks to @nealpoole for security audit. + + +2.0.4 / 2013-04-08 +------------------ + +- Updated .npmignore to reduce package size + + +2.0.3 / 2013-02-26 +------------------ + +- Fixed dumping of empty arrays ans objects. ([] and {} instead of null) + + +2.0.2 / 2013-02-15 +------------------ + +- Fixed input validation: tabs are printable characters. + + +2.0.1 / 2013-02-09 +------------------ + +- Fixed error, when options not passed to function cass + + +2.0.0 / 2013-02-09 +------------------ + +- Full rewrite. New architecture. Fast one-stage parsing. +- Changed custom types API. +- Added YAML dumper. + + +1.0.3 / 2012-11-05 +------------------ + +- Fixed utf-8 files loading. + + +1.0.2 / 2012-08-02 +------------------ + +- Pull out hand-written shims. Use ES5-Shims for old browsers support. See #44. +- Fix timstamps incorectly parsed in local time when no time part specified. + + +1.0.1 / 2012-07-07 +------------------ + +- Fixes `TypeError: 'undefined' is not an object` under Safari. Thanks Phuong. +- Fix timestamps incorrectly parsed in local time. Thanks @caolan. Closes #46. + + +1.0.0 / 2012-07-01 +------------------ + +- `y`, `yes`, `n`, `no`, `on`, `off` are not converted to Booleans anymore. + Fixes #42. +- `require(filename)` now returns a single document and throws an Error if + file contains more than one document. +- CLI was merged back from js-yaml.bin + + +0.3.7 / 2012-02-28 +------------------ + +- Fix export of `addConstructor()`. Closes #39. + + +0.3.6 / 2012-02-22 +------------------ + +- Removed AMD parts - too buggy to use. Need help to rewrite from scratch +- Removed YUI compressor warning (renamed `double` variable). Closes #40. + + +0.3.5 / 2012-01-10 +------------------ + +- Workagound for .npmignore fuckup under windows. Thanks to airportyh. + + +0.3.4 / 2011-12-24 +------------------ + +- Fixes str[] for oldIEs support. +- Adds better has change support for browserified demo. +- improves compact output of Error. Closes #33. + + +0.3.3 / 2011-12-20 +------------------ + +- jsyaml executable moved to separate module. +- adds `compact` stringification of Errors. + + +0.3.2 / 2011-12-16 +------------------ + +- Fixes ug with block style scalars. Closes #26. +- All sources are passing JSLint now. +- Fixes bug in Safari. Closes #28. +- Fixes bug in Opers. Closes #29. +- Improves browser support. Closes #20. +- Added jsyaml executable. +- Added !!js/function support. Closes #12. + + +0.3.1 / 2011-11-18 +------------------ + +- Added AMD support for browserified version. +- Wrapped browserified js-yaml into closure. +- Fixed the resolvement of non-specific tags. Closes #17. +- Added permalinks for online demo YAML snippets. Now we have YPaste service, lol. +- Added !!js/regexp and !!js/undefined types. Partially solves #12. +- Fixed !!set mapping. +- Fixed month parse in dates. Closes #19. + + +0.3.0 / 2011-11-09 +------------------ + +- Removed JS.Class dependency. Closes #3. +- Added browserified version. Closes #13. +- Added live demo of browserified version. +- Ported some of the PyYAML tests. See #14. +- Fixed timestamp bug when fraction was given. + + +0.2.2 / 2011-11-06 +------------------ + +- Fixed crash on docs without ---. Closes #8. +- Fixed miltiline string parse +- Fixed tests/comments for using array as key + + +0.2.1 / 2011-11-02 +------------------ + +- Fixed short file read (<4k). Closes #9. + + +0.2.0 / 2011-11-02 +------------------ + +- First public release diff --git a/hm_sunwell/node_modules/js-yaml/LICENSE b/hm_sunwell/node_modules/js-yaml/LICENSE new file mode 100644 index 0000000..09d3a29 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/LICENSE @@ -0,0 +1,21 @@ +(The MIT License) + +Copyright (C) 2011-2015 by Vitaly Puzrin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/js-yaml/README.md b/hm_sunwell/node_modules/js-yaml/README.md new file mode 100644 index 0000000..45c3502 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/README.md @@ -0,0 +1,295 @@ +JS-YAML - YAML 1.2 parser / writer for JavaScript +================================================= + +[![Build Status](https://travis-ci.org/nodeca/js-yaml.svg?branch=master)](https://travis-ci.org/nodeca/js-yaml) +[![NPM version](https://img.shields.io/npm/v/js-yaml.svg)](https://www.npmjs.org/package/js-yaml) + +__[Online Demo](http://nodeca.github.com/js-yaml/)__ + + +This is an implementation of [YAML](http://yaml.org/), a human friendly data +serialization language. Started as [PyYAML](http://pyyaml.org/) port, it was +completely rewritten from scratch. Now it's very fast, and supports 1.2 spec. + + +Installation +------------ + +### YAML module for node.js + +``` +npm install js-yaml +``` + + +### CLI executable + +If you want to inspect your YAML files from CLI, install js-yaml globally: + +``` +npm install -g js-yaml +``` + +#### Usage + +``` +usage: js-yaml [-h] [-v] [-c] [-t] file + +Positional arguments: + file File with YAML document(s) + +Optional arguments: + -h, --help Show this help message and exit. + -v, --version Show program's version number and exit. + -c, --compact Display errors in compact mode + -t, --trace Show stack trace on error +``` + + +### Bundled YAML library for browsers + +``` html + + + + +``` + +Browser support was done mostly for online demo. If you find any errors - feel +free to send pull requests with fixes. Also note, that IE and other old browsers +needs [es5-shims](https://github.com/kriskowal/es5-shim) to operate. + +Notes: + +1. We have no resources to support browserified version. Don't expect it to be + well tested. Don't expect fast fixes if something goes wrong there. +2. `!!js/function` in browser bundle will not work by default. If you really need + it - load `esprima` parser first (via amd or directly). +3. `!!bin` in browser will return `Array`, because browsers do not support + node.js `Buffer` and adding Buffer shims is completely useless on practice. + + +API +--- + +Here we cover the most 'useful' methods. If you need advanced details (creating +your own tags), see [wiki](https://github.com/nodeca/js-yaml/wiki) and +[examples](https://github.com/nodeca/js-yaml/tree/master/examples) for more +info. + +``` javascript +yaml = require('js-yaml'); +fs = require('fs'); + +// Get document, or throw exception on error +try { + var doc = yaml.safeLoad(fs.readFileSync('/home/ixti/example.yml', 'utf8')); + console.log(doc); +} catch (e) { + console.log(e); +} +``` + + +### safeLoad (string [ , options ]) + +**Recommended loading way.** Parses `string` as single YAML document. Returns a JavaScript +object or throws `YAMLException` on error. By default, does not support regexps, +functions and undefined. This method is safe for untrusted data. + +options: + +- `filename` _(default: null)_ - string to be used as a file path in + error/warning messages. +- `onWarning` _(default: null)_ - function to call on warning messages. + Loader will throw on warnings if this function is not provided. +- `schema` _(default: `DEFAULT_SAFE_SCHEMA`)_ - specifies a schema to use. + - `FAILSAFE_SCHEMA` - only strings, arrays and plain objects: + http://www.yaml.org/spec/1.2/spec.html#id2802346 + - `JSON_SCHEMA` - all JSON-supported types: + http://www.yaml.org/spec/1.2/spec.html#id2803231 + - `CORE_SCHEMA` - same as `JSON_SCHEMA`: + http://www.yaml.org/spec/1.2/spec.html#id2804923 + - `DEFAULT_SAFE_SCHEMA` - all supported YAML types, without unsafe ones + (`!!js/undefined`, `!!js/regexp` and `!!js/function`): + http://yaml.org/type/ + - `DEFAULT_FULL_SCHEMA` - all supported YAML types. +- `json` _(default: false)_ - compatibility with JSON.parse behaviour. If true, then duplicate keys in a mapping will override values rather than throwing an error. + +NOTE: This function **does not** understand multi-document sources, it throws +exception on those. + +NOTE: JS-YAML **does not** support schema-specific tag resolution restrictions. +So, JSON schema is not as strict as defined in the YAML specification. +It allows numbers in any notation, use `Null` and `NULL` as `null`, etc. +Core schema also has no such restrictions. It allows binary notation for integers. + + +### load (string [ , options ]) + +**Use with care with untrusted sources**. The same as `safeLoad()` but uses +`DEFAULT_FULL_SCHEMA` by default - adds some JavaScript-specific types: +`!!js/function`, `!!js/regexp` and `!!js/undefined`. For untrusted sources you +must additionally validate object structure, to avoid injections: + +``` javascript +var untrusted_code = '"toString": ! "function (){very_evil_thing();}"'; + +// I'm just converting that string, what could possibly go wrong? +require('js-yaml').load(untrusted_code) + '' +``` + + +### safeLoadAll (string, iterator [ , options ]) + +Same as `safeLoad()`, but understands multi-document sources and apply +`iterator` to each document. + +``` javascript +var yaml = require('js-yaml'); + +yaml.safeLoadAll(data, function (doc) { + console.log(doc); +}); +``` + + +### loadAll (string, iterator [ , options ]) + +Same as `safeLoadAll()` but uses `DEFAULT_FULL_SCHEMA` by default. + + +### safeDump (object [ , options ]) + +Serializes `object` as YAML document. Uses `DEFAULT_SAFE_SCHEMA`, so it will +throw exception if you try to dump regexps or functions. However, you can +disable exceptions by `skipInvalid` option. + +options: + +- `indent` _(default: 2)_ - indentation width to use (in spaces). +- `skipInvalid` _(default: false)_ - do not throw on invalid types (like function + in the safe schema) and skip pairs and single values with such types. +- `flowLevel` (default: -1) - specifies level of nesting, when to switch from + block to flow style for collections. -1 means block style everwhere +- `styles` - "tag" => "style" map. Each tag may have own set of styles. +- `schema` _(default: `DEFAULT_SAFE_SCHEMA`)_ specifies a schema to use. +- `sortKeys` _(default: `false`)_ - if `true`, sort keys when dumping YAML. If a + function, use the function to sort the keys. +- `lineWidth` _(default: `80`)_ - set max line width. +- `noRefs` _(default: `false`)_ - if `true`, don't convert duplicate objects into references +- `noCompatMode` _(default: `false`)_ - if `true` don't try to be compatible with older + yaml versions. Currently: don't quote "yes", "no" and so on, as required for YAML 1.1 + +styles: + +``` none +!!null + "canonical" => "~" + +!!int + "binary" => "0b1", "0b101010", "0b1110001111010" + "octal" => "01", "052", "016172" + "decimal" => "1", "42", "7290" + "hexadecimal" => "0x1", "0x2A", "0x1C7A" + +!!null, !!bool, !!float + "lowercase" => "null", "true", "false", ".nan", '.inf' + "uppercase" => "NULL", "TRUE", "FALSE", ".NAN", '.INF' + "camelcase" => "Null", "True", "False", ".NaN", '.Inf' +``` + +By default, !!int uses `decimal`, and !!null, !!bool, !!float use `lowercase`. + + + +### dump (object [ , options ]) + +Same as `safeDump()` but without limits (uses `DEFAULT_FULL_SCHEMA` by default). + + +Supported YAML types +-------------------- + +The list of standard YAML tags and corresponding JavaScipt types. See also +[YAML tag discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and +[YAML types repository](http://yaml.org/type/). + +``` +!!null '' # null +!!bool 'yes' # bool +!!int '3...' # number +!!float '3.14...' # number +!!binary '...base64...' # buffer +!!timestamp 'YYYY-...' # date +!!omap [ ... ] # array of key-value pairs +!!pairs [ ... ] # array or array pairs +!!set { ... } # array of objects with given keys and null values +!!str '...' # string +!!seq [ ... ] # array +!!map { ... } # object +``` + +**JavaScript-specific tags** + +``` +!!js/regexp /pattern/gim # RegExp +!!js/undefined '' # Undefined +!!js/function 'function () {...}' # Function +``` + +Caveats +------- + +Note, that you use arrays or objects as key in JS-YAML. JS does not allow objects +or array as keys, and stringifies (by calling .toString method) them at the +moment of adding them. + +``` yaml +--- +? [ foo, bar ] +: - baz +? { foo: bar } +: - baz + - baz +``` + +``` javascript +{ "foo,bar": ["baz"], "[object Object]": ["baz", "baz"] } +``` + +Also, reading of properties on implicit block mapping keys is not supported yet. +So, the following YAML document cannot be loaded. + +``` yaml +&anchor foo: + foo: bar + *anchor: duplicate key + baz: bat + *anchor: duplicate key +``` + + +Breaking changes in 2.x.x -> 3.x.x +---------------------------------- + +If you have not used __custom__ tags or loader classes and not loaded yaml +files via `require()` - no changes needed. Just upgrade library. + +Otherwise, you should: + +1. Replace all occurences of `require('xxxx.yml')` by `fs.readFileSync()` + + `yaml.safeLoad()`. +2. rewrite your custom tags constructors and custom loader + classes, to conform new API. See + [examples](https://github.com/nodeca/js-yaml/tree/master/examples) and + [wiki](https://github.com/nodeca/js-yaml/wiki) for details. + + +License +------- + +View the [LICENSE](https://github.com/nodeca/js-yaml/blob/master/LICENSE) file +(MIT). diff --git a/hm_sunwell/node_modules/js-yaml/bin/js-yaml.js b/hm_sunwell/node_modules/js-yaml/bin/js-yaml.js new file mode 100644 index 0000000..e79186b --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/bin/js-yaml.js @@ -0,0 +1,132 @@ +#!/usr/bin/env node + + +'use strict'; + +/*eslint-disable no-console*/ + + +// stdlib +var fs = require('fs'); + + +// 3rd-party +var argparse = require('argparse'); + + +// internal +var yaml = require('..'); + + +//////////////////////////////////////////////////////////////////////////////// + + +var cli = new argparse.ArgumentParser({ + prog: 'js-yaml', + version: require('../package.json').version, + addHelp: true +}); + + +cli.addArgument([ '-c', '--compact' ], { + help: 'Display errors in compact mode', + action: 'storeTrue' +}); + + +// deprecated (not needed after we removed output colors) +// option suppressed, but not completely removed for compatibility +cli.addArgument([ '-j', '--to-json' ], { + help: argparse.Const.SUPPRESS, + dest: 'json', + action: 'storeTrue' +}); + + +cli.addArgument([ '-t', '--trace' ], { + help: 'Show stack trace on error', + action: 'storeTrue' +}); + +cli.addArgument([ 'file' ], { + help: 'File to read, utf-8 encoded without BOM', + nargs: '?', + defaultValue: '-' +}); + + +//////////////////////////////////////////////////////////////////////////////// + + +var options = cli.parseArgs(); + + +//////////////////////////////////////////////////////////////////////////////// + +function readFile(filename, encoding, callback) { + if (options.file === '-') { + // read from stdin + + var chunks = []; + + process.stdin.on('data', function (chunk) { + chunks.push(chunk); + }); + + process.stdin.on('end', function () { + return callback(null, Buffer.concat(chunks).toString(encoding)); + }); + } else { + fs.readFile(filename, encoding, callback); + } +} + +readFile(options.file, 'utf8', function (error, input) { + var output, isYaml; + + if (error) { + if (error.code === 'ENOENT') { + console.error('File not found: ' + options.file); + process.exit(2); + } + + console.error( + options.trace && error.stack || + error.message || + String(error)); + + process.exit(1); + } + + try { + output = JSON.parse(input); + isYaml = false; + } catch (err) { + if (err instanceof SyntaxError) { + try { + output = []; + yaml.loadAll(input, function (doc) { output.push(doc); }, {}); + isYaml = true; + + if (output.length === 0) output = null; + else if (output.length === 1) output = output[0]; + + } catch (e) { + if (options.trace && err.stack) console.error(e.stack); + else console.error(e.toString(options.compact)); + + process.exit(1); + } + } else { + console.error( + options.trace && err.stack || + err.message || + String(err)); + + process.exit(1); + } + } + + if (isYaml) console.log(JSON.stringify(output, null, ' ')); + else console.log(yaml.dump(output)); +}); diff --git a/hm_sunwell/node_modules/js-yaml/dist/js-yaml.js b/hm_sunwell/node_modules/js-yaml/dist/js-yaml.js new file mode 100644 index 0000000..f7e893e --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/dist/js-yaml.js @@ -0,0 +1,3851 @@ +/* js-yaml 3.6.1 https://github.com/nodeca/js-yaml */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jsyaml = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o */ +var CHAR_QUESTION = 0x3F; /* ? */ +var CHAR_COMMERCIAL_AT = 0x40; /* @ */ +var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */ +var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */ +var CHAR_GRAVE_ACCENT = 0x60; /* ` */ +var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */ +var CHAR_VERTICAL_LINE = 0x7C; /* | */ +var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */ + +var ESCAPE_SEQUENCES = {}; + +ESCAPE_SEQUENCES[0x00] = '\\0'; +ESCAPE_SEQUENCES[0x07] = '\\a'; +ESCAPE_SEQUENCES[0x08] = '\\b'; +ESCAPE_SEQUENCES[0x09] = '\\t'; +ESCAPE_SEQUENCES[0x0A] = '\\n'; +ESCAPE_SEQUENCES[0x0B] = '\\v'; +ESCAPE_SEQUENCES[0x0C] = '\\f'; +ESCAPE_SEQUENCES[0x0D] = '\\r'; +ESCAPE_SEQUENCES[0x1B] = '\\e'; +ESCAPE_SEQUENCES[0x22] = '\\"'; +ESCAPE_SEQUENCES[0x5C] = '\\\\'; +ESCAPE_SEQUENCES[0x85] = '\\N'; +ESCAPE_SEQUENCES[0xA0] = '\\_'; +ESCAPE_SEQUENCES[0x2028] = '\\L'; +ESCAPE_SEQUENCES[0x2029] = '\\P'; + +var DEPRECATED_BOOLEANS_SYNTAX = [ + 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON', + 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF' +]; + +function compileStyleMap(schema, map) { + var result, keys, index, length, tag, style, type; + + if (map === null) return {}; + + result = {}; + keys = Object.keys(map); + + for (index = 0, length = keys.length; index < length; index += 1) { + tag = keys[index]; + style = String(map[tag]); + + if (tag.slice(0, 2) === '!!') { + tag = 'tag:yaml.org,2002:' + tag.slice(2); + } + + type = schema.compiledTypeMap[tag]; + + if (type && _hasOwnProperty.call(type.styleAliases, style)) { + style = type.styleAliases[style]; + } + + result[tag] = style; + } + + return result; +} + +function encodeHex(character) { + var string, handle, length; + + string = character.toString(16).toUpperCase(); + + if (character <= 0xFF) { + handle = 'x'; + length = 2; + } else if (character <= 0xFFFF) { + handle = 'u'; + length = 4; + } else if (character <= 0xFFFFFFFF) { + handle = 'U'; + length = 8; + } else { + throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF'); + } + + return '\\' + handle + common.repeat('0', length - string.length) + string; +} + +function State(options) { + this.schema = options['schema'] || DEFAULT_FULL_SCHEMA; + this.indent = Math.max(1, (options['indent'] || 2)); + this.skipInvalid = options['skipInvalid'] || false; + this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']); + this.styleMap = compileStyleMap(this.schema, options['styles'] || null); + this.sortKeys = options['sortKeys'] || false; + this.lineWidth = options['lineWidth'] || 80; + this.noRefs = options['noRefs'] || false; + this.noCompatMode = options['noCompatMode'] || false; + + this.implicitTypes = this.schema.compiledImplicit; + this.explicitTypes = this.schema.compiledExplicit; + + this.tag = null; + this.result = ''; + + this.duplicates = []; + this.usedDuplicates = null; +} + +// Indents every line in a string. Empty lines (\n only) are not indented. +function indentString(string, spaces) { + var ind = common.repeat(' ', spaces), + position = 0, + next = -1, + result = '', + line, + length = string.length; + + while (position < length) { + next = string.indexOf('\n', position); + if (next === -1) { + line = string.slice(position); + position = length; + } else { + line = string.slice(position, next + 1); + position = next + 1; + } + + if (line.length && line !== '\n') result += ind; + + result += line; + } + + return result; +} + +function generateNextLine(state, level) { + return '\n' + common.repeat(' ', state.indent * level); +} + +function testImplicitResolving(state, str) { + var index, length, type; + + for (index = 0, length = state.implicitTypes.length; index < length; index += 1) { + type = state.implicitTypes[index]; + + if (type.resolve(str)) { + return true; + } + } + + return false; +} + +// [33] s-white ::= s-space | s-tab +function isWhitespace(c) { + return c === CHAR_SPACE || c === CHAR_TAB; +} + +// Returns true if the character can be printed without escaping. +// From YAML 1.2: "any allowed characters known to be non-printable +// should also be escaped. [However,] This isn’t mandatory" +// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029. +function isPrintable(c) { + return (0x00020 <= c && c <= 0x00007E) + || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) + || ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */) + || (0x10000 <= c && c <= 0x10FFFF); +} + +// Simplified test for values allowed after the first character in plain style. +function isPlainSafe(c) { + // Uses a subset of nb-char - c-flow-indicator - ":" - "#" + // where nb-char ::= c-printable - b-char - c-byte-order-mark. + return isPrintable(c) && c !== 0xFEFF + // - c-flow-indicator + && c !== CHAR_COMMA + && c !== CHAR_LEFT_SQUARE_BRACKET + && c !== CHAR_RIGHT_SQUARE_BRACKET + && c !== CHAR_LEFT_CURLY_BRACKET + && c !== CHAR_RIGHT_CURLY_BRACKET + // - ":" - "#" + && c !== CHAR_COLON + && c !== CHAR_SHARP; +} + +// Simplified test for values allowed as the first character in plain style. +function isPlainSafeFirst(c) { + // Uses a subset of ns-char - c-indicator + // where ns-char = nb-char - s-white. + return isPrintable(c) && c !== 0xFEFF + && !isWhitespace(c) // - s-white + // - (c-indicator ::= + // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}” + && c !== CHAR_MINUS + && c !== CHAR_QUESTION + && c !== CHAR_COLON + && c !== CHAR_COMMA + && c !== CHAR_LEFT_SQUARE_BRACKET + && c !== CHAR_RIGHT_SQUARE_BRACKET + && c !== CHAR_LEFT_CURLY_BRACKET + && c !== CHAR_RIGHT_CURLY_BRACKET + // | “#” | “&” | “*” | “!” | “|” | “>” | “'” | “"” + && c !== CHAR_SHARP + && c !== CHAR_AMPERSAND + && c !== CHAR_ASTERISK + && c !== CHAR_EXCLAMATION + && c !== CHAR_VERTICAL_LINE + && c !== CHAR_GREATER_THAN + && c !== CHAR_SINGLE_QUOTE + && c !== CHAR_DOUBLE_QUOTE + // | “%” | “@” | “`”) + && c !== CHAR_PERCENT + && c !== CHAR_COMMERCIAL_AT + && c !== CHAR_GRAVE_ACCENT; +} + +var STYLE_PLAIN = 1, + STYLE_SINGLE = 2, + STYLE_LITERAL = 3, + STYLE_FOLDED = 4, + STYLE_DOUBLE = 5; + +// Determines which scalar styles are possible and returns the preferred style. +// lineWidth = -1 => no limit. +// Pre-conditions: str.length > 0. +// Post-conditions: +// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string. +// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1). +// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1). +function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) { + var i; + var char; + var hasLineBreak = false; + var hasFoldableLine = false; // only checked if shouldTrackWidth + var shouldTrackWidth = lineWidth !== -1; + var previousLineBreak = -1; // count the first line correctly + var plain = isPlainSafeFirst(string.charCodeAt(0)) + && !isWhitespace(string.charCodeAt(string.length - 1)); + + if (singleLineOnly) { + // Case: no block styles. + // Check for disallowed characters to rule out plain and single. + for (i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + if (!isPrintable(char)) { + return STYLE_DOUBLE; + } + plain = plain && isPlainSafe(char); + } + } else { + // Case: block styles permitted. + for (i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + if (char === CHAR_LINE_FEED) { + hasLineBreak = true; + // Check if any line can be folded. + if (shouldTrackWidth) { + hasFoldableLine = hasFoldableLine || + // Foldable line = too long, and not more-indented. + (i - previousLineBreak - 1 > lineWidth && + string[previousLineBreak + 1] !== ' '); + previousLineBreak = i; + } + } else if (!isPrintable(char)) { + return STYLE_DOUBLE; + } + plain = plain && isPlainSafe(char); + } + // in case the end is missing a \n + hasFoldableLine = hasFoldableLine || (shouldTrackWidth && + (i - previousLineBreak - 1 > lineWidth && + string[previousLineBreak + 1] !== ' ')); + } + // Although every style can represent \n without escaping, prefer block styles + // for multiline, since they're more readable and they don't add empty lines. + // Also prefer folding a super-long line. + if (!hasLineBreak && !hasFoldableLine) { + // Strings interpretable as another type have to be quoted; + // e.g. the string 'true' vs. the boolean true. + return plain && !testAmbiguousType(string) + ? STYLE_PLAIN : STYLE_SINGLE; + } + // Edge case: block indentation indicator can only have one digit. + if (string[0] === ' ' && indentPerLevel > 9) { + return STYLE_DOUBLE; + } + // At this point we know block styles are valid. + // Prefer literal style unless we want to fold. + return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL; +} + +// Note: line breaking/folding is implemented for only the folded style. +// NB. We drop the last trailing newline (if any) of a returned block scalar +// since the dumper adds its own newline. This always works: +// • No ending newline => unaffected; already using strip "-" chomping. +// • Ending newline => removed then restored. +// Importantly, this keeps the "+" chomp indicator from gaining an extra line. +function writeScalar(state, string, level, iskey) { + state.dump = (function () { + if (string.length === 0) { + return "''"; + } + if (!state.noCompatMode && + DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) { + return "'" + string + "'"; + } + + var indent = state.indent * Math.max(1, level); // no 0-indent scalars + // As indentation gets deeper, let the width decrease monotonically + // to the lower bound min(state.lineWidth, 40). + // Note that this implies + // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound. + // state.lineWidth > 40 + state.indent: width decreases until the lower bound. + // This behaves better than a constant minimum width which disallows narrower options, + // or an indent threshold which causes the width to suddenly increase. + var lineWidth = state.lineWidth === -1 + ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent); + + // Without knowing if keys are implicit/explicit, assume implicit for safety. + var singleLineOnly = iskey + // No block styles in flow mode. + || (state.flowLevel > -1 && level >= state.flowLevel); + function testAmbiguity(string) { + return testImplicitResolving(state, string); + } + + switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) { + case STYLE_PLAIN: + return string; + case STYLE_SINGLE: + return "'" + string.replace(/'/g, "''") + "'"; + case STYLE_LITERAL: + return '|' + blockHeader(string, state.indent) + + dropEndingNewline(indentString(string, indent)); + case STYLE_FOLDED: + return '>' + blockHeader(string, state.indent) + + dropEndingNewline(indentString(foldString(string, lineWidth), indent)); + case STYLE_DOUBLE: + return '"' + escapeString(string, lineWidth) + '"'; + default: + throw new YAMLException('impossible error: invalid scalar style'); + } + }()); +} + +// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9. +function blockHeader(string, indentPerLevel) { + var indentIndicator = (string[0] === ' ') ? String(indentPerLevel) : ''; + + // note the special case: the string '\n' counts as a "trailing" empty line. + var clip = string[string.length - 1] === '\n'; + var keep = clip && (string[string.length - 2] === '\n' || string === '\n'); + var chomp = keep ? '+' : (clip ? '' : '-'); + + return indentIndicator + chomp + '\n'; +} + +// (See the note for writeScalar.) +function dropEndingNewline(string) { + return string[string.length - 1] === '\n' ? string.slice(0, -1) : string; +} + +// Note: a long line without a suitable break point will exceed the width limit. +// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0. +function foldString(string, width) { + // In folded style, $k$ consecutive newlines output as $k+1$ newlines— + // unless they're before or after a more-indented line, or at the very + // beginning or end, in which case $k$ maps to $k$. + // Therefore, parse each chunk as newline(s) followed by a content line. + var lineRe = /(\n+)([^\n]*)/g; + + // first line (possibly an empty line) + var result = (function () { + var nextLF = string.indexOf('\n'); + nextLF = nextLF !== -1 ? nextLF : string.length; + lineRe.lastIndex = nextLF; + return foldLine(string.slice(0, nextLF), width); + }()); + // If we haven't reached the first content line yet, don't add an extra \n. + var prevMoreIndented = string[0] === '\n' || string[0] === ' '; + var moreIndented; + + // rest of the lines + var match; + while ((match = lineRe.exec(string))) { + var prefix = match[1], line = match[2]; + moreIndented = (line[0] === ' '); + result += prefix + + (!prevMoreIndented && !moreIndented && line !== '' + ? '\n' : '') + + foldLine(line, width); + prevMoreIndented = moreIndented; + } + + return result; +} + +// Greedy line breaking. +// Picks the longest line under the limit each time, +// otherwise settles for the shortest line over the limit. +// NB. More-indented lines *cannot* be folded, as that would add an extra \n. +function foldLine(line, width) { + if (line === '' || line[0] === ' ') return line; + + // Since a more-indented line adds a \n, breaks can't be followed by a space. + var breakRe = / [^ ]/g; // note: the match index will always be <= length-2. + var match; + // start is an inclusive index. end, curr, and next are exclusive. + var start = 0, end, curr = 0, next = 0; + var result = ''; + + // Invariants: 0 <= start <= length-1. + // 0 <= curr <= next <= max(0, length-2). curr - start <= width. + // Inside the loop: + // A match implies length >= 2, so curr and next are <= length-2. + while ((match = breakRe.exec(line))) { + next = match.index; + // maintain invariant: curr - start <= width + if (next - start > width) { + end = (curr > start) ? curr : next; // derive end <= length-2 + result += '\n' + line.slice(start, end); + // skip the space that was output as \n + start = end + 1; // derive start <= length-1 + } + curr = next; + } + + // By the invariants, start <= length-1, so there is something left over. + // It is either the whole string or a part starting from non-whitespace. + result += '\n'; + // Insert a break if the remainder is too long and there is a break available. + if (line.length - start > width && curr > start) { + result += line.slice(start, curr) + '\n' + line.slice(curr + 1); + } else { + result += line.slice(start); + } + + return result.slice(1); // drop extra \n joiner +} + +// Escapes a double-quoted string. +function escapeString(string) { + var result = ''; + var char; + var escapeSeq; + + for (var i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + escapeSeq = ESCAPE_SEQUENCES[char]; + result += !escapeSeq && isPrintable(char) + ? string[i] + : escapeSeq || encodeHex(char); + } + + return result; +} + +function writeFlowSequence(state, level, object) { + var _result = '', + _tag = state.tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + // Write only valid elements. + if (writeNode(state, level, object[index], false, false)) { + if (index !== 0) _result += ', '; + _result += state.dump; + } + } + + state.tag = _tag; + state.dump = '[' + _result + ']'; +} + +function writeBlockSequence(state, level, object, compact) { + var _result = '', + _tag = state.tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + // Write only valid elements. + if (writeNode(state, level + 1, object[index], true, true)) { + if (!compact || index !== 0) { + _result += generateNextLine(state, level); + } + _result += '- ' + state.dump; + } + } + + state.tag = _tag; + state.dump = _result || '[]'; // Empty sequence if no valid values. +} + +function writeFlowMapping(state, level, object) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + pairBuffer; + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (index !== 0) pairBuffer += ', '; + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (!writeNode(state, level, objectKey, false, false)) { + continue; // Skip this pair because of invalid key; + } + + if (state.dump.length > 1024) pairBuffer += '? '; + + pairBuffer += state.dump + ': '; + + if (!writeNode(state, level, objectValue, false, false)) { + continue; // Skip this pair because of invalid value. + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = '{' + _result + '}'; +} + +function writeBlockMapping(state, level, object, compact) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + explicitPair, + pairBuffer; + + // Allow sorting keys so that the output file is deterministic + if (state.sortKeys === true) { + // Default sorting + objectKeyList.sort(); + } else if (typeof state.sortKeys === 'function') { + // Custom sort function + objectKeyList.sort(state.sortKeys); + } else if (state.sortKeys) { + // Something is wrong + throw new YAMLException('sortKeys must be a boolean or a function'); + } + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (!compact || index !== 0) { + pairBuffer += generateNextLine(state, level); + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (!writeNode(state, level + 1, objectKey, true, true, true)) { + continue; // Skip this pair because of invalid key. + } + + explicitPair = (state.tag !== null && state.tag !== '?') || + (state.dump && state.dump.length > 1024); + + if (explicitPair) { + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += '?'; + } else { + pairBuffer += '? '; + } + } + + pairBuffer += state.dump; + + if (explicitPair) { + pairBuffer += generateNextLine(state, level); + } + + if (!writeNode(state, level + 1, objectValue, true, explicitPair)) { + continue; // Skip this pair because of invalid value. + } + + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += ':'; + } else { + pairBuffer += ': '; + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = _result || '{}'; // Empty mapping if no valid pairs. +} + +function detectType(state, object, explicit) { + var _result, typeList, index, length, type, style; + + typeList = explicit ? state.explicitTypes : state.implicitTypes; + + for (index = 0, length = typeList.length; index < length; index += 1) { + type = typeList[index]; + + if ((type.instanceOf || type.predicate) && + (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) && + (!type.predicate || type.predicate(object))) { + + state.tag = explicit ? type.tag : '?'; + + if (type.represent) { + style = state.styleMap[type.tag] || type.defaultStyle; + + if (_toString.call(type.represent) === '[object Function]') { + _result = type.represent(object, style); + } else if (_hasOwnProperty.call(type.represent, style)) { + _result = type.represent[style](object, style); + } else { + throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style'); + } + + state.dump = _result; + } + + return true; + } + } + + return false; +} + +// Serializes `object` and writes it to global `result`. +// Returns true on success, or false on invalid object. +// +function writeNode(state, level, object, block, compact, iskey) { + state.tag = null; + state.dump = object; + + if (!detectType(state, object, false)) { + detectType(state, object, true); + } + + var type = _toString.call(state.dump); + + if (block) { + block = (state.flowLevel < 0 || state.flowLevel > level); + } + + var objectOrArray = type === '[object Object]' || type === '[object Array]', + duplicateIndex, + duplicate; + + if (objectOrArray) { + duplicateIndex = state.duplicates.indexOf(object); + duplicate = duplicateIndex !== -1; + } + + if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) { + compact = false; + } + + if (duplicate && state.usedDuplicates[duplicateIndex]) { + state.dump = '*ref_' + duplicateIndex; + } else { + if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) { + state.usedDuplicates[duplicateIndex] = true; + } + if (type === '[object Object]') { + if (block && (Object.keys(state.dump).length !== 0)) { + writeBlockMapping(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowMapping(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if (type === '[object Array]') { + if (block && (state.dump.length !== 0)) { + writeBlockSequence(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowSequence(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if (type === '[object String]') { + if (state.tag !== '?') { + writeScalar(state, state.dump, level, iskey); + } + } else { + if (state.skipInvalid) return false; + throw new YAMLException('unacceptable kind of an object to dump ' + type); + } + + if (state.tag !== null && state.tag !== '?') { + state.dump = '!<' + state.tag + '> ' + state.dump; + } + } + + return true; +} + +function getDuplicateReferences(object, state) { + var objects = [], + duplicatesIndexes = [], + index, + length; + + inspectNode(object, objects, duplicatesIndexes); + + for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) { + state.duplicates.push(objects[duplicatesIndexes[index]]); + } + state.usedDuplicates = new Array(length); +} + +function inspectNode(object, objects, duplicatesIndexes) { + var objectKeyList, + index, + length; + + if (object !== null && typeof object === 'object') { + index = objects.indexOf(object); + if (index !== -1) { + if (duplicatesIndexes.indexOf(index) === -1) { + duplicatesIndexes.push(index); + } + } else { + objects.push(object); + + if (Array.isArray(object)) { + for (index = 0, length = object.length; index < length; index += 1) { + inspectNode(object[index], objects, duplicatesIndexes); + } + } else { + objectKeyList = Object.keys(object); + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes); + } + } + } + } +} + +function dump(input, options) { + options = options || {}; + + var state = new State(options); + + if (!state.noRefs) getDuplicateReferences(input, state); + + if (writeNode(state, 0, input, true, true)) return state.dump + '\n'; + + return ''; +} + +function safeDump(input, options) { + return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + +module.exports.dump = dump; +module.exports.safeDump = safeDump; + +},{"./common":2,"./exception":4,"./schema/default_full":9,"./schema/default_safe":10}],4:[function(require,module,exports){ +// YAML error class. http://stackoverflow.com/questions/8458984 +// +'use strict'; + +function YAMLException(reason, mark) { + // Super constructor + Error.call(this); + + // Include stack trace in error object + if (Error.captureStackTrace) { + // Chrome and NodeJS + Error.captureStackTrace(this, this.constructor); + } else { + // FF, IE 10+ and Safari 6+. Fallback for others + this.stack = (new Error()).stack || ''; + } + + this.name = 'YAMLException'; + this.reason = reason; + this.mark = mark; + this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : ''); +} + + +// Inherit from Error +YAMLException.prototype = Object.create(Error.prototype); +YAMLException.prototype.constructor = YAMLException; + + +YAMLException.prototype.toString = function toString(compact) { + var result = this.name + ': '; + + result += this.reason || '(unknown reason)'; + + if (!compact && this.mark) { + result += ' ' + this.mark.toString(); + } + + return result; +}; + + +module.exports = YAMLException; + +},{}],5:[function(require,module,exports){ +'use strict'; + +/*eslint-disable max-len,no-use-before-define*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var Mark = require('./mark'); +var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe'); +var DEFAULT_FULL_SCHEMA = require('./schema/default_full'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + + +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; + + +var CHOMPING_CLIP = 1; +var CHOMPING_STRIP = 2; +var CHOMPING_KEEP = 3; + + +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i; +var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; + + +function is_EOL(c) { + return (c === 0x0A/* LF */) || (c === 0x0D/* CR */); +} + +function is_WHITE_SPACE(c) { + return (c === 0x09/* Tab */) || (c === 0x20/* Space */); +} + +function is_WS_OR_EOL(c) { + return (c === 0x09/* Tab */) || + (c === 0x20/* Space */) || + (c === 0x0A/* LF */) || + (c === 0x0D/* CR */); +} + +function is_FLOW_INDICATOR(c) { + return c === 0x2C/* , */ || + c === 0x5B/* [ */ || + c === 0x5D/* ] */ || + c === 0x7B/* { */ || + c === 0x7D/* } */; +} + +function fromHexCode(c) { + var lc; + + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + /*eslint-disable no-bitwise*/ + lc = c | 0x20; + + if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) { + return lc - 0x61 + 10; + } + + return -1; +} + +function escapedHexLen(c) { + if (c === 0x78/* x */) { return 2; } + if (c === 0x75/* u */) { return 4; } + if (c === 0x55/* U */) { return 8; } + return 0; +} + +function fromDecimalCode(c) { + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + return -1; +} + +function simpleEscapeSequence(c) { + return (c === 0x30/* 0 */) ? '\x00' : + (c === 0x61/* a */) ? '\x07' : + (c === 0x62/* b */) ? '\x08' : + (c === 0x74/* t */) ? '\x09' : + (c === 0x09/* Tab */) ? '\x09' : + (c === 0x6E/* n */) ? '\x0A' : + (c === 0x76/* v */) ? '\x0B' : + (c === 0x66/* f */) ? '\x0C' : + (c === 0x72/* r */) ? '\x0D' : + (c === 0x65/* e */) ? '\x1B' : + (c === 0x20/* Space */) ? ' ' : + (c === 0x22/* " */) ? '\x22' : + (c === 0x2F/* / */) ? '/' : + (c === 0x5C/* \ */) ? '\x5C' : + (c === 0x4E/* N */) ? '\x85' : + (c === 0x5F/* _ */) ? '\xA0' : + (c === 0x4C/* L */) ? '\u2028' : + (c === 0x50/* P */) ? '\u2029' : ''; +} + +function charFromCodepoint(c) { + if (c <= 0xFFFF) { + return String.fromCharCode(c); + } + // Encode UTF-16 surrogate pair + // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF + return String.fromCharCode(((c - 0x010000) >> 10) + 0xD800, + ((c - 0x010000) & 0x03FF) + 0xDC00); +} + +var simpleEscapeCheck = new Array(256); // integer, for fast access +var simpleEscapeMap = new Array(256); +for (var i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} + + +function State(input, options) { + this.input = input; + + this.filename = options['filename'] || null; + this.schema = options['schema'] || DEFAULT_FULL_SCHEMA; + this.onWarning = options['onWarning'] || null; + this.legacy = options['legacy'] || false; + this.json = options['json'] || false; + this.listener = options['listener'] || null; + + this.implicitTypes = this.schema.compiledImplicit; + this.typeMap = this.schema.compiledTypeMap; + + this.length = input.length; + this.position = 0; + this.line = 0; + this.lineStart = 0; + this.lineIndent = 0; + + this.documents = []; + + /* + this.version; + this.checkLineBreaks; + this.tagMap; + this.anchorMap; + this.tag; + this.anchor; + this.kind; + this.result;*/ + +} + + +function generateError(state, message) { + return new YAMLException( + message, + new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart))); +} + +function throwError(state, message) { + throw generateError(state, message); +} + +function throwWarning(state, message) { + if (state.onWarning) { + state.onWarning.call(null, generateError(state, message)); + } +} + + +var directiveHandlers = { + + YAML: function handleYamlDirective(state, name, args) { + + var match, major, minor; + + if (state.version !== null) { + throwError(state, 'duplication of %YAML directive'); + } + + if (args.length !== 1) { + throwError(state, 'YAML directive accepts exactly one argument'); + } + + match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + + if (match === null) { + throwError(state, 'ill-formed argument of the YAML directive'); + } + + major = parseInt(match[1], 10); + minor = parseInt(match[2], 10); + + if (major !== 1) { + throwError(state, 'unacceptable YAML version of the document'); + } + + state.version = args[0]; + state.checkLineBreaks = (minor < 2); + + if (minor !== 1 && minor !== 2) { + throwWarning(state, 'unsupported YAML version of the document'); + } + }, + + TAG: function handleTagDirective(state, name, args) { + + var handle, prefix; + + if (args.length !== 2) { + throwError(state, 'TAG directive accepts exactly two arguments'); + } + + handle = args[0]; + prefix = args[1]; + + if (!PATTERN_TAG_HANDLE.test(handle)) { + throwError(state, 'ill-formed tag handle (first argument) of the TAG directive'); + } + + if (_hasOwnProperty.call(state.tagMap, handle)) { + throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); + } + + if (!PATTERN_TAG_URI.test(prefix)) { + throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive'); + } + + state.tagMap[handle] = prefix; + } +}; + + +function captureSegment(state, start, end, checkJson) { + var _position, _length, _character, _result; + + if (start < end) { + _result = state.input.slice(start, end); + + if (checkJson) { + for (_position = 0, _length = _result.length; + _position < _length; + _position += 1) { + _character = _result.charCodeAt(_position); + if (!(_character === 0x09 || + (0x20 <= _character && _character <= 0x10FFFF))) { + throwError(state, 'expected valid JSON character'); + } + } + } else if (PATTERN_NON_PRINTABLE.test(_result)) { + throwError(state, 'the stream contains non-printable characters'); + } + + state.result += _result; + } +} + +function mergeMappings(state, destination, source, overridableKeys) { + var sourceKeys, key, index, quantity; + + if (!common.isObject(source)) { + throwError(state, 'cannot merge mappings; the provided source object is unacceptable'); + } + + sourceKeys = Object.keys(source); + + for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + key = sourceKeys[index]; + + if (!_hasOwnProperty.call(destination, key)) { + destination[key] = source[key]; + overridableKeys[key] = true; + } + } +} + +function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode) { + var index, quantity; + + keyNode = String(keyNode); + + if (_result === null) { + _result = {}; + } + + if (keyTag === 'tag:yaml.org,2002:merge') { + if (Array.isArray(valueNode)) { + for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { + mergeMappings(state, _result, valueNode[index], overridableKeys); + } + } else { + mergeMappings(state, _result, valueNode, overridableKeys); + } + } else { + if (!state.json && + !_hasOwnProperty.call(overridableKeys, keyNode) && + _hasOwnProperty.call(_result, keyNode)) { + throwError(state, 'duplicated mapping key'); + } + _result[keyNode] = valueNode; + delete overridableKeys[keyNode]; + } + + return _result; +} + +function readLineBreak(state) { + var ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x0A/* LF */) { + state.position++; + } else if (ch === 0x0D/* CR */) { + state.position++; + if (state.input.charCodeAt(state.position) === 0x0A/* LF */) { + state.position++; + } + } else { + throwError(state, 'a line break is expected'); + } + + state.line += 1; + state.lineStart = state.position; +} + +function skipSeparationSpace(state, allowComments, checkIndent) { + var lineBreaks = 0, + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (allowComments && ch === 0x23/* # */) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0); + } + + if (is_EOL(ch)) { + readLineBreak(state); + + ch = state.input.charCodeAt(state.position); + lineBreaks++; + state.lineIndent = 0; + + while (ch === 0x20/* Space */) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } else { + break; + } + } + + if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) { + throwWarning(state, 'deficient indentation'); + } + + return lineBreaks; +} + +function testDocumentSeparator(state) { + var _position = state.position, + ch; + + ch = state.input.charCodeAt(_position); + + // Condition state.position === state.lineStart is tested + // in parent on each call, for efficiency. No needs to test here again. + if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) && + ch === state.input.charCodeAt(_position + 1) && + ch === state.input.charCodeAt(_position + 2)) { + + _position += 3; + + ch = state.input.charCodeAt(_position); + + if (ch === 0 || is_WS_OR_EOL(ch)) { + return true; + } + } + + return false; +} + +function writeFoldedLines(state, count) { + if (count === 1) { + state.result += ' '; + } else if (count > 1) { + state.result += common.repeat('\n', count - 1); + } +} + + +function readPlainScalar(state, nodeIndent, withinFlowCollection) { + var preceding, + following, + captureStart, + captureEnd, + hasPendingContent, + _line, + _lineStart, + _lineIndent, + _kind = state.kind, + _result = state.result, + ch; + + ch = state.input.charCodeAt(state.position); + + if (is_WS_OR_EOL(ch) || + is_FLOW_INDICATOR(ch) || + ch === 0x23/* # */ || + ch === 0x26/* & */ || + ch === 0x2A/* * */ || + ch === 0x21/* ! */ || + ch === 0x7C/* | */ || + ch === 0x3E/* > */ || + ch === 0x27/* ' */ || + ch === 0x22/* " */ || + ch === 0x25/* % */ || + ch === 0x40/* @ */ || + ch === 0x60/* ` */) { + return false; + } + + if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following) || + withinFlowCollection && is_FLOW_INDICATOR(following)) { + return false; + } + } + + state.kind = 'scalar'; + state.result = ''; + captureStart = captureEnd = state.position; + hasPendingContent = false; + + while (ch !== 0) { + if (ch === 0x3A/* : */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following) || + withinFlowCollection && is_FLOW_INDICATOR(following)) { + break; + } + + } else if (ch === 0x23/* # */) { + preceding = state.input.charCodeAt(state.position - 1); + + if (is_WS_OR_EOL(preceding)) { + break; + } + + } else if ((state.position === state.lineStart && testDocumentSeparator(state)) || + withinFlowCollection && is_FLOW_INDICATOR(ch)) { + break; + + } else if (is_EOL(ch)) { + _line = state.line; + _lineStart = state.lineStart; + _lineIndent = state.lineIndent; + skipSeparationSpace(state, false, -1); + + if (state.lineIndent >= nodeIndent) { + hasPendingContent = true; + ch = state.input.charCodeAt(state.position); + continue; + } else { + state.position = captureEnd; + state.line = _line; + state.lineStart = _lineStart; + state.lineIndent = _lineIndent; + break; + } + } + + if (hasPendingContent) { + captureSegment(state, captureStart, captureEnd, false); + writeFoldedLines(state, state.line - _line); + captureStart = captureEnd = state.position; + hasPendingContent = false; + } + + if (!is_WHITE_SPACE(ch)) { + captureEnd = state.position + 1; + } + + ch = state.input.charCodeAt(++state.position); + } + + captureSegment(state, captureStart, captureEnd, false); + + if (state.result) { + return true; + } + + state.kind = _kind; + state.result = _result; + return false; +} + +function readSingleQuotedScalar(state, nodeIndent) { + var ch, + captureStart, captureEnd; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x27/* ' */) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x27/* ' */) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x27/* ' */) { + captureStart = captureEnd = state.position; + state.position++; + } else { + return true; + } + + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a single quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError(state, 'unexpected end of the stream within a single quoted scalar'); +} + +function readDoubleQuotedScalar(state, nodeIndent) { + var captureStart, + captureEnd, + hexLength, + hexResult, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x22/* " */) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x22/* " */) { + captureSegment(state, captureStart, state.position, true); + state.position++; + return true; + + } else if (ch === 0x5C/* \ */) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (is_EOL(ch)) { + skipSeparationSpace(state, false, nodeIndent); + + // TODO: rework to inline fn with no type cast? + } else if (ch < 256 && simpleEscapeCheck[ch]) { + state.result += simpleEscapeMap[ch]; + state.position++; + + } else if ((tmp = escapedHexLen(ch)) > 0) { + hexLength = tmp; + hexResult = 0; + + for (; hexLength > 0; hexLength--) { + ch = state.input.charCodeAt(++state.position); + + if ((tmp = fromHexCode(ch)) >= 0) { + hexResult = (hexResult << 4) + tmp; + + } else { + throwError(state, 'expected hexadecimal character'); + } + } + + state.result += charFromCodepoint(hexResult); + + state.position++; + + } else { + throwError(state, 'unknown escape sequence'); + } + + captureStart = captureEnd = state.position; + + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a double quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError(state, 'unexpected end of the stream within a double quoted scalar'); +} + +function readFlowCollection(state, nodeIndent) { + var readNext = true, + _line, + _tag = state.tag, + _result, + _anchor = state.anchor, + following, + terminator, + isPair, + isExplicitPair, + isMapping, + overridableKeys = {}, + keyNode, + keyTag, + valueNode, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x5B/* [ */) { + terminator = 0x5D;/* ] */ + isMapping = false; + _result = []; + } else if (ch === 0x7B/* { */) { + terminator = 0x7D;/* } */ + isMapping = true; + _result = {}; + } else { + return false; + } + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(++state.position); + + while (ch !== 0) { + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === terminator) { + state.position++; + state.tag = _tag; + state.anchor = _anchor; + state.kind = isMapping ? 'mapping' : 'sequence'; + state.result = _result; + return true; + } else if (!readNext) { + throwError(state, 'missed comma between flow collection entries'); + } + + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; + + if (ch === 0x3F/* ? */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following)) { + isPair = isExplicitPair = true; + state.position++; + skipSeparationSpace(state, true, nodeIndent); + } + } + + _line = state.line; + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + keyTag = state.tag; + keyNode = state.result; + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) { + isPair = true; + ch = state.input.charCodeAt(++state.position); + skipSeparationSpace(state, true, nodeIndent); + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + valueNode = state.result; + } + + if (isMapping) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode); + } else if (isPair) { + _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode)); + } else { + _result.push(keyNode); + } + + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x2C/* , */) { + readNext = true; + ch = state.input.charCodeAt(++state.position); + } else { + readNext = false; + } + } + + throwError(state, 'unexpected end of the stream within a flow collection'); +} + +function readBlockScalar(state, nodeIndent) { + var captureStart, + folding, + chomping = CHOMPING_CLIP, + didReadContent = false, + detectedIndent = false, + textIndent = nodeIndent, + emptyLines = 0, + atMoreIndented = false, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x7C/* | */) { + folding = false; + } else if (ch === 0x3E/* > */) { + folding = true; + } else { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + + while (ch !== 0) { + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + if (CHOMPING_CLIP === chomping) { + chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP; + } else { + throwError(state, 'repeat of a chomping mode identifier'); + } + + } else if ((tmp = fromDecimalCode(ch)) >= 0) { + if (tmp === 0) { + throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one'); + } else if (!detectedIndent) { + textIndent = nodeIndent + tmp - 1; + detectedIndent = true; + } else { + throwError(state, 'repeat of an indentation width identifier'); + } + + } else { + break; + } + } + + if (is_WHITE_SPACE(ch)) { + do { ch = state.input.charCodeAt(++state.position); } + while (is_WHITE_SPACE(ch)); + + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (!is_EOL(ch) && (ch !== 0)); + } + } + + while (ch !== 0) { + readLineBreak(state); + state.lineIndent = 0; + + ch = state.input.charCodeAt(state.position); + + while ((!detectedIndent || state.lineIndent < textIndent) && + (ch === 0x20/* Space */)) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + + if (!detectedIndent && state.lineIndent > textIndent) { + textIndent = state.lineIndent; + } + + if (is_EOL(ch)) { + emptyLines++; + continue; + } + + // End of the scalar. + if (state.lineIndent < textIndent) { + + // Perform the chomping. + if (chomping === CHOMPING_KEEP) { + state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + } else if (chomping === CHOMPING_CLIP) { + if (didReadContent) { // i.e. only if the scalar is not empty. + state.result += '\n'; + } + } + + // Break this `while` cycle and go to the funciton's epilogue. + break; + } + + // Folded style: use fancy rules to handle line breaks. + if (folding) { + + // Lines starting with white space characters (more-indented lines) are not folded. + if (is_WHITE_SPACE(ch)) { + atMoreIndented = true; + // except for the first content line (cf. Example 8.1) + state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + + // End of more-indented block. + } else if (atMoreIndented) { + atMoreIndented = false; + state.result += common.repeat('\n', emptyLines + 1); + + // Just one line break - perceive as the same line. + } else if (emptyLines === 0) { + if (didReadContent) { // i.e. only if we have already read some scalar content. + state.result += ' '; + } + + // Several line breaks - perceive as different lines. + } else { + state.result += common.repeat('\n', emptyLines); + } + + // Literal style: just add exact number of line breaks between content lines. + } else { + // Keep all line breaks except the header line break. + state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + } + + didReadContent = true; + detectedIndent = true; + emptyLines = 0; + captureStart = state.position; + + while (!is_EOL(ch) && (ch !== 0)) { + ch = state.input.charCodeAt(++state.position); + } + + captureSegment(state, captureStart, state.position, false); + } + + return true; +} + +function readBlockSequence(state, nodeIndent) { + var _line, + _tag = state.tag, + _anchor = state.anchor, + _result = [], + following, + detected = false, + ch; + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + + if (ch !== 0x2D/* - */) { + break; + } + + following = state.input.charCodeAt(state.position + 1); + + if (!is_WS_OR_EOL(following)) { + break; + } + + detected = true; + state.position++; + + if (skipSeparationSpace(state, true, -1)) { + if (state.lineIndent <= nodeIndent) { + _result.push(null); + ch = state.input.charCodeAt(state.position); + continue; + } + } + + _line = state.line; + composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + _result.push(state.result); + skipSeparationSpace(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) { + throwError(state, 'bad indentation of a sequence entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'sequence'; + state.result = _result; + return true; + } + return false; +} + +function readBlockMapping(state, nodeIndent, flowIndent) { + var following, + allowCompact, + _line, + _tag = state.tag, + _anchor = state.anchor, + _result = {}, + overridableKeys = {}, + keyTag = null, + keyNode = null, + valueNode = null, + atExplicitKey = false, + detected = false, + ch; + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + following = state.input.charCodeAt(state.position + 1); + _line = state.line; // Save the current line. + + // + // Explicit notation case. There are two separate blocks: + // first for the key (denoted by "?") and second for the value (denoted by ":") + // + if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) { + + if (ch === 0x3F/* ? */) { + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = true; + allowCompact = true; + + } else if (atExplicitKey) { + // i.e. 0x3A/* : */ === character after the explicit key. + atExplicitKey = false; + allowCompact = true; + + } else { + throwError(state, 'incomplete explicit mapping pair; a key node is missed'); + } + + state.position += 1; + ch = following; + + // + // Implicit notation case. Flow-style node as the key first, then ":", and the value. + // + } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { + + if (state.line === _line) { + ch = state.input.charCodeAt(state.position); + + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (ch === 0x3A/* : */) { + ch = state.input.charCodeAt(++state.position); + + if (!is_WS_OR_EOL(ch)) { + throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping'); + } + + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = state.tag; + keyNode = state.result; + + } else if (detected) { + throwError(state, 'can not read an implicit mapping pair; a colon is missed'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else if (detected) { + throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else { + break; // Reading is done. Go to the epilogue. + } + + // + // Common reading code for both explicit and implicit notations. + // + if (state.line === _line || state.lineIndent > nodeIndent) { + if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (atExplicitKey) { + keyNode = state.result; + } else { + valueNode = state.result; + } + } + + if (!atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode); + keyTag = keyNode = valueNode = null; + } + + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); + } + + if (state.lineIndent > nodeIndent && (ch !== 0)) { + throwError(state, 'bad indentation of a mapping entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + // + // Epilogue. + // + + // Special case: last mapping's node contains only the key in explicit notation. + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null); + } + + // Expose the resulting mapping. + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'mapping'; + state.result = _result; + } + + return detected; +} + +function readTagProperty(state) { + var _position, + isVerbatim = false, + isNamed = false, + tagHandle, + tagName, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x21/* ! */) return false; + + if (state.tag !== null) { + throwError(state, 'duplication of a tag property'); + } + + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x3C/* < */) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + + } else if (ch === 0x21/* ! */) { + isNamed = true; + tagHandle = '!!'; + ch = state.input.charCodeAt(++state.position); + + } else { + tagHandle = '!'; + } + + _position = state.position; + + if (isVerbatim) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && ch !== 0x3E/* > */); + + if (state.position < state.length) { + tagName = state.input.slice(_position, state.position); + ch = state.input.charCodeAt(++state.position); + } else { + throwError(state, 'unexpected end of the stream within a verbatim tag'); + } + } else { + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + + if (ch === 0x21/* ! */) { + if (!isNamed) { + tagHandle = state.input.slice(_position - 1, state.position + 1); + + if (!PATTERN_TAG_HANDLE.test(tagHandle)) { + throwError(state, 'named tag handle cannot contain such characters'); + } + + isNamed = true; + _position = state.position + 1; + } else { + throwError(state, 'tag suffix cannot contain exclamation marks'); + } + } + + ch = state.input.charCodeAt(++state.position); + } + + tagName = state.input.slice(_position, state.position); + + if (PATTERN_FLOW_INDICATORS.test(tagName)) { + throwError(state, 'tag suffix cannot contain flow indicator characters'); + } + } + + if (tagName && !PATTERN_TAG_URI.test(tagName)) { + throwError(state, 'tag name cannot contain such characters: ' + tagName); + } + + if (isVerbatim) { + state.tag = tagName; + + } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) { + state.tag = state.tagMap[tagHandle] + tagName; + + } else if (tagHandle === '!') { + state.tag = '!' + tagName; + + } else if (tagHandle === '!!') { + state.tag = 'tag:yaml.org,2002:' + tagName; + + } else { + throwError(state, 'undeclared tag handle "' + tagHandle + '"'); + } + + return true; +} + +function readAnchorProperty(state) { + var _position, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x26/* & */) return false; + + if (state.anchor !== null) { + throwError(state, 'duplication of an anchor property'); + } + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError(state, 'name of an anchor node must contain at least one character'); + } + + state.anchor = state.input.slice(_position, state.position); + return true; +} + +function readAlias(state) { + var _position, alias, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x2A/* * */) return false; + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError(state, 'name of an alias node must contain at least one character'); + } + + alias = state.input.slice(_position, state.position); + + if (!state.anchorMap.hasOwnProperty(alias)) { + throwError(state, 'unidentified alias "' + alias + '"'); + } + + state.result = state.anchorMap[alias]; + skipSeparationSpace(state, true, -1); + return true; +} + +function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) { + var allowBlockStyles, + allowBlockScalars, + allowBlockCollections, + indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } + } + + if (indentStatus === 1) { + while (readTagProperty(state) || readAnchorProperty(state)) { + if (skipSeparationSpace(state, true, -1)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + + if (state.lineIndent > parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } else { + allowBlockCollections = false; + } + } + } + + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } + + if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) { + if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { + flowIndent = parentIndent; + } else { + flowIndent = parentIndent + 1; + } + + blockIndent = state.position - state.lineStart; + + if (indentStatus === 1) { + if (allowBlockCollections && + (readBlockSequence(state, blockIndent) || + readBlockMapping(state, blockIndent, flowIndent)) || + readFlowCollection(state, flowIndent)) { + hasContent = true; + } else { + if ((allowBlockScalars && readBlockScalar(state, flowIndent)) || + readSingleQuotedScalar(state, flowIndent) || + readDoubleQuotedScalar(state, flowIndent)) { + hasContent = true; + + } else if (readAlias(state)) { + hasContent = true; + + if (state.tag !== null || state.anchor !== null) { + throwError(state, 'alias node should not have any properties'); + } + + } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) { + hasContent = true; + + if (state.tag === null) { + state.tag = '?'; + } + } + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + } + } else if (indentStatus === 0) { + // Special case: block sequences are allowed to have same indentation level as the parent. + // http://www.yaml.org/spec/1.2/spec.html#id2799784 + hasContent = allowBlockCollections && readBlockSequence(state, blockIndent); + } + } + + if (state.tag !== null && state.tag !== '!') { + if (state.tag === '?') { + for (typeIndex = 0, typeQuantity = state.implicitTypes.length; + typeIndex < typeQuantity; + typeIndex += 1) { + type = state.implicitTypes[typeIndex]; + + // Implicit resolving is not allowed for non-scalar types, and '?' + // non-specific tag is only assigned to plain scalars. So, it isn't + // needed to check for 'kind' conformity. + + if (type.resolve(state.result)) { // `state.result` updated in resolver if matched + state.result = type.construct(state.result); + state.tag = type.tag; + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + break; + } + } + } else if (_hasOwnProperty.call(state.typeMap, state.tag)) { + type = state.typeMap[state.tag]; + + if (state.result !== null && type.kind !== state.kind) { + throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"'); + } + + if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched + throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag'); + } else { + state.result = type.construct(state.result); + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + } + } else { + throwError(state, 'unknown tag !<' + state.tag + '>'); + } + } + + if (state.listener !== null) { + state.listener('close', state); + } + return state.tag !== null || state.anchor !== null || hasContent; +} + +function readDocument(state) { + var documentStart = state.position, + _position, + directiveName, + directiveArgs, + hasDirectives = false, + ch; + + state.version = null; + state.checkLineBreaks = state.legacy; + state.tagMap = {}; + state.anchorMap = {}; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + skipSeparationSpace(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if (state.lineIndent > 0 || ch !== 0x25/* % */) { + break; + } + + hasDirectives = true; + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveName = state.input.slice(_position, state.position); + directiveArgs = []; + + if (directiveName.length < 1) { + throwError(state, 'directive name must not be less than one character in length'); + } + + while (ch !== 0) { + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && !is_EOL(ch)); + break; + } + + if (is_EOL(ch)) break; + + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveArgs.push(state.input.slice(_position, state.position)); + } + + if (ch !== 0) readLineBreak(state); + + if (_hasOwnProperty.call(directiveHandlers, directiveName)) { + directiveHandlers[directiveName](state, directiveName, directiveArgs); + } else { + throwWarning(state, 'unknown document directive "' + directiveName + '"'); + } + } + + skipSeparationSpace(state, true, -1); + + if (state.lineIndent === 0 && + state.input.charCodeAt(state.position) === 0x2D/* - */ && + state.input.charCodeAt(state.position + 1) === 0x2D/* - */ && + state.input.charCodeAt(state.position + 2) === 0x2D/* - */) { + state.position += 3; + skipSeparationSpace(state, true, -1); + + } else if (hasDirectives) { + throwError(state, 'directives end mark is expected'); + } + + composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); + skipSeparationSpace(state, true, -1); + + if (state.checkLineBreaks && + PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) { + throwWarning(state, 'non-ASCII line breaks are interpreted as content'); + } + + state.documents.push(state.result); + + if (state.position === state.lineStart && testDocumentSeparator(state)) { + + if (state.input.charCodeAt(state.position) === 0x2E/* . */) { + state.position += 3; + skipSeparationSpace(state, true, -1); + } + return; + } + + if (state.position < (state.length - 1)) { + throwError(state, 'end of the stream or a document separator is expected'); + } else { + return; + } +} + + +function loadDocuments(input, options) { + input = String(input); + options = options || {}; + + if (input.length !== 0) { + + // Add tailing `\n` if not exists + if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ && + input.charCodeAt(input.length - 1) !== 0x0D/* CR */) { + input += '\n'; + } + + // Strip BOM + if (input.charCodeAt(0) === 0xFEFF) { + input = input.slice(1); + } + } + + var state = new State(input, options); + + // Use 0 as string terminator. That significantly simplifies bounds check. + state.input += '\0'; + + while (state.input.charCodeAt(state.position) === 0x20/* Space */) { + state.lineIndent += 1; + state.position += 1; + } + + while (state.position < (state.length - 1)) { + readDocument(state); + } + + return state.documents; +} + + +function loadAll(input, iterator, options) { + var documents = loadDocuments(input, options), index, length; + + for (index = 0, length = documents.length; index < length; index += 1) { + iterator(documents[index]); + } +} + + +function load(input, options) { + var documents = loadDocuments(input, options); + + if (documents.length === 0) { + /*eslint-disable no-undefined*/ + return undefined; + } else if (documents.length === 1) { + return documents[0]; + } + throw new YAMLException('expected a single document in the stream, but found more'); +} + + +function safeLoadAll(input, output, options) { + loadAll(input, output, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + + +function safeLoad(input, options) { + return load(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + + +module.exports.loadAll = loadAll; +module.exports.load = load; +module.exports.safeLoadAll = safeLoadAll; +module.exports.safeLoad = safeLoad; + +},{"./common":2,"./exception":4,"./mark":6,"./schema/default_full":9,"./schema/default_safe":10}],6:[function(require,module,exports){ +'use strict'; + + +var common = require('./common'); + + +function Mark(name, buffer, position, line, column) { + this.name = name; + this.buffer = buffer; + this.position = position; + this.line = line; + this.column = column; +} + + +Mark.prototype.getSnippet = function getSnippet(indent, maxLength) { + var head, start, tail, end, snippet; + + if (!this.buffer) return null; + + indent = indent || 4; + maxLength = maxLength || 75; + + head = ''; + start = this.position; + + while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) { + start -= 1; + if (this.position - start > (maxLength / 2 - 1)) { + head = ' ... '; + start += 5; + break; + } + } + + tail = ''; + end = this.position; + + while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) { + end += 1; + if (end - this.position > (maxLength / 2 - 1)) { + tail = ' ... '; + end -= 5; + break; + } + } + + snippet = this.buffer.slice(start, end); + + return common.repeat(' ', indent) + head + snippet + tail + '\n' + + common.repeat(' ', indent + this.position - start + head.length) + '^'; +}; + + +Mark.prototype.toString = function toString(compact) { + var snippet, where = ''; + + if (this.name) { + where += 'in "' + this.name + '" '; + } + + where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1); + + if (!compact) { + snippet = this.getSnippet(); + + if (snippet) { + where += ':\n' + snippet; + } + } + + return where; +}; + + +module.exports = Mark; + +},{"./common":2}],7:[function(require,module,exports){ +'use strict'; + +/*eslint-disable max-len*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var Type = require('./type'); + + +function compileList(schema, name, result) { + var exclude = []; + + schema.include.forEach(function (includedSchema) { + result = compileList(includedSchema, name, result); + }); + + schema[name].forEach(function (currentType) { + result.forEach(function (previousType, previousIndex) { + if (previousType.tag === currentType.tag) { + exclude.push(previousIndex); + } + }); + + result.push(currentType); + }); + + return result.filter(function (type, index) { + return exclude.indexOf(index) === -1; + }); +} + + +function compileMap(/* lists... */) { + var result = {}, index, length; + + function collectType(type) { + result[type.tag] = type; + } + + for (index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); + } + + return result; +} + + +function Schema(definition) { + this.include = definition.include || []; + this.implicit = definition.implicit || []; + this.explicit = definition.explicit || []; + + this.implicit.forEach(function (type) { + if (type.loadKind && type.loadKind !== 'scalar') { + throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); + } + }); + + this.compiledImplicit = compileList(this, 'implicit', []); + this.compiledExplicit = compileList(this, 'explicit', []); + this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit); +} + + +Schema.DEFAULT = null; + + +Schema.create = function createSchema() { + var schemas, types; + + switch (arguments.length) { + case 1: + schemas = Schema.DEFAULT; + types = arguments[0]; + break; + + case 2: + schemas = arguments[0]; + types = arguments[1]; + break; + + default: + throw new YAMLException('Wrong number of arguments for Schema.create function'); + } + + schemas = common.toArray(schemas); + types = common.toArray(types); + + if (!schemas.every(function (schema) { return schema instanceof Schema; })) { + throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.'); + } + + if (!types.every(function (type) { return type instanceof Type; })) { + throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + + return new Schema({ + include: schemas, + explicit: types + }); +}; + + +module.exports = Schema; + +},{"./common":2,"./exception":4,"./type":13}],8:[function(require,module,exports){ +// Standard YAML's Core schema. +// http://www.yaml.org/spec/1.2/spec.html#id2804923 +// +// NOTE: JS-YAML does not support schema-specific tag resolution restrictions. +// So, Core schema has no distinctions from JSON schema is JS-YAML. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./json') + ] +}); + +},{"../schema":7,"./json":12}],9:[function(require,module,exports){ +// JS-YAML's default schema for `load` function. +// It is not described in the YAML specification. +// +// This schema is based on JS-YAML's default safe schema and includes +// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function. +// +// Also this schema is used as default base schema at `Schema.create` function. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = Schema.DEFAULT = new Schema({ + include: [ + require('./default_safe') + ], + explicit: [ + require('../type/js/undefined'), + require('../type/js/regexp'), + require('../type/js/function') + ] +}); + +},{"../schema":7,"../type/js/function":18,"../type/js/regexp":19,"../type/js/undefined":20,"./default_safe":10}],10:[function(require,module,exports){ +// JS-YAML's default schema for `safeLoad` function. +// It is not described in the YAML specification. +// +// This schema is based on standard YAML's Core schema and includes most of +// extra types described at YAML tag repository. (http://yaml.org/type/) + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./core') + ], + implicit: [ + require('../type/timestamp'), + require('../type/merge') + ], + explicit: [ + require('../type/binary'), + require('../type/omap'), + require('../type/pairs'), + require('../type/set') + ] +}); + +},{"../schema":7,"../type/binary":14,"../type/merge":22,"../type/omap":24,"../type/pairs":25,"../type/set":27,"../type/timestamp":29,"./core":8}],11:[function(require,module,exports){ +// Standard YAML's Failsafe schema. +// http://www.yaml.org/spec/1.2/spec.html#id2802346 + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + explicit: [ + require('../type/str'), + require('../type/seq'), + require('../type/map') + ] +}); + +},{"../schema":7,"../type/map":21,"../type/seq":26,"../type/str":28}],12:[function(require,module,exports){ +// Standard YAML's JSON schema. +// http://www.yaml.org/spec/1.2/spec.html#id2803231 +// +// NOTE: JS-YAML does not support schema-specific tag resolution restrictions. +// So, this schema is not such strict as defined in the YAML specification. +// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./failsafe') + ], + implicit: [ + require('../type/null'), + require('../type/bool'), + require('../type/int'), + require('../type/float') + ] +}); + +},{"../schema":7,"../type/bool":15,"../type/float":16,"../type/int":17,"../type/null":23,"./failsafe":11}],13:[function(require,module,exports){ +'use strict'; + +var YAMLException = require('./exception'); + +var TYPE_CONSTRUCTOR_OPTIONS = [ + 'kind', + 'resolve', + 'construct', + 'instanceOf', + 'predicate', + 'represent', + 'defaultStyle', + 'styleAliases' +]; + +var YAML_NODE_KINDS = [ + 'scalar', + 'sequence', + 'mapping' +]; + +function compileStyleAliases(map) { + var result = {}; + + if (map !== null) { + Object.keys(map).forEach(function (style) { + map[style].forEach(function (alias) { + result[String(alias)] = style; + }); + }); + } + + return result; +} + +function Type(tag, options) { + options = options || {}; + + Object.keys(options).forEach(function (name) { + if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) { + throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); + } + }); + + // TODO: Add tag format check. + this.tag = tag; + this.kind = options['kind'] || null; + this.resolve = options['resolve'] || function () { return true; }; + this.construct = options['construct'] || function (data) { return data; }; + this.instanceOf = options['instanceOf'] || null; + this.predicate = options['predicate'] || null; + this.represent = options['represent'] || null; + this.defaultStyle = options['defaultStyle'] || null; + this.styleAliases = compileStyleAliases(options['styleAliases'] || null); + + if (YAML_NODE_KINDS.indexOf(this.kind) === -1) { + throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); + } +} + +module.exports = Type; + +},{"./exception":4}],14:[function(require,module,exports){ +'use strict'; + +/*eslint-disable no-bitwise*/ + +var NodeBuffer; + +try { + // A trick for browserified version, to not include `Buffer` shim + var _require = require; + NodeBuffer = _require('buffer').Buffer; +} catch (__) {} + +var Type = require('../type'); + + +// [ 64, 65, 66 ] -> [ padding, CR, LF ] +var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'; + + +function resolveYamlBinary(data) { + if (data === null) return false; + + var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP; + + // Convert one by one. + for (idx = 0; idx < max; idx++) { + code = map.indexOf(data.charAt(idx)); + + // Skip CR/LF + if (code > 64) continue; + + // Fail on illegal characters + if (code < 0) return false; + + bitlen += 6; + } + + // If there are any bits left, source was corrupted + return (bitlen % 8) === 0; +} + +function constructYamlBinary(data) { + var idx, tailbits, + input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan + max = input.length, + map = BASE64_MAP, + bits = 0, + result = []; + + // Collect by 6*4 bits (3 bytes) + + for (idx = 0; idx < max; idx++) { + if ((idx % 4 === 0) && idx) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } + + bits = (bits << 6) | map.indexOf(input.charAt(idx)); + } + + // Dump tail + + tailbits = (max % 4) * 6; + + if (tailbits === 0) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } else if (tailbits === 18) { + result.push((bits >> 10) & 0xFF); + result.push((bits >> 2) & 0xFF); + } else if (tailbits === 12) { + result.push((bits >> 4) & 0xFF); + } + + // Wrap into Buffer for NodeJS and leave Array for browser + if (NodeBuffer) return new NodeBuffer(result); + + return result; +} + +function representYamlBinary(object /*, style*/) { + var result = '', bits = 0, idx, tail, + max = object.length, + map = BASE64_MAP; + + // Convert every three bytes to 4 ASCII characters. + + for (idx = 0; idx < max; idx++) { + if ((idx % 3 === 0) && idx) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } + + bits = (bits << 8) + object[idx]; + } + + // Dump tail + + tail = max % 3; + + if (tail === 0) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } else if (tail === 2) { + result += map[(bits >> 10) & 0x3F]; + result += map[(bits >> 4) & 0x3F]; + result += map[(bits << 2) & 0x3F]; + result += map[64]; + } else if (tail === 1) { + result += map[(bits >> 2) & 0x3F]; + result += map[(bits << 4) & 0x3F]; + result += map[64]; + result += map[64]; + } + + return result; +} + +function isBinary(object) { + return NodeBuffer && NodeBuffer.isBuffer(object); +} + +module.exports = new Type('tag:yaml.org,2002:binary', { + kind: 'scalar', + resolve: resolveYamlBinary, + construct: constructYamlBinary, + predicate: isBinary, + represent: representYamlBinary +}); + +},{"../type":13}],15:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +function resolveYamlBoolean(data) { + if (data === null) return false; + + var max = data.length; + + return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) || + (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE')); +} + +function constructYamlBoolean(data) { + return data === 'true' || + data === 'True' || + data === 'TRUE'; +} + +function isBoolean(object) { + return Object.prototype.toString.call(object) === '[object Boolean]'; +} + +module.exports = new Type('tag:yaml.org,2002:bool', { + kind: 'scalar', + resolve: resolveYamlBoolean, + construct: constructYamlBoolean, + predicate: isBoolean, + represent: { + lowercase: function (object) { return object ? 'true' : 'false'; }, + uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; }, + camelcase: function (object) { return object ? 'True' : 'False'; } + }, + defaultStyle: 'lowercase' +}); + +},{"../type":13}],16:[function(require,module,exports){ +'use strict'; + +var common = require('../common'); +var Type = require('../type'); + +var YAML_FLOAT_PATTERN = new RegExp( + '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' + + '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' + + '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' + + '|[-+]?\\.(?:inf|Inf|INF)' + + '|\\.(?:nan|NaN|NAN))$'); + +function resolveYamlFloat(data) { + if (data === null) return false; + + if (!YAML_FLOAT_PATTERN.test(data)) return false; + + return true; +} + +function constructYamlFloat(data) { + var value, sign, base, digits; + + value = data.replace(/_/g, '').toLowerCase(); + sign = value[0] === '-' ? -1 : 1; + digits = []; + + if ('+-'.indexOf(value[0]) >= 0) { + value = value.slice(1); + } + + if (value === '.inf') { + return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + + } else if (value === '.nan') { + return NaN; + + } else if (value.indexOf(':') >= 0) { + value.split(':').forEach(function (v) { + digits.unshift(parseFloat(v, 10)); + }); + + value = 0.0; + base = 1; + + digits.forEach(function (d) { + value += d * base; + base *= 60; + }); + + return sign * value; + + } + return sign * parseFloat(value, 10); +} + + +var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/; + +function representYamlFloat(object, style) { + var res; + + if (isNaN(object)) { + switch (style) { + case 'lowercase': return '.nan'; + case 'uppercase': return '.NAN'; + case 'camelcase': return '.NaN'; + } + } else if (Number.POSITIVE_INFINITY === object) { + switch (style) { + case 'lowercase': return '.inf'; + case 'uppercase': return '.INF'; + case 'camelcase': return '.Inf'; + } + } else if (Number.NEGATIVE_INFINITY === object) { + switch (style) { + case 'lowercase': return '-.inf'; + case 'uppercase': return '-.INF'; + case 'camelcase': return '-.Inf'; + } + } else if (common.isNegativeZero(object)) { + return '-0.0'; + } + + res = object.toString(10); + + // JS stringifier can build scientific format without dots: 5e-100, + // while YAML requres dot: 5.e-100. Fix it with simple hack + + return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res; +} + +function isFloat(object) { + return (Object.prototype.toString.call(object) === '[object Number]') && + (object % 1 !== 0 || common.isNegativeZero(object)); +} + +module.exports = new Type('tag:yaml.org,2002:float', { + kind: 'scalar', + resolve: resolveYamlFloat, + construct: constructYamlFloat, + predicate: isFloat, + represent: representYamlFloat, + defaultStyle: 'lowercase' +}); + +},{"../common":2,"../type":13}],17:[function(require,module,exports){ +'use strict'; + +var common = require('../common'); +var Type = require('../type'); + +function isHexCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) || + ((0x41/* A */ <= c) && (c <= 0x46/* F */)) || + ((0x61/* a */ <= c) && (c <= 0x66/* f */)); +} + +function isOctCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */)); +} + +function isDecCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)); +} + +function resolveYamlInteger(data) { + if (data === null) return false; + + var max = data.length, + index = 0, + hasDigits = false, + ch; + + if (!max) return false; + + ch = data[index]; + + // sign + if (ch === '-' || ch === '+') { + ch = data[++index]; + } + + if (ch === '0') { + // 0 + if (index + 1 === max) return true; + ch = data[++index]; + + // base 2, base 8, base 16 + + if (ch === 'b') { + // base 2 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (ch !== '0' && ch !== '1') return false; + hasDigits = true; + } + return hasDigits; + } + + + if (ch === 'x') { + // base 16 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isHexCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits; + } + + // base 8 + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isOctCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits; + } + + // base 10 (except 0) or base 60 + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (ch === ':') break; + if (!isDecCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + + if (!hasDigits) return false; + + // if !base60 - done; + if (ch !== ':') return true; + + // base60 almost not used, no needs to optimize + return /^(:[0-5]?[0-9])+$/.test(data.slice(index)); +} + +function constructYamlInteger(data) { + var value = data, sign = 1, ch, base, digits = []; + + if (value.indexOf('_') !== -1) { + value = value.replace(/_/g, ''); + } + + ch = value[0]; + + if (ch === '-' || ch === '+') { + if (ch === '-') sign = -1; + value = value.slice(1); + ch = value[0]; + } + + if (value === '0') return 0; + + if (ch === '0') { + if (value[1] === 'b') return sign * parseInt(value.slice(2), 2); + if (value[1] === 'x') return sign * parseInt(value, 16); + return sign * parseInt(value, 8); + } + + if (value.indexOf(':') !== -1) { + value.split(':').forEach(function (v) { + digits.unshift(parseInt(v, 10)); + }); + + value = 0; + base = 1; + + digits.forEach(function (d) { + value += (d * base); + base *= 60; + }); + + return sign * value; + + } + + return sign * parseInt(value, 10); +} + +function isInteger(object) { + return (Object.prototype.toString.call(object)) === '[object Number]' && + (object % 1 === 0 && !common.isNegativeZero(object)); +} + +module.exports = new Type('tag:yaml.org,2002:int', { + kind: 'scalar', + resolve: resolveYamlInteger, + construct: constructYamlInteger, + predicate: isInteger, + represent: { + binary: function (object) { return '0b' + object.toString(2); }, + octal: function (object) { return '0' + object.toString(8); }, + decimal: function (object) { return object.toString(10); }, + hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); } + }, + defaultStyle: 'decimal', + styleAliases: { + binary: [ 2, 'bin' ], + octal: [ 8, 'oct' ], + decimal: [ 10, 'dec' ], + hexadecimal: [ 16, 'hex' ] + } +}); + +},{"../common":2,"../type":13}],18:[function(require,module,exports){ +'use strict'; + +var esprima; + +// Browserified version does not have esprima +// +// 1. For node.js just require module as deps +// 2. For browser try to require mudule via external AMD system. +// If not found - try to fallback to window.esprima. If not +// found too - then fail to parse. +// +try { + // workaround to exclude package from browserify list. + var _require = require; + esprima = _require('esprima'); +} catch (_) { + /*global window */ + if (typeof window !== 'undefined') esprima = window.esprima; +} + +var Type = require('../../type'); + +function resolveJavascriptFunction(data) { + if (data === null) return false; + + try { + var source = '(' + data + ')', + ast = esprima.parse(source, { range: true }); + + if (ast.type !== 'Program' || + ast.body.length !== 1 || + ast.body[0].type !== 'ExpressionStatement' || + ast.body[0].expression.type !== 'FunctionExpression') { + return false; + } + + return true; + } catch (err) { + return false; + } +} + +function constructJavascriptFunction(data) { + /*jslint evil:true*/ + + var source = '(' + data + ')', + ast = esprima.parse(source, { range: true }), + params = [], + body; + + if (ast.type !== 'Program' || + ast.body.length !== 1 || + ast.body[0].type !== 'ExpressionStatement' || + ast.body[0].expression.type !== 'FunctionExpression') { + throw new Error('Failed to resolve function'); + } + + ast.body[0].expression.params.forEach(function (param) { + params.push(param.name); + }); + + body = ast.body[0].expression.body.range; + + // Esprima's ranges include the first '{' and the last '}' characters on + // function expressions. So cut them out. + /*eslint-disable no-new-func*/ + return new Function(params, source.slice(body[0] + 1, body[1] - 1)); +} + +function representJavascriptFunction(object /*, style*/) { + return object.toString(); +} + +function isFunction(object) { + return Object.prototype.toString.call(object) === '[object Function]'; +} + +module.exports = new Type('tag:yaml.org,2002:js/function', { + kind: 'scalar', + resolve: resolveJavascriptFunction, + construct: constructJavascriptFunction, + predicate: isFunction, + represent: representJavascriptFunction +}); + +},{"../../type":13}],19:[function(require,module,exports){ +'use strict'; + +var Type = require('../../type'); + +function resolveJavascriptRegExp(data) { + if (data === null) return false; + if (data.length === 0) return false; + + var regexp = data, + tail = /\/([gim]*)$/.exec(data), + modifiers = ''; + + // if regexp starts with '/' it can have modifiers and must be properly closed + // `/foo/gim` - modifiers tail can be maximum 3 chars + if (regexp[0] === '/') { + if (tail) modifiers = tail[1]; + + if (modifiers.length > 3) return false; + // if expression starts with /, is should be properly terminated + if (regexp[regexp.length - modifiers.length - 1] !== '/') return false; + } + + return true; +} + +function constructJavascriptRegExp(data) { + var regexp = data, + tail = /\/([gim]*)$/.exec(data), + modifiers = ''; + + // `/foo/gim` - tail can be maximum 4 chars + if (regexp[0] === '/') { + if (tail) modifiers = tail[1]; + regexp = regexp.slice(1, regexp.length - modifiers.length - 1); + } + + return new RegExp(regexp, modifiers); +} + +function representJavascriptRegExp(object /*, style*/) { + var result = '/' + object.source + '/'; + + if (object.global) result += 'g'; + if (object.multiline) result += 'm'; + if (object.ignoreCase) result += 'i'; + + return result; +} + +function isRegExp(object) { + return Object.prototype.toString.call(object) === '[object RegExp]'; +} + +module.exports = new Type('tag:yaml.org,2002:js/regexp', { + kind: 'scalar', + resolve: resolveJavascriptRegExp, + construct: constructJavascriptRegExp, + predicate: isRegExp, + represent: representJavascriptRegExp +}); + +},{"../../type":13}],20:[function(require,module,exports){ +'use strict'; + +var Type = require('../../type'); + +function resolveJavascriptUndefined() { + return true; +} + +function constructJavascriptUndefined() { + /*eslint-disable no-undefined*/ + return undefined; +} + +function representJavascriptUndefined() { + return ''; +} + +function isUndefined(object) { + return typeof object === 'undefined'; +} + +module.exports = new Type('tag:yaml.org,2002:js/undefined', { + kind: 'scalar', + resolve: resolveJavascriptUndefined, + construct: constructJavascriptUndefined, + predicate: isUndefined, + represent: representJavascriptUndefined +}); + +},{"../../type":13}],21:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:map', { + kind: 'mapping', + construct: function (data) { return data !== null ? data : {}; } +}); + +},{"../type":13}],22:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +function resolveYamlMerge(data) { + return data === '<<' || data === null; +} + +module.exports = new Type('tag:yaml.org,2002:merge', { + kind: 'scalar', + resolve: resolveYamlMerge +}); + +},{"../type":13}],23:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +function resolveYamlNull(data) { + if (data === null) return true; + + var max = data.length; + + return (max === 1 && data === '~') || + (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL')); +} + +function constructYamlNull() { + return null; +} + +function isNull(object) { + return object === null; +} + +module.exports = new Type('tag:yaml.org,2002:null', { + kind: 'scalar', + resolve: resolveYamlNull, + construct: constructYamlNull, + predicate: isNull, + represent: { + canonical: function () { return '~'; }, + lowercase: function () { return 'null'; }, + uppercase: function () { return 'NULL'; }, + camelcase: function () { return 'Null'; } + }, + defaultStyle: 'lowercase' +}); + +},{"../type":13}],24:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var _hasOwnProperty = Object.prototype.hasOwnProperty; +var _toString = Object.prototype.toString; + +function resolveYamlOmap(data) { + if (data === null) return true; + + var objectKeys = [], index, length, pair, pairKey, pairHasKey, + object = data; + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + pairHasKey = false; + + if (_toString.call(pair) !== '[object Object]') return false; + + for (pairKey in pair) { + if (_hasOwnProperty.call(pair, pairKey)) { + if (!pairHasKey) pairHasKey = true; + else return false; + } + } + + if (!pairHasKey) return false; + + if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey); + else return false; + } + + return true; +} + +function constructYamlOmap(data) { + return data !== null ? data : []; +} + +module.exports = new Type('tag:yaml.org,2002:omap', { + kind: 'sequence', + resolve: resolveYamlOmap, + construct: constructYamlOmap +}); + +},{"../type":13}],25:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var _toString = Object.prototype.toString; + +function resolveYamlPairs(data) { + if (data === null) return true; + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + if (_toString.call(pair) !== '[object Object]') return false; + + keys = Object.keys(pair); + + if (keys.length !== 1) return false; + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return true; +} + +function constructYamlPairs(data) { + if (data === null) return []; + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + keys = Object.keys(pair); + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return result; +} + +module.exports = new Type('tag:yaml.org,2002:pairs', { + kind: 'sequence', + resolve: resolveYamlPairs, + construct: constructYamlPairs +}); + +},{"../type":13}],26:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:seq', { + kind: 'sequence', + construct: function (data) { return data !== null ? data : []; } +}); + +},{"../type":13}],27:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + +function resolveYamlSet(data) { + if (data === null) return true; + + var key, object = data; + + for (key in object) { + if (_hasOwnProperty.call(object, key)) { + if (object[key] !== null) return false; + } + } + + return true; +} + +function constructYamlSet(data) { + return data !== null ? data : {}; +} + +module.exports = new Type('tag:yaml.org,2002:set', { + kind: 'mapping', + resolve: resolveYamlSet, + construct: constructYamlSet +}); + +},{"../type":13}],28:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:str', { + kind: 'scalar', + construct: function (data) { return data !== null ? data : ''; } +}); + +},{"../type":13}],29:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var YAML_DATE_REGEXP = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9])' + // [2] month + '-([0-9][0-9])$'); // [3] day + +var YAML_TIMESTAMP_REGEXP = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9]?)' + // [2] month + '-([0-9][0-9]?)' + // [3] day + '(?:[Tt]|[ \\t]+)' + // ... + '([0-9][0-9]?)' + // [4] hour + ':([0-9][0-9])' + // [5] minute + ':([0-9][0-9])' + // [6] second + '(?:\\.([0-9]*))?' + // [7] fraction + '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour + '(?::([0-9][0-9]))?))?$'); // [11] tz_minute + +function resolveYamlTimestamp(data) { + if (data === null) return false; + if (YAML_DATE_REGEXP.exec(data) !== null) return true; + if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true; + return false; +} + +function constructYamlTimestamp(data) { + var match, year, month, day, hour, minute, second, fraction = 0, + delta = null, tz_hour, tz_minute, date; + + match = YAML_DATE_REGEXP.exec(data); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); + + if (match === null) throw new Error('Date resolve error'); + + // match: [1] year [2] month [3] day + + year = +(match[1]); + month = +(match[2]) - 1; // JS month starts with 0 + day = +(match[3]); + + if (!match[4]) { // no hour + return new Date(Date.UTC(year, month, day)); + } + + // match: [4] hour [5] minute [6] second [7] fraction + + hour = +(match[4]); + minute = +(match[5]); + second = +(match[6]); + + if (match[7]) { + fraction = match[7].slice(0, 3); + while (fraction.length < 3) { // milli-seconds + fraction += '0'; + } + fraction = +fraction; + } + + // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute + + if (match[9]) { + tz_hour = +(match[10]); + tz_minute = +(match[11] || 0); + delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds + if (match[9] === '-') delta = -delta; + } + + date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + + if (delta) date.setTime(date.getTime() - delta); + + return date; +} + +function representYamlTimestamp(object /*, style*/) { + return object.toISOString(); +} + +module.exports = new Type('tag:yaml.org,2002:timestamp', { + kind: 'scalar', + resolve: resolveYamlTimestamp, + construct: constructYamlTimestamp, + instanceOf: Date, + represent: representYamlTimestamp +}); + +},{"../type":13}],"/":[function(require,module,exports){ +'use strict'; + + +var yaml = require('./lib/js-yaml.js'); + + +module.exports = yaml; + +},{"./lib/js-yaml.js":1}]},{},[])("/") +}); \ No newline at end of file diff --git a/hm_sunwell/node_modules/js-yaml/dist/js-yaml.min.js b/hm_sunwell/node_modules/js-yaml/dist/js-yaml.min.js new file mode 100644 index 0000000..3f2f2a1 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/dist/js-yaml.min.js @@ -0,0 +1,3 @@ +/* js-yaml 3.6.1 https://github.com/nodeca/js-yaml */ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.jsyaml=e()}}(function(){return function e(t,n,i){function r(a,s){if(!n[a]){if(!t[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(o)return o(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[a]={exports:{}};t[a][0].call(l.exports,function(e){var n=t[a][1][e];return r(n?n:e)},l,l.exports,e,t,n,i)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;an;n+=1)r=o[n],e[r]=t[r];return e}function s(e,t){var n,i="";for(n=0;t>n;n+=1)i+=e;return i}function c(e){return 0===e&&Number.NEGATIVE_INFINITY===1/e}t.exports.isNothing=i,t.exports.isObject=r,t.exports.toArray=o,t.exports.repeat=s,t.exports.isNegativeZero=c,t.exports.extend=a},{}],3:[function(e,t,n){"use strict";function i(e,t){var n,i,r,o,a,s,c;if(null===t)return{};for(n={},i=Object.keys(t),r=0,o=i.length;o>r;r+=1)a=i[r],s=String(t[a]),"!!"===a.slice(0,2)&&(a="tag:yaml.org,2002:"+a.slice(2)),c=e.compiledTypeMap[a],c&&L.call(c.styleAliases,s)&&(s=c.styleAliases[s]),n[a]=s;return n}function r(e){var t,n,i;if(t=e.toString(16).toUpperCase(),255>=e)n="x",i=2;else if(65535>=e)n="u",i=4;else{if(!(4294967295>=e))throw new N("code point within a string may not be greater than 0xFFFFFFFF");n="U",i=8}return"\\"+n+F.repeat("0",i-t.length)+t}function o(e){this.schema=e.schema||M,this.indent=Math.max(1,e.indent||2),this.skipInvalid=e.skipInvalid||!1,this.flowLevel=F.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=i(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function a(e,t){for(var n,i=F.repeat(" ",t),r=0,o=-1,a="",s=e.length;s>r;)o=e.indexOf("\n",r),-1===o?(n=e.slice(r),r=s):(n=e.slice(r,o+1),r=o+1),n.length&&"\n"!==n&&(a+=i),a+=n;return a}function s(e,t){return"\n"+F.repeat(" ",e.indent*t)}function c(e,t){var n,i,r;for(n=0,i=e.implicitTypes.length;i>n;n+=1)if(r=e.implicitTypes[n],r.resolve(t))return!0;return!1}function u(e){return e===q||e===D}function l(e){return e>=32&&126>=e||e>=161&&55295>=e&&8232!==e&&8233!==e||e>=57344&&65533>=e&&65279!==e||e>=65536&&1114111>=e}function p(e){return l(e)&&65279!==e&&e!==H&&e!==Q&&e!==X&&e!==te&&e!==ie&&e!==V&&e!==B}function f(e){return l(e)&&65279!==e&&!u(e)&&e!==G&&e!==z&&e!==V&&e!==H&&e!==Q&&e!==X&&e!==te&&e!==ie&&e!==B&&e!==W&&e!==$&&e!==Y&&e!==ne&&e!==Z&&e!==K&&e!==R&&e!==P&&e!==J&&e!==ee}function d(e,t,n,i,r){var o,a,s=!1,c=!1,d=-1!==i,h=-1,m=f(e.charCodeAt(0))&&!u(e.charCodeAt(e.length-1));if(t)for(o=0;oi&&" "!==e[h+1],h=o);else if(!l(a))return le;m=m&&p(a)}c=c||d&&o-h-1>i&&" "!==e[h+1]}return s||c?" "===e[0]&&n>9?le:c?ue:ce:m&&!r(e)?ae:se}function h(e,t,n,i){e.dump=function(){function r(t){return c(e,t)}if(0===t.length)return"''";if(!e.noCompatMode&&-1!==oe.indexOf(t))return"'"+t+"'";var o=e.indent*Math.max(1,n),s=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-o),u=i||e.flowLevel>-1&&n>=e.flowLevel;switch(d(t,u,e.indent,s,r)){case ae:return t;case se:return"'"+t.replace(/'/g,"''")+"'";case ce:return"|"+m(t,e.indent)+g(a(t,o));case ue:return">"+m(t,e.indent)+g(a(y(t,s),o));case le:return'"'+v(t,s)+'"';default:throw new N("impossible error: invalid scalar style")}}()}function m(e,t){var n=" "===e[0]?String(t):"",i="\n"===e[e.length-1],r=i&&("\n"===e[e.length-2]||"\n"===e),o=r?"+":i?"":"-";return n+o+"\n"}function g(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function y(e,t){for(var n,i,r=/(\n+)([^\n]*)/g,o=function(){var n=e.indexOf("\n");return n=-1!==n?n:e.length,r.lastIndex=n,x(e.slice(0,n),t)}(),a="\n"===e[0]||" "===e[0];i=r.exec(e);){var s=i[1],c=i[2];n=" "===c[0],o+=s+(a||n||""===c?"":"\n")+x(c,t),a=n}return o}function x(e,t){if(""===e||" "===e[0])return e;for(var n,i,r=/ [^ ]/g,o=0,a=0,s=0,c="";n=r.exec(e);)s=n.index,s-o>t&&(i=a>o?a:s,c+="\n"+e.slice(o,i),o=i+1),a=s;return c+="\n",c+=e.length-o>t&&a>o?e.slice(o,a)+"\n"+e.slice(a+1):e.slice(o),c.slice(1)}function v(e){for(var t,n,i="",o=0;oi;i+=1)j(e,t,n[i],!1,!1)&&(0!==i&&(o+=", "),o+=e.dump);e.tag=a,e.dump="["+o+"]"}function b(e,t,n,i){var r,o,a="",c=e.tag;for(r=0,o=n.length;o>r;r+=1)j(e,t+1,n[r],!0,!0)&&(i&&0===r||(a+=s(e,t)),a+="- "+e.dump);e.tag=c,e.dump=a||"[]"}function w(e,t,n){var i,r,o,a,s,c="",u=e.tag,l=Object.keys(n);for(i=0,r=l.length;r>i;i+=1)s="",0!==i&&(s+=", "),o=l[i],a=n[o],j(e,t,o,!1,!1)&&(e.dump.length>1024&&(s+="? "),s+=e.dump+": ",j(e,t,a,!1,!1)&&(s+=e.dump,c+=s));e.tag=u,e.dump="{"+c+"}"}function C(e,t,n,i){var r,o,a,c,u,l,p="",f=e.tag,d=Object.keys(n);if(e.sortKeys===!0)d.sort();else if("function"==typeof e.sortKeys)d.sort(e.sortKeys);else if(e.sortKeys)throw new N("sortKeys must be a boolean or a function");for(r=0,o=d.length;o>r;r+=1)l="",i&&0===r||(l+=s(e,t)),a=d[r],c=n[a],j(e,t+1,a,!0,!0,!0)&&(u=null!==e.tag&&"?"!==e.tag||e.dump&&e.dump.length>1024,u&&(l+=e.dump&&U===e.dump.charCodeAt(0)?"?":"? "),l+=e.dump,u&&(l+=s(e,t)),j(e,t+1,c,!0,u)&&(l+=e.dump&&U===e.dump.charCodeAt(0)?":":": ",l+=e.dump,p+=l));e.tag=f,e.dump=p||"{}"}function k(e,t,n){var i,r,o,a,s,c;for(r=n?e.explicitTypes:e.implicitTypes,o=0,a=r.length;a>o;o+=1)if(s=r[o],(s.instanceOf||s.predicate)&&(!s.instanceOf||"object"==typeof t&&t instanceof s.instanceOf)&&(!s.predicate||s.predicate(t))){if(e.tag=n?s.tag:"?",s.represent){if(c=e.styleMap[s.tag]||s.defaultStyle,"[object Function]"===T.call(s.represent))i=s.represent(t,c);else{if(!L.call(s.represent,c))throw new N("!<"+s.tag+'> tag resolver accepts not "'+c+'" style');i=s.represent[c](t,c)}e.dump=i}return!0}return!1}function j(e,t,n,i,r,o){e.tag=null,e.dump=n,k(e,n,!1)||k(e,n,!0);var a=T.call(e.dump);i&&(i=e.flowLevel<0||e.flowLevel>t);var s,c,u="[object Object]"===a||"[object Array]"===a;if(u&&(s=e.duplicates.indexOf(n),c=-1!==s),(null!==e.tag&&"?"!==e.tag||c||2!==e.indent&&t>0)&&(r=!1),c&&e.usedDuplicates[s])e.dump="*ref_"+s;else{if(u&&c&&!e.usedDuplicates[s]&&(e.usedDuplicates[s]=!0),"[object Object]"===a)i&&0!==Object.keys(e.dump).length?(C(e,t,e.dump,r),c&&(e.dump="&ref_"+s+e.dump)):(w(e,t,e.dump),c&&(e.dump="&ref_"+s+" "+e.dump));else if("[object Array]"===a)i&&0!==e.dump.length?(b(e,t,e.dump,r),c&&(e.dump="&ref_"+s+e.dump)):(A(e,t,e.dump),c&&(e.dump="&ref_"+s+" "+e.dump));else{if("[object String]"!==a){if(e.skipInvalid)return!1;throw new N("unacceptable kind of an object to dump "+a)}"?"!==e.tag&&h(e,e.dump,t,o)}null!==e.tag&&"?"!==e.tag&&(e.dump="!<"+e.tag+"> "+e.dump)}return!0}function I(e,t){var n,i,r=[],o=[];for(S(e,r,o),n=0,i=o.length;i>n;n+=1)t.duplicates.push(r[o[n]]);t.usedDuplicates=new Array(i)}function S(e,t,n){var i,r,o;if(null!==e&&"object"==typeof e)if(r=t.indexOf(e),-1!==r)-1===n.indexOf(r)&&n.push(r);else if(t.push(e),Array.isArray(e))for(r=0,o=e.length;o>r;r+=1)S(e[r],t,n);else for(i=Object.keys(e),r=0,o=i.length;o>r;r+=1)S(e[i[r]],t,n)}function O(e,t){t=t||{};var n=new o(t);return n.noRefs||I(e,n),j(n,0,e,!0,!0)?n.dump+"\n":""}function E(e,t){return O(e,F.extend({schema:_},t))}var F=e("./common"),N=e("./exception"),M=e("./schema/default_full"),_=e("./schema/default_safe"),T=Object.prototype.toString,L=Object.prototype.hasOwnProperty,D=9,U=10,q=32,Y=33,R=34,B=35,P=37,W=38,K=39,$=42,H=44,G=45,V=58,Z=62,z=63,J=64,Q=91,X=93,ee=96,te=123,ne=124,ie=125,re={};re[0]="\\0",re[7]="\\a",re[8]="\\b",re[9]="\\t",re[10]="\\n",re[11]="\\v",re[12]="\\f",re[13]="\\r",re[27]="\\e",re[34]='\\"',re[92]="\\\\",re[133]="\\N",re[160]="\\_",re[8232]="\\L",re[8233]="\\P";var oe=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],ae=1,se=2,ce=3,ue=4,le=5;t.exports.dump=O,t.exports.safeDump=E},{"./common":2,"./exception":4,"./schema/default_full":9,"./schema/default_safe":10}],4:[function(e,t,n){"use strict";function i(e,t){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack||"",this.name="YAMLException",this.reason=e,this.mark=t,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():"")}i.prototype=Object.create(Error.prototype),i.prototype.constructor=i,i.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t},t.exports=i},{}],5:[function(e,t,n){"use strict";function i(e){return 10===e||13===e}function r(e){return 9===e||32===e}function o(e){return 9===e||32===e||10===e||13===e}function a(e){return 44===e||91===e||93===e||123===e||125===e}function s(e){var t;return e>=48&&57>=e?e-48:(t=32|e,t>=97&&102>=t?t-97+10:-1)}function c(e){return 120===e?2:117===e?4:85===e?8:0}function u(e){return e>=48&&57>=e?e-48:-1}function l(e){return 48===e?"\x00":97===e?"":98===e?"\b":116===e?" ":9===e?" ":110===e?"\n":118===e?"\x0B":102===e?"\f":114===e?"\r":101===e?"":32===e?" ":34===e?'"':47===e?"/":92===e?"\\":78===e?"…":95===e?" ":76===e?"\u2028":80===e?"\u2029":""}function p(e){return 65535>=e?String.fromCharCode(e):String.fromCharCode((e-65536>>10)+55296,(e-65536&1023)+56320)}function f(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||K,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function d(e,t){return new B(t,new P(e.filename,e.input,e.position,e.line,e.position-e.lineStart))}function h(e,t){throw d(e,t)}function m(e,t){e.onWarning&&e.onWarning.call(null,d(e,t))}function g(e,t,n,i){var r,o,a,s;if(n>t){if(s=e.input.slice(t,n),i)for(r=0,o=s.length;o>r;r+=1)a=s.charCodeAt(r),9===a||a>=32&&1114111>=a||h(e,"expected valid JSON character");else X.test(s)&&h(e,"the stream contains non-printable characters");e.result+=s}}function y(e,t,n,i){var r,o,a,s;for(R.isObject(n)||h(e,"cannot merge mappings; the provided source object is unacceptable"),r=Object.keys(n),a=0,s=r.length;s>a;a+=1)o=r[a],$.call(t,o)||(t[o]=n[o],i[o]=!0)}function x(e,t,n,i,r,o){var a,s;if(r=String(r),null===t&&(t={}),"tag:yaml.org,2002:merge"===i)if(Array.isArray(o))for(a=0,s=o.length;s>a;a+=1)y(e,t,o[a],n);else y(e,t,o,n);else e.json||$.call(n,r)||!$.call(t,r)||h(e,"duplicated mapping key"),t[r]=o,delete n[r];return t}function v(e){var t;t=e.input.charCodeAt(e.position),10===t?e.position++:13===t?(e.position++,10===e.input.charCodeAt(e.position)&&e.position++):h(e,"a line break is expected"),e.line+=1,e.lineStart=e.position}function A(e,t,n){for(var o=0,a=e.input.charCodeAt(e.position);0!==a;){for(;r(a);)a=e.input.charCodeAt(++e.position);if(t&&35===a)do a=e.input.charCodeAt(++e.position);while(10!==a&&13!==a&&0!==a);if(!i(a))break;for(v(e),a=e.input.charCodeAt(e.position),o++,e.lineIndent=0;32===a;)e.lineIndent++,a=e.input.charCodeAt(++e.position)}return-1!==n&&0!==o&&e.lineIndent1&&(e.result+=R.repeat("\n",t-1))}function C(e,t,n){var s,c,u,l,p,f,d,h,m,y=e.kind,x=e.result;if(m=e.input.charCodeAt(e.position),o(m)||a(m)||35===m||38===m||42===m||33===m||124===m||62===m||39===m||34===m||37===m||64===m||96===m)return!1;if((63===m||45===m)&&(c=e.input.charCodeAt(e.position+1),o(c)||n&&a(c)))return!1;for(e.kind="scalar",e.result="",u=l=e.position,p=!1;0!==m;){if(58===m){if(c=e.input.charCodeAt(e.position+1),o(c)||n&&a(c))break}else if(35===m){if(s=e.input.charCodeAt(e.position-1),o(s))break}else{if(e.position===e.lineStart&&b(e)||n&&a(m))break;if(i(m)){if(f=e.line,d=e.lineStart,h=e.lineIndent,A(e,!1,-1),e.lineIndent>=t){p=!0,m=e.input.charCodeAt(e.position);continue}e.position=l,e.line=f,e.lineStart=d,e.lineIndent=h;break}}p&&(g(e,u,l,!1),w(e,e.line-f),u=l=e.position,p=!1),r(m)||(l=e.position+1),m=e.input.charCodeAt(++e.position)}return g(e,u,l,!1),e.result?!0:(e.kind=y,e.result=x,!1)}function k(e,t){var n,r,o;if(n=e.input.charCodeAt(e.position),39!==n)return!1;for(e.kind="scalar",e.result="",e.position++,r=o=e.position;0!==(n=e.input.charCodeAt(e.position));)if(39===n){if(g(e,r,e.position,!0),n=e.input.charCodeAt(++e.position),39!==n)return!0;r=o=e.position,e.position++}else i(n)?(g(e,r,o,!0),w(e,A(e,!1,t)),r=o=e.position):e.position===e.lineStart&&b(e)?h(e,"unexpected end of the document within a single quoted scalar"):(e.position++,o=e.position);h(e,"unexpected end of the stream within a single quoted scalar")}function j(e,t){var n,r,o,a,u,l;if(l=e.input.charCodeAt(e.position),34!==l)return!1;for(e.kind="scalar",e.result="",e.position++,n=r=e.position;0!==(l=e.input.charCodeAt(e.position));){if(34===l)return g(e,n,e.position,!0),e.position++,!0;if(92===l){if(g(e,n,e.position,!0),l=e.input.charCodeAt(++e.position),i(l))A(e,!1,t);else if(256>l&&re[l])e.result+=oe[l],e.position++;else if((u=c(l))>0){for(o=u,a=0;o>0;o--)l=e.input.charCodeAt(++e.position),(u=s(l))>=0?a=(a<<4)+u:h(e,"expected hexadecimal character");e.result+=p(a),e.position++}else h(e,"unknown escape sequence");n=r=e.position}else i(l)?(g(e,n,r,!0),w(e,A(e,!1,t)),n=r=e.position):e.position===e.lineStart&&b(e)?h(e,"unexpected end of the document within a double quoted scalar"):(e.position++,r=e.position)}h(e,"unexpected end of the stream within a double quoted scalar")}function I(e,t){var n,i,r,a,s,c,u,l,p,f,d,m=!0,g=e.tag,y=e.anchor,v={};if(d=e.input.charCodeAt(e.position),91===d)a=93,u=!1,i=[];else{if(123!==d)return!1;a=125,u=!0,i={}}for(null!==e.anchor&&(e.anchorMap[e.anchor]=i),d=e.input.charCodeAt(++e.position);0!==d;){if(A(e,!0,t),d=e.input.charCodeAt(e.position),d===a)return e.position++,e.tag=g,e.anchor=y,e.kind=u?"mapping":"sequence",e.result=i,!0;m||h(e,"missed comma between flow collection entries"),p=l=f=null,s=c=!1,63===d&&(r=e.input.charCodeAt(e.position+1),o(r)&&(s=c=!0,e.position++,A(e,!0,t))),n=e.line,_(e,t,H,!1,!0),p=e.tag,l=e.result,A(e,!0,t),d=e.input.charCodeAt(e.position),!c&&e.line!==n||58!==d||(s=!0,d=e.input.charCodeAt(++e.position),A(e,!0,t),_(e,t,H,!1,!0),f=e.result),u?x(e,i,v,p,l,f):s?i.push(x(e,null,v,p,l,f)):i.push(l),A(e,!0,t),d=e.input.charCodeAt(e.position),44===d?(m=!0,d=e.input.charCodeAt(++e.position)):m=!1}h(e,"unexpected end of the stream within a flow collection")}function S(e,t){var n,o,a,s,c=z,l=!1,p=!1,f=t,d=0,m=!1;if(s=e.input.charCodeAt(e.position),124===s)o=!1;else{if(62!==s)return!1;o=!0}for(e.kind="scalar",e.result="";0!==s;)if(s=e.input.charCodeAt(++e.position),43===s||45===s)z===c?c=43===s?Q:J:h(e,"repeat of a chomping mode identifier");else{if(!((a=u(s))>=0))break;0===a?h(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):p?h(e,"repeat of an indentation width identifier"):(f=t+a-1,p=!0)}if(r(s)){do s=e.input.charCodeAt(++e.position);while(r(s));if(35===s)do s=e.input.charCodeAt(++e.position);while(!i(s)&&0!==s)}for(;0!==s;){for(v(e),e.lineIndent=0,s=e.input.charCodeAt(e.position);(!p||e.lineIndentf&&(f=e.lineIndent),i(s))d++;else{if(e.lineIndentt)&&0!==r)h(e,"bad indentation of a sequence entry");else if(e.lineIndentt)&&(_(e,t,Z,!0,a)&&(y?m=e.result:g=e.result),y||(x(e,p,f,d,m,g),d=m=g=null),A(e,!0,-1),c=e.input.charCodeAt(e.position)),e.lineIndent>t&&0!==c)h(e,"bad indentation of a mapping entry");else if(e.lineIndentt?d=1:e.lineIndent===t?d=0:e.lineIndentt?d=1:e.lineIndent===t?d=0:e.lineIndentc;c+=1)if(l=e.implicitTypes[c],l.resolve(e.result)){e.result=l.construct(e.result),e.tag=l.tag,null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);break}}else $.call(e.typeMap,e.tag)?(l=e.typeMap[e.tag],null!==e.result&&l.kind!==e.kind&&h(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+l.kind+'", not "'+e.kind+'"'),l.resolve(e.result)?(e.result=l.construct(e.result),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):h(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")):h(e,"unknown tag !<"+e.tag+">");return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||g}function T(e){var t,n,a,s,c=e.position,u=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap={},e.anchorMap={};0!==(s=e.input.charCodeAt(e.position))&&(A(e,!0,-1),s=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==s));){for(u=!0,s=e.input.charCodeAt(++e.position),t=e.position;0!==s&&!o(s);)s=e.input.charCodeAt(++e.position);for(n=e.input.slice(t,e.position),a=[],n.length<1&&h(e,"directive name must not be less than one character in length");0!==s;){for(;r(s);)s=e.input.charCodeAt(++e.position);if(35===s){do s=e.input.charCodeAt(++e.position);while(0!==s&&!i(s));break}if(i(s))break;for(t=e.position;0!==s&&!o(s);)s=e.input.charCodeAt(++e.position);a.push(e.input.slice(t,e.position))}0!==s&&v(e),$.call(se,n)?se[n](e,n,a):m(e,'unknown document directive "'+n+'"')}return A(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,A(e,!0,-1)):u&&h(e,"directives end mark is expected"),_(e,e.lineIndent-1,Z,!1,!0),A(e,!0,-1),e.checkLineBreaks&&ee.test(e.input.slice(c,e.position))&&m(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&b(e)?void(46===e.input.charCodeAt(e.position)&&(e.position+=3,A(e,!0,-1))):void(e.positioni;i+=1)t(o[i])}function U(e,t){var n=L(e,t);if(0!==n.length){if(1===n.length)return n[0];throw new B("expected a single document in the stream, but found more")}}function q(e,t,n){D(e,t,R.extend({schema:W},n))}function Y(e,t){return U(e,R.extend({schema:W},t))}for(var R=e("./common"),B=e("./exception"),P=e("./mark"),W=e("./schema/default_safe"),K=e("./schema/default_full"),$=Object.prototype.hasOwnProperty,H=1,G=2,V=3,Z=4,z=1,J=2,Q=3,X=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,ee=/[\x85\u2028\u2029]/,te=/[,\[\]\{\}]/,ne=/^(?:!|!!|![a-z\-]+!)$/i,ie=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i,re=new Array(256),oe=new Array(256),ae=0;256>ae;ae++)re[ae]=l(ae)?1:0,oe[ae]=l(ae);var se={YAML:function(e,t,n){var i,r,o;null!==e.version&&h(e,"duplication of %YAML directive"),1!==n.length&&h(e,"YAML directive accepts exactly one argument"),i=/^([0-9]+)\.([0-9]+)$/.exec(n[0]),null===i&&h(e,"ill-formed argument of the YAML directive"),r=parseInt(i[1],10),o=parseInt(i[2],10),1!==r&&h(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=2>o,1!==o&&2!==o&&m(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var i,r;2!==n.length&&h(e,"TAG directive accepts exactly two arguments"),i=n[0],r=n[1],ne.test(i)||h(e,"ill-formed tag handle (first argument) of the TAG directive"),$.call(e.tagMap,i)&&h(e,'there is a previously declared suffix for "'+i+'" tag handle'),ie.test(r)||h(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[i]=r}};t.exports.loadAll=D,t.exports.load=U,t.exports.safeLoadAll=q,t.exports.safeLoad=Y},{"./common":2,"./exception":4,"./mark":6,"./schema/default_full":9,"./schema/default_safe":10}],6:[function(e,t,n){"use strict";function i(e,t,n,i,r){this.name=e,this.buffer=t,this.position=n,this.line=i,this.column=r}var r=e("./common");i.prototype.getSnippet=function(e,t){var n,i,o,a,s;if(!this.buffer)return null;for(e=e||4,t=t||75,n="",i=this.position;i>0&&-1==="\x00\r\n…\u2028\u2029".indexOf(this.buffer.charAt(i-1));)if(i-=1,this.position-i>t/2-1){n=" ... ",i+=5;break}for(o="",a=this.position;at/2-1){o=" ... ",a-=5;break}return s=this.buffer.slice(i,a),r.repeat(" ",e)+n+s+o+"\n"+r.repeat(" ",e+this.position-i+n.length)+"^"},i.prototype.toString=function(e){var t,n="";return this.name&&(n+='in "'+this.name+'" '),n+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet(),t&&(n+=":\n"+t)),n},t.exports=i},{"./common":2}],7:[function(e,t,n){"use strict";function i(e,t,n){var r=[];return e.include.forEach(function(e){n=i(e,t,n)}),e[t].forEach(function(e){n.forEach(function(t,n){t.tag===e.tag&&r.push(n)}),n.push(e)}),n.filter(function(e,t){return-1===r.indexOf(t)})}function r(){function e(e){i[e.tag]=e}var t,n,i={};for(t=0,n=arguments.length;n>t;t+=1)arguments[t].forEach(e);return i}function o(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&"scalar"!==e.loadKind)throw new s("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")}),this.compiledImplicit=i(this,"implicit",[]),this.compiledExplicit=i(this,"explicit",[]),this.compiledTypeMap=r(this.compiledImplicit,this.compiledExplicit)}var a=e("./common"),s=e("./exception"),c=e("./type");o.DEFAULT=null,o.create=function(){var e,t;switch(arguments.length){case 1:e=o.DEFAULT,t=arguments[0];break;case 2:e=arguments[0],t=arguments[1];break;default:throw new s("Wrong number of arguments for Schema.create function")}if(e=a.toArray(e),t=a.toArray(t),!e.every(function(e){return e instanceof o}))throw new s("Specified list of super schemas (or a single Schema object) contains a non-Schema object.");if(!t.every(function(e){return e instanceof c}))throw new s("Specified list of YAML types (or a single Type object) contains a non-Type object.");return new o({include:e,explicit:t})},t.exports=o},{"./common":2,"./exception":4,"./type":13}],8:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({include:[e("./json")]})},{"../schema":7,"./json":12}],9:[function(e,t,n){"use strict";var i=e("../schema");t.exports=i.DEFAULT=new i({include:[e("./default_safe")],explicit:[e("../type/js/undefined"),e("../type/js/regexp"),e("../type/js/function")]})},{"../schema":7,"../type/js/function":18,"../type/js/regexp":19,"../type/js/undefined":20,"./default_safe":10}],10:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({include:[e("./core")],implicit:[e("../type/timestamp"),e("../type/merge")],explicit:[e("../type/binary"),e("../type/omap"),e("../type/pairs"),e("../type/set")]})},{"../schema":7,"../type/binary":14,"../type/merge":22,"../type/omap":24,"../type/pairs":25,"../type/set":27,"../type/timestamp":29,"./core":8}],11:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({explicit:[e("../type/str"),e("../type/seq"),e("../type/map")]})},{"../schema":7,"../type/map":21,"../type/seq":26,"../type/str":28}],12:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({include:[e("./failsafe")],implicit:[e("../type/null"),e("../type/bool"),e("../type/int"),e("../type/float")]})},{"../schema":7,"../type/bool":15,"../type/float":16,"../type/int":17,"../type/null":23,"./failsafe":11}],13:[function(e,t,n){"use strict";function i(e){var t={};return null!==e&&Object.keys(e).forEach(function(n){e[n].forEach(function(e){t[String(e)]=n})}),t}function r(e,t){if(t=t||{},Object.keys(t).forEach(function(t){if(-1===a.indexOf(t))throw new o('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')}),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.defaultStyle=t.defaultStyle||null,this.styleAliases=i(t.styleAliases||null),-1===s.indexOf(this.kind))throw new o('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')}var o=e("./exception"),a=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],s=["scalar","sequence","mapping"];t.exports=r},{"./exception":4}],14:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;var t,n,i=0,r=e.length,o=p;for(n=0;r>n;n++)if(t=o.indexOf(e.charAt(n)),!(t>64)){if(0>t)return!1;i+=6}return i%8===0}function r(e){var t,n,i=e.replace(/[\r\n=]/g,""),r=i.length,o=p,a=0,c=[];for(t=0;r>t;t++)t%4===0&&t&&(c.push(a>>16&255),c.push(a>>8&255),c.push(255&a)),a=a<<6|o.indexOf(i.charAt(t));return n=r%4*6,0===n?(c.push(a>>16&255),c.push(a>>8&255),c.push(255&a)):18===n?(c.push(a>>10&255),c.push(a>>2&255)):12===n&&c.push(a>>4&255),s?new s(c):c}function o(e){var t,n,i="",r=0,o=e.length,a=p;for(t=0;o>t;t++)t%3===0&&t&&(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t];return n=o%3,0===n?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}function a(e){return s&&s.isBuffer(e)}var s;try{var c=e;s=c("buffer").Buffer; +}catch(u){}var l=e("../type"),p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";t.exports=new l("tag:yaml.org,2002:binary",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../type":13}],15:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)}function r(e){return"true"===e||"True"===e||"TRUE"===e}function o(e){return"[object Boolean]"===Object.prototype.toString.call(e)}var a=e("../type");t.exports=new a("tag:yaml.org,2002:bool",{kind:"scalar",resolve:i,construct:r,predicate:o,represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"})},{"../type":13}],16:[function(e,t,n){"use strict";function i(e){return null===e?!1:!!u.test(e)}function r(e){var t,n,i,r;return t=e.replace(/_/g,"").toLowerCase(),n="-"===t[0]?-1:1,r=[],"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:t.indexOf(":")>=0?(t.split(":").forEach(function(e){r.unshift(parseFloat(e,10))}),t=0,i=1,r.forEach(function(e){t+=e*i,i*=60}),n*t):n*parseFloat(t,10)}function o(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(s.isNegativeZero(e))return"-0.0";return n=e.toString(10),l.test(n)?n.replace("e",".e"):n}function a(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!==0||s.isNegativeZero(e))}var s=e("../common"),c=e("../type"),u=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?|\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"),l=/^[-+]?[0-9]+e/;t.exports=new c("tag:yaml.org,2002:float",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o,defaultStyle:"lowercase"})},{"../common":2,"../type":13}],17:[function(e,t,n){"use strict";function i(e){return e>=48&&57>=e||e>=65&&70>=e||e>=97&&102>=e}function r(e){return e>=48&&55>=e}function o(e){return e>=48&&57>=e}function a(e){if(null===e)return!1;var t,n=e.length,a=0,s=!1;if(!n)return!1;if(t=e[a],"-"!==t&&"+"!==t||(t=e[++a]),"0"===t){if(a+1===n)return!0;if(t=e[++a],"b"===t){for(a++;n>a;a++)if(t=e[a],"_"!==t){if("0"!==t&&"1"!==t)return!1;s=!0}return s}if("x"===t){for(a++;n>a;a++)if(t=e[a],"_"!==t){if(!i(e.charCodeAt(a)))return!1;s=!0}return s}for(;n>a;a++)if(t=e[a],"_"!==t){if(!r(e.charCodeAt(a)))return!1;s=!0}return s}for(;n>a;a++)if(t=e[a],"_"!==t){if(":"===t)break;if(!o(e.charCodeAt(a)))return!1;s=!0}return s?":"!==t?!0:/^(:[0-5]?[0-9])+$/.test(e.slice(a)):!1}function s(e){var t,n,i=e,r=1,o=[];return-1!==i.indexOf("_")&&(i=i.replace(/_/g,"")),t=i[0],"-"!==t&&"+"!==t||("-"===t&&(r=-1),i=i.slice(1),t=i[0]),"0"===i?0:"0"===t?"b"===i[1]?r*parseInt(i.slice(2),2):"x"===i[1]?r*parseInt(i,16):r*parseInt(i,8):-1!==i.indexOf(":")?(i.split(":").forEach(function(e){o.unshift(parseInt(e,10))}),i=0,n=1,o.forEach(function(e){i+=e*n,n*=60}),r*i):r*parseInt(i,10)}function c(e){return"[object Number]"===Object.prototype.toString.call(e)&&e%1===0&&!u.isNegativeZero(e)}var u=e("../common"),l=e("../type");t.exports=new l("tag:yaml.org,2002:int",{kind:"scalar",resolve:a,construct:s,predicate:c,represent:{binary:function(e){return"0b"+e.toString(2)},octal:function(e){return"0"+e.toString(8)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return"0x"+e.toString(16).toUpperCase()}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})},{"../common":2,"../type":13}],18:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;try{var t="("+e+")",n=s.parse(t,{range:!0});return"Program"===n.type&&1===n.body.length&&"ExpressionStatement"===n.body[0].type&&"FunctionExpression"===n.body[0].expression.type}catch(i){return!1}}function r(e){var t,n="("+e+")",i=s.parse(n,{range:!0}),r=[];if("Program"!==i.type||1!==i.body.length||"ExpressionStatement"!==i.body[0].type||"FunctionExpression"!==i.body[0].expression.type)throw new Error("Failed to resolve function");return i.body[0].expression.params.forEach(function(e){r.push(e.name)}),t=i.body[0].expression.body.range,new Function(r,n.slice(t[0]+1,t[1]-1))}function o(e){return e.toString()}function a(e){return"[object Function]"===Object.prototype.toString.call(e)}var s;try{var c=e;s=c("esprima")}catch(u){"undefined"!=typeof window&&(s=window.esprima)}var l=e("../../type");t.exports=new l("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../../type":13}],19:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;if(0===e.length)return!1;var t=e,n=/\/([gim]*)$/.exec(e),i="";if("/"===t[0]){if(n&&(i=n[1]),i.length>3)return!1;if("/"!==t[t.length-i.length-1])return!1}return!0}function r(e){var t=e,n=/\/([gim]*)$/.exec(e),i="";return"/"===t[0]&&(n&&(i=n[1]),t=t.slice(1,t.length-i.length-1)),new RegExp(t,i)}function o(e){var t="/"+e.source+"/";return e.global&&(t+="g"),e.multiline&&(t+="m"),e.ignoreCase&&(t+="i"),t}function a(e){return"[object RegExp]"===Object.prototype.toString.call(e)}var s=e("../../type");t.exports=new s("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../../type":13}],20:[function(e,t,n){"use strict";function i(){return!0}function r(){}function o(){return""}function a(e){return"undefined"==typeof e}var s=e("../../type");t.exports=new s("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../../type":13}],21:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return null!==e?e:{}}})},{"../type":13}],22:[function(e,t,n){"use strict";function i(e){return"<<"===e||null===e}var r=e("../type");t.exports=new r("tag:yaml.org,2002:merge",{kind:"scalar",resolve:i})},{"../type":13}],23:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t=e.length;return 1===t&&"~"===e||4===t&&("null"===e||"Null"===e||"NULL"===e)}function r(){return null}function o(e){return null===e}var a=e("../type");t.exports=new a("tag:yaml.org,2002:null",{kind:"scalar",resolve:i,construct:r,predicate:o,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})},{"../type":13}],24:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t,n,i,r,o,c=[],u=e;for(t=0,n=u.length;n>t;t+=1){if(i=u[t],o=!1,"[object Object]"!==s.call(i))return!1;for(r in i)if(a.call(i,r)){if(o)return!1;o=!0}if(!o)return!1;if(-1!==c.indexOf(r))return!1;c.push(r)}return!0}function r(e){return null!==e?e:[]}var o=e("../type"),a=Object.prototype.hasOwnProperty,s=Object.prototype.toString;t.exports=new o("tag:yaml.org,2002:omap",{kind:"sequence",resolve:i,construct:r})},{"../type":13}],25:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t,n,i,r,o,s=e;for(o=new Array(s.length),t=0,n=s.length;n>t;t+=1){if(i=s[t],"[object Object]"!==a.call(i))return!1;if(r=Object.keys(i),1!==r.length)return!1;o[t]=[r[0],i[r[0]]]}return!0}function r(e){if(null===e)return[];var t,n,i,r,o,a=e;for(o=new Array(a.length),t=0,n=a.length;n>t;t+=1)i=a[t],r=Object.keys(i),o[t]=[r[0],i[r[0]]];return o}var o=e("../type"),a=Object.prototype.toString;t.exports=new o("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:i,construct:r})},{"../type":13}],26:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return null!==e?e:[]}})},{"../type":13}],27:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t,n=e;for(t in n)if(a.call(n,t)&&null!==n[t])return!1;return!0}function r(e){return null!==e?e:{}}var o=e("../type"),a=Object.prototype.hasOwnProperty;t.exports=new o("tag:yaml.org,2002:set",{kind:"mapping",resolve:i,construct:r})},{"../type":13}],28:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return null!==e?e:""}})},{"../type":13}],29:[function(e,t,n){"use strict";function i(e){return null===e?!1:null!==s.exec(e)?!0:null!==c.exec(e)}function r(e){var t,n,i,r,o,a,u,l,p,f,d=0,h=null;if(t=s.exec(e),null===t&&(t=c.exec(e)),null===t)throw new Error("Date resolve error");if(n=+t[1],i=+t[2]-1,r=+t[3],!t[4])return new Date(Date.UTC(n,i,r));if(o=+t[4],a=+t[5],u=+t[6],t[7]){for(d=t[7].slice(0,3);d.length<3;)d+="0";d=+d}return t[9]&&(l=+t[10],p=+(t[11]||0),h=6e4*(60*l+p),"-"===t[9]&&(h=-h)),f=new Date(Date.UTC(n,i,r,o,a,u,d)),h&&f.setTime(f.getTime()-h),f}function o(e){return e.toISOString()}var a=e("../type"),s=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),c=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");t.exports=new a("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:i,construct:r,instanceOf:Date,represent:o})},{"../type":13}],"/":[function(e,t,n){"use strict";var i=e("./lib/js-yaml.js");t.exports=i},{"./lib/js-yaml.js":1}]},{},[])("/")}); diff --git a/hm_sunwell/node_modules/js-yaml/index.js b/hm_sunwell/node_modules/js-yaml/index.js new file mode 100644 index 0000000..1374435 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/index.js @@ -0,0 +1,7 @@ +'use strict'; + + +var yaml = require('./lib/js-yaml.js'); + + +module.exports = yaml; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml.js new file mode 100644 index 0000000..f0e9281 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml.js @@ -0,0 +1,39 @@ +'use strict'; + + +var loader = require('./js-yaml/loader'); +var dumper = require('./js-yaml/dumper'); + + +function deprecated(name) { + return function () { + throw new Error('Function ' + name + ' is deprecated and cannot be used.'); + }; +} + + +module.exports.Type = require('./js-yaml/type'); +module.exports.Schema = require('./js-yaml/schema'); +module.exports.FAILSAFE_SCHEMA = require('./js-yaml/schema/failsafe'); +module.exports.JSON_SCHEMA = require('./js-yaml/schema/json'); +module.exports.CORE_SCHEMA = require('./js-yaml/schema/core'); +module.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe'); +module.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full'); +module.exports.load = loader.load; +module.exports.loadAll = loader.loadAll; +module.exports.safeLoad = loader.safeLoad; +module.exports.safeLoadAll = loader.safeLoadAll; +module.exports.dump = dumper.dump; +module.exports.safeDump = dumper.safeDump; +module.exports.YAMLException = require('./js-yaml/exception'); + +// Deprecated schema names from JS-YAML 2.0.x +module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe'); +module.exports.SAFE_SCHEMA = require('./js-yaml/schema/default_safe'); +module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full'); + +// Deprecated functions from JS-YAML 1.x.x +module.exports.scan = deprecated('scan'); +module.exports.parse = deprecated('parse'); +module.exports.compose = deprecated('compose'); +module.exports.addConstructor = deprecated('addConstructor'); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/common.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/common.js new file mode 100644 index 0000000..25ef7d8 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/common.js @@ -0,0 +1,59 @@ +'use strict'; + + +function isNothing(subject) { + return (typeof subject === 'undefined') || (subject === null); +} + + +function isObject(subject) { + return (typeof subject === 'object') && (subject !== null); +} + + +function toArray(sequence) { + if (Array.isArray(sequence)) return sequence; + else if (isNothing(sequence)) return []; + + return [ sequence ]; +} + + +function extend(target, source) { + var index, length, key, sourceKeys; + + if (source) { + sourceKeys = Object.keys(source); + + for (index = 0, length = sourceKeys.length; index < length; index += 1) { + key = sourceKeys[index]; + target[key] = source[key]; + } + } + + return target; +} + + +function repeat(string, count) { + var result = '', cycle; + + for (cycle = 0; cycle < count; cycle += 1) { + result += string; + } + + return result; +} + + +function isNegativeZero(number) { + return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number); +} + + +module.exports.isNothing = isNothing; +module.exports.isObject = isObject; +module.exports.toArray = toArray; +module.exports.repeat = repeat; +module.exports.isNegativeZero = isNegativeZero; +module.exports.extend = extend; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/dumper.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/dumper.js new file mode 100644 index 0000000..41d3d45 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/dumper.js @@ -0,0 +1,802 @@ +'use strict'; + +/*eslint-disable no-use-before-define*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var DEFAULT_FULL_SCHEMA = require('./schema/default_full'); +var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe'); + +var _toString = Object.prototype.toString; +var _hasOwnProperty = Object.prototype.hasOwnProperty; + +var CHAR_TAB = 0x09; /* Tab */ +var CHAR_LINE_FEED = 0x0A; /* LF */ +var CHAR_SPACE = 0x20; /* Space */ +var CHAR_EXCLAMATION = 0x21; /* ! */ +var CHAR_DOUBLE_QUOTE = 0x22; /* " */ +var CHAR_SHARP = 0x23; /* # */ +var CHAR_PERCENT = 0x25; /* % */ +var CHAR_AMPERSAND = 0x26; /* & */ +var CHAR_SINGLE_QUOTE = 0x27; /* ' */ +var CHAR_ASTERISK = 0x2A; /* * */ +var CHAR_COMMA = 0x2C; /* , */ +var CHAR_MINUS = 0x2D; /* - */ +var CHAR_COLON = 0x3A; /* : */ +var CHAR_GREATER_THAN = 0x3E; /* > */ +var CHAR_QUESTION = 0x3F; /* ? */ +var CHAR_COMMERCIAL_AT = 0x40; /* @ */ +var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */ +var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */ +var CHAR_GRAVE_ACCENT = 0x60; /* ` */ +var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */ +var CHAR_VERTICAL_LINE = 0x7C; /* | */ +var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */ + +var ESCAPE_SEQUENCES = {}; + +ESCAPE_SEQUENCES[0x00] = '\\0'; +ESCAPE_SEQUENCES[0x07] = '\\a'; +ESCAPE_SEQUENCES[0x08] = '\\b'; +ESCAPE_SEQUENCES[0x09] = '\\t'; +ESCAPE_SEQUENCES[0x0A] = '\\n'; +ESCAPE_SEQUENCES[0x0B] = '\\v'; +ESCAPE_SEQUENCES[0x0C] = '\\f'; +ESCAPE_SEQUENCES[0x0D] = '\\r'; +ESCAPE_SEQUENCES[0x1B] = '\\e'; +ESCAPE_SEQUENCES[0x22] = '\\"'; +ESCAPE_SEQUENCES[0x5C] = '\\\\'; +ESCAPE_SEQUENCES[0x85] = '\\N'; +ESCAPE_SEQUENCES[0xA0] = '\\_'; +ESCAPE_SEQUENCES[0x2028] = '\\L'; +ESCAPE_SEQUENCES[0x2029] = '\\P'; + +var DEPRECATED_BOOLEANS_SYNTAX = [ + 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON', + 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF' +]; + +function compileStyleMap(schema, map) { + var result, keys, index, length, tag, style, type; + + if (map === null) return {}; + + result = {}; + keys = Object.keys(map); + + for (index = 0, length = keys.length; index < length; index += 1) { + tag = keys[index]; + style = String(map[tag]); + + if (tag.slice(0, 2) === '!!') { + tag = 'tag:yaml.org,2002:' + tag.slice(2); + } + + type = schema.compiledTypeMap[tag]; + + if (type && _hasOwnProperty.call(type.styleAliases, style)) { + style = type.styleAliases[style]; + } + + result[tag] = style; + } + + return result; +} + +function encodeHex(character) { + var string, handle, length; + + string = character.toString(16).toUpperCase(); + + if (character <= 0xFF) { + handle = 'x'; + length = 2; + } else if (character <= 0xFFFF) { + handle = 'u'; + length = 4; + } else if (character <= 0xFFFFFFFF) { + handle = 'U'; + length = 8; + } else { + throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF'); + } + + return '\\' + handle + common.repeat('0', length - string.length) + string; +} + +function State(options) { + this.schema = options['schema'] || DEFAULT_FULL_SCHEMA; + this.indent = Math.max(1, (options['indent'] || 2)); + this.skipInvalid = options['skipInvalid'] || false; + this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']); + this.styleMap = compileStyleMap(this.schema, options['styles'] || null); + this.sortKeys = options['sortKeys'] || false; + this.lineWidth = options['lineWidth'] || 80; + this.noRefs = options['noRefs'] || false; + this.noCompatMode = options['noCompatMode'] || false; + + this.implicitTypes = this.schema.compiledImplicit; + this.explicitTypes = this.schema.compiledExplicit; + + this.tag = null; + this.result = ''; + + this.duplicates = []; + this.usedDuplicates = null; +} + +// Indents every line in a string. Empty lines (\n only) are not indented. +function indentString(string, spaces) { + var ind = common.repeat(' ', spaces), + position = 0, + next = -1, + result = '', + line, + length = string.length; + + while (position < length) { + next = string.indexOf('\n', position); + if (next === -1) { + line = string.slice(position); + position = length; + } else { + line = string.slice(position, next + 1); + position = next + 1; + } + + if (line.length && line !== '\n') result += ind; + + result += line; + } + + return result; +} + +function generateNextLine(state, level) { + return '\n' + common.repeat(' ', state.indent * level); +} + +function testImplicitResolving(state, str) { + var index, length, type; + + for (index = 0, length = state.implicitTypes.length; index < length; index += 1) { + type = state.implicitTypes[index]; + + if (type.resolve(str)) { + return true; + } + } + + return false; +} + +// [33] s-white ::= s-space | s-tab +function isWhitespace(c) { + return c === CHAR_SPACE || c === CHAR_TAB; +} + +// Returns true if the character can be printed without escaping. +// From YAML 1.2: "any allowed characters known to be non-printable +// should also be escaped. [However,] This isn’t mandatory" +// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029. +function isPrintable(c) { + return (0x00020 <= c && c <= 0x00007E) + || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) + || ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */) + || (0x10000 <= c && c <= 0x10FFFF); +} + +// Simplified test for values allowed after the first character in plain style. +function isPlainSafe(c) { + // Uses a subset of nb-char - c-flow-indicator - ":" - "#" + // where nb-char ::= c-printable - b-char - c-byte-order-mark. + return isPrintable(c) && c !== 0xFEFF + // - c-flow-indicator + && c !== CHAR_COMMA + && c !== CHAR_LEFT_SQUARE_BRACKET + && c !== CHAR_RIGHT_SQUARE_BRACKET + && c !== CHAR_LEFT_CURLY_BRACKET + && c !== CHAR_RIGHT_CURLY_BRACKET + // - ":" - "#" + && c !== CHAR_COLON + && c !== CHAR_SHARP; +} + +// Simplified test for values allowed as the first character in plain style. +function isPlainSafeFirst(c) { + // Uses a subset of ns-char - c-indicator + // where ns-char = nb-char - s-white. + return isPrintable(c) && c !== 0xFEFF + && !isWhitespace(c) // - s-white + // - (c-indicator ::= + // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}” + && c !== CHAR_MINUS + && c !== CHAR_QUESTION + && c !== CHAR_COLON + && c !== CHAR_COMMA + && c !== CHAR_LEFT_SQUARE_BRACKET + && c !== CHAR_RIGHT_SQUARE_BRACKET + && c !== CHAR_LEFT_CURLY_BRACKET + && c !== CHAR_RIGHT_CURLY_BRACKET + // | “#” | “&” | “*” | “!” | “|” | “>” | “'” | “"” + && c !== CHAR_SHARP + && c !== CHAR_AMPERSAND + && c !== CHAR_ASTERISK + && c !== CHAR_EXCLAMATION + && c !== CHAR_VERTICAL_LINE + && c !== CHAR_GREATER_THAN + && c !== CHAR_SINGLE_QUOTE + && c !== CHAR_DOUBLE_QUOTE + // | “%” | “@” | “`”) + && c !== CHAR_PERCENT + && c !== CHAR_COMMERCIAL_AT + && c !== CHAR_GRAVE_ACCENT; +} + +var STYLE_PLAIN = 1, + STYLE_SINGLE = 2, + STYLE_LITERAL = 3, + STYLE_FOLDED = 4, + STYLE_DOUBLE = 5; + +// Determines which scalar styles are possible and returns the preferred style. +// lineWidth = -1 => no limit. +// Pre-conditions: str.length > 0. +// Post-conditions: +// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string. +// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1). +// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1). +function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) { + var i; + var char; + var hasLineBreak = false; + var hasFoldableLine = false; // only checked if shouldTrackWidth + var shouldTrackWidth = lineWidth !== -1; + var previousLineBreak = -1; // count the first line correctly + var plain = isPlainSafeFirst(string.charCodeAt(0)) + && !isWhitespace(string.charCodeAt(string.length - 1)); + + if (singleLineOnly) { + // Case: no block styles. + // Check for disallowed characters to rule out plain and single. + for (i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + if (!isPrintable(char)) { + return STYLE_DOUBLE; + } + plain = plain && isPlainSafe(char); + } + } else { + // Case: block styles permitted. + for (i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + if (char === CHAR_LINE_FEED) { + hasLineBreak = true; + // Check if any line can be folded. + if (shouldTrackWidth) { + hasFoldableLine = hasFoldableLine || + // Foldable line = too long, and not more-indented. + (i - previousLineBreak - 1 > lineWidth && + string[previousLineBreak + 1] !== ' '); + previousLineBreak = i; + } + } else if (!isPrintable(char)) { + return STYLE_DOUBLE; + } + plain = plain && isPlainSafe(char); + } + // in case the end is missing a \n + hasFoldableLine = hasFoldableLine || (shouldTrackWidth && + (i - previousLineBreak - 1 > lineWidth && + string[previousLineBreak + 1] !== ' ')); + } + // Although every style can represent \n without escaping, prefer block styles + // for multiline, since they're more readable and they don't add empty lines. + // Also prefer folding a super-long line. + if (!hasLineBreak && !hasFoldableLine) { + // Strings interpretable as another type have to be quoted; + // e.g. the string 'true' vs. the boolean true. + return plain && !testAmbiguousType(string) + ? STYLE_PLAIN : STYLE_SINGLE; + } + // Edge case: block indentation indicator can only have one digit. + if (string[0] === ' ' && indentPerLevel > 9) { + return STYLE_DOUBLE; + } + // At this point we know block styles are valid. + // Prefer literal style unless we want to fold. + return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL; +} + +// Note: line breaking/folding is implemented for only the folded style. +// NB. We drop the last trailing newline (if any) of a returned block scalar +// since the dumper adds its own newline. This always works: +// • No ending newline => unaffected; already using strip "-" chomping. +// • Ending newline => removed then restored. +// Importantly, this keeps the "+" chomp indicator from gaining an extra line. +function writeScalar(state, string, level, iskey) { + state.dump = (function () { + if (string.length === 0) { + return "''"; + } + if (!state.noCompatMode && + DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) { + return "'" + string + "'"; + } + + var indent = state.indent * Math.max(1, level); // no 0-indent scalars + // As indentation gets deeper, let the width decrease monotonically + // to the lower bound min(state.lineWidth, 40). + // Note that this implies + // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound. + // state.lineWidth > 40 + state.indent: width decreases until the lower bound. + // This behaves better than a constant minimum width which disallows narrower options, + // or an indent threshold which causes the width to suddenly increase. + var lineWidth = state.lineWidth === -1 + ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent); + + // Without knowing if keys are implicit/explicit, assume implicit for safety. + var singleLineOnly = iskey + // No block styles in flow mode. + || (state.flowLevel > -1 && level >= state.flowLevel); + function testAmbiguity(string) { + return testImplicitResolving(state, string); + } + + switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) { + case STYLE_PLAIN: + return string; + case STYLE_SINGLE: + return "'" + string.replace(/'/g, "''") + "'"; + case STYLE_LITERAL: + return '|' + blockHeader(string, state.indent) + + dropEndingNewline(indentString(string, indent)); + case STYLE_FOLDED: + return '>' + blockHeader(string, state.indent) + + dropEndingNewline(indentString(foldString(string, lineWidth), indent)); + case STYLE_DOUBLE: + return '"' + escapeString(string, lineWidth) + '"'; + default: + throw new YAMLException('impossible error: invalid scalar style'); + } + }()); +} + +// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9. +function blockHeader(string, indentPerLevel) { + var indentIndicator = (string[0] === ' ') ? String(indentPerLevel) : ''; + + // note the special case: the string '\n' counts as a "trailing" empty line. + var clip = string[string.length - 1] === '\n'; + var keep = clip && (string[string.length - 2] === '\n' || string === '\n'); + var chomp = keep ? '+' : (clip ? '' : '-'); + + return indentIndicator + chomp + '\n'; +} + +// (See the note for writeScalar.) +function dropEndingNewline(string) { + return string[string.length - 1] === '\n' ? string.slice(0, -1) : string; +} + +// Note: a long line without a suitable break point will exceed the width limit. +// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0. +function foldString(string, width) { + // In folded style, $k$ consecutive newlines output as $k+1$ newlines— + // unless they're before or after a more-indented line, or at the very + // beginning or end, in which case $k$ maps to $k$. + // Therefore, parse each chunk as newline(s) followed by a content line. + var lineRe = /(\n+)([^\n]*)/g; + + // first line (possibly an empty line) + var result = (function () { + var nextLF = string.indexOf('\n'); + nextLF = nextLF !== -1 ? nextLF : string.length; + lineRe.lastIndex = nextLF; + return foldLine(string.slice(0, nextLF), width); + }()); + // If we haven't reached the first content line yet, don't add an extra \n. + var prevMoreIndented = string[0] === '\n' || string[0] === ' '; + var moreIndented; + + // rest of the lines + var match; + while ((match = lineRe.exec(string))) { + var prefix = match[1], line = match[2]; + moreIndented = (line[0] === ' '); + result += prefix + + (!prevMoreIndented && !moreIndented && line !== '' + ? '\n' : '') + + foldLine(line, width); + prevMoreIndented = moreIndented; + } + + return result; +} + +// Greedy line breaking. +// Picks the longest line under the limit each time, +// otherwise settles for the shortest line over the limit. +// NB. More-indented lines *cannot* be folded, as that would add an extra \n. +function foldLine(line, width) { + if (line === '' || line[0] === ' ') return line; + + // Since a more-indented line adds a \n, breaks can't be followed by a space. + var breakRe = / [^ ]/g; // note: the match index will always be <= length-2. + var match; + // start is an inclusive index. end, curr, and next are exclusive. + var start = 0, end, curr = 0, next = 0; + var result = ''; + + // Invariants: 0 <= start <= length-1. + // 0 <= curr <= next <= max(0, length-2). curr - start <= width. + // Inside the loop: + // A match implies length >= 2, so curr and next are <= length-2. + while ((match = breakRe.exec(line))) { + next = match.index; + // maintain invariant: curr - start <= width + if (next - start > width) { + end = (curr > start) ? curr : next; // derive end <= length-2 + result += '\n' + line.slice(start, end); + // skip the space that was output as \n + start = end + 1; // derive start <= length-1 + } + curr = next; + } + + // By the invariants, start <= length-1, so there is something left over. + // It is either the whole string or a part starting from non-whitespace. + result += '\n'; + // Insert a break if the remainder is too long and there is a break available. + if (line.length - start > width && curr > start) { + result += line.slice(start, curr) + '\n' + line.slice(curr + 1); + } else { + result += line.slice(start); + } + + return result.slice(1); // drop extra \n joiner +} + +// Escapes a double-quoted string. +function escapeString(string) { + var result = ''; + var char; + var escapeSeq; + + for (var i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + escapeSeq = ESCAPE_SEQUENCES[char]; + result += !escapeSeq && isPrintable(char) + ? string[i] + : escapeSeq || encodeHex(char); + } + + return result; +} + +function writeFlowSequence(state, level, object) { + var _result = '', + _tag = state.tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + // Write only valid elements. + if (writeNode(state, level, object[index], false, false)) { + if (index !== 0) _result += ', '; + _result += state.dump; + } + } + + state.tag = _tag; + state.dump = '[' + _result + ']'; +} + +function writeBlockSequence(state, level, object, compact) { + var _result = '', + _tag = state.tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + // Write only valid elements. + if (writeNode(state, level + 1, object[index], true, true)) { + if (!compact || index !== 0) { + _result += generateNextLine(state, level); + } + _result += '- ' + state.dump; + } + } + + state.tag = _tag; + state.dump = _result || '[]'; // Empty sequence if no valid values. +} + +function writeFlowMapping(state, level, object) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + pairBuffer; + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (index !== 0) pairBuffer += ', '; + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (!writeNode(state, level, objectKey, false, false)) { + continue; // Skip this pair because of invalid key; + } + + if (state.dump.length > 1024) pairBuffer += '? '; + + pairBuffer += state.dump + ': '; + + if (!writeNode(state, level, objectValue, false, false)) { + continue; // Skip this pair because of invalid value. + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = '{' + _result + '}'; +} + +function writeBlockMapping(state, level, object, compact) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + explicitPair, + pairBuffer; + + // Allow sorting keys so that the output file is deterministic + if (state.sortKeys === true) { + // Default sorting + objectKeyList.sort(); + } else if (typeof state.sortKeys === 'function') { + // Custom sort function + objectKeyList.sort(state.sortKeys); + } else if (state.sortKeys) { + // Something is wrong + throw new YAMLException('sortKeys must be a boolean or a function'); + } + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (!compact || index !== 0) { + pairBuffer += generateNextLine(state, level); + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (!writeNode(state, level + 1, objectKey, true, true, true)) { + continue; // Skip this pair because of invalid key. + } + + explicitPair = (state.tag !== null && state.tag !== '?') || + (state.dump && state.dump.length > 1024); + + if (explicitPair) { + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += '?'; + } else { + pairBuffer += '? '; + } + } + + pairBuffer += state.dump; + + if (explicitPair) { + pairBuffer += generateNextLine(state, level); + } + + if (!writeNode(state, level + 1, objectValue, true, explicitPair)) { + continue; // Skip this pair because of invalid value. + } + + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += ':'; + } else { + pairBuffer += ': '; + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = _result || '{}'; // Empty mapping if no valid pairs. +} + +function detectType(state, object, explicit) { + var _result, typeList, index, length, type, style; + + typeList = explicit ? state.explicitTypes : state.implicitTypes; + + for (index = 0, length = typeList.length; index < length; index += 1) { + type = typeList[index]; + + if ((type.instanceOf || type.predicate) && + (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) && + (!type.predicate || type.predicate(object))) { + + state.tag = explicit ? type.tag : '?'; + + if (type.represent) { + style = state.styleMap[type.tag] || type.defaultStyle; + + if (_toString.call(type.represent) === '[object Function]') { + _result = type.represent(object, style); + } else if (_hasOwnProperty.call(type.represent, style)) { + _result = type.represent[style](object, style); + } else { + throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style'); + } + + state.dump = _result; + } + + return true; + } + } + + return false; +} + +// Serializes `object` and writes it to global `result`. +// Returns true on success, or false on invalid object. +// +function writeNode(state, level, object, block, compact, iskey) { + state.tag = null; + state.dump = object; + + if (!detectType(state, object, false)) { + detectType(state, object, true); + } + + var type = _toString.call(state.dump); + + if (block) { + block = (state.flowLevel < 0 || state.flowLevel > level); + } + + var objectOrArray = type === '[object Object]' || type === '[object Array]', + duplicateIndex, + duplicate; + + if (objectOrArray) { + duplicateIndex = state.duplicates.indexOf(object); + duplicate = duplicateIndex !== -1; + } + + if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) { + compact = false; + } + + if (duplicate && state.usedDuplicates[duplicateIndex]) { + state.dump = '*ref_' + duplicateIndex; + } else { + if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) { + state.usedDuplicates[duplicateIndex] = true; + } + if (type === '[object Object]') { + if (block && (Object.keys(state.dump).length !== 0)) { + writeBlockMapping(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowMapping(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if (type === '[object Array]') { + if (block && (state.dump.length !== 0)) { + writeBlockSequence(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowSequence(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if (type === '[object String]') { + if (state.tag !== '?') { + writeScalar(state, state.dump, level, iskey); + } + } else { + if (state.skipInvalid) return false; + throw new YAMLException('unacceptable kind of an object to dump ' + type); + } + + if (state.tag !== null && state.tag !== '?') { + state.dump = '!<' + state.tag + '> ' + state.dump; + } + } + + return true; +} + +function getDuplicateReferences(object, state) { + var objects = [], + duplicatesIndexes = [], + index, + length; + + inspectNode(object, objects, duplicatesIndexes); + + for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) { + state.duplicates.push(objects[duplicatesIndexes[index]]); + } + state.usedDuplicates = new Array(length); +} + +function inspectNode(object, objects, duplicatesIndexes) { + var objectKeyList, + index, + length; + + if (object !== null && typeof object === 'object') { + index = objects.indexOf(object); + if (index !== -1) { + if (duplicatesIndexes.indexOf(index) === -1) { + duplicatesIndexes.push(index); + } + } else { + objects.push(object); + + if (Array.isArray(object)) { + for (index = 0, length = object.length; index < length; index += 1) { + inspectNode(object[index], objects, duplicatesIndexes); + } + } else { + objectKeyList = Object.keys(object); + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes); + } + } + } + } +} + +function dump(input, options) { + options = options || {}; + + var state = new State(options); + + if (!state.noRefs) getDuplicateReferences(input, state); + + if (writeNode(state, 0, input, true, true)) return state.dump + '\n'; + + return ''; +} + +function safeDump(input, options) { + return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + +module.exports.dump = dump; +module.exports.safeDump = safeDump; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/exception.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/exception.js new file mode 100644 index 0000000..cf4e625 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/exception.js @@ -0,0 +1,43 @@ +// YAML error class. http://stackoverflow.com/questions/8458984 +// +'use strict'; + +function YAMLException(reason, mark) { + // Super constructor + Error.call(this); + + // Include stack trace in error object + if (Error.captureStackTrace) { + // Chrome and NodeJS + Error.captureStackTrace(this, this.constructor); + } else { + // FF, IE 10+ and Safari 6+. Fallback for others + this.stack = (new Error()).stack || ''; + } + + this.name = 'YAMLException'; + this.reason = reason; + this.mark = mark; + this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : ''); +} + + +// Inherit from Error +YAMLException.prototype = Object.create(Error.prototype); +YAMLException.prototype.constructor = YAMLException; + + +YAMLException.prototype.toString = function toString(compact) { + var result = this.name + ': '; + + result += this.reason || '(unknown reason)'; + + if (!compact && this.mark) { + result += ' ' + this.mark.toString(); + } + + return result; +}; + + +module.exports = YAMLException; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/loader.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/loader.js new file mode 100644 index 0000000..8966d6b --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/loader.js @@ -0,0 +1,1586 @@ +'use strict'; + +/*eslint-disable max-len,no-use-before-define*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var Mark = require('./mark'); +var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe'); +var DEFAULT_FULL_SCHEMA = require('./schema/default_full'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + + +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; + + +var CHOMPING_CLIP = 1; +var CHOMPING_STRIP = 2; +var CHOMPING_KEEP = 3; + + +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i; +var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; + + +function is_EOL(c) { + return (c === 0x0A/* LF */) || (c === 0x0D/* CR */); +} + +function is_WHITE_SPACE(c) { + return (c === 0x09/* Tab */) || (c === 0x20/* Space */); +} + +function is_WS_OR_EOL(c) { + return (c === 0x09/* Tab */) || + (c === 0x20/* Space */) || + (c === 0x0A/* LF */) || + (c === 0x0D/* CR */); +} + +function is_FLOW_INDICATOR(c) { + return c === 0x2C/* , */ || + c === 0x5B/* [ */ || + c === 0x5D/* ] */ || + c === 0x7B/* { */ || + c === 0x7D/* } */; +} + +function fromHexCode(c) { + var lc; + + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + /*eslint-disable no-bitwise*/ + lc = c | 0x20; + + if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) { + return lc - 0x61 + 10; + } + + return -1; +} + +function escapedHexLen(c) { + if (c === 0x78/* x */) { return 2; } + if (c === 0x75/* u */) { return 4; } + if (c === 0x55/* U */) { return 8; } + return 0; +} + +function fromDecimalCode(c) { + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + return -1; +} + +function simpleEscapeSequence(c) { + return (c === 0x30/* 0 */) ? '\x00' : + (c === 0x61/* a */) ? '\x07' : + (c === 0x62/* b */) ? '\x08' : + (c === 0x74/* t */) ? '\x09' : + (c === 0x09/* Tab */) ? '\x09' : + (c === 0x6E/* n */) ? '\x0A' : + (c === 0x76/* v */) ? '\x0B' : + (c === 0x66/* f */) ? '\x0C' : + (c === 0x72/* r */) ? '\x0D' : + (c === 0x65/* e */) ? '\x1B' : + (c === 0x20/* Space */) ? ' ' : + (c === 0x22/* " */) ? '\x22' : + (c === 0x2F/* / */) ? '/' : + (c === 0x5C/* \ */) ? '\x5C' : + (c === 0x4E/* N */) ? '\x85' : + (c === 0x5F/* _ */) ? '\xA0' : + (c === 0x4C/* L */) ? '\u2028' : + (c === 0x50/* P */) ? '\u2029' : ''; +} + +function charFromCodepoint(c) { + if (c <= 0xFFFF) { + return String.fromCharCode(c); + } + // Encode UTF-16 surrogate pair + // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF + return String.fromCharCode(((c - 0x010000) >> 10) + 0xD800, + ((c - 0x010000) & 0x03FF) + 0xDC00); +} + +var simpleEscapeCheck = new Array(256); // integer, for fast access +var simpleEscapeMap = new Array(256); +for (var i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} + + +function State(input, options) { + this.input = input; + + this.filename = options['filename'] || null; + this.schema = options['schema'] || DEFAULT_FULL_SCHEMA; + this.onWarning = options['onWarning'] || null; + this.legacy = options['legacy'] || false; + this.json = options['json'] || false; + this.listener = options['listener'] || null; + + this.implicitTypes = this.schema.compiledImplicit; + this.typeMap = this.schema.compiledTypeMap; + + this.length = input.length; + this.position = 0; + this.line = 0; + this.lineStart = 0; + this.lineIndent = 0; + + this.documents = []; + + /* + this.version; + this.checkLineBreaks; + this.tagMap; + this.anchorMap; + this.tag; + this.anchor; + this.kind; + this.result;*/ + +} + + +function generateError(state, message) { + return new YAMLException( + message, + new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart))); +} + +function throwError(state, message) { + throw generateError(state, message); +} + +function throwWarning(state, message) { + if (state.onWarning) { + state.onWarning.call(null, generateError(state, message)); + } +} + + +var directiveHandlers = { + + YAML: function handleYamlDirective(state, name, args) { + + var match, major, minor; + + if (state.version !== null) { + throwError(state, 'duplication of %YAML directive'); + } + + if (args.length !== 1) { + throwError(state, 'YAML directive accepts exactly one argument'); + } + + match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + + if (match === null) { + throwError(state, 'ill-formed argument of the YAML directive'); + } + + major = parseInt(match[1], 10); + minor = parseInt(match[2], 10); + + if (major !== 1) { + throwError(state, 'unacceptable YAML version of the document'); + } + + state.version = args[0]; + state.checkLineBreaks = (minor < 2); + + if (minor !== 1 && minor !== 2) { + throwWarning(state, 'unsupported YAML version of the document'); + } + }, + + TAG: function handleTagDirective(state, name, args) { + + var handle, prefix; + + if (args.length !== 2) { + throwError(state, 'TAG directive accepts exactly two arguments'); + } + + handle = args[0]; + prefix = args[1]; + + if (!PATTERN_TAG_HANDLE.test(handle)) { + throwError(state, 'ill-formed tag handle (first argument) of the TAG directive'); + } + + if (_hasOwnProperty.call(state.tagMap, handle)) { + throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); + } + + if (!PATTERN_TAG_URI.test(prefix)) { + throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive'); + } + + state.tagMap[handle] = prefix; + } +}; + + +function captureSegment(state, start, end, checkJson) { + var _position, _length, _character, _result; + + if (start < end) { + _result = state.input.slice(start, end); + + if (checkJson) { + for (_position = 0, _length = _result.length; + _position < _length; + _position += 1) { + _character = _result.charCodeAt(_position); + if (!(_character === 0x09 || + (0x20 <= _character && _character <= 0x10FFFF))) { + throwError(state, 'expected valid JSON character'); + } + } + } else if (PATTERN_NON_PRINTABLE.test(_result)) { + throwError(state, 'the stream contains non-printable characters'); + } + + state.result += _result; + } +} + +function mergeMappings(state, destination, source, overridableKeys) { + var sourceKeys, key, index, quantity; + + if (!common.isObject(source)) { + throwError(state, 'cannot merge mappings; the provided source object is unacceptable'); + } + + sourceKeys = Object.keys(source); + + for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + key = sourceKeys[index]; + + if (!_hasOwnProperty.call(destination, key)) { + destination[key] = source[key]; + overridableKeys[key] = true; + } + } +} + +function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode) { + var index, quantity; + + keyNode = String(keyNode); + + if (_result === null) { + _result = {}; + } + + if (keyTag === 'tag:yaml.org,2002:merge') { + if (Array.isArray(valueNode)) { + for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { + mergeMappings(state, _result, valueNode[index], overridableKeys); + } + } else { + mergeMappings(state, _result, valueNode, overridableKeys); + } + } else { + if (!state.json && + !_hasOwnProperty.call(overridableKeys, keyNode) && + _hasOwnProperty.call(_result, keyNode)) { + throwError(state, 'duplicated mapping key'); + } + _result[keyNode] = valueNode; + delete overridableKeys[keyNode]; + } + + return _result; +} + +function readLineBreak(state) { + var ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x0A/* LF */) { + state.position++; + } else if (ch === 0x0D/* CR */) { + state.position++; + if (state.input.charCodeAt(state.position) === 0x0A/* LF */) { + state.position++; + } + } else { + throwError(state, 'a line break is expected'); + } + + state.line += 1; + state.lineStart = state.position; +} + +function skipSeparationSpace(state, allowComments, checkIndent) { + var lineBreaks = 0, + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (allowComments && ch === 0x23/* # */) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0); + } + + if (is_EOL(ch)) { + readLineBreak(state); + + ch = state.input.charCodeAt(state.position); + lineBreaks++; + state.lineIndent = 0; + + while (ch === 0x20/* Space */) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } else { + break; + } + } + + if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) { + throwWarning(state, 'deficient indentation'); + } + + return lineBreaks; +} + +function testDocumentSeparator(state) { + var _position = state.position, + ch; + + ch = state.input.charCodeAt(_position); + + // Condition state.position === state.lineStart is tested + // in parent on each call, for efficiency. No needs to test here again. + if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) && + ch === state.input.charCodeAt(_position + 1) && + ch === state.input.charCodeAt(_position + 2)) { + + _position += 3; + + ch = state.input.charCodeAt(_position); + + if (ch === 0 || is_WS_OR_EOL(ch)) { + return true; + } + } + + return false; +} + +function writeFoldedLines(state, count) { + if (count === 1) { + state.result += ' '; + } else if (count > 1) { + state.result += common.repeat('\n', count - 1); + } +} + + +function readPlainScalar(state, nodeIndent, withinFlowCollection) { + var preceding, + following, + captureStart, + captureEnd, + hasPendingContent, + _line, + _lineStart, + _lineIndent, + _kind = state.kind, + _result = state.result, + ch; + + ch = state.input.charCodeAt(state.position); + + if (is_WS_OR_EOL(ch) || + is_FLOW_INDICATOR(ch) || + ch === 0x23/* # */ || + ch === 0x26/* & */ || + ch === 0x2A/* * */ || + ch === 0x21/* ! */ || + ch === 0x7C/* | */ || + ch === 0x3E/* > */ || + ch === 0x27/* ' */ || + ch === 0x22/* " */ || + ch === 0x25/* % */ || + ch === 0x40/* @ */ || + ch === 0x60/* ` */) { + return false; + } + + if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following) || + withinFlowCollection && is_FLOW_INDICATOR(following)) { + return false; + } + } + + state.kind = 'scalar'; + state.result = ''; + captureStart = captureEnd = state.position; + hasPendingContent = false; + + while (ch !== 0) { + if (ch === 0x3A/* : */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following) || + withinFlowCollection && is_FLOW_INDICATOR(following)) { + break; + } + + } else if (ch === 0x23/* # */) { + preceding = state.input.charCodeAt(state.position - 1); + + if (is_WS_OR_EOL(preceding)) { + break; + } + + } else if ((state.position === state.lineStart && testDocumentSeparator(state)) || + withinFlowCollection && is_FLOW_INDICATOR(ch)) { + break; + + } else if (is_EOL(ch)) { + _line = state.line; + _lineStart = state.lineStart; + _lineIndent = state.lineIndent; + skipSeparationSpace(state, false, -1); + + if (state.lineIndent >= nodeIndent) { + hasPendingContent = true; + ch = state.input.charCodeAt(state.position); + continue; + } else { + state.position = captureEnd; + state.line = _line; + state.lineStart = _lineStart; + state.lineIndent = _lineIndent; + break; + } + } + + if (hasPendingContent) { + captureSegment(state, captureStart, captureEnd, false); + writeFoldedLines(state, state.line - _line); + captureStart = captureEnd = state.position; + hasPendingContent = false; + } + + if (!is_WHITE_SPACE(ch)) { + captureEnd = state.position + 1; + } + + ch = state.input.charCodeAt(++state.position); + } + + captureSegment(state, captureStart, captureEnd, false); + + if (state.result) { + return true; + } + + state.kind = _kind; + state.result = _result; + return false; +} + +function readSingleQuotedScalar(state, nodeIndent) { + var ch, + captureStart, captureEnd; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x27/* ' */) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x27/* ' */) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x27/* ' */) { + captureStart = captureEnd = state.position; + state.position++; + } else { + return true; + } + + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a single quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError(state, 'unexpected end of the stream within a single quoted scalar'); +} + +function readDoubleQuotedScalar(state, nodeIndent) { + var captureStart, + captureEnd, + hexLength, + hexResult, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x22/* " */) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x22/* " */) { + captureSegment(state, captureStart, state.position, true); + state.position++; + return true; + + } else if (ch === 0x5C/* \ */) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (is_EOL(ch)) { + skipSeparationSpace(state, false, nodeIndent); + + // TODO: rework to inline fn with no type cast? + } else if (ch < 256 && simpleEscapeCheck[ch]) { + state.result += simpleEscapeMap[ch]; + state.position++; + + } else if ((tmp = escapedHexLen(ch)) > 0) { + hexLength = tmp; + hexResult = 0; + + for (; hexLength > 0; hexLength--) { + ch = state.input.charCodeAt(++state.position); + + if ((tmp = fromHexCode(ch)) >= 0) { + hexResult = (hexResult << 4) + tmp; + + } else { + throwError(state, 'expected hexadecimal character'); + } + } + + state.result += charFromCodepoint(hexResult); + + state.position++; + + } else { + throwError(state, 'unknown escape sequence'); + } + + captureStart = captureEnd = state.position; + + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a double quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError(state, 'unexpected end of the stream within a double quoted scalar'); +} + +function readFlowCollection(state, nodeIndent) { + var readNext = true, + _line, + _tag = state.tag, + _result, + _anchor = state.anchor, + following, + terminator, + isPair, + isExplicitPair, + isMapping, + overridableKeys = {}, + keyNode, + keyTag, + valueNode, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x5B/* [ */) { + terminator = 0x5D;/* ] */ + isMapping = false; + _result = []; + } else if (ch === 0x7B/* { */) { + terminator = 0x7D;/* } */ + isMapping = true; + _result = {}; + } else { + return false; + } + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(++state.position); + + while (ch !== 0) { + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === terminator) { + state.position++; + state.tag = _tag; + state.anchor = _anchor; + state.kind = isMapping ? 'mapping' : 'sequence'; + state.result = _result; + return true; + } else if (!readNext) { + throwError(state, 'missed comma between flow collection entries'); + } + + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; + + if (ch === 0x3F/* ? */) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following)) { + isPair = isExplicitPair = true; + state.position++; + skipSeparationSpace(state, true, nodeIndent); + } + } + + _line = state.line; + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + keyTag = state.tag; + keyNode = state.result; + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) { + isPair = true; + ch = state.input.charCodeAt(++state.position); + skipSeparationSpace(state, true, nodeIndent); + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + valueNode = state.result; + } + + if (isMapping) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode); + } else if (isPair) { + _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode)); + } else { + _result.push(keyNode); + } + + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x2C/* , */) { + readNext = true; + ch = state.input.charCodeAt(++state.position); + } else { + readNext = false; + } + } + + throwError(state, 'unexpected end of the stream within a flow collection'); +} + +function readBlockScalar(state, nodeIndent) { + var captureStart, + folding, + chomping = CHOMPING_CLIP, + didReadContent = false, + detectedIndent = false, + textIndent = nodeIndent, + emptyLines = 0, + atMoreIndented = false, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x7C/* | */) { + folding = false; + } else if (ch === 0x3E/* > */) { + folding = true; + } else { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + + while (ch !== 0) { + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + if (CHOMPING_CLIP === chomping) { + chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP; + } else { + throwError(state, 'repeat of a chomping mode identifier'); + } + + } else if ((tmp = fromDecimalCode(ch)) >= 0) { + if (tmp === 0) { + throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one'); + } else if (!detectedIndent) { + textIndent = nodeIndent + tmp - 1; + detectedIndent = true; + } else { + throwError(state, 'repeat of an indentation width identifier'); + } + + } else { + break; + } + } + + if (is_WHITE_SPACE(ch)) { + do { ch = state.input.charCodeAt(++state.position); } + while (is_WHITE_SPACE(ch)); + + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (!is_EOL(ch) && (ch !== 0)); + } + } + + while (ch !== 0) { + readLineBreak(state); + state.lineIndent = 0; + + ch = state.input.charCodeAt(state.position); + + while ((!detectedIndent || state.lineIndent < textIndent) && + (ch === 0x20/* Space */)) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + + if (!detectedIndent && state.lineIndent > textIndent) { + textIndent = state.lineIndent; + } + + if (is_EOL(ch)) { + emptyLines++; + continue; + } + + // End of the scalar. + if (state.lineIndent < textIndent) { + + // Perform the chomping. + if (chomping === CHOMPING_KEEP) { + state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + } else if (chomping === CHOMPING_CLIP) { + if (didReadContent) { // i.e. only if the scalar is not empty. + state.result += '\n'; + } + } + + // Break this `while` cycle and go to the funciton's epilogue. + break; + } + + // Folded style: use fancy rules to handle line breaks. + if (folding) { + + // Lines starting with white space characters (more-indented lines) are not folded. + if (is_WHITE_SPACE(ch)) { + atMoreIndented = true; + // except for the first content line (cf. Example 8.1) + state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + + // End of more-indented block. + } else if (atMoreIndented) { + atMoreIndented = false; + state.result += common.repeat('\n', emptyLines + 1); + + // Just one line break - perceive as the same line. + } else if (emptyLines === 0) { + if (didReadContent) { // i.e. only if we have already read some scalar content. + state.result += ' '; + } + + // Several line breaks - perceive as different lines. + } else { + state.result += common.repeat('\n', emptyLines); + } + + // Literal style: just add exact number of line breaks between content lines. + } else { + // Keep all line breaks except the header line break. + state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + } + + didReadContent = true; + detectedIndent = true; + emptyLines = 0; + captureStart = state.position; + + while (!is_EOL(ch) && (ch !== 0)) { + ch = state.input.charCodeAt(++state.position); + } + + captureSegment(state, captureStart, state.position, false); + } + + return true; +} + +function readBlockSequence(state, nodeIndent) { + var _line, + _tag = state.tag, + _anchor = state.anchor, + _result = [], + following, + detected = false, + ch; + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + + if (ch !== 0x2D/* - */) { + break; + } + + following = state.input.charCodeAt(state.position + 1); + + if (!is_WS_OR_EOL(following)) { + break; + } + + detected = true; + state.position++; + + if (skipSeparationSpace(state, true, -1)) { + if (state.lineIndent <= nodeIndent) { + _result.push(null); + ch = state.input.charCodeAt(state.position); + continue; + } + } + + _line = state.line; + composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + _result.push(state.result); + skipSeparationSpace(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) { + throwError(state, 'bad indentation of a sequence entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'sequence'; + state.result = _result; + return true; + } + return false; +} + +function readBlockMapping(state, nodeIndent, flowIndent) { + var following, + allowCompact, + _line, + _tag = state.tag, + _anchor = state.anchor, + _result = {}, + overridableKeys = {}, + keyTag = null, + keyNode = null, + valueNode = null, + atExplicitKey = false, + detected = false, + ch; + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + following = state.input.charCodeAt(state.position + 1); + _line = state.line; // Save the current line. + + // + // Explicit notation case. There are two separate blocks: + // first for the key (denoted by "?") and second for the value (denoted by ":") + // + if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) { + + if (ch === 0x3F/* ? */) { + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = true; + allowCompact = true; + + } else if (atExplicitKey) { + // i.e. 0x3A/* : */ === character after the explicit key. + atExplicitKey = false; + allowCompact = true; + + } else { + throwError(state, 'incomplete explicit mapping pair; a key node is missed'); + } + + state.position += 1; + ch = following; + + // + // Implicit notation case. Flow-style node as the key first, then ":", and the value. + // + } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { + + if (state.line === _line) { + ch = state.input.charCodeAt(state.position); + + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (ch === 0x3A/* : */) { + ch = state.input.charCodeAt(++state.position); + + if (!is_WS_OR_EOL(ch)) { + throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping'); + } + + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = state.tag; + keyNode = state.result; + + } else if (detected) { + throwError(state, 'can not read an implicit mapping pair; a colon is missed'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else if (detected) { + throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else { + break; // Reading is done. Go to the epilogue. + } + + // + // Common reading code for both explicit and implicit notations. + // + if (state.line === _line || state.lineIndent > nodeIndent) { + if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (atExplicitKey) { + keyNode = state.result; + } else { + valueNode = state.result; + } + } + + if (!atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode); + keyTag = keyNode = valueNode = null; + } + + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); + } + + if (state.lineIndent > nodeIndent && (ch !== 0)) { + throwError(state, 'bad indentation of a mapping entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + // + // Epilogue. + // + + // Special case: last mapping's node contains only the key in explicit notation. + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null); + } + + // Expose the resulting mapping. + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'mapping'; + state.result = _result; + } + + return detected; +} + +function readTagProperty(state) { + var _position, + isVerbatim = false, + isNamed = false, + tagHandle, + tagName, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x21/* ! */) return false; + + if (state.tag !== null) { + throwError(state, 'duplication of a tag property'); + } + + ch = state.input.charCodeAt(++state.position); + + if (ch === 0x3C/* < */) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + + } else if (ch === 0x21/* ! */) { + isNamed = true; + tagHandle = '!!'; + ch = state.input.charCodeAt(++state.position); + + } else { + tagHandle = '!'; + } + + _position = state.position; + + if (isVerbatim) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && ch !== 0x3E/* > */); + + if (state.position < state.length) { + tagName = state.input.slice(_position, state.position); + ch = state.input.charCodeAt(++state.position); + } else { + throwError(state, 'unexpected end of the stream within a verbatim tag'); + } + } else { + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + + if (ch === 0x21/* ! */) { + if (!isNamed) { + tagHandle = state.input.slice(_position - 1, state.position + 1); + + if (!PATTERN_TAG_HANDLE.test(tagHandle)) { + throwError(state, 'named tag handle cannot contain such characters'); + } + + isNamed = true; + _position = state.position + 1; + } else { + throwError(state, 'tag suffix cannot contain exclamation marks'); + } + } + + ch = state.input.charCodeAt(++state.position); + } + + tagName = state.input.slice(_position, state.position); + + if (PATTERN_FLOW_INDICATORS.test(tagName)) { + throwError(state, 'tag suffix cannot contain flow indicator characters'); + } + } + + if (tagName && !PATTERN_TAG_URI.test(tagName)) { + throwError(state, 'tag name cannot contain such characters: ' + tagName); + } + + if (isVerbatim) { + state.tag = tagName; + + } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) { + state.tag = state.tagMap[tagHandle] + tagName; + + } else if (tagHandle === '!') { + state.tag = '!' + tagName; + + } else if (tagHandle === '!!') { + state.tag = 'tag:yaml.org,2002:' + tagName; + + } else { + throwError(state, 'undeclared tag handle "' + tagHandle + '"'); + } + + return true; +} + +function readAnchorProperty(state) { + var _position, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x26/* & */) return false; + + if (state.anchor !== null) { + throwError(state, 'duplication of an anchor property'); + } + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError(state, 'name of an anchor node must contain at least one character'); + } + + state.anchor = state.input.slice(_position, state.position); + return true; +} + +function readAlias(state) { + var _position, alias, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch !== 0x2A/* * */) return false; + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError(state, 'name of an alias node must contain at least one character'); + } + + alias = state.input.slice(_position, state.position); + + if (!state.anchorMap.hasOwnProperty(alias)) { + throwError(state, 'unidentified alias "' + alias + '"'); + } + + state.result = state.anchorMap[alias]; + skipSeparationSpace(state, true, -1); + return true; +} + +function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) { + var allowBlockStyles, + allowBlockScalars, + allowBlockCollections, + indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } + } + + if (indentStatus === 1) { + while (readTagProperty(state) || readAnchorProperty(state)) { + if (skipSeparationSpace(state, true, -1)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + + if (state.lineIndent > parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } else { + allowBlockCollections = false; + } + } + } + + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } + + if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) { + if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { + flowIndent = parentIndent; + } else { + flowIndent = parentIndent + 1; + } + + blockIndent = state.position - state.lineStart; + + if (indentStatus === 1) { + if (allowBlockCollections && + (readBlockSequence(state, blockIndent) || + readBlockMapping(state, blockIndent, flowIndent)) || + readFlowCollection(state, flowIndent)) { + hasContent = true; + } else { + if ((allowBlockScalars && readBlockScalar(state, flowIndent)) || + readSingleQuotedScalar(state, flowIndent) || + readDoubleQuotedScalar(state, flowIndent)) { + hasContent = true; + + } else if (readAlias(state)) { + hasContent = true; + + if (state.tag !== null || state.anchor !== null) { + throwError(state, 'alias node should not have any properties'); + } + + } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) { + hasContent = true; + + if (state.tag === null) { + state.tag = '?'; + } + } + + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + } + } else if (indentStatus === 0) { + // Special case: block sequences are allowed to have same indentation level as the parent. + // http://www.yaml.org/spec/1.2/spec.html#id2799784 + hasContent = allowBlockCollections && readBlockSequence(state, blockIndent); + } + } + + if (state.tag !== null && state.tag !== '!') { + if (state.tag === '?') { + for (typeIndex = 0, typeQuantity = state.implicitTypes.length; + typeIndex < typeQuantity; + typeIndex += 1) { + type = state.implicitTypes[typeIndex]; + + // Implicit resolving is not allowed for non-scalar types, and '?' + // non-specific tag is only assigned to plain scalars. So, it isn't + // needed to check for 'kind' conformity. + + if (type.resolve(state.result)) { // `state.result` updated in resolver if matched + state.result = type.construct(state.result); + state.tag = type.tag; + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + break; + } + } + } else if (_hasOwnProperty.call(state.typeMap, state.tag)) { + type = state.typeMap[state.tag]; + + if (state.result !== null && type.kind !== state.kind) { + throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"'); + } + + if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched + throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag'); + } else { + state.result = type.construct(state.result); + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } + } + } else { + throwError(state, 'unknown tag !<' + state.tag + '>'); + } + } + + if (state.listener !== null) { + state.listener('close', state); + } + return state.tag !== null || state.anchor !== null || hasContent; +} + +function readDocument(state) { + var documentStart = state.position, + _position, + directiveName, + directiveArgs, + hasDirectives = false, + ch; + + state.version = null; + state.checkLineBreaks = state.legacy; + state.tagMap = {}; + state.anchorMap = {}; + + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + skipSeparationSpace(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if (state.lineIndent > 0 || ch !== 0x25/* % */) { + break; + } + + hasDirectives = true; + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveName = state.input.slice(_position, state.position); + directiveArgs = []; + + if (directiveName.length < 1) { + throwError(state, 'directive name must not be less than one character in length'); + } + + while (ch !== 0) { + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && !is_EOL(ch)); + break; + } + + if (is_EOL(ch)) break; + + _position = state.position; + + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveArgs.push(state.input.slice(_position, state.position)); + } + + if (ch !== 0) readLineBreak(state); + + if (_hasOwnProperty.call(directiveHandlers, directiveName)) { + directiveHandlers[directiveName](state, directiveName, directiveArgs); + } else { + throwWarning(state, 'unknown document directive "' + directiveName + '"'); + } + } + + skipSeparationSpace(state, true, -1); + + if (state.lineIndent === 0 && + state.input.charCodeAt(state.position) === 0x2D/* - */ && + state.input.charCodeAt(state.position + 1) === 0x2D/* - */ && + state.input.charCodeAt(state.position + 2) === 0x2D/* - */) { + state.position += 3; + skipSeparationSpace(state, true, -1); + + } else if (hasDirectives) { + throwError(state, 'directives end mark is expected'); + } + + composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); + skipSeparationSpace(state, true, -1); + + if (state.checkLineBreaks && + PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) { + throwWarning(state, 'non-ASCII line breaks are interpreted as content'); + } + + state.documents.push(state.result); + + if (state.position === state.lineStart && testDocumentSeparator(state)) { + + if (state.input.charCodeAt(state.position) === 0x2E/* . */) { + state.position += 3; + skipSeparationSpace(state, true, -1); + } + return; + } + + if (state.position < (state.length - 1)) { + throwError(state, 'end of the stream or a document separator is expected'); + } else { + return; + } +} + + +function loadDocuments(input, options) { + input = String(input); + options = options || {}; + + if (input.length !== 0) { + + // Add tailing `\n` if not exists + if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ && + input.charCodeAt(input.length - 1) !== 0x0D/* CR */) { + input += '\n'; + } + + // Strip BOM + if (input.charCodeAt(0) === 0xFEFF) { + input = input.slice(1); + } + } + + var state = new State(input, options); + + // Use 0 as string terminator. That significantly simplifies bounds check. + state.input += '\0'; + + while (state.input.charCodeAt(state.position) === 0x20/* Space */) { + state.lineIndent += 1; + state.position += 1; + } + + while (state.position < (state.length - 1)) { + readDocument(state); + } + + return state.documents; +} + + +function loadAll(input, iterator, options) { + var documents = loadDocuments(input, options), index, length; + + for (index = 0, length = documents.length; index < length; index += 1) { + iterator(documents[index]); + } +} + + +function load(input, options) { + var documents = loadDocuments(input, options); + + if (documents.length === 0) { + /*eslint-disable no-undefined*/ + return undefined; + } else if (documents.length === 1) { + return documents[0]; + } + throw new YAMLException('expected a single document in the stream, but found more'); +} + + +function safeLoadAll(input, output, options) { + loadAll(input, output, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + + +function safeLoad(input, options) { + return load(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + + +module.exports.loadAll = loadAll; +module.exports.load = load; +module.exports.safeLoadAll = safeLoadAll; +module.exports.safeLoad = safeLoad; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/mark.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/mark.js new file mode 100644 index 0000000..47b265c --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/mark.js @@ -0,0 +1,76 @@ +'use strict'; + + +var common = require('./common'); + + +function Mark(name, buffer, position, line, column) { + this.name = name; + this.buffer = buffer; + this.position = position; + this.line = line; + this.column = column; +} + + +Mark.prototype.getSnippet = function getSnippet(indent, maxLength) { + var head, start, tail, end, snippet; + + if (!this.buffer) return null; + + indent = indent || 4; + maxLength = maxLength || 75; + + head = ''; + start = this.position; + + while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) { + start -= 1; + if (this.position - start > (maxLength / 2 - 1)) { + head = ' ... '; + start += 5; + break; + } + } + + tail = ''; + end = this.position; + + while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) { + end += 1; + if (end - this.position > (maxLength / 2 - 1)) { + tail = ' ... '; + end -= 5; + break; + } + } + + snippet = this.buffer.slice(start, end); + + return common.repeat(' ', indent) + head + snippet + tail + '\n' + + common.repeat(' ', indent + this.position - start + head.length) + '^'; +}; + + +Mark.prototype.toString = function toString(compact) { + var snippet, where = ''; + + if (this.name) { + where += 'in "' + this.name + '" '; + } + + where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1); + + if (!compact) { + snippet = this.getSnippet(); + + if (snippet) { + where += ':\n' + snippet; + } + } + + return where; +}; + + +module.exports = Mark; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema.js new file mode 100644 index 0000000..32803ff --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema.js @@ -0,0 +1,104 @@ +'use strict'; + +/*eslint-disable max-len*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var Type = require('./type'); + + +function compileList(schema, name, result) { + var exclude = []; + + schema.include.forEach(function (includedSchema) { + result = compileList(includedSchema, name, result); + }); + + schema[name].forEach(function (currentType) { + result.forEach(function (previousType, previousIndex) { + if (previousType.tag === currentType.tag) { + exclude.push(previousIndex); + } + }); + + result.push(currentType); + }); + + return result.filter(function (type, index) { + return exclude.indexOf(index) === -1; + }); +} + + +function compileMap(/* lists... */) { + var result = {}, index, length; + + function collectType(type) { + result[type.tag] = type; + } + + for (index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); + } + + return result; +} + + +function Schema(definition) { + this.include = definition.include || []; + this.implicit = definition.implicit || []; + this.explicit = definition.explicit || []; + + this.implicit.forEach(function (type) { + if (type.loadKind && type.loadKind !== 'scalar') { + throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); + } + }); + + this.compiledImplicit = compileList(this, 'implicit', []); + this.compiledExplicit = compileList(this, 'explicit', []); + this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit); +} + + +Schema.DEFAULT = null; + + +Schema.create = function createSchema() { + var schemas, types; + + switch (arguments.length) { + case 1: + schemas = Schema.DEFAULT; + types = arguments[0]; + break; + + case 2: + schemas = arguments[0]; + types = arguments[1]; + break; + + default: + throw new YAMLException('Wrong number of arguments for Schema.create function'); + } + + schemas = common.toArray(schemas); + types = common.toArray(types); + + if (!schemas.every(function (schema) { return schema instanceof Schema; })) { + throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.'); + } + + if (!types.every(function (type) { return type instanceof Type; })) { + throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + + return new Schema({ + include: schemas, + explicit: types + }); +}; + + +module.exports = Schema; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/core.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/core.js new file mode 100644 index 0000000..206daab --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/core.js @@ -0,0 +1,18 @@ +// Standard YAML's Core schema. +// http://www.yaml.org/spec/1.2/spec.html#id2804923 +// +// NOTE: JS-YAML does not support schema-specific tag resolution restrictions. +// So, Core schema has no distinctions from JSON schema is JS-YAML. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./json') + ] +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/default_full.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/default_full.js new file mode 100644 index 0000000..a55ef42 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/default_full.js @@ -0,0 +1,25 @@ +// JS-YAML's default schema for `load` function. +// It is not described in the YAML specification. +// +// This schema is based on JS-YAML's default safe schema and includes +// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function. +// +// Also this schema is used as default base schema at `Schema.create` function. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = Schema.DEFAULT = new Schema({ + include: [ + require('./default_safe') + ], + explicit: [ + require('../type/js/undefined'), + require('../type/js/regexp'), + require('../type/js/function') + ] +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js new file mode 100644 index 0000000..11d89bb --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js @@ -0,0 +1,28 @@ +// JS-YAML's default schema for `safeLoad` function. +// It is not described in the YAML specification. +// +// This schema is based on standard YAML's Core schema and includes most of +// extra types described at YAML tag repository. (http://yaml.org/type/) + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./core') + ], + implicit: [ + require('../type/timestamp'), + require('../type/merge') + ], + explicit: [ + require('../type/binary'), + require('../type/omap'), + require('../type/pairs'), + require('../type/set') + ] +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js new file mode 100644 index 0000000..b7a33eb --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js @@ -0,0 +1,17 @@ +// Standard YAML's Failsafe schema. +// http://www.yaml.org/spec/1.2/spec.html#id2802346 + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + explicit: [ + require('../type/str'), + require('../type/seq'), + require('../type/map') + ] +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/json.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/json.js new file mode 100644 index 0000000..5be3dbf --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/schema/json.js @@ -0,0 +1,25 @@ +// Standard YAML's JSON schema. +// http://www.yaml.org/spec/1.2/spec.html#id2803231 +// +// NOTE: JS-YAML does not support schema-specific tag resolution restrictions. +// So, this schema is not such strict as defined in the YAML specification. +// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./failsafe') + ], + implicit: [ + require('../type/null'), + require('../type/bool'), + require('../type/int'), + require('../type/float') + ] +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type.js new file mode 100644 index 0000000..90b702a --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type.js @@ -0,0 +1,61 @@ +'use strict'; + +var YAMLException = require('./exception'); + +var TYPE_CONSTRUCTOR_OPTIONS = [ + 'kind', + 'resolve', + 'construct', + 'instanceOf', + 'predicate', + 'represent', + 'defaultStyle', + 'styleAliases' +]; + +var YAML_NODE_KINDS = [ + 'scalar', + 'sequence', + 'mapping' +]; + +function compileStyleAliases(map) { + var result = {}; + + if (map !== null) { + Object.keys(map).forEach(function (style) { + map[style].forEach(function (alias) { + result[String(alias)] = style; + }); + }); + } + + return result; +} + +function Type(tag, options) { + options = options || {}; + + Object.keys(options).forEach(function (name) { + if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) { + throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); + } + }); + + // TODO: Add tag format check. + this.tag = tag; + this.kind = options['kind'] || null; + this.resolve = options['resolve'] || function () { return true; }; + this.construct = options['construct'] || function (data) { return data; }; + this.instanceOf = options['instanceOf'] || null; + this.predicate = options['predicate'] || null; + this.represent = options['represent'] || null; + this.defaultStyle = options['defaultStyle'] || null; + this.styleAliases = compileStyleAliases(options['styleAliases'] || null); + + if (YAML_NODE_KINDS.indexOf(this.kind) === -1) { + throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); + } +} + +module.exports = Type; diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/binary.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/binary.js new file mode 100644 index 0000000..205629f --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/binary.js @@ -0,0 +1,135 @@ +'use strict'; + +/*eslint-disable no-bitwise*/ + +var NodeBuffer; + +try { + // A trick for browserified version, to not include `Buffer` shim + var _require = require; + NodeBuffer = _require('buffer').Buffer; +} catch (__) {} + +var Type = require('../type'); + + +// [ 64, 65, 66 ] -> [ padding, CR, LF ] +var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'; + + +function resolveYamlBinary(data) { + if (data === null) return false; + + var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP; + + // Convert one by one. + for (idx = 0; idx < max; idx++) { + code = map.indexOf(data.charAt(idx)); + + // Skip CR/LF + if (code > 64) continue; + + // Fail on illegal characters + if (code < 0) return false; + + bitlen += 6; + } + + // If there are any bits left, source was corrupted + return (bitlen % 8) === 0; +} + +function constructYamlBinary(data) { + var idx, tailbits, + input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan + max = input.length, + map = BASE64_MAP, + bits = 0, + result = []; + + // Collect by 6*4 bits (3 bytes) + + for (idx = 0; idx < max; idx++) { + if ((idx % 4 === 0) && idx) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } + + bits = (bits << 6) | map.indexOf(input.charAt(idx)); + } + + // Dump tail + + tailbits = (max % 4) * 6; + + if (tailbits === 0) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } else if (tailbits === 18) { + result.push((bits >> 10) & 0xFF); + result.push((bits >> 2) & 0xFF); + } else if (tailbits === 12) { + result.push((bits >> 4) & 0xFF); + } + + // Wrap into Buffer for NodeJS and leave Array for browser + if (NodeBuffer) return new NodeBuffer(result); + + return result; +} + +function representYamlBinary(object /*, style*/) { + var result = '', bits = 0, idx, tail, + max = object.length, + map = BASE64_MAP; + + // Convert every three bytes to 4 ASCII characters. + + for (idx = 0; idx < max; idx++) { + if ((idx % 3 === 0) && idx) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } + + bits = (bits << 8) + object[idx]; + } + + // Dump tail + + tail = max % 3; + + if (tail === 0) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } else if (tail === 2) { + result += map[(bits >> 10) & 0x3F]; + result += map[(bits >> 4) & 0x3F]; + result += map[(bits << 2) & 0x3F]; + result += map[64]; + } else if (tail === 1) { + result += map[(bits >> 2) & 0x3F]; + result += map[(bits << 4) & 0x3F]; + result += map[64]; + result += map[64]; + } + + return result; +} + +function isBinary(object) { + return NodeBuffer && NodeBuffer.isBuffer(object); +} + +module.exports = new Type('tag:yaml.org,2002:binary', { + kind: 'scalar', + resolve: resolveYamlBinary, + construct: constructYamlBinary, + predicate: isBinary, + represent: representYamlBinary +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/bool.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/bool.js new file mode 100644 index 0000000..cb77459 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/bool.js @@ -0,0 +1,35 @@ +'use strict'; + +var Type = require('../type'); + +function resolveYamlBoolean(data) { + if (data === null) return false; + + var max = data.length; + + return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) || + (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE')); +} + +function constructYamlBoolean(data) { + return data === 'true' || + data === 'True' || + data === 'TRUE'; +} + +function isBoolean(object) { + return Object.prototype.toString.call(object) === '[object Boolean]'; +} + +module.exports = new Type('tag:yaml.org,2002:bool', { + kind: 'scalar', + resolve: resolveYamlBoolean, + construct: constructYamlBoolean, + predicate: isBoolean, + represent: { + lowercase: function (object) { return object ? 'true' : 'false'; }, + uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; }, + camelcase: function (object) { return object ? 'True' : 'False'; } + }, + defaultStyle: 'lowercase' +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/float.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/float.js new file mode 100644 index 0000000..7687154 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/float.js @@ -0,0 +1,105 @@ +'use strict'; + +var common = require('../common'); +var Type = require('../type'); + +var YAML_FLOAT_PATTERN = new RegExp( + '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' + + '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' + + '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' + + '|[-+]?\\.(?:inf|Inf|INF)' + + '|\\.(?:nan|NaN|NAN))$'); + +function resolveYamlFloat(data) { + if (data === null) return false; + + if (!YAML_FLOAT_PATTERN.test(data)) return false; + + return true; +} + +function constructYamlFloat(data) { + var value, sign, base, digits; + + value = data.replace(/_/g, '').toLowerCase(); + sign = value[0] === '-' ? -1 : 1; + digits = []; + + if ('+-'.indexOf(value[0]) >= 0) { + value = value.slice(1); + } + + if (value === '.inf') { + return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + + } else if (value === '.nan') { + return NaN; + + } else if (value.indexOf(':') >= 0) { + value.split(':').forEach(function (v) { + digits.unshift(parseFloat(v, 10)); + }); + + value = 0.0; + base = 1; + + digits.forEach(function (d) { + value += d * base; + base *= 60; + }); + + return sign * value; + + } + return sign * parseFloat(value, 10); +} + + +var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/; + +function representYamlFloat(object, style) { + var res; + + if (isNaN(object)) { + switch (style) { + case 'lowercase': return '.nan'; + case 'uppercase': return '.NAN'; + case 'camelcase': return '.NaN'; + } + } else if (Number.POSITIVE_INFINITY === object) { + switch (style) { + case 'lowercase': return '.inf'; + case 'uppercase': return '.INF'; + case 'camelcase': return '.Inf'; + } + } else if (Number.NEGATIVE_INFINITY === object) { + switch (style) { + case 'lowercase': return '-.inf'; + case 'uppercase': return '-.INF'; + case 'camelcase': return '-.Inf'; + } + } else if (common.isNegativeZero(object)) { + return '-0.0'; + } + + res = object.toString(10); + + // JS stringifier can build scientific format without dots: 5e-100, + // while YAML requres dot: 5.e-100. Fix it with simple hack + + return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res; +} + +function isFloat(object) { + return (Object.prototype.toString.call(object) === '[object Number]') && + (object % 1 !== 0 || common.isNegativeZero(object)); +} + +module.exports = new Type('tag:yaml.org,2002:float', { + kind: 'scalar', + resolve: resolveYamlFloat, + construct: constructYamlFloat, + predicate: isFloat, + represent: representYamlFloat, + defaultStyle: 'lowercase' +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/int.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/int.js new file mode 100644 index 0000000..a3c4965 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/int.js @@ -0,0 +1,168 @@ +'use strict'; + +var common = require('../common'); +var Type = require('../type'); + +function isHexCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) || + ((0x41/* A */ <= c) && (c <= 0x46/* F */)) || + ((0x61/* a */ <= c) && (c <= 0x66/* f */)); +} + +function isOctCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */)); +} + +function isDecCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)); +} + +function resolveYamlInteger(data) { + if (data === null) return false; + + var max = data.length, + index = 0, + hasDigits = false, + ch; + + if (!max) return false; + + ch = data[index]; + + // sign + if (ch === '-' || ch === '+') { + ch = data[++index]; + } + + if (ch === '0') { + // 0 + if (index + 1 === max) return true; + ch = data[++index]; + + // base 2, base 8, base 16 + + if (ch === 'b') { + // base 2 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (ch !== '0' && ch !== '1') return false; + hasDigits = true; + } + return hasDigits; + } + + + if (ch === 'x') { + // base 16 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isHexCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits; + } + + // base 8 + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isOctCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits; + } + + // base 10 (except 0) or base 60 + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (ch === ':') break; + if (!isDecCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + + if (!hasDigits) return false; + + // if !base60 - done; + if (ch !== ':') return true; + + // base60 almost not used, no needs to optimize + return /^(:[0-5]?[0-9])+$/.test(data.slice(index)); +} + +function constructYamlInteger(data) { + var value = data, sign = 1, ch, base, digits = []; + + if (value.indexOf('_') !== -1) { + value = value.replace(/_/g, ''); + } + + ch = value[0]; + + if (ch === '-' || ch === '+') { + if (ch === '-') sign = -1; + value = value.slice(1); + ch = value[0]; + } + + if (value === '0') return 0; + + if (ch === '0') { + if (value[1] === 'b') return sign * parseInt(value.slice(2), 2); + if (value[1] === 'x') return sign * parseInt(value, 16); + return sign * parseInt(value, 8); + } + + if (value.indexOf(':') !== -1) { + value.split(':').forEach(function (v) { + digits.unshift(parseInt(v, 10)); + }); + + value = 0; + base = 1; + + digits.forEach(function (d) { + value += (d * base); + base *= 60; + }); + + return sign * value; + + } + + return sign * parseInt(value, 10); +} + +function isInteger(object) { + return (Object.prototype.toString.call(object)) === '[object Number]' && + (object % 1 === 0 && !common.isNegativeZero(object)); +} + +module.exports = new Type('tag:yaml.org,2002:int', { + kind: 'scalar', + resolve: resolveYamlInteger, + construct: constructYamlInteger, + predicate: isInteger, + represent: { + binary: function (object) { return '0b' + object.toString(2); }, + octal: function (object) { return '0' + object.toString(8); }, + decimal: function (object) { return object.toString(10); }, + hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); } + }, + defaultStyle: 'decimal', + styleAliases: { + binary: [ 2, 'bin' ], + octal: [ 8, 'oct' ], + decimal: [ 10, 'dec' ], + hexadecimal: [ 16, 'hex' ] + } +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/function.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/function.js new file mode 100644 index 0000000..c6a42d0 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/function.js @@ -0,0 +1,84 @@ +'use strict'; + +var esprima; + +// Browserified version does not have esprima +// +// 1. For node.js just require module as deps +// 2. For browser try to require mudule via external AMD system. +// If not found - try to fallback to window.esprima. If not +// found too - then fail to parse. +// +try { + // workaround to exclude package from browserify list. + var _require = require; + esprima = _require('esprima'); +} catch (_) { + /*global window */ + if (typeof window !== 'undefined') esprima = window.esprima; +} + +var Type = require('../../type'); + +function resolveJavascriptFunction(data) { + if (data === null) return false; + + try { + var source = '(' + data + ')', + ast = esprima.parse(source, { range: true }); + + if (ast.type !== 'Program' || + ast.body.length !== 1 || + ast.body[0].type !== 'ExpressionStatement' || + ast.body[0].expression.type !== 'FunctionExpression') { + return false; + } + + return true; + } catch (err) { + return false; + } +} + +function constructJavascriptFunction(data) { + /*jslint evil:true*/ + + var source = '(' + data + ')', + ast = esprima.parse(source, { range: true }), + params = [], + body; + + if (ast.type !== 'Program' || + ast.body.length !== 1 || + ast.body[0].type !== 'ExpressionStatement' || + ast.body[0].expression.type !== 'FunctionExpression') { + throw new Error('Failed to resolve function'); + } + + ast.body[0].expression.params.forEach(function (param) { + params.push(param.name); + }); + + body = ast.body[0].expression.body.range; + + // Esprima's ranges include the first '{' and the last '}' characters on + // function expressions. So cut them out. + /*eslint-disable no-new-func*/ + return new Function(params, source.slice(body[0] + 1, body[1] - 1)); +} + +function representJavascriptFunction(object /*, style*/) { + return object.toString(); +} + +function isFunction(object) { + return Object.prototype.toString.call(object) === '[object Function]'; +} + +module.exports = new Type('tag:yaml.org,2002:js/function', { + kind: 'scalar', + resolve: resolveJavascriptFunction, + construct: constructJavascriptFunction, + predicate: isFunction, + represent: representJavascriptFunction +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js new file mode 100644 index 0000000..43fa470 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js @@ -0,0 +1,60 @@ +'use strict'; + +var Type = require('../../type'); + +function resolveJavascriptRegExp(data) { + if (data === null) return false; + if (data.length === 0) return false; + + var regexp = data, + tail = /\/([gim]*)$/.exec(data), + modifiers = ''; + + // if regexp starts with '/' it can have modifiers and must be properly closed + // `/foo/gim` - modifiers tail can be maximum 3 chars + if (regexp[0] === '/') { + if (tail) modifiers = tail[1]; + + if (modifiers.length > 3) return false; + // if expression starts with /, is should be properly terminated + if (regexp[regexp.length - modifiers.length - 1] !== '/') return false; + } + + return true; +} + +function constructJavascriptRegExp(data) { + var regexp = data, + tail = /\/([gim]*)$/.exec(data), + modifiers = ''; + + // `/foo/gim` - tail can be maximum 4 chars + if (regexp[0] === '/') { + if (tail) modifiers = tail[1]; + regexp = regexp.slice(1, regexp.length - modifiers.length - 1); + } + + return new RegExp(regexp, modifiers); +} + +function representJavascriptRegExp(object /*, style*/) { + var result = '/' + object.source + '/'; + + if (object.global) result += 'g'; + if (object.multiline) result += 'm'; + if (object.ignoreCase) result += 'i'; + + return result; +} + +function isRegExp(object) { + return Object.prototype.toString.call(object) === '[object RegExp]'; +} + +module.exports = new Type('tag:yaml.org,2002:js/regexp', { + kind: 'scalar', + resolve: resolveJavascriptRegExp, + construct: constructJavascriptRegExp, + predicate: isRegExp, + represent: representJavascriptRegExp +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js new file mode 100644 index 0000000..95b5569 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js @@ -0,0 +1,28 @@ +'use strict'; + +var Type = require('../../type'); + +function resolveJavascriptUndefined() { + return true; +} + +function constructJavascriptUndefined() { + /*eslint-disable no-undefined*/ + return undefined; +} + +function representJavascriptUndefined() { + return ''; +} + +function isUndefined(object) { + return typeof object === 'undefined'; +} + +module.exports = new Type('tag:yaml.org,2002:js/undefined', { + kind: 'scalar', + resolve: resolveJavascriptUndefined, + construct: constructJavascriptUndefined, + predicate: isUndefined, + represent: representJavascriptUndefined +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/map.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/map.js new file mode 100644 index 0000000..f327bee --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/map.js @@ -0,0 +1,8 @@ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:map', { + kind: 'mapping', + construct: function (data) { return data !== null ? data : {}; } +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/merge.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/merge.js new file mode 100644 index 0000000..ae08a86 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/merge.js @@ -0,0 +1,12 @@ +'use strict'; + +var Type = require('../type'); + +function resolveYamlMerge(data) { + return data === '<<' || data === null; +} + +module.exports = new Type('tag:yaml.org,2002:merge', { + kind: 'scalar', + resolve: resolveYamlMerge +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/null.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/null.js new file mode 100644 index 0000000..6874daa --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/null.js @@ -0,0 +1,34 @@ +'use strict'; + +var Type = require('../type'); + +function resolveYamlNull(data) { + if (data === null) return true; + + var max = data.length; + + return (max === 1 && data === '~') || + (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL')); +} + +function constructYamlNull() { + return null; +} + +function isNull(object) { + return object === null; +} + +module.exports = new Type('tag:yaml.org,2002:null', { + kind: 'scalar', + resolve: resolveYamlNull, + construct: constructYamlNull, + predicate: isNull, + represent: { + canonical: function () { return '~'; }, + lowercase: function () { return 'null'; }, + uppercase: function () { return 'NULL'; }, + camelcase: function () { return 'Null'; } + }, + defaultStyle: 'lowercase' +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/omap.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/omap.js new file mode 100644 index 0000000..b2b5323 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/omap.js @@ -0,0 +1,44 @@ +'use strict'; + +var Type = require('../type'); + +var _hasOwnProperty = Object.prototype.hasOwnProperty; +var _toString = Object.prototype.toString; + +function resolveYamlOmap(data) { + if (data === null) return true; + + var objectKeys = [], index, length, pair, pairKey, pairHasKey, + object = data; + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + pairHasKey = false; + + if (_toString.call(pair) !== '[object Object]') return false; + + for (pairKey in pair) { + if (_hasOwnProperty.call(pair, pairKey)) { + if (!pairHasKey) pairHasKey = true; + else return false; + } + } + + if (!pairHasKey) return false; + + if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey); + else return false; + } + + return true; +} + +function constructYamlOmap(data) { + return data !== null ? data : []; +} + +module.exports = new Type('tag:yaml.org,2002:omap', { + kind: 'sequence', + resolve: resolveYamlOmap, + construct: constructYamlOmap +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/pairs.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/pairs.js new file mode 100644 index 0000000..74b5240 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/pairs.js @@ -0,0 +1,53 @@ +'use strict'; + +var Type = require('../type'); + +var _toString = Object.prototype.toString; + +function resolveYamlPairs(data) { + if (data === null) return true; + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + if (_toString.call(pair) !== '[object Object]') return false; + + keys = Object.keys(pair); + + if (keys.length !== 1) return false; + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return true; +} + +function constructYamlPairs(data) { + if (data === null) return []; + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + keys = Object.keys(pair); + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return result; +} + +module.exports = new Type('tag:yaml.org,2002:pairs', { + kind: 'sequence', + resolve: resolveYamlPairs, + construct: constructYamlPairs +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/seq.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/seq.js new file mode 100644 index 0000000..be8f77f --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/seq.js @@ -0,0 +1,8 @@ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:seq', { + kind: 'sequence', + construct: function (data) { return data !== null ? data : []; } +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/set.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/set.js new file mode 100644 index 0000000..f885a32 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/set.js @@ -0,0 +1,29 @@ +'use strict'; + +var Type = require('../type'); + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + +function resolveYamlSet(data) { + if (data === null) return true; + + var key, object = data; + + for (key in object) { + if (_hasOwnProperty.call(object, key)) { + if (object[key] !== null) return false; + } + } + + return true; +} + +function constructYamlSet(data) { + return data !== null ? data : {}; +} + +module.exports = new Type('tag:yaml.org,2002:set', { + kind: 'mapping', + resolve: resolveYamlSet, + construct: constructYamlSet +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/str.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/str.js new file mode 100644 index 0000000..27acc10 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/str.js @@ -0,0 +1,8 @@ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:str', { + kind: 'scalar', + construct: function (data) { return data !== null ? data : ''; } +}); diff --git a/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/timestamp.js b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/timestamp.js new file mode 100644 index 0000000..8fa9c58 --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/lib/js-yaml/type/timestamp.js @@ -0,0 +1,88 @@ +'use strict'; + +var Type = require('../type'); + +var YAML_DATE_REGEXP = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9])' + // [2] month + '-([0-9][0-9])$'); // [3] day + +var YAML_TIMESTAMP_REGEXP = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9]?)' + // [2] month + '-([0-9][0-9]?)' + // [3] day + '(?:[Tt]|[ \\t]+)' + // ... + '([0-9][0-9]?)' + // [4] hour + ':([0-9][0-9])' + // [5] minute + ':([0-9][0-9])' + // [6] second + '(?:\\.([0-9]*))?' + // [7] fraction + '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour + '(?::([0-9][0-9]))?))?$'); // [11] tz_minute + +function resolveYamlTimestamp(data) { + if (data === null) return false; + if (YAML_DATE_REGEXP.exec(data) !== null) return true; + if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true; + return false; +} + +function constructYamlTimestamp(data) { + var match, year, month, day, hour, minute, second, fraction = 0, + delta = null, tz_hour, tz_minute, date; + + match = YAML_DATE_REGEXP.exec(data); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); + + if (match === null) throw new Error('Date resolve error'); + + // match: [1] year [2] month [3] day + + year = +(match[1]); + month = +(match[2]) - 1; // JS month starts with 0 + day = +(match[3]); + + if (!match[4]) { // no hour + return new Date(Date.UTC(year, month, day)); + } + + // match: [4] hour [5] minute [6] second [7] fraction + + hour = +(match[4]); + minute = +(match[5]); + second = +(match[6]); + + if (match[7]) { + fraction = match[7].slice(0, 3); + while (fraction.length < 3) { // milli-seconds + fraction += '0'; + } + fraction = +fraction; + } + + // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute + + if (match[9]) { + tz_hour = +(match[10]); + tz_minute = +(match[11] || 0); + delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds + if (match[9] === '-') delta = -delta; + } + + date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + + if (delta) date.setTime(date.getTime() - delta); + + return date; +} + +function representYamlTimestamp(object /*, style*/) { + return object.toISOString(); +} + +module.exports = new Type('tag:yaml.org,2002:timestamp', { + kind: 'scalar', + resolve: resolveYamlTimestamp, + construct: constructYamlTimestamp, + instanceOf: Date, + represent: representYamlTimestamp +}); diff --git a/hm_sunwell/node_modules/js-yaml/package.json b/hm_sunwell/node_modules/js-yaml/package.json new file mode 100644 index 0000000..73d0dba --- /dev/null +++ b/hm_sunwell/node_modules/js-yaml/package.json @@ -0,0 +1,120 @@ +{ + "_args": [ + [ + "js-yaml@3.6.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/coveralls" + ] + ], + "_from": "js-yaml@3.6.1", + "_id": "js-yaml@3.6.1", + "_inCache": true, + "_installable": true, + "_location": "/js-yaml", + "_nodeVersion": "4.4.3", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/js-yaml-3.6.1.tgz_1462995636349_0.2209061929024756" + }, + "_npmUser": { + "email": "vitaly@rcdesign.ru", + "name": "vitaly" + }, + "_npmVersion": "2.15.1", + "_phantomChildren": {}, + "_requested": { + "name": "js-yaml", + "raw": "js-yaml@3.6.1", + "rawSpec": "3.6.1", + "scope": null, + "spec": "3.6.1", + "type": "version" + }, + "_requiredBy": [ + "/coveralls", + "/istanbul" + ], + "_resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "_shasum": "6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30", + "_shrinkwrap": null, + "_spec": "js-yaml@3.6.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/coveralls", + "author": { + "email": "dervus.grim@gmail.com", + "name": "Vladimir Zapparov" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + }, + "bugs": { + "url": "https://github.com/nodeca/js-yaml/issues" + }, + "contributors": [ + { + "name": "Aleksey V Zapparov", + "email": "ixti@member.fsf.org", + "url": "http://www.ixti.net/" + }, + { + "name": "Vitaly Puzrin", + "email": "vitaly@rcdesign.ru", + "url": "https://github.com/puzrin" + }, + { + "name": "Martin Grenfell", + "email": "martin.grenfell@gmail.com", + "url": "http://got-ravings.blogspot.com" + } + ], + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + }, + "description": "YAML 1.2 parser and serializer", + "devDependencies": { + "ansi": "*", + "benchmark": "*", + "browserify": "^13.0.0", + "codemirror": "^5.13.4", + "eslint": "^2.8.0", + "istanbul": "*", + "mocha": "*", + "uglify-js": "^2.6.1" + }, + "directories": {}, + "dist": { + "shasum": "6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30", + "tarball": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz" + }, + "files": [ + "bin/", + "dist/", + "index.js", + "lib/" + ], + "gitHead": "c76b837cacc69de6b86a0781db31a9bb7a193875", + "homepage": "https://github.com/nodeca/js-yaml", + "keywords": [ + "parser", + "pyyaml", + "serializer", + "yaml" + ], + "license": "MIT", + "maintainers": [ + { + "name": "vitaly", + "email": "vitaly@rcdesign.ru" + } + ], + "name": "js-yaml", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/nodeca/js-yaml.git" + }, + "scripts": { + "test": "make test" + }, + "version": "3.6.1" +} diff --git a/hm_sunwell/node_modules/jsbn/.npmignore b/hm_sunwell/node_modules/jsbn/.npmignore new file mode 100644 index 0000000..28f1ba7 --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/.npmignore @@ -0,0 +1,2 @@ +node_modules +.DS_Store \ No newline at end of file diff --git a/hm_sunwell/node_modules/jsbn/LICENSE b/hm_sunwell/node_modules/jsbn/LICENSE new file mode 100644 index 0000000..2a6457e --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/LICENSE @@ -0,0 +1,40 @@ +Licensing +--------- + +This software is covered under the following copyright: + +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + +Address all questions regarding this license to: + + Tom Wu + tjw@cs.Stanford.EDU \ No newline at end of file diff --git a/hm_sunwell/node_modules/jsbn/README.md b/hm_sunwell/node_modules/jsbn/README.md new file mode 100644 index 0000000..7aac67f --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/README.md @@ -0,0 +1,175 @@ +# jsbn: javascript big number + +[Tom Wu's Original Website](http://www-cs-students.stanford.edu/~tjw/jsbn/) + +I felt compelled to put this on github and publish to npm. I haven't tested every other big integer library out there, but the few that I have tested in comparison to this one have not even come close in performance. I am aware of the `bi` module on npm, however it has been modified and I wanted to publish the original without modifications. This is jsbn and jsbn2 from Tom Wu's original website above, with the modular pattern applied to prevent global leaks and to allow for use with node.js on the server side. + +## usage + + var BigInteger = require('jsbn'); + + var a = new BigInteger('91823918239182398123'); + alert(a.bitLength()); // 67 + + +## API + +### bi.toString() + +returns the base-10 number as a string + +### bi.negate() + +returns a new BigInteger equal to the negation of `bi` + +### bi.abs + +returns new BI of absolute value + +### bi.compareTo + + + +### bi.bitLength + + + +### bi.mod + + + +### bi.modPowInt + + + +### bi.clone + + + +### bi.intValue + + + +### bi.byteValue + + + +### bi.shortValue + + + +### bi.signum + + + +### bi.toByteArray + + + +### bi.equals + + + +### bi.min + + + +### bi.max + + + +### bi.and + + + +### bi.or + + + +### bi.xor + + + +### bi.andNot + + + +### bi.not + + + +### bi.shiftLeft + + + +### bi.shiftRight + + + +### bi.getLowestSetBit + + + +### bi.bitCount + + + +### bi.testBit + + + +### bi.setBit + + + +### bi.clearBit + + + +### bi.flipBit + + + +### bi.add + + + +### bi.subtract + + + +### bi.multiply + + + +### bi.divide + + + +### bi.remainder + + + +### bi.divideAndRemainder + + + +### bi.modPow + + + +### bi.modInverse + + + +### bi.pow + + + +### bi.gcd + + + +### bi.isProbablePrime + + diff --git a/hm_sunwell/node_modules/jsbn/example.html b/hm_sunwell/node_modules/jsbn/example.html new file mode 100644 index 0000000..7c26a56 --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/example.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/hm_sunwell/node_modules/jsbn/example.js b/hm_sunwell/node_modules/jsbn/example.js new file mode 100644 index 0000000..664c1b4 --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/example.js @@ -0,0 +1,3 @@ +var BigInteger = require('./'); +var a = new BigInteger('91823918239182398123'); +console.log(a.bitLength()); \ No newline at end of file diff --git a/hm_sunwell/node_modules/jsbn/index.js b/hm_sunwell/node_modules/jsbn/index.js new file mode 100644 index 0000000..e32fe13 --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/index.js @@ -0,0 +1,1358 @@ +(function(){ + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // See "LICENSE" for details. + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + var inBrowser = typeof navigator !== "undefined"; + if(inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(inBrowser && j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+this.DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // Copyright (c) 2005-2009 Tom Wu + // All Rights Reserved. + // See "LICENSE" for details. + + // Extended JavaScript BN functions, required for RSA private ops. + + // Version 1.1: new BigInteger("0", 10) returns "proper" zero + // Version 1.2: square() API, isProbablePrime fix + + // (public) + function bnClone() { var r = nbi(); this.copyTo(r); return r; } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>24; } + + // (public) return value as short (assumes DB>=16) + function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) alternate constructor + function bnpFromNumber(a,b,c) { + if("number" == typeof b) { + // new BigInteger(int,int,RNG) + if(a < 2) this.fromInt(1); + else { + this.fromNumber(a,c); + if(!this.testBit(a-1)) // force MSB set + this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); + if(this.isEven()) this.dAddOffset(1,0); // force odd + while(!this.isProbablePrime(b)) { + this.dAddOffset(2,0); + if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); + } + } + } + else { + // new BigInteger(int,RNG) + var x = new Array(), t = a&7; + x.length = (a>>3)+1; + b.nextBytes(x); + if(t > 0) x[0] &= ((1< 0) { + if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) + r[k++] = d|(this.s<<(this.DB-p)); + while(i >= 0) { + if(p < 8) { + d = (this[i]&((1<>(p+=this.DB-8); + } + else { + d = (this[i]>>(p-=8))&0xff; + if(p <= 0) { p += this.DB; --i; } + } + if((d&0x80) != 0) d |= -256; + if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; + if(k > 0 || d != this.s) r[k++] = d; + } + } + return r; + } + + function bnEquals(a) { return(this.compareTo(a)==0); } + function bnMin(a) { return(this.compareTo(a)<0)?this:a; } + function bnMax(a) { return(this.compareTo(a)>0)?this:a; } + + // (protected) r = this op a (bitwise) + function bnpBitwiseTo(a,op,r) { + var i, f, m = Math.min(a.t,this.t); + for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); + if(a.t < this.t) { + f = a.s&this.DM; + for(i = m; i < this.t; ++i) r[i] = op(this[i],f); + r.t = this.t; + } + else { + f = this.s&this.DM; + for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); + r.t = a.t; + } + r.s = op(this.s,a.s); + r.clamp(); + } + + // (public) this & a + function op_and(x,y) { return x&y; } + function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } + + // (public) this | a + function op_or(x,y) { return x|y; } + function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } + + // (public) this ^ a + function op_xor(x,y) { return x^y; } + function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } + + // (public) this & ~a + function op_andnot(x,y) { return x&~y; } + function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } + + // (public) ~this + function bnNot() { + var r = nbi(); + for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; + r.t = this.t; + r.s = ~this.s; + return r; + } + + // (public) this << n + function bnShiftLeft(n) { + var r = nbi(); + if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); + return r; + } + + // (public) this >> n + function bnShiftRight(n) { + var r = nbi(); + if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); + return r; + } + + // return index of lowest 1-bit in x, x < 2^31 + function lbit(x) { + if(x == 0) return -1; + var r = 0; + if((x&0xffff) == 0) { x >>= 16; r += 16; } + if((x&0xff) == 0) { x >>= 8; r += 8; } + if((x&0xf) == 0) { x >>= 4; r += 4; } + if((x&3) == 0) { x >>= 2; r += 2; } + if((x&1) == 0) ++r; + return r; + } + + // (public) returns index of lowest 1-bit (or -1 if none) + function bnGetLowestSetBit() { + for(var i = 0; i < this.t; ++i) + if(this[i] != 0) return i*this.DB+lbit(this[i]); + if(this.s < 0) return this.t*this.DB; + return -1; + } + + // return number of 1 bits in x + function cbit(x) { + var r = 0; + while(x != 0) { x &= x-1; ++r; } + return r; + } + + // (public) return number of set bits + function bnBitCount() { + var r = 0, x = this.s&this.DM; + for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); + return r; + } + + // (public) true iff nth bit is set + function bnTestBit(n) { + var j = Math.floor(n/this.DB); + if(j >= this.t) return(this.s!=0); + return((this[j]&(1<<(n%this.DB)))!=0); + } + + // (protected) this op (1<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + // (public) this + a + function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } + + // (public) this - a + function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } + + // (public) this * a + function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } + + // (public) this^2 + function bnSquare() { var r = nbi(); this.squareTo(r); return r; } + + // (public) this / a + function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } + + // (public) this % a + function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } + + // (public) [this/a,this%a] + function bnDivideAndRemainder(a) { + var q = nbi(), r = nbi(); + this.divRemTo(a,q,r); + return new Array(q,r); + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // A "null" reducer + function NullExp() {} + function nNop(x) { return x; } + function nMulTo(x,y,r) { x.multiplyTo(y,r); } + function nSqrTo(x,r) { x.squareTo(r); } + + NullExp.prototype.convert = nNop; + NullExp.prototype.revert = nNop; + NullExp.prototype.mulTo = nMulTo; + NullExp.prototype.sqrTo = nSqrTo; + + // (public) this^e + function bnPow(e) { return this.exp(e,new NullExp()); } + + // (protected) r = lower n words of "this * a", a.t <= n + // "this" should be the larger one if appropriate. + function bnpMultiplyLowerTo(a,n,r) { + var i = Math.min(this.t+a.t,n); + r.s = 0; // assumes a,this >= 0 + r.t = i; + while(i > 0) r[--i] = 0; + var j; + for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); + for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); + r.clamp(); + } + + // (protected) r = "this * a" without lower n words, n > 0 + // "this" should be the larger one if appropriate. + function bnpMultiplyUpperTo(a,n,r) { + --n; + var i = r.t = this.t+a.t-n; + r.s = 0; // assumes a,this >= 0 + while(--i >= 0) r[i] = 0; + for(i = Math.max(n-this.t,0); i < a.t; ++i) + r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); + r.clamp(); + r.drShiftTo(1,r); + } + + // Barrett modular reduction + function Barrett(m) { + // setup Barrett + this.r2 = nbi(); + this.q3 = nbi(); + BigInteger.ONE.dlShiftTo(2*m.t,this.r2); + this.mu = this.r2.divide(m); + this.m = m; + } + + function barrettConvert(x) { + if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); + else if(x.compareTo(this.m) < 0) return x; + else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } + } + + function barrettRevert(x) { return x; } + + // x = x mod m (HAC 14.42) + function barrettReduce(x) { + x.drShiftTo(this.m.t-1,this.r2); + if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } + this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); + this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); + while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); + x.subTo(this.r2,x); + while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = x^2 mod m; x != r + function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = x*y mod m; x,y != r + function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Barrett.prototype.convert = barrettConvert; + Barrett.prototype.revert = barrettRevert; + Barrett.prototype.reduce = barrettReduce; + Barrett.prototype.mulTo = barrettMulTo; + Barrett.prototype.sqrTo = barrettSqrTo; + + // (public) this^e % m (HAC 14.85) + function bnModPow(e,m) { + var i = e.bitLength(), k, r = nbv(1), z; + if(i <= 0) return r; + else if(i < 18) k = 1; + else if(i < 48) k = 3; + else if(i < 144) k = 4; + else if(i < 768) k = 5; + else k = 6; + if(i < 8) + z = new Classic(m); + else if(m.isEven()) + z = new Barrett(m); + else + z = new Montgomery(m); + + // precomputation + var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { + var g2 = nbi(); + z.sqrTo(g[1],g2); + while(n <= km) { + g[n] = nbi(); + z.mulTo(g2,g[n-2],g[n]); + n += 2; + } + } + + var j = e.t-1, w, is1 = true, r2 = nbi(), t; + i = nbits(e[j])-1; + while(j >= 0) { + if(i >= k1) w = (e[j]>>(i-k1))&km; + else { + w = (e[j]&((1<<(i+1))-1))<<(k1-i); + if(j > 0) w |= e[j-1]>>(this.DB+i-k1); + } + + n = k; + while((w&1) == 0) { w >>= 1; --n; } + if((i -= n) < 0) { i += this.DB; --j; } + if(is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } + else { + while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } + if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } + z.mulTo(r2,g[w],r); + } + + while(j >= 0 && (e[j]&(1< 0) { + x.rShiftTo(g,x); + y.rShiftTo(g,y); + } + while(x.signum() > 0) { + if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); + if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); + if(x.compareTo(y) >= 0) { + x.subTo(y,x); + x.rShiftTo(1,x); + } + else { + y.subTo(x,y); + y.rShiftTo(1,y); + } + } + if(g > 0) y.lShiftTo(g,y); + return y; + } + + // (protected) this % n, n < 2^26 + function bnpModInt(n) { + if(n <= 0) return 0; + var d = this.DV%n, r = (this.s<0)?n-1:0; + if(this.t > 0) + if(d == 0) r = this[0]%n; + else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; + return r; + } + + // (public) 1/this % m (HAC 14.61) + function bnModInverse(m) { + var ac = m.isEven(); + if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; + var u = m.clone(), v = this.clone(); + var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); + while(u.signum() != 0) { + while(u.isEven()) { + u.rShiftTo(1,u); + if(ac) { + if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } + a.rShiftTo(1,a); + } + else if(!b.isEven()) b.subTo(m,b); + b.rShiftTo(1,b); + } + while(v.isEven()) { + v.rShiftTo(1,v); + if(ac) { + if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } + c.rShiftTo(1,c); + } + else if(!d.isEven()) d.subTo(m,d); + d.rShiftTo(1,d); + } + if(u.compareTo(v) >= 0) { + u.subTo(v,u); + if(ac) a.subTo(c,a); + b.subTo(d,b); + } + else { + v.subTo(u,v); + if(ac) c.subTo(a,c); + d.subTo(b,d); + } + } + if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; + if(d.compareTo(m) >= 0) return d.subtract(m); + if(d.signum() < 0) d.addTo(m,d); else return d; + if(d.signum() < 0) return d.add(m); else return d; + } + + var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; + var lplim = (1<<26)/lowprimes[lowprimes.length-1]; + + // (public) test primality with certainty >= 1-.5^t + function bnIsProbablePrime(t) { + var i, x = this.abs(); + if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { + for(i = 0; i < lowprimes.length; ++i) + if(x[0] == lowprimes[i]) return true; + return false; + } + if(x.isEven()) return false; + i = 1; + while(i < lowprimes.length) { + var m = lowprimes[i], j = i+1; + while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; + m = x.modInt(m); + while(i < j) if(m%lowprimes[i++] == 0) return false; + } + return x.millerRabin(t); + } + + // (protected) true if probably prime (HAC 4.24, Miller-Rabin) + function bnpMillerRabin(t) { + var n1 = this.subtract(BigInteger.ONE); + var k = n1.getLowestSetBit(); + if(k <= 0) return false; + var r = n1.shiftRight(k); + t = (t+1)>>1; + if(t > lowprimes.length) t = lowprimes.length; + var a = nbi(); + for(var i = 0; i < t; ++i) { + //Pick bases at random, instead of starting at 2 + a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); + var y = a.modPow(r,this); + if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + var j = 1; + while(j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2,this); + if(y.compareTo(BigInteger.ONE) == 0) return false; + } + if(y.compareTo(n1) != 0) return false; + } + } + return true; + } + + // protected + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.fromNumber = bnpFromNumber; + BigInteger.prototype.bitwiseTo = bnpBitwiseTo; + BigInteger.prototype.changeBit = bnpChangeBit; + BigInteger.prototype.addTo = bnpAddTo; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; + BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; + BigInteger.prototype.modInt = bnpModInt; + BigInteger.prototype.millerRabin = bnpMillerRabin; + + // public + BigInteger.prototype.clone = bnClone; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.byteValue = bnByteValue; + BigInteger.prototype.shortValue = bnShortValue; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.toByteArray = bnToByteArray; + BigInteger.prototype.equals = bnEquals; + BigInteger.prototype.min = bnMin; + BigInteger.prototype.max = bnMax; + BigInteger.prototype.and = bnAnd; + BigInteger.prototype.or = bnOr; + BigInteger.prototype.xor = bnXor; + BigInteger.prototype.andNot = bnAndNot; + BigInteger.prototype.not = bnNot; + BigInteger.prototype.shiftLeft = bnShiftLeft; + BigInteger.prototype.shiftRight = bnShiftRight; + BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; + BigInteger.prototype.bitCount = bnBitCount; + BigInteger.prototype.testBit = bnTestBit; + BigInteger.prototype.setBit = bnSetBit; + BigInteger.prototype.clearBit = bnClearBit; + BigInteger.prototype.flipBit = bnFlipBit; + BigInteger.prototype.add = bnAdd; + BigInteger.prototype.subtract = bnSubtract; + BigInteger.prototype.multiply = bnMultiply; + BigInteger.prototype.divide = bnDivide; + BigInteger.prototype.remainder = bnRemainder; + BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; + BigInteger.prototype.modPow = bnModPow; + BigInteger.prototype.modInverse = bnModInverse; + BigInteger.prototype.pow = bnPow; + BigInteger.prototype.gcd = bnGCD; + BigInteger.prototype.isProbablePrime = bnIsProbablePrime; + + // JSBN-specific extension + BigInteger.prototype.square = bnSquare; + + // Expose the Barrett function + BigInteger.prototype.Barrett = Barrett + + // BigInteger interfaces not implemented in jsbn: + + // BigInteger(int signum, byte[] magnitude) + // double doubleValue() + // float floatValue() + // int hashCode() + // long longValue() + // static BigInteger valueOf(long val) + + // Random number generator - requires a PRNG backend, e.g. prng4.js + + // For best results, put code like + // + // in your main HTML document. + + var rng_state; + var rng_pool; + var rng_pptr; + + // Mix in a 32-bit integer into the pool + function rng_seed_int(x) { + rng_pool[rng_pptr++] ^= x & 255; + rng_pool[rng_pptr++] ^= (x >> 8) & 255; + rng_pool[rng_pptr++] ^= (x >> 16) & 255; + rng_pool[rng_pptr++] ^= (x >> 24) & 255; + if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; + } + + // Mix in the current time (w/milliseconds) into the pool + function rng_seed_time() { + rng_seed_int(new Date().getTime()); + } + + // Initialize the pool with junk if needed. + if(rng_pool == null) { + rng_pool = new Array(); + rng_pptr = 0; + var t; + if(typeof window !== "undefined" && window.crypto) { + if (window.crypto.getRandomValues) { + // Use webcrypto if available + var ua = new Uint8Array(32); + window.crypto.getRandomValues(ua); + for(t = 0; t < 32; ++t) + rng_pool[rng_pptr++] = ua[t]; + } + else if(navigator.appName == "Netscape" && navigator.appVersion < "5") { + // Extract entropy (256 bits) from NS4 RNG if available + var z = window.crypto.random(32); + for(t = 0; t < z.length; ++t) + rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; + } + } + while(rng_pptr < rng_psize) { // extract some randomness from Math.random() + t = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = t >>> 8; + rng_pool[rng_pptr++] = t & 255; + } + rng_pptr = 0; + rng_seed_time(); + //rng_seed_int(window.screenX); + //rng_seed_int(window.screenY); + } + + function rng_get_byte() { + if(rng_state == null) { + rng_seed_time(); + rng_state = prng_newstate(); + rng_state.init(rng_pool); + for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) + rng_pool[rng_pptr] = 0; + rng_pptr = 0; + //rng_pool = null; + } + // TODO: allow reseeding after first request + return rng_state.next(); + } + + function rng_get_bytes(ba) { + var i; + for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); + } + + function SecureRandom() {} + + SecureRandom.prototype.nextBytes = rng_get_bytes; + + // prng4.js - uses Arcfour as a PRNG + + function Arcfour() { + this.i = 0; + this.j = 0; + this.S = new Array(); + } + + // Initialize arcfour context from key, an array of ints, each from [0..255] + function ARC4init(key) { + var i, j, t; + for(i = 0; i < 256; ++i) + this.S[i] = i; + j = 0; + for(i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; + } + + function ARC4next() { + var t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; + } + + Arcfour.prototype.init = ARC4init; + Arcfour.prototype.next = ARC4next; + + // Plug in your RNG constructor here + function prng_newstate() { + return new Arcfour(); + } + + // Pool size must be a multiple of 4 and greater than 32. + // An array of bytes the size of the pool will be passed to init() + var rng_psize = 256; + + if (typeof exports !== 'undefined') { + exports = module.exports = { + BigInteger: BigInteger, + SecureRandom: SecureRandom, + }; + } else { + this.BigInteger = BigInteger; + this.SecureRandom = SecureRandom; + } + +}).call(this); diff --git a/hm_sunwell/node_modules/jsbn/package.json b/hm_sunwell/node_modules/jsbn/package.json new file mode 100644 index 0000000..f1dc9cc --- /dev/null +++ b/hm_sunwell/node_modules/jsbn/package.json @@ -0,0 +1,79 @@ +{ + "_args": [ + [ + "jsbn@~0.1.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk" + ] + ], + "_from": "jsbn@>=0.1.0 <0.2.0", + "_id": "jsbn@0.1.0", + "_inCache": true, + "_installable": true, + "_location": "/jsbn", + "_nodeVersion": "0.12.2", + "_npmUser": { + "email": "andyperlitch@gmail.com", + "name": "andyperlitch" + }, + "_npmVersion": "2.7.4", + "_phantomChildren": {}, + "_requested": { + "name": "jsbn", + "raw": "jsbn@~0.1.0", + "rawSpec": "~0.1.0", + "scope": null, + "spec": ">=0.1.0 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/ecc-jsbn", + "/jodid25519", + "/sshpk" + ], + "_resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "_shasum": "650987da0dd74f4ebf5a11377a2aa2d273e97dfd", + "_shrinkwrap": null, + "_spec": "jsbn@~0.1.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/sshpk", + "author": { + "name": "Tom Wu" + }, + "bugs": { + "url": "https://github.com/andyperlitch/jsbn/issues" + }, + "dependencies": {}, + "description": "The jsbn library is a fast, portable implementation of large-number math in pure JavaScript, enabling public-key crypto and other applications on desktop and mobile browsers.", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "650987da0dd74f4ebf5a11377a2aa2d273e97dfd", + "tarball": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" + }, + "gitHead": "148a967b112806e63ddeeed78ee7938eef74c84a", + "homepage": "https://github.com/andyperlitch/jsbn", + "keywords": [ + "big", + "biginteger", + "bignumber", + "integer" + ], + "license": "BSD", + "main": "index.js", + "maintainers": [ + { + "name": "andyperlitch", + "email": "andyperlitch@gmail.com" + } + ], + "name": "jsbn", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/andyperlitch/jsbn.git" + }, + "scripts": { + "test": "mocha test.js" + }, + "version": "0.1.0" +} diff --git a/hm_sunwell/node_modules/json-schema/README.md b/hm_sunwell/node_modules/json-schema/README.md new file mode 100644 index 0000000..4de0124 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/README.md @@ -0,0 +1,5 @@ +JSON Schema is a repository for the JSON Schema specification, reference schemas and a CommonJS implementation of JSON Schema (not the only JavaScript implementation of JSON Schema, JSV is another excellent JavaScript validator). + +Code is licensed under the AFL or BSD license as part of the Persevere +project which is administered under the Dojo foundation, +and all contributions require a Dojo CLA. \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-00/hyper-schema b/hm_sunwell/node_modules/json-schema/draft-00/hyper-schema new file mode 100644 index 0000000..de80b91 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-00/hyper-schema @@ -0,0 +1,68 @@ +{ + "$schema" : "http://json-schema.org/draft-00/hyper-schema#", + "id" : "http://json-schema.org/draft-00/hyper-schema#", + + "properties" : { + "links" : { + "type" : "array", + "items" : {"$ref" : "http://json-schema.org/draft-00/links#"}, + "optional" : true + }, + + "fragmentResolution" : { + "type" : "string", + "optional" : true, + "default" : "dot-delimited" + }, + + "root" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "readonly" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "pathStart" : { + "type" : "string", + "optional" : true, + "format" : "uri" + }, + + "mediaType" : { + "type" : "string", + "optional" : true, + "format" : "media-type" + }, + + "alternate" : { + "type" : "array", + "items" : {"$ref" : "#"}, + "optional" : true + } + }, + + "links" : [ + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + }, + + { + "href" : "{id}", + "rel" : "self" + } + ], + + "fragmentResolution" : "dot-delimited", + "extends" : {"$ref" : "http://json-schema.org/draft-00/schema#"} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-00/json-ref b/hm_sunwell/node_modules/json-schema/draft-00/json-ref new file mode 100644 index 0000000..3a872a7 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-00/json-ref @@ -0,0 +1,26 @@ +{ + "$schema" : "http://json-schema.org/draft-00/hyper-schema#", + "id" : "http://json-schema.org/draft-00/json-ref#", + + "items" : {"$ref" : "#"}, + "additionalProperties" : {"$ref" : "#"}, + + "links" : [ + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + }, + + { + "href" : "{id}", + "rel" : "self" + } + ], + + "fragmentResolution" : "dot-delimited" +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-00/links b/hm_sunwell/node_modules/json-schema/draft-00/links new file mode 100644 index 0000000..8a5e780 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-00/links @@ -0,0 +1,33 @@ +{ + "$schema" : "http://json-schema.org/draft-00/hyper-schema#", + "id" : "http://json-schema.org/draft-00/links#", + "type" : "object", + + "properties" : { + "href" : { + "type" : "string" + }, + + "rel" : { + "type" : "string" + }, + + "method" : { + "type" : "string", + "default" : "GET", + "optional" : true + }, + + "enctype" : { + "type" : "string", + "requires" : "method", + "optional" : true + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "http://json-schema.org/draft-00/hyper-schema#"}, + "optional" : true + } + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-00/schema b/hm_sunwell/node_modules/json-schema/draft-00/schema new file mode 100644 index 0000000..9aa2fbc --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-00/schema @@ -0,0 +1,155 @@ +{ + "$schema" : "http://json-schema.org/draft-00/hyper-schema#", + "id" : "http://json-schema.org/draft-00/schema#", + "type" : "object", + + "properties" : { + "type" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "optional" : true, + "default" : "any" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + }, + + "items" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + }, + + "optional" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "additionalProperties" : { + "type" : [{"$ref" : "#"}, "boolean"], + "optional" : true, + "default" : {} + }, + + "requires" : { + "type" : ["string", {"$ref" : "#"}], + "optional" : true + }, + + "minimum" : { + "type" : "number", + "optional" : true + }, + + "maximum" : { + "type" : "number", + "optional" : true + }, + + "minimumCanEqual" : { + "type" : "boolean", + "optional" : true, + "requires" : "minimum", + "default" : true + }, + + "maximumCanEqual" : { + "type" : "boolean", + "optional" : true, + "requires" : "maximum", + "default" : true + }, + + "minItems" : { + "type" : "integer", + "optional" : true, + "minimum" : 0, + "default" : 0 + }, + + "maxItems" : { + "type" : "integer", + "optional" : true, + "minimum" : 0 + }, + + "pattern" : { + "type" : "string", + "optional" : true, + "format" : "regex" + }, + + "minLength" : { + "type" : "integer", + "optional" : true, + "minimum" : 0, + "default" : 0 + }, + + "maxLength" : { + "type" : "integer", + "optional" : true + }, + + "enum" : { + "type" : "array", + "optional" : true, + "minItems" : 1 + }, + + "title" : { + "type" : "string", + "optional" : true + }, + + "description" : { + "type" : "string", + "optional" : true + }, + + "format" : { + "type" : "string", + "optional" : true + }, + + "contentEncoding" : { + "type" : "string", + "optional" : true + }, + + "default" : { + "type" : "any", + "optional" : true + }, + + "maxDecimal" : { + "type" : "integer", + "optional" : true, + "minimum" : 0 + }, + + "disallow" : { + "type" : ["string", "array"], + "items" : {"type" : "string"}, + "optional" : true + }, + + "extends" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + } + }, + + "optional" : true, + "default" : {} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-01/hyper-schema b/hm_sunwell/node_modules/json-schema/draft-01/hyper-schema new file mode 100644 index 0000000..3f6c6cc --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-01/hyper-schema @@ -0,0 +1,68 @@ +{ + "$schema" : "http://json-schema.org/draft-01/hyper-schema#", + "id" : "http://json-schema.org/draft-01/hyper-schema#", + + "properties" : { + "links" : { + "type" : "array", + "items" : {"$ref" : "http://json-schema.org/draft-01/links#"}, + "optional" : true + }, + + "fragmentResolution" : { + "type" : "string", + "optional" : true, + "default" : "dot-delimited" + }, + + "root" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "readonly" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "pathStart" : { + "type" : "string", + "optional" : true, + "format" : "uri" + }, + + "mediaType" : { + "type" : "string", + "optional" : true, + "format" : "media-type" + }, + + "alternate" : { + "type" : "array", + "items" : {"$ref" : "#"}, + "optional" : true + } + }, + + "links" : [ + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + }, + + { + "href" : "{id}", + "rel" : "self" + } + ], + + "fragmentResolution" : "dot-delimited", + "extends" : {"$ref" : "http://json-schema.org/draft-01/schema#"} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-01/json-ref b/hm_sunwell/node_modules/json-schema/draft-01/json-ref new file mode 100644 index 0000000..4d26174 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-01/json-ref @@ -0,0 +1,26 @@ +{ + "$schema" : "http://json-schema.org/draft-01/hyper-schema#", + "id" : "http://json-schema.org/draft-01/json-ref#", + + "items" : {"$ref" : "#"}, + "additionalProperties" : {"$ref" : "#"}, + + "links" : [ + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + }, + + { + "href" : "{id}", + "rel" : "self" + } + ], + + "fragmentResolution" : "dot-delimited" +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-01/links b/hm_sunwell/node_modules/json-schema/draft-01/links new file mode 100644 index 0000000..52430a5 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-01/links @@ -0,0 +1,33 @@ +{ + "$schema" : "http://json-schema.org/draft-01/hyper-schema#", + "id" : "http://json-schema.org/draft-01/links#", + "type" : "object", + + "properties" : { + "href" : { + "type" : "string" + }, + + "rel" : { + "type" : "string" + }, + + "method" : { + "type" : "string", + "default" : "GET", + "optional" : true + }, + + "enctype" : { + "type" : "string", + "requires" : "method", + "optional" : true + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "http://json-schema.org/draft-01/hyper-schema#"}, + "optional" : true + } + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-01/schema b/hm_sunwell/node_modules/json-schema/draft-01/schema new file mode 100644 index 0000000..7a208e6 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-01/schema @@ -0,0 +1,155 @@ +{ + "$schema" : "http://json-schema.org/draft-01/hyper-schema#", + "id" : "http://json-schema.org/draft-01/schema#", + "type" : "object", + + "properties" : { + "type" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "optional" : true, + "default" : "any" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + }, + + "items" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + }, + + "optional" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "additionalProperties" : { + "type" : [{"$ref" : "#"}, "boolean"], + "optional" : true, + "default" : {} + }, + + "requires" : { + "type" : ["string", {"$ref" : "#"}], + "optional" : true + }, + + "minimum" : { + "type" : "number", + "optional" : true + }, + + "maximum" : { + "type" : "number", + "optional" : true + }, + + "minimumCanEqual" : { + "type" : "boolean", + "optional" : true, + "requires" : "minimum", + "default" : true + }, + + "maximumCanEqual" : { + "type" : "boolean", + "optional" : true, + "requires" : "maximum", + "default" : true + }, + + "minItems" : { + "type" : "integer", + "optional" : true, + "minimum" : 0, + "default" : 0 + }, + + "maxItems" : { + "type" : "integer", + "optional" : true, + "minimum" : 0 + }, + + "pattern" : { + "type" : "string", + "optional" : true, + "format" : "regex" + }, + + "minLength" : { + "type" : "integer", + "optional" : true, + "minimum" : 0, + "default" : 0 + }, + + "maxLength" : { + "type" : "integer", + "optional" : true + }, + + "enum" : { + "type" : "array", + "optional" : true, + "minItems" : 1 + }, + + "title" : { + "type" : "string", + "optional" : true + }, + + "description" : { + "type" : "string", + "optional" : true + }, + + "format" : { + "type" : "string", + "optional" : true + }, + + "contentEncoding" : { + "type" : "string", + "optional" : true + }, + + "default" : { + "type" : "any", + "optional" : true + }, + + "maxDecimal" : { + "type" : "integer", + "optional" : true, + "minimum" : 0 + }, + + "disallow" : { + "type" : ["string", "array"], + "items" : {"type" : "string"}, + "optional" : true + }, + + "extends" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + } + }, + + "optional" : true, + "default" : {} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-02/hyper-schema b/hm_sunwell/node_modules/json-schema/draft-02/hyper-schema new file mode 100644 index 0000000..4ec1b75 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-02/hyper-schema @@ -0,0 +1,68 @@ +{ + "$schema" : "http://json-schema.org/draft-02/hyper-schema#", + "id" : "http://json-schema.org/draft-02/hyper-schema#", + + "properties" : { + "links" : { + "type" : "array", + "items" : {"$ref" : "http://json-schema.org/draft-02/links#"}, + "optional" : true + }, + + "fragmentResolution" : { + "type" : "string", + "optional" : true, + "default" : "slash-delimited" + }, + + "root" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "readonly" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "pathStart" : { + "type" : "string", + "optional" : true, + "format" : "uri" + }, + + "mediaType" : { + "type" : "string", + "optional" : true, + "format" : "media-type" + }, + + "alternate" : { + "type" : "array", + "items" : {"$ref" : "#"}, + "optional" : true + } + }, + + "links" : [ + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + }, + + { + "href" : "{id}", + "rel" : "self" + } + ], + + "fragmentResolution" : "slash-delimited", + "extends" : {"$ref" : "http://json-schema.org/draft-02/schema#"} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-02/json-ref b/hm_sunwell/node_modules/json-schema/draft-02/json-ref new file mode 100644 index 0000000..6526c39 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-02/json-ref @@ -0,0 +1,26 @@ +{ + "$schema" : "http://json-schema.org/draft-02/hyper-schema#", + "id" : "http://json-schema.org/draft-02/json-ref#", + + "items" : {"$ref" : "#"}, + "additionalProperties" : {"$ref" : "#"}, + + "links" : [ + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + }, + + { + "href" : "{id}", + "rel" : "self" + } + ], + + "fragmentResolution" : "dot-delimited" +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-02/links b/hm_sunwell/node_modules/json-schema/draft-02/links new file mode 100644 index 0000000..1b17617 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-02/links @@ -0,0 +1,35 @@ +{ + "$schema" : "http://json-schema.org/draft-02/hyper-schema#", + "id" : "http://json-schema.org/draft-02/links#", + "type" : "object", + + "properties" : { + "href" : { + "type" : "string" + }, + + "rel" : { + "type" : "string" + }, + + "targetSchema" : {"$ref" : "http://json-schema.org/draft-02/hyper-schema#"}, + + "method" : { + "type" : "string", + "default" : "GET", + "optional" : true + }, + + "enctype" : { + "type" : "string", + "requires" : "method", + "optional" : true + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "http://json-schema.org/draft-02/hyper-schema#"}, + "optional" : true + } + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-02/schema b/hm_sunwell/node_modules/json-schema/draft-02/schema new file mode 100644 index 0000000..61b8de1 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-02/schema @@ -0,0 +1,166 @@ +{ + "$schema" : "http://json-schema.org/draft-02/hyper-schema#", + "id" : "http://json-schema.org/draft-02/schema#", + "type" : "object", + + "properties" : { + "type" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "optional" : true, + "uniqueItems" : true, + "default" : "any" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + }, + + "items" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + }, + + "optional" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "additionalProperties" : { + "type" : [{"$ref" : "#"}, "boolean"], + "optional" : true, + "default" : {} + }, + + "requires" : { + "type" : ["string", {"$ref" : "#"}], + "optional" : true + }, + + "minimum" : { + "type" : "number", + "optional" : true + }, + + "maximum" : { + "type" : "number", + "optional" : true + }, + + "minimumCanEqual" : { + "type" : "boolean", + "optional" : true, + "requires" : "minimum", + "default" : true + }, + + "maximumCanEqual" : { + "type" : "boolean", + "optional" : true, + "requires" : "maximum", + "default" : true + }, + + "minItems" : { + "type" : "integer", + "optional" : true, + "minimum" : 0, + "default" : 0 + }, + + "maxItems" : { + "type" : "integer", + "optional" : true, + "minimum" : 0 + }, + + "uniqueItems" : { + "type" : "boolean", + "optional" : true, + "default" : false + }, + + "pattern" : { + "type" : "string", + "optional" : true, + "format" : "regex" + }, + + "minLength" : { + "type" : "integer", + "optional" : true, + "minimum" : 0, + "default" : 0 + }, + + "maxLength" : { + "type" : "integer", + "optional" : true + }, + + "enum" : { + "type" : "array", + "optional" : true, + "minItems" : 1, + "uniqueItems" : true + }, + + "title" : { + "type" : "string", + "optional" : true + }, + + "description" : { + "type" : "string", + "optional" : true + }, + + "format" : { + "type" : "string", + "optional" : true + }, + + "contentEncoding" : { + "type" : "string", + "optional" : true + }, + + "default" : { + "type" : "any", + "optional" : true + }, + + "divisibleBy" : { + "type" : "number", + "minimum" : 0, + "minimumCanEqual" : false, + "optional" : true, + "default" : 1 + }, + + "disallow" : { + "type" : ["string", "array"], + "items" : {"type" : "string"}, + "optional" : true, + "uniqueItems" : true + }, + + "extends" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "optional" : true, + "default" : {} + } + }, + + "optional" : true, + "default" : {} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-03/examples/address b/hm_sunwell/node_modules/json-schema/draft-03/examples/address new file mode 100644 index 0000000..074d34e --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/examples/address @@ -0,0 +1,20 @@ +{ + "description" : "An Address following the convention of http://microformats.org/wiki/hcard", + "type" : "object", + "properties" : { + "post-office-box" : { "type" : "string" }, + "extended-address" : { "type" : "string" }, + "street-address" : { "type":"string" }, + "locality" : { "type" : "string", "required" : true }, + "region" : { "type" : "string", "required" : true }, + "postal-code" : { "type" : "string" }, + "country-name" : { "type" : "string", "required" : true } + }, + "dependencies" : { + "post-office-box" : "street-address", + "extended-address" : "street-address", + "street-address" : "region", + "locality" : "region", + "region" : "country-name" + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-03/examples/calendar b/hm_sunwell/node_modules/json-schema/draft-03/examples/calendar new file mode 100644 index 0000000..463cfb3 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/examples/calendar @@ -0,0 +1,53 @@ +{ + "description" : "A representation of an event", + "type" : "object", + "properties" : { + "dtstart" : { + "format" : "date-time", + "type" : "string", + "description" : "Event starting time", + "required":true + }, + "summary" : { + "type":"string", + "required":true + }, + "location" : { + "type" : "string" + }, + "url" : { + "type" : "string", + "format" : "url" + }, + "dtend" : { + "format" : "date-time", + "type" : "string", + "description" : "Event ending time" + }, + "duration" : { + "format" : "date", + "type" : "string", + "description" : "Event duration" + }, + "rdate" : { + "format" : "date-time", + "type" : "string", + "description" : "Recurrence date" + }, + "rrule" : { + "type" : "string", + "description" : "Recurrence rule" + }, + "category" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "geo" : { "$ref" : "http://json-schema.org/draft-03/geo" } + } +} + + + + diff --git a/hm_sunwell/node_modules/json-schema/draft-03/examples/card b/hm_sunwell/node_modules/json-schema/draft-03/examples/card new file mode 100644 index 0000000..89287a4 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/examples/card @@ -0,0 +1,105 @@ +{ + "description":"A representation of a person, company, organization, or place", + "type":"object", + "properties":{ + "fn":{ + "description":"Formatted Name", + "type":"string" + }, + "familyName":{ + "type":"string", + "required":true + }, + "givenName":{ + "type":"string", + "required":true + }, + "additionalName":{ + "type":"array", + "items":{ + "type":"string" + } + }, + "honorificPrefix":{ + "type":"array", + "items":{ + "type":"string" + } + }, + "honorificSuffix":{ + "type":"array", + "items":{ + "type":"string" + } + }, + "nickname":{ + "type":"string" + }, + "url":{ + "type":"string", + "format":"url" + }, + "email":{ + "type":"object", + "properties":{ + "type":{ + "type":"string" + }, + "value":{ + "type":"string", + "format":"email" + } + } + }, + "tel":{ + "type":"object", + "properties":{ + "type":{ + "type":"string" + }, + "value":{ + "type":"string", + "format":"phone" + } + } + }, + "adr":{"$ref" : "http://json-schema.org/address"}, + "geo":{"$ref" : "http://json-schema.org/geo"}, + "tz":{ + "type":"string" + }, + "photo":{ + "format":"image", + "type":"string" + }, + "logo":{ + "format":"image", + "type":"string" + }, + "sound":{ + "format":"attachment", + "type":"string" + }, + "bday":{ + "type":"string", + "format":"date" + }, + "title":{ + "type":"string" + }, + "role":{ + "type":"string" + }, + "org":{ + "type":"object", + "properties":{ + "organizationName":{ + "type":"string" + }, + "organizationUnit":{ + "type":"string" + } + } + } + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-03/examples/geo b/hm_sunwell/node_modules/json-schema/draft-03/examples/geo new file mode 100644 index 0000000..73ac7e5 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/examples/geo @@ -0,0 +1,8 @@ +{ + "description" : "A geographical coordinate", + "type" : "object", + "properties" : { + "latitude" : { "type" : "number" }, + "longitude" : { "type" : "number" } + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-03/examples/interfaces b/hm_sunwell/node_modules/json-schema/draft-03/examples/interfaces new file mode 100644 index 0000000..288a198 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/examples/interfaces @@ -0,0 +1,23 @@ +{ + "extends":"http://json-schema.org/hyper-schema", + "description":"A schema for schema interface definitions that describe programmatic class structures using JSON schema syntax", + "properties":{ + "methods":{ + "type":"object", + "description":"This defines the set of methods available to the class instances", + "additionalProperties":{ + "type":"object", + "description":"The definition of the method", + "properties":{ + "parameters":{ + "type":"array", + "description":"The set of parameters that should be passed to the method when it is called", + "items":{"$ref":"#"}, + "required": true + }, + "returns":{"$ref":"#"} + } + } + } + } +} diff --git a/hm_sunwell/node_modules/json-schema/draft-03/hyper-schema b/hm_sunwell/node_modules/json-schema/draft-03/hyper-schema new file mode 100644 index 0000000..623055c --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/hyper-schema @@ -0,0 +1,60 @@ +{ + "$schema" : "http://json-schema.org/draft-03/hyper-schema#", + "extends" : {"$ref" : "http://json-schema.org/draft-03/schema#"}, + "id" : "http://json-schema.org/draft-03/hyper-schema#", + + "properties" : { + "links" : { + "type" : "array", + "items" : {"$ref" : "http://json-schema.org/draft-03/links#"} + }, + + "fragmentResolution" : { + "type" : "string", + "default" : "slash-delimited" + }, + + "root" : { + "type" : "boolean", + "default" : false + }, + + "readonly" : { + "type" : "boolean", + "default" : false + }, + + "contentEncoding" : { + "type" : "string" + }, + + "pathStart" : { + "type" : "string", + "format" : "uri" + }, + + "mediaType" : { + "type" : "string", + "format" : "media-type" + } + }, + + "links" : [ + { + "href" : "{id}", + "rel" : "self" + }, + + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + } + ], + + "fragmentResolution" : "slash-delimited" +} diff --git a/hm_sunwell/node_modules/json-schema/draft-03/json-ref b/hm_sunwell/node_modules/json-schema/draft-03/json-ref new file mode 100644 index 0000000..7e491a8 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/json-ref @@ -0,0 +1,26 @@ +{ + "$schema" : "http://json-schema.org/draft-03/hyper-schema#", + "id" : "http://json-schema.org/draft-03/json-ref#", + + "additionalItems" : {"$ref" : "#"}, + "additionalProperties" : {"$ref" : "#"}, + + "links" : [ + { + "href" : "{id}", + "rel" : "self" + }, + + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + } + ], + + "fragmentResolution" : "dot-delimited" +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-03/links b/hm_sunwell/node_modules/json-schema/draft-03/links new file mode 100644 index 0000000..6b0a85a --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/links @@ -0,0 +1,35 @@ +{ + "$schema" : "http://json-schema.org/draft-03/hyper-schema#", + "id" : "http://json-schema.org/draft-03/links#", + "type" : "object", + + "properties" : { + "href" : { + "type" : "string", + "required" : true, + "format" : "link-description-object-template" + }, + + "rel" : { + "type" : "string", + "required" : true + }, + + "targetSchema" : {"$ref" : "http://json-schema.org/draft-03/hyper-schema#"}, + + "method" : { + "type" : "string", + "default" : "GET" + }, + + "enctype" : { + "type" : "string", + "requires" : "method" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "http://json-schema.org/draft-03/hyper-schema#"} + } + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-03/schema b/hm_sunwell/node_modules/json-schema/draft-03/schema new file mode 100644 index 0000000..55ae47d --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-03/schema @@ -0,0 +1,174 @@ +{ + "$schema" : "http://json-schema.org/draft-03/schema#", + "id" : "http://json-schema.org/draft-03/schema#", + "type" : "object", + + "properties" : { + "type" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "uniqueItems" : true, + "default" : "any" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "default" : {} + }, + + "patternProperties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "default" : {} + }, + + "additionalProperties" : { + "type" : [{"$ref" : "#"}, "boolean"], + "default" : {} + }, + + "items" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "default" : {} + }, + + "additionalItems" : { + "type" : [{"$ref" : "#"}, "boolean"], + "default" : {} + }, + + "required" : { + "type" : "boolean", + "default" : false + }, + + "dependencies" : { + "type" : "object", + "additionalProperties" : { + "type" : ["string", "array", {"$ref" : "#"}], + "items" : { + "type" : "string" + } + }, + "default" : {} + }, + + "minimum" : { + "type" : "number" + }, + + "maximum" : { + "type" : "number" + }, + + "exclusiveMinimum" : { + "type" : "boolean", + "default" : false + }, + + "exclusiveMaximum" : { + "type" : "boolean", + "default" : false + }, + + "minItems" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxItems" : { + "type" : "integer", + "minimum" : 0 + }, + + "uniqueItems" : { + "type" : "boolean", + "default" : false + }, + + "pattern" : { + "type" : "string", + "format" : "regex" + }, + + "minLength" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxLength" : { + "type" : "integer" + }, + + "enum" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true + }, + + "default" : { + "type" : "any" + }, + + "title" : { + "type" : "string" + }, + + "description" : { + "type" : "string" + }, + + "format" : { + "type" : "string" + }, + + "divisibleBy" : { + "type" : "number", + "minimum" : 0, + "exclusiveMinimum" : true, + "default" : 1 + }, + + "disallow" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "uniqueItems" : true + }, + + "extends" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "default" : {} + }, + + "id" : { + "type" : "string", + "format" : "uri" + }, + + "$ref" : { + "type" : "string", + "format" : "uri" + }, + + "$schema" : { + "type" : "string", + "format" : "uri" + } + }, + + "dependencies" : { + "exclusiveMinimum" : "minimum", + "exclusiveMaximum" : "maximum" + }, + + "default" : {} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-04/hyper-schema b/hm_sunwell/node_modules/json-schema/draft-04/hyper-schema new file mode 100644 index 0000000..f96d1ac --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-04/hyper-schema @@ -0,0 +1,60 @@ +{ + "$schema" : "http://json-schema.org/draft-04/hyper-schema#", + "extends" : {"$ref" : "http://json-schema.org/draft-04/schema#"}, + "id" : "http://json-schema.org/draft-04/hyper-schema#", + + "properties" : { + "links" : { + "type" : "array", + "items" : {"$ref" : "http://json-schema.org/draft-04/links#"} + }, + + "fragmentResolution" : { + "type" : "string", + "default" : "json-pointer" + }, + + "root" : { + "type" : "boolean", + "default" : false + }, + + "readonly" : { + "type" : "boolean", + "default" : false + }, + + "contentEncoding" : { + "type" : "string" + }, + + "pathStart" : { + "type" : "string", + "format" : "uri" + }, + + "mediaType" : { + "type" : "string", + "format" : "media-type" + } + }, + + "links" : [ + { + "href" : "{id}", + "rel" : "self" + }, + + { + "href" : "{$ref}", + "rel" : "full" + }, + + { + "href" : "{$schema}", + "rel" : "describedby" + } + ], + + "fragmentResolution" : "json-pointer" +} diff --git a/hm_sunwell/node_modules/json-schema/draft-04/links b/hm_sunwell/node_modules/json-schema/draft-04/links new file mode 100644 index 0000000..de272cc --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-04/links @@ -0,0 +1,41 @@ +{ + "$schema" : "http://json-schema.org/draft-04/hyper-schema#", + "id" : "http://json-schema.org/draft-04/links#", + "type" : "object", + + "properties" : { + "rel" : { + "type" : "string" + }, + + "href" : { + "type" : "string" + }, + + "template" : { + "type" : "string" + }, + + "targetSchema" : {"$ref" : "http://json-schema.org/draft-04/hyper-schema#"}, + + "method" : { + "type" : "string", + "default" : "GET" + }, + + "enctype" : { + "type" : "string" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "http://json-schema.org/draft-04/hyper-schema#"} + } + }, + + "required" : ["rel", "href"], + + "dependencies" : { + "enctype" : "method" + } +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-04/schema b/hm_sunwell/node_modules/json-schema/draft-04/schema new file mode 100644 index 0000000..598951e --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-04/schema @@ -0,0 +1,189 @@ +{ + "$schema" : "http://json-schema.org/draft-04/schema#", + "id" : "http://json-schema.org/draft-04/schema#", + "type" : "object", + + "properties" : { + "type" : { + "type" : [ + { + "id" : "#simple-type", + "type" : "string", + "enum" : ["object", "array", "string", "number", "boolean", "null", "any"] + }, + "array" + ], + "items" : { + "type" : [ + {"$ref" : "#simple-type"}, + {"$ref" : "#"} + ] + }, + "uniqueItems" : true, + "default" : "any" + }, + + "disallow" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "uniqueItems" : true + }, + + "extends" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "default" : {} + }, + + "enum" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true + }, + + "minimum" : { + "type" : "number" + }, + + "maximum" : { + "type" : "number" + }, + + "exclusiveMinimum" : { + "type" : "boolean", + "default" : false + }, + + "exclusiveMaximum" : { + "type" : "boolean", + "default" : false + }, + + "divisibleBy" : { + "type" : "number", + "minimum" : 0, + "exclusiveMinimum" : true, + "default" : 1 + }, + + "minLength" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxLength" : { + "type" : "integer" + }, + + "pattern" : { + "type" : "string" + }, + + "items" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "default" : {} + }, + + "additionalItems" : { + "type" : [{"$ref" : "#"}, "boolean"], + "default" : {} + }, + + "minItems" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxItems" : { + "type" : "integer", + "minimum" : 0 + }, + + "uniqueItems" : { + "type" : "boolean", + "default" : false + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "default" : {} + }, + + "patternProperties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "default" : {} + }, + + "additionalProperties" : { + "type" : [{"$ref" : "#"}, "boolean"], + "default" : {} + }, + + "minProperties" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxProperties" : { + "type" : "integer", + "minimum" : 0 + }, + + "required" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + + "dependencies" : { + "type" : "object", + "additionalProperties" : { + "type" : ["string", "array", {"$ref" : "#"}], + "items" : { + "type" : "string" + } + }, + "default" : {} + }, + + "id" : { + "type" : "string" + }, + + "$ref" : { + "type" : "string" + }, + + "$schema" : { + "type" : "string" + }, + + "title" : { + "type" : "string" + }, + + "description" : { + "type" : "string" + }, + + "default" : { + "type" : "any" + } + }, + + "dependencies" : { + "exclusiveMinimum" : "minimum", + "exclusiveMaximum" : "maximum" + }, + + "default" : {} +} \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/draft-zyp-json-schema-03.xml b/hm_sunwell/node_modules/json-schema/draft-zyp-json-schema-03.xml new file mode 100644 index 0000000..c28f40d --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-zyp-json-schema-03.xml @@ -0,0 +1,1120 @@ + + + + + + + + + + + + + + + +]> + + + + + + + + + A JSON Media Type for Describing the Structure and Meaning of JSON Documents + + + SitePen (USA) +
+ + 530 Lytton Avenue + Palo Alto, CA 94301 + USA + + +1 650 968 8787 + kris@sitepen.com +
+
+ + +
+ + + Calgary, AB + Canada + + gary.court@gmail.com +
+
+ + + Internet Engineering Task Force + JSON + Schema + JavaScript + Object + Notation + Hyper Schema + Hypermedia + + + + JSON (JavaScript Object Notation) Schema defines the media type "application/schema+json", + a JSON based format for defining + the structure of JSON data. JSON Schema provides a contract for what JSON + data is required for a given application and how to interact with it. JSON + Schema is intended to define validation, documentation, hyperlink + navigation, and interaction control of JSON data. + + +
+ + +
+ + JSON (JavaScript Object Notation) Schema is a JSON media type for defining + the structure of JSON data. JSON Schema provides a contract for what JSON + data is required for a given application and how to interact with it. JSON + Schema is intended to define validation, documentation, hyperlink + navigation, and interaction control of JSON data. + +
+ +
+ + + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", + "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be + interpreted as described in RFC 2119. + +
+ + + +
+ + JSON Schema defines the media type "application/schema+json" for + describing the structure of other + JSON documents. JSON Schema is JSON-based and includes facilities + for describing the structure of JSON documents in terms of + allowable values, descriptions, and interpreting relations with other resources. + + + JSON Schema format is organized into several separate definitions. The first + definition is the core schema specification. This definition is primary + concerned with describing a JSON structure and specifying valid elements + in the structure. The second definition is the Hyper Schema specification + which is intended define elements in a structure that can be interpreted as + hyperlinks. + Hyper Schema builds on JSON Schema to describe the hyperlink structure of + other JSON documents and elements of interaction. This allows user agents to be able to successfully navigate + JSON documents based on their schemas. + + + Cumulatively JSON Schema acts as a meta-document that can be used to define the required type and constraints on + property values, as well as define the meaning of the property values + for the purpose of describing a resource and determining hyperlinks + within the representation. + +
+ An example JSON Schema that describes products might look like: + + + + + This schema defines the properties of the instance JSON documents, + the required properties (id, name, and price), as well as an optional + property (tags). This also defines the link relations of the instance + JSON documents. + +
+ +
+ + For this specification, schema will be used to denote a JSON Schema + definition, and an instance refers to a JSON value that the schema + will be describing and validating. + +
+ +
+ + The JSON Schema media type does not attempt to dictate the structure of JSON + representations that contain data, but rather provides a separate format + for flexibly communicating how a JSON representation should be + interpreted and validated, such that user agents can properly understand + acceptable structures and extrapolate hyperlink information + with the JSON document. It is acknowledged that JSON documents come + in a variety of structures, and JSON is unique in that the structure + of stored data structures often prescribes a non-ambiguous definite + JSON representation. Attempting to force a specific structure is generally + not viable, and therefore JSON Schema allows for a great flexibility + in the structure of the JSON data that it describes. + + + This specification is protocol agnostic. + The underlying protocol (such as HTTP) should sufficiently define the + semantics of the client-server interface, the retrieval of resource + representations linked to by JSON representations, and modification of + those resources. The goal of this + format is to sufficiently describe JSON structures such that one can + utilize existing information available in existing JSON + representations from a large variety of services that leverage a representational state transfer + architecture using existing protocols. + +
+
+ +
+ + JSON Schema instances are correlated to their schema by the "describedby" + relation, where the schema is defined to be the target of the relation. + Instance representations may be of the "application/json" media type or + any other subtype. Consequently, dictating how an instance + representation should specify the relation to the schema is beyond the normative scope + of this document (since this document specifically defines the JSON + Schema media type, and no other), but it is recommended that instances + specify their schema so that user agents can interpret the instance + representation and messages may retain the self-descriptive + characteristic, avoiding the need for out-of-band information about + instance data. Two approaches are recommended for declaring the + relation to the schema that describes the meaning of a JSON instance's (or collection + of instances) structure. A MIME type parameter named + "profile" or a relation of "describedby" (which could be defined by a Link header) may be used: + +
+ + + +
+ + or if the content is being transferred by a protocol (such as HTTP) that + provides headers, a Link header can be used: + +
+ +; rel="describedby" +]]> + +
+ + Instances MAY specify multiple schemas, to indicate all the schemas that + are applicable to the data, and the data SHOULD be valid by all the schemas. + The instance data MAY have multiple schemas + that it is defined by (the instance data SHOULD be valid for those schemas). + Or if the document is a collection of instances, the collection MAY contain + instances from different schemas. When collections contain heterogeneous + instances, the "pathStart" attribute MAY be specified in the + schema to disambiguate which schema should be applied for each item in the + collection. However, ultimately, the mechanism for referencing a schema is up to the + media type of the instance documents (if they choose to specify that schemas + can be referenced). +
+ +
+ + JSON Schemas can themselves be described using JSON Schemas. + A self-describing JSON Schema for the core JSON Schema can + be found at http://json-schema.org/schema for the latest version or + http://json-schema.org/draft-03/schema for the draft-03 version. The hyper schema + self-description can be found at http://json-schema.org/hyper-schema + or http://json-schema.org/draft-03/hyper-schema. All schemas + used within a protocol with media type definitions + SHOULD include a MIME parameter that refers to the self-descriptive + hyper schema or another schema that extends this hyper schema: + +
+ + + +
+
+
+
+ +
+ + A JSON Schema is a JSON Object that defines various attributes + (including usage and valid values) of a JSON value. JSON + Schema has recursive capabilities; there are a number of elements + in the structure that allow for nested JSON Schemas. + + +
+ An example JSON Schema definition could look like: + + + +
+ + + A JSON Schema object may have any of the following properties, called schema + attributes (all attributes are optional): + + +
+ + This attribute defines what the primitive type or the schema of the instance MUST be in order to validate. + This attribute can take one of two forms: + + + + A string indicating a primitive or simple type. The following are acceptable string values: + + + Value MUST be a string. + Value MUST be a number, floating point numbers are allowed. + Value MUST be an integer, no floating point numbers are allowed. This is a subset of the number type. + Value MUST be a boolean. + Value MUST be an object. + Value MUST be an array. + Value MUST be null. Note this is mainly for purpose of being able use union types to define nullability. If this type is not included in a union, null values are not allowed (the primitives listed above do not allow nulls on their own). + Value MAY be of any type including null. + + + If the property is not defined or is not in this list, then any type of value is acceptable. + Other type values MAY be used for custom purposes, but minimal validators of the specification + implementation can allow any instance value on unknown type values. + + + + An array of two or more simple type definitions. Each item in the array MUST be a simple type definition or a schema. + The instance value is valid if it is of the same type as one of the simple type definitions, or valid by one of the schemas, in the array. + + + + +
+ For example, a schema that defines if an instance can be a string or a number would be: + + +
+
+ +
+ This attribute is an object with property definitions that define the valid values of instance object property values. When the instance value is an object, the property values of the instance object MUST conform to the property definitions in this object. In this object, each property definition's value MUST be a schema, and the property's name MUST be the name of the instance property that it defines. The instance property value MUST be valid according to the schema from the property definition. Properties are considered unordered, the order of the instance properties MAY be in any order. +
+ +
+ This attribute is an object that defines the schema for a set of property names of an object instance. The name of each property of this attribute's object is a regular expression pattern in the ECMA 262/Perl 5 format, while the value is a schema. If the pattern matches the name of a property on the instance object, the value of the instance's property MUST be valid against the pattern name's schema value. +
+ +
+ This attribute defines a schema for all properties that are not explicitly defined in an object type definition. If specified, the value MUST be a schema or a boolean. If false is provided, no additional properties are allowed beyond the properties defined in the schema. The default value is an empty schema which allows any value for additional properties. +
+ +
+ This attribute defines the allowed items in an instance array, and MUST be a schema or an array of schemas. The default value is an empty schema which allows any value for items in the instance array. + When this attribute value is a schema and the instance value is an array, then all the items in the array MUST be valid according to the schema. + When this attribute value is an array of schemas and the instance value is an array, each position in the instance array MUST conform to the schema in the corresponding position for this array. This called tuple typing. When tuple typing is used, additional items are allowed, disallowed, or constrained by the "additionalItems" attribute using the same rules as "additionalProperties" for objects. +
+ +
+ This provides a definition for additional items in an array instance when tuple definitions of the items is provided. This can be false to indicate additional items in the array are not allowed, or it can be a schema that defines the schema of the additional items. +
+ +
+ This attribute indicates if the instance must have a value, and not be undefined. This is false by default, making the instance optional. +
+ +
+ This attribute is an object that defines the requirements of a property on an instance object. If an object instance has a property with the same name as a property in this attribute's object, then the instance must be valid against the attribute's property value (hereafter referred to as the "dependency value"). + + The dependency value can take one of two forms: + + + + If the dependency value is a string, then the instance object MUST have a property with the same name as the dependency value. + If the dependency value is an array of strings, then the instance object MUST have a property with the same name as each string in the dependency value's array. + + + If the dependency value is a schema, then the instance object MUST be valid against the schema. + + + +
+ +
+ This attribute defines the minimum value of the instance property when the type of the instance value is a number. +
+ +
+ This attribute defines the maximum value of the instance property when the type of the instance value is a number. +
+ +
+ This attribute indicates if the value of the instance (if the instance is a number) can not equal the number defined by the "minimum" attribute. This is false by default, meaning the instance value can be greater then or equal to the minimum value. +
+ +
+ This attribute indicates if the value of the instance (if the instance is a number) can not equal the number defined by the "maximum" attribute. This is false by default, meaning the instance value can be less then or equal to the maximum value. +
+ +
+ This attribute defines the minimum number of values in an array when the array is the instance value. +
+ +
+ This attribute defines the maximum number of values in an array when the array is the instance value. +
+ +
+ This attribute indicates that all items in an array instance MUST be unique (contains no two identical values). + + Two instance are consider equal if they are both of the same type and: + + + are null; or + are booleans/numbers/strings and have the same value; or + are arrays, contains the same number of items, and each item in the array is equal to the corresponding item in the other array; or + are objects, contains the same property names, and each property in the object is equal to the corresponding property in the other object. + + +
+ +
+ When the instance value is a string, this provides a regular expression that a string instance MUST match in order to be valid. Regular expressions SHOULD follow the regular expression specification from ECMA 262/Perl 5 +
+ +
+ When the instance value is a string, this defines the minimum length of the string. +
+ +
+ When the instance value is a string, this defines the maximum length of the string. +
+ +
+ This provides an enumeration of all possible values that are valid for the instance property. This MUST be an array, and each item in the array represents a possible value for the instance value. If this attribute is defined, the instance value MUST be one of the values in the array in order for the schema to be valid. Comparison of enum values uses the same algorithm as defined in "uniqueItems". +
+ +
+ This attribute defines the default value of the instance when the instance is undefined. +
+ +
+ This attribute is a string that provides a short description of the instance property. +
+ +
+ This attribute is a string that provides a full description of the of purpose the instance property. +
+ +
+ This property defines the type of data, content type, or microformat to be expected in the instance property values. A format attribute MAY be one of the values listed below, and if so, SHOULD adhere to the semantics describing for the format. A format SHOULD only be used to give meaning to primitive types (string, integer, number, or boolean). Validators MAY (but are not required to) validate that the instance values conform to a format. + + + The following formats are predefined: + + + This SHOULD be a date in ISO 8601 format of YYYY-MM-DDThh:mm:ssZ in UTC time. This is the recommended form of date/timestamp. + This SHOULD be a date in the format of YYYY-MM-DD. It is recommended that you use the "date-time" format instead of "date" unless you need to transfer only the date part. + This SHOULD be a time in the format of hh:mm:ss. It is recommended that you use the "date-time" format instead of "time" unless you need to transfer only the time part. + This SHOULD be the difference, measured in milliseconds, between the specified time and midnight, 00:00 of January 1, 1970 UTC. The value SHOULD be a number (integer or float). + A regular expression, following the regular expression specification from ECMA 262/Perl 5. + This is a CSS color (like "#FF0000" or "red"), based on CSS 2.1. + This is a CSS style definition (like "color: red; background-color:#FFF"), based on CSS 2.1. + This SHOULD be a phone number (format MAY follow E.123). + This value SHOULD be a URI. + This SHOULD be an email address. + This SHOULD be an ip version 4 address. + This SHOULD be an ip version 6 address. + This SHOULD be a host-name. + + + + Additional custom formats MAY be created. These custom formats MAY be expressed as an URI, and this URI MAY reference a schema of that format. +
+ +
+ This attribute defines what value the number instance must be divisible by with no remainder (the result of the division must be an integer.) The value of this attribute SHOULD NOT be 0. +
+ +
+ This attribute takes the same values as the "type" attribute, however if the instance matches the type or if this value is an array and the instance matches any type or schema in the array, then this instance is not valid. +
+ +
+ The value of this property MUST be another schema which will provide a base schema which the current schema will inherit from. The inheritance rules are such that any instance that is valid according to the current schema MUST be valid according to the referenced schema. This MAY also be an array, in which case, the instance MUST be valid for all the schemas in the array. A schema that extends another schema MAY define additional attributes, constrain existing attributes, or add other constraints. + + Conceptually, the behavior of extends can be seen as validating an + instance against all constraints in the extending schema as well as + the extended schema(s). More optimized implementations that merge + schemas are possible, but are not required. Some examples of using "extends": + +
+ + + +
+ +
+ + + +
+
+
+ +
+ + This attribute defines the current URI of this schema (this attribute is + effectively a "self" link). This URI MAY be relative or absolute. If + the URI is relative it is resolved against the current URI of the parent + schema it is contained in. If this schema is not contained in any + parent schema, the current URI of the parent schema is held to be the + URI under which this schema was addressed. If id is missing, the current URI of a schema is + defined to be that of the parent schema. The current URI of the schema + is also used to construct relative references such as for $ref. + +
+ +
+ + This attribute defines a URI of a schema that contains the full representation of this schema. + When a validator encounters this attribute, it SHOULD replace the current schema with the schema referenced by the value's URI (if known and available) and re-validate the instance. + This URI MAY be relative or absolute, and relative URIs SHOULD be resolved against the URI of the current schema. + +
+ +
+ + This attribute defines a URI of a JSON Schema that is the schema of the current schema. + When this attribute is defined, a validator SHOULD use the schema referenced by the value's URI (if known and available) when resolving Hyper Schemalinks. + + + + A validator MAY use this attribute's value to determine which version of JSON Schema the current schema is written in, and provide the appropriate validation features and behavior. + Therefore, it is RECOMMENDED that all schema authors include this attribute in their schemas to prevent conflicts with future JSON Schema specification changes. + +
+
+ +
+ + The following attributes are specified in addition to those + attributes that already provided by the core schema with the specific + purpose of informing user agents of relations between resources based + on JSON data. Just as with JSON + schema attributes, all the attributes in hyper schemas are optional. + Therefore, an empty object is a valid (non-informative) schema, and + essentially describes plain JSON (no constraints on the structures). + Addition of attributes provides additive information for user agents. + + +
+ + The value of the links property MUST be an array, where each item + in the array is a link description object which describes the link + relations of the instances. + + +
+ + A link description object is used to describe link relations. In + the context of a schema, it defines the link relations of the + instances of the schema, and can be parameterized by the instance + values. The link description format can be used on its own in + regular (non-schema documents), and use of this format can + be declared by referencing the normative link description + schema as the the schema for the data structure that uses the + links. The URI of the normative link description schema is: + http://json-schema.org/links (latest version) or + http://json-schema.org/draft-03/links (draft-03 version). + + +
+ + The value of the "href" link description property + indicates the target URI of the related resource. The value + of the instance property SHOULD be resolved as a URI-Reference per RFC 3986 + and MAY be a relative URI. The base URI to be used for relative resolution + SHOULD be the URI used to retrieve the instance object (not the schema) + when used within a schema. Also, when links are used within a schema, the URI + SHOULD be parametrized by the property values of the instance + object, if property values exist for the corresponding variables + in the template (otherwise they MAY be provided from alternate sources, like user input). + + + + Instance property values SHOULD be substituted into the URIs where + matching braces ('{', '}') are found surrounding zero or more characters, + creating an expanded URI. Instance property value substitutions are resolved + by using the text between the braces to denote the property name + from the instance to get the value to substitute. + +
+ For example, if an href value is defined: + + + + Then it would be resolved by replace the value of the "id" property value from the instance object. +
+ +
+ If the value of the "id" property was "45", the expanded URI would be: + + + +
+ + If matching braces are found with the string "@" (no quotes) between the braces, then the + actual instance value SHOULD be used to replace the braces, rather than a property value. + This should only be used in situations where the instance is a scalar (string, + boolean, or number), and not for objects or arrays. +
+
+ +
+ + The value of the "rel" property indicates the name of the + relation to the target resource. The relation to the target SHOULD be interpreted as specifically from the instance object that the schema (or sub-schema) applies to, not just the top level resource that contains the object within its hierarchy. If a resource JSON representation contains a sub object with a property interpreted as a link, that sub-object holds the relation with the target. A relation to target from the top level resource MUST be indicated with the schema describing the top level JSON representation. + + + + Relationship definitions SHOULD NOT be media type dependent, and users are encouraged to utilize existing accepted relation definitions, including those in existing relation registries (see RFC 4287). However, we define these relations here for clarity of normative interpretation within the context of JSON hyper schema defined relations: + + + + If the relation value is "self", when this property is encountered in + the instance object, the object represents a resource and the instance object is + treated as a full representation of the target resource identified by + the specified URI. + + + + This indicates that the target of the link is the full representation for the instance object. The object that contains this link possibly may not be the full representation. + + + + This indicates the target of the link is the schema for the instance object. This MAY be used to specifically denote the schemas of objects within a JSON object hierarchy, facilitating polymorphic type data structures. + + + + This relation indicates that the target of the link + SHOULD be treated as the root or the body of the representation for the + purposes of user agent interaction or fragment resolution. All other + properties of the instance objects can be regarded as meta-data + descriptions for the data. + + + + + + The following relations are applicable for schemas (the schema as the "from" resource in the relation): + + + This indicates the target resource that represents collection of instances of a schema. + This indicates a target to use for creating new instances of a schema. This link definition SHOULD be a submission link with a non-safe method (like POST). + + + + +
+ For example, if a schema is defined: + + + +
+ +
+ And if a collection of instance resource's JSON representation was retrieved: + + + +
+ + This would indicate that for the first item in the collection, its own + (self) URI would resolve to "/Resource/thing" and the first item's "up" + relation SHOULD be resolved to the resource at "/Resource/parent". + The "children" collection would be located at "/Resource/?upId=thing". +
+
+ +
+ This property value is a schema that defines the expected structure of the JSON representation of the target of the link. +
+ +
+ + The following properties also apply to link definition objects, and + provide functionality analogous to HTML forms, in providing a + means for submitting extra (often user supplied) information to send to a server. + + +
+ + This attribute defines which method can be used to access the target resource. + In an HTTP environment, this would be "GET" or "POST" (other HTTP methods + such as "PUT" and "DELETE" have semantics that are clearly implied by + accessed resources, and do not need to be defined here). + This defaults to "GET". + +
+ +
+ + If present, this property indicates a query media type format that the server + supports for querying or posting to the collection of instances at the target + resource. The query can be + suffixed to the target URI to query the collection with + property-based constraints on the resources that SHOULD be returned from + the server or used to post data to the resource (depending on the method). + +
+ For example, with the following schema: + + + + This indicates that the client can query the server for instances that have a specific name. +
+ +
+ For example: + + + +
+ + If no enctype or method is specified, only the single URI specified by + the href property is defined. If the method is POST, "application/json" is + the default media type. +
+
+ +
+ + This attribute contains a schema which defines the acceptable structure of the submitted + request (for a GET request, this schema would define the properties for the query string + and for a POST request, this would define the body). + +
+
+
+
+ +
+ + This property indicates the fragment resolution protocol to use for + resolving fragment identifiers in URIs within the instance + representations. This applies to the instance object URIs and all + children of the instance object's URIs. The default fragment resolution + protocol is "slash-delimited", which is defined below. Other fragment + resolution protocols MAY be used, but are not defined in this document. + + + + The fragment identifier is based on RFC 2396, Sec 5, and defines the + mechanism for resolving references to entities within a document. + + +
+ + With the slash-delimited fragment resolution protocol, the fragment + identifier is interpreted as a series of property reference tokens that start with and + are delimited by the "/" character (\x2F). Each property reference token + is a series of unreserved or escaped URI characters. Each property + reference token SHOULD be interpreted, starting from the beginning of + the fragment identifier, as a path reference in the target JSON + structure. The final target value of the fragment can be determined by + starting with the root of the JSON structure from the representation of + the resource identified by the pre-fragment URI. If the target is a JSON + object, then the new target is the value of the property with the name + identified by the next property reference token in the fragment. If the + target is a JSON array, then the target is determined by finding the + item in array the array with the index defined by the next property + reference token (which MUST be a number). The target is successively + updated for each property reference token, until the entire fragment has + been traversed. + + + + Property names SHOULD be URI-encoded. In particular, any "/" in a + property name MUST be encoded to avoid being interpreted as a property + delimiter. + + + +
+ For example, for the following JSON representation: + + + +
+ +
+ The following fragment identifiers would be resolved: + + + +
+
+
+ +
+ + The dot-delimited fragment resolution protocol is the same as + slash-delimited fragment resolution protocol except that the "." character + (\x2E) is used as the delimiter between property names (instead of "/") and + the path does not need to start with a ".". For example, #.foo and #foo are a valid fragment + identifiers for referencing the value of the foo propery. + +
+
+ +
+ This attribute indicates that the instance property SHOULD NOT be changed. Attempts by a user agent to modify the value of this property are expected to be rejected by a server. +
+ +
+ If the instance property value is a string, this attribute defines that the string SHOULD be interpreted as binary data and decoded using the encoding named by this schema property. RFC 2045, Sec 6.1 lists the possible values for this property. +
+ +
+ + This attribute is a URI that defines what the instance's URI MUST start with in order to validate. + The value of the "pathStart" attribute MUST be resolved as per RFC 3986, Sec 5, + and is relative to the instance's URI. + + + + When multiple schemas have been referenced for an instance, the user agent + can determine if this schema is applicable for a particular instance by + determining if the URI of the instance begins with the the value of the "pathStart" + attribute. If the URI of the instance does not start with this URI, + or if another schema specifies a starting URI that is longer and also matches the + instance, this schema SHOULD NOT be applied to the instance. Any schema + that does not have a pathStart attribute SHOULD be considered applicable + to all the instances for which it is referenced. + +
+ +
+ This attribute defines the media type of the instance representations that this schema is defining. +
+
+ +
+ + This specification is a sub-type of the JSON format, and + consequently the security considerations are generally the same as RFC 4627. + However, an additional issue is that when link relation of "self" + is used to denote a full representation of an object, the user agent + SHOULD NOT consider the representation to be the authoritative representation + of the resource denoted by the target URI if the target URI is not + equivalent to or a sub-path of the the URI used to request the resource + representation which contains the target URI with the "self" link. + +
+ For example, if a hyper schema was defined: + + + +
+ +
+ And a resource was requested from somesite.com: + + + +
+ +
+ With a response of: + + + +
+
+
+ +
+ The proposed MIME media type for JSON Schema is "application/schema+json". + Type name: application + Subtype name: schema+json + Required parameters: profile + + The value of the profile parameter SHOULD be a URI (relative or absolute) that + refers to the schema used to define the structure of this structure (the + meta-schema). Normally the value would be http://json-schema.org/draft-03/hyper-schema, + but it is allowable to use other schemas that extend the hyper schema's meta- + schema. + + Optional parameters: pretty + The value of the pretty parameter MAY be true or false to indicate if additional whitespace has been included to make the JSON representation easier to read. + +
+ + This registry is maintained by IANA per RFC 4287 and this specification adds + four values: "full", "create", "instances", "root". New + assignments are subject to IESG Approval, as outlined in RFC 5226. + Requests should be made by email to IANA, which will then forward the + request to the IESG, requesting approval. + +
+
+
+ + + + + &rfc2045; + &rfc2119; + &rfc2396; + &rfc3339; + &rfc3986; + &rfc4287; + + + &rfc2616; + &rfc4627; + &rfc5226; + &iddiscovery; + &uritemplate; + &linkheader; + &html401; + &css21; + + +
+ + + + + Added example and verbiage to "extends" attribute. + Defined slash-delimited to use a leading slash. + Made "root" a relation instead of an attribute. + Removed address values, and MIME media type from format to reduce confusion (mediaType already exists, so it can be used for MIME types). + Added more explanation of nullability. + Removed "alternate" attribute. + Upper cased many normative usages of must, may, and should. + Replaced the link submission "properties" attribute to "schema" attribute. + Replaced "optional" attribute with "required" attribute. + Replaced "maximumCanEqual" attribute with "exclusiveMaximum" attribute. + Replaced "minimumCanEqual" attribute with "exclusiveMinimum" attribute. + Replaced "requires" attribute with "dependencies" attribute. + Moved "contentEncoding" attribute to hyper schema. + Added "additionalItems" attribute. + Added "id" attribute. + Switched self-referencing variable substitution from "-this" to "@" to align with reserved characters in URI template. + Added "patternProperties" attribute. + Schema URIs are now namespace versioned. + Added "$ref" and "$schema" attributes. + + + + + + Replaced "maxDecimal" attribute with "divisibleBy" attribute. + Added slash-delimited fragment resolution protocol and made it the default. + Added language about using links outside of schemas by referencing its normative URI. + Added "uniqueItems" attribute. + Added "targetSchema" attribute to link description object. + + + + + + Fixed category and updates from template. + + + + + + Initial draft. + + + + +
+ +
+ + + Should we give a preference to MIME headers over Link headers (or only use one)? + Should "root" be a MIME parameter? + Should "format" be renamed to "mediaType" or "contentType" to reflect the usage MIME media types that are allowed? + How should dates be handled? + + +
+
+
diff --git a/hm_sunwell/node_modules/json-schema/draft-zyp-json-schema-04.xml b/hm_sunwell/node_modules/json-schema/draft-zyp-json-schema-04.xml new file mode 100644 index 0000000..f9c1ea5 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/draft-zyp-json-schema-04.xml @@ -0,0 +1,1072 @@ + + + + + + + + + + + + + + +]> + + + + + + + + + A JSON Media Type for Describing the Structure and Meaning of JSON Documents + + + SitePen (USA) +
+ + 530 Lytton Avenue + Palo Alto, CA 94301 + USA + + +1 650 968 8787 + kris@sitepen.com +
+
+ + +
+ + + Calgary, AB + Canada + + gary.court@gmail.com +
+
+ + + Internet Engineering Task Force + JSON + Schema + JavaScript + Object + Notation + Hyper Schema + Hypermedia + + + + JSON (JavaScript Object Notation) Schema defines the media type "application/schema+json", + a JSON based format for defining the structure of JSON data. JSON Schema provides a contract for what JSON + data is required for a given application and how to interact with it. JSON + Schema is intended to define validation, documentation, hyperlink + navigation, and interaction control of JSON data. + + +
+ + +
+ + JSON (JavaScript Object Notation) Schema is a JSON media type for defining + the structure of JSON data. JSON Schema provides a contract for what JSON + data is required for a given application and how to interact with it. JSON + Schema is intended to define validation, documentation, hyperlink + navigation, and interaction control of JSON data. + +
+ +
+ + + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", + "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be + interpreted as described in RFC 2119. + + + + The terms "JSON", "JSON text", "JSON value", "member", "element", "object", + "array", "number", "string", "boolean", "true", "false", and "null" in this + document are to be interpreted as defined in RFC 4627. + + + + This specification also uses the following defined terms: + + + A JSON Schema object. + Equivalent to "JSON value" as defined in RFC 4627. + Equivalent to "member" as defined in RFC 4627. + Equivalent to "element" as defined in RFC 4627. + A property of a JSON Schema object. + + +
+ +
+ + JSON Schema defines the media type "application/schema+json" for + describing the structure of JSON text. JSON Schemas are also written in JSON and includes facilities + for describing the structure of JSON in terms of + allowable values, descriptions, and interpreting relations with other resources. + + + This document is organized into several separate definitions. The first + definition is the core schema specification. This definition is primary + concerned with describing a JSON structure and specifying valid elements + in the structure. The second definition is the Hyper Schema specification + which is intended to define elements in a structure that can be interpreted as + hyperlinks. + Hyper Schema builds on JSON Schema to describe the hyperlink structure of + JSON values. This allows user agents to be able to successfully navigate + documents containing JSON based on their schemas. + + + Cumulatively JSON Schema acts as meta-JSON that can be used to define the + required type and constraints on JSON values, as well as define the meaning + of the JSON values for the purpose of describing a resource and determining + hyperlinks within the representation. + +
+ An example JSON Schema that describes products might look like: + + + + + This schema defines the properties of the instance, + the required properties (id, name, and price), as well as an optional + property (tags). This also defines the link relations of the instance. + +
+ +
+ + The JSON Schema media type does not attempt to dictate the structure of JSON + values that contain data, but rather provides a separate format + for flexibly communicating how a JSON value should be + interpreted and validated, such that user agents can properly understand + acceptable structures and extrapolate hyperlink information + from the JSON. It is acknowledged that JSON values come + in a variety of structures, and JSON is unique in that the structure + of stored data structures often prescribes a non-ambiguous definite + JSON representation. Attempting to force a specific structure is generally + not viable, and therefore JSON Schema allows for a great flexibility + in the structure of the JSON data that it describes. + + + This specification is protocol agnostic. + The underlying protocol (such as HTTP) should sufficiently define the + semantics of the client-server interface, the retrieval of resource + representations linked to by JSON representations, and modification of + those resources. The goal of this + format is to sufficiently describe JSON structures such that one can + utilize existing information available in existing JSON + representations from a large variety of services that leverage a representational state transfer + architecture using existing protocols. + +
+
+ +
+ + JSON values are correlated to their schema by the "describedby" + relation, where the schema is the target of the relation. + JSON values MUST be of the "application/json" media type or + any other subtype. Consequently, dictating how a JSON value should + specify the relation to the schema is beyond the normative scope + of this document since this document specifically defines the JSON + Schema media type, and no other. It is RECOMMNENDED that JSON values + specify their schema so that user agents can interpret the instance + and retain the self-descriptive characteristics. This avoides the need for out-of-band information about + instance data. Two approaches are recommended for declaring the + relation to the schema that describes the meaning of a JSON instance's (or collection + of instances) structure. A MIME type parameter named + "profile" or a relation of "describedby" (which could be specified by a Link header) may be used: + +
+ + + +
+ + or if the content is being transferred by a protocol (such as HTTP) that + provides headers, a Link header can be used: + +
+ +; rel="describedby" +]]> + +
+ + Instances MAY specify multiple schemas, to indicate all the schemas that + are applicable to the data, and the data SHOULD be valid by all the schemas. + The instance data MAY have multiple schemas + that it is described by (the instance data SHOULD be valid for those schemas). + Or if the document is a collection of instances, the collection MAY contain + instances from different schemas. The mechanism for referencing a schema is + determined by the media type of the instance (if it provides a method for + referencing schemas). +
+ +
+ + JSON Schemas can themselves be described using JSON Schemas. + A self-describing JSON Schema for the core JSON Schema can + be found at http://json-schema.org/schema for the latest version or + http://json-schema.org/draft-04/schema for the draft-04 version. The hyper schema + self-description can be found at http://json-schema.org/hyper-schema + or http://json-schema.org/draft-04/hyper-schema. All schemas + used within a protocol with a media type specified SHOULD include a MIME parameter that refers to the self-descriptive + hyper schema or another schema that extends this hyper schema: + +
+ + + +
+
+
+
+ +
+ + A JSON Schema is a JSON object that defines various attributes + (including usage and valid values) of a JSON value. JSON + Schema has recursive capabilities; there are a number of elements + in the structure that allow for nested JSON Schemas. + + +
+ An example JSON Schema could look like: + + + +
+ + + A JSON Schema object MAY have any of the following optional properties: + + + + + +
+ + This attribute defines what the primitive type or the schema of the instance MUST be in order to validate. + This attribute can take one of two forms: + + + + A string indicating a primitive or simple type. The string MUST be one of the following values: + + + Instance MUST be an object. + Instance MUST be an array. + Instance MUST be a string. + Instance MUST be a number, including floating point numbers. + Instance MUST be the JSON literal "true" or "false". + Instance MUST be the JSON literal "null". Note that without this type, null values are not allowed. + Instance MAY be of any type, including null. + + + + + An array of one or more simple or schema types. + The instance value is valid if it is of the same type as one of the simple types, or valid by one of the schemas, in the array. + + + + If this attribute is not specified, then all value types are accepted. + + +
+ For example, a schema that defines if an instance can be a string or a number would be: + + +
+
+ +
+ + This attribute is an object with properties that specify the schemas for the properties of the instance object. + In this attribute's object, each property value MUST be a schema. + When the instance value is an object, the value of the instance's properties MUST be valid according to the schemas with the same property names specified in this attribute. + Objects are unordered, so therefore the order of the instance properties or attribute properties MUST NOT determine validation success. + +
+ +
+ + This attribute is an object that defines the schema for a set of property names of an object instance. + The name of each property of this attribute's object is a regular expression pattern in the ECMA 262/Perl 5 format, while the value is a schema. + If the pattern matches the name of a property on the instance object, the value of the instance's property MUST be valid against the pattern name's schema value. + +
+ +
+ This attribute specifies how any instance property that is not explicitly defined by either the "properties" or "patternProperties" attributes (hereafter referred to as "additional properties") is handled. If specified, the value MUST be a schema or a boolean. + If a schema is provided, then all additional properties MUST be valid according to the schema. + If false is provided, then no additional properties are allowed. + The default value is an empty schema, which allows any value for additional properties. +
+ +
+ This attribute provides the allowed items in an array instance. If specified, this attribute MUST be a schema or an array of schemas. + When this attribute value is a schema and the instance value is an array, then all the items in the array MUST be valid according to the schema. + When this attribute value is an array of schemas and the instance value is an array, each position in the instance array MUST be valid according to the schema in the corresponding position for this array. This called tuple typing. When tuple typing is used, additional items are allowed, disallowed, or constrained by the "additionalItems" attribute the same way as "additionalProperties" for objects is. +
+ +
+ This attribute specifies how any item in the array instance that is not explicitly defined by "items" (hereafter referred to as "additional items") is handled. If specified, the value MUST be a schema or a boolean. + If a schema is provided: + + If the "items" attribute is unspecified, then all items in the array instance must be valid against this schema. + If the "items" attribute is a schema, then this attribute is ignored. + If the "items" attribute is an array (during tuple typing), then any additional items MUST be valid against this schema. + + + If false is provided, then any additional items in the array are not allowed. + The default value is an empty schema, which allows any value for additional items. +
+ +
+ This attribute is an array of strings that defines all the property names that must exist on the object instance. +
+ +
+ This attribute is an object that specifies the requirements of a property on an object instance. If an object instance has a property with the same name as a property in this attribute's object, then the instance must be valid against the attribute's property value (hereafter referred to as the "dependency value"). + + The dependency value can take one of two forms: + + + + If the dependency value is a string, then the instance object MUST have a property with the same name as the dependency value. + If the dependency value is an array of strings, then the instance object MUST have a property with the same name as each string in the dependency value's array. + + + If the dependency value is a schema, then the instance object MUST be valid against the schema. + + + +
+ +
+ This attribute defines the minimum value of the instance property when the type of the instance value is a number. +
+ +
+ This attribute defines the maximum value of the instance property when the type of the instance value is a number. +
+ +
+ This attribute indicates if the value of the instance (if the instance is a number) can not equal the number defined by the "minimum" attribute. This is false by default, meaning the instance value can be greater then or equal to the minimum value. +
+ +
+ This attribute indicates if the value of the instance (if the instance is a number) can not equal the number defined by the "maximum" attribute. This is false by default, meaning the instance value can be less then or equal to the maximum value. +
+ +
+ This attribute defines the minimum number of values in an array when the array is the instance value. +
+ +
+ This attribute defines the maximum number of values in an array when the array is the instance value. +
+ +
+ This attribute defines the minimum number of properties required on an object instance. +
+ +
+ This attribute defines the maximum number of properties the object instance can have. +
+ +
+ This attribute indicates that all items in an array instance MUST be unique (contains no two identical values). + + Two instance are consider equal if they are both of the same type and: + + + are null; or + are booleans/numbers/strings and have the same value; or + are arrays, contains the same number of items, and each item in the array is equal to the item at the corresponding index in the other array; or + are objects, contains the same property names, and each property in the object is equal to the corresponding property in the other object. + + +
+ +
+ When the instance value is a string, this provides a regular expression that a string instance MUST match in order to be valid. Regular expressions SHOULD follow the regular expression specification from ECMA 262/Perl 5 +
+ +
+ When the instance value is a string, this defines the minimum length of the string. +
+ +
+ When the instance value is a string, this defines the maximum length of the string. +
+ +
+ This provides an enumeration of all possible values that are valid for the instance property. This MUST be an array, and each item in the array represents a possible value for the instance value. If this attribute is defined, the instance value MUST be one of the values in the array in order for the schema to be valid. Comparison of enum values uses the same algorithm as defined in "uniqueItems". +
+ +
+ This attribute defines the default value of the instance when the instance is undefined. +
+ +
+ This attribute is a string that provides a short description of the instance property. +
+ +
+ This attribute is a string that provides a full description of the of purpose the instance property. +
+ +
+ This attribute defines what value the number instance must be divisible by with no remainder (the result of the division must be an integer.) The value of this attribute SHOULD NOT be 0. +
+ +
+ This attribute takes the same values as the "type" attribute, however if the instance matches the type or if this value is an array and the instance matches any type or schema in the array, then this instance is not valid. +
+ +
+ The value of this property MUST be another schema which will provide a base schema which the current schema will inherit from. The inheritance rules are such that any instance that is valid according to the current schema MUST be valid according to the referenced schema. This MAY also be an array, in which case, the instance MUST be valid for all the schemas in the array. A schema that extends another schema MAY define additional attributes, constrain existing attributes, or add other constraints. + + Conceptually, the behavior of extends can be seen as validating an + instance against all constraints in the extending schema as well as + the extended schema(s). More optimized implementations that merge + schemas are possible, but are not required. Some examples of using "extends": + +
+ + + +
+ +
+ + + +
+
+
+ +
+ + This attribute defines the current URI of this schema (this attribute is + effectively a "self" link). This URI MAY be relative or absolute. If + the URI is relative it is resolved against the current URI of the parent + schema it is contained in. If this schema is not contained in any + parent schema, the current URI of the parent schema is held to be the + URI under which this schema was addressed. If id is missing, the current URI of a schema is + defined to be that of the parent schema. The current URI of the schema + is also used to construct relative references such as for $ref. + +
+ +
+ + This attribute defines a URI of a schema that contains the full representation of this schema. + When a validator encounters this attribute, it SHOULD replace the current schema with the schema referenced by the value's URI (if known and available) and re-validate the instance. + This URI MAY be relative or absolute, and relative URIs SHOULD be resolved against the URI of the current schema. + +
+ +
+ + This attribute defines a URI of a JSON Schema that is the schema of the current schema. + When this attribute is defined, a validator SHOULD use the schema referenced by the value's URI (if known and available) when resolving Hyper Schemalinks. + + + + A validator MAY use this attribute's value to determine which version of JSON Schema the current schema is written in, and provide the appropriate validation features and behavior. + Therefore, it is RECOMMENDED that all schema authors include this attribute in their schemas to prevent conflicts with future JSON Schema specification changes. + +
+
+ +
+ + The following attributes are specified in addition to those + attributes that already provided by the core schema with the specific + purpose of informing user agents of relations between resources based + on JSON data. Just as with JSON + schema attributes, all the attributes in hyper schemas are optional. + Therefore, an empty object is a valid (non-informative) schema, and + essentially describes plain JSON (no constraints on the structures). + Addition of attributes provides additive information for user agents. + + +
+ + The value of the links property MUST be an array, where each item + in the array is a link description object which describes the link + relations of the instances. + + + + +
+ + A link description object is used to describe link relations. In + the context of a schema, it defines the link relations of the + instances of the schema, and can be parameterized by the instance + values. The link description format can be used without JSON Schema, + and use of this format can + be declared by referencing the normative link description + schema as the the schema for the data structure that uses the + links. The URI of the normative link description schema is: + http://json-schema.org/links (latest version) or + http://json-schema.org/draft-04/links (draft-04 version). + + +
+ + The value of the "href" link description property + indicates the target URI of the related resource. The value + of the instance property SHOULD be resolved as a URI-Reference per RFC 3986 + and MAY be a relative URI. The base URI to be used for relative resolution + SHOULD be the URI used to retrieve the instance object (not the schema) + when used within a schema. Also, when links are used within a schema, the URI + SHOULD be parametrized by the property values of the instance + object, if property values exist for the corresponding variables + in the template (otherwise they MAY be provided from alternate sources, like user input). + + + + Instance property values SHOULD be substituted into the URIs where + matching braces ('{', '}') are found surrounding zero or more characters, + creating an expanded URI. Instance property value substitutions are resolved + by using the text between the braces to denote the property name + from the instance to get the value to substitute. + +
+ For example, if an href value is defined: + + + + Then it would be resolved by replace the value of the "id" property value from the instance object. +
+ +
+ If the value of the "id" property was "45", the expanded URI would be: + + + +
+ + If matching braces are found with the string "@" (no quotes) between the braces, then the + actual instance value SHOULD be used to replace the braces, rather than a property value. + This should only be used in situations where the instance is a scalar (string, + boolean, or number), and not for objects or arrays. +
+
+ +
+ + The value of the "rel" property indicates the name of the + relation to the target resource. The relation to the target SHOULD be interpreted as specifically from the instance object that the schema (or sub-schema) applies to, not just the top level resource that contains the object within its hierarchy. If a resource JSON representation contains a sub object with a property interpreted as a link, that sub-object holds the relation with the target. A relation to target from the top level resource MUST be indicated with the schema describing the top level JSON representation. + + + + Relationship definitions SHOULD NOT be media type dependent, and users are encouraged to utilize existing accepted relation definitions, including those in existing relation registries (see RFC 4287). However, we define these relations here for clarity of normative interpretation within the context of JSON hyper schema defined relations: + + + + If the relation value is "self", when this property is encountered in + the instance object, the object represents a resource and the instance object is + treated as a full representation of the target resource identified by + the specified URI. + + + + This indicates that the target of the link is the full representation for the instance object. The object that contains this link possibly may not be the full representation. + + + + This indicates the target of the link is the schema for the instance object. This MAY be used to specifically denote the schemas of objects within a JSON object hierarchy, facilitating polymorphic type data structures. + + + + This relation indicates that the target of the link + SHOULD be treated as the root or the body of the representation for the + purposes of user agent interaction or fragment resolution. All other + properties of the instance objects can be regarded as meta-data + descriptions for the data. + + + + + + The following relations are applicable for schemas (the schema as the "from" resource in the relation): + + + This indicates the target resource that represents collection of instances of a schema. + This indicates a target to use for creating new instances of a schema. This link definition SHOULD be a submission link with a non-safe method (like POST). + + + + +
+ For example, if a schema is defined: + + + +
+ +
+ And if a collection of instance resource's JSON representation was retrieved: + + + +
+ + This would indicate that for the first item in the collection, its own + (self) URI would resolve to "/Resource/thing" and the first item's "up" + relation SHOULD be resolved to the resource at "/Resource/parent". + The "children" collection would be located at "/Resource/?upId=thing". +
+
+ +
+ This property value is a string that defines the templating language used in the "href" attribute. If no templating language is defined, then the default Link Description Object templating langauge is used. +
+ +
+ This property value is a schema that defines the expected structure of the JSON representation of the target of the link. +
+ +
+ + The following properties also apply to link definition objects, and + provide functionality analogous to HTML forms, in providing a + means for submitting extra (often user supplied) information to send to a server. + + +
+ + This attribute defines which method can be used to access the target resource. + In an HTTP environment, this would be "GET" or "POST" (other HTTP methods + such as "PUT" and "DELETE" have semantics that are clearly implied by + accessed resources, and do not need to be defined here). + This defaults to "GET". + +
+ +
+ + If present, this property indicates a query media type format that the server + supports for querying or posting to the collection of instances at the target + resource. The query can be + suffixed to the target URI to query the collection with + property-based constraints on the resources that SHOULD be returned from + the server or used to post data to the resource (depending on the method). + +
+ For example, with the following schema: + + + + This indicates that the client can query the server for instances that have a specific name. +
+ +
+ For example: + + + +
+ + If no enctype or method is specified, only the single URI specified by + the href property is defined. If the method is POST, "application/json" is + the default media type. +
+
+ +
+ + This attribute contains a schema which defines the acceptable structure of the submitted + request (for a GET request, this schema would define the properties for the query string + and for a POST request, this would define the body). + +
+
+
+
+ +
+ + This property indicates the fragment resolution protocol to use for + resolving fragment identifiers in URIs within the instance + representations. This applies to the instance object URIs and all + children of the instance object's URIs. The default fragment resolution + protocol is "json-pointer", which is defined below. Other fragment + resolution protocols MAY be used, but are not defined in this document. + + + + The fragment identifier is based on RFC 3986, Sec 5, and defines the + mechanism for resolving references to entities within a document. + + +
+ The "json-pointer" fragment resolution protocol uses a JSON Pointer to resolve fragment identifiers in URIs within instance representations. +
+
+ + + +
+ This attribute indicates that the instance value SHOULD NOT be changed. Attempts by a user agent to modify the value of this property are expected to be rejected by a server. +
+ +
+ If the instance property value is a string, this attribute defines that the string SHOULD be interpreted as binary data and decoded using the encoding named by this schema property. RFC 2045, Sec 6.1 lists the possible values for this property. +
+ +
+ + This attribute is a URI that defines what the instance's URI MUST start with in order to validate. + The value of the "pathStart" attribute MUST be resolved as per RFC 3986, Sec 5, + and is relative to the instance's URI. + + + + When multiple schemas have been referenced for an instance, the user agent + can determine if this schema is applicable for a particular instance by + determining if the URI of the instance begins with the the value of the "pathStart" + attribute. If the URI of the instance does not start with this URI, + or if another schema specifies a starting URI that is longer and also matches the + instance, this schema SHOULD NOT be applied to the instance. Any schema + that does not have a pathStart attribute SHOULD be considered applicable + to all the instances for which it is referenced. + +
+ +
+ This attribute defines the media type of the instance representations that this schema is defining. +
+
+ +
+ + This specification is a sub-type of the JSON format, and + consequently the security considerations are generally the same as RFC 4627. + However, an additional issue is that when link relation of "self" + is used to denote a full representation of an object, the user agent + SHOULD NOT consider the representation to be the authoritative representation + of the resource denoted by the target URI if the target URI is not + equivalent to or a sub-path of the the URI used to request the resource + representation which contains the target URI with the "self" link. + +
+ For example, if a hyper schema was defined: + + + +
+ +
+ And a resource was requested from somesite.com: + + + +
+ +
+ With a response of: + + + +
+
+
+ +
+ The proposed MIME media type for JSON Schema is "application/schema+json". + Type name: application + Subtype name: schema+json + Required parameters: profile + + The value of the profile parameter SHOULD be a URI (relative or absolute) that + refers to the schema used to define the structure of this structure (the + meta-schema). Normally the value would be http://json-schema.org/draft-04/hyper-schema, + but it is allowable to use other schemas that extend the hyper schema's meta- + schema. + + Optional parameters: pretty + The value of the pretty parameter MAY be true or false to indicate if additional whitespace has been included to make the JSON representation easier to read. + +
+ + This registry is maintained by IANA per RFC 4287 and this specification adds + four values: "full", "create", "instances", "root". New + assignments are subject to IESG Approval, as outlined in RFC 5226. + Requests should be made by email to IANA, which will then forward the + request to the IESG, requesting approval. + +
+
+
+ + + + + &rfc2045; + &rfc2119; + &rfc3339; + &rfc3986; + &rfc4287; + + + JSON Pointer + + ForgeRock US, Inc. + + + SitePen (USA) + + + + + + + &rfc2616; + &rfc4627; + &rfc5226; + &iddiscovery; + &uritemplate; + &linkheader; + &html401; + &css21; + + +
+ + + + + Changed "required" attribute to an array of strings. + Removed "format" attribute. + Added "minProperties" and "maxProperties" attributes. + Replaced "slash-delimited" fragment resolution with "json-pointer". + Added "template" LDO attribute. + Removed irrelevant "Open Issues" section. + Merged Conventions and Terminology sections. + Defined terms used in specification. + Removed "integer" type in favor of {"type":"number", "divisibleBy":1}. + Restricted "type" to only the core JSON types. + Improved wording of many sections. + + + + + + Added example and verbiage to "extends" attribute. + Defined slash-delimited to use a leading slash. + Made "root" a relation instead of an attribute. + Removed address values, and MIME media type from format to reduce confusion (mediaType already exists, so it can be used for MIME types). + Added more explanation of nullability. + Removed "alternate" attribute. + Upper cased many normative usages of must, may, and should. + Replaced the link submission "properties" attribute to "schema" attribute. + Replaced "optional" attribute with "required" attribute. + Replaced "maximumCanEqual" attribute with "exclusiveMaximum" attribute. + Replaced "minimumCanEqual" attribute with "exclusiveMinimum" attribute. + Replaced "requires" attribute with "dependencies" attribute. + Moved "contentEncoding" attribute to hyper schema. + Added "additionalItems" attribute. + Added "id" attribute. + Switched self-referencing variable substitution from "-this" to "@" to align with reserved characters in URI template. + Added "patternProperties" attribute. + Schema URIs are now namespace versioned. + Added "$ref" and "$schema" attributes. + + + + + + Replaced "maxDecimal" attribute with "divisibleBy" attribute. + Added slash-delimited fragment resolution protocol and made it the default. + Added language about using links outside of schemas by referencing its normative URI. + Added "uniqueItems" attribute. + Added "targetSchema" attribute to link description object. + + + + + + Fixed category and updates from template. + + + + + + Initial draft. + + + + +
+
+
diff --git a/hm_sunwell/node_modules/json-schema/lib/links.js b/hm_sunwell/node_modules/json-schema/lib/links.js new file mode 100644 index 0000000..2f450ff --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/lib/links.js @@ -0,0 +1,66 @@ +/** + * JSON Schema link handler + * Copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com) + * Licensed under the MIT (MIT-LICENSE.txt) license. + */ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], function () { + return factory(); + }); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals + root.jsonSchemaLinks = factory(); + } +}(this, function () {// setup primitive classes to be JSON Schema types +var exports = {}; +exports.cacheLinks = true; +exports.getLink = function(relation, instance, schema){ + // gets the URI of the link for the given relation based on the instance and schema + // for example: + // getLink( + // "brother", + // {"brother_id":33}, + // {links:[{rel:"brother", href:"Brother/{brother_id}"}]}) -> + // "Brother/33" + var links = schema.__linkTemplates; + if(!links){ + links = {}; + var schemaLinks = schema.links; + if(schemaLinks && schemaLinks instanceof Array){ + schemaLinks.forEach(function(link){ + /* // TODO: allow for multiple same-name relations + if(links[link.rel]){ + if(!(links[link.rel] instanceof Array)){ + links[link.rel] = [links[link.rel]]; + } + }*/ + links[link.rel] = link.href; + }); + } + if(exports.cacheLinks){ + schema.__linkTemplates = links; + } + } + var linkTemplate = links[relation]; + return linkTemplate && exports.substitute(linkTemplate, instance); +}; + +exports.substitute = function(linkTemplate, instance){ + return linkTemplate.replace(/\{([^\}]*)\}/g, function(t, property){ + var value = instance[decodeURIComponent(property)]; + if(value instanceof Array){ + // the value is an array, it should produce a URI like /Table/(4,5,8) and store.get() should handle that as an array of values + return '(' + value.join(',') + ')'; + } + return value; + }); +}; +return exports; +})); \ No newline at end of file diff --git a/hm_sunwell/node_modules/json-schema/lib/validate.js b/hm_sunwell/node_modules/json-schema/lib/validate.js new file mode 100644 index 0000000..4d0b537 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/lib/validate.js @@ -0,0 +1,273 @@ +/** + * JSONSchema Validator - Validates JavaScript objects using JSON Schemas + * (http://www.json.com/json-schema-proposal/) + * + * Copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com) + * Licensed under the MIT (MIT-LICENSE.txt) license. +To use the validator call the validate function with an instance object and an optional schema object. +If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating), +that schema will be used to validate and the schema parameter is not necessary (if both exist, +both validations will occur). +The validate method will return an array of validation errors. If there are no errors, then an +empty list will be returned. A validation error will have two properties: +"property" which indicates which property had the error +"message" which indicates what the error was + */ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], function () { + return factory(); + }); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals + root.jsonSchema = factory(); + } +}(this, function () {// setup primitive classes to be JSON Schema types +var exports = validate +exports.Integer = {type:"integer"}; +var primitiveConstructors = { + String: String, + Boolean: Boolean, + Number: Number, + Object: Object, + Array: Array, + Date: Date +} +exports.validate = validate; +function validate(/*Any*/instance,/*Object*/schema) { + // Summary: + // To use the validator call JSONSchema.validate with an instance object and an optional schema object. + // If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating), + // that schema will be used to validate and the schema parameter is not necessary (if both exist, + // both validations will occur). + // The validate method will return an object with two properties: + // valid: A boolean indicating if the instance is valid by the schema + // errors: An array of validation errors. If there are no errors, then an + // empty list will be returned. A validation error will have two properties: + // property: which indicates which property had the error + // message: which indicates what the error was + // + return validate(instance, schema, {changing: false});//, coerce: false, existingOnly: false}); + }; +exports.checkPropertyChange = function(/*Any*/value,/*Object*/schema, /*String*/property) { + // Summary: + // The checkPropertyChange method will check to see if an value can legally be in property with the given schema + // This is slightly different than the validate method in that it will fail if the schema is readonly and it will + // not check for self-validation, it is assumed that the passed in value is already internally valid. + // The checkPropertyChange method will return the same object type as validate, see JSONSchema.validate for + // information. + // + return validate(value, schema, {changing: property || "property"}); + }; +var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*Object*/options) { + + if (!options) options = {}; + var _changing = options.changing; + + function getType(schema){ + return schema.type || (primitiveConstructors[schema.name] == schema && schema.name.toLowerCase()); + } + var errors = []; + // validate a value against a property definition + function checkProp(value, schema, path,i){ + + var l; + path += path ? typeof i == 'number' ? '[' + i + ']' : typeof i == 'undefined' ? '' : '.' + i : i; + function addError(message){ + errors.push({property:path,message:message}); + } + + if((typeof schema != 'object' || schema instanceof Array) && (path || typeof schema != 'function') && !(schema && getType(schema))){ + if(typeof schema == 'function'){ + if(!(value instanceof schema)){ + addError("is not an instance of the class/constructor " + schema.name); + } + }else if(schema){ + addError("Invalid schema/property definition " + schema); + } + return null; + } + if(_changing && schema.readonly){ + addError("is a readonly field, it can not be changed"); + } + if(schema['extends']){ // if it extends another schema, it must pass that schema as well + checkProp(value,schema['extends'],path,i); + } + // validate a value against a type definition + function checkType(type,value){ + if(type){ + if(typeof type == 'string' && type != 'any' && + (type == 'null' ? value !== null : typeof value != type) && + !(value instanceof Array && type == 'array') && + !(value instanceof Date && type == 'date') && + !(type == 'integer' && value%1===0)){ + return [{property:path,message:(typeof value) + " value found, but a " + type + " is required"}]; + } + if(type instanceof Array){ + var unionErrors=[]; + for(var j = 0; j < type.length; j++){ // a union type + if(!(unionErrors=checkType(type[j],value)).length){ + break; + } + } + if(unionErrors.length){ + return unionErrors; + } + }else if(typeof type == 'object'){ + var priorErrors = errors; + errors = []; + checkProp(value,type,path); + var theseErrors = errors; + errors = priorErrors; + return theseErrors; + } + } + return []; + } + if(value === undefined){ + if(schema.required){ + addError("is missing and it is required"); + } + }else{ + errors = errors.concat(checkType(getType(schema),value)); + if(schema.disallow && !checkType(schema.disallow,value).length){ + addError(" disallowed value was matched"); + } + if(value !== null){ + if(value instanceof Array){ + if(schema.items){ + var itemsIsArray = schema.items instanceof Array; + var propDef = schema.items; + for (i = 0, l = value.length; i < l; i += 1) { + if (itemsIsArray) + propDef = schema.items[i]; + if (options.coerce) + value[i] = options.coerce(value[i], propDef); + errors.concat(checkProp(value[i],propDef,path,i)); + } + } + if(schema.minItems && value.length < schema.minItems){ + addError("There must be a minimum of " + schema.minItems + " in the array"); + } + if(schema.maxItems && value.length > schema.maxItems){ + addError("There must be a maximum of " + schema.maxItems + " in the array"); + } + }else if(schema.properties || schema.additionalProperties){ + errors.concat(checkObj(value, schema.properties, path, schema.additionalProperties)); + } + if(schema.pattern && typeof value == 'string' && !value.match(schema.pattern)){ + addError("does not match the regex pattern " + schema.pattern); + } + if(schema.maxLength && typeof value == 'string' && value.length > schema.maxLength){ + addError("may only be " + schema.maxLength + " characters long"); + } + if(schema.minLength && typeof value == 'string' && value.length < schema.minLength){ + addError("must be at least " + schema.minLength + " characters long"); + } + if(typeof schema.minimum !== undefined && typeof value == typeof schema.minimum && + schema.minimum > value){ + addError("must have a minimum value of " + schema.minimum); + } + if(typeof schema.maximum !== undefined && typeof value == typeof schema.maximum && + schema.maximum < value){ + addError("must have a maximum value of " + schema.maximum); + } + if(schema['enum']){ + var enumer = schema['enum']; + l = enumer.length; + var found; + for(var j = 0; j < l; j++){ + if(enumer[j]===value){ + found=1; + break; + } + } + if(!found){ + addError("does not have a value in the enumeration " + enumer.join(", ")); + } + } + if(typeof schema.maxDecimal == 'number' && + (value.toString().match(new RegExp("\\.[0-9]{" + (schema.maxDecimal + 1) + ",}")))){ + addError("may only have " + schema.maxDecimal + " digits of decimal places"); + } + } + } + return null; + } + // validate an object against a schema + function checkObj(instance,objTypeDef,path,additionalProp){ + + if(typeof objTypeDef =='object'){ + if(typeof instance != 'object' || instance instanceof Array){ + errors.push({property:path,message:"an object is required"}); + } + + for(var i in objTypeDef){ + if(objTypeDef.hasOwnProperty(i)){ + var value = instance[i]; + // skip _not_ specified properties + if (value === undefined && options.existingOnly) continue; + var propDef = objTypeDef[i]; + // set default + if(value === undefined && propDef["default"]){ + value = instance[i] = propDef["default"]; + } + if(options.coerce && i in instance){ + value = instance[i] = options.coerce(value, propDef); + } + checkProp(value,propDef,path,i); + } + } + } + for(i in instance){ + if(instance.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && objTypeDef && !objTypeDef[i] && additionalProp===false){ + if (options.filter) { + delete instance[i]; + continue; + } else { + errors.push({property:path,message:(typeof value) + "The property " + i + + " is not defined in the schema and the schema does not allow additional properties"}); + } + } + var requires = objTypeDef && objTypeDef[i] && objTypeDef[i].requires; + if(requires && !(requires in instance)){ + errors.push({property:path,message:"the presence of the property " + i + " requires that " + requires + " also be present"}); + } + value = instance[i]; + if(additionalProp && (!(objTypeDef && typeof objTypeDef == 'object') || !(i in objTypeDef))){ + if(options.coerce){ + value = instance[i] = options.coerce(value, additionalProp); + } + checkProp(value,additionalProp,path,i); + } + if(!_changing && value && value.$schema){ + errors = errors.concat(checkProp(value,value.$schema,path,i)); + } + } + return errors; + } + if(schema){ + checkProp(instance,schema,'',_changing || ''); + } + if(!_changing && instance && instance.$schema){ + checkProp(instance,instance.$schema,'',''); + } + return {valid:!errors.length,errors:errors}; +}; +exports.mustBeValid = function(result){ + // summary: + // This checks to ensure that the result is valid and will throw an appropriate error message if it is not + // result: the result returned from checkPropertyChange or validate + if(!result.valid){ + throw new TypeError(result.errors.map(function(error){return "for property " + error.property + ': ' + error.message;}).join(", \n")); + } +} + +return exports; +})); diff --git a/hm_sunwell/node_modules/json-schema/package.json b/hm_sunwell/node_modules/json-schema/package.json new file mode 100644 index 0000000..0b50bc3 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/package.json @@ -0,0 +1,92 @@ +{ + "_args": [ + [ + "json-schema@0.2.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/jsprim" + ] + ], + "_from": "json-schema@0.2.3", + "_id": "json-schema@0.2.3", + "_inCache": true, + "_installable": true, + "_location": "/json-schema", + "_nodeVersion": "6.1.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/json-schema-0.2.3.tgz_1473699189380_0.7420965158380568" + }, + "_npmUser": { + "email": "kriszyp@gmail.com", + "name": "kriszyp" + }, + "_npmVersion": "3.8.9", + "_phantomChildren": {}, + "_requested": { + "name": "json-schema", + "raw": "json-schema@0.2.3", + "rawSpec": "0.2.3", + "scope": null, + "spec": "0.2.3", + "type": "version" + }, + "_requiredBy": [ + "/jsprim" + ], + "_resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "_shasum": "b480c892e59a2f05954ce727bd3f2a4e882f9e13", + "_shrinkwrap": null, + "_spec": "json-schema@0.2.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/jsprim", + "author": { + "name": "Kris Zyp" + }, + "bugs": { + "url": "https://github.com/kriszyp/json-schema/issues" + }, + "dependencies": {}, + "description": "JSON Schema validation and specifications", + "devDependencies": { + "vows": "*" + }, + "directories": { + "lib": "./lib" + }, + "dist": { + "shasum": "b480c892e59a2f05954ce727bd3f2a4e882f9e13", + "tarball": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" + }, + "gitHead": "07ae2c618b5f581dbc108e065f4f95dcf0a1d85f", + "homepage": "https://github.com/kriszyp/json-schema#readme", + "keywords": [ + "json", + "schema" + ], + "licenses": [ + { + "type": "AFLv2.1", + "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L43" + }, + { + "type": "BSD", + "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L13" + } + ], + "main": "./lib/validate.js", + "maintainers": [ + { + "name": "kriszyp", + "email": "kriszyp@gmail.com" + } + ], + "name": "json-schema", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/kriszyp/json-schema.git" + }, + "scripts": { + "test": "echo TESTS DISABLED vows --spec test/*.js" + }, + "version": "0.2.3" +} diff --git a/hm_sunwell/node_modules/json-schema/test/tests.js b/hm_sunwell/node_modules/json-schema/test/tests.js new file mode 100644 index 0000000..40eeda5 --- /dev/null +++ b/hm_sunwell/node_modules/json-schema/test/tests.js @@ -0,0 +1,95 @@ +var assert = require('assert'); +var vows = require('vows'); +var path = require('path'); +var fs = require('fs'); + +var validate = require('../lib/validate').validate; + + +var revision = 'draft-03'; +var schemaRoot = path.join(__dirname, '..', revision); +var schemaNames = ['schema', 'hyper-schema', 'links', 'json-ref' ]; +var schemas = {}; + +schemaNames.forEach(function(name) { + var file = path.join(schemaRoot, name); + schemas[name] = loadSchema(file); +}); + +schemaNames.forEach(function(name) { + var s, n = name+'-nsd', f = path.join(schemaRoot, name); + schemas[n] = loadSchema(f); + s = schemas[n]; + delete s['$schema']; +}); + +function loadSchema(path) { + var data = fs.readFileSync(path, 'utf-8'); + var schema = JSON.parse(data); + return schema; +} + +function resultIsValid() { + return function(result) { + assert.isObject(result); + //assert.isBoolean(result.valid); + assert.equal(typeof(result.valid), 'boolean'); + assert.isArray(result.errors); + for (var i = 0; i < result.errors.length; i++) { + assert.notEqual(result.errors[i], null, 'errors['+i+'] is null'); + } + } +} + +function assertValidates(doc, schema) { + var context = {}; + + context[': validate('+doc+', '+schema+')'] = { + topic: validate(schemas[doc], schemas[schema]), + 'returns valid result': resultIsValid(), + 'with valid=true': function(result) { assert.equal(result.valid, true); }, + 'and no errors': function(result) { + // XXX work-around for bug in vows: [null] chokes it + if (result.errors[0] == null) assert.fail('(errors contains null)'); + assert.length(result.errors, 0); + } + }; + + return context; +} + +function assertSelfValidates(doc) { + var context = {}; + + context[': validate('+doc+')'] = { + topic: validate(schemas[doc]), + 'returns valid result': resultIsValid(), + 'with valid=true': function(result) { assert.equal(result.valid, true); }, + 'and no errors': function(result) { assert.length(result.errors, 0); } + }; + + return context; +} + +var suite = vows.describe('JSON Schema').addBatch({ + 'Core-NSD self-validates': assertSelfValidates('schema-nsd'), + 'Core-NSD/Core-NSD': assertValidates('schema-nsd', 'schema-nsd'), + 'Core-NSD/Core': assertValidates('schema-nsd', 'schema'), + + 'Core self-validates': assertSelfValidates('schema'), + 'Core/Core': assertValidates('schema', 'schema'), + + 'Hyper-NSD self-validates': assertSelfValidates('hyper-schema-nsd'), + 'Hyper self-validates': assertSelfValidates('hyper-schema'), + 'Hyper/Hyper': assertValidates('hyper-schema', 'hyper-schema'), + 'Hyper/Core': assertValidates('hyper-schema', 'schema'), + + 'Links-NSD self-validates': assertSelfValidates('links-nsd'), + 'Links self-validates': assertSelfValidates('links'), + 'Links/Hyper': assertValidates('links', 'hyper-schema'), + 'Links/Core': assertValidates('links', 'schema'), + + 'Json-Ref self-validates': assertSelfValidates('json-ref'), + 'Json-Ref/Hyper': assertValidates('json-ref', 'hyper-schema'), + 'Json-Ref/Core': assertValidates('json-ref', 'schema') +}).export(module); diff --git a/hm_sunwell/node_modules/json-stringify-safe/.npmignore b/hm_sunwell/node_modules/json-stringify-safe/.npmignore new file mode 100644 index 0000000..17d6b36 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/.npmignore @@ -0,0 +1 @@ +/*.tgz diff --git a/hm_sunwell/node_modules/json-stringify-safe/CHANGELOG.md b/hm_sunwell/node_modules/json-stringify-safe/CHANGELOG.md new file mode 100644 index 0000000..42bcb60 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/CHANGELOG.md @@ -0,0 +1,14 @@ +## Unreleased +- Fixes stringify to only take ancestors into account when checking + circularity. + It previously assumed every visited object was circular which led to [false + positives][issue9]. + Uses the tiny serializer I wrote for [Must.js][must] a year and a half ago. +- Fixes calling the `replacer` function in the proper context (`thisArg`). +- Fixes calling the `cycleReplacer` function in the proper context (`thisArg`). +- Speeds serializing by a factor of + Big-O(h-my-god-it-linearly-searched-every-object) it had ever seen. Searching + only the ancestors for a circular references speeds up things considerably. + +[must]: https://github.com/moll/js-must +[issue9]: https://github.com/isaacs/json-stringify-safe/issues/9 diff --git a/hm_sunwell/node_modules/json-stringify-safe/LICENSE b/hm_sunwell/node_modules/json-stringify-safe/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/hm_sunwell/node_modules/json-stringify-safe/Makefile b/hm_sunwell/node_modules/json-stringify-safe/Makefile new file mode 100644 index 0000000..36088c7 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/Makefile @@ -0,0 +1,35 @@ +NODE_OPTS = +TEST_OPTS = + +love: + @echo "Feel like makin' love." + +test: + @node $(NODE_OPTS) ./node_modules/.bin/_mocha -R dot $(TEST_OPTS) + +spec: + @node $(NODE_OPTS) ./node_modules/.bin/_mocha -R spec $(TEST_OPTS) + +autotest: + @node $(NODE_OPTS) ./node_modules/.bin/_mocha -R dot --watch $(TEST_OPTS) + +autospec: + @node $(NODE_OPTS) ./node_modules/.bin/_mocha -R spec --watch $(TEST_OPTS) + +pack: + @file=$$(npm pack); echo "$$file"; tar tf "$$file" + +publish: + npm publish + +tag: + git tag "v$$(node -e 'console.log(require("./package").version)')" + +clean: + rm -f *.tgz + npm prune --production + +.PHONY: love +.PHONY: test spec autotest autospec +.PHONY: pack publish tag +.PHONY: clean diff --git a/hm_sunwell/node_modules/json-stringify-safe/README.md b/hm_sunwell/node_modules/json-stringify-safe/README.md new file mode 100644 index 0000000..a11f302 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/README.md @@ -0,0 +1,52 @@ +# json-stringify-safe + +Like JSON.stringify, but doesn't throw on circular references. + +## Usage + +Takes the same arguments as `JSON.stringify`. + +```javascript +var stringify = require('json-stringify-safe'); +var circularObj = {}; +circularObj.circularRef = circularObj; +circularObj.list = [ circularObj, circularObj ]; +console.log(stringify(circularObj, null, 2)); +``` + +Output: + +```json +{ + "circularRef": "[Circular]", + "list": [ + "[Circular]", + "[Circular]" + ] +} +``` + +## Details + +``` +stringify(obj, serializer, indent, decycler) +``` + +The first three arguments are the same as to JSON.stringify. The last +is an argument that's only used when the object has been seen already. + +The default `decycler` function returns the string `'[Circular]'`. +If, for example, you pass in `function(k,v){}` (return nothing) then it +will prune cycles. If you pass in `function(k,v){ return {foo: 'bar'}}`, +then cyclical objects will always be represented as `{"foo":"bar"}` in +the result. + +``` +stringify.getSerialize(serializer, decycler) +``` + +Returns a serializer that can be used elsewhere. This is the actual +function that's passed to JSON.stringify. + +**Note** that the function returned from `getSerialize` is stateful for now, so +do **not** use it more than once. diff --git a/hm_sunwell/node_modules/json-stringify-safe/package.json b/hm_sunwell/node_modules/json-stringify-safe/package.json new file mode 100644 index 0000000..44d0a4b --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/package.json @@ -0,0 +1,94 @@ +{ + "_args": [ + [ + "json-stringify-safe@~5.0.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/request" + ] + ], + "_from": "json-stringify-safe@>=5.0.1 <5.1.0", + "_id": "json-stringify-safe@5.0.1", + "_inCache": true, + "_installable": true, + "_location": "/json-stringify-safe", + "_nodeVersion": "2.0.1", + "_npmUser": { + "email": "isaacs@npmjs.com", + "name": "isaacs" + }, + "_npmVersion": "2.10.0", + "_phantomChildren": {}, + "_requested": { + "name": "json-stringify-safe", + "raw": "json-stringify-safe@~5.0.1", + "rawSpec": "~5.0.1", + "scope": null, + "spec": ">=5.0.1 <5.1.0", + "type": "range" + }, + "_requiredBy": [ + "/request" + ], + "_resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "_shasum": "1296a2d58fd45f19a0f6ce01d65701e2c735b6eb", + "_shrinkwrap": null, + "_spec": "json-stringify-safe@~5.0.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/request", + "author": { + "email": "i@izs.me", + "name": "Isaac Z. Schlueter", + "url": "http://blog.izs.me" + }, + "bugs": { + "url": "https://github.com/isaacs/json-stringify-safe/issues" + }, + "contributors": [ + { + "name": "Andri Möll", + "email": "andri@dot.ee", + "url": "http://themoll.com" + } + ], + "dependencies": {}, + "description": "Like JSON.stringify, but doesn't blow up on circular refs.", + "devDependencies": { + "mocha": ">= 2.1.0 < 3", + "must": ">= 0.12 < 0.13", + "sinon": ">= 1.12.2 < 2" + }, + "directories": {}, + "dist": { + "shasum": "1296a2d58fd45f19a0f6ce01d65701e2c735b6eb", + "tarball": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + }, + "gitHead": "3890dceab3ad14f8701e38ca74f38276abc76de5", + "homepage": "https://github.com/isaacs/json-stringify-safe", + "keywords": [ + "circular", + "json", + "safe", + "stringify" + ], + "license": "ISC", + "main": "stringify.js", + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + }, + { + "name": "moll", + "email": "andri@dot.ee" + } + ], + "name": "json-stringify-safe", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/json-stringify-safe.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "5.0.1" +} diff --git a/hm_sunwell/node_modules/json-stringify-safe/stringify.js b/hm_sunwell/node_modules/json-stringify-safe/stringify.js new file mode 100644 index 0000000..124a452 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/stringify.js @@ -0,0 +1,27 @@ +exports = module.exports = stringify +exports.getSerialize = serializer + +function stringify(obj, replacer, spaces, cycleReplacer) { + return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces) +} + +function serializer(replacer, cycleReplacer) { + var stack = [], keys = [] + + if (cycleReplacer == null) cycleReplacer = function(key, value) { + if (stack[0] === value) return "[Circular ~]" + return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]" + } + + return function(key, value) { + if (stack.length > 0) { + var thisPos = stack.indexOf(this) + ~thisPos ? stack.splice(thisPos + 1) : stack.push(this) + ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key) + if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value) + } + else stack.push(value) + + return replacer == null ? value : replacer.call(this, key, value) + } +} diff --git a/hm_sunwell/node_modules/json-stringify-safe/test/mocha.opts b/hm_sunwell/node_modules/json-stringify-safe/test/mocha.opts new file mode 100644 index 0000000..2544e58 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/test/mocha.opts @@ -0,0 +1,2 @@ +--recursive +--require must diff --git a/hm_sunwell/node_modules/json-stringify-safe/test/stringify_test.js b/hm_sunwell/node_modules/json-stringify-safe/test/stringify_test.js new file mode 100644 index 0000000..5b32583 --- /dev/null +++ b/hm_sunwell/node_modules/json-stringify-safe/test/stringify_test.js @@ -0,0 +1,246 @@ +var Sinon = require("sinon") +var stringify = require("..") +function jsonify(obj) { return JSON.stringify(obj, null, 2) } + +describe("Stringify", function() { + it("must stringify circular objects", function() { + var obj = {name: "Alice"} + obj.self = obj + var json = stringify(obj, null, 2) + json.must.eql(jsonify({name: "Alice", self: "[Circular ~]"})) + }) + + it("must stringify circular objects with intermediaries", function() { + var obj = {name: "Alice"} + obj.identity = {self: obj} + var json = stringify(obj, null, 2) + json.must.eql(jsonify({name: "Alice", identity: {self: "[Circular ~]"}})) + }) + + it("must stringify circular objects deeper", function() { + var obj = {name: "Alice", child: {name: "Bob"}} + obj.child.self = obj.child + + stringify(obj, null, 2).must.eql(jsonify({ + name: "Alice", + child: {name: "Bob", self: "[Circular ~.child]"} + })) + }) + + it("must stringify circular objects deeper with intermediaries", function() { + var obj = {name: "Alice", child: {name: "Bob"}} + obj.child.identity = {self: obj.child} + + stringify(obj, null, 2).must.eql(jsonify({ + name: "Alice", + child: {name: "Bob", identity: {self: "[Circular ~.child]"}} + })) + }) + + it("must stringify circular objects in an array", function() { + var obj = {name: "Alice"} + obj.self = [obj, obj] + + stringify(obj, null, 2).must.eql(jsonify({ + name: "Alice", self: ["[Circular ~]", "[Circular ~]"] + })) + }) + + it("must stringify circular objects deeper in an array", function() { + var obj = {name: "Alice", children: [{name: "Bob"}, {name: "Eve"}]} + obj.children[0].self = obj.children[0] + obj.children[1].self = obj.children[1] + + stringify(obj, null, 2).must.eql(jsonify({ + name: "Alice", + children: [ + {name: "Bob", self: "[Circular ~.children.0]"}, + {name: "Eve", self: "[Circular ~.children.1]"} + ] + })) + }) + + it("must stringify circular arrays", function() { + var obj = [] + obj.push(obj) + obj.push(obj) + var json = stringify(obj, null, 2) + json.must.eql(jsonify(["[Circular ~]", "[Circular ~]"])) + }) + + it("must stringify circular arrays with intermediaries", function() { + var obj = [] + obj.push({name: "Alice", self: obj}) + obj.push({name: "Bob", self: obj}) + + stringify(obj, null, 2).must.eql(jsonify([ + {name: "Alice", self: "[Circular ~]"}, + {name: "Bob", self: "[Circular ~]"} + ])) + }) + + it("must stringify repeated objects in objects", function() { + var obj = {} + var alice = {name: "Alice"} + obj.alice1 = alice + obj.alice2 = alice + + stringify(obj, null, 2).must.eql(jsonify({ + alice1: {name: "Alice"}, + alice2: {name: "Alice"} + })) + }) + + it("must stringify repeated objects in arrays", function() { + var alice = {name: "Alice"} + var obj = [alice, alice] + var json = stringify(obj, null, 2) + json.must.eql(jsonify([{name: "Alice"}, {name: "Alice"}])) + }) + + it("must call given decycler and use its output", function() { + var obj = {} + obj.a = obj + obj.b = obj + + var decycle = Sinon.spy(function() { return decycle.callCount }) + var json = stringify(obj, null, 2, decycle) + json.must.eql(jsonify({a: 1, b: 2}, null, 2)) + + decycle.callCount.must.equal(2) + decycle.thisValues[0].must.equal(obj) + decycle.args[0][0].must.equal("a") + decycle.args[0][1].must.equal(obj) + decycle.thisValues[1].must.equal(obj) + decycle.args[1][0].must.equal("b") + decycle.args[1][1].must.equal(obj) + }) + + it("must call replacer and use its output", function() { + var obj = {name: "Alice", child: {name: "Bob"}} + + var replacer = Sinon.spy(bangString) + var json = stringify(obj, replacer, 2) + json.must.eql(jsonify({name: "Alice!", child: {name: "Bob!"}})) + + replacer.callCount.must.equal(4) + replacer.args[0][0].must.equal("") + replacer.args[0][1].must.equal(obj) + replacer.thisValues[1].must.equal(obj) + replacer.args[1][0].must.equal("name") + replacer.args[1][1].must.equal("Alice") + replacer.thisValues[2].must.equal(obj) + replacer.args[2][0].must.equal("child") + replacer.args[2][1].must.equal(obj.child) + replacer.thisValues[3].must.equal(obj.child) + replacer.args[3][0].must.equal("name") + replacer.args[3][1].must.equal("Bob") + }) + + it("must call replacer after describing circular references", function() { + var obj = {name: "Alice"} + obj.self = obj + + var replacer = Sinon.spy(bangString) + var json = stringify(obj, replacer, 2) + json.must.eql(jsonify({name: "Alice!", self: "[Circular ~]!"})) + + replacer.callCount.must.equal(3) + replacer.args[0][0].must.equal("") + replacer.args[0][1].must.equal(obj) + replacer.thisValues[1].must.equal(obj) + replacer.args[1][0].must.equal("name") + replacer.args[1][1].must.equal("Alice") + replacer.thisValues[2].must.equal(obj) + replacer.args[2][0].must.equal("self") + replacer.args[2][1].must.equal("[Circular ~]") + }) + + it("must call given decycler and use its output for nested objects", + function() { + var obj = {} + obj.a = obj + obj.b = {self: obj} + + var decycle = Sinon.spy(function() { return decycle.callCount }) + var json = stringify(obj, null, 2, decycle) + json.must.eql(jsonify({a: 1, b: {self: 2}})) + + decycle.callCount.must.equal(2) + decycle.args[0][0].must.equal("a") + decycle.args[0][1].must.equal(obj) + decycle.args[1][0].must.equal("self") + decycle.args[1][1].must.equal(obj) + }) + + it("must use decycler's output when it returned null", function() { + var obj = {a: "b"} + obj.self = obj + obj.selves = [obj, obj] + + function decycle() { return null } + stringify(obj, null, 2, decycle).must.eql(jsonify({ + a: "b", + self: null, + selves: [null, null] + })) + }) + + it("must use decycler's output when it returned undefined", function() { + var obj = {a: "b"} + obj.self = obj + obj.selves = [obj, obj] + + function decycle() {} + stringify(obj, null, 2, decycle).must.eql(jsonify({ + a: "b", + selves: [null, null] + })) + }) + + it("must throw given a decycler that returns a cycle", function() { + var obj = {} + obj.self = obj + var err + function identity(key, value) { return value } + try { stringify(obj, null, 2, identity) } catch (ex) { err = ex } + err.must.be.an.instanceof(TypeError) + }) + + describe(".getSerialize", function() { + it("must stringify circular objects", function() { + var obj = {a: "b"} + obj.circularRef = obj + obj.list = [obj, obj] + + var json = JSON.stringify(obj, stringify.getSerialize(), 2) + json.must.eql(jsonify({ + "a": "b", + "circularRef": "[Circular ~]", + "list": ["[Circular ~]", "[Circular ~]"] + })) + }) + + // This is the behavior as of Mar 3, 2015. + // The serializer function keeps state inside the returned function and + // so far I'm not sure how to not do that. JSON.stringify's replacer is not + // called _after_ serialization. + xit("must return a function that could be called twice", function() { + var obj = {name: "Alice"} + obj.self = obj + + var json + var serializer = stringify.getSerialize() + + json = JSON.stringify(obj, serializer, 2) + json.must.eql(jsonify({name: "Alice", self: "[Circular ~]"})) + + json = JSON.stringify(obj, serializer, 2) + json.must.eql(jsonify({name: "Alice", self: "[Circular ~]"})) + }) + }) +}) + +function bangString(key, value) { + return typeof value == "string" ? value + "!" : value +} diff --git a/hm_sunwell/node_modules/jsonpointer/.travis.yml b/hm_sunwell/node_modules/jsonpointer/.travis.yml new file mode 100644 index 0000000..7f56324 --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/.travis.yml @@ -0,0 +1,7 @@ +language: "node_js" +node_js: + - 0.10 + - 0.11 + - 0.12 + - 4.0 + - node diff --git a/hm_sunwell/node_modules/jsonpointer/LICENSE.md b/hm_sunwell/node_modules/jsonpointer/LICENSE.md new file mode 100644 index 0000000..ac32f5d --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011-2015 Jan Lehnardt & Marc Bachmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/jsonpointer/README.md b/hm_sunwell/node_modules/jsonpointer/README.md new file mode 100644 index 0000000..bc7aa15 --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/README.md @@ -0,0 +1,39 @@ +# JSON Pointer for nodejs + +This is an implementation of [JSON Pointer](http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-08). + +## Usage +```javascript +var jsonpointer = require('jsonpointer'); +var obj = { foo: 1, bar: { baz: 2}, qux: [3, 4, 5]}; + +jsonpointer.get(obj, '/foo'); // returns 1 +jsonpointer.get(obj, '/bar/baz'); // returns 2 +jsonpointer.get(obj, '/qux/0'); // returns 3 +jsonpointer.get(obj, '/qux/1'); // returns 4 +jsonpointer.get(obj, '/qux/2'); // returns 5 +jsonpointer.get(obj, '/quo'); // returns null + +jsonpointer.set(obj, '/foo', 6); // sets obj.foo = 6; +jsonpointer.set(obj, '/qux/-', 6) // sets obj.qux = [3, 4, 5, 6] + +var pointer = jsonpointer.compile('/foo') +pointer.get(obj) // returns 1 +pointer.set(obj, 1) // sets obj.foo = 1 +``` + +## Testing + + $ node test.js + All tests pass. + $ + +[![Build Status](https://travis-ci.org/janl/node-jsonpointer.png?branch=master)](https://travis-ci.org/janl/node-jsonpointer) + +## Author + +(c) 2011-2015 Jan Lehnardt & Marc Bachmann + +## License + +MIT License. diff --git a/hm_sunwell/node_modules/jsonpointer/benchmark.js b/hm_sunwell/node_modules/jsonpointer/benchmark.js new file mode 100644 index 0000000..8a95636 --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/benchmark.js @@ -0,0 +1,56 @@ +var jsonpointer = require('./') + +var i +var obj = { + a: 1, + b: { + c: 2 + }, + d: { + e: [{ a: 3 }, { b: 4 }, { c: 5 }] + } +} + +// Get +console.time('get first level property') +for (i = 0; i < 1e6; i++) { + jsonpointer.get(obj, '/a') +} +console.timeEnd('get first level property') + +console.time('get second level property') +for (i = 0; i < 1e6; i++) { + jsonpointer.get(obj, '/d/e') +} +console.timeEnd('get second level property') + +console.time('get third level property') +for (i = 0; i < 1e6; i++) { + jsonpointer.get(obj, '/d/e/0') +} +console.timeEnd('get third level property') + +// Set +console.time('set first level property') +for (i = 0; i < 1e6; i++) { + jsonpointer.set(obj, '/a', 'bla') +} +console.timeEnd('set first level property') + +console.time('set second level property') +for (i = 0; i < 1e6; i++) { + jsonpointer.set(obj, '/d/e', 'bla') +} +console.timeEnd('set second level property') + +console.time('set third level property') +for (i = 0; i < 1e6; i++) { + jsonpointer.set(obj, '/d/e/0', 'bla') +} +console.timeEnd('set third level property') + +console.time('push property into array') +for (i = 0; i < 1e6; i++) { + jsonpointer.set(obj, '/d/e/-', 'bla') +} +console.timeEnd('push property into array') diff --git a/hm_sunwell/node_modules/jsonpointer/jsonpointer.js b/hm_sunwell/node_modules/jsonpointer/jsonpointer.js new file mode 100644 index 0000000..7cfaec0 --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/jsonpointer.js @@ -0,0 +1,93 @@ +var hasExcape = /~/ +var escapeMatcher = /~[01]/g +function escapeReplacer (m) { + switch (m) { + case '~1': return '/' + case '~0': return '~' + } + throw new Error('Invalid tilde escape: ' + m) +} + +function untilde (str) { + if (!hasExcape.test(str)) return str + return str.replace(escapeMatcher, escapeReplacer) +} + +function setter (obj, pointer, value) { + var part + var hasNextPart + + for (var p = 1, len = pointer.length; p < len;) { + part = untilde(pointer[p++]) + hasNextPart = len > p + + if (typeof obj[part] === 'undefined') { + // support setting of /- + if (Array.isArray(obj) && part === '-') { + part = obj.length + } + + // support nested objects/array when setting values + if (hasNextPart) { + if ((pointer[p] !== '' && pointer[p] < Infinity) || pointer[p] === '-') obj[part] = [] + else obj[part] = {} + } + } + + if (!hasNextPart) break + obj = obj[part] + } + + var oldValue = obj[part] + if (value === undefined) delete obj[part] + else obj[part] = value + return oldValue +} + +function compilePointer (pointer) { + if (typeof pointer === 'string') { + pointer = pointer.split('/') + if (pointer[0] === '') return pointer + throw new Error('Invalid JSON pointer.') + } else if (Array.isArray(pointer)) { + return pointer + } + + throw new Error('Invalid JSON pointer.') +} + +function get (obj, pointer) { + if (typeof obj !== 'object') throw new Error('Invalid input object.') + pointer = compilePointer(pointer) + var len = pointer.length + if (len === 1) return obj + + for (var p = 1; p < len;) { + obj = obj[untilde(pointer[p++])] + if (len === p) return obj + if (typeof obj !== 'object') return undefined + } +} + +function set (obj, pointer, value) { + if (typeof obj !== 'object') throw new Error('Invalid input object.') + pointer = compilePointer(pointer) + if (pointer.length === 0) throw new Error('Invalid JSON pointer for set.') + return setter(obj, pointer, value) +} + +function compile (pointer) { + var compiled = compilePointer(pointer) + return { + get: function (object) { + return get(object, compiled) + }, + set: function (object, value) { + return set(object, compiled, value) + } + } +} + +exports.get = get +exports.set = set +exports.compile = compile diff --git a/hm_sunwell/node_modules/jsonpointer/package.json b/hm_sunwell/node_modules/jsonpointer/package.json new file mode 100644 index 0000000..0669f0c --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/package.json @@ -0,0 +1,101 @@ +{ + "_args": [ + [ + "jsonpointer@^4.0.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/is-my-json-valid" + ] + ], + "_from": "jsonpointer@>=4.0.0 <5.0.0", + "_id": "jsonpointer@4.0.0", + "_inCache": true, + "_installable": true, + "_location": "/jsonpointer", + "_nodeVersion": "6.1.0", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/jsonpointer-4.0.0.tgz_1463651460494_0.02921536797657609" + }, + "_npmUser": { + "email": "marc.brookman@gmail.com", + "name": "marcbachmann" + }, + "_npmVersion": "3.8.6", + "_phantomChildren": {}, + "_requested": { + "name": "jsonpointer", + "raw": "jsonpointer@^4.0.0", + "rawSpec": "^4.0.0", + "scope": null, + "spec": ">=4.0.0 <5.0.0", + "type": "range" + }, + "_requiredBy": [ + "/is-my-json-valid" + ], + "_resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz", + "_shasum": "6661e161d2fc445f19f98430231343722e1fcbd5", + "_shrinkwrap": null, + "_spec": "jsonpointer@^4.0.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/is-my-json-valid", + "author": { + "email": "jan@apache.org", + "name": "Jan Lehnardt" + }, + "bugs": { + "url": "http://github.com/janl/node-jsonpointer/issues" + }, + "contributors": [ + { + "name": "Joe Hildebrand", + "email": "joe-github@cursive.net" + }, + { + "name": "Marc Bachmann", + "email": "marc.brookman@gmail.com" + } + ], + "dependencies": {}, + "description": "Simple JSON Addressing.", + "devDependencies": { + "standard": "^5.3.1" + }, + "directories": {}, + "dist": { + "shasum": "6661e161d2fc445f19f98430231343722e1fcbd5", + "tarball": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "gitHead": "2d46030ba6df41b566934c7202e31fb65058de71", + "homepage": "https://github.com/janl/node-jsonpointer#readme", + "license": "MIT", + "main": "./jsonpointer", + "maintainers": [ + { + "name": "jan", + "email": "jan@apache.org" + }, + { + "name": "marcbachmann", + "email": "marc.brookman@gmail.com" + } + ], + "name": "jsonpointer", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/janl/node-jsonpointer.git" + }, + "scripts": { + "test": "standard && node test.js" + }, + "tags": [ + "simple", + "util", + "util", + "utility" + ], + "version": "4.0.0" +} diff --git a/hm_sunwell/node_modules/jsonpointer/test.js b/hm_sunwell/node_modules/jsonpointer/test.js new file mode 100644 index 0000000..e3d9963 --- /dev/null +++ b/hm_sunwell/node_modules/jsonpointer/test.js @@ -0,0 +1,131 @@ +var assert = require('assert') +var jsonpointer = require('./jsonpointer') + +var obj = { + a: 1, + b: { + c: 2 + }, + d: { + e: [{ a: 3 }, { b: 4 }, { c: 5 }] + } +} + +assert.equal(jsonpointer.get(obj, '/a'), 1) +assert.equal(jsonpointer.get(obj, '/b/c'), 2) +assert.equal(jsonpointer.get(obj, '/d/e/0/a'), 3) +assert.equal(jsonpointer.get(obj, '/d/e/1/b'), 4) +assert.equal(jsonpointer.get(obj, '/d/e/2/c'), 5) + +// set returns old value +assert.equal(jsonpointer.set(obj, '/a', 2), 1) +assert.equal(jsonpointer.set(obj, '/b/c', 3), 2) +assert.equal(jsonpointer.set(obj, '/d/e/0/a', 4), 3) +assert.equal(jsonpointer.set(obj, '/d/e/1/b', 5), 4) +assert.equal(jsonpointer.set(obj, '/d/e/2/c', 6), 5) + +// set nested properties +assert.equal(jsonpointer.set(obj, '/f/g/h/i', 6), undefined) +assert.equal(jsonpointer.get(obj, '/f/g/h/i'), 6) + +// set an array +assert.equal(jsonpointer.set(obj, '/f/g/h/foo/-', 'test'), undefined) +var arr = jsonpointer.get(obj, '/f/g/h/foo') +assert(Array.isArray(arr), 'set /- creates an array.') +assert.equal(arr[0], 'test') + +assert.equal(jsonpointer.get(obj, '/a'), 2) +assert.equal(jsonpointer.get(obj, '/b/c'), 3) +assert.equal(jsonpointer.get(obj, '/d/e/0/a'), 4) +assert.equal(jsonpointer.get(obj, '/d/e/1/b'), 5) +assert.equal(jsonpointer.get(obj, '/d/e/2/c'), 6) + +// can set `null` as a value +assert.equal(jsonpointer.set(obj, '/f/g/h/foo/0', null), 'test') +assert.strictEqual(jsonpointer.get(obj, '/f/g/h/foo/0'), null) +assert.equal(jsonpointer.set(obj, '/b/c', null), 3) +assert.strictEqual(jsonpointer.get(obj, '/b/c'), null) + +assert.equal(jsonpointer.get(obj, ''), obj) +assert.throws(function () { jsonpointer.get(obj, 'a') }, validateError) +assert.throws(function () { jsonpointer.get(obj, 'a/') }, validateError) + +// can unset values with `undefined` +jsonpointer.set(obj, '/a', undefined) +assert.strictEqual(jsonpointer.get(obj, '/a'), undefined) +jsonpointer.set(obj, '/d/e/1', undefined) +assert.strictEqual(jsonpointer.get(obj, '/d/e/1'), undefined) + +// returns `undefined` when path extends beyond any existing objects +assert.strictEqual(jsonpointer.get(obj, '/x/y/z'), undefined) + +function validateError (err) { + if ((err instanceof Error) && /Invalid JSON pointer/.test(err.message)) { + return true + } +} + +var complexKeys = { + 'a/b': { + c: 1 + }, + d: { + 'e/f': 2 + }, + '~1': 3, + '01': 4 +} + +assert.equal(jsonpointer.get(complexKeys, '/a~1b/c'), 1) +assert.equal(jsonpointer.get(complexKeys, '/d/e~1f'), 2) +assert.equal(jsonpointer.get(complexKeys, '/~01'), 3) +assert.equal(jsonpointer.get(complexKeys, '/01'), 4) +assert.equal(jsonpointer.get(complexKeys, '/a/b/c'), null) +assert.equal(jsonpointer.get(complexKeys, '/~1'), null) + +// draft-ietf-appsawg-json-pointer-08 has special array rules +var ary = [ 'zero', 'one', 'two' ] +assert.equal(jsonpointer.get(ary, '/01'), null) + +assert.equal(jsonpointer.set(ary, '/-', 'three'), null) +assert.equal(ary[3], 'three') + +// Examples from the draft: +var example = { + 'foo': ['bar', 'baz'], + '': 0, + 'a/b': 1, + 'c%d': 2, + 'e^f': 3, + 'g|h': 4, + 'i\\j': 5, + 'k\'l': 6, + ' ': 7, + 'm~n': 8 +} + +assert.equal(jsonpointer.get(example, ''), example) +var ans = jsonpointer.get(example, '/foo') +assert.equal(ans.length, 2) +assert.equal(ans[0], 'bar') +assert.equal(ans[1], 'baz') +assert.equal(jsonpointer.get(example, '/foo/0'), 'bar') +assert.equal(jsonpointer.get(example, '/'), 0) +assert.equal(jsonpointer.get(example, '/a~1b'), 1) +assert.equal(jsonpointer.get(example, '/c%d'), 2) +assert.equal(jsonpointer.get(example, '/e^f'), 3) +assert.equal(jsonpointer.get(example, '/g|h'), 4) +assert.equal(jsonpointer.get(example, '/i\\j'), 5) +assert.equal(jsonpointer.get(example, '/k\'l'), 6) +assert.equal(jsonpointer.get(example, '/ '), 7) +assert.equal(jsonpointer.get(example, '/m~0n'), 8) + +// jsonpointer.compile(path) +var a = {foo: 'bar'} +var pointer = jsonpointer.compile('/foo') +assert.equal(pointer.get(a), 'bar') +assert.equal(pointer.set(a, 'test'), 'bar') +assert.equal(pointer.get(a), 'test') +assert.deepEqual(a, {foo: 'test'}) + +console.log('All tests pass.') diff --git a/hm_sunwell/node_modules/jsprim/CHANGES.md b/hm_sunwell/node_modules/jsprim/CHANGES.md new file mode 100644 index 0000000..3e152ab --- /dev/null +++ b/hm_sunwell/node_modules/jsprim/CHANGES.md @@ -0,0 +1,39 @@ +# Changelog + +## not yet released + +None yet. + +## v1.3.1 (2016-09-12) + +* #13 Incompatible with webpack + +## v1.3.0 (2016-06-22) + +* #14 add safer version of hasOwnProperty() +* #15 forEachKey() should ignore inherited properties + +## v1.2.2 (2015-10-15) + +* #11 NPM package shouldn't include any code that does `require('JSV')` +* #12 jsl.node.conf missing definition for "module" + +## v1.2.1 (2015-10-14) + +* #8 odd date parsing behaviour + +## v1.2.0 (2015-10-13) + +* #9 want function for returning RFC1123 dates + +## v1.1.0 (2015-09-02) + +* #6 a new suite of hrtime manipulation routines: `hrtimeAdd()`, + `hrtimeAccum()`, `hrtimeNanosec()`, `hrtimeMicrosec()` and + `hrtimeMillisec()`. + +## v1.0.0 (2015-09-01) + +First tracked release. Includes everything in previous releases, plus: + +* #4 want function for merging objects diff --git a/hm_sunwell/node_modules/jsprim/LICENSE b/hm_sunwell/node_modules/jsprim/LICENSE new file mode 100644 index 0000000..cbc0bb3 --- /dev/null +++ b/hm_sunwell/node_modules/jsprim/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012, Joyent, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE diff --git a/hm_sunwell/node_modules/jsprim/README.md b/hm_sunwell/node_modules/jsprim/README.md new file mode 100644 index 0000000..7303642 --- /dev/null +++ b/hm_sunwell/node_modules/jsprim/README.md @@ -0,0 +1,237 @@ +# jsprim: utilities for primitive JavaScript types + +This module provides miscellaneous facilities for working with strings, +numbers, dates, and objects and arrays of these basic types. + + +### deepCopy(obj) + +Creates a deep copy of a primitive type, object, or array of primitive types. + + +### deepEqual(obj1, obj2) + +Returns whether two objects are equal. + + +### isEmpty(obj) + +Returns true if the given object has no properties and false otherwise. This +is O(1) (unlike `Object.keys(obj).length === 0`, which is O(N)). + +### hasKey(obj, key) + +Returns true if the given object has an enumerable, non-inherited property +called `key`. [For information on enumerability and ownership of properties, see +the MDN +documentation.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) + +### forEachKey(obj, callback) + +Like Array.forEach, but iterates enumerable, owned properties of an object +rather than elements of an array. Equivalent to: + + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + callback(key, obj[key]); + } + } + + +### flattenObject(obj, depth) + +Flattens an object up to a given level of nesting, returning an array of arrays +of length "depth + 1", where the first "depth" elements correspond to flattened +columns and the last element contains the remaining object . For example: + + flattenObject({ + 'I': { + 'A': { + 'i': { + 'datum1': [ 1, 2 ], + 'datum2': [ 3, 4 ] + }, + 'ii': { + 'datum1': [ 3, 4 ] + } + }, + 'B': { + 'i': { + 'datum1': [ 5, 6 ] + }, + 'ii': { + 'datum1': [ 7, 8 ], + 'datum2': [ 3, 4 ], + }, + 'iii': { + } + } + }, + 'II': { + 'A': { + 'i': { + 'datum1': [ 1, 2 ], + 'datum2': [ 3, 4 ] + } + } + } + }, 3) + +becomes: + + [ + [ 'I', 'A', 'i', { 'datum1': [ 1, 2 ], 'datum2': [ 3, 4 ] } ], + [ 'I', 'A', 'ii', { 'datum1': [ 3, 4 ] } ], + [ 'I', 'B', 'i', { 'datum1': [ 5, 6 ] } ], + [ 'I', 'B', 'ii', { 'datum1': [ 7, 8 ], 'datum2': [ 3, 4 ] } ], + [ 'I', 'B', 'iii', {} ], + [ 'II', 'A', 'i', { 'datum1': [ 1, 2 ], 'datum2': [ 3, 4 ] } ] + ] + +This function is strict: "depth" must be a non-negative integer and "obj" must +be a non-null object with at least "depth" levels of nesting under all keys. + + +### flattenIter(obj, depth, func) + +This is similar to `flattenObject` except that instead of returning an array, +this function invokes `func(entry)` for each `entry` in the array that +`flattenObject` would return. `flattenIter(obj, depth, func)` is logically +equivalent to `flattenObject(obj, depth).forEach(func)`. Importantly, this +version never constructs the full array. Its memory usage is O(depth) rather +than O(n) (where `n` is the number of flattened elements). + +There's another difference between `flattenObject` and `flattenIter` that's +related to the special case where `depth === 0`. In this case, `flattenObject` +omits the array wrapping `obj` (which is regrettable). + + +### pluck(obj, key) + +Fetch nested property "key" from object "obj", traversing objects as needed. +For example, `pluck(obj, "foo.bar.baz")` is roughly equivalent to +`obj.foo.bar.baz`, except that: + +1. If traversal fails, the resulting value is undefined, and no error is + thrown. For example, `pluck({}, "foo.bar")` is just undefined. +2. If "obj" has property "key" directly (without traversing), the + corresponding property is returned. For example, + `pluck({ 'foo.bar': 1 }, 'foo.bar')` is 1, not undefined. This is also + true recursively, so `pluck({ 'a': { 'foo.bar': 1 } }, 'a.foo.bar')` is + also 1, not undefined. + + +### randElt(array) + +Returns an element from "array" selected uniformly at random. If "array" is +empty, throws an Error. + + +### startsWith(str, prefix) + +Returns true if the given string starts with the given prefix and false +otherwise. + + +### endsWith(str, suffix) + +Returns true if the given string ends with the given suffix and false +otherwise. + + +### iso8601(date) + +Converts a Date object to an ISO8601 date string of the form +"YYYY-MM-DDTHH:MM:SS.sssZ". This format is not customizable. + + +### parseDateTime(str) + +Parses a date expressed as a string, as either a number of milliseconds since +the epoch or any string format that Date accepts, giving preference to the +former where these two sets overlap (e.g., strings containing small numbers). + + +### hrtimeDiff(timeA, timeB) + +Given two hrtime readings (as from Node's `process.hrtime()`), where timeA is +later than timeB, compute the difference and return that as an hrtime. It is +illegal to invoke this for a pair of times where timeB is newer than timeA. + +### hrtimeAdd(timeA, timeB) + +Add two hrtime intervals (as from Node's `process.hrtime()`), returning a new +hrtime interval array. This function does not modify either input argument. + + +### hrtimeAccum(timeA, timeB) + +Add two hrtime intervals (as from Node's `process.hrtime()`), storing the +result in `timeA`. This function overwrites (and returns) the first argument +passed in. + + +### hrtimeNanosec(timeA), hrtimeMicrosec(timeA), hrtimeMillisec(timeA) + +This suite of functions converts a hrtime interval (as from Node's +`process.hrtime()`) into a scalar number of nanoseconds, microseconds or +milliseconds. Results are truncated, as with `Math.floor()`. + + +### validateJsonObject(schema, object) + +Uses JSON validation (via JSV) to validate the given object against the given +schema. On success, returns null. On failure, *returns* (does not throw) a +useful Error object. + + +### extraProperties(object, allowed) + +Check an object for unexpected properties. Accepts the object to check, and an +array of allowed property name strings. If extra properties are detected, an +array of extra property names is returned. If no properties other than those +in the allowed list are present on the object, the returned array will be of +zero length. + +### mergeObjects(provided, overrides, defaults) + +Merge properties from objects "provided", "overrides", and "defaults". The +intended use case is for functions that accept named arguments in an "args" +object, but want to provide some default values and override other values. In +that case, "provided" is what the caller specified, "overrides" are what the +function wants to override, and "defaults" contains default values. + +The function starts with the values in "defaults", overrides them with the +values in "provided", and then overrides those with the values in "overrides". +For convenience, any of these objects may be falsey, in which case they will be +ignored. The input objects are never modified, but properties in the returned +object are not deep-copied. + +For example: + + mergeObjects(undefined, { 'objectMode': true }, { 'highWaterMark': 0 }) + +returns: + + { 'objectMode': true, 'highWaterMark': 0 } + +For another example: + + mergeObjects( + { 'highWaterMark': 16, 'objectMode': 7 }, /* from caller */ + { 'objectMode': true }, /* overrides */ + { 'highWaterMark': 0 }); /* default */ + +returns: + + { 'objectMode': true, 'highWaterMark': 16 } + + +# Contributing + +Code should be "make check" clean. This target assumes that +[jsl](http://github.com/davepacheco/javascriptlint) and +[jsstyle](http://github.com/davepacheco/jsstyle) are on your path. + +New tests should generally accompany new functions and bug fixes. The tests +should pass cleanly (run tests/basic.js). diff --git a/hm_sunwell/node_modules/jsprim/lib/jsprim.js b/hm_sunwell/node_modules/jsprim/lib/jsprim.js new file mode 100644 index 0000000..26c3ba1 --- /dev/null +++ b/hm_sunwell/node_modules/jsprim/lib/jsprim.js @@ -0,0 +1,488 @@ +/* + * lib/jsprim.js: utilities for primitive JavaScript types + */ + +var mod_assert = require('assert'); +var mod_util = require('util'); + +var mod_extsprintf = require('extsprintf'); +var mod_verror = require('verror'); +var mod_jsonschema = require('json-schema'); + +/* + * Public interface + */ +exports.deepCopy = deepCopy; +exports.deepEqual = deepEqual; +exports.isEmpty = isEmpty; +exports.hasKey = hasKey; +exports.forEachKey = forEachKey; +exports.pluck = pluck; +exports.flattenObject = flattenObject; +exports.flattenIter = flattenIter; +exports.validateJsonObject = validateJsonObjectJS; +exports.validateJsonObjectJS = validateJsonObjectJS; +exports.randElt = randElt; +exports.extraProperties = extraProperties; +exports.mergeObjects = mergeObjects; + +exports.startsWith = startsWith; +exports.endsWith = endsWith; + +exports.iso8601 = iso8601; +exports.rfc1123 = rfc1123; +exports.parseDateTime = parseDateTime; + +exports.hrtimediff = hrtimeDiff; +exports.hrtimeDiff = hrtimeDiff; +exports.hrtimeAccum = hrtimeAccum; +exports.hrtimeAdd = hrtimeAdd; +exports.hrtimeNanosec = hrtimeNanosec; +exports.hrtimeMicrosec = hrtimeMicrosec; +exports.hrtimeMillisec = hrtimeMillisec; + + +/* + * Deep copy an acyclic *basic* Javascript object. This only handles basic + * scalars (strings, numbers, booleans) and arbitrarily deep arrays and objects + * containing these. This does *not* handle instances of other classes. + */ +function deepCopy(obj) +{ + var ret, key; + var marker = '__deepCopy'; + + if (obj && obj[marker]) + throw (new Error('attempted deep copy of cyclic object')); + + if (obj && obj.constructor == Object) { + ret = {}; + obj[marker] = true; + + for (key in obj) { + if (key == marker) + continue; + + ret[key] = deepCopy(obj[key]); + } + + delete (obj[marker]); + return (ret); + } + + if (obj && obj.constructor == Array) { + ret = []; + obj[marker] = true; + + for (key = 0; key < obj.length; key++) + ret.push(deepCopy(obj[key])); + + delete (obj[marker]); + return (ret); + } + + /* + * It must be a primitive type -- just return it. + */ + return (obj); +} + +function deepEqual(obj1, obj2) +{ + if (typeof (obj1) != typeof (obj2)) + return (false); + + if (obj1 === null || obj2 === null || typeof (obj1) != 'object') + return (obj1 === obj2); + + if (obj1.constructor != obj2.constructor) + return (false); + + var k; + for (k in obj1) { + if (!obj2.hasOwnProperty(k)) + return (false); + + if (!deepEqual(obj1[k], obj2[k])) + return (false); + } + + for (k in obj2) { + if (!obj1.hasOwnProperty(k)) + return (false); + } + + return (true); +} + +function isEmpty(obj) +{ + var key; + for (key in obj) + return (false); + return (true); +} + +function hasKey(obj, key) +{ + mod_assert.equal(typeof (key), 'string'); + return (Object.prototype.hasOwnProperty.call(obj, key)); +} + +function forEachKey(obj, callback) +{ + for (var key in obj) { + if (hasKey(obj, key)) { + callback(key, obj[key]); + } + } +} + +function pluck(obj, key) +{ + mod_assert.equal(typeof (key), 'string'); + return (pluckv(obj, key)); +} + +function pluckv(obj, key) +{ + if (obj === null || typeof (obj) !== 'object') + return (undefined); + + if (obj.hasOwnProperty(key)) + return (obj[key]); + + var i = key.indexOf('.'); + if (i == -1) + return (undefined); + + var key1 = key.substr(0, i); + if (!obj.hasOwnProperty(key1)) + return (undefined); + + return (pluckv(obj[key1], key.substr(i + 1))); +} + +/* + * Invoke callback(row) for each entry in the array that would be returned by + * flattenObject(data, depth). This is just like flattenObject(data, + * depth).forEach(callback), except that the intermediate array is never + * created. + */ +function flattenIter(data, depth, callback) +{ + doFlattenIter(data, depth, [], callback); +} + +function doFlattenIter(data, depth, accum, callback) +{ + var each; + var key; + + if (depth === 0) { + each = accum.slice(0); + each.push(data); + callback(each); + return; + } + + mod_assert.ok(data !== null); + mod_assert.equal(typeof (data), 'object'); + mod_assert.equal(typeof (depth), 'number'); + mod_assert.ok(depth >= 0); + + for (key in data) { + each = accum.slice(0); + each.push(key); + doFlattenIter(data[key], depth - 1, each, callback); + } +} + +function flattenObject(data, depth) +{ + if (depth === 0) + return ([ data ]); + + mod_assert.ok(data !== null); + mod_assert.equal(typeof (data), 'object'); + mod_assert.equal(typeof (depth), 'number'); + mod_assert.ok(depth >= 0); + + var rv = []; + var key; + + for (key in data) { + flattenObject(data[key], depth - 1).forEach(function (p) { + rv.push([ key ].concat(p)); + }); + } + + return (rv); +} + +function startsWith(str, prefix) +{ + return (str.substr(0, prefix.length) == prefix); +} + +function endsWith(str, suffix) +{ + return (str.substr( + str.length - suffix.length, suffix.length) == suffix); +} + +function iso8601(d) +{ + if (typeof (d) == 'number') + d = new Date(d); + mod_assert.ok(d.constructor === Date); + return (mod_extsprintf.sprintf('%4d-%02d-%02dT%02d:%02d:%02d.%03dZ', + d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(), + d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), + d.getUTCMilliseconds())); +} + +var RFC1123_MONTHS = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; +var RFC1123_DAYS = [ + 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + +function rfc1123(date) { + return (mod_extsprintf.sprintf('%s, %02d %s %04d %02d:%02d:%02d GMT', + RFC1123_DAYS[date.getUTCDay()], date.getUTCDate(), + RFC1123_MONTHS[date.getUTCMonth()], date.getUTCFullYear(), + date.getUTCHours(), date.getUTCMinutes(), + date.getUTCSeconds())); +} + +/* + * Parses a date expressed as a string, as either a number of milliseconds since + * the epoch or any string format that Date accepts, giving preference to the + * former where these two sets overlap (e.g., small numbers). + */ +function parseDateTime(str) +{ + /* + * This is irritatingly implicit, but significantly more concise than + * alternatives. The "+str" will convert a string containing only a + * number directly to a Number, or NaN for other strings. Thus, if the + * conversion succeeds, we use it (this is the milliseconds-since-epoch + * case). Otherwise, we pass the string directly to the Date + * constructor to parse. + */ + var numeric = +str; + if (!isNaN(numeric)) { + return (new Date(numeric)); + } else { + return (new Date(str)); + } +} + +function validateJsonObjectJS(schema, input) +{ + var report = mod_jsonschema.validate(input, schema); + + if (report.errors.length === 0) + return (null); + + /* Currently, we only do anything useful with the first error. */ + var error = report.errors[0]; + + /* The failed property is given by a URI with an irrelevant prefix. */ + var propname = error['property']; + var reason = error['message'].toLowerCase(); + var i, j; + + /* + * There's at least one case where the property error message is + * confusing at best. We work around this here. + */ + if ((i = reason.indexOf('the property ')) != -1 && + (j = reason.indexOf(' is not defined in the schema and the ' + + 'schema does not allow additional properties')) != -1) { + i += 'the property '.length; + if (propname === '') + propname = reason.substr(i, j - i); + else + propname = propname + '.' + reason.substr(i, j - i); + + reason = 'unsupported property'; + } + + var rv = new mod_verror.VError('property "%s": %s', propname, reason); + rv.jsv_details = error; + return (rv); +} + +function randElt(arr) +{ + mod_assert.ok(Array.isArray(arr) && arr.length > 0, + 'randElt argument must be a non-empty array'); + + return (arr[Math.floor(Math.random() * arr.length)]); +} + +function assertHrtime(a) +{ + mod_assert.ok(a[0] >= 0 && a[1] >= 0, + 'negative numbers not allowed in hrtimes'); + mod_assert.ok(a[1] < 1e9, 'nanoseconds column overflow'); +} + +/* + * Compute the time elapsed between hrtime readings A and B, where A is later + * than B. hrtime readings come from Node's process.hrtime(). There is no + * defined way to represent negative deltas, so it's illegal to diff B from A + * where the time denoted by B is later than the time denoted by A. If this + * becomes valuable, we can define a representation and extend the + * implementation to support it. + */ +function hrtimeDiff(a, b) +{ + assertHrtime(a); + assertHrtime(b); + mod_assert.ok(a[0] > b[0] || (a[0] == b[0] && a[1] >= b[1]), + 'negative differences not allowed'); + + var rv = [ a[0] - b[0], 0 ]; + + if (a[1] >= b[1]) { + rv[1] = a[1] - b[1]; + } else { + rv[0]--; + rv[1] = 1e9 - (b[1] - a[1]); + } + + return (rv); +} + +/* + * Convert a hrtime reading from the array format returned by Node's + * process.hrtime() into a scalar number of nanoseconds. + */ +function hrtimeNanosec(a) +{ + assertHrtime(a); + + return (Math.floor(a[0] * 1e9 + a[1])); +} + +/* + * Convert a hrtime reading from the array format returned by Node's + * process.hrtime() into a scalar number of microseconds. + */ +function hrtimeMicrosec(a) +{ + assertHrtime(a); + + return (Math.floor(a[0] * 1e6 + a[1] / 1e3)); +} + +/* + * Convert a hrtime reading from the array format returned by Node's + * process.hrtime() into a scalar number of milliseconds. + */ +function hrtimeMillisec(a) +{ + assertHrtime(a); + + return (Math.floor(a[0] * 1e3 + a[1] / 1e6)); +} + +/* + * Add two hrtime readings A and B, overwriting A with the result of the + * addition. This function is useful for accumulating several hrtime intervals + * into a counter. Returns A. + */ +function hrtimeAccum(a, b) +{ + assertHrtime(a); + assertHrtime(b); + + /* + * Accumulate the nanosecond component. + */ + a[1] += b[1]; + if (a[1] >= 1e9) { + /* + * The nanosecond component overflowed, so carry to the seconds + * field. + */ + a[0]++; + a[1] -= 1e9; + } + + /* + * Accumulate the seconds component. + */ + a[0] += b[0]; + + return (a); +} + +/* + * Add two hrtime readings A and B, returning the result as a new hrtime array. + * Does not modify either input argument. + */ +function hrtimeAdd(a, b) +{ + assertHrtime(a); + + var rv = [ a[0], a[1] ]; + + return (hrtimeAccum(rv, b)); +} + + +/* + * Check an object for unexpected properties. Accepts the object to check, and + * an array of allowed property names (strings). Returns an array of key names + * that were found on the object, but did not appear in the list of allowed + * properties. If no properties were found, the returned array will be of + * zero length. + */ +function extraProperties(obj, allowed) +{ + mod_assert.ok(typeof (obj) === 'object' && obj !== null, + 'obj argument must be a non-null object'); + mod_assert.ok(Array.isArray(allowed), + 'allowed argument must be an array of strings'); + for (var i = 0; i < allowed.length; i++) { + mod_assert.ok(typeof (allowed[i]) === 'string', + 'allowed argument must be an array of strings'); + } + + return (Object.keys(obj).filter(function (key) { + return (allowed.indexOf(key) === -1); + })); +} + +/* + * Given three sets of properties "provided" (may be undefined), "overrides" + * (required), and "defaults" (may be undefined), construct an object containing + * the union of these sets with "overrides" overriding "provided", and + * "provided" overriding "defaults". None of the input objects are modified. + */ +function mergeObjects(provided, overrides, defaults) +{ + var rv, k; + + rv = {}; + if (defaults) { + for (k in defaults) + rv[k] = defaults[k]; + } + + if (provided) { + for (k in provided) + rv[k] = provided[k]; + } + + if (overrides) { + for (k in overrides) + rv[k] = overrides[k]; + } + + return (rv); +} diff --git a/hm_sunwell/node_modules/jsprim/package.json b/hm_sunwell/node_modules/jsprim/package.json new file mode 100644 index 0000000..3823cea --- /dev/null +++ b/hm_sunwell/node_modules/jsprim/package.json @@ -0,0 +1,77 @@ +{ + "_args": [ + [ + "jsprim@^1.2.2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/http-signature" + ] + ], + "_from": "jsprim@>=1.2.2 <2.0.0", + "_id": "jsprim@1.3.1", + "_inCache": true, + "_installable": true, + "_location": "/jsprim", + "_nodeVersion": "0.12.7", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/jsprim-1.3.1.tgz_1473725209917_0.5387293708045036" + }, + "_npmUser": { + "email": "dap@cs.brown.edu", + "name": "dap" + }, + "_npmVersion": "2.15.9", + "_phantomChildren": {}, + "_requested": { + "name": "jsprim", + "raw": "jsprim@^1.2.2", + "rawSpec": "^1.2.2", + "scope": null, + "spec": ">=1.2.2 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/http-signature" + ], + "_resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", + "_shasum": "2a7256f70412a29ee3670aaca625994c4dcff252", + "_shrinkwrap": null, + "_spec": "jsprim@^1.2.2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/http-signature", + "bugs": { + "url": "https://github.com/davepacheco/node-jsprim/issues" + }, + "dependencies": { + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "description": "utilities for primitive JavaScript types", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "2a7256f70412a29ee3670aaca625994c4dcff252", + "tarball": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz" + }, + "engines": [ + "node >=0.6.0" + ], + "gitHead": "825aba45c6cff4340c18cdae363ccb5bdf840bd7", + "homepage": "https://github.com/davepacheco/node-jsprim#readme", + "license": "MIT", + "main": "./lib/jsprim.js", + "maintainers": [ + { + "name": "dap", + "email": "dap@cs.brown.edu" + } + ], + "name": "jsprim", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/davepacheco/node-jsprim.git" + }, + "scripts": {}, + "version": "1.3.1" +} diff --git a/hm_sunwell/node_modules/kind-of/LICENSE b/hm_sunwell/node_modules/kind-of/LICENSE new file mode 100644 index 0000000..39245ac --- /dev/null +++ b/hm_sunwell/node_modules/kind-of/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/kind-of/README.md b/hm_sunwell/node_modules/kind-of/README.md new file mode 100644 index 0000000..4ac4f18 --- /dev/null +++ b/hm_sunwell/node_modules/kind-of/README.md @@ -0,0 +1,247 @@ +# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat)](https://travis-ci.org/jonschlinkert/kind-of) + +Get the native type of a value. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save kind-of +``` + +Install with [bower](http://bower.io/) + +```sh +$ bower install kind-of --save +``` + +## Usage + +> es5, browser and es6 ready + +```js +var kindOf = require('kind-of'); + +kindOf(undefined); +//=> 'undefined' + +kindOf(null); +//=> 'null' + +kindOf(true); +//=> 'boolean' + +kindOf(false); +//=> 'boolean' + +kindOf(new Boolean(true)); +//=> 'boolean' + +kindOf(new Buffer('')); +//=> 'buffer' + +kindOf(42); +//=> 'number' + +kindOf(new Number(42)); +//=> 'number' + +kindOf('str'); +//=> 'string' + +kindOf(new String('str')); +//=> 'string' + +kindOf(arguments); +//=> 'arguments' + +kindOf({}); +//=> 'object' + +kindOf(Object.create(null)); +//=> 'object' + +kindOf(new Test()); +//=> 'object' + +kindOf(new Date()); +//=> 'date' + +kindOf([]); +//=> 'array' + +kindOf([1, 2, 3]); +//=> 'array' + +kindOf(new Array()); +//=> 'array' + +kindOf(/foo/); +//=> 'regexp' + +kindOf(new RegExp('foo')); +//=> 'regexp' + +kindOf(function () {}); +//=> 'function' + +kindOf(function * () {}); +//=> 'function' + +kindOf(new Function()); +//=> 'function' + +kindOf(new Map()); +//=> 'map' + +kindOf(new WeakMap()); +//=> 'weakmap' + +kindOf(new Set()); +//=> 'set' + +kindOf(new WeakSet()); +//=> 'weakset' + +kindOf(Symbol('str')); +//=> 'symbol' + +kindOf(new Int8Array()); +//=> 'int8array' + +kindOf(new Uint8Array()); +//=> 'uint8array' + +kindOf(new Uint8ClampedArray()); +//=> 'uint8clampedarray' + +kindOf(new Int16Array()); +//=> 'int16array' + +kindOf(new Uint16Array()); +//=> 'uint16array' + +kindOf(new Int32Array()); +//=> 'int32array' + +kindOf(new Uint32Array()); +//=> 'uint32array' + +kindOf(new Float32Array()); +//=> 'float32array' + +kindOf(new Float64Array()); +//=> 'float64array' +``` + +## Benchmarks + +Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of). +Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`. + +```bash +#1: array + current x 23,329,397 ops/sec ±0.82% (94 runs sampled) + lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled) + lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled) + +#2: boolean + current x 27,197,115 ops/sec ±0.85% (94 runs sampled) + lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled) + lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled) + +#3: date + current x 20,190,117 ops/sec ±0.86% (92 runs sampled) + lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled) + lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled) + +#4: function + current x 23,855,460 ops/sec ±0.60% (97 runs sampled) + lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled) + lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled) + +#5: null + current x 27,061,047 ops/sec ±0.97% (96 runs sampled) + lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled) + lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled) + +#6: number + current x 25,075,682 ops/sec ±0.53% (99 runs sampled) + lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled) + lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled) + +#7: object + current x 3,348,980 ops/sec ±0.49% (99 runs sampled) + lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled) + lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled) + +#8: regex + current x 21,284,827 ops/sec ±0.72% (96 runs sampled) + lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled) + lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled) + +#9: string + current x 25,379,234 ops/sec ±0.58% (96 runs sampled) + lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled) + lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled) + +#10: undef + current x 27,459,221 ops/sec ±1.01% (93 runs sampled) + lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled) + lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled) +``` + +## Optimizations + +In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library: + +1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot. +2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it. +3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'` + +## About + +### Related projects + +* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet") +* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.") +* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive. | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Building docs + +_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ + +To generate the readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install -g verb verb-generate-readme && verb +``` + +### Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +### License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/kind-of/blob/master/LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.28, on July 29, 2016._ \ No newline at end of file diff --git a/hm_sunwell/node_modules/kind-of/index.js b/hm_sunwell/node_modules/kind-of/index.js new file mode 100644 index 0000000..87938c9 --- /dev/null +++ b/hm_sunwell/node_modules/kind-of/index.js @@ -0,0 +1,113 @@ +var isBuffer = require('is-buffer'); +var toString = Object.prototype.toString; + +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ + +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } + + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } + + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } + + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + + // buffer + if (typeof Buffer !== 'undefined' && isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; diff --git a/hm_sunwell/node_modules/kind-of/package.json b/hm_sunwell/node_modules/kind-of/package.json new file mode 100644 index 0000000..9f92ed9 --- /dev/null +++ b/hm_sunwell/node_modules/kind-of/package.json @@ -0,0 +1,146 @@ +{ + "_args": [ + [ + "kind-of@^3.0.2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/align-text" + ] + ], + "_from": "kind-of@>=3.0.2 <4.0.0", + "_id": "kind-of@3.0.4", + "_inCache": true, + "_installable": true, + "_location": "/kind-of", + "_nodeVersion": "6.3.0", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/kind-of-3.0.4.tgz_1469811230830_0.8813814013265073" + }, + "_npmUser": { + "email": "github@sellside.com", + "name": "jonschlinkert" + }, + "_npmVersion": "3.10.3", + "_phantomChildren": {}, + "_requested": { + "name": "kind-of", + "raw": "kind-of@^3.0.2", + "rawSpec": "^3.0.2", + "scope": null, + "spec": ">=3.0.2 <4.0.0", + "type": "range" + }, + "_requiredBy": [ + "/align-text" + ], + "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz", + "_shasum": "7b8ecf18a4e17f8269d73b501c9f232c96887a74", + "_shrinkwrap": null, + "_spec": "kind-of@^3.0.2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/align-text", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/kind-of/issues" + }, + "dependencies": { + "is-buffer": "^1.0.2" + }, + "description": "Get the native type of a value.", + "devDependencies": { + "ansi-bold": "^0.1.1", + "benchmarked": "^0.2.5", + "browserify": "^13.1.0", + "glob": "^7.0.5", + "gulp-format-md": "^0.1.9", + "mocha": "^2.5.3", + "type-of": "^2.0.1", + "typeof": "^1.0.0" + }, + "directories": {}, + "dist": { + "shasum": "7b8ecf18a4e17f8269d73b501c9f232c96887a74", + "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "LICENSE", + "README.md", + "index.js" + ], + "gitHead": "8f93765a6bbbe350e1ba68e790d1ff337b91331a", + "homepage": "https://github.com/jonschlinkert/kind-of", + "keywords": [ + "arguments", + "array", + "boolean", + "check", + "date", + "function", + "is", + "is-type", + "is-type-of", + "kind", + "kind-of", + "number", + "object", + "of", + "regexp", + "string", + "test", + "type", + "type-of", + "typeof", + "types" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + } + ], + "name": "kind-of", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/kind-of.git" + }, + "scripts": { + "prepublish": "browserify -o browser.js -e index.js -s index --bare", + "test": "mocha" + }, + "verb": { + "layout": "default", + "lint": { + "reflinks": true + }, + "plugins": [ + "gulp-format-md" + ], + "reflinks": [ + "verb" + ], + "related": { + "list": [ + "is-glob", + "is-number", + "is-primitive" + ] + }, + "tasks": [ + "readme" + ], + "toc": false + }, + "version": "3.0.4" +} diff --git a/hm_sunwell/node_modules/lazy-cache/LICENSE b/hm_sunwell/node_modules/lazy-cache/LICENSE new file mode 100644 index 0000000..1e49edf --- /dev/null +++ b/hm_sunwell/node_modules/lazy-cache/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/lazy-cache/README.md b/hm_sunwell/node_modules/lazy-cache/README.md new file mode 100644 index 0000000..33b5a4d --- /dev/null +++ b/hm_sunwell/node_modules/lazy-cache/README.md @@ -0,0 +1,147 @@ +# lazy-cache [![NPM version](https://img.shields.io/npm/v/lazy-cache.svg?style=flat)](https://www.npmjs.com/package/lazy-cache) [![NPM downloads](https://img.shields.io/npm/dm/lazy-cache.svg?style=flat)](https://npmjs.org/package/lazy-cache) [![Build Status](https://img.shields.io/travis/jonschlinkert/lazy-cache.svg?style=flat)](https://travis-ci.org/jonschlinkert/lazy-cache) + +> Cache requires to be lazy-loaded when needed. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install lazy-cache --save +``` + +If you use webpack and are experiencing issues, try using [unlazy-loader](https://github.com/doowb/unlazy-loader), a webpack loader that fixes the bug that prevents webpack from working with native javascript getters. + +## Usage + +```js +var utils = require('lazy-cache')(require); +``` + +**Use as a property on `lazy`** + +The module is also added as a property to the `lazy` function +so it can be called without having to call a function first. + +```js +var utils = require('lazy-cache')(require); + +// `npm install glob` +utils('glob'); + +// glob sync +console.log(utils.glob.sync('*.js')); + +// glob async +utils.glob('*.js', function (err, files) { + console.log(files); +}); +``` + +**Use as a function** + +```js +var utils = require('lazy-cache')(require); +var glob = utils('glob'); + +// `glob` is a now a function that may be called when needed +glob().sync('foo/*.js'); +``` + +## Aliases + +An alias may be passed as the second argument if you don't want to use the automatically camel-cased variable name. + +**Example** + +```js +var utils = require('lazy-cache')(require); + +// alias `ansi-yellow` as `yellow` +utils('ansi-yellow', 'yellow'); +console.log(utils.yellow('foo')); +``` + +## Browserify usage + +**Example** + +```js +var utils = require('lazy-cache')(require); +// temporarily re-assign `require` to trick browserify +var fn = require; +require = utils; +// list module dependencies (here, `require` is actually `lazy-cache`) +require('glob'); +require = fn; // restore the native `require` function + +/** + * Now you can use glob with the `utils.glob` variable + */ + +// sync +console.log(utils.glob.sync('*.js')); + +// async +utils.glob('*.js', function (err, files) { + console.log(files.join('\n')); +}); +``` + +## Kill switch + +In certain rare edge cases it may be necessary to unlazy all lazy-cached dependencies (5 reported cases after ~30 million downloads). + +To force lazy-cache to immediately invoke all dependencies, do: + +```js +process.env.UNLAZY = true; +``` + +## Related projects + +You might also be interested in these projects: + +[lint-deps](https://www.npmjs.com/package/lint-deps): CLI tool that tells you when dependencies are missing from package.json and offers you a… [more](https://www.npmjs.com/package/lint-deps) | [homepage](https://github.com/jonschlinkert/lint-deps) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/lazy-cache/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/lazy-cache/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on April 22, 2016._ \ No newline at end of file diff --git a/hm_sunwell/node_modules/lazy-cache/index.js b/hm_sunwell/node_modules/lazy-cache/index.js new file mode 100644 index 0000000..da7897d --- /dev/null +++ b/hm_sunwell/node_modules/lazy-cache/index.js @@ -0,0 +1,67 @@ +'use strict'; + +/** + * Cache results of the first function call to ensure only calling once. + * + * ```js + * var utils = require('lazy-cache')(require); + * // cache the call to `require('ansi-yellow')` + * utils('ansi-yellow', 'yellow'); + * // use `ansi-yellow` + * console.log(utils.yellow('this is yellow')); + * ``` + * + * @param {Function} `fn` Function that will be called only once. + * @return {Function} Function that can be called to get the cached function + * @api public + */ + +function lazyCache(fn) { + var cache = {}; + var proxy = function(mod, name) { + name = name || camelcase(mod); + + // check both boolean and string in case `process.env` cases to string + if (process.env.UNLAZY === 'true' || process.env.UNLAZY === true || process.env.TRAVIS) { + cache[name] = fn(mod); + } + + Object.defineProperty(proxy, name, { + enumerable: true, + configurable: true, + get: getter + }); + + function getter() { + if (cache.hasOwnProperty(name)) { + return cache[name]; + } + return (cache[name] = fn(mod)); + } + return getter; + }; + return proxy; +} + +/** + * Used to camelcase the name to be stored on the `lazy` object. + * + * @param {String} `str` String containing `_`, `.`, `-` or whitespace that will be camelcased. + * @return {String} camelcased string. + */ + +function camelcase(str) { + if (str.length === 1) { + return str.toLowerCase(); + } + str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); + return str.replace(/[\W_]+(\w|$)/g, function(_, ch) { + return ch.toUpperCase(); + }); +} + +/** + * Expose `lazyCache` + */ + +module.exports = lazyCache; diff --git a/hm_sunwell/node_modules/lazy-cache/package.json b/hm_sunwell/node_modules/lazy-cache/package.json new file mode 100644 index 0000000..0b6876f --- /dev/null +++ b/hm_sunwell/node_modules/lazy-cache/package.json @@ -0,0 +1,121 @@ +{ + "_args": [ + [ + "lazy-cache@^1.0.3", + "/home/xor/shared_vm/git/node-sunwell/node_modules/center-align" + ] + ], + "_from": "lazy-cache@>=1.0.3 <2.0.0", + "_id": "lazy-cache@1.0.4", + "_inCache": true, + "_installable": true, + "_location": "/lazy-cache", + "_nodeVersion": "5.5.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/lazy-cache-1.0.4.tgz_1461378859142_0.0996799839194864" + }, + "_npmUser": { + "email": "github@sellside.com", + "name": "jonschlinkert" + }, + "_npmVersion": "3.6.0", + "_phantomChildren": {}, + "_requested": { + "name": "lazy-cache", + "raw": "lazy-cache@^1.0.3", + "rawSpec": "^1.0.3", + "scope": null, + "spec": ">=1.0.3 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/center-align" + ], + "_resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "_shasum": "a1d78fc3a50474cb80845d3b3b6e1da49a446e8e", + "_shrinkwrap": null, + "_spec": "lazy-cache@^1.0.3", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/center-align", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/lazy-cache/issues" + }, + "dependencies": {}, + "description": "Cache requires to be lazy-loaded when needed.", + "devDependencies": { + "ansi-yellow": "^0.1.1", + "glob": "^7.0.3", + "gulp-format-md": "^0.1.8", + "mocha": "^2.4.5" + }, + "directories": {}, + "dist": { + "shasum": "a1d78fc3a50474cb80845d3b3b6e1da49a446e8e", + "tarball": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "d081ffbda147391083a6856fafb1c5d82308f80c", + "homepage": "https://github.com/jonschlinkert/lazy-cache", + "keywords": [ + "cache", + "caching", + "dependencies", + "dependency", + "lazy", + "require", + "requires" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + } + ], + "name": "lazy-cache", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/lazy-cache.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "layout": "default", + "lint": { + "reflinks": true + }, + "plugins": [ + "gulp-format-md" + ], + "reflinks": [ + "verb" + ], + "related": { + "list": [ + "lint-deps" + ] + }, + "tasks": [ + "readme" + ], + "toc": false + }, + "version": "1.0.4" +} diff --git a/hm_sunwell/node_modules/lcov-parse/.npmignore b/hm_sunwell/node_modules/lcov-parse/.npmignore new file mode 100644 index 0000000..6abaafc --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/.npmignore @@ -0,0 +1,2 @@ +tests +.travis.yml diff --git a/hm_sunwell/node_modules/lcov-parse/LICENSE b/hm_sunwell/node_modules/lcov-parse/LICENSE new file mode 100644 index 0000000..22960b6 --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/LICENSE @@ -0,0 +1,25 @@ +Copyright 2012 Yahoo! Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yahoo! Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/hm_sunwell/node_modules/lcov-parse/README.md b/hm_sunwell/node_modules/lcov-parse/README.md new file mode 100644 index 0000000..0b7bf68 --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/README.md @@ -0,0 +1,79 @@ +## LCOV file parser + +Simple LCOV file parser + +## Installation + + npm install lcov-parse + + +## Usage + + var parse = require('lcov-parse'); + + parse('./path/to/file.info', function(err, data) { + //process the data here + }); + +or + + parse(lcovString, function(err, data) { + //process the data here + }); + +## Formatting + +Using this as a guide: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php + +It will return JSON like this: + +``` + { + "title": "Test #1", + "file": "anim-base/anim-base-coverage.js", + "functions": { + "hit": 23, + "found": 29, + "details": [ + { + "name": "(anonymous 1)", + "line": 7, + "hit": 6 + }, + { + "name": "(anonymous 2)", + "line": 620, + "hit": 225 + }, + { + "name": "_end", + "line": 516, + "hit": 228 + } + ] + } + "lines": { + "found": 181, + "hit": 143, + "details": [ + { + "line": 7, + "hit": 6 + }, + { + "line": 29, + "hit": 6 + } + ] + } +} +``` + +## Tests + + npm install && npm test + + +## Build Status + +[![Build Status](https://secure.travis-ci.org/davglass/lcov-parse.png?branch=master)](http://travis-ci.org/davglass/lcov-parse) diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/coverage.json b/hm_sunwell/node_modules/lcov-parse/coverage/coverage.json new file mode 100644 index 0000000..f35c208 --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/coverage.json @@ -0,0 +1 @@ +{"/Users/davglass/src/lcov-parse/lib/index.js":{"path":"/Users/davglass/src/lcov-parse/lib/index.js","s":{"1":1,"2":1,"3":1,"4":3,"5":3,"6":424,"7":424,"8":424,"9":4,"10":4,"11":4,"12":4,"13":3,"14":3,"15":3,"16":3,"17":3,"18":3,"19":3,"20":3,"21":263,"22":263,"23":263,"24":48,"25":48,"26":48,"27":48,"28":48,"29":591,"30":48,"31":48,"32":48,"33":23,"34":23,"35":23,"36":2,"37":2,"38":2,"39":2,"40":424,"41":7,"42":7,"43":3,"44":3,"45":2,"46":1,"47":1,"48":3,"49":3,"50":2,"51":1,"52":1,"53":1,"54":1},"b":{"1":[1,0],"2":[4,4,3,3,3,3,263,48,48,23,2,2],"3":[48,543],"4":[591,53],"5":[1,22],"6":[7,417],"7":[2,1],"8":[2,1]},"f":{"1":3,"2":424,"3":591,"4":3,"5":3,"6":1},"fnMap":{"1":{"name":"(anonymous_1)","line":13,"loc":{"start":{"line":13,"column":15},"end":{"line":13,"column":33}}},"2":{"name":"(anonymous_2)","line":16,"loc":{"start":{"line":16,"column":56},"end":{"line":16,"column":71}}},"3":{"name":"(anonymous_3)","line":57,"loc":{"start":{"line":57,"column":44},"end":{"line":57,"column":59}}},"4":{"name":"(anonymous_4)","line":112,"loc":{"start":{"line":112,"column":12},"end":{"line":112,"column":31}}},"5":{"name":"(anonymous_5)","line":113,"loc":{"start":{"line":113,"column":17},"end":{"line":113,"column":29}}},"6":{"name":"(anonymous_6)","line":117,"loc":{"start":{"line":117,"column":34},"end":{"line":117,"column":53}}}},"statementMap":{"1":{"start":{"line":7,"column":0},"end":{"line":8,"column":27}},"2":{"start":{"line":11,"column":0},"end":{"line":11,"column":38},"skip":true},"3":{"start":{"line":13,"column":0},"end":{"line":110,"column":2}},"4":{"start":{"line":14,"column":4},"end":{"line":14,"column":24}},"5":{"start":{"line":16,"column":4},"end":{"line":101,"column":7}},"6":{"start":{"line":17,"column":8},"end":{"line":17,"column":27}},"7":{"start":{"line":18,"column":8},"end":{"line":20,"column":22}},"8":{"start":{"line":22,"column":8},"end":{"line":79,"column":9}},"9":{"start":{"line":24,"column":16},"end":{"line":24,"column":45}},"10":{"start":{"line":25,"column":16},"end":{"line":25,"column":22}},"11":{"start":{"line":27,"column":16},"end":{"line":27,"column":60}},"12":{"start":{"line":28,"column":16},"end":{"line":28,"column":22}},"13":{"start":{"line":30,"column":16},"end":{"line":30,"column":63}},"14":{"start":{"line":31,"column":16},"end":{"line":31,"column":22}},"15":{"start":{"line":33,"column":16},"end":{"line":33,"column":61}},"16":{"start":{"line":34,"column":16},"end":{"line":34,"column":22}},"17":{"start":{"line":36,"column":16},"end":{"line":36,"column":59}},"18":{"start":{"line":37,"column":16},"end":{"line":37,"column":22}},"19":{"start":{"line":39,"column":16},"end":{"line":39,"column":57}},"20":{"start":{"line":40,"column":16},"end":{"line":40,"column":22}},"21":{"start":{"line":42,"column":16},"end":{"line":42,"column":44}},"22":{"start":{"line":43,"column":16},"end":{"line":46,"column":19}},"23":{"start":{"line":47,"column":16},"end":{"line":47,"column":22}},"24":{"start":{"line":49,"column":16},"end":{"line":49,"column":41}},"25":{"start":{"line":50,"column":16},"end":{"line":53,"column":19}},"26":{"start":{"line":54,"column":16},"end":{"line":54,"column":22}},"27":{"start":{"line":56,"column":16},"end":{"line":56,"column":41}},"28":{"start":{"line":57,"column":16},"end":{"line":62,"column":19}},"29":{"start":{"line":58,"column":20},"end":{"line":61,"column":21}},"30":{"start":{"line":59,"column":24},"end":{"line":59,"column":70}},"31":{"start":{"line":60,"column":24},"end":{"line":60,"column":36}},"32":{"start":{"line":63,"column":16},"end":{"line":63,"column":22}},"33":{"start":{"line":65,"column":16},"end":{"line":65,"column":41}},"34":{"start":{"line":66,"column":16},"end":{"line":71,"column":19}},"35":{"start":{"line":72,"column":16},"end":{"line":72,"column":22}},"36":{"start":{"line":74,"column":16},"end":{"line":74,"column":55}},"37":{"start":{"line":75,"column":16},"end":{"line":75,"column":22}},"38":{"start":{"line":77,"column":16},"end":{"line":77,"column":53}},"39":{"start":{"line":78,"column":16},"end":{"line":78,"column":22}},"40":{"start":{"line":81,"column":8},"end":{"line":100,"column":9}},"41":{"start":{"line":82,"column":12},"end":{"line":82,"column":28}},"42":{"start":{"line":83,"column":12},"end":{"line":99,"column":14}},"43":{"start":{"line":103,"column":4},"end":{"line":103,"column":17}},"44":{"start":{"line":105,"column":4},"end":{"line":109,"column":5}},"45":{"start":{"line":106,"column":8},"end":{"line":106,"column":23}},"46":{"start":{"line":108,"column":8},"end":{"line":108,"column":37}},"47":{"start":{"line":112,"column":0},"end":{"line":122,"column":2}},"48":{"start":{"line":113,"column":4},"end":{"line":120,"column":7}},"49":{"start":{"line":114,"column":8},"end":{"line":116,"column":9}},"50":{"start":{"line":115,"column":12},"end":{"line":115,"column":38}},"51":{"start":{"line":117,"column":8},"end":{"line":119,"column":11}},"52":{"start":{"line":118,"column":12},"end":{"line":118,"column":30}},"53":{"start":{"line":125,"column":0},"end":{"line":125,"column":23}},"54":{"start":{"line":126,"column":0},"end":{"line":126,"column":33}}},"branchMap":{"1":{"line":11,"type":"binary-expr","locations":[{"start":{"line":11,"column":13},"end":{"line":11,"column":22},"skip":true},{"start":{"line":11,"column":26},"end":{"line":11,"column":37},"skip":true}]},"2":{"line":22,"type":"switch","locations":[{"start":{"line":23,"column":12},"end":{"line":25,"column":22}},{"start":{"line":26,"column":12},"end":{"line":28,"column":22}},{"start":{"line":29,"column":12},"end":{"line":31,"column":22}},{"start":{"line":32,"column":12},"end":{"line":34,"column":22}},{"start":{"line":35,"column":12},"end":{"line":37,"column":22}},{"start":{"line":38,"column":12},"end":{"line":40,"column":22}},{"start":{"line":41,"column":12},"end":{"line":47,"column":22}},{"start":{"line":48,"column":12},"end":{"line":54,"column":22}},{"start":{"line":55,"column":12},"end":{"line":63,"column":22}},{"start":{"line":64,"column":12},"end":{"line":72,"column":22}},{"start":{"line":73,"column":12},"end":{"line":75,"column":22}},{"start":{"line":76,"column":12},"end":{"line":78,"column":22}}]},"3":{"line":58,"type":"if","locations":[{"start":{"line":58,"column":20},"end":{"line":58,"column":20}},{"start":{"line":58,"column":20},"end":{"line":58,"column":20}}]},"4":{"line":58,"type":"binary-expr","locations":[{"start":{"line":58,"column":24},"end":{"line":58,"column":40}},{"start":{"line":58,"column":44},"end":{"line":58,"column":63}}]},"5":{"line":70,"type":"cond-expr","locations":[{"start":{"line":70,"column":46},"end":{"line":70,"column":47}},{"start":{"line":70,"column":50},"end":{"line":70,"column":63}}]},"6":{"line":81,"type":"if","locations":[{"start":{"line":81,"column":8},"end":{"line":81,"column":8}},{"start":{"line":81,"column":8},"end":{"line":81,"column":8}}]},"7":{"line":105,"type":"if","locations":[{"start":{"line":105,"column":4},"end":{"line":105,"column":4}},{"start":{"line":105,"column":4},"end":{"line":105,"column":4}}]},"8":{"line":114,"type":"if","locations":[{"start":{"line":114,"column":8},"end":{"line":114,"column":8}},{"start":{"line":114,"column":8},"end":{"line":114,"column":8}}]}}}} \ No newline at end of file diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/index.html b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/index.html new file mode 100644 index 0000000..353eec9 --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/index.html @@ -0,0 +1,350 @@ + + + + Code coverage report for All files + + + + + + + +
+

Code coverage report for All files

+

+ + Statements: 100% (54 / 54)      + + + Branches: 100% (26 / 26)      + + + Functions: 100% (6 / 6)      + + + Lines: 100% (54 / 54)      + + Ignored: 1 branch      +

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
lib/100%(54 / 54)100%(26 / 26)100%(6 / 6)100%(54 / 54)
+
+
+
+ + + + + + + diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/lib/index.html b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/lib/index.html new file mode 100644 index 0000000..016826c --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/lib/index.html @@ -0,0 +1,350 @@ + + + + Code coverage report for lib/ + + + + + + + +
+

Code coverage report for lib/

+

+ + Statements: 100% (54 / 54)      + + + Branches: 100% (26 / 26)      + + + Functions: 100% (6 / 6)      + + + Lines: 100% (54 / 54)      + + Ignored: 1 branch      +

+
All files » lib/
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js100%(54 / 54)100%(26 / 26)100%(6 / 6)100%(54 / 54)
+
+
+ + + + + + + + diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/lib/index.js.html b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/lib/index.js.html new file mode 100644 index 0000000..ba18edb --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/lib/index.js.html @@ -0,0 +1,700 @@ + + + + Code coverage report for lib/index.js + + + + + + + +
+

Code coverage report for lib/index.js

+

+ + Statements: 100% (54 / 54)      + + + Branches: 100% (26 / 26)      + + + Functions: 100% (6 / 6)      + + + Lines: 100% (54 / 54)      + + Ignored: 1 branch      +

+
All files » lib/ » index.js
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127  +  +  +  +  +  +1 +  +  +  +1 +  +1 +3 +  +3 +424 +424 +  +  +  +424 +  +4 +4 +  +4 +4 +  +3 +3 +  +3 +3 +  +3 +3 +  +3 +3 +  +263 +263 +  +  +  +263 +  +48 +48 +  +  +  +48 +  +48 +48 +591 +48 +48 +  +  +48 +  +23 +23 +  +  +  +  +  +23 +  +2 +2 +  +2 +2 +  +  +424 +7 +7 +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3 +  +3 +2 +  +1 +  +  +  +1 +3 +3 +2 +  +1 +1 +  +  +  +  +  +  +1 +1 + 
/*
+Copyright (c) 2012, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://yuilibrary.com/license/
+*/
+ 
+var fs = require('fs'),
+    path = require('path');
+ 
+/* istanbul ignore next */
+var exists = fs.exists || path.exists;
+ 
+var walkFile = function(str, cb) {
+    var data = [], item;
+ 
+    [ 'end_of_record' ].concat(str.split('\n')).forEach(function(line) {
+        line = line.trim();
+        var allparts = line.split(':'),
+            parts = [allparts.shift(), allparts.join(':')],
+            lines, fn;
+ 
+        switch (parts[0].toUpperCase()) {
+            case 'TN':
+                item.title = parts[1].trim();
+                break;
+            case 'SF':
+                item.file = parts.slice(1).join(':').trim();
+                break;
+            case 'FNF':
+                item.functions.found = Number(parts[1].trim());
+                break;
+            case 'FNH':
+                item.functions.hit = Number(parts[1].trim());
+                break;
+            case 'LF':
+                item.lines.found = Number(parts[1].trim());
+                break;
+            case 'LH':
+                item.lines.hit = Number(parts[1].trim());
+                break;
+            case 'DA':
+                lines = parts[1].split(',');
+                item.lines.details.push({
+                    line: Number(lines[0]),
+                    hit: Number(lines[1])
+                });
+                break;
+            case 'FN':
+                fn = parts[1].split(',');
+                item.functions.details.push({
+                    name: fn[1],
+                    line: Number(fn[0])
+                });
+                break;
+            case 'FNDA':
+                fn = parts[1].split(',');
+                item.functions.details.some(function(i, k) {
+                    if (i.name === fn[1] && i.hit === undefined) {
+                        item.functions.details[k].hit = Number(fn[0]);
+                        return true;
+                    }
+                });
+                break;
+            case 'BRDA':
+                fn = parts[1].split(',');
+                item.branches.details.push({
+                    line: Number(fn[0]),
+                    block: Number(fn[1]),
+                    branch: Number(fn[2]),
+                    taken: ((fn[3] === '-') ? 0 : Number(fn[3]))
+                });
+                break;
+            case 'BRF':
+                item.branches.found = Number(parts[1]);
+                break;
+            case 'BRH':
+                item.branches.hit = Number(parts[1]);
+                break;
+        }
+ 
+        if (line.indexOf('end_of_record') > -1) {
+            data.push(item);
+            item = {
+              lines: {
+                  found: 0,
+                  hit: 0,
+                  details: []
+              },
+              functions: {
+                  hit: 0,
+                  found: 0,
+                  details: []
+              },
+              branches: {
+                hit: 0,
+                found: 0,
+                details: []
+              }
+            };
+        }
+    });
+ 
+    data.shift();
+ 
+    if (data.length) {
+        cb(null, data);
+    } else {
+        cb('Failed to parse string');
+    }
+};
+ 
+var parse = function(file, cb) {
+    exists(file, function(x) {
+        if (!x) {
+            return walkFile(file, cb);
+        }
+        fs.readFile(file, 'utf8', function(err, str) {
+            walkFile(str, cb);
+        });
+    });
+ 
+};
+ 
+ 
+module.exports = parse;
+module.exports.source = walkFile;
+ 
+ +
+ + + + + + + + diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/prettify.css b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/prettify.js b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..ef51e03 --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/lcov-report/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/hm_sunwell/node_modules/lcov-parse/coverage/lcov.info b/hm_sunwell/node_modules/lcov-parse/coverage/lcov.info new file mode 100644 index 0000000..f50be6c --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/coverage/lcov.info @@ -0,0 +1,101 @@ +TN: +SF:/Users/davglass/src/lcov-parse/lib/index.js +FN:13,(anonymous_1) +FN:16,(anonymous_2) +FN:57,(anonymous_3) +FN:112,(anonymous_4) +FN:113,(anonymous_5) +FN:117,(anonymous_6) +FNF:6 +FNH:6 +FNDA:3,(anonymous_1) +FNDA:424,(anonymous_2) +FNDA:591,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:1,(anonymous_6) +DA:7,1 +DA:11,1 +DA:13,1 +DA:14,3 +DA:16,3 +DA:17,424 +DA:18,424 +DA:22,424 +DA:24,4 +DA:25,4 +DA:27,4 +DA:28,4 +DA:30,3 +DA:31,3 +DA:33,3 +DA:34,3 +DA:36,3 +DA:37,3 +DA:39,3 +DA:40,3 +DA:42,263 +DA:43,263 +DA:47,263 +DA:49,48 +DA:50,48 +DA:54,48 +DA:56,48 +DA:57,48 +DA:58,591 +DA:59,48 +DA:60,48 +DA:63,48 +DA:65,23 +DA:66,23 +DA:72,23 +DA:74,2 +DA:75,2 +DA:77,2 +DA:78,2 +DA:81,424 +DA:82,7 +DA:83,7 +DA:103,3 +DA:105,3 +DA:106,2 +DA:108,1 +DA:112,1 +DA:113,3 +DA:114,3 +DA:115,2 +DA:117,1 +DA:118,1 +DA:125,1 +DA:126,1 +LF:54 +LH:54 +BRDA:11,1,0,1 +BRDA:11,1,1,0 +BRDA:22,2,0,4 +BRDA:22,2,1,4 +BRDA:22,2,2,3 +BRDA:22,2,3,3 +BRDA:22,2,4,3 +BRDA:22,2,5,3 +BRDA:22,2,6,263 +BRDA:22,2,7,48 +BRDA:22,2,8,48 +BRDA:22,2,9,23 +BRDA:22,2,10,2 +BRDA:22,2,11,2 +BRDA:58,3,0,48 +BRDA:58,3,1,543 +BRDA:58,4,0,591 +BRDA:58,4,1,53 +BRDA:70,5,0,1 +BRDA:70,5,1,22 +BRDA:81,6,0,7 +BRDA:81,6,1,417 +BRDA:105,7,0,2 +BRDA:105,7,1,1 +BRDA:114,8,0,2 +BRDA:114,8,1,1 +BRF:26 +BRH:26 +end_of_record diff --git a/hm_sunwell/node_modules/lcov-parse/lib/index.js b/hm_sunwell/node_modules/lcov-parse/lib/index.js new file mode 100644 index 0000000..caeae32 --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/lib/index.js @@ -0,0 +1,126 @@ +/* +Copyright (c) 2012, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://yuilibrary.com/license/ +*/ + +var fs = require('fs'), + path = require('path'); + +/* istanbul ignore next */ +var exists = fs.exists || path.exists; + +var walkFile = function(str, cb) { + var data = [], item; + + [ 'end_of_record' ].concat(str.split('\n')).forEach(function(line) { + line = line.trim(); + var allparts = line.split(':'), + parts = [allparts.shift(), allparts.join(':')], + lines, fn; + + switch (parts[0].toUpperCase()) { + case 'TN': + item.title = parts[1].trim(); + break; + case 'SF': + item.file = parts.slice(1).join(':').trim(); + break; + case 'FNF': + item.functions.found = Number(parts[1].trim()); + break; + case 'FNH': + item.functions.hit = Number(parts[1].trim()); + break; + case 'LF': + item.lines.found = Number(parts[1].trim()); + break; + case 'LH': + item.lines.hit = Number(parts[1].trim()); + break; + case 'DA': + lines = parts[1].split(','); + item.lines.details.push({ + line: Number(lines[0]), + hit: Number(lines[1]) + }); + break; + case 'FN': + fn = parts[1].split(','); + item.functions.details.push({ + name: fn[1], + line: Number(fn[0]) + }); + break; + case 'FNDA': + fn = parts[1].split(','); + item.functions.details.some(function(i, k) { + if (i.name === fn[1] && i.hit === undefined) { + item.functions.details[k].hit = Number(fn[0]); + return true; + } + }); + break; + case 'BRDA': + fn = parts[1].split(','); + item.branches.details.push({ + line: Number(fn[0]), + block: Number(fn[1]), + branch: Number(fn[2]), + taken: ((fn[3] === '-') ? 0 : Number(fn[3])) + }); + break; + case 'BRF': + item.branches.found = Number(parts[1]); + break; + case 'BRH': + item.branches.hit = Number(parts[1]); + break; + } + + if (line.indexOf('end_of_record') > -1) { + data.push(item); + item = { + lines: { + found: 0, + hit: 0, + details: [] + }, + functions: { + hit: 0, + found: 0, + details: [] + }, + branches: { + hit: 0, + found: 0, + details: [] + } + }; + } + }); + + data.shift(); + + if (data.length) { + cb(null, data); + } else { + cb('Failed to parse string'); + } +}; + +var parse = function(file, cb) { + exists(file, function(x) { + if (!x) { + return walkFile(file, cb); + } + fs.readFile(file, 'utf8', function(err, str) { + walkFile(str, cb); + }); + }); + +}; + + +module.exports = parse; +module.exports.source = walkFile; diff --git a/hm_sunwell/node_modules/lcov-parse/package.json b/hm_sunwell/node_modules/lcov-parse/package.json new file mode 100644 index 0000000..9077e1b --- /dev/null +++ b/hm_sunwell/node_modules/lcov-parse/package.json @@ -0,0 +1,94 @@ +{ + "_args": [ + [ + "lcov-parse@0.0.10", + "/home/xor/shared_vm/git/node-sunwell/node_modules/coveralls" + ] + ], + "_from": "lcov-parse@0.0.10", + "_id": "lcov-parse@0.0.10", + "_inCache": true, + "_installable": true, + "_location": "/lcov-parse", + "_nodeVersion": "0.12.4", + "_npmUser": { + "email": "davglass@gmail.com", + "name": "davglass" + }, + "_npmVersion": "2.10.1", + "_phantomChildren": {}, + "_requested": { + "name": "lcov-parse", + "raw": "lcov-parse@0.0.10", + "rawSpec": "0.0.10", + "scope": null, + "spec": "0.0.10", + "type": "version" + }, + "_requiredBy": [ + "/coveralls" + ], + "_resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "_shasum": "1b0b8ff9ac9c7889250582b70b71315d9da6d9a3", + "_shrinkwrap": null, + "_spec": "lcov-parse@0.0.10", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/coveralls", + "author": { + "email": "davglass@gmail.com", + "name": "Dav Glass" + }, + "bugs": { + "url": "http://github.com/davglass/lcov-parse/issues" + }, + "contributors": [ + { + "name": "Alan Gutierrez", + "email": "alan@prettyrobots.com" + }, + { + "name": "Gerard Escalante", + "email": "gerard@saygo.ca" + } + ], + "dependencies": {}, + "description": "Parse lcov results files and return JSON", + "devDependencies": { + "istanbul": "^0.2.10", + "jshint": "^2.5.1", + "vows": "*", + "yui-lint": "~0.1.1" + }, + "directories": {}, + "dist": { + "shasum": "1b0b8ff9ac9c7889250582b70b71315d9da6d9a3", + "tarball": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz" + }, + "gitHead": "aee8d290e66440046fc9aebbc704f68a9d8e1b98", + "homepage": "https://github.com/davglass/lcov-parse#readme", + "license": "BSD-3-Clause", + "main": "./lib/index", + "maintainers": [ + { + "name": "davglass", + "email": "davglass@gmail.com" + } + ], + "name": "lcov-parse", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/davglass/lcov-parse.git" + }, + "scripts": { + "pretest": "jshint --config ./node_modules/yui-lint/jshint.json ./lib/", + "test": "istanbul cover --print both ./node_modules/vows/bin/vows -- --spec ./tests/*.js" + }, + "tags": [ + "coverage", + "json", + "lcov", + "parser" + ], + "version": "0.0.10" +} diff --git a/hm_sunwell/node_modules/levn/LICENSE b/hm_sunwell/node_modules/levn/LICENSE new file mode 100644 index 0000000..525b118 --- /dev/null +++ b/hm_sunwell/node_modules/levn/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) George Zahariev + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/levn/README.md b/hm_sunwell/node_modules/levn/README.md new file mode 100644 index 0000000..bb9ffea --- /dev/null +++ b/hm_sunwell/node_modules/levn/README.md @@ -0,0 +1,196 @@ +# levn [![Build Status](https://travis-ci.org/gkz/levn.png)](https://travis-ci.org/gkz/levn) +__Light ECMAScript (JavaScript) Value Notation__ +Levn is a library which allows you to parse a string into a JavaScript value based on an expected type. It is meant for short amounts of human entered data (eg. config files, command line arguments). + +Levn aims to concisely describe JavaScript values in text, and allow for the extraction and validation of those values. Levn uses [type-check](https://github.com/gkz/type-check) for its type format, and to validate the results. MIT license. Version 0.3.0. + +__How is this different than JSON?__ levn is meant to be written by humans only, is (due to the previous point) much more concise, can be validated against supplied types, has regex and date literals, and can easily be extended with custom types. On the other hand, it is probably slower and thus less efficient at transporting large amounts of data, which is fine since this is not its purpose. + + npm install levn + +For updates on levn, [follow me on twitter](https://twitter.com/gkzahariev). + + +## Quick Examples + +```js +var parse = require('levn').parse; +parse('Number', '2'); // 2 +parse('String', '2'); // '2' +parse('String', 'levn'); // 'levn' +parse('String', 'a b'); // 'a b' +parse('Boolean', 'true'); // true + +parse('Date', '#2011-11-11#'); // (Date object) +parse('Date', '2011-11-11'); // (Date object) +parse('RegExp', '/[a-z]/gi'); // /[a-z]/gi +parse('RegExp', 're'); // /re/ +parse('Int', '2'); // 2 + +parse('Number | String', 'str'); // 'str' +parse('Number | String', '2'); // 2 + +parse('[Number]', '[1,2,3]'); // [1,2,3] +parse('(String, Boolean)', '(hi, false)'); // ['hi', false] +parse('{a: String, b: Number}', '{a: str, b: 2}'); // {a: 'str', b: 2} + +// at the top level, you can ommit surrounding delimiters +parse('[Number]', '1,2,3'); // [1,2,3] +parse('(String, Boolean)', 'hi, false'); // ['hi', false] +parse('{a: String, b: Number}', 'a: str, b: 2'); // {a: 'str', b: 2} + +// wildcard - auto choose type +parse('*', '[hi,(null,[42]),{k: true}]'); // ['hi', [null, [42]], {k: true}] +``` +## Usage + +`require('levn');` returns an object that exposes three properties. `VERSION` is the current version of the library as a string. `parse` and `parsedTypeParse` are functions. + +```js +// parse(type, input, options); +parse('[Number]', '1,2,3'); // [1, 2, 3] + +// parsedTypeParse(parsedType, input, options); +var parsedType = require('type-check').parseType('[Number]'); +parsedTypeParse(parsedType, '1,2,3'); // [1, 2, 3] +``` + +### parse(type, input, options) + +`parse` casts the string `input` into a JavaScript value according to the specified `type` in the [type format](https://github.com/gkz/type-check#type-format) (and taking account the optional `options`) and returns the resulting JavaScript value. + +##### arguments +* type - `String` - the type written in the [type format](https://github.com/gkz/type-check#type-format) which to check against +* input - `String` - the value written in the [levn format](#levn-format) +* options - `Maybe Object` - an optional parameter specifying additional [options](#options) + +##### returns +`*` - the resulting JavaScript value + +##### example +```js +parse('[Number]', '1,2,3'); // [1, 2, 3] +``` + +### parsedTypeParse(parsedType, input, options) + +`parsedTypeParse` casts the string `input` into a JavaScript value according to the specified `type` which has already been parsed (and taking account the optional `options`) and returns the resulting JavaScript value. You can parse a type using the [type-check](https://github.com/gkz/type-check) library's `parseType` function. + +##### arguments +* type - `Object` - the type in the parsed type format which to check against +* input - `String` - the value written in the [levn format](#levn-format) +* options - `Maybe Object` - an optional parameter specifying additional [options](#options) + +##### returns +`*` - the resulting JavaScript value + +##### example +```js +var parsedType = require('type-check').parseType('[Number]'); +parsedTypeParse(parsedType, '1,2,3'); // [1, 2, 3] +``` + +## Levn Format + +Levn can use the type information you provide to choose the appropriate value to produce from the input. For the same input, it will choose a different output value depending on the type provided. For example, `parse('Number', '2')` will produce the number `2`, but `parse('String', '2')` will produce the string `"2"`. + +If you do not provide type information, and simply use `*`, levn will parse the input according the unambiguous "explicit" mode, which we will now detail - you can also set the `explicit` option to true manually in the [options](#options). + +* `"string"`, `'string'` are parsed as a String, eg. `"a msg"` is `"a msg"` +* `#date#` is parsed as a Date, eg. `#2011-11-11#` is `new Date('2011-11-11')` +* `/regexp/flags` is parsed as a RegExp, eg. `/re/gi` is `/re/gi` +* `undefined`, `null`, `NaN`, `true`, and `false` are all their JavaScript equivalents +* `[element1, element2, etc]` is an Array, and the casting procedure is recursively applied to each element. Eg. `[1,2,3]` is `[1,2,3]`. +* `(element1, element2, etc)` is an tuple, and the casting procedure is recursively applied to each element. Eg. `(1, a)` is `(1, a)` (is `[1, 'a']`). +* `{key1: val1, key2: val2, ...}` is an Object, and the casting procedure is recursively applied to each property. Eg. `{a: 1, b: 2}` is `{a: 1, b: 2}`. +* Any test which does not fall under the above, and which does not contain special characters (`[``]``(``)``{``}``:``,`) is a string, eg. `$12- blah` is `"$12- blah"`. + +If you do provide type information, you can make your input more concise as the program already has some information about what it expects. Please see the [type format](https://github.com/gkz/type-check#type-format) section of [type-check](https://github.com/gkz/type-check) for more information about how to specify types. There are some rules about what levn can do with the information: + +* If a String is expected, and only a String, all characters of the input (including any special ones) will become part of the output. Eg. `[({})]` is `"[({})]"`, and `"hi"` is `'"hi"'`. +* If a Date is expected, the surrounding `#` can be omitted from date literals. Eg. `2011-11-11` is `new Date('2011-11-11')`. +* If a RegExp is expected, no flags need to be specified, and the regex is not using any of the special characters,the opening and closing `/` can be omitted - this will have the affect of setting the source of the regex to the input. Eg. `regex` is `/regex/`. +* If an Array is expected, and it is the root node (at the top level), the opening `[` and closing `]` can be omitted. Eg. `1,2,3` is `[1,2,3]`. +* If a tuple is expected, and it is the root node (at the top level), the opening `(` and closing `)` can be omitted. Eg. `1, a` is `(1, a)` (is `[1, 'a']`). +* If an Object is expected, and it is the root node (at the top level), the opening `{` and closing `}` can be omitted. Eg `a: 1, b: 2` is `{a: 1, b: 2}`. + +If you list multiple types (eg. `Number | String`), it will first attempt to cast to the first type and then validate - if the validation fails it will move on to the next type and so forth, left to right. You must be careful as some types will succeed with any input, such as String. Thus put String at the end of your list. In non-explicit mode, Date and RegExp will succeed with a large variety of input - also be careful with these and list them near the end if not last in your list. + +Whitespace between special characters and elements is inconsequential. + +## Options + +Options is an object. It is an optional parameter to the `parse` and `parsedTypeParse` functions. + +### Explicit + +A `Boolean`. By default it is `false`. + +__Example:__ + +```js +parse('RegExp', 're', {explicit: false}); // /re/ +parse('RegExp', 're', {explicit: true}); // Error: ... does not type check... +parse('RegExp | String', 're', {explicit: true}); // 're' +``` + +`explicit` sets whether to be in explicit mode or not. Using `*` automatically activates explicit mode. For more information, read the [levn format](#levn-format) section. + +### customTypes + +An `Object`. Empty `{}` by default. + +__Example:__ + +```js +var options = { + customTypes: { + Even: { + typeOf: 'Number', + validate: function (x) { + return x % 2 === 0; + }, + cast: function (x) { + return {type: 'Just', value: parseInt(x)}; + } + } + } +} +parse('Even', '2', options); // 2 +parse('Even', '3', options); // Error: Value: "3" does not type check... +``` + +__Another Example:__ +```js +function Person(name, age){ + this.name = name; + this.age = age; +} +var options = { + customTypes: { + Person: { + typeOf: 'Object', + validate: function (x) { + x instanceof Person; + }, + cast: function (value, options, typesCast) { + var name, age; + if ({}.toString.call(value).slice(8, -1) !== 'Object') { + return {type: 'Nothing'}; + } + name = typesCast(value.name, [{type: 'String'}], options); + age = typesCast(value.age, [{type: 'Numger'}], options); + return {type: 'Just', value: new Person(name, age)}; + } + } +} +parse('Person', '{name: Laura, age: 25}', options); // Person {name: 'Laura', age: 25} +``` + +`customTypes` is an object whose keys are the name of the types, and whose values are an object with three properties, `typeOf`, `validate`, and `cast`. For more information about `typeOf` and `validate`, please see the [custom types](https://github.com/gkz/type-check#custom-types) section of type-check. + +`cast` is a function which receives three arguments, the value under question, options, and the typesCast function. In `cast`, attempt to cast the value into the specified type. If you are successful, return an object in the format `{type: 'Just', value: CAST-VALUE}`, if you know it won't work, return `{type: 'Nothing'}`. You can use the `typesCast` function to cast any child values. Remember to pass `options` to it. In your function you can also check for `options.explicit` and act accordingly. + +## Technical About + +`levn` is written in [LiveScript](http://livescript.net/) - a language that compiles to JavaScript. It uses [type-check](https://github.com/gkz/type-check) to both parse types and validate values. It also uses the [prelude.ls](http://preludels.com/) library. diff --git a/hm_sunwell/node_modules/levn/lib/cast.js b/hm_sunwell/node_modules/levn/lib/cast.js new file mode 100644 index 0000000..411e29d --- /dev/null +++ b/hm_sunwell/node_modules/levn/lib/cast.js @@ -0,0 +1,298 @@ +// Generated by LiveScript 1.4.0 +(function(){ + var parsedTypeCheck, types, toString$ = {}.toString; + parsedTypeCheck = require('type-check').parsedTypeCheck; + types = { + '*': function(value, options){ + switch (toString$.call(value).slice(8, -1)) { + case 'Array': + return typeCast(value, { + type: 'Array' + }, options); + case 'Object': + return typeCast(value, { + type: 'Object' + }, options); + default: + return { + type: 'Just', + value: typesCast(value, [ + { + type: 'Undefined' + }, { + type: 'Null' + }, { + type: 'NaN' + }, { + type: 'Boolean' + }, { + type: 'Number' + }, { + type: 'Date' + }, { + type: 'RegExp' + }, { + type: 'Array' + }, { + type: 'Object' + }, { + type: 'String' + } + ], (options.explicit = true, options)) + }; + } + }, + Undefined: function(it){ + if (it === 'undefined' || it === void 8) { + return { + type: 'Just', + value: void 8 + }; + } else { + return { + type: 'Nothing' + }; + } + }, + Null: function(it){ + if (it === 'null') { + return { + type: 'Just', + value: null + }; + } else { + return { + type: 'Nothing' + }; + } + }, + NaN: function(it){ + if (it === 'NaN') { + return { + type: 'Just', + value: NaN + }; + } else { + return { + type: 'Nothing' + }; + } + }, + Boolean: function(it){ + if (it === 'true') { + return { + type: 'Just', + value: true + }; + } else if (it === 'false') { + return { + type: 'Just', + value: false + }; + } else { + return { + type: 'Nothing' + }; + } + }, + Number: function(it){ + return { + type: 'Just', + value: +it + }; + }, + Int: function(it){ + return { + type: 'Just', + value: +it + }; + }, + Float: function(it){ + return { + type: 'Just', + value: +it + }; + }, + Date: function(value, options){ + var that; + if (that = /^\#([\s\S]*)\#$/.exec(value)) { + return { + type: 'Just', + value: new Date(+that[1] || that[1]) + }; + } else if (options.explicit) { + return { + type: 'Nothing' + }; + } else { + return { + type: 'Just', + value: new Date(+value || value) + }; + } + }, + RegExp: function(value, options){ + var that; + if (that = /^\/([\s\S]*)\/([gimy]*)$/.exec(value)) { + return { + type: 'Just', + value: new RegExp(that[1], that[2]) + }; + } else if (options.explicit) { + return { + type: 'Nothing' + }; + } else { + return { + type: 'Just', + value: new RegExp(value) + }; + } + }, + Array: function(value, options){ + return castArray(value, { + of: [{ + type: '*' + }] + }, options); + }, + Object: function(value, options){ + return castFields(value, { + of: {} + }, options); + }, + String: function(it){ + var that; + if (toString$.call(it).slice(8, -1) !== 'String') { + return { + type: 'Nothing' + }; + } + if (that = it.match(/^'([\s\S]*)'$/)) { + return { + type: 'Just', + value: that[1].replace(/\\'/g, "'") + }; + } else if (that = it.match(/^"([\s\S]*)"$/)) { + return { + type: 'Just', + value: that[1].replace(/\\"/g, '"') + }; + } else { + return { + type: 'Just', + value: it + }; + } + } + }; + function castArray(node, type, options){ + var typeOf, element; + if (toString$.call(node).slice(8, -1) !== 'Array') { + return { + type: 'Nothing' + }; + } + typeOf = type.of; + return { + type: 'Just', + value: (function(){ + var i$, ref$, len$, results$ = []; + for (i$ = 0, len$ = (ref$ = node).length; i$ < len$; ++i$) { + element = ref$[i$]; + results$.push(typesCast(element, typeOf, options)); + } + return results$; + }()) + }; + } + function castTuple(node, type, options){ + var result, i, i$, ref$, len$, types, cast; + if (toString$.call(node).slice(8, -1) !== 'Array') { + return { + type: 'Nothing' + }; + } + result = []; + i = 0; + for (i$ = 0, len$ = (ref$ = type.of).length; i$ < len$; ++i$) { + types = ref$[i$]; + cast = typesCast(node[i], types, options); + if (toString$.call(cast).slice(8, -1) !== 'Undefined') { + result.push(cast); + } + i++; + } + if (node.length <= i) { + return { + type: 'Just', + value: result + }; + } else { + return { + type: 'Nothing' + }; + } + } + function castFields(node, type, options){ + var typeOf, key, value; + if (toString$.call(node).slice(8, -1) !== 'Object') { + return { + type: 'Nothing' + }; + } + typeOf = type.of; + return { + type: 'Just', + value: (function(){ + var ref$, resultObj$ = {}; + for (key in ref$ = node) { + value = ref$[key]; + resultObj$[typesCast(key, [{ + type: 'String' + }], options)] = typesCast(value, typeOf[key] || [{ + type: '*' + }], options); + } + return resultObj$; + }()) + }; + } + function typeCast(node, typeObj, options){ + var type, structure, castFunc, ref$; + type = typeObj.type, structure = typeObj.structure; + if (type) { + castFunc = ((ref$ = options.customTypes[type]) != null ? ref$.cast : void 8) || types[type]; + if (!castFunc) { + throw new Error("Type not defined: " + type + "."); + } + return castFunc(node, options, typesCast); + } else { + switch (structure) { + case 'array': + return castArray(node, typeObj, options); + case 'tuple': + return castTuple(node, typeObj, options); + case 'fields': + return castFields(node, typeObj, options); + } + } + } + function typesCast(node, types, options){ + var i$, len$, type, ref$, valueType, value; + for (i$ = 0, len$ = types.length; i$ < len$; ++i$) { + type = types[i$]; + ref$ = typeCast(node, type, options), valueType = ref$.type, value = ref$.value; + if (valueType === 'Nothing') { + continue; + } + if (parsedTypeCheck([type], value, { + customTypes: options.customTypes + })) { + return value; + } + } + throw new Error("Value " + JSON.stringify(node) + " does not type check against " + JSON.stringify(types) + "."); + } + module.exports = typesCast; +}).call(this); diff --git a/hm_sunwell/node_modules/levn/lib/coerce.js b/hm_sunwell/node_modules/levn/lib/coerce.js new file mode 100644 index 0000000..027b6da --- /dev/null +++ b/hm_sunwell/node_modules/levn/lib/coerce.js @@ -0,0 +1,285 @@ +// Generated by LiveScript 1.2.0 +(function(){ + var parsedTypeCheck, types, toString$ = {}.toString; + parsedTypeCheck = require('type-check').parsedTypeCheck; + types = { + '*': function(it){ + switch (toString$.call(it).slice(8, -1)) { + case 'Array': + return coerceType(it, { + type: 'Array' + }); + case 'Object': + return coerceType(it, { + type: 'Object' + }); + default: + return { + type: 'Just', + value: coerceTypes(it, [ + { + type: 'Undefined' + }, { + type: 'Null' + }, { + type: 'NaN' + }, { + type: 'Boolean' + }, { + type: 'Number' + }, { + type: 'Date' + }, { + type: 'RegExp' + }, { + type: 'Array' + }, { + type: 'Object' + }, { + type: 'String' + } + ], { + explicit: true + }) + }; + } + }, + Undefined: function(it){ + if (it === 'undefined' || it === void 8) { + return { + type: 'Just', + value: void 8 + }; + } else { + return { + type: 'Nothing' + }; + } + }, + Null: function(it){ + if (it === 'null') { + return { + type: 'Just', + value: null + }; + } else { + return { + type: 'Nothing' + }; + } + }, + NaN: function(it){ + if (it === 'NaN') { + return { + type: 'Just', + value: NaN + }; + } else { + return { + type: 'Nothing' + }; + } + }, + Boolean: function(it){ + if (it === 'true') { + return { + type: 'Just', + value: true + }; + } else if (it === 'false') { + return { + type: 'Just', + value: false + }; + } else { + return { + type: 'Nothing' + }; + } + }, + Number: function(it){ + return { + type: 'Just', + value: +it + }; + }, + Int: function(it){ + return { + type: 'Just', + value: parseInt(it) + }; + }, + Float: function(it){ + return { + type: 'Just', + value: parseFloat(it) + }; + }, + Date: function(value, options){ + var that; + if (that = /^\#(.*)\#$/.exec(value)) { + return { + type: 'Just', + value: new Date(+that[1] || that[1]) + }; + } else if (options.explicit) { + return { + type: 'Nothing' + }; + } else { + return { + type: 'Just', + value: new Date(+value || value) + }; + } + }, + RegExp: function(value, options){ + var that; + if (that = /^\/(.*)\/([gimy]*)$/.exec(value)) { + return { + type: 'Just', + value: new RegExp(that[1], that[2]) + }; + } else if (options.explicit) { + return { + type: 'Nothing' + }; + } else { + return { + type: 'Just', + value: new RegExp(value) + }; + } + }, + Array: function(it){ + return coerceArray(it, { + of: [{ + type: '*' + }] + }); + }, + Object: function(it){ + return coerceFields(it, { + of: {} + }); + }, + String: function(it){ + var that; + if (toString$.call(it).slice(8, -1) !== 'String') { + return { + type: 'Nothing' + }; + } + if (that = it.match(/^'(.*)'$/)) { + return { + type: 'Just', + value: that[1] + }; + } else if (that = it.match(/^"(.*)"$/)) { + return { + type: 'Just', + value: that[1] + }; + } else { + return { + type: 'Just', + value: it + }; + } + } + }; + function coerceArray(node, type){ + var typeOf, element; + if (toString$.call(node).slice(8, -1) !== 'Array') { + return { + type: 'Nothing' + }; + } + typeOf = type.of; + return { + type: 'Just', + value: (function(){ + var i$, ref$, len$, results$ = []; + for (i$ = 0, len$ = (ref$ = node).length; i$ < len$; ++i$) { + element = ref$[i$]; + results$.push(coerceTypes(element, typeOf)); + } + return results$; + }()) + }; + } + function coerceTuple(node, type){ + var result, i$, ref$, len$, i, types, that; + if (toString$.call(node).slice(8, -1) !== 'Array') { + return { + type: 'Nothing' + }; + } + result = []; + for (i$ = 0, len$ = (ref$ = type.of).length; i$ < len$; ++i$) { + i = i$; + types = ref$[i$]; + if (that = coerceTypes(node[i], types)) { + result.push(that); + } + } + return { + type: 'Just', + value: result + }; + } + function coerceFields(node, type){ + var typeOf, key, value; + if (toString$.call(node).slice(8, -1) !== 'Object') { + return { + type: 'Nothing' + }; + } + typeOf = type.of; + return { + type: 'Just', + value: (function(){ + var ref$, results$ = {}; + for (key in ref$ = node) { + value = ref$[key]; + results$[key] = coerceTypes(value, typeOf[key] || [{ + type: '*' + }]); + } + return results$; + }()) + }; + } + function coerceType(node, typeObj, options){ + var type, structure, coerceFunc; + type = typeObj.type, structure = typeObj.structure; + if (type) { + coerceFunc = types[type]; + return coerceFunc(node, options); + } else { + switch (structure) { + case 'array': + return coerceArray(node, typeObj); + case 'tuple': + return coerceTuple(node, typeObj); + case 'fields': + return coerceFields(node, typeObj); + } + } + } + function coerceTypes(node, types, options){ + var i$, len$, type, ref$, valueType, value; + for (i$ = 0, len$ = types.length; i$ < len$; ++i$) { + type = types[i$]; + ref$ = coerceType(node, type, options), valueType = ref$.type, value = ref$.value; + if (valueType === 'Nothing') { + continue; + } + if (parsedTypeCheck([type], value)) { + return value; + } + } + throw new Error("Value " + JSON.stringify(node) + " does not type check against " + JSON.stringify(types) + "."); + } + module.exports = coerceTypes; +}).call(this); diff --git a/hm_sunwell/node_modules/levn/lib/index.js b/hm_sunwell/node_modules/levn/lib/index.js new file mode 100644 index 0000000..4adae30 --- /dev/null +++ b/hm_sunwell/node_modules/levn/lib/index.js @@ -0,0 +1,22 @@ +// Generated by LiveScript 1.4.0 +(function(){ + var parseString, cast, parseType, VERSION, parsedTypeParse, parse; + parseString = require('./parse-string'); + cast = require('./cast'); + parseType = require('type-check').parseType; + VERSION = '0.3.0'; + parsedTypeParse = function(parsedType, string, options){ + options == null && (options = {}); + options.explicit == null && (options.explicit = false); + options.customTypes == null && (options.customTypes = {}); + return cast(parseString(parsedType, string, options), parsedType, options); + }; + parse = function(type, string, options){ + return parsedTypeParse(parseType(type), string, options); + }; + module.exports = { + VERSION: VERSION, + parse: parse, + parsedTypeParse: parsedTypeParse + }; +}).call(this); diff --git a/hm_sunwell/node_modules/levn/lib/parse-string.js b/hm_sunwell/node_modules/levn/lib/parse-string.js new file mode 100644 index 0000000..d573975 --- /dev/null +++ b/hm_sunwell/node_modules/levn/lib/parse-string.js @@ -0,0 +1,113 @@ +// Generated by LiveScript 1.4.0 +(function(){ + var reject, special, tokenRegex; + reject = require('prelude-ls').reject; + function consumeOp(tokens, op){ + if (tokens[0] === op) { + return tokens.shift(); + } else { + throw new Error("Expected '" + op + "', but got '" + tokens[0] + "' instead in " + JSON.stringify(tokens) + "."); + } + } + function maybeConsumeOp(tokens, op){ + if (tokens[0] === op) { + return tokens.shift(); + } + } + function consumeList(tokens, arg$, hasDelimiters){ + var open, close, result, untilTest; + open = arg$[0], close = arg$[1]; + if (hasDelimiters) { + consumeOp(tokens, open); + } + result = []; + untilTest = "," + (hasDelimiters ? close : ''); + while (tokens.length && (hasDelimiters && tokens[0] !== close)) { + result.push(consumeElement(tokens, untilTest)); + maybeConsumeOp(tokens, ','); + } + if (hasDelimiters) { + consumeOp(tokens, close); + } + return result; + } + function consumeArray(tokens, hasDelimiters){ + return consumeList(tokens, ['[', ']'], hasDelimiters); + } + function consumeTuple(tokens, hasDelimiters){ + return consumeList(tokens, ['(', ')'], hasDelimiters); + } + function consumeFields(tokens, hasDelimiters){ + var result, untilTest, key; + if (hasDelimiters) { + consumeOp(tokens, '{'); + } + result = {}; + untilTest = "," + (hasDelimiters ? '}' : ''); + while (tokens.length && (!hasDelimiters || tokens[0] !== '}')) { + key = consumeValue(tokens, ':'); + consumeOp(tokens, ':'); + result[key] = consumeElement(tokens, untilTest); + maybeConsumeOp(tokens, ','); + } + if (hasDelimiters) { + consumeOp(tokens, '}'); + } + return result; + } + function consumeValue(tokens, untilTest){ + var out; + untilTest == null && (untilTest = ''); + out = ''; + while (tokens.length && -1 === untilTest.indexOf(tokens[0])) { + out += tokens.shift(); + } + return out; + } + function consumeElement(tokens, untilTest){ + switch (tokens[0]) { + case '[': + return consumeArray(tokens, true); + case '(': + return consumeTuple(tokens, true); + case '{': + return consumeFields(tokens, true); + default: + return consumeValue(tokens, untilTest); + } + } + function consumeTopLevel(tokens, types, options){ + var ref$, type, structure, origTokens, result, finalResult, x$, y$; + ref$ = types[0], type = ref$.type, structure = ref$.structure; + origTokens = tokens.concat(); + if (!options.explicit && types.length === 1 && ((!type && structure) || (type === 'Array' || type === 'Object'))) { + result = structure === 'array' || type === 'Array' + ? consumeArray(tokens, tokens[0] === '[') + : structure === 'tuple' + ? consumeTuple(tokens, tokens[0] === '(') + : consumeFields(tokens, tokens[0] === '{'); + finalResult = tokens.length ? consumeElement(structure === 'array' || type === 'Array' + ? (x$ = origTokens, x$.unshift('['), x$.push(']'), x$) + : (y$ = origTokens, y$.unshift('('), y$.push(')'), y$)) : result; + } else { + finalResult = consumeElement(tokens); + } + return finalResult; + } + special = /\[\]\(\)}{:,/.source; + tokenRegex = RegExp('("(?:\\\\"|[^"])*")|(\'(?:\\\\\'|[^\'])*\')|(/(?:\\\\/|[^/])*/[a-zA-Z]*)|(#.*#)|([' + special + '])|([^\\s' + special + '](?:\\s*[^\\s' + special + ']+)*)|\\s*'); + module.exports = function(types, string, options){ + var tokens, node; + options == null && (options = {}); + if (!options.explicit && types.length === 1 && types[0].type === 'String') { + return "'" + string.replace(/\\'/g, "\\\\'") + "'"; + } + tokens = reject(not$, string.split(tokenRegex)); + node = consumeTopLevel(tokens, types, options); + if (!node) { + throw new Error("Error parsing '" + string + "'."); + } + return node; + }; + function not$(x){ return !x; } +}).call(this); diff --git a/hm_sunwell/node_modules/levn/lib/parse.js b/hm_sunwell/node_modules/levn/lib/parse.js new file mode 100644 index 0000000..2beff0f --- /dev/null +++ b/hm_sunwell/node_modules/levn/lib/parse.js @@ -0,0 +1,102 @@ +// Generated by LiveScript 1.2.0 +(function(){ + var reject, special, tokenRegex; + reject = require('prelude-ls').reject; + function consumeOp(tokens, op){ + if (tokens[0] === op) { + return tokens.shift(); + } else { + throw new Error("Expected '" + op + "', but got '" + tokens[0] + "' instead in " + JSON.stringify(tokens) + "."); + } + } + function maybeConsumeOp(tokens, op){ + if (tokens[0] === op) { + return tokens.shift(); + } + } + function consumeList(tokens, delimiters, hasDelimiters){ + var result; + if (hasDelimiters) { + consumeOp(tokens, delimiters[0]); + } + result = []; + while (tokens.length && tokens[0] !== delimiters[1]) { + result.push(consumeElement(tokens)); + maybeConsumeOp(tokens, ','); + } + if (hasDelimiters) { + consumeOp(tokens, delimiters[1]); + } + return result; + } + function consumeArray(tokens, hasDelimiters){ + return consumeList(tokens, ['[', ']'], hasDelimiters); + } + function consumeTuple(tokens, hasDelimiters){ + return consumeList(tokens, ['(', ')'], hasDelimiters); + } + function consumeFields(tokens, hasDelimiters){ + var result, key; + if (hasDelimiters) { + consumeOp(tokens, '{'); + } + result = {}; + while (tokens.length && (!hasDelimiters || tokens[0] !== '}')) { + key = tokens.shift(); + consumeOp(tokens, ':'); + result[key] = consumeElement(tokens); + maybeConsumeOp(tokens, ','); + } + if (hasDelimiters) { + consumeOp(tokens, '}'); + } + return result; + } + function consumeElement(tokens){ + switch (tokens[0]) { + case '[': + return consumeArray(tokens, true); + case '(': + return consumeTuple(tokens, true); + case '{': + return consumeFields(tokens, true); + default: + return tokens.shift(); + } + } + function consumeTopLevel(tokens, types){ + var ref$, type, structure, origTokens, result, finalResult, x$, y$; + ref$ = types[0], type = ref$.type, structure = ref$.structure; + origTokens = tokens.concat(); + if (types.length === 1 && (structure || (type === 'Array' || type === 'Object'))) { + result = structure === 'array' || type === 'Array' + ? consumeArray(tokens, tokens[0] === '[') + : structure === 'tuple' + ? consumeTuple(tokens, tokens[0] === '(') + : consumeFields(tokens, tokens[0] === '{'); + finalResult = tokens.length ? consumeElement(structure === 'array' || type === 'Array' + ? (x$ = origTokens, x$.unshift('['), x$.push(']'), x$) + : (y$ = origTokens, y$.unshift('('), y$.push(')'), y$)) : result; + } else { + finalResult = consumeElement(tokens); + } + if (tokens.length && origTokens.length) { + throw new Error("Unable to parse " + JSON.stringify(origTokens) + " of type " + JSON.stringify(types) + "."); + } else { + return finalResult; + } + } + special = /\[\]\(\)}{:,/.source; + tokenRegex = RegExp('("(?:[^"]|\\\\")*")|(\'(?:[^\']|\\\\\')*\')|(#.*#)|(/(?:\\\\/|[^/])*/[gimy]*)|([' + special + '])|([^\\s' + special + ']+)|\\s*'); + module.exports = function(string, types){ + var tokens, node; + tokens = reject(function(it){ + return !it || /^\s+$/.test(it); + }, string.split(tokenRegex)); + node = consumeTopLevel(tokens, types); + if (!node) { + throw new Error("Error parsing '" + string + "'."); + } + return node; + }; +}).call(this); diff --git a/hm_sunwell/node_modules/levn/package.json b/hm_sunwell/node_modules/levn/package.json new file mode 100644 index 0000000..22c6831 --- /dev/null +++ b/hm_sunwell/node_modules/levn/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + "levn@~0.3.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/optionator" + ] + ], + "_from": "levn@>=0.3.0 <0.4.0", + "_id": "levn@0.3.0", + "_inCache": true, + "_installable": true, + "_location": "/levn", + "_nodeVersion": "4.2.4", + "_npmUser": { + "email": "z@georgezahariev.com", + "name": "gkz" + }, + "_npmVersion": "2.14.12", + "_phantomChildren": {}, + "_requested": { + "name": "levn", + "raw": "levn@~0.3.0", + "rawSpec": "~0.3.0", + "scope": null, + "spec": ">=0.3.0 <0.4.0", + "type": "range" + }, + "_requiredBy": [ + "/optionator" + ], + "_resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "_shasum": "3b09924edf9f083c0490fdd4c0bc4421e04764ee", + "_shrinkwrap": null, + "_spec": "levn@~0.3.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/optionator", + "author": { + "email": "z@georgezahariev.com", + "name": "George Zahariev" + }, + "bugs": { + "url": "https://github.com/gkz/levn/issues" + }, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "description": "Light ECMAScript (JavaScript) Value Notation - human written, concise, typed, flexible", + "devDependencies": { + "istanbul": "~0.4.1", + "livescript": "~1.4.0", + "mocha": "~2.3.4" + }, + "directories": {}, + "dist": { + "shasum": "3b09924edf9f083c0490fdd4c0bc4421e04764ee", + "tarball": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "LICENSE", + "README.md", + "lib" + ], + "gitHead": "a92b9acf928282ba81134b4ae8e6a5f29e1f5e1e", + "homepage": "https://github.com/gkz/levn", + "keywords": [ + "concise", + "ecmascript", + "flexible", + "human", + "json", + "levn", + "light", + "notation", + "typed", + "typed", + "value" + ], + "license": "MIT", + "main": "./lib/", + "maintainers": [ + { + "name": "gkz", + "email": "z@georgezahariev.com" + } + ], + "name": "levn", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/gkz/levn.git" + }, + "scripts": { + "test": "make test" + }, + "version": "0.3.0" +} diff --git a/hm_sunwell/node_modules/log-driver/.npmignore b/hm_sunwell/node_modules/log-driver/.npmignore new file mode 100644 index 0000000..748f2ed --- /dev/null +++ b/hm_sunwell/node_modules/log-driver/.npmignore @@ -0,0 +1,4 @@ +test +waltz.jpg +logo.png + diff --git a/hm_sunwell/node_modules/log-driver/.travis.yml b/hm_sunwell/node_modules/log-driver/.travis.yml new file mode 100644 index 0000000..26da641 --- /dev/null +++ b/hm_sunwell/node_modules/log-driver/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - 0.8 + - 0.9 + - "0.10" + diff --git a/hm_sunwell/node_modules/log-driver/Makefile b/hm_sunwell/node_modules/log-driver/Makefile new file mode 100644 index 0000000..bc70d7f --- /dev/null +++ b/hm_sunwell/node_modules/log-driver/Makefile @@ -0,0 +1,20 @@ +REPORTER = spec +test: + @NODE_ENV=test ./node_modules/.bin/mocha -b --reporter $(REPORTER) --check-leaks + +lint: + ./node_modules/.bin/jshint ./test ./index.js + +test-cov: + $(MAKE) lint + @NODE_ENV=test ./node_modules/.bin/istanbul cover \ + ./node_modules/mocha/bin/_mocha -- -R spec --check-leaks + +test-coveralls: + echo TRAVIS_JOB_ID $(TRAVIS_JOB_ID) + $(MAKE) test + @NODE_ENV=test ./node_modules/.bin/istanbul cover \ + ./node_modules/mocha/bin/_mocha --check-leaks --report lcovonly -- -R spec && \ + cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js || true + +.PHONY: test diff --git a/hm_sunwell/node_modules/log-driver/README.md b/hm_sunwell/node_modules/log-driver/README.md new file mode 100644 index 0000000..d2a2f3a --- /dev/null +++ b/hm_sunwell/node_modules/log-driver/README.md @@ -0,0 +1,99 @@ +![Log Driver][logdriver-logo] +========= +[![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![NPM Version][npm-image]][npm-url] + +Logdriver is a node.js logger that only logs to stdout. + +####You're going to want to log the output of stdout and stderr anyway, so you might as well put all your logging through stdout. Logging libraries that don't write to stdout or stderr are missing absolutely critical output like the stack trace if/when your app dies. + +##There are some other nice advantages: +* When working on your app locally, logs just show up in stdout just like if you'd used console.log(). That's a heck of a lot simpler than tailing a log file. +* Logging transports can be externalized from your app entirely, and completely decoupled. This means if you want to log to irc, you write an irc client script that reads from stdin, and you just pipe your app's output to that script. + +```console +node yourapp.js 2>&1 | node ircloggerbot.js +``` +* You can still easily log to a file on a production server by piping your stdout and stderr to a file like so when you initialize your app: + +```console +node yourapp.js 2>&1 >> somefile.log +``` + +NB: If you're logging to a file, [Logrotate](http://linuxcommand.org/man_pages/logrotate8.html) is probably going to be your best friend. +* You can still easily log to syslog by piping your stdout and stderr to the 'logger' command like so: + +```console +node yourapp.js 2>&1 | logger +``` + +##Usage: +Getting the default logger: +```javascript +var logger = require('log-driver').logger; +``` + +This logger has levels 'error', 'warn', 'info', 'debug', and 'trace'. +If you don't like those levels, change the default: + +```javascript +var logger = require('log-driver')({ + levels: ['superimportant', 'checkthisout', 'whocares' ] +}); +logger.whocares("brangelina in lover's quarrel!"); +``` + +Specifying what log level to log at to make logs less chatty: +```javascript +var logger = require('log-driver')({ level: "info" }); +logger.info("info test"); +logger.warn("warn test"); +logger.error("error test"); +logger.trace("trace test"); +``` +output: +```console +[info] "2013-03-26T18:30:14.570Z" 'info test' +[warn] "2013-03-26T18:30:14.573Z" 'warn test' +[error] "2013-03-26T18:30:14.574Z" 'error test' +``` +(notice the trace() call was omitted because it's less than the info +level. + +Turning off all log output (sometimes nice for automated tests to keep +output clean): +```javascript +var logger = require('log-driver')({ level: false }); +``` + +Using the same logger everywhere: +The last logger you created is always available this way: +```javascript +var logger = require('log-driver').logger; +``` +This way, if you use only one logger in your application (like most +applications), you can just configure it once, and get it this way +everywhere else. + +Don't like the logging format? Just change it by passing a new +formatting function like so: +```javascript +var logger = require('log-driver')({ + format: function() { + // let's do pure JSON: + return JSON.stringify(arguments); + } +}); +``` + +![Log Driver](https://raw.github.com/cainus/logdriver/master/waltz.jpg) + +[logdriver-logo]: https://raw.github.com/cainus/logdriver/master/logo.png + +[travis-image]: https://travis-ci.org/cainus/logdriver.png?branch=master +[travis-url]: https://travis-ci.org/cainus/logdriver + +[coveralls-image]: https://coveralls.io/repos/cainus/logdriver/badge.png?branch=master +[coveralls-url]: https://coveralls.io/repos/cainus/logdriver + +[npm-image]: https://badge.fury.io/js/log-driver.png +[npm-url]: https://badge.fury.io/js/log-driver diff --git a/hm_sunwell/node_modules/log-driver/index.js b/hm_sunwell/node_modules/log-driver/index.js new file mode 100644 index 0000000..769e891 --- /dev/null +++ b/hm_sunwell/node_modules/log-driver/index.js @@ -0,0 +1,60 @@ +var util = require('util'); + +var LogDriver = function(options){ + options = options || {}; + var logger = this; + if (options.format){ + this.format = options.format; + } + this.levels = options.levels || ['error', 'warn', 'info', 'debug', 'trace']; + if (options.level === false){ + this.level = false; // don't log anything + } else { + this.level = options.level || this.levels[this.levels.length - 1]; + if (this.levels.indexOf(this.level) === -1){ + throw new Error("Log level '" + + this.level + + "' does not exist in level list '" + JSON.stringify() + "'"); + } + } + this.levels.forEach(function(level){ + if (logLevelShouldOutput(level, logger.level, logger.levels)){ + logger[level] = function(){ + var args = Array.prototype.slice.call(arguments); + args.unshift(level); // log level is added as the first parameter + console.log(logger.format.apply(logger, args)); + }; + } else { + logger[level] = function(){/* no-op, because this log level is ignored */}; + } + }); +}; + +var logLevelShouldOutput = function(logLevel, configuredLevel, levels){ + if (configuredLevel === false){ + return false; + } + return (levels.indexOf(logLevel) <= levels.indexOf(configuredLevel)); +}; + +LogDriver.prototype.format = function(){ + var args = Array.prototype.slice.call(arguments, [1]); // change arguments to an array, but + // drop the first item (log level) + var out = "[" + arguments[0] + "] " + JSON.stringify(new Date()) + " "; + args.forEach(function(arg){ + out += " " + util.inspect(arg); + }); + return out; +}; + +var defaultLogger = null; + +var factory = function(options){ + defaultLogger = new LogDriver(options); + factory.logger = defaultLogger; + return defaultLogger; +}; + +factory(); + +module.exports = factory; diff --git a/hm_sunwell/node_modules/log-driver/package.json b/hm_sunwell/node_modules/log-driver/package.json new file mode 100644 index 0000000..3c1e509 --- /dev/null +++ b/hm_sunwell/node_modules/log-driver/package.json @@ -0,0 +1,80 @@ +{ + "_args": [ + [ + "log-driver@1.2.5", + "/home/xor/shared_vm/git/node-sunwell/node_modules/coveralls" + ] + ], + "_from": "log-driver@1.2.5", + "_id": "log-driver@1.2.5", + "_inCache": true, + "_installable": true, + "_location": "/log-driver", + "_npmUser": { + "email": "gregg@caines.ca", + "name": "cainus" + }, + "_npmVersion": "1.4.14", + "_phantomChildren": {}, + "_requested": { + "name": "log-driver", + "raw": "log-driver@1.2.5", + "rawSpec": "1.2.5", + "scope": null, + "spec": "1.2.5", + "type": "version" + }, + "_requiredBy": [ + "/coveralls" + ], + "_resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "_shasum": "7ae4ec257302fd790d557cb10c97100d857b0056", + "_shrinkwrap": null, + "_spec": "log-driver@1.2.5", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/coveralls", + "bugs": { + "url": "https://github.com/cainus/logdriver/issues" + }, + "dependencies": {}, + "description": "log-driver is a simple logging framework for logging to stdout", + "devDependencies": { + "coveralls": "2.10.0", + "istanbul": "0.2.6", + "jshint": "2.4.4", + "mocha": "1.20.1", + "should": "1.1.0", + "sinon-restore": "1.0.1" + }, + "directories": {}, + "dist": { + "shasum": "7ae4ec257302fd790d557cb10c97100d857b0056", + "tarball": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz" + }, + "engines": { + "node": ">=0.8.6" + }, + "gitHead": "09dd22cc242bc70e2f224bfe7cf06961cd1127dc", + "homepage": "https://github.com/cainus/logdriver", + "keywords": [ + "log", + "logger", + "logging" + ], + "maintainers": [ + { + "name": "cainus", + "email": "gregg@caines.ca" + } + ], + "name": "log-driver", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/cainus/logdriver.git" + }, + "scripts": { + "test": "make test-coveralls" + }, + "version": "1.2.5" +} diff --git a/hm_sunwell/node_modules/longest/LICENSE b/hm_sunwell/node_modules/longest/LICENSE new file mode 100644 index 0000000..fa30c4c --- /dev/null +++ b/hm_sunwell/node_modules/longest/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hm_sunwell/node_modules/longest/README.md b/hm_sunwell/node_modules/longest/README.md new file mode 100644 index 0000000..cdffe65 --- /dev/null +++ b/hm_sunwell/node_modules/longest/README.md @@ -0,0 +1,65 @@ +# longest [![NPM version](https://badge.fury.io/js/longest.svg)](http://badge.fury.io/js/longest) [![Build Status](https://travis-ci.org/jonschlinkert/longest.svg)](https://travis-ci.org/jonschlinkert/longest) + +> Get the longest item in an array. + +## Install with [npm](npmjs.org) + +```bash +npm i longest --save +``` +### Install with [bower](https://github.com/bower/bower) + +```bash +bower install longest --save +``` + +## Running tests +Install dev dependencies. + +```bash +npm i -d && npm test +``` + +## Usage + +```js +var longest = require('longest'); +longest(['a', 'abcde', 'abc']); +//=> 'abcde' + +longest(['a', 'abcde', 'abc']).length; +//=> 5 +``` + +## Related projects +* [longest-value](https://github.com/jonschlinkert/longest-value): Get the longest value for the given property from an array of objects. Useful for aligning values. +* [right-align-values](https://github.com/jonschlinkert/right-align-values): Right align the values of a given property for each object in an array. Useful for creating text columns or tables. +* [right-pad-values](https://github.com/jonschlinkert/right-pad-values): Right pad the values of a given property for each object in an array. Useful for creating text columns or tables. +* [repeat-string](https://github.com/jonschlinkert/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. +* [pad-right](https://github.com/jonschlinkert/pad-right): Right pad a string with zeros or a specified string. Fastest implementation. +* [pad-left](https://github.com/jonschlinkert/pad-left): Left pad a string with zeros or a specified string. Fastest implementation. + +## Running tests +Install dev dependencies. + +```bash +npm i -d && npm test +``` + +## Contributing +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/longest/issues) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License +Copyright (c) 2015 Jon Schlinkert +Released under the MIT license + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on March 31, 2015._ \ No newline at end of file diff --git a/hm_sunwell/node_modules/longest/index.js b/hm_sunwell/node_modules/longest/index.js new file mode 100644 index 0000000..9892e52 --- /dev/null +++ b/hm_sunwell/node_modules/longest/index.js @@ -0,0 +1,37 @@ +/*! + * longest + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +module.exports = function(arr) { + if (!arr) { + return null; + } + + var len = arr.length; + if (!len) { + return null; + } + + var c = 0; + var i = 0; + var ele; + var elen; + var res; + + for (; i < len; i++) { + ele = arr[i].toString(); + elen = ele.length; + + if (elen > c) { + res = ele; + c = elen; + } + } + + return res; +}; diff --git a/hm_sunwell/node_modules/longest/package.json b/hm_sunwell/node_modules/longest/package.json new file mode 100644 index 0000000..5df0db0 --- /dev/null +++ b/hm_sunwell/node_modules/longest/package.json @@ -0,0 +1,96 @@ +{ + "_args": [ + [ + "longest@^1.0.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/align-text" + ] + ], + "_from": "longest@>=1.0.1 <2.0.0", + "_id": "longest@1.0.1", + "_inCache": true, + "_installable": true, + "_location": "/longest", + "_nodeVersion": "0.12.0", + "_npmUser": { + "email": "github@sellside.com", + "name": "jonschlinkert" + }, + "_npmVersion": "2.5.1", + "_phantomChildren": {}, + "_requested": { + "name": "longest", + "raw": "longest@^1.0.1", + "rawSpec": "^1.0.1", + "scope": null, + "spec": ">=1.0.1 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/align-text" + ], + "_resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "_shasum": "30a0b2da38f73770e8294a0d22e6625ed77d0097", + "_shrinkwrap": null, + "_spec": "longest@^1.0.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/align-text", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/longest/issues" + }, + "dependencies": {}, + "description": "Get the longest item in an array.", + "devDependencies": { + "fill-range": "^2.1.0", + "mocha": "*" + }, + "directories": {}, + "dist": { + "shasum": "30a0b2da38f73770e8294a0d22e6625ed77d0097", + "tarball": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "99d9d8257584500aedaea54427a828197c452b0a", + "homepage": "https://github.com/jonschlinkert/longest", + "keywords": [ + "array", + "element", + "item", + "length", + "long", + "longest" + ], + "license": { + "type": "MIT", + "url": "https://github.com/jonschlinkert/longest/blob/master/LICENSE" + }, + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "shinnn", + "email": "snnskwtnb@gmail.com" + } + ], + "name": "longest", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/longest.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "1.0.1" +} diff --git a/hm_sunwell/node_modules/lru-cache/.npmignore b/hm_sunwell/node_modules/lru-cache/.npmignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/hm_sunwell/node_modules/lru-cache/.travis.yml b/hm_sunwell/node_modules/lru-cache/.travis.yml new file mode 100644 index 0000000..4af02b3 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - '0.8' + - '0.10' + - '0.12' + - 'iojs' +before_install: + - npm install -g npm@latest diff --git a/hm_sunwell/node_modules/lru-cache/CONTRIBUTORS b/hm_sunwell/node_modules/lru-cache/CONTRIBUTORS new file mode 100644 index 0000000..4a0bc50 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/CONTRIBUTORS @@ -0,0 +1,14 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Brian Cottingham +Carlos Brito Lage +Jesse Dailey +Kevin O'Hara +Marco Rogers +Mark Cavage +Marko Mikulicic +Nathan Rajlich +Satheesh Natesan +Trent Mick +ashleybrener +n4kz diff --git a/hm_sunwell/node_modules/lru-cache/LICENSE b/hm_sunwell/node_modules/lru-cache/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/hm_sunwell/node_modules/lru-cache/README.md b/hm_sunwell/node_modules/lru-cache/README.md new file mode 100644 index 0000000..c06814e --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/README.md @@ -0,0 +1,137 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Keys should always be Strings or Numbers + +Note: this module will print warnings to `console.error` if you use a +key that is not a String or Number. Because items are stored in an +object, which coerces keys to a string, it won't go well for you if +you try to use a key that is not a unique string, it'll cause surprise +collisions. For example: + +```JavaScript +// Bad Example! Dont' do this! +var cache = LRU() +var a = {} +var b = {} +cache.set(a, 'this is a') +cache.set(b, 'this is b') +console.log(cache.get(a)) // prints: 'this is b' +``` + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `max` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value, maxAge)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. `max` is optional and overrides the + cache `max` option if provided. + +* `peek(key)` + + Returns the key value (or `undefined` if not found) without + updating the "recently used"-ness of the key. + + (If you find yourself using this a lot, you *might* be using the + wrong sort of data structure, but there are some use cases where + it's handy.) + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. + +* `length()` + + Return total length of objects in cache taking into account + `length` options function. + +* `itemCount` + + Return total quantity of objects currently in cache. Note, that + `stale` (see options) items are returned as part of this item + count. + +* `dump()` + + Return an array of the cache entries ready for serialization and usage + with 'destinationCache.load(arr)`. + +* `load(cacheEntriesArray)` + + Loads another cache entries array, obtained with `sourceCache.dump()`, + into the cache. The destination cache is reset before loading new entries diff --git a/hm_sunwell/node_modules/lru-cache/lib/lru-cache.js b/hm_sunwell/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 0000000..2bbe653 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,334 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +var didTypeWarning = false +function typeCheckKey(key) { + if (!didTypeWarning && typeof key !== 'string' && typeof key !== 'number') { + didTypeWarning = true + console.error(new TypeError("LRU: key must be a string or number. Almost certainly a bug! " + typeof key).stack) + } +} + +function LRUCache (options) { + if (!(this instanceof LRUCache)) + return new LRUCache(options) + + if (typeof options === 'number') + options = { max: options } + + if (!options) + options = {} + + this._max = options.max + // Kind of weird to have a default max of Infinity, but oh well. + if (!this._max || !(typeof this._max === "number") || this._max <= 0 ) + this._max = Infinity + + this._lengthCalculator = options.length || naiveLength + if (typeof this._lengthCalculator !== "function") + this._lengthCalculator = naiveLength + + this._allowStale = options.stale || false + this._maxAge = options.maxAge || null + this._dispose = options.dispose + this.reset() +} + +// resize the cache when the max changes. +Object.defineProperty(LRUCache.prototype, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + this._max = mL + if (this._length > this._max) trim(this) + } + , get : function () { return this._max } + , enumerable : true + }) + +// resize the cache when the lengthCalculator changes. +Object.defineProperty(LRUCache.prototype, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + this._lengthCalculator = naiveLength + this._length = this._itemCount + for (var key in this._cache) { + this._cache[key].length = 1 + } + } else { + this._lengthCalculator = lC + this._length = 0 + for (var key in this._cache) { + this._cache[key].length = this._lengthCalculator(this._cache[key].value) + this._length += this._cache[key].length + } + } + + if (this._length > this._max) trim(this) + } + , get : function () { return this._lengthCalculator } + , enumerable : true + }) + +Object.defineProperty(LRUCache.prototype, "length", + { get : function () { return this._length } + , enumerable : true + }) + + +Object.defineProperty(LRUCache.prototype, "itemCount", + { get : function () { return this._itemCount } + , enumerable : true + }) + +LRUCache.prototype.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0 + var itemCount = this._itemCount + + for (var k = this._mru - 1; k >= 0 && i < itemCount; k--) if (this._lruList[k]) { + i++ + var hit = this._lruList[k] + if (isStale(this, hit)) { + del(this, hit) + if (!this._allowStale) hit = undefined + } + if (hit) { + fn.call(thisp, hit.value, hit.key, this) + } + } +} + +LRUCache.prototype.keys = function () { + var keys = new Array(this._itemCount) + var i = 0 + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + keys[i++] = hit.key + } + return keys +} + +LRUCache.prototype.values = function () { + var values = new Array(this._itemCount) + var i = 0 + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + values[i++] = hit.value + } + return values +} + +LRUCache.prototype.reset = function () { + if (this._dispose && this._cache) { + for (var k in this._cache) { + this._dispose(k, this._cache[k].value) + } + } + + this._cache = Object.create(null) // hash of items by key + this._lruList = Object.create(null) // list of items in order of use recency + this._mru = 0 // most recently used + this._lru = 0 // least recently used + this._length = 0 // number of items in the list + this._itemCount = 0 +} + +LRUCache.prototype.dump = function () { + var arr = [] + var i = 0 + + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + if (!isStale(this, hit)) { + //Do not store staled hits + ++i + arr.push({ + k: hit.key, + v: hit.value, + e: hit.now + (hit.maxAge || 0) + }); + } + } + //arr has the most read first + return arr +} + +LRUCache.prototype.dumpLru = function () { + return this._lruList +} + +LRUCache.prototype.set = function (key, value, maxAge) { + maxAge = maxAge || this._maxAge + typeCheckKey(key) + + var now = maxAge ? Date.now() : 0 + var len = this._lengthCalculator(value) + + if (hOP(this._cache, key)) { + if (len > this._max) { + del(this, this._cache[key]) + return false + } + // dispose of the old one before overwriting + if (this._dispose) + this._dispose(key, this._cache[key].value) + + this._cache[key].now = now + this._cache[key].maxAge = maxAge + this._cache[key].value = value + this._length += (len - this._cache[key].length) + this._cache[key].length = len + this.get(key) + + if (this._length > this._max) + trim(this) + + return true + } + + var hit = new Entry(key, value, this._mru++, len, now, maxAge) + + // oversized objects fall out of cache automatically. + if (hit.length > this._max) { + if (this._dispose) this._dispose(key, value) + return false + } + + this._length += hit.length + this._lruList[hit.lu] = this._cache[key] = hit + this._itemCount ++ + + if (this._length > this._max) + trim(this) + + return true +} + +LRUCache.prototype.has = function (key) { + typeCheckKey(key) + if (!hOP(this._cache, key)) return false + var hit = this._cache[key] + if (isStale(this, hit)) { + return false + } + return true +} + +LRUCache.prototype.get = function (key) { + typeCheckKey(key) + return get(this, key, true) +} + +LRUCache.prototype.peek = function (key) { + typeCheckKey(key) + return get(this, key, false) +} + +LRUCache.prototype.pop = function () { + var hit = this._lruList[this._lru] + del(this, hit) + return hit || null +} + +LRUCache.prototype.del = function (key) { + typeCheckKey(key) + del(this, this._cache[key]) +} + +LRUCache.prototype.load = function (arr) { + //reset the cache + this.reset(); + + var now = Date.now() + //A previous serialized cache has the most recent items first + for (var l = arr.length - 1; l >= 0; l-- ) { + var hit = arr[l] + typeCheckKey(hit.k) + var expiresAt = hit.e || 0 + if (expiresAt === 0) { + //the item was created without expiration in a non aged cache + this.set(hit.k, hit.v) + } else { + var maxAge = expiresAt - now + //dont add already expired items + if (maxAge > 0) this.set(hit.k, hit.v, maxAge) + } + } +} + +function get (self, key, doUse) { + typeCheckKey(key) + var hit = self._cache[key] + if (hit) { + if (isStale(self, hit)) { + del(self, hit) + if (!self._allowStale) hit = undefined + } else { + if (doUse) use(self, hit) + } + if (hit) hit = hit.value + } + return hit +} + +function isStale(self, hit) { + if (!hit || (!hit.maxAge && !self._maxAge)) return false + var stale = false; + var diff = Date.now() - hit.now + if (hit.maxAge) { + stale = diff > hit.maxAge + } else { + stale = self._maxAge && (diff > self._maxAge) + } + return stale; +} + +function use (self, hit) { + shiftLU(self, hit) + hit.lu = self._mru ++ + self._lruList[hit.lu] = hit +} + +function trim (self) { + while (self._lru < self._mru && self._length > self._max) + del(self, self._lruList[self._lru]) +} + +function shiftLU (self, hit) { + delete self._lruList[ hit.lu ] + while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++ +} + +function del (self, hit) { + if (hit) { + if (self._dispose) self._dispose(hit.key, hit.value) + self._length -= hit.length + self._itemCount -- + delete self._cache[ hit.key ] + shiftLU(self, hit) + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, lu, length, now, maxAge) { + this.key = key + this.value = value + this.lu = lu + this.length = length + this.now = now + if (maxAge) this.maxAge = maxAge +} + +})() diff --git a/hm_sunwell/node_modules/lru-cache/package.json b/hm_sunwell/node_modules/lru-cache/package.json new file mode 100644 index 0000000..c236d74 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/package.json @@ -0,0 +1,84 @@ +{ + "_args": [ + [ + "lru-cache@2", + "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha/node_modules/minimatch" + ] + ], + "_from": "lru-cache@>=2.0.0 <3.0.0", + "_id": "lru-cache@2.7.3", + "_inCache": true, + "_installable": true, + "_location": "/lru-cache", + "_nodeVersion": "4.0.0", + "_npmUser": { + "email": "i@izs.me", + "name": "isaacs" + }, + "_npmVersion": "3.3.2", + "_phantomChildren": {}, + "_requested": { + "name": "lru-cache", + "raw": "lru-cache@2", + "rawSpec": "2", + "scope": null, + "spec": ">=2.0.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/mocha/minimatch" + ], + "_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "_shasum": "6d4524e8b955f95d4f5b58851ce21dd72fb4e952", + "_shrinkwrap": null, + "_spec": "lru-cache@2", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/mocha/node_modules/minimatch", + "author": { + "email": "i@izs.me", + "name": "Isaac Z. Schlueter" + }, + "bugs": { + "url": "https://github.com/isaacs/node-lru-cache/issues" + }, + "dependencies": {}, + "description": "A cache object that deletes the least-recently-used items.", + "devDependencies": { + "tap": "^1.2.0", + "weak": "" + }, + "directories": {}, + "dist": { + "shasum": "6d4524e8b955f95d4f5b58851ce21dd72fb4e952", + "tarball": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "gitHead": "292048199f6d28b77fbe584279a1898e25e4c714", + "homepage": "https://github.com/isaacs/node-lru-cache#readme", + "keywords": [ + "cache", + "lru", + "mru" + ], + "license": "ISC", + "main": "lib/lru-cache.js", + "maintainers": [ + { + "name": "isaacs", + "email": "isaacs@npmjs.com" + }, + { + "name": "othiym23", + "email": "ogd@aoaioxxysz.net" + } + ], + "name": "lru-cache", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "scripts": { + "test": "tap test --gc" + }, + "version": "2.7.3" +} diff --git a/hm_sunwell/node_modules/lru-cache/test/basic.js b/hm_sunwell/node_modules/lru-cache/test/basic.js new file mode 100644 index 0000000..b47225f --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/test/basic.js @@ -0,0 +1,396 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("lru recently updated with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + t.equal(cache.length, 6) //CCC BB A + cache.set("a", "+A") + t.equal(cache.length, 7) //+A CCC BB + cache.set("b", "++BB") + t.equal(cache.length, 6) //++BB +A + t.equal(cache.get("c"), undefined) + + cache.set("c", "oversized") + t.equal(cache.length, 6) //++BB +A + t.equal(cache.get("c"), undefined) + + cache.set("a", "oversized") + t.equal(cache.length, 4) //++BB + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), "++BB") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60 + 25) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("individual item can have it's own maxAge", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A", 20) + setTimeout(function () { + t.notOk(cache.get("a")) + t.end() + }, 25) +}) + +test("individual item can have it's own maxAge > cache's", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 20 + }) + + cache.set("a", "A", 50) + setTimeout(function () { + t.equal(cache.get("a"), "A") + t.end() + }, 25) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) + +test("least recently set w/ peek", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + t.equal(cache.peek("a"), "A") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("pop the least used item", function (t) { + var cache = new LRU(3) + , last + + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + + t.equal(cache.length, 3) + t.equal(cache.max, 3) + + // Ensure we pop a, c, b + cache.get("b", "B") + + last = cache.pop() + t.equal(last.key, "a") + t.equal(last.value, "A") + t.equal(cache.length, 2) + t.equal(cache.max, 3) + + last = cache.pop() + t.equal(last.key, "c") + t.equal(last.value, "C") + t.equal(cache.length, 1) + t.equal(cache.max, 3) + + last = cache.pop() + t.equal(last.key, "b") + t.equal(last.value, "B") + t.equal(cache.length, 0) + t.equal(cache.max, 3) + + last = cache.pop() + t.equal(last, null) + t.equal(cache.length, 0) + t.equal(cache.max, 3) + + t.end() +}) diff --git a/hm_sunwell/node_modules/lru-cache/test/foreach.js b/hm_sunwell/node_modules/lru-cache/test/foreach.js new file mode 100644 index 0000000..4190417 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,120 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + t.equal(i, order.length); + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) + +test('all entries are iterated over', function(t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 0 + l.forEach(function (val, key, cache) { + if (i > 0) { + cache.del(key) + } + i += 1 + }) + + t.equal(i, 5) + t.equal(l.keys().length, 1) + + t.end() +}) + +test('all stale entries are removed', function(t) { + var l = new LRU({ max: 5, maxAge: -5, stale: true }) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 0 + l.forEach(function () { + i += 1 + }) + + t.equal(i, 5) + t.equal(l.keys().length, 0) + + t.end() +}) + +test('expires', function (t) { + var l = new LRU({ + max: 10, + maxAge: 50 + }) + for (var i = 0; i < 10; i++) { + l.set(i.toString(), i.toString(2), ((i % 2) ? 25 : undefined)) + } + + var i = 0 + var order = [ 8, 6, 4, 2, 0 ] + setTimeout(function () { + l.forEach(function (val, key, cache) { + var j = order[i++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + t.equal(i, order.length); + + setTimeout(function () { + var count = 0; + l.forEach(function (val, key, cache) { count++; }) + t.equal(0, count); + t.end() + }, 25) + + }, 26) +}) diff --git a/hm_sunwell/node_modules/lru-cache/test/memory-leak.js b/hm_sunwell/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 0000000..b5912f6 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,51 @@ +#!/usr/bin/env node --expose_gc + + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/hm_sunwell/node_modules/lru-cache/test/serialize.js b/hm_sunwell/node_modules/lru-cache/test/serialize.js new file mode 100644 index 0000000..1094194 --- /dev/null +++ b/hm_sunwell/node_modules/lru-cache/test/serialize.js @@ -0,0 +1,216 @@ +var test = require('tap').test +var LRU = require('../') + +test('dump', function (t) { + var cache = new LRU() + + t.equal(cache.dump().length, 0, "nothing in dump for empty cache") + + cache.set("a", "A") + cache.set("b", "B") + t.deepEqual(cache.dump(), [ + { k: "b", v: "B", e: 0 }, + { k: "a", v: "A", e: 0 } + ]) + + cache.set("a", "A"); + t.deepEqual(cache.dump(), [ + { k: "a", v: "A", e: 0 }, + { k: "b", v: "B", e: 0 } + ]) + + cache.get("b"); + t.deepEqual(cache.dump(), [ + { k: "b", v: "B", e: 0 }, + { k: "a", v: "A", e: 0 } + ]) + + cache.del("a"); + t.deepEqual(cache.dump(), [ + { k: "b", v: "B", e: 0 } + ]) + + t.end() +}) + +test("do not dump stale items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + //expires at 50 + cache.set("a", "A") + + setTimeout(function () { + //expires at 75 + cache.set("b", "B") + var s = cache.dump() + t.equal(s.length, 2) + t.equal(s[0].k, "b") + t.equal(s[1].k, "a") + }, 25) + + setTimeout(function () { + //expires at 110 + cache.set("c", "C") + var s = cache.dump() + t.equal(s.length, 2) + t.equal(s[0].k, "c") + t.equal(s[1].k, "b") + }, 60) + + setTimeout(function () { + //expires at 130 + cache.set("d", "D", 40) + var s = cache.dump() + t.equal(s.length, 2) + t.equal(s[0].k, "d") + t.equal(s[1].k, "c") + }, 90) + + setTimeout(function () { + var s = cache.dump() + t.equal(s.length, 1) + t.equal(s[0].k, "d") + }, 120) + + setTimeout(function () { + var s = cache.dump() + t.deepEqual(s, []) + t.end() + }, 155) +}) + +test("load basic cache", function(t) { + var cache = new LRU(), + copy = new LRU() + + cache.set("a", "A") + cache.set("b", "B") + + copy.load(cache.dump()) + t.deepEquals(cache.dump(), copy.dump()) + + t.end() +}) + + +test("load staled cache", function(t) { + var cache = new LRU({maxAge: 50}), + copy = new LRU({maxAge: 50}), + arr + + //expires at 50 + cache.set("a", "A") + setTimeout(function () { + //expires at 80 + cache.set("b", "B") + arr = cache.dump() + t.equal(arr.length, 2) + }, 30) + + setTimeout(function () { + copy.load(arr) + t.equal(copy.get("a"), undefined) + t.equal(copy.get("b"), "B") + }, 60) + + setTimeout(function () { + t.equal(copy.get("b"), undefined) + t.end() + }, 90) +}) + +test("load to other size cache", function(t) { + var cache = new LRU({max: 2}), + copy = new LRU({max: 1}) + + cache.set("a", "A") + cache.set("b", "B") + + copy.load(cache.dump()) + t.equal(copy.get("a"), undefined) + t.equal(copy.get("b"), "B") + + //update the last read from original cache + cache.get("a") + copy.load(cache.dump()) + t.equal(copy.get("a"), "A") + t.equal(copy.get("b"), undefined) + + t.end() +}) + + +test("load to other age cache", function(t) { + var cache = new LRU({maxAge: 50}), + aged = new LRU({maxAge: 100}), + simple = new LRU(), + arr, + expired + + //created at 0 + //a would be valid till 0 + 50 + cache.set("a", "A") + setTimeout(function () { + //created at 20 + //b would be valid till 20 + 50 + cache.set("b", "B") + //b would be valid till 20 + 70 + cache.set("c", "C", 70) + arr = cache.dump() + t.equal(arr.length, 3) + }, 20) + + setTimeout(function () { + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), "B") + t.equal(cache.get("c"), "C") + + aged.load(arr) + t.equal(aged.get("a"), undefined) + t.equal(aged.get("b"), "B") + t.equal(aged.get("c"), "C") + + simple.load(arr) + t.equal(simple.get("a"), undefined) + t.equal(simple.get("b"), "B") + t.equal(simple.get("c"), "C") + }, 60) + + setTimeout(function () { + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.equal(cache.get("c"), "C") + + aged.load(arr) + t.equal(aged.get("a"), undefined) + t.equal(aged.get("b"), undefined) + t.equal(aged.get("c"), "C") + + simple.load(arr) + t.equal(simple.get("a"), undefined) + t.equal(simple.get("b"), undefined) + t.equal(simple.get("c"), "C") + }, 80) + + setTimeout(function () { + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.equal(cache.get("c"), undefined) + + aged.load(arr) + t.equal(aged.get("a"), undefined) + t.equal(aged.get("b"), undefined) + t.equal(aged.get("c"), undefined) + + simple.load(arr) + t.equal(simple.get("a"), undefined) + t.equal(simple.get("b"), undefined) + t.equal(simple.get("c"), undefined) + t.end() + }, 100) + +}) + diff --git a/hm_sunwell/node_modules/media-typer/HISTORY.md b/hm_sunwell/node_modules/media-typer/HISTORY.md new file mode 100644 index 0000000..62c2003 --- /dev/null +++ b/hm_sunwell/node_modules/media-typer/HISTORY.md @@ -0,0 +1,22 @@ +0.3.0 / 2014-09-07 +================== + + * Support Node.js 0.6 + * Throw error when parameter format invalid on parse + +0.2.0 / 2014-06-18 +================== + + * Add `typer.format()` to format media types + +0.1.0 / 2014-06-17 +================== + + * Accept `req` as argument to `parse` + * Accept `res` as argument to `parse` + * Parse media type with extra LWS between type and first parameter + +0.0.0 / 2014-06-13 +================== + + * Initial implementation diff --git a/hm_sunwell/node_modules/media-typer/LICENSE b/hm_sunwell/node_modules/media-typer/LICENSE new file mode 100644 index 0000000..b7dce6c --- /dev/null +++ b/hm_sunwell/node_modules/media-typer/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/media-typer/README.md b/hm_sunwell/node_modules/media-typer/README.md new file mode 100644 index 0000000..d8df623 --- /dev/null +++ b/hm_sunwell/node_modules/media-typer/README.md @@ -0,0 +1,81 @@ +# media-typer + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Simple RFC 6838 media type parser + +## Installation + +```sh +$ npm install media-typer +``` + +## API + +```js +var typer = require('media-typer') +``` + +### typer.parse(string) + +```js +var obj = typer.parse('image/svg+xml; charset=utf-8') +``` + +Parse a media type string. This will return an object with the following +properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`): + + - `type`: The type of the media type (always lower case). Example: `'image'` + + - `subtype`: The subtype of the media type (always lower case). Example: `'svg'` + + - `suffix`: The suffix of the media type (always lower case). Example: `'xml'` + + - `parameters`: An object of the parameters in the media type (name of parameter always lower case). Example: `{charset: 'utf-8'}` + +### typer.parse(req) + +```js +var obj = typer.parse(req) +``` + +Parse the `content-type` header from the given `req`. Short-cut for +`typer.parse(req.headers['content-type'])`. + +### typer.parse(res) + +```js +var obj = typer.parse(res) +``` + +Parse the `content-type` header set on the given `res`. Short-cut for +`typer.parse(res.getHeader('content-type'))`. + +### typer.format(obj) + +```js +var obj = typer.format({type: 'image', subtype: 'svg', suffix: 'xml'}) +``` + +Format an object into a media type string. This will return a string of the +mime type for the given object. For the properties of the object, see the +documentation for `typer.parse(string)`. + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/media-typer.svg?style=flat +[npm-url]: https://npmjs.org/package/media-typer +[node-version-image]: https://img.shields.io/badge/node.js-%3E%3D_0.6-brightgreen.svg?style=flat +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/media-typer.svg?style=flat +[travis-url]: https://travis-ci.org/jshttp/media-typer +[coveralls-image]: https://img.shields.io/coveralls/jshttp/media-typer.svg?style=flat +[coveralls-url]: https://coveralls.io/r/jshttp/media-typer +[downloads-image]: https://img.shields.io/npm/dm/media-typer.svg?style=flat +[downloads-url]: https://npmjs.org/package/media-typer diff --git a/hm_sunwell/node_modules/media-typer/index.js b/hm_sunwell/node_modules/media-typer/index.js new file mode 100644 index 0000000..07f7295 --- /dev/null +++ b/hm_sunwell/node_modules/media-typer/index.js @@ -0,0 +1,270 @@ +/*! + * media-typer + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +/** + * RegExp to match *( ";" parameter ) in RFC 2616 sec 3.7 + * + * parameter = token "=" ( token | quoted-string ) + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) + * qdtext = > + * quoted-pair = "\" CHAR + * CHAR = + * TEXT = + * LWS = [CRLF] 1*( SP | HT ) + * CRLF = CR LF + * CR = + * LF = + * SP = + * SHT = + * CTL = + * OCTET = + */ +var paramRegExp = /; *([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *= *("(?:[ !\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u0020-\u007e])*"|[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) */g; +var textRegExp = /^[\u0020-\u007e\u0080-\u00ff]+$/ +var tokenRegExp = /^[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+$/ + +/** + * RegExp to match quoted-pair in RFC 2616 + * + * quoted-pair = "\" CHAR + * CHAR = + */ +var qescRegExp = /\\([\u0000-\u007f])/g; + +/** + * RegExp to match chars that must be quoted-pair in RFC 2616 + */ +var quoteRegExp = /([\\"])/g; + +/** + * RegExp to match type in RFC 6838 + * + * type-name = restricted-name + * subtype-name = restricted-name + * restricted-name = restricted-name-first *126restricted-name-chars + * restricted-name-first = ALPHA / DIGIT + * restricted-name-chars = ALPHA / DIGIT / "!" / "#" / + * "$" / "&" / "-" / "^" / "_" + * restricted-name-chars =/ "." ; Characters before first dot always + * ; specify a facet name + * restricted-name-chars =/ "+" ; Characters after last plus always + * ; specify a structured syntax suffix + * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z + * DIGIT = %x30-39 ; 0-9 + */ +var subtypeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.-]{0,126}$/ +var typeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/ +var typeRegExp = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/; + +/** + * Module exports. + */ + +exports.format = format +exports.parse = parse + +/** + * Format object to media type. + * + * @param {object} obj + * @return {string} + * @api public + */ + +function format(obj) { + if (!obj || typeof obj !== 'object') { + throw new TypeError('argument obj is required') + } + + var parameters = obj.parameters + var subtype = obj.subtype + var suffix = obj.suffix + var type = obj.type + + if (!type || !typeNameRegExp.test(type)) { + throw new TypeError('invalid type') + } + + if (!subtype || !subtypeNameRegExp.test(subtype)) { + throw new TypeError('invalid subtype') + } + + // format as type/subtype + var string = type + '/' + subtype + + // append +suffix + if (suffix) { + if (!typeNameRegExp.test(suffix)) { + throw new TypeError('invalid suffix') + } + + string += '+' + suffix + } + + // append parameters + if (parameters && typeof parameters === 'object') { + var param + var params = Object.keys(parameters).sort() + + for (var i = 0; i < params.length; i++) { + param = params[i] + + if (!tokenRegExp.test(param)) { + throw new TypeError('invalid parameter name') + } + + string += '; ' + param + '=' + qstring(parameters[param]) + } + } + + return string +} + +/** + * Parse media type to object. + * + * @param {string|object} string + * @return {Object} + * @api public + */ + +function parse(string) { + if (!string) { + throw new TypeError('argument string is required') + } + + // support req/res-like objects as argument + if (typeof string === 'object') { + string = getcontenttype(string) + } + + if (typeof string !== 'string') { + throw new TypeError('argument string is required to be a string') + } + + var index = string.indexOf(';') + var type = index !== -1 + ? string.substr(0, index) + : string + + var key + var match + var obj = splitType(type) + var params = {} + var value + + paramRegExp.lastIndex = index + + while (match = paramRegExp.exec(string)) { + if (match.index !== index) { + throw new TypeError('invalid parameter format') + } + + index += match[0].length + key = match[1].toLowerCase() + value = match[2] + + if (value[0] === '"') { + // remove quotes and escapes + value = value + .substr(1, value.length - 2) + .replace(qescRegExp, '$1') + } + + params[key] = value + } + + if (index !== -1 && index !== string.length) { + throw new TypeError('invalid parameter format') + } + + obj.parameters = params + + return obj +} + +/** + * Get content-type from req/res objects. + * + * @param {object} + * @return {Object} + * @api private + */ + +function getcontenttype(obj) { + if (typeof obj.getHeader === 'function') { + // res-like + return obj.getHeader('content-type') + } + + if (typeof obj.headers === 'object') { + // req-like + return obj.headers && obj.headers['content-type'] + } +} + +/** + * Quote a string if necessary. + * + * @param {string} val + * @return {string} + * @api private + */ + +function qstring(val) { + var str = String(val) + + // no need to quote tokens + if (tokenRegExp.test(str)) { + return str + } + + if (str.length > 0 && !textRegExp.test(str)) { + throw new TypeError('invalid parameter value') + } + + return '"' + str.replace(quoteRegExp, '\\$1') + '"' +} + +/** + * Simply "type/subtype+siffx" into parts. + * + * @param {string} string + * @return {Object} + * @api private + */ + +function splitType(string) { + var match = typeRegExp.exec(string.toLowerCase()) + + if (!match) { + throw new TypeError('invalid media type') + } + + var type = match[1] + var subtype = match[2] + var suffix + + // suffix after last + + var index = subtype.lastIndexOf('+') + if (index !== -1) { + suffix = subtype.substr(index + 1) + subtype = subtype.substr(0, index) + } + + var obj = { + type: type, + subtype: subtype, + suffix: suffix + } + + return obj +} diff --git a/hm_sunwell/node_modules/media-typer/package.json b/hm_sunwell/node_modules/media-typer/package.json new file mode 100644 index 0000000..bffdd80 --- /dev/null +++ b/hm_sunwell/node_modules/media-typer/package.json @@ -0,0 +1,84 @@ +{ + "_args": [ + [ + "media-typer@0.3.0", + "/home/xor/shared_vm/git/node-sunwell/node_modules/type-is" + ] + ], + "_from": "media-typer@0.3.0", + "_id": "media-typer@0.3.0", + "_inCache": true, + "_installable": true, + "_location": "/media-typer", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.21", + "_phantomChildren": {}, + "_requested": { + "name": "media-typer", + "raw": "media-typer@0.3.0", + "rawSpec": "0.3.0", + "scope": null, + "spec": "0.3.0", + "type": "version" + }, + "_requiredBy": [ + "/type-is" + ], + "_resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "_shasum": "8710d7af0aa626f8fffa1ce00168545263255748", + "_shrinkwrap": null, + "_spec": "media-typer@0.3.0", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/type-is", + "author": { + "email": "doug@somethingdoug.com", + "name": "Douglas Christopher Wilson" + }, + "bugs": { + "url": "https://github.com/jshttp/media-typer/issues" + }, + "dependencies": {}, + "description": "Simple RFC 6838 media type parser and formatter", + "devDependencies": { + "istanbul": "0.3.2", + "mocha": "~1.21.4", + "should": "~4.0.4" + }, + "directories": {}, + "dist": { + "shasum": "8710d7af0aa626f8fffa1ce00168545263255748", + "tarball": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "gitHead": "d49d41ffd0bb5a0655fa44a59df2ec0bfc835b16", + "homepage": "https://github.com/jshttp/media-typer", + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "media-typer", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/media-typer.git" + }, + "scripts": { + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "0.3.0" +} diff --git a/hm_sunwell/node_modules/merge-descriptors/HISTORY.md b/hm_sunwell/node_modules/merge-descriptors/HISTORY.md new file mode 100644 index 0000000..486771f --- /dev/null +++ b/hm_sunwell/node_modules/merge-descriptors/HISTORY.md @@ -0,0 +1,21 @@ +1.0.1 / 2016-01-17 +================== + + * perf: enable strict mode + +1.0.0 / 2015-03-01 +================== + + * Add option to only add new descriptors + * Add simple argument validation + * Add jsdoc to source file + +0.0.2 / 2013-12-14 +================== + + * Move repository to `component` organization + +0.0.1 / 2013-10-29 +================== + + * Initial release diff --git a/hm_sunwell/node_modules/merge-descriptors/LICENSE b/hm_sunwell/node_modules/merge-descriptors/LICENSE new file mode 100644 index 0000000..274bfd8 --- /dev/null +++ b/hm_sunwell/node_modules/merge-descriptors/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hm_sunwell/node_modules/merge-descriptors/README.md b/hm_sunwell/node_modules/merge-descriptors/README.md new file mode 100644 index 0000000..d593c0e --- /dev/null +++ b/hm_sunwell/node_modules/merge-descriptors/README.md @@ -0,0 +1,48 @@ +# Merge Descriptors + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Merge objects using descriptors. + +```js +var thing = { + get name() { + return 'jon' + } +} + +var animal = { + +} + +merge(animal, thing) + +animal.name === 'jon' +``` + +## API + +### merge(destination, source) + +Redefines `destination`'s descriptors with `source`'s. + +### merge(destination, source, false) + +Defines `source`'s descriptors on `destination` if `destination` does not have +a descriptor by the same name. + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/merge-descriptors.svg +[npm-url]: https://npmjs.org/package/merge-descriptors +[travis-image]: https://img.shields.io/travis/component/merge-descriptors/master.svg +[travis-url]: https://travis-ci.org/component/merge-descriptors +[coveralls-image]: https://img.shields.io/coveralls/component/merge-descriptors/master.svg +[coveralls-url]: https://coveralls.io/r/component/merge-descriptors?branch=master +[downloads-image]: https://img.shields.io/npm/dm/merge-descriptors.svg +[downloads-url]: https://npmjs.org/package/merge-descriptors diff --git a/hm_sunwell/node_modules/merge-descriptors/index.js b/hm_sunwell/node_modules/merge-descriptors/index.js new file mode 100644 index 0000000..573b132 --- /dev/null +++ b/hm_sunwell/node_modules/merge-descriptors/index.js @@ -0,0 +1,60 @@ +/*! + * merge-descriptors + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = merge + +/** + * Module variables. + * @private + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty + +/** + * Merge the property descriptors of `src` into `dest` + * + * @param {object} dest Object to add descriptors to + * @param {object} src Object to clone descriptors from + * @param {boolean} [redefine=true] Redefine `dest` properties with `src` properties + * @returns {object} Reference to dest + * @public + */ + +function merge(dest, src, redefine) { + if (!dest) { + throw new TypeError('argument dest is required') + } + + if (!src) { + throw new TypeError('argument src is required') + } + + if (redefine === undefined) { + // Default to true + redefine = true + } + + Object.getOwnPropertyNames(src).forEach(function forEachOwnPropertyName(name) { + if (!redefine && hasOwnProperty.call(dest, name)) { + // Skip desriptor + return + } + + // Copy descriptor + var descriptor = Object.getOwnPropertyDescriptor(src, name) + Object.defineProperty(dest, name, descriptor) + }) + + return dest +} diff --git a/hm_sunwell/node_modules/merge-descriptors/package.json b/hm_sunwell/node_modules/merge-descriptors/package.json new file mode 100644 index 0000000..594b1da --- /dev/null +++ b/hm_sunwell/node_modules/merge-descriptors/package.json @@ -0,0 +1,164 @@ +{ + "_args": [ + [ + "merge-descriptors@1.0.1", + "/home/xor/shared_vm/git/node-sunwell/node_modules/express" + ] + ], + "_from": "merge-descriptors@1.0.1", + "_id": "merge-descriptors@1.0.1", + "_inCache": true, + "_installable": true, + "_location": "/merge-descriptors", + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "merge-descriptors", + "raw": "merge-descriptors@1.0.1", + "rawSpec": "1.0.1", + "scope": null, + "spec": "1.0.1", + "type": "version" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "_shasum": "b00aaa556dd8b44568150ec9d1b953f3f90cbb61", + "_shrinkwrap": null, + "_spec": "merge-descriptors@1.0.1", + "_where": "/home/xor/shared_vm/git/node-sunwell/node_modules/express", + "author": { + "email": "me@jongleberry.com", + "name": "Jonathan Ong", + "url": "http://jongleberry.com" + }, + "bugs": { + "url": "https://github.com/component/merge-descriptors/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Mike Grabowski", + "email": "grabbou@gmail.com" + } + ], + "dependencies": {}, + "description": "Merge objects using descriptors", + "devDependencies": { + "istanbul": "0.4.1", + "mocha": "1.21.5" + }, + "directories": {}, + "dist": { + "shasum": "b00aaa556dd8b44568150ec9d1b953f3f90cbb61", + "tarball": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "gitHead": "f26c49c3b423b0b2ac31f6e32a84e1632f2d7ac2", + "homepage": "https://github.com/component/merge-descriptors", + "license": "MIT", + "maintainers": [ + { + "name": "mattmueller", + "email": "mattmuelle@gmail.com" + }, + { + "name": "anthonyshort", + "email": "antshort@gmail.com" + }, + { + "name": "dfcreative", + "email": "df.creative@gmail.com" + }, + { + "name": "dominicbarnes", + "email": "dominic@dbarnes.info" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "ianstormtaylor", + "email": "ian@ianstormtaylor.com" + }, + { + "name": "jonathanong", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "juliangruber", + "email": "julian@juliangruber.com" + }, + { + "name": "clintwood", + "email": "clint@anotherway.co.za" + }, + { + "name": "queckezz", + "email": "fabian.eichenberger@gmail.com" + }, + { + "name": "stephenmathieson", + "email": "me@stephenmathieson.com" + }, + { + "name": "thehydroimpulse", + "email": "dnfagnan@gmail.com" + }, + { + "name": "timaschew", + "email": "timaschew@gmail.com" + }, + { + "name": "timoxley", + "email": "secoif@gmail.com" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + { + "name": "trevorgerhardt", + "email": "trevorgerhardt@gmail.com" + }, + { + "name": "yields", + "email": "yields@icloud.com" + } + ], + "name": "merge-descriptors", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/component/merge-descriptors.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" + }, + "version": "1.0.1" +} diff --git a/hm_sunwell/node_modules/methods/HISTORY.md b/hm_sunwell/node_modules/methods/HISTORY.md new file mode 100644 index 0000000..c0ecf07 --- /dev/null +++ b/hm_sunwell/node_modules/methods/HISTORY.md @@ -0,0 +1,29 @@ +1.1.2 / 2016-01-17 +================== + + * perf: enable strict mode + +1.1.1 / 2014-12-30 +================== + + * Improve `browserify` support + +1.1.0 / 2014-07-05 +================== + + * Add `CONNECT` method + +1.0.1 / 2014-06-02 +================== + + * Fix module to work with harmony transform + +1.0.0 / 2014-05-08 +================== + + * Add `PURGE` method + +0.1.0 / 2013-10-28 +================== + + * Add `http.METHODS` support diff --git a/hm_sunwell/node_modules/methods/LICENSE b/hm_sunwell/node_modules/methods/LICENSE new file mode 100644 index 0000000..220dc1a --- /dev/null +++ b/hm_sunwell/node_modules/methods/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2013-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/hm_sunwell/package.json b/hm_sunwell/package.json new file mode 100644 index 0000000..764f2c0 --- /dev/null +++ b/hm_sunwell/package.json @@ -0,0 +1,32 @@ +{ + "name": "node-sunwell", + "version": "0.1.1", + "description": "Canvas based renderer for Hearthstone cards.", + "main": "sunwell.js", + "scripts": { + "start": "node examples/server", + "test": "istanbul cover ./node_modules/mocha/bin/_mocha", + "coveralls": "cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", + "postpublish": "git push && git push --tags" + }, + "repository": "matkl/node-sunwell", + "keywords": [ + "hearthstone" + ], + "author": "Matthias Klein ", + "license": "MIT", + "bugs": { + "url": "https://github.com/matkl/node-sunwell/issues" + }, + "homepage": "https://github.com/matkl/node-sunwell#readme", + "dependencies": { + "canvas": "^1.3.13" + }, + "devDependencies": { + "chai": "^3.5.0", + "coveralls": "^2.11.9", + "express": "^4.13.4", + "istanbul": "^0.4.3", + "mocha": "^2.4.5" + } +} diff --git a/hm_sunwell/sunwell.js b/hm_sunwell/sunwell.js new file mode 100644 index 0000000..f35f443 --- /dev/null +++ b/hm_sunwell/sunwell.js @@ -0,0 +1,1235 @@ +var fs = require('fs'); +var path = require('path'); +var Canvas = require('canvas'); +var Image = Canvas.Image; + +/** + * Sunwell + * ======= + * Sunwell is a renderer for hearthstone cards. + * + * @author Christian Engel + * @author Matthias Klein (node.js port) + */ + +module.exports = function(settings) { + 'use strict'; + + var sunwell = {}, + pluralRegex = /(\d+)(.+?)\|4\((.+?),(.+?)\)/g, + validRarity = ['COMMON', 'RARE', 'EPIC', 'LEGENDARY']; + + function log(msg) { + if (!sunwell.settings.debug) { + return; + } + console.log(msg); + } + + /** + * Returns a new render buffer (canvas). + * @returns {*} + */ + function getBuffer() { + return new Canvas(); + } + + var imgReplacement; + + function getMissingImg(assetId) { + log('Substitute for ' + assetId); + + if (imgReplacement) { + return imgReplacement; + } + + var buffer = getBuffer(), + bufferctx = buffer.getContext('2d'); + buffer.width = buffer.height = 512; + bufferctx.save(); + bufferctx.fillStyle = 'grey'; + bufferctx.fillRect(0, 0, 512, 512); + bufferctx.fill(); + bufferctx.fillStyle = 'red'; + bufferctx.textAlign = 'center'; + bufferctx.textBaseline = 'middle'; + bufferctx.font = '50px Belwe'; + bufferctx.fillText('missing artwork', 256, 256); + bufferctx.restore(); + imgReplacement = new Image(); + imgReplacement.src = buffer.toBuffer(); + return imgReplacement; + } + + sunwell.settings = settings || {}; + + sunwell.settings.titleFont = sunwell.settings.titleFont || 'Belwe Bold'; + sunwell.settings.bodyFont = sunwell.settings.bodyFont || 'ITC Franklin Condensed'; + sunwell.settings.bodyFontSize = sunwell.settings.bodyFontSize || 60; + sunwell.settings.bodyFontOffset = sunwell.settings.bodyFontOffset || {x: 0, y: 0}; + sunwell.settings.bodyLineHeight = sunwell.settings.bodyLineHeight || 50; + sunwell.settings.assetFolder = sunwell.settings.assetFolder || path.join(__dirname, 'assets'); + sunwell.settings.assetExtension = sunwell.settings.assetExtension || 'png'; + sunwell.settings.textureFolder = sunwell.settings.textureFolder || path.join(__dirname, 'artwork'); + sunwell.settings.textureExtension = sunwell.settings.textureExtension || 'jpg'; + sunwell.settings.smallTextureFolder = sunwell.settings.smallTextureFolder || null; + sunwell.settings.smallTextureExtension = sunwell.settings.smallTextureExtension || 'jpg'; + sunwell.settings.autoInit = sunwell.settings.autoInit || true; + sunwell.settings.idAsTexture = sunwell.settings.idAsTexture || false; + + + sunwell.settings.debug = sunwell.settings.debug || false; + + sunwell.races = { + 'enUS': { + 'MURLOC': 'Murloc', + 'MECHANICAL': 'Mech', + 'BEAST': 'Beast', + 'DEMON': 'Demon', + 'PIRATE': 'Pirate', + 'DRAGON': 'Dragon', + 'TOTEM': 'Totem', + 'HERO': 'Hero' + }, + "deDE": { + 'MURLOC': 'Murloc', + 'MECHANICAL': 'Mech', + 'BEAST': 'Wildtier', + 'DEMON': 'Dämon', + 'PIRATE': 'Pirat', + 'DRAGON': 'Drache', + 'TOTEM': 'Totem' + } + }; + + /** + * Calculate the checksum for an object. + * @param o + * @returns {number} + */ + function checksum(o) { + var i, key, s = ''; + var chk = 0x12345678; + + for (key in o) { + s = s + key + o[key]; + } + + for (i = 0; i < s.length; i++) { + chk += (s.charCodeAt(i) * (i + 1)); + } + + return chk; + } + + /** + * Helper function to draw the oval mask for the cards artwork. + * @param ctx + * @param x + * @param y + * @param w + * @param h + */ + function drawEllipse(ctx, x, y, w, h) { + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + ctx.beginPath(); + ctx.moveTo(x, ym); + ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + //ctx.closePath(); // not used correctly, see comments (use to close off open path) + ctx.stroke(); + } + + /** + * Preloads the basic card assets. + * You can call this before you start to render any cards, but you don't have to. + */ + function fetchAssets(loadAssets) { + return new Promise(function (resolve) { + var loaded = 0, + loadingTotal = 1, + assets = {}, + key, + isTexture, + smallTexture, + isUrl, + srcURL; + + for (var i = 0; i < loadAssets.length; i++) { + key = loadAssets[i]; + isTexture = false; + smallTexture = false; + + if (key.substr(0, 2) === 'h:') { + isTexture = true; + smallTexture = !!(sunwell.settings.smallTextureFolder && true); + key = key.substr(2); + } + + if (key.substr(0, 2) === 't:') { + isTexture = true; + key = key.substr(2); + if (assets[key] !== undefined) { + if (assets[key].width === 256) { + assets[key] = undefined; + } + } + } + + if (key.substr(0, 2) === 'u:') { + isUrl = true; + key = key.substr(2); + } + + assets[key] = new Image(); + assets[key].crossOrigin = "Anonymous"; + assets[key].loaded = false; + loadingTotal++; + (function (key) { + assets[key].onload = function () { + loaded++; + assets[key].loaded = true; + if (!assets[key].width || !assets[key].height) { + assets[key] = getMissingImg(); + } + if (loaded >= loadingTotal) { + resolve(assets); + } + }; + assets[key].onerror = function () { + loaded++; + + assets[key] = getMissingImg(); + if (loaded >= loadingTotal) { + resolve(assets); + } + }; + })(key); + if (isUrl) { + assets[key].src = key; + } else { + if (isTexture) { + assets[key].isTexture = true; + if (smallTexture) { + srcURL = path.join(sunwell.settings.smallTextureFolder, key + '.' + sunwell.settings.smallTextureExtension); + } else { + srcURL = path.join(sunwell.settings.textureFolder, key + '.' + sunwell.settings.textureExtension); + } + } else { + srcURL = path.join(sunwell.settings.assetFolder, key + '.' + sunwell.settings.assetExtension); + } + log('Requesting ' + srcURL); + assets[key].src = srcURL; + } + } + + loadingTotal--; + if (loaded > 0 && loaded >= loadingTotal) { + resolve(assets); + } + }); + } + + /** + * Get the bounding box of a canvas' content. + * @param ctx + * @param alphaThreshold + * @returns {{x: *, y: *, maxX: (number|*|w), maxY: *, w: number, h: number}} + */ + function contextBoundingBox(ctx) { + var w = ctx.canvas.width, h = ctx.canvas.height; + var data = ctx.getImageData(0, 0, w, h).data; + var x, y, minX = 999, minY = 999, maxX = 0, maxY = 0; + + var out = false; + + for (y = h - 1; y > -1; y--) { + if (out) { + break; + } + for (x = 0; x < w; x++) { + if (data[((y * (w * 4)) + (x * 4)) + 3] > 0) { + maxY = Math.max(maxY, y); + out = true; + break; + } + } + } + + if (maxY === undefined) { + return null; + } + + out2: + for (x = w - 1; x > -1; x--) { + for (y = 0; y < h; y++) { + if (data[((y * (w * 4)) + (x * 4)) + 3] > 0) { + maxX = Math.max(maxX, x); + break out2; + } + } + } + + out3: + for (x = 0; x < maxX; x++) { + for (y = 0; y < h; y++) { + if (data[((y * (w * 4)) + (x * 4)) + 3] > 0) { + minX = Math.min(x, minX); + break out3; + } + } + } + + out4: + for (y = 0; y < maxY; y++) { + for (x = 0; x < w; x++) { + if (data[((y * (w * 4)) + (x * 4)) + 3] > 0) { + minY = Math.min(minY, y); + break out4; + } + } + } + + return {x: minX, y: minY, maxX: maxX, maxY: maxY, w: maxX - minX, h: maxY - minY}; + } + + function renderRaceText(targetCtx, s, card) { + var text, x; + + if (sunwell.races[card.language]) { + if (sunwell.races[card.language][card.race]) { + text = sunwell.races[card.language][card.race]; + } else { + text = card.race; + } + } else { + if (sunwell.races['enUS'][card.race]) { + text = sunwell.races['enUS'][card.race]; + } else { + text = card.race; + } + } + + var buffer = getBuffer(); + var bufferCtx = buffer.getContext('2d'); + + buffer.width = 300; + buffer.height = 60; + + bufferCtx.font = '45px Belwe'; + + bufferCtx.lineCap = 'round'; + bufferCtx.lineJoin = 'round'; + bufferCtx.textBaseline = 'hanging'; + + bufferCtx.textAlign = 'left'; + + text = text.split(''); + + x = 10; + + for (var i = 0; i < text.length; i++) { + bufferCtx.lineWidth = 8; + bufferCtx.strokeStyle = 'black'; + bufferCtx.fillStyle = 'black'; + bufferCtx.fillText(text[i], x, 10); + bufferCtx.strokeText(text[i], x, 10); + + bufferCtx.fillStyle = 'white'; + bufferCtx.strokeStyle = 'white'; + bufferCtx.lineWidth = 1; + bufferCtx.fillText(text[i], x, 10); + //ctx.strokeText(text[i], x, y); + + x += bufferCtx.measureText(text[i]).width; + } + + var b = contextBoundingBox(bufferCtx); + + targetCtx.drawImage(buffer, b.x, b.y, b.w, b.h, (394 - (b.w / 2)) * s, (1001 - (b.h / 2)) * s, b.w * s, b.h * s); + } + + /** + * Renders a given number to the defined position. + * The x/y position should be the position on an unscaled card. + * + * @param targetCtx + * @param x + * @param y + * @param s + * @param number + * @param size + * @param [drawStyle="0"] Either "+", "-" or "0". Default: "0" + */ + function drawNumber(targetCtx, x, y, s, number, size, drawStyle) { + var buffer = getBuffer(); + var bufferCtx = buffer.getContext('2d'); + + if (drawStyle === undefined) { + drawStyle = '0'; + } + + buffer.width = 256; + buffer.height = 256; + + number = number.toString(); + + number = number.split(''); + + var tX = 10; + + bufferCtx.font = size + 'px Belwe'; + + bufferCtx.lineCap = 'round'; + bufferCtx.lineJoin = 'round'; + bufferCtx.textBaseline = 'hanging'; + + bufferCtx.textAlign = 'left'; + + var color = 'white'; + + if (drawStyle === '-') { + color = '#f00'; + } + + if (drawStyle === '+') { + color = '#0f0'; + } + + for (var i = 0; i < number.length; i++) { + bufferCtx.lineWidth = 13; + bufferCtx.strokeStyle = 'black'; + bufferCtx.fillStyle = 'black'; + bufferCtx.fillText(number[i], tX, 10); + bufferCtx.strokeText(number[i], tX, 10); + + bufferCtx.fillStyle = color; + bufferCtx.strokeStyle = color; + bufferCtx.lineWidth = 2.5; + bufferCtx.fillText(number[i], tX, 10); + //ctx.strokeText(text[i], x, y); + + tX += bufferCtx.measureText(number[i]).width; + } + + var b = contextBoundingBox(bufferCtx); + + targetCtx.drawImage(buffer, b.x, b.y, b.w, b.h, (x - (b.w / 2)) * s, (y - (b.h / 2)) * s, b.w * s, b.h * s); + } + + /** + * Finishes a text line and starts a new one. + * @param bufferTextCtx + * @param bufferRow + * @param bufferRowCtx + * @param xPos + * @param yPos + * @param totalWidth + * @returns {*[]} + */ + function finishLine(bufferTextCtx, bufferRow, bufferRowCtx, xPos, yPos, totalWidth) { + if (sunwell.settings.debug) { + bufferTextCtx.save(); + bufferTextCtx.strokeStyle = 'red'; + bufferTextCtx.beginPath(); + bufferTextCtx.moveTo((totalWidth / 2) - (xPos / 2), yPos); + bufferTextCtx.lineTo((totalWidth / 2) + (xPos / 2), yPos); + bufferTextCtx.stroke(); + bufferTextCtx.restore(); + } + + var xCalc = (totalWidth / 2) - (xPos / 2); + + if (xCalc < 0) { + xCalc = 0; + } + + if (xPos > 0 && bufferRow.width > 0) { + bufferTextCtx.drawImage( + bufferRow, + 0, + 0, + xPos > bufferRow.width ? bufferRow.width : xPos, + bufferRow.height, + xCalc, + yPos, + Math.min(xPos, bufferRow.width), + bufferRow.height + ); + } + + xPos = 5; + yPos += bufferRow.height; + bufferRowCtx.clearRect(0, 0, bufferRow.width, bufferRow.height); + + return [xPos, yPos]; + } + + /** + * Renders the HTML body text of a card. + * @param targetCtx + * @param s + * @param card + */ + function drawBodyText(targetCtx, s, card, forceSmallerFirstLine) { + var manualBreak = card.text.substr(0, 3) === '[x]', + bufferText = getBuffer(), + bufferTextCtx = bufferText.getContext('2d'), + bufferRow = getBuffer(), + bufferRowCtx = bufferRow.getContext('2d'), + bodyText = manualBreak ? card.text.substr(3) : card.text, + words, + word, + chars, + char, + width, + spaceWidth, + xPos = 0, + yPos = 0, + isBold = 0, + isItalic = 0, + i, + j, + r, + centerLeft, + centerTop, + justLineBreak, + lineCount = 0, + plurals, + pBodyText; + + + pBodyText = bodyText; + while((plurals = pluralRegex.exec(bodyText)) !== null){ + pBodyText = pBodyText.replace(plurals[0], plurals[1] + plurals[2] + (parseInt(plurals[1], 10) === 1 ? plurals[3] : plurals[4])); + } + bodyText = pBodyText; + + words = bodyText.replace(/[\$#_]/g, '').split(/( |\n)/g); + + log('Rendering body: ' + bodyText); + + centerLeft = 390; + centerTop = 860; + bufferText.width = 520; + bufferText.height = 290; + + bufferRow.width = 520; + + if (card.type === 'SPELL') { + bufferText.width = 460; + bufferText.height = 290; + + bufferRow.width = 460; + } + + if (card.type === 'WEAPON') { + bufferText.width = 470; + bufferText.height = 250; + + bufferRow.width = 470; + } + + var fontSize = sunwell.settings.bodyFontSize; + var lineHeight = sunwell.settings.bodyLineHeight; + var totalLength = card.text.replace(/<\/*.>/g, '').length; + var smallerFirstLine = false; + + if (totalLength >= 80) { + fontSize = sunwell.settings.bodyFontSize * 0.9; + lineHeight = sunwell.settings.bodyLineHeight * 0.9; + } + + if (totalLength >= 100) { + fontSize = sunwell.settings.bodyFontSize * 0.8; + lineHeight = sunwell.settings.bodyLineHeight * 0.8; + } + + bufferRow.height = lineHeight; + + + if (totalLength >= 75 && card.type === 'SPELL') { + smallerFirstLine = true; + } + + if(forceSmallerFirstLine){ + smallerFirstLine = true; + } + + if (card.type === 'WEAPON') { + bufferRowCtx.fillStyle = '#fff'; + } else { + bufferRowCtx.fillStyle = '#000'; + } + bufferRowCtx.textBaseline = 'hanging'; + + bufferRowCtx.font = fontSize + 'px "' + sunwell.settings.bodyFont + '", sans-serif'; + + spaceWidth = 3; + + for (i = 0; i < words.length; i++) { + word = words[i]; + + chars = word.split(''); + + width = bufferRowCtx.measureText(word).width; + log('Next word: ' + word); + + if (!manualBreak && (xPos + width > bufferRow.width || (smallerFirstLine && xPos + width > bufferRow.width * 0.8))) { + log((xPos + width) + ' > ' + bufferRow.width); + log('Calculated line break'); + smallerFirstLine = false; + lineCount++; + r = finishLine(bufferTextCtx, bufferRow, bufferRowCtx, xPos, yPos, bufferText.width); + xPos = r[0]; + yPos = r[1]; + justLineBreak = true; + } + + for (j = 0; j < chars.length; j++) { + char = chars[j]; + + log(char + ' ' + char.charCodeAt(0)); + + if (char.charCodeAt(0) === 10) { + if (justLineBreak) { + justLineBreak = false; + continue; + } + lineCount++; + r = finishLine(bufferTextCtx, bufferRow, bufferRowCtx, xPos, yPos, bufferText.width); + xPos = r[0]; + yPos = r[1]; + log('Manual line break'); + continue; + } + + justLineBreak = false; + + if (char === '<') { + if (chars[j + 1] === '/') { + if (chars[j + 2] === 'b') { + isBold--; + j += 3; + } + + if (chars[j + 2] === 'i') { + isItalic--; + j += 3; + } + } else { + if (chars[j + 1] === 'b') { + isBold++; + j += 2; + } + + if (chars[j + 1] === 'i') { + isItalic++; + j += 2; + } + } + + bufferRowCtx.font = (isBold > 0 ? 'bold ' : '') + (isItalic > 0 ? 'italic' : '') + ' ' + fontSize + 'px/1em "' + sunwell.settings.bodyFont + '", sans-serif'; + continue; + } + + bufferRowCtx.fillText(char, xPos + sunwell.settings.bodyFontOffset.x, sunwell.settings.bodyFontOffset.y); + + xPos += bufferRowCtx.measureText(char).width + (spaceWidth / 8); + } + + xPos += spaceWidth; + } + + lineCount++; + finishLine(bufferTextCtx, bufferRow, bufferRowCtx, xPos, yPos, bufferText.width); + + if(card.type === 'SPELL' && lineCount === 4){ + if(!smallerFirstLine && !forceSmallerFirstLine){ + drawBodyText(targetCtx, s, card, true); + return; + } + } + + var b = contextBoundingBox(bufferTextCtx); + + b.h = Math.ceil(b.h / bufferRow.height) * bufferRow.height; + + targetCtx.drawImage(bufferText, b.x, b.y - 2, b.w, b.h, (centerLeft - (b.w / 2)) * s, (centerTop - (b.h / 2)) * s, b.w * s, (b.h + 2) * s); + + if (sunwell.settings.debug) { + targetCtx.save(); + targetCtx.strokeStyle = 'green'; + targetCtx.beginPath(); + targetCtx.rect((centerLeft - (b.w / 2)) * s, (centerTop - (b.h / 2)) * s, b.w * s, (b.h + 2) * s); + targetCtx.stroke(); + targetCtx.strokeStyle = 'red'; + targetCtx.beginPath(); + targetCtx.rect((centerLeft - (bufferText.width / 2)) * s, (centerTop - (bufferText.height / 2)) * s, bufferText.width * s, (bufferText.height + 2) * s); + targetCtx.stroke(); + targetCtx.restore(); + } + } + + /** + * Given a curve and t, the function returns the point on the curve. + * r is the rotation of the point in radians. + * @param curve + * @param t + * @returns {{x: (number|*), y: (number|*), r: number}} + */ + function getPointOnCurve(curve, t) { + + var rX, rY, x, y; + + rX = 3 * Math.pow(1 - t, 2) * (curve[1].x - curve[0].x) + 6 * (1 - t) * t * (curve[2].x - curve[1].x) + 3 * Math.pow(t, 2) * (curve[3].x - curve[2].x); + rY = 3 * Math.pow(1 - t, 2) * (curve[1].y - curve[0].y) + 6 * (1 - t) * t * (curve[2].y - curve[1].y) + 3 * Math.pow(t, 2) * (curve[3].y - curve[2].y); + + x = Math.pow((1 - t), 3) * curve[0].x + 3 * Math.pow((1 - t), 2) * t * curve[1].x + 3 * (1 - t) * Math.pow(t, 2) * curve[2].x + Math.pow(t, 3) * curve[3].x; + y = Math.pow((1 - t), 3) * curve[0].y + 3 * Math.pow((1 - t), 2) * t * curve[1].y + 3 * (1 - t) * Math.pow(t, 2) * curve[2].y + Math.pow(t, 3) * curve[3].y; + + return { + x: x, + y: y, + r: Math.atan2(rY, rX) + } + } + + /** + * Prints the title of a card. + * @param title + */ + function drawCardTitle(targetCtx, s, card) { + var buffer = getBuffer(); + var title = card.title; + buffer.width = 1024; + buffer.height = 200; + var ctx = buffer.getContext('2d'); + var boundaries; + ctx.save(); + + var pathMiddle = .58; + var maxWidth = 580; + + //Path midpoint at t = 0.56 + var c = [ + {x: 0, y: 110}, + {x: 102, y: 137}, + {x: 368, y: 16}, + {x: 580, y: 100} + ]; + + if (card.type === 'SPELL') { + pathMiddle = .52; + maxWidth = 580; + c = [ + {x: 10, y: 100}, + {x: 212, y: 35}, + {x: 368, y: 35}, + {x: 570, y: 105} + ] + } + + if (card.type === 'WEAPON') { + pathMiddle = .58; + maxWidth = 580; + c = [ + {x: 10, y: 75}, + {x: 50, y: 75}, + {x: 500, y: 75}, + {x: 570, y: 75} + ] + } + + var fontSize = 51; + + ctx.lineWidth = 13; + ctx.strokeStyle = 'black'; + + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + + var textWidth = maxWidth + 1; + var steps, + begin; + + while (textWidth > maxWidth && fontSize > 10) { + fontSize -= 1; + ctx.font = fontSize + 'px Belwe'; + textWidth = 0; + for (var i = 0; i < title.length; i++) { + textWidth += ctx.measureText(title[i]).width + 2; + } + + textWidth *= 1.25; + } + + textWidth = textWidth / maxWidth; + begin = pathMiddle - (textWidth / 2); + steps = textWidth / title.length; + + if (sunwell.settings.debug) { + ctx.save(); + ctx.strokeStyle = 'red'; + ctx.lineWidth = 5; + ctx.beginPath(); + ctx.moveTo(c[0].x, c[0].y); + ctx.bezierCurveTo(c[1].x, c[1].y, c[2].x, c[2].y, c[3].x, c[3].y); + ctx.stroke(); + ctx.restore(); + } + + var p, t, leftPos = 0, m; + for (i = 0; i < title.length; i++) { + if (leftPos === 0) { + t = begin + (steps * i); + p = getPointOnCurve(c, t); + leftPos = p.x; + } else { + t += 0.01; + p = getPointOnCurve(c, t); + while (p.x < leftPos) { + t += 0.001; + p = getPointOnCurve(c, t); + } + } + + ctx.save(); + ctx.translate(p.x, p.y); + + ctx.scale(1.2, 1); + //ctx.setTransform(1.2, p.r, 0, 1, p.x, p.y); + ctx.rotate(p.r); + + ctx.lineWidth = 10 * (fontSize / 50); + ctx.strokeStyle = 'black'; + ctx.fillStyle = 'black'; + ctx.fillText(title[i], 0, 0); + ctx.strokeText(title[i], 0, 0); + m = ctx.measureText(title[i]).width * 1.25; + leftPos += m; + + if (['i', 'f'].indexOf(title[i]) !== -1) { + leftPos += m * 0.1; + } + + ctx.fillStyle = 'white'; + ctx.strokeStyle = 'white'; + ctx.lineWidth = 2.5 * (fontSize / 50); + ctx.fillText(title[i], 0, 0); + + ctx.restore(); + } + + targetCtx.drawImage( + buffer, + 0, + 0, + 580, + 200, + + (395 - (580 / 2)) * s, + (725 - 200) * s, + 580 * s, + 200 * s + ); + } + + function draw(getAsset, cvs, ctx, card, s, callback, internalCB) { + + var sw = card.sunwell, + t, + drawTimeout, + drawProgress = 0, + renderStart = Date.now(); + + drawTimeout = setTimeout(function () { + log('Drawing timeout at point ' + drawProgress + ' in ' + card.title); + log(card); + internalCB(); + if (callback) { + callback(cvs); + } + }, 5000); + + if (typeof card.texture === 'string') { + t = getAsset(card.texture); + } else { + if (card.texture instanceof Image) { + t = card.texture; + } else { + t = getBuffer(); + t.width = card.texture.crop.w; + t.height = card.texture.crop.h; + (function () { + var tCtx = t.getContext('2d'); + tCtx.drawImage(card.texture.image, card.texture.crop.x, card.texture.crop.y, card.texture.crop.w, card.texture.crop.h, 0, 0, t.width, t.height); + })(); + } + } + + if (!t) { + t = getAsset('~'); + } + + drawProgress = 2; + + ctx.save(); + ctx.clearRect(0, 0, cvs.width, cvs.height); + + drawProgress = 3; + + ctx.save(); + if (card.type === 'MINION') { + drawEllipse(ctx, 180 * s, 75 * s, 430 * s, 590 * s); + ctx.clip(); + ctx.fillStyle = 'grey'; + ctx.fillRect(0, 0, 765 * s, 1100 * s); + ctx.drawImage(t, 0, 0, t.width, t.height, 100 * s, 75 * s, 590 * s, 590 * s); + } + + if (card.type === 'SPELL') { + ctx.rect(125 * s, 165 * s, 529 * s, 434 * s); + ctx.clip(); + ctx.fillStyle = 'grey'; + ctx.fillRect(0, 0, 765 * s, 1100 * s); + ctx.drawImage(t, 0, 0, t.width, t.height, 125 * s, 117 * s, 529 * s, 529 * s); + } + + if (card.type === 'WEAPON') { + drawEllipse(ctx, 150 * s, 135 * s, 476 * s, 468 * s); + ctx.clip(); + ctx.fillStyle = 'grey'; + ctx.fillRect(0, 0, 765 * s, 1100 * s); + ctx.drawImage(t, 0, 0, t.width, t.height, 150 * s, 135 * s, 476 * s, 476 * s); + } + ctx.restore(); + + drawProgress = 4; + + ctx.drawImage(getAsset(sw.cardBack), 0, 0, 764, 1100, 0, 0, cvs.width, cvs.height); + + drawProgress = 5; + + if(card.costHealth){ + ctx.drawImage(getAsset('health'), 0, 0, 167, 218, 24 * s, 62 * s, 167 * s, 218 * s); + ctx.save(); + ctx.shadowBlur=50*s; + ctx.shadowColor='#FF7275'; + ctx.shadowOffsetX = 1000; + ctx.globalAlpha = .5; + ctx.drawImage(getAsset('health'), 0, 0, 167, 218, (24 * s)-1000, 62 * s, 167 * s, 218 * s); + ctx.restore(); + } else { + ctx.drawImage(getAsset('gem'), 0, 0, 182, 180, 24 * s, 82 * s, 182 * s, 180 * s); + } + + drawProgress = 6; + + if (card.type === 'MINION') { + if (sw.rarity) { + ctx.drawImage(getAsset(sw.rarity), 0, 0, 146, 146, 326 * s, 607 * s, 146 * s, 146 * s); + } + + ctx.drawImage(getAsset('title'), 0, 0, 608, 144, 94 * s, 546 * s, 608 * s, 144 * s); + + if (card.race) { + ctx.drawImage(getAsset('race'), 0, 0, 529, 106, 125 * s, 937 * s, 529 * s, 106 * s); + } + + ctx.drawImage(getAsset('attack'), 0, 0, 214, 238, 0, 862 * s, 214 * s, 238 * s); + ctx.drawImage(getAsset('health'), 0, 0, 167, 218, 575 * s, 876 * s, 167 * s, 218 * s); + + if (card.rarity === 'LEGENDARY') { + ctx.drawImage(getAsset('dragon'), 0, 0, 569, 417, 196 * s, 0, 569 * s, 417 * s); + } + } + + drawProgress = 7; + + if (card.type === 'SPELL') { + if (sw.rarity) { + ctx.drawImage(getAsset(sw.rarity), 0, 0, 149, 149, 311 * s, 607 * s, 150 * s, 150 * s); + } + + ctx.drawImage(getAsset('title-spell'), 0, 0, 646, 199, 66 * s, 530 * s, 646 * s, 199 * s); + } + + if (card.type === 'WEAPON') { + if (sw.rarity) { + ctx.drawImage(getAsset(sw.rarity), 0, 0, 146, 144, 315 * s, 592 * s, 146 * s, 144 * s); + } + + ctx.drawImage(getAsset('title-weapon'), 0, 0, 660, 140, 56 * s, 551 * s, 660 * s, 140 * s); + + ctx.drawImage(getAsset('swords'), 0, 0, 312, 306, 32 * s, 906 * s, 187 * s, 183 * s); + ctx.drawImage(getAsset('shield'), 0, 0, 301, 333, 584 * s, 890 * s, 186 * s, 205 * s); + } + + drawProgress = 8; + + + if (card.set !== 'CORE') { + (function () { + var xPos; + + if (card.type === 'SPELL') { + xPos = 265; + } + + if (card.type === 'MINION') { + xPos = 265; + } + + if (card.race && card.type === 'MINION') { + ctx.drawImage(getAsset(sw.bgLogo), 0, 0, 281, 244, xPos * s, 734 * s, (281 * 0.95) * s, (244 * 0.95) * s); + } else { + if (card.type === 'SPELL') { + ctx.drawImage(getAsset(sw.bgLogo), 0, 0, 281, 244, xPos * s, 740 * s, 253 * s, 220 * s); + } else { + ctx.drawImage(getAsset(sw.bgLogo), 0, 0, 281, 244, xPos * s, 734 * s, 281 * s, 244 * s); + } + + } + })(); + } + + drawProgress = 9; + + + drawProgress = 10; + + drawNumber(ctx, 116, 170, s, card.cost || 0, 170, card.costStyle); + + drawProgress = 11; + + drawCardTitle(ctx, s, card); + + drawProgress = 12; + + if (card.type === 'MINION') { + if (card.race) { + renderRaceText(ctx, s, card); + } + + drawNumber(ctx, 128, 994, s, card.attack || 0, 150, card.attackStyle); + drawNumber(ctx, 668, 994, s, card.health || 0, 150, card.healthStyle); + } + + drawProgress = 13; + + if (card.type === 'WEAPON') { + drawNumber(ctx, 128, 994, s, card.attack || 0, 150, card.attackStyle); + drawNumber(ctx, 668, 994, s, card.durability || 0, 150, card.durabilityStyle); + } + + drawProgress = 14; + + if (!card.silenced || card.type !== 'MINION') { + drawBodyText(ctx, s, card); + } else { + ctx.drawImage(getAsset('silence-x'), 0, 0, 410, 397, 200 * s, 660 * s, 410 * s, 397 * s); + } + + ctx.restore(); + + clearTimeout(drawTimeout); + + log('Rendertime: ' + (Date.now() - renderStart) + 'ms'); + + internalCB(); + if (callback) { + callback(cvs); + } + } + + /** + * Renders the HS-API object, you pass to this function. + * @return Canvas + */ + function render(card, resolution, callback) { + log('Preparing assets for: ' + card.title); + + var cvs = getBuffer(), + ctx = cvs.getContext('2d'), + s = (resolution || 512) / 764, + loadList = ['silence-x']; + + cvs.width = resolution || 512; + cvs.height = Math.round(cvs.width * 1.4397905759); + + card.sunwell = card.sunwell || {}; + + card.sunwell.cardBack = card.type.substr(0, 1).toLowerCase() + card.playerClass.substr(0, 1) + card.playerClass.substr(1).toLowerCase(); + + loadList.push(card.sunwell.cardBack); + + loadList.push('gem'); + + if (card.type === 'MINION') { + loadList.push('attack', 'health', 'title'); + + if (card.rarity === 'LEGENDARY') { + loadList.push('dragon'); + } + + if (card.rarity !== 'FREE' && !(card.rarity === 'COMMON' && card.set === 'CORE')) { + card.sunwell.rarity = 'rarity-' + card.rarity.toLowerCase(); + loadList.push(card.sunwell.rarity); + } + } + + if (card.type === 'SPELL') { + loadList.push('attack', 'health', 'title-spell'); + + if (card.rarity !== 'FREE' && !(card.rarity === 'COMMON' && card.set === 'CORE')) { + card.sunwell.rarity = 'spell-rarity-' + card.rarity.toLowerCase(); + loadList.push(card.sunwell.rarity); + } + } + + if (card.type === 'WEAPON') { + loadList.push('swords', 'shield', 'title-weapon'); + + if (card.rarity !== 'FREE' && !(card.rarity === 'COMMON' && card.set === 'CORE')) { + card.sunwell.rarity = 'weapon-rarity-' + card.rarity.toLowerCase(); + loadList.push(card.sunwell.rarity); + } + } + + + if (['BRM', 'GVG', 'LOE', 'NAX', 'TGT', 'OG'].indexOf(card.set) === -1) { + card.sunwell.bgLogo = 'bg-cl'; + } else { + card.sunwell.bgLogo = 'bg-' + card.set.toLowerCase(); + } + + if (card.type === 'SPELL') { + card.sunwell.bgLogo = 'spell-' + card.sunwell.bgLogo; + } + + loadList.push(card.sunwell.bgLogo); + + if (card.race) { + loadList.push('race'); + } + + + if (typeof card.texture === 'string' && card.set !== 'CHEAT') { + if (s <= .5) { + loadList.push('h:' + card.texture); + } else { + loadList.push('t:' + card.texture); + } + } + + log('Assets prepared, now loading'); + + fetchAssets(loadList) + .then(function (assets) { + log('Assets loaded for: ' + card.title); + + function getAsset(id) { + return assets[id] || getMissingImg(id); + } + + draw(getAsset, cvs, ctx, card, s, callback, function () { + log('Card rendered: ' + card.title); + }); + }) + .catch(function(err) { + console.error(err.stack); + }); + }; + + /** + * Creates a new card object that can also be manipulated at a later point. + * Provide an image object as render target as output for the visual card data. + * @param settings + * @param width + * @param renderTarget + */ + sunwell.createCard = function (settings, width, callback) { + if (!settings) { + throw new Error('No card object given'); + } + + //Make compatible to tech cards + if (validRarity.indexOf(settings.rarity) === -1) { + settings.rarity = 'FREE'; + } + + //Make compatible to hearthstoneJSON format. + if (settings.title === undefined) { + settings.title = settings.name; + } + if (settings.gameId === undefined) { + settings.gameId = settings.id; + } + + if (sunwell.settings.idAsTexture) { + settings.texture = settings.gameId; + } + + settings.costStyle = settings.costStyle || '0'; + settings.healthStyle = settings.healthStyle || '0'; + settings.attackStyle = settings.attackStyle || '0'; + settings.durabilityStyle = settings.durabilityStyle || '0'; + + settings.silenced = settings.silenced || false; + settings.costHealth = settings.costHealth || false; + + settings.width = width; + + log('Queried render: ' + settings.title); + + render(settings, width, function (result) { + result.toBuffer(function(err, buffer) { + if (callback) { + callback(err, buffer); + } + }); + }); + + return { + redraw: function (callback) { + render(settings, width, function (result) { + result.toBuffer(function(err, buffer) { + if (callback) { + callback(err, buffer); + } + }); + }); + }, + update: function (properties, callback) { + for (var key in properties) { + settings[key] = properties[key]; + } + + cacheKey = checksum(settings); + + render(settings, width, function (result) { + result.toBuffer(function(err, buffer) { + if (callback) { + callback(err, buffer); + } + }); + }); + } + }; + } + + return sunwell; +}; diff --git a/hm_web/LICENSE b/hm_web/LICENSE new file mode 100644 index 0000000..e0345c0 --- /dev/null +++ b/hm_web/LICENSE @@ -0,0 +1,622 @@ + GNU GENERAL PUBLIC LICENSE + + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/hm_web/Makefile b/hm_web/Makefile new file mode 100644 index 0000000..e6b3fd0 --- /dev/null +++ b/hm_web/Makefile @@ -0,0 +1,10 @@ +DIR=.publish + +publish: + # publish + mkdir -p ~/git/clones/$(DIR) + rm -rf $(DIR) + mkdir $(DIR) + cp -r * $(DIR) + cd $(DIR) && rm -rf test test.sh *.pyc customMod static/images static/images sessions cache/cardsxml_p1 cache/cardsxml_p3 + tar cvvf web.tar $(DIR) && mv web.tar ~/git/clones/$(DIR) diff --git a/hm_web/README.md b/hm_web/README.md new file mode 100644 index 0000000..b7a5741 --- /dev/null +++ b/hm_web/README.md @@ -0,0 +1,7 @@ +# hm_web + +hearthmod web interface allows users to create account, sign in, modify decks, etc. + +# This is not a standalone project! + +[hm_web](https://github.com/farb3yonddriv3n/hm_web) is part of [hearthmod software stack](https://github.com/hearthmod/hearthmod) diff --git a/hm_web/all_tags.py b/hm_web/all_tags.py new file mode 100644 index 0000000..b9cbd2e --- /dev/null +++ b/hm_web/all_tags.py @@ -0,0 +1 @@ +tagsDict = {2: "tag_script_data_num_1", 3: "tag_script_data_num_2", 4: "tag_script_data_ent_1", 5: "tag_script_data_ent_2", 6: "mission_event", 7: "timeout", 8: "turn_start", 9: "turn_timer_slush", 12: "premium", 13: "gold_reward_state", 17: "playstate", 18: "last_affected_by", 19: "step", 20: "turn", 22: "fatigue", 23: "current_player", 24: "first_player", 25: "resources_used", 26: "resources", 27: "hero_entity", 28: "maxhandsize", 29: "starthandsize", 30: "player_id", 31: "team_id", 32: "trigger_visual", 33: "recently_arrived", 34: "protecting", 35: "protected", 36: "defending", 37: "proposed_defender", 38: "attacking", 39: "proposed_attacker", 40: "attached", 43: "exhausted", 44: "damage", 45: "health", 47: "atk", 48: "cost", 49: "zone", 50: "controller", 51: "owner", 52: "definition", 53: "entity_id", 54: "history_proxy", 55: "copy_deathrattle", 114: "elite", 176: "maxresources", 183: "card_set", 184: "cardtext_inhand", 185: "cardname", 186: "card_id", 187: "durability", 188: "silenced", 189: "windfury", 190: "taunt", 191: "stealth", 192: "spellpower", 194: "divine_shield", 197: "charge", 198: "next_step", 199: "class", 200: "cardrace", 201: "faction", 202: "cardtype", 203: "rarity", 204: "state", 205: "summoned", 208: "freeze", 212: "enraged", 215: "overload", 216: "loyalty", 217: "deathrattle", 218: "battlecry", 219: "secret", 220: "combo", 221: "cant_heal", 222: "cant_damage", 223: "cant_set_aside", 224: "cant_remove_from_game", 225: "cant_ready", 226: "cant_exhaust", 227: "cant_attack", 228: "cant_target", 229: "cant_destroy", 230: "cant_discard", 231: "cant_play", 232: "cant_draw", 233: "incoming_healing_multiplier", 234: "incoming_healing_adjustment", 235: "incoming_healing_cap", 236: "incoming_damage_multiplier", 237: "incoming_damage_adjustment", 238: "incoming_damage_cap", 239: "cant_be_healed", 240: "cant_be_damaged", 241: "cant_be_set_aside", 242: "cant_be_removed_from_game", 243: "cant_be_readied", 244: "cant_be_exhausted", 245: "cant_be_attacked", 246: "cant_be_targeted", 247: "cant_be_destroyed", 251: "attackvisualtype", 253: "cant_be_summoning_sick", 260: "frozen", 261: "just_played", 262: "linkedcard", 263: "zone_position", 264: "cant_be_frozen", 266: "combo_active", 267: "card_target", 268: "devstate", 269: "num_cards_played_this_turn", 270: "cant_be_targeted_by_opponents", 271: "num_turns_in_play", 272: "num_turns_left", 273: "outgoing_damage_cap", 274: "outgoing_damage_adjustment", 275: "outgoing_damage_multiplier", 276: "outgoing_healing_cap", 277: "outgoing_healing_adjustment", 278: "outgoing_healing_multiplier", 279: "incoming_ability_damage_adjustment", 280: "incoming_combat_damage_adjustment", 281: "outgoing_ability_damage_adjustment", 282: "outgoing_combat_damage_adjustment", 283: "outgoing_ability_damage_multiplier", 284: "outgoing_ability_damage_cap", 285: "incoming_ability_damage_multiplier", 286: "incoming_ability_damage_cap", 287: "outgoing_combat_damage_multiplier", 288: "outgoing_combat_damage_cap", 289: "incoming_combat_damage_multiplier", 290: "incoming_combat_damage_cap", 291: "current_spellpower", 292: "armor", 293: "morph", 294: "is_morphed", 295: "temp_resources", 296: "overload_owed", 297: "num_attacks_this_turn", 302: "next_ally_buff", 303: "magnet", 304: "first_card_played_this_turn", 305: "mulligan_state", 306: "taunt_ready", 307: "stealth_ready", 308: "charge_ready", 311: "cant_be_targeted_by_abilities", 312: "shouldexitcombat", 313: "creator", 314: "cant_be_dispelled", 316: "parent_card", 317: "num_minions_played_this_turn", 318: "predamage", 321: "collectible", 325: "targeting_arrow_text", 330: "enchantment_birth_visual", 331: "enchantment_idle_visual", 332: "cant_be_targeted_by_hero_powers", 335: "invisibledeathrattle", 337: "health_minimum", 338: "tag_one_turn_effect", 338: "oneturneffect", 339: "silence", 340: "counter", 342: "artistname", 348: "hand_revealed", 349: "immunetospellpower", 350: "adjacent_buff", 351: "flavortext", 352: "forced_play", 353: "low_health_threshold", 355: "grantcharge", 356: "spellpower_double", 357: "healing_double", 358: "num_options_played_this_turn", 360: "to_be_destroyed", 361: "healtarget", 362: "aura", 363: "poisonous", 364: "how_to_earn", 365: "how_to_earn_golden", 366: "hero_power_double", 367: "ai_must_play", 368: "num_minions_player_killed_this_turn", 369: "num_minions_killed_this_turn", 370: "affected_by_spell_power", 371: "extra_deathrattles", 372: "start_with_1_health", 373: "immune_while_attacking", 374: "multiply_hero_damage", 375: "multiply_buff_value", 376: "custom_keyword_effect", 377: "topdeck", 379: "cant_be_targeted_by_battlecries", 380: "shown_hero_power", 382: "deathrattle_return_zone", 383: "steady_shot_can_target", 385: "displayed_creator", 386: "powered_up", 388: "spare_part", 389: "forgetful", 390: "can_summon_maxplusone_minion", 391: "obfuscated", 392: "burning", 393: "overload_locked", 394: "num_times_hero_power_used_this_game", 395: "current_heropower_damage_bonus", 396: "heropower_damage", 397: "last_card_played", 398: "num_friendly_minions_that_died_this_turn", 399: "num_cards_drawn_this_turn", 400: "ai_one_shot_kill", 401: "evil_glow", 402: "hide_cost", 403: "inspire", 404: "receives_double_spelldamage_bonus", 405: "heropower_additional_activations", 406: "heropower_activations_this_turn", 410: "revealed", 412: "num_friendly_minions_that_died_this_game", 413: "cannot_attack_heroes", 414: "lock_and_load", 415: "treasure", 416: "shadowform", 417: "num_friendly_minions_that_attacked_this_turn", 418: "num_resources_spent_this_game", 419: "choose_both", 420: "electric_charge_level", 421: "heavily_armored", 422: "dont_show_immune", 432: "history_proxy_no_big_card", 435: "transformed_from_card", } \ No newline at end of file diff --git a/hm_web/app.py b/hm_web/app.py new file mode 100644 index 0000000..e489a0f --- /dev/null +++ b/hm_web/app.py @@ -0,0 +1,479 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import division +try: + import couchbase + from couchbase.bucket import Bucket + from couchbase.views.iterator import View +except: + import couchbase_ffi + from couchbase_ffi.bucket import Bucket + from couchbase_ffi.views.iterator import View +import random +import string +import web +import json +import xml.etree.ElementTree +from all_tags import tagsDict +import re +import os +import sys +from generate import gen +from subprocess import Popen, PIPE + +ERR_0 = 0 +ERR_1 = 1 +ERR_2 = 2 +ERR_3 = 3 + +web.config.debug = False + +urls = ('/', 'home', + '/signup', 'signup', + '/signin', 'signin', + '/mod/create', 'mod_create', + '/mod/edit/.*', 'mod_edit', + '/mod', 'mod', + '/deck/.*', 'deck_edit', + '/faq', 'faq', + '/rss', 'rss', + '/ladder', 'ladder' + ) +render = web.template.render('templates/') + +app = web.application(urls, globals()) + +store = web.session.DiskStore('sessions') +session = web.session.Session(app, store, initializer={'login': 0}) + +cb = Bucket('couchbase://localhost/hbs', password='aci') + +def rand(num): + return ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(num)]) + +class faq: + def GET(self): + return render.base(session, render.faq(), [], []) + +class mod_edit: + def GET(self): + s = web.ctx['path'].split("/") + m = s[len(s) - 1] + print m + return render.base(session, [], [], []) + +class ladder: + def GET(self): + players = [] + for result in View(cb, "dev_result", "result"): + w = int(result.value["w"]) + l = int(result.value["l"]) + n = result.value["nick"] + players.append([n, w, l, int(round(w / (w + l), 2) * 100)]) + players = sorted(players, key=lambda x: x[3], reverse=True) + + return render.base(session, render.ladder(players), [], []) + +class home: + def GET(self): + return render.base(session, render.home(), [], []) + +class mod: + def __init__(self): + print 'mod init' + + def POST(self): + #try: + d = json.loads(web.data()) + if(len(d['name']) > 0 and len(d['url']) > 0): + mod = {'name': d['name'], 'url': d['url'], 'cards': []} + cb.upsert('u:mod_%s' % d['name'], mod) + + return 'success' + + return 'fail' + + #except: + # print 'except' + # return '' + + def GET(self): + if(session.login == 0): + return render.base(session, render.login_required(), [], []) + + l = [] + for result in View(cb, "dev_mods", "mods"): + l.append({ "url": result.value["url"], "name": result.value["name"] }) + + return render.base(session, render.mod(l), [], []) + +class mod_edit: + def __init__(self): + self.e = xml.etree.ElementTree.parse('cache/c0').getroot() + self.cards = self.defaultSchema() + s = web.ctx['path'].split("/") + self.modname = "u:mod_%s" % s[len(s) - 1] + + def defaultSchema(self): + f = open('cache/cards.basic') + default = f.read() + f.close() + + alias = [] + for atype in self.e.findall("Entity"): + card = atype.get("CardID") + if(default.find("[%s]" % card) == -1): + continue + for t in atype.findall("Tag"): + if(t.get("enumID") == "185"): + alias.append([card, t.text]) + return alias + + def cardTags(self, dst, e): + tags = [] + tags.append(["__name", dst, "cardcode"]) + for atype in e.findall("Entity"): + if(atype.get("CardID") == dst): + for t in atype.findall("Tag"): + key = t.get("enumID") + m = t.get("type") + if(m == ""): + tags.append([key, t.get("value"), tagsDict[int(key)]]) + elif(m == "String"): + tags.append([key, t.text, tagsDict[int(key)]]) + else: + abort() + try: + f = open("../hm_gameserver/script/mechanics/cards/%s.card" % dst, "r") + r = f.read() + f.close() + tags.append(['__code', r, 'mechanics']) + except: + tags.append(['__code', "{}", 'mechanics']) + + j = json.dumps(tags) + + return j + + def modCards(self, card, tags, enabledCards): + + customName = '' + b = 'card=%s tags={' % card + for t in tags: + if(t.get("type") == ""): + b += "%s:%s," % (t.get("enumID"), t.get("value")) + if(t.get("type") == "String" and t.get("enumID") == "185"): + customName = t.text + if(t.get("type") == "String" and t.get("enumID") == "184"): + r = re.findall("\$[\w]+\ ", t.text) + if(len(r) > 0): + b += "47:%s," % r[0].replace(" ", "").replace("$", "") + + b += '} custom=1' + enabledCards = enabledCards.replace("[%s]" % card, "name=\"%s\" %s" % (customName, b)) + return enabledCards + + def modPublish(self, modName): + try: + print 'publishing mod ' + self.modname + loaded = cb.get(self.modname).value + names = [] + + f = open('cache/cards.basic') + enabledCards = f.read() + f.close() + + for atype in self.e.findall("Entity"): + for new in loaded['cards']: + if(atype.get("CardID") == new[0][1]): + for t in atype.findall("Tag"): + for tag in new: + if(tag[0] == t.get("enumID")): + + key = t.get("enumID") + m = t.get("type") + + if(m == ""): + t.set("value", tag[1]) + elif(m == "String"): + t.text = tag[1] + else: + abort() + + enabledCards = self.modCards(new[0][1], atype.findall("Tag"), enabledCards) + break + f = open(self.modname[2:], "w") + f.write(enabledCards) + f.close() + + xmlstr = xml.etree.ElementTree.tostring(self.e, encoding='utf8', method='xml') + + f = open("cache/cardsxml_p1", "rb") + p1 = f.read() + f.close() + + f = open("cache/cardsxml_p3", "rb") + p3 = f.read() + f.close() + + f = open("xml_%s" % self.modname[2:], "w") + f.write(p1 + xmlstr[38:] + p3) + f.close() + + + return "success" + + except: + return "fail" + + def enabledCardRemove(self, j): + try: + loaded = cb.get(self.modname).value + # delete if element exists + for l in loaded['cards']: + if l[0][1] == j: + loaded['cards'].remove(l) + break + cb.upsert(self.modname, loaded) + + names = [] + for l in loaded['cards']: + names.append([l[0][1], l[1][1]]) + + return json.dumps(names) + + except: + cb.upsert(self.modname, {"cards": [j]}) + + return "" + + def getStored(self): + try: + x = cb.get(self.modname) + loaded = x.value + except: + return [] + + names = [] + for l in loaded['cards']: + names.append([l[0][1], l[1][1]]) + + return json.dumps(names) + + def storeLoaded(self, j): + try: + loaded = cb.get(self.modname).value + # replace if element exists + for l in loaded['cards']: + if l[0][1] == j[0][1]: + loaded['cards'].remove(l) + break + loaded['cards'].append(j) + cb.upsert(selfmodname, loaded) + except: + cb.upsert(selfmodname, {"cards": [j]}) + + loaded = cb.get(self.modname).value + + names = [] + for l in loaded['cards']: + names.append([l[0][1], l[1][1]]) + + gen(j); + + return json.dumps(names) + + def modifiedCardTags(self, j): + #try: + loaded = cb.get(self.modname).value + for l in loaded['cards']: + if l[0][1] == j: + names = [] + for i in l: + if(i[0] == '__name'): + names.append([i[0], i[1], "cardcode"]) + elif(i[0] == '__code'): + names.append([i[0], i[1], "mechanics"]) + else: + names.append([i[0], i[1], tagsDict[int(i[0])]]) + + return json.dumps(names) + + return "" + + def isAuth(self): + if session.login == 1 and session.user == 'john': + print 'auth yes' + return 1 + else: + print 'auth no' + return 0 + + + def POST(self): + + j = json.loads(web.data()) + + if(j == None): + return '{}' + + if(len(j) == 1): + if 'modified' in j: + return self.modifiedCardTags(j['modified']) + + elif 'card' in j: + return self.cardTags(j['card'], self.e) + + elif 'remove' in j: + if not self.isAuth(): + return '{}' + return self.enabledCardRemove(j['remove']) + + elif 'publish' in j: + if not self.isAuth(): + return '{}' + + result = self.modPublish(j['publish']) + if(result == "success"): + os.system("cd script && bash publish.sh") + + return result + + else: + if(self.isAuth()): + return self.storeLoaded(j) + else: + return '{}' + + def GET(self): + if(session.login == 0): + return render.base(session, render.login_required(), [], []) + + try: + stored = json.loads(self.getStored()) + except: + stored = '{}' + return render.base(session, render.mod_create(self.cards, len(self.cards), stored), [], []) + + +class signup: + + def signup(self, arr): + session.login = 0 + + e = arr['email'] + p = arr['pass'] + p1 = arr['pass1'] + + if(len(e) < 2 or len(p) < 2): + return ERR_1 + if(p != p1): + return ERR_1 + + cb.upsert('u:%s' % e, {'email': e, 'password': p, 'secret': rand(6)}) + + return ERR_0 + + def GET(self): + return render.base(session, render.signup(), [], []) + + def POST(self): + + r = self.signup(json.loads(web.data())) + return r + +class signin: + def signin(self, arr): + session.login = 0 + session.user = '' + e = arr['user'] + p = arr['pass'] + if(len(e) < 2 or len(p) < 2): + session.login = 0 + return ERR_1 + + try: + out = cb.get('u:%s' % e).value + for o in out: + if(o == 'password'): + if(p == out[o]): + session.login = 1 + session.secret = out['secret'] + session.user = e + return ERR_0 + else: + session.login = 0 + return ERR_3 + return ERR_2 + except: + return ERR_2 + + def GET(self): + return render.base(session, render.signin(), [], []) + + def POST(self): + d = json.loads(web.data()) + + r = self.signin(d) + return r + +class deck: + def __init__(self): + s = web.ctx['path'].split("/") + self.modname = s[len(s) - 1] + + def save_deck(self, arr): + + out = cb.set('u:deck_%s_%s' % (self.modname, session.secret), arr) + + return ERR_0 + + + def GET(self): + if(session.login == 0): + return render.base(session, render.login_required(), [], []) + + cards = [] + loaded = cb.get('u:mod_%s' % self.modname).value + for l in loaded['cards']: + names = [] + enabled = 0 + for i in l: + if(i[0] == '185'): + names.append(i[1]) + elif(i[0] == '__name'): + names.append(i[1]) + elif(i[0] == '__code'): + if(i[1].find("\"enabled") > -1): + enabled = 1 + if(i[1].find("\"enabled:2\"") > -1): + names.append(2) + else: + names.append(1) + if(i[1].find("\"boss\"") > -1): + names.append('boss') + else: + names.append('noboss') + + if(len(names) != 0 and enabled == 1): + cards.append(names) + + try: + loaded = cb.get('u:deck_%s_%s' % (self.modname, session.secret)).value + except: + loaded = {} + + return render.base(session, render.deck(cards, loaded), loaded, cards) + + def POST(self): + if(session.login == 0): + return render.base(session, render.login_required(), [], []) + + r = self.save_deck(json.loads(web.data())) + return r + +if __name__ == '__main__': + web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr) + os.system("cd ../hm_sunwell/examples && npm start &") + + app.run() diff --git a/hm_web/cache/c0 b/hm_web/cache/c0 new file mode 100644 index 0000000..5333059 --- /dev/null +++ b/hm_web/cache/c0 @@ -0,0 +1,33992 @@ + + + 5f0999b3-52fd-4382-90d4-296de2994e34 + Lesser Heal + + + + + + + + <b>Hero Power</b> +Restore #2 Health. + + + + + + Goldshire Footman + + + + + + + + + <b>Taunt</b> + + + + + Donato Giancola + Unlocked at Paladin Level 57. + If 1/2 minions are all that is defending Goldshire, you would think it would have been overrun years ago. + + + + + add8d26e-2838-4f10-97f4-d2a9312b79b5 + Holy Nova + + + + + + + + Deal $2 damage to all enemies. Restore #2 Health to all friendly characters. + + + + Luca Zontini + If the Holy Light forsakes you, good luck casting this spell. Also, you're probably a jerk. + Unlocked at Level 6. + Unlocked at Level 45. + + + + 3779b451-83fa-4a47-85cf-dc4fe87746a9 + Mind Control + + + + + + + + Take control of an enemy minion. + + + + + Sean O’Daniels + Nominated as "Spell Most Likely to Make Your Opponent Punch the Wall." + Unlocked at Level 10. + Unlocked at Level 49. + + + + + + + + + e62d02c5-d4df-47f0-a3e3-5a569f6026f8 + Holy Smite + + + + + + + + Deal $2 damage. + + Steve Ellis + It doesn't matter how pious you are. Everyone needs a good smiting now and again. + Unlocked at Level 23. + Unlocked at Level 1. + + + + + + f7e4f69e-1f6e-4387-9b55-b7fd51f76a5b + Mind Vision + + + + + + + + Put a copy of a random card in your opponent's hand into your hand. + + + + + Michael Komarck + I see what you did there. + Unlocked at Level 4. + Unlocked at Level 32. + + + + 28ee13a3-783f-4d8e-9884-0562ed2c0752 + Power Word: Shield + + + + + + + + Give a minion +2 Health. +Draw a card. + + + + Jessica Jung + Sure the extra protection is nice, but the shield really reduces visibility. + Unlocked at Level 47. + Unlocked at Level 1. + + + + + + + Power Word: Shield + + + + +2 Health. + + + + + + a871043b-5755-4b92-85e1-a831512f8099 + Claw + + + + + + + + Give your hero +2 Attack this turn and 2 Armor. + + Dany Orizio + The claw decides who will stay and who will go. + + + Unlocked at Level 32. + Unlocked at Level 1. + + + + Claw + + + + +2 Attack this turn. + + + + + + + + 1978a68f-848d-4fe2-91f4-56039c3676ad + Healing Touch + + + + + + + + Restore #8 Health. + + Cyril Van Der Haegen + 8 Health, no waiting. + Unlocked at Level 15. + Unlocked at Level 1. + + + + + + f8b493c3-9a36-4f05-9c01-36e3859b4252 + Moonfire + + + + + + + Deal $1 damage. + + + Richard Wright + "Cast Moonfire, and never stop." - How to Be a Druid, Chapter 5, Section 3 + Unlocked at Level 6. + Unlocked at Level 40. + + + + + + 12d263a6-bdff-4ce1-af5f-cbd7e5ac7806 + Mark of the Wild + + + + + + + + Give a minion <b>Taunt</b> and +2/+2.<i> (+2 Attack/+2 Health)</i> + + + + Brad Vancata + Unlocked at Level 28. + Unlocked at Level 1. + Not to be confused with Jim of the Wild. + + + + + + + + Mark of the Wild + + + + This minion has +2/+2 and <b>Taunt</b>. + + + + + + 70d268ce-756c-49cf-9437-fb0dbceb0ac4 + Savage Roar + + + + + + + + Give your characters +2 Attack this turn. + + + + Grace Liu + What do they roar? Nobody can quite tell, but it sounds like "Elephant Macho Breeze". It's probably not that, though. + Unlocked at Level 4. + Unlocked at Level 43. + + + + Savage Roar + + + + +2 Attack this turn. + + + + + + + + 754440d0-0f8f-45a2-bd5d-e350aa2daf71 + Swipe + + + + + + + + Deal $4 damage to an enemy and $1 damage to all other enemies. + + + + Sean O’Daniels + When a bear rears back and extends his arms, he's about to Swipe! ... or hug. + Unlocked at Level 8. + Unlocked at Level 47. + + + + + + + Wild Growth + + + + + + + + Gain an empty Mana Crystal. + + + + James Ryman + Grow your own mana crystals with this Mana Crystal Growth Kit, only 39.99! + Unlocked at Level 23. + Unlocked at Level 1. + + + + afbc46d9-471b-4963-944a-fddb08f7df86 + Excess Mana + + + + + Draw a card. <i>(You can only have 10 Mana in your tray.)</i> + + + + + + 5fe4dcd6-fdf6-4b95-88c5-a11437db155b + Shapeshift + + + + + + + + <b>Hero Power</b> ++1 Attack this turn. +1 Armor. + + + + + + Claws + + + + Your hero has +1 Attack this turn. + + + + + + + + 651d1d7d-5022-44cf-b062-e475fe399ed3 + Polymorph + + + + + + + + Transform a minion into a 1/1 Sheep. + + + + + There was going to be a pun in this flavor text, but it just came out baa-d. + Vance Kovacs + Unlocked at Level 47. + Unlocked at Level 1. + + + + + + + Polymorph + + + + + + This minion has been transformed into a 1/1 Sheep. + + + + + Arcane Intellect + + + + + + + + Draw 2 cards. + + + + + Playing this card makes you SMARTER. And let's face it: we could all stand to be a little smarter. + Dave Berggren + Unlocked at Level 15. + Unlocked at Level 1. + + + + ea3beb34-7358-422b-8194-5f1999561bab + Frostbolt + + + + + + + + Deal $3 damage to a character and <b>Freeze</b> it. + + + It is customary to yell "Chill out!" or "Freeze!" or "Ice ice, baby!" when you play this card. + Steve Ellis + Unlocked at Level 2. + Unlocked at Level 40. + + + + + + + Arcane Explosion + + + + + + + + Deal $1 damage to all enemy minions. + + + + + This spell is much better than Arcane Implosion. + Howard Lyon + Unlocked at Level 28. + Unlocked at Level 1. + + + + cb0b6a1a-8c22-4904-a480-39acafd24d3d + Frost Nova + + + + + + + + <b>Freeze</b> all enemy minions. + + + + + Hey man, that's cold. Literally and metaphorically. + Josh Tallman + Unlocked at Level 6. + Unlocked at Level 23. + + + + + Mirror Image + + + + + + + + Summon two 0/2 minions with <b>Taunt</b>. + + + + + Oh hey it's Mirror Image! !egamI rorriM s'ti yeh hO + Jim Nelson + Unlocked at Level 4. + Unlocked at Level 36. + + + + + + + 436aaafa-1a04-4392-9ba5-cea496ddd86d + Fireball + + + + + + + + Deal $6 damage. + + + + + This spell is useful for burning things. If you're looking for spells that toast things, or just warm them a little, you're in the wrong place. + Ralph Horsley + Unlocked at Level 44. + Unlocked at Level 1. + + + + + + Flamestrike + + + + + + + + Deal $4 damage to all enemy minions. + + + + + When the ground is on fire, you should <i>not</i> stop, drop, and roll. + Romain De Santi + Unlocked at Level 10. + Unlocked at Level 51. + + + + Water Elemental + + + + + + + + + + <b>Freeze</b> any character damaged by this minion. + + + + + Don't summon a water elemental at a party. It'll dampen the mood. + John Avon + Unlocked at Level 8. + Unlocked at Level 49. + + + + + + 71be3917-6e17-4105-9e43-27d2de771947 + Fireblast + + + + + <b>Hero Power</b> +Deal $1 damage. + + + + + Deal 1 damage. + + + + + + + + 09724f29-2a7b-490b-b0d1-110d017840ee + Frost Shock + + + + + + + + Deal $1 damage to an enemy character and <b>Freeze</b> it. + + + + Alex Horley Orlandelli + FROST SHOCK! + Unlocked at Level 32. + Unlocked at Level 1. + + + + + + + + a65b410d-4f85-4661-b3e2-cdc9d5acaeea + Windfury + + + + + + + + Give a minion <b>Windfury</b>. + + + + Justin Sweet + Windfury is like Earthfury and Firefury, but more light and airy. + Unlocked at Level 23. + Unlocked at Level 1. + + + + + + + + 843fc26d-63b9-419e-bead-baccd15e59c6 + Ancestral Healing + + + + + + + + Restore a minion to full Health and give it <b>Taunt</b>. + + Dan Scott + I personally prefer some non-ancestral right-the-heck-now healing, but maybe that is just me. + + + Unlocked at Level 15. + Unlocked at Level 1. + + + + + + + + Ancestral Infusion + + + + Taunt. + + + + + + + d6fa0669-c4bc-4a71-843a-94355e129c93 + Fire Elemental + + + + + + + + + + <b>Battlecry:</b> Deal 3 damage. + + Deal 3 damage. + Ralph Horsley + He can never take a bath. Ewww. + Unlocked at Level 10. + Unlocked at Level 49. + + + + + + + 3581b0c4-e8c0-4d5e-9773-7add416504a6 + Rockbiter Weapon + + + + + + + + Give a friendly character +3 Attack this turn. + + Alex Horley Orlandelli + This would be real handy if your enemy is made of rock. + Unlocked at Level 36. + Unlocked at Level 1. + + + + + + + Rockbiter Weapon + + + + This character has +3 Attack this turn. + + + + + + + + Bloodlust + + + + + + + + Give your minions +3 Attack this turn. + + + + Luca Zontini + blaarghghLLGHRHARAAHAHHH!! + Unlocked at Level 2. + Unlocked at Level 40. + + + + Bloodlust + + + + +3 Attack this turn. + + + + + + + + 6c5c7b20-6aa1-44d5-9ab2-fcf6755877dc + Totemic Call + + + + + + + + + + <b>Hero Power</b> +Summon a random Totem. + + + + + + + + + + + Searing Totem + + + + + + + + + + + + + Stoneclaw Totem + + + + + + + + <b>Taunt</b> + + + + + + + + Wrath of Air Totem + + + + + + + + <b>Spell Damage +1</b> + + + + + + + + 78d0b174-c5ca-4a4b-b9d4-b7edfe8bf029 + Life Tap + + + + + + + + <b>Hero Power</b> +Draw a card and take 2 damage. + + + + + + + 602996a6-72c3-4e52-ba1f-5daf3b240708 + Shadow Bolt + + + + + + + + Deal $4 damage to a minion. + + + + + Dave Allsop + It’s a Bolt. It's made out of Shadow. What more do you need to know! + Unlocked at Level 47. + Unlocked at Level 1. + + + + + + + 56647e8e-df83-4230-b6f9-1755433490f3 + Drain Life + + + + + + + + Deal $2 damage. Restore #2 Health to your hero. + + + Alex Horley Orlandelli + "I've just sucked one year of your life away." + + + Unlocked at Level 45. + Unlocked at Level 1. + + + + + + Hellfire + + + + + + + + Deal $3 damage to ALL characters. + + + Chippy + It's spells like these that make it hard for Warlocks to get decent help. + Unlocked at Level 49. + Unlocked at Level 1. + + + + + + 36100a42-5d00-4066-b6b0-9b896a01e824 + Corruption + + + + + + + + Choose an enemy minion. At the start of your turn, destroy it. + + Wayne Reynolds + + + It starts with stealing a pen from work, and before you know it, BOOM! Corrupted! + Unlocked at Level 2. + Unlocked at Level 32. + + + + + + + + Corruption + + + + At the start of the corrupting player's turn, destroy this minion. + + + + + + + + Dread Infernal + + + + + + + + + + + <b>Battlecry:</b> Deal 1 damage to ALL other characters. + + + Zoltan & Gabor + "INFERNOOOOOOOOOO!" - Jaraxxus, Eredar Lord of the Burning Legion + Unlocked at Level 10. + Unlocked at Level 23. + + + + + + + Voidwalker + + + + + + + + + + + <b>Taunt</b> + + + Alex Horley Orlandelli + Unlocked at Level 36. + Unlocked at Level 1. + No relation to "The Voidsteppers", the popular Void-based dance troupe. + + + + + 3dec4fdc-fd2b-4f3b-8a2a-8b0585a763fd + Backstab + + + + + + + + Deal $2 damage to an undamaged minion. + + + Michael Sutfin + It's funny how often yelling "Look over there!" gets your opponent to turn around. + + + Unlocked at Level 36. + Unlocked at Level 1. + + + + + + + + f51fe4b0-1f7b-45dc-834e-3b4beeaf3109 + Deadly Poison + + + + + + + + Give your weapon +2 Attack. + + + Trevor Jacobs + Rogues guard the secrets to poison-making carefully, lest magi start incorporating poison into their spells. Poisonbolt? Rain of Poison? Poison Elemental? Nobody wants that. + + + Unlocked at Level 43. + Unlocked at Level 1. + + + + + + Deadly Poison + + + +2 Attack. + + + + + + Sinister Strike + + + + + + + + Deal $3 damage to the enemy hero. + + + Frank Cho + There's something about this strike that just feels off. Sinister, even. + Unlocked at Level 15. + Unlocked at Level 1. + + + + 2223ff8e-c651-42c7-914e-d722a0130103 + Assassinate + + + + + + + + Destroy an enemy minion. + + + + + Glenn Rane + If you don't want to be assassinated, move to the Barrens and change your name. Good luck! + Unlocked at Level 47. + Unlocked at Level 1. + + + + + + + + Sprint + + + + + + + + Draw 4 cards. + + + + + James Zhang + Unlocked at Level 10. + Unlocked at Level 49. + Rogues are not good joggers. + + + + Assassin's Blade + + + + + + + + + + + + Brian Huang + Guaranteed to have been owned by a real assassin. Certificate of authenticity included. + Unlocked at Level 2. + Unlocked at Level 32. + + + Wicked Knife + + + + + + + + + + + + 43361d24-86c6-42a3-b9ea-1320bdf35997 + Dagger Mastery + + + + + <b>Hero Power</b> +Equip a 1/2 Dagger. + + + + + + + + + + Sharpened + + + + +1 Attack this turn. + + + + + + + + a791d666-f98d-43c4-812a-5da475c31d01 + Hunter's Mark + + + + + + + + Change a minion's Health to 1. + + Jimmy Lo + + + Never play 'Hide and Go Seek' with a Hunter. + Unlocked at Level 6. + Unlocked at Level 40. + + + + + + + Hunter's Mark + + + + This minion has 1 Health. + + + + + + da3b501a-3f94-42a3-bfa3-ab34d2ab2b7b + Blessing of Might + + + + + + + + Give a minion +3 Attack. + + + + + Zoltan Boros + "As in, you MIGHT want to get out of my way." - Toad Mackle, recently buffed. + Unlocked at Level 45. + Unlocked at Level 1. + + + + + + + Blessing of Might + + + + + +3 Attack. + + + + + + + 8783150c-66a2-4f10-ba7d-02e4bfd85763 + Guardian of Kings + + + + + + + + + + <b>Battlecry:</b> Restore 6 Health to your hero. + + E.M. Gist + Unlocked at Level 8. + Unlocked at Level 47. + Holy beings from the beyond are so cliché! + + + + + e6c228a5-77cf-4ef5-add4-ed4c3197ce0f + Holy Light + + + + + + + + Restore #6 Health. + + Zoltan & Gabor + If you are often bathed in Holy Light, you should consider wearing sunscreen. + Unlocked at Level 15. + Unlocked at Level 1. + + + + + + Light's Justice + + + + + + + + + + + Glenn Rane + Prince Malchezaar was a collector of rare weapons. He'd animate them and have them dance for him. + Unlocked at Level 36. + Unlocked at Level 1. + + + 3999cb63-121b-4da3-9561-a53b698820ca + Blessing of Kings + + + + + + + + Give a minion +4/+4. <i>(+4 Attack/+4 Health)</i> + + + + Lucas Graciano + Given the number of kings who have been assassinated, are you sure you want their blessing? + Unlocked at Level 10. + Unlocked at Level 49. + + + + + + + Blessing of Kings + + + + +4/+4. + + + + + + 3c4d4f5f-4038-4afd-b3d4-028dfeb4dbbd + Consecration + + + + + + + + Deal $2 damage to all enemies. + + Vance Kovacs + Consecrated ground glows with Holy energy. But it smells a little, too. + Unlocked at Level 4. + Unlocked at Level 43. + + + + + + f406e1e1-0503-4e05-827e-cbc6f2ac6afe + Hammer of Wrath + + + + + + + + Deal $3 damage. +Draw a card. + + Efrem Palacios + Unlocked at Level 32. + Unlocked at Level 1. + A good paladin has many tools. Hammer of Wrath, Pliers of Vengeance, Hacksaw of Justice, etc. + + + + + + Truesilver Champion + + + + + + + + + + Whenever your hero attacks, restore 2 Health to it. + + + + Ryan Sook + Unlocked at Level 2. + Unlocked at Level 40. + It Slices, it Dices. You can cut a tin can with it. (But you wouldn't want to.) + + + + + + 0bd7d4df-e99d-4f73-bdec-2e107742c59c + Reinforce + + + + + + + + <b>Hero Power</b> +Summon a 1/1 Silver Hand Recruit. + + + + + + + + Silver Hand Recruit + + + + + + + + + + + + 99f9e182-b386-40b7-93f2-a56a1d3d85b3 + Armor Up! + + + + + + + + <b>Hero Power</b> +Gain 2 Armor. + + + + + + 30511767-3711-465e-bb62-114a8880691d + Charge + + + + + + + Give a friendly minion +2 Attack and <b>Charge</b>. + + + + + + Alex Horley Orlandelli + Unlocked at Level 23. + Unlocked at Level 1. + "Guys! Guys! Slow down!" - some kind of non-warrior minion + + + + + + + + + Charge + + + + +2 Attack and <b>Charge</b>. + + + + + + Heroic Strike + + + + + + + + Give your hero +4 Attack this turn. + + + Jonboy Meyers + Unlocked at Level 15. + Unlocked at Level 1. + Really, if you're a hero, this is <i>every</i> strike. + + + + Heroic Strike + + + +4 Attack this turn. + + + + + + + Fiery War Axe + + + + + + + + + + + Lucas Graciano + During times of tranquility and harmony, this weapon was called by its less popular name, Chilly Peace Axe. + Unlocked at Level 49. + Unlocked at Level 1. + + + d1cb4bf4-f913-4976-b51e-0639bb9d9227 + Execute + + + + + + + + Destroy a damaged enemy minion. + + + + + Dany Orizio + Unlocked at Level 47. + Unlocked at Level 1. + It's okay, he deserved it. + + + + + + + + + Arcanite Reaper + + + + + + + + + + + Stefan Kopinski + No… actually you should fear the Reaper. + Unlocked at Level 10. + Unlocked at Level 51. + + + ca5aa85a-d7e9-4ba2-a931-225207eb5c7e + Cleave + + + + + + + + Deal $2 damage to two random enemy minions. + + + Phroilan Gardner + Hey you two…could you stand next to each other for a second… + Unlocked at Level 2. + Unlocked at Level 40. + + + + + + + + Magma Rager + + + + + + + + + + Matt Gaser + Unlocked at Shaman Level 51. + He likes to think he is powerful, but pretty much anyone can solo Molten Core now. + + + Oasis Snapjaw + + + + + + + + + Ittoku + Unlocked at Druid Level 51. + His dreams of flying and breathing fire like his idol will never be realized. + + + River Crocolisk + + + + + + + + + Daren Bader + Unlocked at Druid Level 55. + Edward "Lefty" Smith tried to make luggage out of a river crocolisk once. + + + Frostwolf Grunt + + + + + + + + + <b>Taunt</b> + + + Richie Marella + Unlocked at Shaman Level 57. + Grunting is what his father did and his father before that. It's more than just a job. + + + + + Raid Leader + + + + + + + + Your other minions have +1 Attack. + Phill Gonzales + + + Unlocked at Warrior Level 57. + "That's a 50 DKP minus!" + + + + + Enhanced + + + Raid Leader is granting this minion +1 Attack. + + + + + + + Wolfrider + + + + + + + + + <b>Charge</b> + + + Dany Orizio + Unlocked at Warrior Level 59. + Orcish raiders ride wolves because they are well adapted to harsh environments, and because they are soft and cuddly. + + + + + Ironfur Grizzly + + + + + + + + + <b>Taunt</b> + + + + Lars Grant-West + Unlocked at Hunter Level 59. + "Bear Carcass 1/10" + + + + + Silverback Patriarch + + + + + + + + + <b>Taunt</b> + + + + Daren Bader + He likes to act like he's in charge, but the silverback matriarch actually runs things. + Unlocked at Warrior Level 53. + + + + + Stormwind Knight + + + + + + + + + <b>Charge</b> + + + Ladronn + They're still embarassed about "The Deathwing Incident". + Unlocked at Paladin Level 55. + + + + + 783563ab-2e50-4216-ad51-6f2d759e397d + Ironforge Rifleman + + + + + + + + + <b>Battlecry:</b> Deal 1 damage. + + + Deal 1 damage. + Tooth + Unlocked at Mage Level 55. + "Ready! Aim! Drink!" + + + + + + + + Kobold Geomancer + + + + + + + + + <b>Spell Damage +1</b> + + + Gabor Szikszai + Unlocked at Warlock Level 59. + In the old days, Kobolds were the finest candle merchants in the land. Then they got pushed too far... + + + + + + + Gnomish Inventor + + + + + + + + <b>Battlecry:</b> Draw a card. + + + + Court Jones + She's never quite sure what she's making, she just knows it's AWESOME! + Unlocked at Priest Level 57. + + + + + 67914002-5c70-412e-aa3d-6e08983694fd + Stormpike Commando + + + + + + + + + <b>Battlecry:</b> Deal 2 damage. + + Deal 2 damage. + Kev Walker + The Stormpike Commandos are demolition experts. They also bake a mean cupcake. + Unlocked at Paladin Level 51. + + + + + + + + Archmage + + + + + + + + + <b>Spell Damage +1</b> + + + Steve Ellis + You earn the title of Archmage when you can destroy anyone who calls you on it. + Unlocked at Mage Level 57. + + + + + Lord of the Arena + + + + + + + + + <b>Taunt</b> + + + E.M. Gist + Unlocked at Priest Level 59. + He used to be a 2100+ rated arena player, but that was years ago and nobody can get him to shut up about it. + + + + + Murloc Raider + + + + + + + + + + + Dan Scott + Mrrraggglhlhghghlgh, mrgaaag blarrghlgaahahl mrgggg glhalhah a bghhll graggmgmg Garrosh mglhlhlh mrghlhlhl!! + Unlocked at Priest Level 51. + + + Stonetusk Boar + + + + + + + + + + <b>Charge</b> + + + Howard Lyon + Unlocked at Hunter Level 53. + This card is boaring. + + + + + Bloodfen Raptor + + + + + + + + + + + + Dan Brereton + "Kill 30 raptors." - Hemet Nesingwary + Unlocked at Hunter Level 57. + + + Bluegill Warrior + + + + + + + + + + <b>Charge</b> + + + Jakub Kasper + Unlocked at Paladin Level 53. + He just wants a hug. A sloppy... slimy... hug. + + + + + Sen'jin Shieldmasta + + + + + + + + + <b>Taunt</b> + + + Brian Despain + Unlocked at Rogue Level 59. + Sen'jin Villiage is nice, if you like trolls and dust. + + + + + Chillwind Yeti + + + + + + + + + + + + + Mauro Cascioli + Unlocked at Warrior Level 55. + He always dreamed of coming down from the mountains and opening a noodle shop, but he never got the nerve. + + + War Golem + + + + + + + + + + + Dave Kendall + Golems are not afraid, but for some reason they still run when you cast Fear on them. Instinct, maybe? A desire to blend in? + Unlocked at Rogue Level 51. + + + Booty Bay Bodyguard + + + + + + + + + <b>Taunt</b> + + + Matt Cavotta + Unlocked at Shaman Level 55. + You can hire him... until someone offers him enough gold to turn on you. + + + + + 1d8c64df-efd1-4c47-8a7c-fe2b670aa3f5 + Elven Archer + + + + + + + + + <b>Battlecry:</b> Deal 1 damage. + + Deal 1 damage. + Steve Prescott + Don't bother asking her out on a date. She'll shoot you down. + Unlocked at Druid Level 57. + + + + + + + + 11d06f39-b180-4162-b54d-9bef1f665d06 + Razorfen Hunter + + + + + + + + + <b>Battlecry:</b> Summon a 1/1 Boar. + + + + Clint Langley + Unlocked at Hunter Level 55. + Someone did mess with Tuskerr once. ONCE. + + + + + Ogre Magi + + + + + + + + + <b>Spell Damage +1</b> + + + James Ryman + Unlocked at Warlock Level 55. + Training Ogres in the art of spellcasting is a questionable decision. + + + + + Boulderfist Ogre + + + + + + + + Brian Despain + Unlocked at Warlock Level 51. + "ME HAVE GOOD STATS FOR THE COST" + + + Core Hound + + + + + + + + + E.M. Gist + You don’t tame a Core Hound. You just train it to eat someone else before it eats you. + Unlocked at Hunter Level 51. + + + Reckless Rocketeer + + + + + + + + + <b>Charge</b> + + + John Polidora + Unlocked at Shaman Level 59. + One Insane Rocketeer. One Rocket full of Explosives. Infinite Fun. + + + + + Stormwind Champion + + + + + + + + + Your other minions have +1/+1. + + + + Doug Alexander + When Deathwing assaulted the capital, this soldier was the only member of his squad to survive. Now he's all bitter and stuff. + Unlocked at Paladin Level 59. + + + + + Might of Stormwind + + + Has +1/+1. + + + + + + Frostwolf Warlord + + + + + + + + + <b>Battlecry:</b> Gain +1/+1 for each other friendly minion on the battlefield. + + + + James Ryman + Unlocked at Shaman Level 53. + The Frostwolves are locked in combat with the Stormpike Expedition over control of Alterac Valley. Every attempt at peace-talks has ended with Captain Galvangar killing the mediator. + + + + + Frostwolf Banner + + + Increased stats. + + + + + + Ironbark Protector + + + + + + + + + + <b>Taunt</b> + + Dave Allsop + I <i>dare</i> you to attack Darnassus. + Unlocked at Level 10. + Unlocked at Level 49. + + + + + 36c113fe-50dd-42bc-b88c-ba7b5c1a0c5e + Shadow Word: Pain + + + + + + + Destroy a minion with 3 or less Attack. + + + Raymond Swanland + A step up from a spell cast by many beginning acolytes: "Shadow Word: Annoy". + Unlocked at Level 36. + Unlocked at Level 1. + + + + + + + + Northshire Cleric + + + + + + + + + Whenever a minion is healed, draw a card. + + + Terese Nielsen + They help the downtrodden and distressed. Also they sell cookies. + Unlocked at Level 40. + Unlocked at Level 1. + + + + + + + + 80eea4e6-5792-4f2a-9dff-6bf8cb17804f + Divine Spirit + + + + + + + Double a minion's Health. + + + Jim Pavelec + Double the trouble. Double the fun! + Unlocked at Level 2. + Unlocked at Level 28. + + + + + + + Divine Spirit + + + + This minion has double Health. + + + + + + Starving Buzzard + + + + + + + + + Whenever you summon a Beast, draw a card. + + + + Bernie Kang + If you feed him, he loses his whole <i>identity</i>. + Unlocked at Level 4. + Unlocked at Level 47. + + + + + + Boar + + + + + + + + + + + + + + Mirror Image + + + + + + + <b>Taunt</b> + + + + + + + + + Sheep + + + + + + + + + + + + + c89937a8-b00c-4410-bf24-82b162821bd5 + Steady Shot + + + + + + + + <b>Hero Power</b> +Deal $2 damage to the enemy hero. + + + + + + + + + Darkscale Healer + + + + + + + + + <b>Battlecry:</b> Restore 2 Health to all friendly characters. + + + Jesper Ejsing + Unlocked at Priest Level 55. + Healing is just something she does in her free time. It's more of a hobby really. + + + + + + + fa93d019-f433-479a-8eca-8960b8a558f1 + Houndmaster + + + + + + + + + <b>Battlecry:</b> Give a friendly Beast +2/+2 and <b>Taunt</b>. + + + + + Dan Brereton + Give a Beast +2/+2 and Taunt. + "Who let the dogs out?" he asks. It's rhetorical. + Unlocked at Level 28. + Unlocked at Level 1. + + + + + + + + + + + Master's Presence + + + + +2/+2 and <b>Taunt</b>. + + + + + + Timber Wolf + + + + + + + + + + Your other Beasts have +1 Attack. + + + Malcolm Davis + Other beasts totally dig hanging out with timber wolves. + + + Unlocked at Level 23. + Unlocked at Level 1. + + + + + Furious Howl + + + + This Beast has +1 Attack from Timber Wolf. + + + + + + Tundra Rhino + + + + + + + + + + Your Beasts have <b>Charge</b>. + + + + + Lars Grant-West + Tundra rhinos are often mistaken for kodos. Or am I mistaken? + Unlocked at Level 8. + Unlocked at Level 43. + + + + + Charge + + + + Tundra Rhino grants <b>Charge</b>. + + + + + + 33ac6d62-a3f1-4d6e-957e-86c30aad383e + Multi-Shot + + + + + + + + Deal $3 damage to two random enemy minions. + + Benjamin Zhang + You see, it's all about <i>throughput</i>. + Unlocked at Level 36. + Unlocked at Level 1. + + + + + + + + 7d56ad57-6aea-484b-ae4c-899658cb3125 + Tracking + + + + + + + + Look at the top three cards of your deck. Draw one and discard the others. + + + + Mauro Cascioli + For the person who just cannot decide what card to put into a deck! + Unlocked at Level 15. + Unlocked at Level 1. + + + + a0cd07d8-4c9c-48b1-a978-80a230d43fd1 + Arcane Shot + + + + + + + + Deal $2 damage. + + Luca Zontini + Magi conjured arcane arrows to sell to hunters, until hunters learned just enough magic to do it themselves. The resulting loss of jobs sent Stormwind into a minor recession. + Unlocked at Level 32. + Unlocked at Level 1. + + + + + + Mind Blast + + + + + + + + Deal $5 damage to the enemy hero. + + Dave Allsop + This spell blasts you directly in the MIND. + Unlocked at Level 15. + Unlocked at Level 1. + + + + 16b3528e-10d9-45b5-acdc-6eaa826f4817 + Voodoo Doctor + + + + + + + + + <b>Battlecry:</b> Restore 2 Health. + + Restore 2 Health. + Karl Richardson + Voodoo is an oft-misunderstood art. But it <i>is</i> art. + Unlocked at Rogue Level 55. + + + + + + + 4295b5dc-4faa-43ab-b755-00d8c5f1b91f + Novice Engineer + + + + + + + + + <b>Battlecry:</b> Draw a card. + + Karl Richardson + Unlocked at Druid Level 59. + "Half of this class will not graduate… since they'll have been turned to chickens." - Tinkmaster Overspark, teaching Gizmos 101. + + + + + + + a888e345-781f-46bd-a094-870b3680be7d + Shattered Sun Cleric + + + + + + + + + <b>Battlecry:</b> Give a friendly minion +1/+1. + + Give +1/+1. + Doug Alexander + + + Unlocked at Priest Level 53. + They always have a spare flask of Sunwell Energy Drink™! + + + + + + + + + b3930144-6586-4c45-b217-ca6cdd195248 + Cleric's Blessing + + + + +1/+1. + + + + + + d5da4b2c-4233-4200-883e-9643d3b409ab + Dragonling Mechanic + + + + + + + + + <b>Battlecry:</b> Summon a 2/1 Mechanical Dragonling. + + Warren Mahy + Unlocked at Mage Level 53. + She is still working on installing the rocket launcher add-on for Mr. Bitey. + + + + + + + Mechanical Dragonling + + + + + + + + + + + + 83fbbb43-283a-41e1-afc4-c471f4fa1fc8 + Acidic Swamp Ooze + + + + + + + + + <b>Battlecry:</b> Destroy your opponent's weapon. + + Chris Rahn + Oozes love Flamenco. Don't ask. + Unlocked at Rogue Level 57. + + + + + + + Warsong Commander + + + + + + + + + + Your <b>Charge</b> minions have +1 Attack. + + + + + Wei Wang + Unlocked at Level 36. + Unlocked at Level 1. + The Warsong clan is <i>such drama</i>. It's really not worth it to become a commander. + + + + + + Charge + + + + Warsong Commander is granting this minion +1 Attack. + + + + + + Fan of Knives + + + + + + + + Deal $1 damage to all enemy minions. Draw a card. + + + Andrew Robinson + I wouldn't say I LOVE knives, but I'm definitely a fan. + + + Unlocked at Level 4. + Unlocked at Level 28. + + + + 11d8014d-0b27-4d8f-be4f-edfc7040367b + Innervate + + + + + + + + Gain 2 Mana Crystals this turn only. + + Doug Alexander + Some druids still have flashbacks from strangers yelling "Innervate me!!" at them. + Unlocked at Level 36. + Unlocked at Level 1. + + + + 02786f36-b628-4962-b554-e9bcced94a91 + Starfire + + + + + + + + Deal $5 damage. +Draw a card. + + Alex Horley Orlandelli + Balance is important to druids. This card is perfectly balanced. + Unlocked at Level 2. + Unlocked at Level 45. + + + + + + Totemic Might + + + + + + + + Give your Totems +2 Health. + + Trent Kaniuga + + + Unlocked at Level 6. + Unlocked at Level 28. + Totem-stomping is no longer recommended. + + + + Totemic Might + + + + +2 Health. + + + + + + 800a56dc-97e6-4dba-b594-28eb024b83cd + Hex + + + + + + + + Transform a minion into a 0/1 Frog with <b>Taunt</b>. + + + + Steve Hui + If you Hex a Murloc... it really isn't much of a change, is it? + Unlocked at Level 47. + Unlocked at Level 1. + + + + + + + + Hexxed + + + + This minion has been transformed! + + + + + + + Arcane Missiles + + + + + + + + Deal $3 damage randomly split among all enemies. + + + + + You'd think you'd be able to control your missiles a little better since you're a powerful mage and all. + Warren Mahy + Unlocked at Level 32. + Unlocked at Level 1. + + + + + 3e703ffb-3cda-4a44-9611-e23b9a7aa9e0 + Shiv + + + + + + + + Deal $1 damage. Draw a card. + + + + Alex Garner + Unlocked at Level 6. + Unlocked at Level 45. + Rogues are experts at SHIV-al-ry. + + + + + + 61265a89-a7da-4a13-8b73-302e204116a1 + Mortal Coil + + + + + + + + Deal $1 damage to a minion. If that kills it, draw a card. + + + Matt Gaser + If your spells look like horrifying skulls, let's be honest, you should get to draw some cards. + Unlocked at Level 4. + Unlocked at Level 43. + + + + + + + Succubus + + + + + + + + + + + <b>Battlecry:</b> Discard a random card. + + + Matt Dixon + Warlocks have it pretty good. + Unlocked at Level 40. + Unlocked at Level 1. + + + + + 59ec1a94-36e2-45e2-a7d6-4958f435ac69 + Soulfire + + + + + + + + Deal $4 damage. Discard a random card. + + + Raymond Swanland + Are you lighting a soul on fire? Or burning someone with your OWN soul? This seems like an important distinction. + Unlocked at Level 6. + Unlocked at Level 28. + + + + + + + + fb36d4ce-ba97-43bd-8c6f-67f9c1a7a3bd + Humility + Change a minion's Attack to 1. + + + + + + + + + Daren Bader + This card makes something really damp. Oh wait. That's "Humidity." + Unlocked at Level 6. + Unlocked at Level 28. + + + + + + + + + Humility + + + + + Attack has been changed to 1. + + + + + + cfb61b8f-4148-4c61-b5a2-89bba5f04bbd + Hand of Protection + + + + + + + + Give a minion <b>Divine Shield</b>. + + + + Clint Langley + Unlocked at Level 23. + Unlocked at Level 1. + This spell has been renamed so many times, even paladins don’t know what it should be called anymore. + + + + + + + + Gurubashi Berserker + + + + + + + + + Whenever this minion takes damage, gain +3 Attack. + + + + Alex Horley Orlandelli + Unlocked at Warlock Level 57. + No Pain, No Gain. + + + + + + Berserking + + + This minion has increased Attack. + + + + + + 79654337-4a80-4672-94ca-ebd26dbcd9e6 + Whirlwind + + + + + + + + Deal $1 damage to ALL minions. + + Jonboy Meyers + The way to tell seasoned warriors from novice ones: the novices yell "wheeeee" while whirlwinding. + Unlocked at Level 6. + Unlocked at Level 32. + + + + + + 811d9942-036d-4f05-8dce-42e5fe68642f + Murloc Tidehunter + + + + + + + + + + <b>Battlecry:</b> Summon a 1/1 Murloc Scout. + + Dan Scott + Unlocked at Rogue Level 53. + "Death will rise, from the tides!" + + + + + + + Murloc Scout + + + + + + + + + + + + Grimscale Oracle + + + + + + + + + + ALL other Murlocs have +1 Attack. + + Phil Saunders + + + Unlocked at Warlock Level 53. + These are the brainy murlocs. It turns out that doesn’t mean much. + + + + Mlarggragllabl! + + + This Murloc has +1 Attack. + + + + + + 44c376c8-bf0a-4c0b-afec-666d95f7059f + Kill Command + + + + + + + + Deal $3 damage. If you have a Beast, deal $5 damage instead. + + Gabe from Penny Arcade + "Kill!", he commanded. + Unlocked at Level 10. + Unlocked at Level 49. + + + + + + + + + Flametongue Totem + + + + + + + + + + Adjacent minions have +2 Attack. + + + + + Jonathan Ryder + Totemsmiths like to use the rarest woods for their totems. There are even rumors of totems made of Ironbark Protectors. + Unlocked at Level 4. + Unlocked at Level 43. + + + + + + + Flametongue + + + + +2 Attack from Flametongue Totem. + + + + + + 891e592b-29b8-43e7-bb92-a6d72780117c + Sap + + + + + + + Return an enemy minion to your opponent's hand. + + + Scott Altmann + + + Unlocked at Level 40. + Unlocked at Level 1. + Rogues love sappy movies. + + + + + + + + Dalaran Mage + + + + + + + + <b>Spell Damage +1</b> + + Jim Nelson + Unlocked at Mage Level 59. + You don't see a lot of Dalaran warriors. + + + + + 915080c5-726d-4231-9772-a60367576d80 + Windspeaker + + + + + + + + <b>Battlecry:</b> Give a friendly minion <b>Windfury</b>. + + + Give <b>Windfury</b>. + + + Vance Kovacs + Is there anything worse than a Windspeaker with halitosis? + Unlocked at Level 8. + Unlocked at Level 45. + + + + + + + + + + edb9d489-93ea-4ab6-94c0-5866dc2fc9e7 + Nightblade + + + + + + + + <b>Battlecry: </b>Deal 3 damage to the enemy hero. + + Raymond Swanland + Unlocked at Druid Level 53. + Your face is the place you'd probably least like a dagger, and where rogues are most likely to deliver them. + + + + + 1483cbb5-5431-4468-a6a6-91331623cb53 + Shield Block + + + + + + + Gain 5 Armor. +Draw a card. + + + + Michael Komarck + Unlocked at Level 8. + Unlocked at Level 28. + Shields were invented because Face Block is USELESS. + + + + af8152e7-6136-43c5-bf1d-7fdeb5e92066 + Shadow Word: Death + + + + + + + Destroy a minion with an Attack of 5 or more. + + + Raymond Swanland + Unlocked at Level 8. + Unlocked at Level 43. + If you miss, it leaves a lightning-bolt-shaped scar on your target. + + + + + + + + Luck of the Coin + + + Going second grants you increased Health. + + + + + + Avatar of the Coin + + + + + + + <i>You lost the coin flip, but gained a friend.</i> + + + Coin's Vengeance + + + Going second makes your first minion stronger. + + + + + + + Coin's Vengence + + + Going second makes your first minion stronger. + + + + + + AFK + + + Your turns are shorter. + + + + + + + + 355b524d-2e9b-4a97-81c3-7ae0ac4cdf0f + The Coin + + + Gain 1 Mana Crystal this turn only. + + + + + + The Coin + + + + + + + + + NOOOOOOOOOOOO + + + + Somehow, the card you USED to have has been deleted. Here, have this one instead! + Even your flavor text has been deleted. Dang. + + + 5652cff6-0c7b-4f82-855d-7042d8f775fb + Garrosh Hellscream + + + + + + + + + + + + + Thrall + + + + + + + + + + + + Valeera Sanguinar + + + + + + + + + + + + + 4e3a69b1-a3ad-4cab-a18d-c021a67147ff + Uther Lightbringer + + + + + + + + + + + + + + + 75596ce4-da77-4efd-98b0-f68a3ba38091 + Rexxar + + + + + + + + + + + + 15375f72-fc71-4829-a9d4-7d75f5a21b34 + Malfurion Stormrage + + + + + + + + + + + + Gul'dan + + + + + + + + + + + + + Jaina Proudmoore + + + + + + + + + + + + + + + 7e3d6eaa-4d6e-4b5a-8c60-b69c801d8faf + Anduin Wrynn + + + + + + + + + + + + Frog + + + + + + + + <b>Taunt</b> + + + + + + 26f06b76-b9a6-4a72-92c3-94c12cc5e395 + Sacrificial Pact + + + + + + Destroy a Demon. Restore #5 Health to your hero. + + + + Jim Nelson + This is the reason that Demons never really become friends with Warlocks. + Unlocked at Level 8. + Unlocked at Level 15. + + + + + + + Vanish + + + + + + Return all minions to their owner's hand. + + Sean O’Daniels + + + Unlocked at Level 8. + Unlocked at Level 23. + + + + Healing Totem + + + + + + At the end of your turn, restore 1 Health to all friendly minions. + + + + + + + + + + + Kor'kron Elite + + + + <b>Charge</b> + + + + + + + + Alex Horley Orlandelli + The Kor'kron are the elite forces of Garrosh Hellscream. Let's just say you don't want to run into these guys while wearing a blue tabard. + Unlocked at Level 4. + Unlocked at Level 44. + + + + + 9ec73fe1-8c73-4322-88b0-2cd1f762a8bb + Animal Companion + + + + + Summon a random Beast Companion. + + + + + Wei Wang + You could summon Misha, Leokk, or Huffer! Huffer is more trouble than he's worth. + Unlocked at Level 2. + Unlocked at Level 45. + + + + + + + + + Misha + + + + + <b>Taunt</b> + + + + + + + + + + + Leokk + + + + + Your other minions have +1 Attack. + + + + + + + + + + Eye In The Sky + + + Leokk is granting this minion +1 Attack. + + + + + + + Huffer + + + + + <b>Charge</b> + + + + + + + + + Skeleton + + + + + + + + <b></b> + + + + Fen Creeper + + + + + + + + + <b>Taunt</b> + + + Monica Langlois + He used to be called Bog Beast, but it confused people because he wasn't an actual beast. Boom, New Name! + + + + + 126f032e-e9db-43ff-968f-f1eabcdead0b + Inner Fire + + + + + + + + Change a minion's Attack to be equal to its Health. + + Good idea: Buffing your minions. Bad idea: Starting a conversation in the Barrens. + + + Steve Prescott + + + + + + + Inner Fire + + + + This minion's Attack is equal to its Health. + + + + + + 16d6dfb5-899a-4a22-8893-bf11e98a76cb + Blizzard + + + + + + + + Deal $2 damage to all enemy minions and <b>Freeze</b> them. + + + + + This spell can be very Entertaining. + Chris Seaman + + + + + 7c447496-ee22-4ed6-bdc6-67280d0e2726 + Ice Lance + + + + + + + <b>Freeze</b> a character. If it was already <b>Frozen</b>, deal $4 damage instead. + + + + + + The trick is not to break the lance. Otherwise, you have "Ice Pieces." Ice Pieces aren't as effective. + Alex Horley Orlandelli + + + + + + + 3f0a117e-1171-4a4b-b2c5-53cacdebad2e + Ancestral Spirit + + + + + + + + Give a minion "<b>Deathrattle:</b> Resummon this minion." + + + + Zoltan & Gabor + It was just a flesh wound. + + + + + + + + Ancestral Spirit + + + + <b>Deathrattle:</b> Resummon this minion. + + + + + + 8e067525-a507-46cd-ba14-f51f55d96303 + Far Sight + + + + + + + Draw a card. That card costs (3) less. + + + + + Drek'thar can't see, but he can <i>see</i>. You know what I mean? It's ok if you don't. + Lars Grant-West + + + + Far Sight + + + + One of your cards costs (3) less. + + + Lars Grant-West + + + + Blood Imp + + + + + + + + + <b>Stealth</b>. At the end of your turn, give another random friendly minion +1 Health. + + + + + Bernie Kang + Imps are content to hide and viciously taunt everyone nearby. + + + + + + + + + + + Blood Pact + + + + Increased Health. + + + + + + 0d0e66ed-59ef-4471-b113-4630e520dc2b + Cold Blood + + + + + + + Give a minion +2 Attack. <b>Combo:</b> +4 Attack instead. + + + + Alex Horley Orlandelli + "I'm cold blooded, check it and see!" + + + + + + + + Cold Blood + + + + +2 Attack. + + + + + + Cold Blood + + + + +4 Attack. + + + + + + 80e88a5d-1729-42a1-8b7f-d51cf95d3b5e + Rampage + + + + + + + + Give a damaged minion +3/+3. + + + + + Jonboy Meyers + Minion get ANGRY. Minion SMASH! + + + + + + + + Rampage + + + + + + +3/+3. + + + + d37a04da-f446-40c8-8ddb-1f77659837cd + Earthen Ring Farseer + + + + + + + + <b>Battlecry:</b> Restore 3 Health. + Restore 3 Health. + + + Alex Horley Orlandelli + He can see really far, and he doesn't use a telescope like those filthy pirates. + + + + + + + Southsea Deckhand + + + + + + + + + Has <b>Charge</b> while you have a weapon equipped. + + + Dan Brereton + + + Pirates are into this new fad called "Planking". + + + + + d2b09caf-89d5-4309-88ae-4953a236eb78 + Silver Hand Knight + + + + + + + + + <b>Battlecry:</b> Summon a 2/2 Squire. + + Matt Starbuck + It's good to be a knight. Less so to be one's squire. + + + + + Squire + + + + + + + + + + + Ravenholdt Assassin + + + + + + + + <b>Stealth</b> + + + + Ralph Horsley + Just mail him a package with a name and 10,000 gold. He'll take care of the rest. + + + + + Young Dragonhawk + + + + + + + + + <b>Windfury</b> + + + + + Greg Hildebrandt + They were the inspiration for the championship Taurenball team: The Dragonhawks. + + + + + 6b4c2fa7-4dfe-497f-b662-0968a935ea70 + Injured Blademaster + + + + + + + + + <b>Battlecry:</b> Deal 4 damage to HIMSELF. + + + + Samwise + He claims it is an old war wound, but we think he just cut himself shaving. + + + + + f8057e52-a62b-45ff-bd2f-090a29465369 + Full Strength + + + This minion has +2 Attack. + + + + + + 365c063e-5364-433c-acf3-700fecc72b2e + Abusive Sergeant + + + + + + + + + <b>Battlecry:</b> Give a minion +2 Attack this turn. + + Grant +2 Attack. + + + Luca Zontini + ADD ME TO YOUR DECK, MAGGOT! + + + + + + + + 'Inspired' + + + This minion has +2 Attack this turn. + + + + + + + + d1ea5142-2cae-4800-a76e-e58a7943021d + Ironbeak Owl + + + + + + + + + <b>Battlecry:</b> <b>Silence</b> a minion. + + + <b>Silence</b> a minion. + + + Trevor Jacobs + Their wings are silent but their screech is... whatever the opposite of silent is. + + + + + + + + + Spiteful Smith + + + + + + + + + <b>Enrage:</b> Your weapon has +2 Attack. + + + + Justin Sweet + She'll craft you a sword, but you'll need to bring her 5 Steel Ingots, 3 Motes of Earth, and the scalp of her last customer. + + + + + Sharp! + + + +2 Attack from Spiteful Smith. + + + + + + Venture Co. Mercenary + + + + + + + + + Your minions cost (3) more. + + John Polidora + No Job is too big. No fee is too big. + + + + + + + Wisp + + + + + + + + + A + Malcolm Davis + If you hit an Eredar Lord with enough Wisps, it will explode. But why? + + + 3b6f55d4-2234-41e5-9f13-62632065a254 + Blade Flurry + + + + + + + + Destroy your weapon and deal its damage to all enemy minions. + + + + + Hideaki Takamura + "Look, it's not just about waving daggers around really fast. It's a lot more complicated than that." - Shan, Rogue Trainer + + + + + + + Laughing Sister + + + + + Can't be targeted by spells or Hero Powers. + + + + + + + + 1662c8aa-c080-477a-849b-9a5bfe1d19fb + Ysera Awakens + + + + Deal $5 damage to all characters except Ysera. + + + + + + + Emerald Drake + + + + + + + + + + + + 28e89fe3-39f3-47f0-99ed-6daf76cb5879 + Dream + + + + Return a minion to its owner's hand. + + + + + + + + + + 90db08f8-87af-4e7b-8578-36621fd7065b + Nightmare + + + + Give a minion +5/+5. At the start of your next turn, destroy it. + + + + + + + + Nightmare + + + This minion has +5/+5, but will be destroyed soon. + + + + + + + + + Gladiator's Longbow + + + + + + + + + + + Your hero is <b>Immune</b> while attacking. + + + Peter C. Lee + The longbow allows shots to be fired from farther away and is useful for firing on particularly odorous targets. + + + + + + + Gladiator's Longbow enchantment + + + + + + + + + + + Whelp + + + + + + + + + + + Lightwarden + + + + + + + + Whenever a character is healed, gain +2 Attack. + + + Erik Ko + She’s smaller than her sisters Mediumwarden and Heavywarden. + + + + + + Warded + + + Increased Attack. + + + + + + 9c704757-1b1a-423e-86a3-ec023aa78b81 + The Black Knight + + + + + + + + <b>Battlecry:</b> Destroy an enemy minion with <b>Taunt</b>. + + + + Alex Horley Orlandelli + Destroy a minion with Taunt. + He was sent by the Lich King to disrupt the Argent Tournament. We can pretty much mark that a failure. + + + + + + + + + + + Young Priestess + + + + + + + + At the end of your turn, give another random friendly minion +1 Health. + + + Vance Kovacs + She can't wait to learn Power Word: Fortitude Rank 2. + + + + + + Elune's Grace + + + Increased Health. + + + + + + 41e81c66-edf9-4f0f-b7ba-9dad6a522133 + Big Game Hunter + + + + + + + + <b>Battlecry:</b> Destroy a minion with an Attack of 7 or more. + Destroy a minion with an Attack of 7 or more. + + + Chris Seaman + Mere devilsaurs no longer excite him. Soon he'll be trying to catch Onyxia with only a dull Krol Blade. + + + + + + + + + Alarm-o-Bot + + + + + + + + At the start of your turn, swap this minion with a random one in your hand. + + + Sean O’Daniels + WARNING. WARNING. WARNING. + + + + + + + Acolyte of Pain + + + + + + + + Whenever this minion takes damage, draw a card. + + + Dave Kendall + He trained when he was younger to be an acolyte of joy, but things didn’t work out like he thought they would. + + + + + + Argent Squire + + + + + + + + + <b>Divine Shield</b> + + + + Zoltan & Gabor + "I solemnly swear to uphold the Light, purge the world of darkness, and to eat only burritos." - The Argent Dawn Oath + + + + + Angry Chicken + + + + + + + + + + <b>Enrage:</b> +5 Attack. + + Mike Sass + There is no beast more frightening (or ridiculous) than a fully enraged chicken. + + + + + Enraged + + + + + + +5 Attack. + + + + + Worgen Infiltrator + + + + + + + + + <b>Stealth</b> + + + Raymond Swanland + If you want to stop a worgen from infiltrating, just yell, "No! Bad boy!" + + + + + Bloodmage Thalnos + + + + + + + + + <b>Spell Damage +1</b>. <b>Deathrattle:</b> Draw a card. + + + Alex Horley Orlandelli + He's in charge of the Annual Scarlet Monastery Blood Drive! + + + + + + + + + + bfc8471e-08fb-412b-a569-c7f1709c90eb + King Mukla + + + + + + + + + <b>Battlecry:</b> Give your opponent 2 Bananas. + + + + Sunny Gho + King Mukla wanders Jaguero Isle, searching for love. + + + + + 3f3ed805-a9b8-4b68-b438-a11cf3628033 + Bananas + + + + Give a minion +1/+1. + + + + + + + + + Bananas + + + Has +1/+1. + + + + + + Sylvanas Windrunner + + + + + + + + + <b>Deathrattle:</b> Take control of a random enemy minion. + + + Glenn Rane + Sylvanas was turned into the Banshee Queen by Arthas, but he probably should have just killed her because it just pissed her off. + + + + + + Jungle Panther + + + + + + + + + <b>Stealth</b> + + + + Jaemin Kim + Stranglethorn is a beautiful place to visit, but you wouldn't want to live there. + + + + + Scarlet Crusader + + + + + + + + + <b>Divine Shield</b> + + Gonzalo Ordonez + Never wash your whites with a Scarlet Crusader. + + + + + Thrallmar Farseer + + + + + + + + + <b>Windfury</b> + + + + Efrem Palacios + He's stationed in the Hellfire Peninsula, but he's hoping for a reassignment closer to Orgrimmar, or really anywhere the ground is less on fire. + + + + + Silvermoon Guardian + + + + + + + + + <b>Divine Shield</b> + + + + Phroilan Gardner + The first time they tried to guard Silvermoon against the scourge, it didn’t go so well… + + + + + Stranglethorn Tiger + + + + + + + + <b>Stealth</b> + + + + + Alex Horley Orlandelli + + + The wonderful thing about tigers is tigers are wonderful things! + + + + + Leper Gnome + + + + + + + + + <b>Deathrattle:</b> Deal 2 damage to the enemy hero. + + Glenn Rane + He really just wants to be your friend, but the constant rejection is starting to really get to him. + + + + + + Sunwalker + + + + + + + + + <b>Taunt</b> +<b>Divine Shield</b> + + Andrea Uderzo + She doesn’t ACTUALLY walk on the Sun. It's just a name. Don’t worry! + + + + + + + Windfury Harpy + + + + + + + + + <b>Windfury</b> + + + + Luke Mancini + Harpies are not pleasant sounding. That's the nicest I can put it. + + + + + 80b6975f-1f7c-42de-ac99-e06a273f4399 + Twilight Drake + + + + + + + + + <b>Battlecry:</b> Gain +1 Health for each card in your hand. + + + Jaemin Kim + Twilight drakes feed on Mystical Energy. And Tacos. + + + + + + + Hour of Twilight + + + Increased Health. + + + + + + Questing Adventurer + + + + + + + + + Whenever you play a card, gain +1/+1. + + + + Attila Adorjany + "Does anyone have some extra Boar Pelts?" + + + + + + Level Up! + + + Increased Attack and Health. + + + + + + Ancient Watcher + + + + + + + + + Can't attack. + + + + Richard Wright + Why do its eyes seem to follow you as you walk by? + + + + 1d14b0a8-f2f2-4c33-a181-5b62ccf41f69 + Dark Iron Dwarf + + + + + + + + + <b>Battlecry:</b> Give a minion +2 Attack this turn. + + + + Scott Hampton + Give +2 Attack. + Guardians of Dark Iron Ore. Perhaps the most annoying ore, given where you have to forge it. + + + + + + + + Tempered + + + +2 Attack this turn. + + + + + + + + e796d04c-0b64-4ef5-be1c-fd0bc0e193e5 + Spellbreaker + + + + + + + + + <b>Battlecry:</b> <b>Silence</b> a minion. + + <b>Silence</b> a minion. + + + Matt Cavotta + Spellbreakers can rip enchantments from magic-wielders. The process is painless and can be performed on an outpatient basis. + + + + + + + + + + 821b0a33-8fd7-4c38-af65-500b69b27e9a + Youthful Brewmaster + + + + + + + + + <b>Battlecry:</b> Return a friendly minion from the battlefield to your hand. + + Return a minion to your hand. + + + Wei Wang + His youthful enthusiasm doesn’t always equal excellence in his brews. Don’t drink the Mogu Stout! + + + + + + + + + + b79228a3-8978-4ac2-8a48-32b06b2fd849 + Coldlight Oracle + + + + + + + + + <b>Battlecry:</b> Each player draws 2 cards. + + + Steve Prescott + They can see the future. In that future both players draw more cards. Spoooky. + + + + + Mana Addict + + + + + + + + + Whenever you cast a spell, gain +2 Attack this turn. + + + + Hideaki Takamura + She’s trying to kick the habit, but still takes some mana whenever she has a stressful day. + + + + + + Empowered + + + Mana Addict has increased Attack. + + + + + + + + fbab1bcd-468a-4ae4-9340-487a0b93fe49 + Ancient Brewmaster + + + + + + + + + <b>Battlecry:</b> Return a friendly minion from the battlefield to your hand. + + Return a minion to your hand. + + + Bernie Kang + Most pandaren say his brew tastes like yak. But apparently that's a compliment. + + + + + + + + + + d975806e-3372-4a54-860f-4b046ee22f56 + Sunfury Protector + + + + + + + + + <b>Battlecry:</b> Give adjacent minions <b>Taunt</b>. + + + + James Ryman + She carries a shield, but only so she can give it to someone she can stand behind. + + + + + + dd84de4e-d751-4fa5-b7ac-b1b8042dd7ad + Crazed Alchemist + + + + + + + + + <b>Battlecry:</b> Swap the Attack and Health of a minion. + + Swap Attack and Health of a minion. + + + Tom Fleming + "You'll <i>love</i> my new recipe!" he says... especially if you're not happy with your current number of limbs. + + + + + + + + Experiments! + + + Attack and Health have been swapped by Crazed Alchemist. + + + + + + Argent Commander + + + + + + + + + <b>Charge</b> +<b>Divine Shield</b> + + James Ryman + The Argent Dawn stands vigilant against the Scourge, as well as people who cut in line at coffee shops. + + + + + + + Pint-Sized Summoner + + + + + + + + + The first minion you play each turn costs (1) less. + + Ron Spears + + + She's quite jealous of the Gallon-Sized Summoner. + + + + + Secretkeeper + + + + + + + + + Whenever a <b>Secret</b> is played, gain +1/+1. + + + + Gonzalo Ordonez + She promises not to tell anyone about that thing you did last night with that one person. + + + + + + + Keeping Secrets + + + Increased stats. + + + + + + 30c62987-96d3-478b-8b0f-1b1ad383d922 + Mad Bomber + + + + + + + + + <b>Battlecry:</b> Deal 3 damage randomly split between all other characters. + + + + Mike Sass + He's not really all that crazy, he is just not as careful with explosives as he should be. + + + + + b93e771a-10ce-47cb-92f4-8089be5d2832 + Tinkmaster Overspark + + + + + + + + + <b>Battlecry:</b> Transform another random minion into a 5/5 Devilsaur or a 1/1 Squirrel. + + + Transform a minion into a 5/5 or a 1/1 at random. + + + Tom Baxa + Tinkmaster Overspark nearly lost his Tinker's license after the Great Ironforge Squirrel Stampede of '09. + + + + + 56dde99d-509b-4c47-afa4-4669b08c3864 + Mind Control Tech + + + + + + + + + <b>Battlecry:</b> If your opponent has 4 or more minions, take control of one at random. + + Leo Che + + + Mind Control technology is getting better, but that's not saying much. + + + + + Arcane Golem + + + + + + + + + <b>Battlecry:</b> Give your opponent a Mana Crystal. + + Sedhayu Ardian + Having Arcane golems at home really classes up the place, and as a bonus they are great conversation pieces. + + + + + 857037b7-59bc-4664-8730-4afc2474d7d4 + Cabal Shadow Priest + + + + + + + + + <b>Battlecry:</b> Take control of an enemy minion that has 2 or less Attack. + + + Steal a minion that has 2 or less Attack. + + + Chippy + You never know who may be secretly working for the Cabal.... + + + + + + + + + + 89092cd4-ee01-40aa-ba6f-dd6997a38ee4 + Defender of Argus + + + + + + + + + <b>Battlecry:</b> Give adjacent minions +1/+1 and <b>Taunt</b>. + + + + Alex Horley Orlandelli + You wouldn’t think that Argus would need this much defending. But it does. + + + + + + Hand of Argus + + + +1/+1 and <b>Taunt</b>. + + + + + + Gadgetzan Auctioneer + + + + + + + + + + + + Matt Dixon + He used to run the black market auction house, but there was just too much violence and he had to move. + Whenever you cast a spell, draw a card. + + + + + + Loot Hoarder + + + + + + + + + <b>Deathrattle:</b> Draw a card. + + Jim Nelson + Always roll need. + + + + + + Abomination + + + + + + + + + <b>Taunt</b>. <b>Deathrattle:</b> Deal 2 damage to ALL characters. + + Alex Horley Orlandelli + Abominations enjoy Fresh Meat and long walks on the beach. + + + + + + + + + + Lorewalker Cho + + + + + + + + + Whenever a player casts a spell, put a copy into the other player’s hand. + + + + + Mark Zug + Lorewalker Cho archives and shares tales from the land of Pandaria, but his favorite story is the one where Joey and Phoebe go on a road trip. + + + + + + Demolisher + + + + + + + + + At the start of your turn, deal 2 damage to a random enemy. + + + + Raymond Swanland + Laying siege isn't fun for anyone. It's not even all that effective, now that everyone has a flying mount. + + + + + + + ed1b6657-9a0f-4737-ad76-4cd4e95835fe + Coldlight Seer + + + + + + + + + + <b>Battlecry:</b> Give ALL other Murlocs +2 Health. + + + + Arthur Gimaldinov + The Coldlight murlocs reside in the darkest pits of the Abyssal Depths. So no, there's no getting away from murlocs. + + + + + Mrghlglhal + + + +2 Health. + + + + + + Mountain Giant + + + + + + + + + Costs (1) less for each other card in your hand. + + Samwise + His mother said that he was just big boned. + + + + Cairne Bloodhoof + + + + + + + + + <b>Deathrattle:</b> Summon a 4/5 Baine Bloodhoof. + + + + + Wayne Reynolds + Cairne was killed by Garrosh, so... don't put this guy in a Warrior deck. It's pretty insensitive. + + + + + + Baine Bloodhoof + + + + + + + + + + + + Leeroy Jenkins + + + + + + + + + <b>Charge</b>. <b>Battlecry:</b> Summon two 1/1 Whelps for your opponent. + + + Gabe from Penny Arcade + At least he has Angry Chicken. + + + + + + + + + Whelp + + + + + + + + + de987317-e746-4476-a3a5-7ad0770b3c9f + Eviscerate + + + + + + + + + Deal $2 damage. <b>Combo:</b> Deal $4 damage instead. + + + + Ariel Olivetti + There is a high cost to Eviscerating your opponent: It takes a long time to get blood stains out of leather armor. + + + + + + + ad566701-d43c-435a-8d70-9dd701274824 + Betrayal + + + + + + + + Force an enemy minion to deal its damage to the minions next to it. + + + + + Lucas Graciano + Everyone has a price. Gnomes, for example, can be persuaded by stuffed animals and small amounts of chocolate. + + + + + + + + b5a3da15-a174-4572-8f8e-d17a871066d9 + Conceal + + + + + + + + Give your minions <b>Stealth</b> until your next turn. + + + + + Steve Hui + Rogues conceal everything but their emotions. You can't get 'em to shut up about feelings. + + + + + Concealed + + + + Stealthed until your next turn. + + + + + + + Noble Sacrifice + + + + + + + <b>Secret:</b> When an enemy attacks, summon a 2/1 Defender as the new target. + + + + Zoltan & Gabor + We will always remember you, "Defender!" + + + + + + Defender + + + + + + + + + + + + Defias Ringleader + + + + + + + + + + <b>Combo:</b> Summon a 2/1 Defias Bandit. + + + Dany Orizio + He stole the deed to town years ago, so technically the town <i>is</i> his. He just calls people Scrub to be mean. + + + + + + + Defias Bandit + + + + + + + + + + + Eye for an Eye + + + + + + + + <b>Secret:</b> When your hero takes damage, deal that much damage to the enemy hero. + + James Ryman + Justice sometimes takes the form of a closed fist into a soft cheek. + + + + + + + + d852af62-e44d-4372-a582-18eb55fd2cd6 + Perdition's Blade + + + + + + + + + + <b>Battlecry:</b> Deal 1 damage. <b>Combo:</b> Deal 2 instead. + + + Deal 1 damage. Combo: 2 instead. + Daren Bader + Perdition's Blade is Ragnaros's back-up weapon while Sulfuras is in the shop. + + + + + + + + + 215f20e5-4a77-468e-b3a6-7ab9edcf02dc + SI:7 Agent + + + + + + + + + + <b>Combo:</b> Deal 2 damage. + + + Chris Moeller + The agents of SI:7 are responsible for Stormwind's covert activities. Their duties include espionage, assassination, and throwing surprise birthday parties for the royal family. + Deal 2 damage. + + + + + + + + + Redemption + + + + + + + + <b>Secret:</b> When one of your minions dies, return it to life with 1 Health. + + + + Ittoku + I am not sure how you get demptioned the first time. It’s a mystery! + + + + + + 85cd67bb-f458-4bf6-9173-c16cd61302d0 + Headcrack + + + + + + + + Deal $2 damage to the enemy hero. <b>Combo:</b> Return this to your hand next turn. + + James Zhang + When all else fails, nothing beats a swift whack upside the head. + + + + + 100aa67d-a320-4afb-856e-701b45a4cd48 + Shadowstep + + + + + + + + Return a friendly minion to your hand. It costs (2) less. + + Graven Tung + + + Rogue dance troops will sometimes Shadowstep away at the end of a performance. Crowds love it. + + + + + + + + 0cc6ff8b-fd76-4877-8348-578aef4059a9 + Preparation + + + + + + + + The next spell you cast this turn costs (3) less. + + Clint Langley + "Be Prepared" - Rogue Motto + + + + + + Preparation + + + + The next spell you cast this turn costs (3) less. + + + + + + + + + + + 5c715803-9f7e-4014-abed-776add033ac4 + Wrath + + + + + + + <b>Choose One</b> - Deal $3 damage to a minion; or $1 damage and draw a card. + + Raymond Swanland + The talk around the Ratchet Inn is that this card is too good and should be a Legendary. + + + + + + + + + + 68f1b82c-7a25-4b09-af67-4f54eb066960 + Wrath + + + + + + Deal $3 damage to a minion. + + + + + + + + + 0aba4b5d-3047-4a38-9053-073c3acf41fa + Wrath + + + + + + Deal $1 damage to a minion. Draw a card. + + + + + + + + + 6a765b71-10c6-46e0-b392-dd21cb516cf5 + Mark of Nature + + + + + + + <b>Choose One</b> - Give a minion +4 Attack; or +4 Health and <b>Taunt</b>. + + + + Clint Langley + Druids call it the "Mark of Nature." Everyone else calls it "needing a bath." + + + + + + + + + 0671c592-ad07-41e3-a91b-484778498e07 + Mark of Nature + + + + + + +4 Attack. + + + + + + + + + Mark of Nature + + + + This minion has +4 Attack. + + + + + + e3ff87a1-9d18-4097-b74b-64d74d061cdf + Mark of Nature + + + + + + +4 Health and <b>Taunt</b>. + + + + + + + + + Mark of Nature + + + + This minion has +4 Health and <b>Taunt</b>. + + + + + + b8e935bc-b9e9-4c58-bc13-12182a721972 + Soul of the Forest + + + + + + + + Give your minions "<b>Deathrattle:</b> Summon a 2/2 Treant." + + + + Markus Erdt + "Reforestation" is suddenly a terrifying word. + + + + + Soul of the Forest + + + + Deathrattle: Summon a 2/2 Treant. + + + + + Treant + + + + + + + + + + + + + c6a2ef21-97f2-4477-a3d1-a75aca82c06a + Power of the Wild + + + + + + + <b>Choose One</b> - Give your minions +1/+1; or Summon a 3/2 Panther. + + + + Steve Tappin + Never look a panther in the eye. Or is it 'Always look a panther in the eye'? Well, it's one of those. + + + + + d689b0f7-5eb5-4828-98f4-472fd79dec00 + Summon a Panther + + + + + + Summon a 3/2 Panther. + + + + + + + + 46f9be6e-e077-47a8-97ce-cc7c54502651 + Leader of the Pack + + + + + + Give your minions +1/+1. + + + + + + Leader of the Pack + + + + +1/+1. + + + + + + Panther + + + + + + + + + + + + + + ec37f417-25c4-45d0-a3cd-296f1c25174f + Naturalize + + + + + + + + Destroy a minion. Your opponent draws 2 cards. + + + + Leo Che + Another one bites the dust. + + + + + + + Dire Wolf Alpha + + + + + + + + + Adjacent minions have +1 Attack. + + + + + John Dickenson + We are pretty excited about the upcoming release of Dire Wolf Beta, just repost this sign for a chance at a key. + + + + + + + Strength of the Pack + + + Dire Wolf Alpha is granting +1 Attack to this minion. + + + + + + 94607564-5027-40c7-b217-ccaa8ad362e6 + Nourish + + + + + + + <b>Choose One</b> - Gain 2 Mana Crystals; or Draw 3 cards. + + Terese Nielsen + Druids take nourishment from many things: the power of nature, the songbird's chirp, a chocolate cake. + + + + + + + b7d09f14-695d-499e-819e-24c3d330e1db + Nourish + + + + + + Gain 2 Mana Crystals. + + + + b4e2d9f2-624b-4be3-a4a3-2f71ba3f2614 + Nourish + + + + + + Draw 3 cards. + + + + + + 804d980e-b12b-4eeb-afea-301d96145fbb + Druid of the Claw + + + + + + + + + <b>Choose One -</b> <b>Charge</b>; or +2 Health and <b>Taunt</b>. + + + + Luca Zontini + Cat or Bear? Cat or Bear?! I just cannot CHOOSE! + + + + + + + f436bbc4-fd5f-42e2-8a02-6f1ef7bf6419 + Cat Form + + + + + + + <b>Charge</b> + + + + + + 8121198e-6dc6-405d-8b2d-0c4d2a6e4e59 + Bear Form + + + + + + + +2 Health and <b>Taunt</b>. + + + + + + Druid of the Claw + + + + + + + + <b>Charge</b> + + + + + + + + Druid of the Claw + + + + + + + + <b>Taunt</b> + + + + + + + + be289078-dff1-4cec-969c-efcc1d60cf03 + Keeper of the Grove + + + + + + + + + <b>Choose One</b> - Deal 2 damage; or <b>Silence</b> a minion. + + + + Gabor Szikszai + These guys just show up and start Keeping your Groves without even asking. + + + + + + + + 50d10cab-1438-47aa-b71a-639e7984fa26 + Moonfire + + + + + + Deal 2 damage. + + + + + + 963b5b27-818e-4915-815d-c7fc3a1c330e + Dispel + + + + + + <b>Silence</b> a minion. + + + + + + + + + + Emperor Cobra + + + + + + + + Destroy any minion damaged by this minion. + + + Lars Grant-West + + + + The Sholazar Basin is home to a lot of really horrible things. If you're going to visit, wear bug spray. And plate armor. + + + + + b22cd999-605f-4102-9d85-41e562fdb7ae + Ancient of War + + + + + + + + + <b>Choose One</b> - ++5 Attack; or +5 Health and <b>Taunt</b>. + + + + Sean O’Daniels + Young Night Elves love to play "Who can get the Ancient of War to Uproot?" You lose if you get crushed to death. + + + + + + ec4a6946-90a6-49c2-bb87-b9130226d2cd + Rooted + + + + + + +5 Health and <b>Taunt</b>. + + + + + + Rooted + + + + +5 Health and <b>Taunt</b>. + + + + + + 01388628-946d-465b-871a-222d03526a69 + Uproot + + + + + + +5 Attack. + + + + + + Uprooted + + + + +5 Attack. + + + + + + 1092910a-734d-44e9-a8a6-bd53a37b4899 + Lightning Bolt + + + + + + + + Deal $3 damage. <b>Overload:</b> (1) + + Daarken + Lightning Bolt! Lightning Bolt! Lightning Bolt! + + + + + + + + 5c98dcbc-fd61-4aea-8221-e3ff4acb48b7 + Lava Burst + + + + + + + + Deal $5 damage. <b>Overload:</b> (2) + + Dan Scott + It's like an ocean of liquid magma in your mouth! + + + + + + + + Dust Devil + + + + + + + + + + <b>Windfury</b>. <b>Overload:</b> (2) + + + + Raymond Swanland + Westfall is full of dust devils. And buzzards. And crazed golems. And pirates. Why does anyone live here? + + + + + + + 5b15512a-0fc5-464c-a57c-47d7899fd4f6 + Earth Shock + + + + + + + + <b>Silence</b> a minion, then deal $1 damage to it. + + + + Kevin Chin + Earth Shock? Shouldn't it be "Azeroth Shock"? + + + + + + + + Stormforged Axe + + + + + + + + + + <b>Overload:</b> (1) + + + + Nate Bowden + Yo, that's a nice axe. + + + + + 9f17aa0d-8974-4914-9d57-1b685a130c32 + Feral Spirit + + + + + + + + Summon two 2/3 Spirit Wolves with <b>Taunt</b>. <b>Overload:</b> (2) + + + + Clint Langley + Spirit wolves are like regular wolves with pom-poms. + + + + + + + + + Baron Geddon + + + + + + + + + At the end of your turn, deal 2 damage to ALL other characters. + + + + + Ian Ameling + Baron Geddon was Ragnaros's foremost lieutenant, until he got FIRED. + + + + + + Earth Elemental + + + + + + + + + + <b>Taunt</b>. <b>Overload:</b> (3) + + Dan Scott + Nothing beats rock. + + + + + + + ac9220db-c2e7-4dca-8e3e-c23f0e4a97d6 + Forked Lightning + + + + + + + + Deal $2 damage to 2 random enemy minions. <b>Overload:</b> (2) + + Ralph Horsley + + + If you combine it with Spooned Lightning and Knived Lightning, you have the full dining set. + + + + + + + + Unbound Elemental + + + + + + + + + Whenever you play a card with <b>Overload</b>, gain +1/+1. + + + + Matt Gaser + + Unlike bound elementals, Unbound ones really enjoy a night on the town. + + + + + + Overloading + + + + Increased stats. + + + + + + 0f69420c-bbe9-4524-bc14-9a855f5b24d7 + Lightning Storm + + + + + + + + Deal $2-$3 damage to all enemy minions. <b>Overload:</b> (2) + + + + Christopher Moeller + An umbrella won't be effective, I'm afraid. + + + + + + Ethereal Arcanist + + + + + + + + + If you control a <b>Secret</b> at the end of your turn, gain +2/+2. + + + + Michael Komarck + The ethereals are wrapped in cloth to give form to their non-corporeal bodies. Also because it's nice and soft. + + + + + + + Raw Power! + + + + Increased stats. + + + + + + b13d477d-17c7-42d5-884a-a8518077e042 + Cone of Cold + + + + + + + + <b>Freeze</b> a minion and the minions next to it, and deal $1 damage to them. + + + + + Magi of the Kirin Tor were casting Cubes of Cold for many years before Cones came into fashion some 90 years ago. + Leo Che + + + + + + + + 89cdadf1-6077-479c-b2e8-4ecec39cfe07 + Deal $10 damage. + Pyroblast + + + + + + + + + + + + Take the time for an evil laugh after you draw this card. + Luca Zontini + + + + + + 8972f911-fddb-4fd3-88fa-5b06f481a4eb + Frost Elemental + + + + + + + + + <b>Battlecry:</b> <b>Freeze</b> a character. + + + Freeze a character. + + + Dan Scott + When a Water elemental and an Ice elemental love each other VERY much... + + + + + + + + + Azure Drake + + + + + + + + + <b>Spell Damage +1</b>. <b>Battlecry:</b> Draw a card. + + + + Ben Zhang + They initially planned to be the Beryl or Cerulean drakes, but those felt a tad too pretentious. + + + + + + + Counterspell + + + + + + + + <b>Secret:</b> When your opponent casts a spell, <b>Counter</b> it. + + + + What's the difference between a mage playing with Counterspell and a mage who isn't? The mage who isn't is getting Pyroblasted in the face. + Jason Chan + + + + + + + Ice Barrier + + + + + + + + <b>Secret:</b> When your hero is attacked, gain 8 Armor. + + This is Rank 1. Rank 2 is Chocolate Milk Barrier. + Alex Garner + + + + + + + + Mirror Entity + + + + + + + + <b>Secret:</b> After your opponent plays a minion, summon a copy of it. + + + + + "You go first." - Krush'gor the Behemoth, to his pet boar. + Raven Mimura + + + + + + Ice Block + + + + + + + + <b>Secret:</b> When your hero takes fatal damage, prevent it and become <b>Immune</b> this turn. + + Ice is nice, and will suffice! + Carl Frank + + + + + + + + + Ice Block + + + + Your hero is <b>Immune</b> this turn. + + + + + + + + + + Ragnaros the Firelord + + + + + + + + + Can't attack. At the end of your turn, deal 8 damage to a random enemy. + + + + + + Greg Staples + Ragnaros was summoned by the Dark Iron dwarves, who were eventually enslaved by the Firelord. Summoning Ragnaros often doesn’t work out the way you want it to. + + + + + + + Felguard + + + + + + + + + + + <b>Taunt</b>. <b>Battlecry:</b> Destroy one of your Mana Crystals. + + + + + John Polidora + Yes, he'll fight for you. BUT HE'S NOT GOING TO LIKE IT. + + + + + + + 36bfefdd-48f7-43dd-88bb-36c3b71f6c45 + Shadowflame + + + + + + + + Destroy a friendly minion and deal its Attack damage to all enemy minions. + + + + + Dave Kendall + Start with a powerful minion and stir in Shadowflame and you have a good time! + + + + + + + + + 5c1e2577-5995-40a0-9b89-533372e84877 + Void Terror + + + + + + + <b>Battlecry:</b> Destroy the minions on either side of this minion and gain their Attack and Health. + + + + + + Alexander Alexandrov + If you put this into your deck, you WILL lose the trust of your other minions. + + + + + Consume + + + + Increased stats. + + + + + + 4599bbdf-caf7-482f-be57-b71359b721e0 + Siphon Soul + + + + + + + + Destroy a minion. Restore #3 Health to your hero. + + + + + Tyler Walpole + You probably should avoid siphoning your own soul. You might create some kind of weird infinite loop. + + + + + + + Doomguard + + + + + + + + + + + <b>Charge</b>. <b>Battlecry:</b> Discard two random cards. + + + Lucas Graciano + Summoning a doomguard is risky. <i>Someone</i> is going to die. + + + + + + + Twisting Nether + + + + + + + + Destroy all minions. + + + + + Dave Allsop + The Twisting Nether is a formless place of magic and illusion and destroyed minions. + + + + Pit Lord + + + + + + + + + + + <b>Battlecry:</b> Deal 5 damage to your hero. + + + + + Glenn Rane + Mannoroth, Magtheridon, and Brutallus may be dead, but it turns out there are a LOT of pit lords. + + + + + Summoning Portal + + + + + + + + + Your minions cost (2) less, but not less than (1). + + Tyler Walpole + NOT LESS THAN 1! Don't get any ideas! + + + + + + + + 74f19b0e-2f0f-40ea-bf8c-3db37a308ddd + Power Overwhelming + + + + + + + + Give a friendly minion +4/+4 until end of turn. Then, it dies. Horribly. + + + Tom Baxa + We cannot even describe how horrible the death is. It's CRAZY bad! Maybe worse than that. Just don't do it. + + + + + + + + Power Overwhelming + + + + + This minion has +4/+4, but will die a horrible death at the end of the turn. + + + + + + + + + Sense Demons + + + + + + + + Put 2 random Demons from your deck into your hand. + + + + + Raven Mimura + Generally demons are pretty obvious and you don’t need a spell to sense them. + + + + Worthless Imp + + + + + + + + <i>You are out of demons! At least there are always imps...</i> + + + + + + Flame Imp + + + + + + + + + + + <b>Battlecry:</b> Deal 3 damage to your hero. + + + Alex Horley Orlandelli + + + Imps like being on fire. They just do. + + + + + 745cbe07-c1e8-46ed-93a7-131722f6abbc + Bane of Doom + + + + + + + + Deal $2 damage to a character. If that kills it, summon a random Demon. + + Raymond Swanland + + + My advice to you is to avoid Doom, if possible. + + + + + + + + + + + + Lord Jaraxxus + + + + + <b>Battlecry:</b> Destroy your hero and replace it with Lord Jaraxxus. + + + + + + + + + + Alex Horley Orlandelli + "TRIFLING GNOME! YOUR ARROGANCE WILL BE YOUR UNDOING!!!!" + + + + + Lord Jaraxxus + + + + + + + + + + + + + + + + Blood Fury + + + + + + + + + + + Silence + + + + + + + + <b>Silence</b> a minion. + + + + + Zoltan & Gabor + Reserved for enemy spellcasters, evil liches from beyond the grave, and karaoke nights at the Grim Guzzler. + + + + + + + + d2bacef2-8095-466f-9507-655c664f17b1 + Shadow Madness + + + + + + + + Gain control of an enemy minion with 3 or less Attack until end of turn. + + + + Mark Gibbons + You can rationalize it all you want, it's still a mean thing to do. + + + + + + + + + + Shadow Madness + + + + This minion has switched controllers this turn. + + + + + + + + Lightspawn + + + + + + + + This minion's Attack is always equal to its Health. + + + + + + Daarken + Spawn of the Light? Or Pawn of the Lights? + + + + fc872394-056c-4192-a448-2e2b675340e1 + Thoughtsteal + + + + + + + + Copy 2 cards from your opponent's deck and put them into your hand. + + + + Alex Garner + "What do you get when you cast Thoughtsteal on an Orc? Nothing!" - Tauren joke + + + + Lightwell + + + + + + + + + + At the start of your turn, restore 3 Health to a damaged friendly character. + + + + Blizzard Entertainment + It isn't clear if people ignore the Lightwell, or if it is just invisible. + + + + + + + e0a351e3-a399-432f-946b-cab229f1eb0a + Mindgames + + + + + + + + Put a copy of a random minion from your opponent's deck into the battlefield. + + + + Zoltan & Gabor + Sometimes it feels like this is all a game. + + + + + + + + + + + + + Mindgames whiffed! Your opponent had no minions! + Shadow of Nothing + + + + + ff1f4f95-a80d-4fc7-871f-986ddca62206 + Divine Favor + + + + + + + + Draw cards until you have as many in hand as your opponent. + + Lucas Graciano + This is not just a favor, but a divine one, like helping someone move a couch with a fold out bed! + + + + Prophet Velen + + + + + + + + + + Double the damage and healing of your spells and Hero Power. + + + Wei Wang + He's been exiled from his home, and all his brothers turned evil, but otherwise he doesn't have a lot to complain about. + + + + + + 4a36cd90-3bb4-4e19-a393-59f5ecad56ba + Lay on Hands + + + + + + + + Restore #8 Health. Draw 3 cards. + + + + Raymond Swanland + A grammatically awkward life saver. + + + + + + e2cd1f16-7678-4a4a-95b2-2193b1aacf1a + Blessed Champion + + + + + + + Double a minion's Attack. + + + Tyler Walpole + This card causes double the trouble AND double the fun. + + + + + + + Blessed Champion + + + + This minion's Attack has been doubled. + + + + + + c904173c-b220-4302-97e8-f470bdd52c15 + Argent Protector + + + + + + + + + + <b>Battlecry:</b> Give a friendly minion <b>Divine Shield</b>. + + Give <b>Divine Shield</b>. + + + Doug Alexander + "I'm not saying you can dodge fireballs. I'm saying with this shield, you won't have to." + + + + + + + + + + + 463a57fd-c5cf-4676-8bac-b19f94d7f68f + Blessing of Wisdom + + + + + + + Choose a minion. Whenever it attacks, draw a card. + + + Chippy + Apparently with wisdom comes the knowledge that you should probably be attacking every turn. + + + + + + + Blessing of Wisdom + + + + When this minion attacks, the player who blessed it draws a card. + + + + + + + + Blessing of Wisdom + + + + When this minion attacks, the enemy player draws a card. + + + + + + + + 5387f21c-5014-485e-a39f-3d05c5e1d592 + Holy Wrath + Draw a card and deal damage equal to its cost. + + + + + + + + + + + Justin Sweet + C'mon Molten Giant!! + + + + + + + Sword of Justice + After you summon a minion, give it +1/+1 and this loses 1 Durability. + + + + + + + + + + + + + Efrem Palacios + I dub you Sir Loin of Beef! + + + + + + Justice Served + + + + Has +1/+1. + + + + + + Repentance + <b>Secret:</b> After your opponent plays a minion, reduce its Health to 1. + + + + + + + + + + + Gonzalo Ordonez + Repentance often comes in the moment before obliteration. Curious. + + + + + + + + Repentance + + + + Health reduced to 1. + + + + + + 05db42af-669a-426c-a0ee-44b871475357 + Aldor Peacekeeper + <b>Battlecry:</b> Change an enemy minion's Attack to 1. + + + + + + + + + + + + + Dany Orizio + The Aldor hate two things: the Scryers and smooth jazz. + Change Attack to 1. + + + + + + + + + Stand Down! + + + + Attack changed to 1. + + + + + + Tirion Fordring + + + + + + + + + + <b>Divine Shield</b>. <b>Taunt</b>. <b>Deathrattle:</b> Equip a 5/3 Ashbringer. + + + Brom + + + If you haven't heard the Tirion Fordring theme song, it's because it doesn't exist. + + + + + + + + + + Ashbringer + + + + + + + + + + 6b2a252b-6666-4520-a960-fbe88a54aafd + Avenging Wrath + Deal $8 damage randomly split among all enemies. + + + + + + + + + + + Alex Garner + Wham! Wham! Wham! Wham! Wham! Wham! Wham! Wham! + + + + + Tauren Warrior + + + + + + + + + <b>Taunt</b>. <b>Enrage:</b> +3 Attack + + Paul Warzecha + Tauren Warrior: Champion of Mulgore, Slayer of Quilboar, Rider of Thunderbluff Elevators. + + + + + + + Enraged + + + + + + +3 Attack. + + + + + c88a54f7-22df-4ba2-bd30-b218679e64bd + Slam + + + + + + + + Deal $2 damage to a minion. If it survives, draw a card. + + E.M. Gist + "Dun da dun, dun da dun": if you've heard an ogre sing this, it's too late. + + + + + + + b325b69e-6855-4de3-a96b-592d349880d6 + Battle Rage + + + + + + + + Draw a card for each damaged friendly character. + + Alex Horley Orlandelli + "You won't like me when I'm angry." + + + + + + + + Amani Berserker + + + + + + + + + <b>Enrage:</b> +3 Attack + + Chippy + If an Amani berserker asks "Joo lookin' at me?!", the correct response is "Nah, mon". + + + + + Enraged + + + + + + +3 Attack. + + + + + Mogu'shan Warden + + + + + + + + + <b>Taunt</b> + + + + Cole Eastburn + All these guys ever do is talk about the Thunder King. BOOOORRRINNG! + + + + + Arathi Weaponsmith + + + + + + + + + + <b>Battlecry:</b> Equip a 2/2 weapon. + + + + Samwise + 50% off fist weapons, limited time only! + + + + + Battle Axe + + + + + + + + + + + Armorsmith + + + + + + + + + + Whenever a friendly minion takes damage, gain 1 Armor. + + + + Greg Hildebrandt + She accepts guild funds for repairs! + + + + + + Shieldbearer + + + + + + + + + <b>Taunt</b> + + + + Carl Critchlow + Have you seen the size of the shields in this game?? This is no easy job. + + + + + bc2cdc82-6232-41c0-bf67-e3e3fc3db11e + Brawl + + + + + + + + Destroy all minions except one. <i>(chosen randomly)</i> + + + + Wayne Reynolds + Do you know the first rule of Brawl Club? + + + + + + 9b42e559-052c-4655-ab9b-d82ba20835f5 + Mortal Strike + + + + + + + Deal $4 damage. If you have 12 or less Health, deal $6 instead. + + + Zoltan & Gabor + "If you only use one ability, use Mortal Strike." - The Warrior Code, Line 6 + + + + + + + + + 7d8746db-98bb-499c-be00-f37be77cd424 + Upgrade! + + + + + + + + If you have a weapon, give it +1/+1. Otherwise equip a 1/3 weapon. + + + + Matt Cavotta + Easily worth 50 DKP. + + + + Upgraded + + + + +1 Attack and +1 Durability. + + + + + + Heavy Axe + + + + + + + + + 12f75fac-42bf-485b-a10c-9d766d8ab85f + Shield Slam + + + + + + + + Deal 1 damage to a minion for each Armor you have. + + + + "What is a better weapon? The sharp one your enemies expect, or the blunt one they ignore?" - The Art of Warrior, Chapter 9 + Raymond Swanland + + + + + + + + Gorehowl + + + + + + + + + + Attacking a minion costs 1 Attack instead of 1 Durability. + + + + Zoltan & Gabor + Grommash Hellscream's famous axe. Somehow this ended up in Prince Malchezaar's possession. Quite the mystery! + + + + + + + Bloodrage + + + + No durability loss. + + + + + + + + + + Needs Sharpening + + + + Decreased Attack. + + + + + + Raging Worgen + + + + + + + + + <b>Enrage:</b> <b>Windfury</b> and +1 Attack + + + + Alex Horley Orlandelli + If he's raging now, just wait until he gets nerfed. + + + + + + Enraged + + + + + + +1 Attack and <b>Windfury</b>. + + + + + Grommash Hellscream + + + + + + + + + + <b>Charge</b> +<b>Enrage:</b> +6 Attack + + + Glenn Rane + Grommash drank the tainted blood of Mannoroth, dooming the orcs to green skin and red eyes! Maybe not his best decision. + + + + + + + Enraged + + + + + +6 Attack + + + + + + Murloc Warleader + + + + + + + + + + ALL other Murlocs have +2/+1. + + + + Tim McBurnie + Do Murlocs ever get tired of making the same old sound? Nope! Mrglglrglglglglglglgl! + + + + + Mrgglaargl! + + + Murloc Warleader is granting +2/+1. + + + + + + Murloc Tidecaller + + + + + + + + + + Whenever a Murloc is summoned, gain +1 Attack. + + + + Jaemin Kim + This guy gets crazy strong at family reunions. + + + + + + Blarghghl + + + Increased Attack. + + + + + + Patient Assassin + + + + + + + + + + <b>Stealth</b>. Destroy any minion damaged by this minion. + + + + Ben Olson + He’s not really that patient. It just takes a while for someone to walk by that he can actually reach. + + + + + + + Scavenging Hyena + + + + + + + + + Whenever a friendly Beast dies, gain +2/+1. + + + + Jim Nelson + Hyenas prefer the bones of kodos or windserpents, but they'll eat pretty much anything. Even Brussels sprouts. + + + + + + Well Fed + + + + Increased Attack and Health. + + + + + + Misdirection + + + + + + + <b>Secret:</b> When a character attacks your hero, instead he attacks another random character. + + + + Daren Bader + Sometimes it's as simple as putting on a fake mustache and pointing at someone else. + + + + + + Savannah Highmane + + + + <b>Deathrattle:</b> Summon two 2/2 Hyenas. + + + + + + + + + Milivoj Ceran + In the jungle, the mighty jungle, the lion gets slowly consumed by hyenas. + + + + + + Hyena + + + + + + + + + + + Andrew Robinson + + + Eaglehorn Bow + + + + + + + + + Whenever a friendly <b>Secret</b> is revealed, gain +1 Durability. + + + Cyril Van Der Haegen + First Lesson: Put the pointy end in the other guy. + + + + + + + Upgraded + + + + Increased Durability. + + + + + + 73a53fd2-aa5a-4385-8f7f-a745ca933617 + Explosive Shot + + + + + + + + Deal $5 damage to a minion and $2 damage to adjacent ones. + + Tom Baxa + + + Pull the pin, count to 5, then shoot. Then duck. + + + + + + + b560ff40-9ed7-4ff7-8a7a-120d802afb3c + Unleash the Hounds + + + + + + + For each enemy minion, summon a 1/1 Hound with <b>Charge</b>. + + + Linggar Bramanty + You must read the name of this card out loud each time you play it. + + + + + + + + Hound + + + + <b>Charge</b> + + + + + + + + + + + King Krush + + + + + + + + + + <b>Charge</b> + + + + Alex Horley Orlandelli + The best defense against King Krush is to have someone you don’t like standing in front of you. + + + + + 41c49567-b4aa-4294-8ade-46c180c66131 + Flare + + + + + + + All minions lose <b>Stealth</b>. Destroy all enemy <b>Secrets</b>. Draw a card. + + + + Tyler Walpole + Not only does it reveal your enemies, but it's also great for parties! + + + + + + ec001c18-5106-4cd3-a9c3-fb35a1153440 + Bestial Wrath + + + + + + + Give a friendly Beast +2 Attack and <b>Immune</b> this turn. + + + + Alex Horley Orlandelli + The seething wrath is just beneath the surface. Beneath that is wild abandon, followed by slight annoyance. + + + + + + + + + Bestial Wrath + + + + +2 Attack and <b>Immune</b> this turn. + + + + + + + + Snake Trap + + + + + + + <b>Secret:</b> When one of your minions is attacked, summon three 1/1 Snakes. + + Bernie Kang + Why did it have to be snakes? + + + + + + + + Snake + + + + + + + + + + + + + Harvest Golem + + + + + + + + + <b>Deathrattle:</b> Summon a 2/1 Damaged Golem. + + Brian Despain + "Overheat threshold exceeded. System failure. Wheat clog in port two. Shutting down." + + + + + + + + + Nat Pagle + + + + + + + + + At the start of your turn, you have a 50% chance to draw an extra card. + + + + + Steve Prescott + Nat Pagle, Azeroth's premier fisherman! He invented the Auto-Angler 3000, the Extendo-Pole 3000, and the Lure-o-matic 2099 (still in testing). + + + + + + + 5d39914d-7f77-4fef-8c69-fa08db5ab6ae + Harrison Jones + + + + + + + + + <b>Battlecry:</b> Destroy your opponent's weapon and draw cards equal to its Durability. + + + + + Matt Dixon + “That belongs in the Hall of Explorers!” + + + + + Archmage Antonidas + + + + + + + + + Whenever you cast a spell, add a 'Fireball' spell to your hand. + + + + + + Antonidas was the Grand Magus of the Kirin Tor, and Jaina's mentor. This was a big step up from being Grand Magus of Jelly Donuts. + Wayne Reynolds + + + + + + Nozdormu + + + + + + + + + Players only have 15 seconds to take their turns. + + + + + + James Ryman + Time to write some flavor text. + + + + b44631dc-eec1-434a-a172-04bce74970c7 + Alexstrasza + + + + + + + + + <b>Battlecry:</b> Set a hero's remaining Health to 15. + + + + + + Raymond Swanland + Alexstrasza the Life-Binder brings life and hope to everyone. Except Deathwing. And Malygos. And Nekros. + Set Health to 15. + + + + + + + + Alexstrasza's Fire + + + Health set to 15. + + + + + + cde7eb0e-6173-490f-8901-5799cd878305 + Onyxia + + + + + + + + + + + + + + <b>Battlecry:</b> Summon 1/1 Whelps until your side of the battlefield is full. + Dany Orizio + Onyxia long manipulated the Stormwind Court by disguising herself as Lady Katrana Prestor. You would have thought that the giant wings and scales would have been a giveaway. + + + + + Malygos + + + + + + + + + <b>Spell Damage +5</b> + + + + + + Michael Komarck + Malygos hates it when mortals use magic. He gets so mad! + + + + + + 111ce0c3-f379-4a32-b181-955d962aa42a + Faceless Manipulator + + + + + + + + + <b>Battlecry:</b> Choose a minion and become a copy of it. + + Become a copy of a minion. + + + Raymond Swanland + The Faceless Ones are servants of Yogg-Saron, and they feed on fear. Right now they are feeding on your fear of accidentally disenchanting all your good cards. + + + + + + + + + Doomhammer + + + + + + + + + + <b>Windfury, Overload:</b> (2) + + + + John Polidora + Orgrim Doomhammer gave this legendary weapon to Thrall. His name is a total coincidence. + + + + + + + + 1343f2e6-ff78-411d-8677-a9c2e45e0baa + Bite + + + + + + + + Give your hero +4 Attack this turn and 4 Armor. + + + + Tom Baxa + Chew your food! + + + + Bite + + + + + +4 Attack this turn. + + + + + + d693477e-0b88-45d1-bad5-5384baaeb1f7 + Force of Nature + + + + + + + + Summon three 2/2 Treants. + + + + Trevor Jacobs + "I think I'll just nap under these trees. Wait... AAAAAHHH!" - Blinkfizz, the Unfortunate Gnome + + + + + + + Ysera + + + + + + + + + At the end of your turn, add a Dream Card to your hand. + + + + + + Gabor Szikszai + Ysera rules the Emerald Dream. Which is some kind of green-mirror-version of the real world, or something? + + + + + + + + + + + 2dd5b192-0e52-457a-9899-fc6a98fa5a33 + Cenarius + + + + + + + + + <b>Choose One</b> - Give your other minions +2/+2; or Summon two 2/2 Treants with <b>Taunt</b>. + + + + + Alex Horley Orlandelli + Yes, he's a demigod. No, he doesn't need to wear a shirt. + + + + + + f52f098d-dd17-41af-b8d7-694ba480e7ba + Demigod's Favor + + + + + + Give your other minions +2/+2. + + + + + + Demigod's Favor + +2/+2. + + + + + + + + + + e66f1bb3-dec4-40cd-a851-cdc6fcb761e6 + Shan'do's Lesson + + + + + + Summon two 2/2 Treants with <b>Taunt</b>. + + + + + + Treant + + + + + + + <b>Taunt</b> + + + + + Mana Tide Totem + + + + + + + + At the end of your turn, draw a card. + + + + + + + Scott Altmann + It is said that some shaman can say "Floatin' totem" 10 times, fast. + + + + + + The Beast + + + + + + + + + <b>Deathrattle:</b> Summon a 3/3 Finkle Einhorn for your opponent. + + + + Glenn Rane + He lives in Blackrock Mountain. He eats Gnomes. That's pretty much it. + + + + + + df2d11fa-bec4-4185-960b-fe0045645279 + Savagery + + + + + + + Deal damage equal to your hero's Attack to a minion. + + + + Dave Rapoza + It is true that some druids are savage, but others still enjoy a quiet moment and a spot of tea. + + + + + + + + 1164592e-9e3c-4663-bb8f-b5d03e066e4f + Priestess of Elune + + + + + + + + <b>Battlecry:</b> Restore 4 Health to your hero. + + Dan Scott + If she threatens to "moon" you, it's not what you think. + + + + + fb15ffb3-a414-4622-8c18-21783d04e778 + Ancient Mage + + + + + + + <b>Battlecry:</b> Give adjacent minions <b>Spell Damage +1</b>. + + + + + Howard Lyon + Sometimes he forgets and just wanders into someone else's game. + + + + + + Teachings of the Kirin Tor + + + <b>Spell Damage +1</b>. + + + + Sea Giant + + + + + + + + Costs (1) less for each other minion on the battlefield. + + Svetlin Velinov + See? Giant. + + + + + + b83882c2-46ab-4376-b5f1-b9118273d371 + Blood Knight + + + + + + <b>Battlecry:</b> All minions lose <b>Divine Shield</b>. Gain +3/+3 for each Shield lost. + + + + + + Trent Kaniuga + The Blood Knights get their holy powers from the Sunwell, which you should NOT bathe in. + + + + + + Shadows of M'uru + + + + This minion has consumed Divine Shields and has increased Attack and Health. + + + + + + Auchenai Soulpriest + + + + + + + + + Your cards and powers that restore Health now deal damage instead. + + Doug Alexander + The Auchenai know the end is coming, but they're not sure when. + + + + + + + Vaporize + + + + + + + <b>Secret:</b> When a minion attacks your hero, destroy it. + + + + + Rumor has it that Deathwing brought about the Cataclysm after losing a game to this card. We may never know the truth. + Raymond Swanland + + + + + + Cult Master + + + + + + + + Whenever one of your other minions dies, draw a card. + + + + + Raymond Swanland + She may be an evil cult master, but she still calls her parents once a week. + + + + + + 1da2233d-656d-4fb4-b78b-3b1c8d538eaa + Demonfire + + + + + + Deal $2 damage to a minion. If it’s a friendly Demon, give it +2/+2 instead. + + + + Ben Wootten + + + Demonfire is like regular fire except for IT NEVER STOPS BURNING HELLLPPP + + + + + + + Demonfire + + + + + + + This Demon has +2/+2. + + + + + + Imp Master + + + + + + + + At the end of your turn, deal 1 damage to this minion and summon a 1/1 Imp. + + + + + Mark Gibbons + She would enjoy the job a lot more if she just could get the imps to QUIT BITING HER. + + + + + + Imp + + + + + + + + + + 6f02ec1e-bd79-409b-ab12-e6f16c26966c + Cruel Taskmaster + + + + + + + + + <b>Battlecry:</b> Deal 1 damage to a minion and give it +2 Attack. + + Deal 1 damage and grant +2 Attack. + Phroilan Gardner + "I'm going to need you to come in on Sunday." - Cruel Taskmaster + + + + + + + + + Whipped Into Shape + + + + +2 Attack. + + + + + + Frothing Berserker + + + + + + + + + Whenever a minion takes damage, gain +1 Attack. + + + + Simon Bisley + He used to work as an accountant before he tried his hand at Berserkering. + + + + + + Berserk + + + + Increased Attack. + + + + + + 158b97d6-f4a5-4494-9b6e-e7b73080b0df + Inner Rage + + + + + + + Deal $1 damage to a minion and give it +2 Attack. + + Slawomir Maniak + They're only smiling on the outside. + + + + + + + Inner Rage + + + + +2 Attack. + + + + + + Sorcerer's Apprentice + + + + + + + + + Your spells cost (1) less. + + Apprentices are great for bossing around. "Conjure me some mana buns! And a coffee! Make that a mana coffee!" + Alex Horley Orlandelli + + + + + + + Snipe + + + + + + + <b>Secret:</b> After your opponent plays a minion, deal $4 damage to it. + + Lorenzo Minaca + + + A great sniper hits the spot. Just like a delicious flank of boar. Mmmmm. + + + + + + + + Explosive Trap + + + + + + + <b>Secret:</b> When your hero is attacked, deal $2 damage to all enemies. + + + + Brandon Kitkouski + It traps your food AND cooks it for you! + + + + + + Freezing Trap + + + + + + + <b>Secret:</b> When an enemy minion attacks, return it to its owner's hand and it costs (2) more. + + + + Matt Gaser + "Dang, that's cold." - appropriate response to Freezing Trap, or a mean joke. + + + + + + Trapped + + + + Will be <b>Frozen</b> again at the start of the next turn. + + + + + 87fac18f-63f8-4d0f-b005-adf249191811 + Kirin Tor Mage + + + + + + + + + + <b>Battlecry:</b> The next <b>Secret</b> you play this turn costs (0). + + + + The Kirin Tor reside in the floating city of Dalaran. How do you make a Dalaran float? Two scoops of ice cream, one scoop of Dalaran. + Popo Wei + + + + + + Power of the Kirin Tor + + + + Your next Secret costs (0). + + + + + + + + + + Edwin VanCleef + + + + + + + + + + <b>Combo:</b> Gain +2/+2 for each card played earlier this turn. + + + Efrem Palacios + He led the Stonemasons in the reconstruction of Stormwind, and when the nobles refused to pay, he founded the Defias Brotherhood to, well, <i>deconstruct</i> Stormwind. + + + + + + + VanCleef's Vengeance + + + + Increased stats. + + + + + + Illidan Stormrage + + + + + + + + + Whenever you play a card, summon a 2/1 Flame of Azzinoth. + + + + + Alex Horley Orlandelli + + Illidan's brother, Malfurion, imprisoned him beneath Hyjal for 10,000 years. Stormrages are not good at letting go of grudges. + + + + + + Flame of Azzinoth + + + + + + + + Mana Wraith + + + + + + + + + ALL minions cost (1) more. + + Luca Zontini + + + They come out at night to eat leftover mana crystals. "Mmmmmm," they say. + + + + + 09a28389-535a-4368-9cdb-6a62e2604fbe + Deadly Shot + + + + + + + + Destroy a random enemy minion. + + + + Steve Prescott + Accuracy is not a highly valued trait among the mok'nathal. Deadliness is near the top, though. + + + + + + 6b165805-a3a1-4fa3-a040-f11b1ab1c131 + Equality + + + + + + + + Change the Health of ALL minions to 1. + + + + Michal Ivan + We are all special unique snowflakes... with 1 Health. + + + + Equality + + + + Health changed to 1. + + + + + + Molten Giant + + + + + + + Costs (1) less for each damage your hero has taken. + + Glenn Rane + He gets terrible heartburn. BECAUSE HE IS FULL OF LAVA. + + + + b77d03ca-1c61-4e5d-b30c-fa46f6457ff7 + Circle of Healing + + + + + + + Restore #4 Health to ALL minions. + + + Daarken + It isn't really a circle. + + + + 24ff2fd3-224e-439c-830c-742e5cb7be88 + Temple Enforcer + + + + + + + <b>Battlecry:</b> Give a friendly minion +3 Health. + + + + + Give +3 Health. + Daren Bader + He also moonlights Thursday nights as a bouncer at the Pig and Whistle Tavern. + + + + + + + + + Infusion + + + + +3 Health. + + + + + + 79be47bc-2e0a-4680-8a0f-137ccf3f5550 + Holy Fire + + + + + + + Deal $5 damage. Restore #5 Health to your hero. + Miguel Coimbra + Often followed by Holy Smokes! + + + + + + + + 3552d832-2854-42a2-ac5c-e9ae182e98b1 + Shadowform + + + + + + + Your Hero Power becomes 'Deal 2 damage'. If already in Shadowform: 3 damage. + + + Alex Horley Orlandelli + If a bright light shines on a priest in Shadowform… do they cast a shadow? + + + + 229425c1-cca1-4e74-8985-2ba7689d9fb8 + Mind Spike + + + + + <b>Hero Power</b> +Deal $2 damage. + + + + + + + + + 464bf8cb-0432-4785-aa28-d040dc995d66 + Mind Shatter + + + + + <b>Hero Power</b> +Deal $3 damage. + + + + + + + + + b5af0f9e-8576-47a3-8ca8-b9b1edeaf46c + Mass Dispel + + + + + + + <b>Silence</b> all enemy minions. Draw a card. + + + Sean O'Daniels + It dispels buffs, powers, hopes, and dreams. + + + + + Finkle Einhorn + + + + + + + + + + + + Spirit Wolf + + + + + + + + + <b>Taunt</b> + + + + + + Squirrel + + + + + + + + + + + + + + Devilsaur + + + + + + + + + + + + Mind Controlling + + + + + + + + + + + 16a251c6-90b4-42d3-9c4c-9cba842258ad + INFERNO! + + + + + + <b>Hero Power</b> +Summon a 6/6 Infernal. + + + + + + + Infernal + + + + + + + + + + + + + Treant + + + + + + + + + + + + + + Kidnapper + + + + + + + + <b>Combo:</b> Return a minion to its owner's hand. + + Dave Allsop + Return a minion to hand. + He just wants people to see his vacation photos. + + + + + + + + 22d22d5e-752c-4286-9898-9a0cc1fdde53 + Starfall + + + + + + <b>Choose One -</b> Deal $5 damage to a minion; or $2 damage to all enemy minions. + + + + Richard Wright + Is the sky falling? Yes. Yes it is. + + + + + + + + 4cec1d62-00e3-41f3-9d43-2cbc6550656d + Starfall + + + + Deal $2 damage to all enemy minions. + + + + + + 90885d05-d9e7-4275-a327-80239b5cae8b + Starfall + + + + Deal $5 damage to a minion. + + + + + + + + + aeb7b0e7-666a-44aa-ab82-6bcbbaaac9cf + Ancient of Lore + + + + + + + + <b>Choose One -</b> Draw a card; or Restore 5 Health. + + Patrik Hjelm + Go ahead, carve your initials in him. + + + + + + + + + 8074149a-0a02-44bc-bebb-751039a7ea46 + Ancient Teachings + + + + Draw a card. + + + + 86973367-f3b2-4554-888d-21faf7cc09fe + Ancient Secrets + + + + Restore 5 Health. + + + + + + + + Al'Akir the Windlord + + + + + + + + <b>Windfury, Charge, Divine Shield, Taunt</b> + + + + + Raymond Swanland + He is the weakest of the four Elemental Lords. And the other three don't let him forget it. + + + + + + + + + + + Mana Wyrm + + + + + + + + Whenever you cast a spell, gain +1 Attack. + + + + These wyrms feed on arcane energies, and while they are generally considered a nuisance rather than a real threat, you really shouldn't leave them alone with a bucket of mana. + Blizzard Cinematics + + + + + + Mana Gorged + + + + Increased attack. + + + + + + 770c5fd9-e0e9-4bc5-b358-52479bdf722e + Master of Disguise + + + + + + + <b>Battlecry:</b> Give a friendly minion <b>Stealth</b> until your next turn. + + Give <b>Stealth</b>. + + + + Ron Spencer + She's actually a male tauren. People don't call him "Master of Disguise" for nothing. + + + + + + + + + + + Disguised + + + + Stealthed until your next turn. + + + + + + + c5b2cfe4-3a01-423a-82be-cf633d4b215c + Hungry Crab + + + + + + + <b>Battlecry:</b> Destroy a Murloc and gain +2/+2. + + + Jaemin Kim + + + Murloc. It's what's for dinner. + + + + + + + + Full Belly + + + +2/+2. Full of Murloc. + + + + + + 17b5a25a-f518-4948-910b-7d90db5db4da + Bloodsail Raider + + + + + + + <b>Battlecry:</b> Gain Attack equal to the Attack of your weapon. + + + Jim Nelson + + + "I only plunder on days that end in 'y'." + + + + + Treasure Crazed + + + Increased Attack. + + + + + + Knife Juggler + + + + + + + After you summon a minion, deal 1 damage to a random enemy. + + + + Matt Cavotta + Ambitious Knife Jugglers sometimes graduate to Bomb Jugglers. They never last long enough to make it onto a card though. + + + + + + Wild Pyromancer + + + + + + + After you cast a spell, deal 1 damage to ALL minions. + + + + Alex Horley Orlandelli + BOOM BABY BOOM! BAD IS GOOD! DOWN WITH GOVERNMENT! + + + + + + Doomsayer + + + + + + + At the start of your turn, destroy ALL minions. + + + + Alex Horley Orlandelli + He's almost been right so many times. He was <i>sure</i> it was coming during the Cataclysm. + + + + + + + Dread Corsair + + + + + + + + <b>Taunt.</b> Costs (1) less per Attack of your weapon. + + + + Trent Kaniuga + "Yarrrr" is a pirate word that means "Greetings, milord." + + + + + + Faerie Dragon + + + + + + + Can't be targeted by spells or Hero Powers. + + + + Samwise + + Adorable. Immune to Magic. Doesn't pee on the rug. The perfect pet! + + + + 9436ba03-1e46-4c42-8b2b-a030fa53ea42 + Captain Greenskin + + + + + + + + <b>Battlecry:</b> Give your weapon +1/+1. + + + + + Dan Scott + He was <i>this close</i> to piloting a massive juggernaut into Stormwind Harbor. If it weren't for those pesky kids! + + + + + Greenskin's Command + + + +1/+1. + + + + + + f7e16bf5-f6bd-4520-b35f-130e5baa1a55 + Bloodsail Corsair + + + + + + + + <b>Battlecry:</b> Remove 1 Durability from your opponent's weapon. + + + + Randy Gallegos + Every pirate uses the same four digits to access Automated Gold Dispensers. It's called the "Pirate's Code". + + + + + Bolstered + + + Increased Health. + + + + + + Violet Teacher + + + + + + + Whenever you cast a spell, summon a 1/1 Violet Apprentice. + + + + James Ryman + If you don't pay attention, you may be turned into a pig. And then you get your name on the board. + + + + + + Violet Apprentice + + + + + + + + Southsea Captain + + + + + + + + Your other Pirates have +1/+1. + + + + Ken Steacy + When he saves enough plunder, he's going to commission an enormous captain's hat. He has hat envy. + + + + + Yarrr! + + + Southsea Captain is granting +1/+1. + + + + + + 11945b39-167f-4d55-a023-eb9330d4047c + Millhouse Manastorm + + + + + + + <b>Battlecry:</b> Enemy spells cost (0) next turn. + + + + + Jim Nelson + "I'm gonna light you up, sweetcheeks!" + + + + + Kill Millhouse! + + + + Spells cost (0) this turn! + + + + + + + + Deathwing + + + + + + <b>Battlecry:</b> Destroy all other minions and discard your hand. + + + + + Bernie Kang + + + Once a noble dragon known as Neltharion, Deathwing lost his mind and shattered Azeroth before finally being defeated. Daddy issues? + + + + + cad1a08c-b40a-4d97-913a-284adb9862ac + Commanding Shout + + + + + + Your minions can't be reduced below 1 Health this turn. Draw a card. + + + + Wayne Reynolds + "Shout! Shout! Let it all out!" - Advice to warriors-in-training + + + + Commanding Shout + + + + Can't be reduced below 1 Health this turn. + + + + + + + + Commanding Shout + + + + + Your minions can't be reduced below 1 Health this turn. + + + + + + + Master Swordsmith + + + + + + + At the end of your turn, give another random friendly minion +1 Attack. + + + + E.M. Gist + He's currently trying to craft a "flail-axe", but all the other swordsmiths say it can't be done. + + + + + + Equipped + + + Increased Attack. + + + + + + + Gruul + + + + + + + At the end of each turn, gain +1/+1 . + + + + + Kev Walker + He's Gruul "the Dragonkiller". He just wanted to cuddle them… he never meant to… + + + + + + Growth + + + Gruul is growing... + + + + + + Hogger + + + + + + + At the end of your turn, summon a 2/2 Gnoll with <b>Taunt</b>. + + + + + Laurel D. Austin + Hogger is super powerful. If you kill him, it's because he <i>let</i> you. + + + + + + + Gnoll + + + + + + <b>Taunt</b> + + + + + ab7c359b-abe3-4cfb-acb0-7788e21f9c9f + Stampeding Kodo + + + + + + + + <b>Battlecry:</b> Destroy a random enemy minion with 2 or less Attack. + + + + Daren Bader + This Kodo is so big that he can stampede by <i>himself</i>. + + + + + Druid of the Claw + + + + + + + + + <b>Charge, Taunt</b> + + + + + + + + + Damaged Golem + + + + + + + + + + + + Flesheating Ghoul + + + + + + + + + Whenever a minion dies, gain +1 Attack. + + + + Alex Horley Orlandelli + 'Flesheating' is an unfair name. It's just that there's not really much else for him to eat. + + + + + + d67eeb4e-6b91-4063-a8a4-6210c90ad445 + Cannibalize + + + Increased Attack. + + + + + + Spellbender + + + + + + + + <b>Secret:</b> When an enemy casts a spell on a minion, summon a 1/3 as the new target. + + + + While it's fun to intercept enemy lightning bolts, a spellbender much prefers to intercept opposing Marks of the Wild. It just feels meaner. And blood elves... well, they're a little mean. + Gonzalo Ordonez + + + + + + Spellbender + + + + + + + + + + Jason Chayes + + + + + + + + <b>Enrage:</b> Just kidding! He never Enrages. + + + Eric Dodds + + + + + + + + <b>Battlecry:</b> Summon a 2/2 Pirate and destroy all Ninjas. + + + Bob Fitch + + + + + + + + <b>Super Taunt</b> <i>(EVERY character must attack this minion.)</i> + + + Steven Gabriel + + + + + + + + <b>Battlecry:</b> Summon a frothy beverage. + + + Kyle Harrison + + + + + + + + <i>3 for a 5/4? That's a good deal!</i> + + + Derek Sakamoto + + + + + + + + <i>The notorious Footclapper.</i> + + + Zwick + + + + + + + + <b>Battlecry:</b> Complain about bacon prices. + + + Ben Brode + + + + + + + + Your volume can't be reduced below maximum. + + + Ben Thompson + + + + + + + + <b>Battlecry:</b> Draw some cards. With a pen. + + + Michael Schweitzer + + + + + + + + <b>C-C-C-COMBO:</b> Destroy a minion. + + + Jay Baxter + + + + + + + + <b>Battlecry:</b> Summon FIVE random Inventions. + + + Rachelle Davis + + + + <b>Battlecry:</b> Draw TWO cards. <i>She's not a novice engineer.</i> + + + + + + + Brian Schwab + + + + + + + + At the end of your turn, give a random minion +1 Attack. + + + Yong Woo + + + + + + + + Your other minions have +3 Attack and <b>Charge</b>. + + + Andy Brock + + + + + + + + Can't be <b>Silenced. Divine Shield, Stealth.</b> + + + Hamilton Chu + + + + + + + + <i>Was successfully NOT part of the problem! ...most of the time.</i> + + + Rob Pardo + + + + + + + + You can't start a game without this minion in your deck. + + + Becca Abel + + + + + + + + + + Whenever you draw a card, make it Golden. + + + Beomki Hong + + + + + + + + <b>Taunt.</b> Friendly minions can’t be <b>Frozen.</b> + + + + + Brian Birmingham + + + + + + + + <b>Choose One</b> - Restore a Mech to full Health; or Give a Designer <b>Windfury.</b> + + + + + Bryan Chang + + + + + + + + <b>Foodie:</b> Make all minions edible. + + + + + Cameron Chrisman + + + + + + + + While this is in your hand, Golden cards cost (1) less. + + + + + Christopher Yim + + + + + + + + <b>Battlecry:</b> Your emotes are now spoken in "Radio Voice." + + + + + Dean Ayala + + + + + + + + You can't lose stars while this is in your deck. + + + + + Elizabeth Cho + + + + + + + + <b>Battlecry:</b> Add Echo of Medivh and Echoing Ooze to your hand. + + + + + Eric Del Priore + + + + + + + + Has <b>Taunt</b> if it's 3 AM. + + + + + Henry Ho + + + + + + + + <b>Battlecry:</b> Spectate your opponent's hand. + + + + + He-Rim Woo + + + + + + + + <b>Choose One</b> - Punch an arm; Offer a treat; or Give a big hug. + + + + + Jason MacAllister + + + + + + + + <i>He's a real stand-up guy.</i> + + + JC Park + + + + + + + + <b>Battlecry:</b> Add a new platform for Hearthstone. + + + Jeremy Cranford + + + + + + + + When the game starts, this card climbs to the top of the deck. + + + Jerry Mascho + + + + + + + + At the start of your turn, deal 1 damage. If this card is golden, deal 1 damage at the end of your turn instead. THIS IS A HAN SOLO JOKE. + + + Jomaro Kindred + + + + + + + + <b>Battlecry:</b> TAKE any cards from your opponent's hand that they don't want. + + + + + Max Ma + + + + + + + Can only be played on a mobile device. + + + + Max McCall + + + + + + + + Your emotes have no cooldown and can't be squelched. + + + Mike Donais + + + + + + + + <b>Battlecry:</b> Replace all minions in the battlefield, in both hands, and in both decks with random minions. + + + Ricardo Robaina + + + + + + + + <b>Battlecry:</b> Summon three 1/1 Chinchillas. + + + Robin Fredericksen + + + + + + + + <b>Battlecry:</b> If you have no other Erics on the battlefield, rename this card to "Eric". + + + Ryan Chew + + + + + + + + <b>Chews One</b> - Sing karaoke; or Leave on time and tell everyone about it. + + + Ryan Masterson + + + + + + + <b>Battlecry:</b> Cast copies of Backstab, Cold Blood, and Eviscerate. <i>(targets chosen randomly).</i> + + + + + Seyil Yoon + + + + + + + + <b>Battlecry:</b> Add 3 Sprints and a Marathon to your hand. + + + Tim Erskine + + + + + + + + Whenever this minion destroys another minion, draw a card. + + + Jon Bankard + + + + + + + + 50% chance to be 100% right. + + + Walter Kong + + + + + + + + <b>Battlecry:</b> Deal 1 damage to each of 2 strategic targets. + + + Jonas Laster + + + + + + + + Whenever a <b>Silenced</b> minion dies, gain +1/+1. + + + Keith Landes + + + + + + + + At the start of your turn, get -2 Health due to hunger. + + + 797ef729-1cb4-42b4-8218-cf772985e7eb + Fireblast + + + + + + <b>Hero Power</b> +Deal $1 damage. + Deal 1 damage. + + + + + + + + 32670f20-c7e8-4ec6-a250-e5788c72978f + Fireblast Rank 2 + + + <b>Hero Power</b> +Deal $2 damage. + + + + + + + + + + efb42c61-5a08-4fea-8cff-bb8c6a2f7e79 + Fireblast + + + + + + <b>Hero Power</b> +Deal $1 damage. + Deal 1 damage. + + + + + + + + a7b61a45-1613-4a2d-aaef-88c1b168ca2c + Fireblast Rank 2 + + + <b>Hero Power</b> +Deal $2 damage. + + + + + + + + + + e4b86ac2-481e-4c6d-ba5c-95ec16afd869 + Reinforce + + + + + + <b>Hero Power</b> +Summon a 1/1 Silver Hand Recruit. + + + + + + + + 7dcea8fb-85e6-4c44-9596-c219783df72d + The Silver Hand + + + + + + <b>Hero Power</b> +Summon two 1/1 Recruits. + + + + + + + + f46eab3d-6a52-4385-b8b4-1e7d8b73d9fd + Armor Up! + + + + + + <b>Hero Power</b> +Gain 2 Armor. + + + + + + 098dd913-0267-439d-b0e0-57ed00172135 + Tank Up! + + + + + <b>Hero Power</b> +Gain 4 Armor. + + + + + + 9819c832-6cc1-41e0-bf86-2c38b44d9c60 + Steady Shot + + + + + + <b>Hero Power</b> +Deal $2 damage to the enemy hero. + + + + + + + + + c619d69f-46f0-48be-9256-5a9544ceea22 + Ballista Shot + + + + + <b>Hero Power</b> +Deal $3 damage to the enemy hero. + + + + + + + + + 0a338004-0e43-43b8-a3e0-c69ff9e268d9 + Magni Bronzebeard + + + + + + + + + + + + + a04713b6-67e8-40df-81e8-fc9c81644ee7 + Lady Liadrin + + + + + + + + + + + + + d21de576-161d-495c-bcf3-d28f18a6aefe + Alleria Windrunner + + + + + + + + + + + + + c79bc681-e960-455b-a38d-a5c0b35aad99 + Medivh + + + + + + + + + + + + + d44997ae-8b75-4505-bc1e-7f29285f15bc + Khadgar + + + + + + + + + + + + + 3da37802-65fa-4d65-a9a7-d387805f0bca + Pile On!!! + + + + <b>Hero Power</b> +Put a minion from each deck into the battlefield. + + + + + + 9bd3b6bd-4980-416c-95e5-2386d9d564d7 + Jeering Crowd + + + + Summon a 1/1 Spectator with <b>Taunt</b>. + + + + + + ec456be5-55c3-4f36-91f8-152a6cf79bed + Jeering Crowd + + + + <b>Hero Power</b> +Summon a 1/1 Spectator with <b>Taunt</b>. + + + + + + + + b1b03dae-54f3-45f3-9f37-2d44d6ffed84 + The Majordomo + + <b>Hero Power</b> +Summon a 3/3 Flamewaker Acolyte. + + + + + + + + + + 5220fe12-1900-4ddf-9165-4b609f5f8c0f + ME SMASH + + + + Destroy a random enemy minion. + + + + + + + 47fe5d69-4b3b-49c6-975e-7ac392f5ccbf + ME SMASH + + + + <b>Hero Power</b> +Destroy a random enemy minion. + + + + + + + + + 51629df3-8397-47ee-8d42-ae410978a204 + Open the Gates + + + + + + <b>Hero Power</b> +Summon three 1/1 Whelps. + + + + + + eb7a98e2-64ea-4db8-911e-5ae0195d3b4b + Wild Magic + + + <b>Hero Power</b> +Put a random spell from your opponent's class into your hand. + + + + + + + 4c081137-7988-40c9-9ba1-ab52781d409e + Activate! + + + + + + <b>Hero Power</b> +Activate a random Tron. + + + + + + + + + + f255681b-fd05-4967-92c1-b87114ee2473 + Bone Minions + + + + <b>Hero Power</b> +Summon two 2/1 Bone Constructs. + + + + + + + + ae415978-b1c0-40d7-9ba2-e59ce2b64734 + Living Bomb + + + + Choose an enemy minion. If it lives until your next turn, deal 5 damage to all enemies. + + + + + + + + + + Living Bomb + + + On Ragnaros' turn, deal 5 damage to this side of the board. + + + + + + + + 4848cccb-3cbe-42c2-ab58-e723194c2037 + Open the Gates + + + + Fill your board with 2/2 Whelps. + + + + + + a1e36990-a1f3-4d3d-8eee-346155b14942 + Dragonkin Spellcaster + + + + + + <b>Battlecry:</b> Summon two 2/2 Whelps. + + + + + + + + 6fee445d-2c2c-4a94-82bc-287c14771d8e + Lucifron + + + + + + <b>Battlecry:</b> Cast Corruption on all other minions. + + + + + + + + + Atramedes + + + Whenever your opponent plays a card, gain +2 Attack. + + + + + + + + + + + + + + I Hear You... + + + Increased Attack. + + + + + + Moira Bronzebeard + + + + + + <b>Deathrattle:</b> Summon Emperor Thaurissan. + + + + + + + + + + Drakonid Slayer + + + + Also damages the minions next to whomever he attacks. + + + + + + + + + + Whirling Ash + + + + + + <b>Windfury</b> + + + + + + + Living Lava + + <b>Taunt</b> + + + + + + + + + + + 8c605ab6-9f92-4922-9ff3-01d5f99151d6 + Son of the Flame + + + + + + <b>Battlecry:</b> Deal 6 damage. + + + Deal 6 damage. + + + + + + + d12745e2-dd84-498a-bd55-dad49384715f + Coren Direbrew + + + + + + Always wins Brawls. + <b>Battlecry:</b> Add a Brawl to your hand. + + + + + + + + + 8c8d731f-74b8-4a31-b57a-374725e59b0c + Omnotron Defense System + + + + Summon a random Tron. + + + + + + + + + + Sulfuras + + + <b>Deathrattle:</b> Your Hero Power becomes 'Deal 8 damage to a random enemy'. + + + + + + + + + + + Golemagg + + + + + + Costs (1) less for each damage your hero has taken. + + + + + + + + 1ca15e2e-3d4f-4bab-847b-37fec1e71d8d + Core Hound Puppies + + + + Summon two 2/4 Core Hound Pups. + + + + + + Core Hound Pup + + + + + + + + At the end of each turn, summon all Core Hound Pups that died this turn. + + + + + + + High Justice Grimstone + + + + + + At the start of your turn, summon a <b>Legendary</b> minion. + + + + + + + + + + Vaelastrasz + + + Your cards cost (3) less. + + + + + + + + + + + + Burning Adrenaline + + + Costs (2) less. + + + + + + Razorgore + + + + + + At the start of your turn, give your minions +3 Attack. + + + + + + + + + + + Dragonlust + + + +3 Attack. + + + + + + Garr + + + + + + Whenever this minion takes damage, summon a 2/3 Elemental with <b>Taunt</b>. + + + + + + + + + + + Rock Elemental + + + + <b>Taunt</b> + + + + + + + + + Gearmaster Mechazod + + + + + + + + + <b>Boss</b> +At the beginning of each turn, Mechazod strikes! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overclock + + + + Increased Attack. + + + + + + 9c117406-a0eb-4e95-81e5-0e42d3542867 + Poison Cloud + + + + <b>Hero Power</b> +Deal 1 damage to all enemy minions. If any die, summon a slime. + + + + + + b608f270-2eb2-4027-a8af-2e9e15afb925 + Decimate + + + + Change the Health of enemy minions to 1. + + + + + + 1bf48f10-8814-4963-afc5-9f4d8e1f3ce5 + Decimate + + + + <b>Hero Power</b> +Change the Health of enemy minions to 1. + + + + + + + + 309fed23-c09b-4d36-a78d-2d15fa17eeb6 + Web Wrap + + + + + + <b>Hero Power</b> +Return a random enemy minion to your opponent's hand. + + + + + + f30a3845-8b6e-426e-affb-b97ef07a17e7 + Harvest + + + + <b>Hero Power</b> +Draw a card. Gain a Mana Crystal. + + + + + + 57deff62-cb38-4ec1-83de-d472c4fe6870 + Ragnaros the Firelord + + + + + + + + + + + + ff9906e0-8e06-407d-af06-d93818757d93 + Nefarian + + + + + + + + + + + + 06fdbda8-5844-4b20-8132-b0b5d1f79e2e + Wild Magic + + + + <b>Hero Power</b> +Add a random spell from any class to your hand. It costs (0). + + + + + + 53ea653b-5b2b-463b-9244-de95e6540fdf + Molten Rage + + + + <b>Hero Power</b> +Summon a 5/1 Magma Rager. + + + + + + OLDN3wb Tank + + + + + + <b>Taunt</b> + + + + + + + OLDN3wb Mage + + + + + + + At the end of your turn, deal 1 damage to random enemy minion. + + + + + + + OLDN3wb Healer + + + + + + At the end of your turn, heal 2 damage from adjacent minions. + + + + + + + + OLDLegit Healer + + + + + + At the end of your turn, summon a random friendly minion that died this turn. + + + + + + + OLDPvP Rogue + + + + + + <b>Stealth</b> +Regain <b>Stealth</b> when PvP Rogue kills a minion. + + + + + + + + + OLDTBST Push Common Card + + + + + + push a common card into player's hand + + + + + + + + TBUD Summon Early Minion + + + Each turn, if you have less health then a your opponent, summon a free minion + + + + + + + + + Boss HP Swapper + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8784765a-45c6-4269-91ee-844a8a37dc54 + Big Banana + + + + Give a minion +2/+2. + + + + + + + + + + Big Banana + + + Has +2/+2. + + + + + + ccd5c096-03f4-4053-a478-2aaaa68e8c9d + Deviate Banana + + + + Swap a minion's Attack and Health. + + + + + + + + + + Deviate Switch + + + + + Attack and Health have been swapped by Deviate Banana. + + + + 616ea39e-9e7f-404c-b768-943b97d7edd2 + Rotten Banana + + + + Deal $1 damage. + + + + + + + + + + Create 15 Secrets + + + + + + + + + + + + + + + + + + + + + + + + + + Deckbuilding Enchant + + + + + + + + + + + + + ee15b539-5319-4e3e-949c-7ff6fb79c0f7 + Choose One of Three + + + + + + + + 98f8bc05-29b1-4910-ad99-1d5ffaadebcc + Tarnished Coin + + + + Gain 1 Mana Crystal this turn only. + + + + + + 5cd386ce-2e72-4913-b4ea-559fe679cc98 + Choose a New Card! + + + + Look at 3 random cards. Choose one and shuffle it into your deck. + + + + + + Player Choice Enchant + + + + + + + + + Player Choice Enchant On Curve + + + + + + + + + Player Choice Enchant On Curve2 + + + + + + + + + b2ed0fa1-93e6-4e7f-be12-eecc4a37a048 + Choose a New Card! + + + + Look at 3 random cards. Choose one and put it into your hand. + + + + + + Pirate + + + + + + + + + + + Give Taunt and Charge + + + This minion is granted <b>Taunt</b> and <b>Charge</b>. + + + + Blingtron's Blade + + When this breaks, randomly summon a new weapon. + + + + + Blingtron's Blade HERO + + + + + + + + Valeera Sanguinar + + + + + + + + + + + + Sharpened + + +1 Attack + + + + + + + + 93487cad-4419-4819-bbf5-beceba4b41ad + Sharpen + + + + + + <b>Hero Power</b> +Increase your weapon's attack by 1 + + + + Foam Sword + + + + + + + + + c78c6dfb-b925-430a-bf8c-400b98b668ac + Second Class: Druid + + + Add Druid cards to your deck. + + + + + 046b3ee8-0e9b-48fb-88cf-5436b1f83f69 + Second Class: Hunter + + + Add Hunter cards to your deck. + + + + + 57ab43e2-7aa1-4604-ac79-ea5d880bd2b6 + Second Class: Mage + + + Add Mage cards to your deck. + + + + + adeaa7d6-4694-4460-b445-5f01facedd36 + Second Class: Paladin + + + Add Paladin cards to your deck. + + + + + Pick your second class + + + Not player facing. No need to localize. + + + + + + + + + + + + + + + + + fa1a0602-8688-4d42-974b-f0cf29ee12fa + Second Class: Priest + + + Add Priest cards to your deck. + + + + + f16e0ccd-4233-4265-b31e-04ed28cf586f + Second Class: Rogue + + + Add Rogue cards to your deck. + + + + + f5ad81ef-37e9-4f7a-adac-852c3dadc82a + Second Class: Shaman + + + Add Shaman cards to your deck. + + + + + 3356cdbb-aae6-4aae-9da7-143e2f0b95d4 + Second Class: Warlock + + + Add Warlock cards to your deck. + + + + + 15156d24-dac8-4a5c-b8cc-4e1e32e42469 + Second Class: Warrior + + + Add Warrior cards to your deck. + + + + + Prioritize + + + + + Deal Attack damage to biggest minion. + + + Bomb Salvo + + + + + Deal Attack damage to up to 3 random targets. + + + Release Coolant + + + + + Freeze and deal Attack damage to all minions. +Gain 2 Attack. + + + Overclock + + + + + Gain 2 Attack. + + + Double Zap + + + + + Deal Attack damage to both players. + + + Kill the Lorewalker + + + + + Destroy Lorewalker Cho. + + + Gearmaster Mechazod + + + + + + + + + + <b>Boss</b> +Mechazod wins if he defeats either of you! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overloaded Mechazod + + + + + + + <b>Boss</b> +At the beginning of each turn, Mechazod strikes! + + + + + TB_DecreasingCardCost + + + + + + + + + + + + + + + 876c092f-35ee-4dee-89e4-491a3d1c7675 + TBDecreasingCardCostDebug + + + + + + + + Endless Enchantment + + + +2/+2. + + + + + + Safe + + + + This minion is safe from attacks and cannot have taunt. + + + + a202e73c-b77f-443c-81ca-681afac755b0 + Annoy-o-Tron Fanclub + + + + Summon 3 Annoy-o-Trons + + + + d04210a4-873c-411e-bf48-d282f1e71cdc + TBFactionWarBoomBot + + + + + + + + + + + + + + + + TBFactionWarBoomBotSpell + + + + + + + + cd230ff6-acd4-43da-b823-522c750035e8 + DIE, INSECT! + + + + <b>Hero Power</b> +Deal $8 damage to random enemy. + + + + 856539fb-9620-48ab-827a-7ae6e4b3f49f + The Majordomo + + + + <b>Hero Power</b> +Summon a 1/3 Flamewaker Acolyte. + + + + 7c8d282c-4eb5-4cf2-8b98-10192e04cc3b + Swat Fly + + <b>Hero Power</b> +Deal $3 damage to random enemy, for now... + + + + + + Herold + + + + + + + <b>Deathrattle</b>: Deal 1-4 damage to a random enemy. + + + + + + 41b91847-4a63-401a-a9c7-ad84f1411fe1 + Annoy-o-Tron Prime + + + + + + + + f0ec385f-6257-4630-8eaf-b6f200bd7ca0 + Nefarian + + + + + + + + + + 7f5b0603-2808-4a7a-b05d-82e4d08324b9 + DIE, INSECT! + + + Your hero power becomes "Deal $8 damage to random enemy." + + + + + Cheap Gift + + This card's cost is reduced. + + + + + + + + + 210015a5-e8ac-4f88-a9a5-3caf483c859b + Hardpacked Snowballs + + + Return 3 random enemy minions to your opponent's hand. + + + + Winter's Veil Gift + + + + + + <b>Deathrattle</b>: Give current player a Stolen Gift. + + + + + + + + + + 0784da70-d75a-4435-a282-725de625988f + Stolen Winter's Veil Gift + + + + + + <b>Discover</b> a random Treasure. Its cost is reduced. + + + + Shadow Tower Give My minions Stealth + + + Can't Attack. +<b>Stealth</b>. + + + + + Shadow Tower Stealth + + + <b>Stealth</b>. + + + + + + + + TB_ClockworkCardDealer + + + + + + + + + Massive Runeblade + + + + + Deals double damage to heroes. + + + + + + + Anub'Rekhan + + + + + At the end of your turn, summon a 3/1 Nerubian. + + + + + + + + Noth the Plaguebringer + + + + + Whenever an enemy minion dies, summon a 1/1 Skeleton and give your other minions +1/+1. + + + + + + + + 13e77c3c-b644-4007-a116-03fe77f5b13b + Darkness Calls + + + + Summon two random Naxxramas bosses and trigger their <b>Battlecries</b>. + + + + + + + + + + + + + + + + + + Uncover Staff Piece + Add another piece to your Hero Power. + + + + + Dark Power + + + Granted power from Noth + + + + + + Sapphiron + + + + + At the beginning of your turn, <b>Freeze</b> a random enemy minion. + + + + + + + + + Patchwerk + + + + + <b>Battlecry:</b> Destroy a random enemy minion. + + + + + + + Lady Blaumeux + + + + + <b>Battlecry:</b> Summon a fellow Horseman. + + + + + + + Sir Zeliek + + + Lady Blaumeux is <b>Immune</b>. + + + + + + + + + Gluth + + At the end of your turn, summon a random Undead. + + + + + + + + + + + + + + + + + + + + Gothik the Harvester + + <b>Deathrattle:</b> Summon a Spectral Gothik for your opponent. + + + + + + + + + + + Spectral Gothik + + + At the start of your turn, deal 4 damage to your hero. + + + + + + + + + + Grand Widow Faerlina + + + + + Has +1 Attack for each card in your opponent's hand. + + + + + + Grobbulus + + Whenever this kills a minion, summon a poisonous 2/2 Slime. + + + + + + + + + + + Fallout Slime + + + + + + + + Destroy any minion damaged by this minion. + + + + + Heigan the Unclean + + At the end of your turn, deal 4 damage to a random enemy. + + + + + + + + + + + 30e4ea94-3c0c-4d93-bcf7-d447afe68bcc + Instructor Razuvious + + + <b>Battlecry:</b> Equip a 5/2 Massive Runeblade. + + + + + + + + + Necromancy + + + + Resurrect a random friendly minion that died this game. + + + + + + + 87ce8ad5-4b40-41f3-a123-76585208fa87 + + + + Add a random minion that costs (5) or less to your hand + Staff, First Piece + + + + 79f1f5e7-3966-4a9a-b787-3f08f92485fa + + + + Add a random minion to your hand. It costs (2) less. + Staff, Two Pieces + + + + + + + Add a random legendary minion to your hand. It costs (4) less. + Staff of Origination + + + + 33de4b47-f4ec-4726-aeac-3b017d5d7ef1 + Kel'Thuzad + + + + + + + + + + + + d0d78816-f589-4a52-8ff3-d9409ece55e3 + Rafaam + + + + + + + + + + + + + + Level Up! + Level up all the spells in your hand and deck. + + + + + + 2edb8e2c-ab0a-4e80-a46a-0d235e645ea7 + Annoy-o-Tron + + + + + + + + + + + 60f02399-5c3b-4d2f-a3c6-1f9e7f9dfe24 + Hello! Hello! Hello! + + + + + + <b>Hero Power</b> +Give your lowest attack minion <b>Divine Shield</b> and <b>Taunt</b>. + + + + + + + 45ac9a12-efc6-4d39-a7cc-732554d87252 + Boom Bot + + + + + + + + + + + 8532c8e3-3287-428d-914c-d760608acd1d + Boom Bot Jr. + + + + + + <b>Hero Power</b> +Deal 2 damage randomly split among all enemies. + + + + 6a3e23e8-4a94-4f17-b0d6-c335a07f49d9 + TBMechWarCommonCards + + + + + + + + + + + + + + Mech Fan + + + + + + <b>Taunt</b> + + + + + + + Miniature + + + Mini-sized, set to 1/1 + + + + + Pick Your Fate Build Around + + + + + Not player facing. No need to localize. + + + + + + + + + + + + + + Fate 7 Ench Get a Coin + + + Not player facing. No need to localize. + + + + Pick Your Fate Random + + + Not player facing. No need to localize. + + + + + + + + + + + + + + 0b0867fe-9fd3-4c7a-a6bb-235323595638 + Dire Fate: Taunt and Charge + + + + + All minions have <b>Taunt</b> and <b>Charge</b>. + + + + 2fc820bf-0265-4c49-9b05-58ba39541c4f + Battlecry Bonus + + + Your <b>Battlecry</b> minions have +1/+1. + + + + Fate + + + + + + Bonus + + + Your <b>Battlecry</b> minions have +1/+1. + + + + 1f26fe1f-f412-4857-aa92-bb5c2fbb4d95 + Murloc Bonus + + + Summon a 1/1 Murloc at the end of your turn. + + + + 21239f0d-c953-4413-a76d-02a0929e19c9 + Dire Fate: Murlocs + + + Turn each minion in play into a 1/1 Murloc. + + + + Fate 11 Ench. Murloc + + + Not player facing. No need to localize. + + + + + 0b51e69a-6d0a-4e0d-8c6f-04ce10b797f3 + Fate: Confusion + + + At the end of each turn, swap all minions' Attack and Health. + + + + Fate 12 Ench, Confuse + + + Not player facing. No need to localize. + + + + + + + Pick Your Fate 1 Ench + + + Not player facing. No need to localize. + + + + + + 2dde5cb1-bf61-4fb4-87c6-abc825b7f53a + Fate: Bananas + + + + + When a minion dies, its owner gets a (1) mana Banana. + + + + Pick Your Fate Randon 2nd + + + Not player facing. No need to localize. + + + + + + + + + + + + + + + + Pick Your Fate 2 Ench + + + Not player facing. No need to localize. + + + + Fate + + + <b>Deathrattle</b>: Your owner gets a banana. + + + + + + dfd6b41d-132c-44b5-839e-1289a5edd7d4 + Dire Fate: Windfury + + + + + All minions have <b>Windfury</b>. + + + + Pick Your Fate 3 Ench + + + Not player facing. No need to localize. + + + + + 969b8060-b021-4ec0-a0da-56106a9e01dd + Dire Fate: Card + + + When a minion dies, its owner draws a card. + + + + Pick Your Fate 4 Ench + + + Not player facing. No need to localize. + + + + Fate + + + <b>Deathrattle</b>: Draw a card. + + + + + + 8b7538b6-4d8a-447d-9bec-31a3c76ef987 + Fate: Spells + + + Spells cost (1) less. + + + + Pick Your Fate 5 Ench + + + Not player facing. No need to localize. + + + + f6294a41-1850-44be-a186-05a1c6c877a4 + Fate: Portals + + + Shuffle 10 Unstable Portals into each player's deck. + + + + bbfdc24d-bb87-4c99-9db3-e7519edbaee1 + Dire Fate: Unstable Portals + + + Place 3 Unstable Portals in each player's hand. + + + + c304eea4-6e34-4262-a7e2-95dc006dac84 + Fate: Coin + + + When a minion dies, its owner gets a Coin. + + + + 8d796240-ab32-47d6-8ea3-ece9cfff6cd4 + Dire Fate: Manaburst + + + Minions gain <b>Deathrattle</b>: Random card in owner's hand costs (0). + + + + Fate + + + <b>Deathrattle</b>: random card in owner's hand costs (0). + + + + + Fate + + + <b>Deathrattle</b>: Your owner gets a coin. + + + + + Fate 7 Ench 2nd + + + Not player facing. No need to localize. + + + + 57ca1835-53df-42ba-9644-0c8caf5f0fa7 + Spell Bonus + + + Whenever you cast a spell, gain 3 Armor. + + + + dc899653-6229-40d7-9d67-b27e6c5e34fc + Fate: Armor + + + Each player gains 2 Armor on the start of their turn. + + + + Fate 8 Get Armor + + + Not player facing. No need to localize. + + + + + Fate 8 Rand 2 armor each turn + + + Not player facing. No need to localize. + + + + + abfd0967-e9a0-432b-abe6-331696315dae + Deathrattle Bonus + + + Your <b>Deathrattle</b> minions have +1/+1. + + + + Fate 9 Ench. Deathrattle bonus + + + Not player facing. No need to localize. + + + + Bonus + + + Your <b>Deathrattle</b> minions have +1/+1. + + + + Fate + + + Attack and Health swap at end of each turn. + + + + + + Fate + + + This minion has <b>Windfury</b> + + + + + + + + Who could it be?! + Mystery Pilot + + + TBRandomCardCost + + + + + + + + + + + + TB_EnchWhosTheBossNow + + + + + + + + + + + + + + + + + + + + + + + TB_EnchRandomManaCost + + + + + + + + + + + The Sentinel + + + + + + + + + + + b436ab1b-3632-4199-91b9-62d555814677 + Barracks + + + + <b>Hero Power</b> +Play a random Stormwind Soldier. + + + + + + + + + Armory + + + + + + Attack increases over time. + + + + + + Trial Clear Board + + + + + + Trial Damage Dealt + + + + + Damage dealt to Stormwind. + + + + + Trial Hero Power Used + + + + + + + Trial Length + + + + + + + + + Shieldsman + + + + + <b>Taunt</b> +<b>Battlecry</b>: Add Stormwind's Attack to this minion's Health. + + + + + + + + Will of Stormwind + + + Stormwind is granting this card Health. + + + + + + + + Standard + + + + + Can't attack. +Adjacent units have +2 Attack. + + + + + + + + + Emboldened + + + Standard Bearer is granting +2 Attack to this minion. + + + + + + Swordsman + + + + + + <b>Battlecry</b>: Add Stormwind's Attack to this minion's Attack and Health. + + + + + Strength of Stormwind + + + Stormwind is granting this card Attack and Health. + + + + + + + + Trial Minions Killed + + + + + Number of minions killed. + + + + + Trial Minions Killed Tracker + + + + + Length of game in turns. + + + + + 47647009-02c7-4c31-bac1-64374f6b9d27 + Offensive Play + + + + + + The next Legendary minion you play and all your other copies cost (3) less. + + + + Facilitated + + + + The next legend you cast this turn costs (3) less. + + + + + + + + + + Draw Offensive Play + + + + + + Draw Offensive Play on first turn + + + + + Yogg Servant Hero Enchant + + + + + + + + bbd07e8e-2ae2-4d69-bb9f-55e731612957 + Cash In + + Destroy your weapon, gaining a random one. + + + + + + + + d8562a35-cea9-4596-a444-6acfa92119ea + Sun Raider Phaerix + + + + + + + + + + + + + + + + 4d5de7df-924a-4598-9f26-1a4957945052 + Heroic Phaerix + + + + + + + + + + + + + + + + Blessings of the Sun + + + <b>Passive Hero Power</b> +Whoever controls the Rod of the Sun is <b>Immune.</b> + + + + + + + Blessings of the Sun + + + <b>Passive Hero Power</b> + Phaerix is <b>Immune</b> while he controls the Rod of the Sun. + + + + + + + Rod of the Sun + + + + + + <b>Deathrattle:</b> Surrender this to your opponent. + + + + + + + + Rod of the Sun + + + + + + <b>Deathrattle:</b> Surrender this to your opponent. + + + + + + + + + + Heroic Mode + + + + + +3/+3 if Phaerix controls the Rod. + + + + Tol'vir Hoplite + + + + + + <b>Deathrattle:</b> Deal 5 damage to both heroes. + + + + + + + + Tol'vir Hoplite + + + + + + <b>Deathrattle:</b> Deal 5 damage to both heroes. + + + + + + + + 2361e9ca-39bb-4b9c-802c-6d0184acddc0 + Zinaar + + + + + + + + + + 9e01d341-3021-4019-a834-a66fba0ea0a4 + Heroic Zinaar + + + + + + + + + + + + 7d5d8ec2-1d64-43ed-ac24-ff9c7886aa38 + Djinn’s Intuition + + + + Draw a card. +Give your opponent a Wish. + + + + + + + 22f09099-004a-4a8f-a58d-d24d3b703ccc + Djinn’s Intuition + + + + Draw a card. Gain a Mana Crystal. Give your opponent a Wish. + + + + + + + 1a16ac0d-3329-4314-a905-03b6a8dafb97 + Wish for Power + + + + <b>Discover</b> a spell. + + + + + + + 2c21a575-81b7-4f4c-9a3c-497ae42c0973 + Wish for Valor + + + + <b>Discover</b> a (4)-Cost card. + + + + + + + 823d7c9d-0ae6-46c4-b635-2c720fac1043 + Wish for Glory + + + + <b>Discover</b> a minion. + + + + + + + f1e2c96d-1524-46d3-93db-03bd62ed9f11 + Wish for More Wishes + + + + Gain 2 Wishes. + + + + + + 380b08f8-2096-4d45-9cd8-a0c6f7976c5f + Wish for Companionship + + + + <b>Discover</b> a Companion. + + + + + + + becbedd9-a45c-4e20-bcb8-097afe758680 + Leokk + + + + + Your minions have +1 Attack. + + + + + + + + + + 43233d47-6fc2-4d15-9950-39a68dc01e88 + Misha + + + + + <b>Taunt</b> + + + + + + + + + + 993b3fec-e21a-4557-bb84-7787515c1cd0 + The Scourge + + + + + + + + + + + + + + + + + Temple Escape Enchant + + + + + + + + + + + + + + + Temple Escape Enchant + + + + + + + + + + + + + + + db5cde4a-fafa-4d4f-9812-ee6a9b9c125d + Heroic Escape + + + + + + + + + + + + + + + + + 1d60b8d6-7464-4c64-bc83-fce5df797d28 + Escape! + + + + + Encounter new obstacles! + + + + + + + 22b992c7-2127-4b21-b620-81ff142b0dde + Escape! + + + + Encounter new obstacles! + + + + + + Pit of Spikes + + + + <b>Choose Your Path!</b> + + + + + a1ca364f-217f-4a15-9984-227d0fdc4e50 + Swing Across + + + Take 10 damage or no damage, at random. + + + + + + + 5b0b667e-c165-4bf2-8578-4b8f2196e048 + Walk Across Gingerly + + + Take 5 damage. + + + + + + Orsis Guard + + + + + + <b>Divine Shield</b> + + + + + + + Orsis Guard + + + + + + <b>Divine Shield</b> + + + + + + + Giant Insect + + + + + + + + Giant Insect + + + + + + + + + + Anubisath Temple Guard + + + + + + + + + + Anubisath Temple Guard + + + + + + + + + + Seething Statue + + + + + + At the end of your turn, deal 2 damage to all enemies. + + + + + + + + Seething Statue + + + + + + At the end of your turn, deal 5 damage to all enemies. + + + + + + + + Animated Statue + + + + + + + + You've disturbed the ancient statue... + + + A Glowing Pool + + <b>Drink?</b> + + + + + + + 03c29063-616a-4a57-b0e5-2b7e34542bb9 + Drink Deeply + + + Draw a card. + + + + + + + b300c67c-88c4-498f-9a4f-9d988c0b1e94 + Wade Through + + + Gain a Mana Crystal + + + + + + + The Eye + + + <b>Choose Your Path!</b> + + + + + + 7d86eb28-538c-426f-ab0a-b92a14dcee4d + Touch It + + + Restore 10 Health to your hero. + + + + + + f5706a1c-67aa-42c4-a2ae-409d2ab3d080 + Investigate the Runes + + + Draw 2 cards. + + + + + + The Darkness + + + + <b>Take the Shortcut?</b> + + + + + 02f00b05-6ab4-444a-b95b-cb16ca034acb + Take the Shortcut + + + Get 1 turn closer to the Exit! Encounter a 7/7 War Golem. + + + + + + No Way! + + + Do nothing. + + + 4b2826d5-5076-401f-b17d-1fd0c26c1f80 + Chieftain Scarvash + + + + + + + + + + d2c98022-1eab-488f-aa22-0f47e6aa99d9 + Heroic Scarvash + + + + + + + + + + + + Trogg Hate Minions! + + + <b>Passive Hero Power</b> + Enemy minions cost (2) more. Swap at the start of your turn. + + + + + + + + + Trogg Hate Minions! + + + <b>Passive Hero Power</b> + Enemy minions cost (2) more. Swap at the start of your turn. + + + + + + Trogg Hate Minions! + + + <b>Passive Hero Power</b> + Enemy minions cost (11). Swap at the start of your turn. + + + + + + + Trogg Hate Minions! + + + <b>Passive Hero Power</b> + Enemy minions cost (11). Swap at the start of your turn. + + + + + + Trogg Hate Spells! + + + <b>Passive Hero Power</b> + Enemy spells cost (2) more. Swap at the start of your turn. + + + + + + + + + Trogg Hate Spells! + + + <b>Passive Hero Power</b> + Enemy spells cost (11). Swap at the start of your turn. + + + + + + + + + 079fa39d-150a-4561-87a9-b33aaeab1a6a + Stonesculpting + + + + <b>Hero Power</b> + Summon a 0/2 Statue for both players. + + + + + + + 4b897996-ba28-4ae4-b30a-6406c8d99c1a + Stonesculpting + + + + <b>Hero Power</b> + Summon a Statue for both players. + + + + + + + Earthen Statue + + + + + + + + + + Earthen Statue + + + + + + + + + + 0966eb05-70fc-4bbd-b2a6-32cbe7b268be + Animate Earthen + + + + Give your minions +1/+1 and <b>Taunt</b>. + + + + + + + + Animated + + + +1/+1 and <b>Taunt</b>. + + + + + + Animated + + + +3/+3 and <b>Taunt</b>. + + + + + + 69c1a75d-4d16-4fc3-92d2-746d8be6fe35 + Animate Earthen + + + + Give your minions +3/+3 and <b>Taunt</b>. + + + + + + e93ab7d8-2e88-42fb-a4da-d181ec40479e + Shattering Spree + + + + Destroy all Statues. For each destroyed, deal $1 damage. + + + + + + + + 9ffb6890-0a7c-41d2-8a4a-7f5065a14fa2 + Shattering Spree + + + + Destroy all Statues. For each destroyed, deal $3 damage. + + + + + + + + 58433186-daf6-4b67-bb5e-8370c730afc8 + Mine Cart + + + + + + + + + + + Mine Shaft + + + + + + + + + + + + + + + + + Heroic Mine Shaft + + + + + + + + + + + + + + + 915a7516-afbc-4bd9-817d-b0f8b67e9ca1 + Flee the Mine! + + + + Escape the Troggs! + + + + + + + c0261cd2-2879-4d7d-b519-b57782a1ba4d + Flee the Mine! + + + Escape the Troggs! + + + + + + Chasing Trogg + + + + + + + + Debris + + + + + + + + <b>Taunt.</b> + + + + + Earthen Pursuer + + + + + + + + Lumbering Golem + + + + + + + + + + 82335bcd-83f6-418a-b77f-4734df623aff + Dynamite + + + Deal $10 damage. + + + + + + + + + 98fa2aee-04dd-40cd-969a-62280d7d6bca + Boom! + + + + Deal 3 damage to all enemy minions. + + + + + + 32bcb725-53cb-4bd1-8293-8832d5b16ad7 + Barrel Forward + + + + Get 1 turn closer to the Exit! + + + + + + Spiked Decoy + + + + <b>Taunt</b> +Can't attack. + + + + + + + + + + + Mechanical Parrot + + + + + + + + + 2abc201b-3b12-4755-a8cc-7da1b51da39e + Consult Brann + + + + Draw 3 cards. + + + + + + 256624d5-b003-4ad0-8be3-64698c03a810 + Repairs + + + + Restore 10 Health. + + + + + + + + 6be8be7b-4d2f-4f37-a604-e923b115c80a + Throw Rocks + + + + <b>Hero Power</b> + Deal 3 damage to a random enemy minion. + + + + + + 295ccb02-8a18-4654-9b9f-20bae04a70e0 + Archaedas + + + + + + + + + + + + + + f619043c-9063-42e0-9217-c6ee25ca1530 + Heroic Archaedas + + + + + + + + + + + + + + + + 41c7988a-4ea7-4779-87f4-3f8e5f136e74 + Lord Slitherspear + + + + + + + + + + + + Hungry Naga + + + + + + + + Hungry Naga + + + + + + + + Hungry Naga + + + + + + + + Hungry Naga + + + + + + + + 77f8b2a1-38ef-48e0-9dcb-c82aa48a94d8 + Heroic Slitherspear + + + + + + + + + + + + + + 536f70ab-7864-4202-9040-01fe0d39d21c + Enraged! + + + + + + Give your hero +2 attack this turn. + + + + + Enraged + + + +2 Attack + + + + + + + + Enraged + + + +5 Attack + + + + + + 73ab609f-3271-499f-83a1-a5ba49e5d69f + Enraged! + + + + Give your hero +5 attack this turn. + + + + + + 1f76b7f9-cdfc-4026-aa49-ca1146ec65a4 + Getting Hungry + + + + + + <b>Hero Power</b> +Summon a Hungry Naga. + + + + + Famished + + + Quite Hungry. + + + + + + Famished + + Quite Hungry. + + + + + 515b9c38-a861-46e4-8c97-192cb79a6c36 + Getting Hungry + + + + <b>Hero Power</b> +Summon a 1/1 Hungry Naga. + + + + + + + 5be3d853-2952-4867-b43d-b235805da621 + Getting Hungry + + + + <b>Hero Power</b> +Summon a 2/1 Hungry Naga. + + + + + + + d15378af-a63d-4029-bc5c-cc393805e254 + Getting Hungry + + + + <b>Hero Power</b> +Summon a 5/1 Hungry Naga. + + + + + + + 4f8f46a0-c1c6-476e-83d4-5491a92e4b52 + Endless Hunger + + + + <b>Hero Power</b> +Summon a Hungry Naga. + + + + + + + Rare Spear + + + + + + + + Whenever your opponent plays a Rare card, gain +1/+1. + + + + + Rare Spear + + + + + + Whenever your opponent plays a Rare card, gain +1/+1. + + + + + Hungry Naga + + + + + + + + + + Hungry Naga + + + + + + + + + + b5a6765d-e12d-4dce-9035-b8c2854bec27 + Slithering Archer + + + + + + + + <b>Battlecry:</b> Deal 1 damage. + + + + + + + + da82d95b-d098-49c8-a6f9-1e35d09e0733 + Slithering Archer + + + + + + <b>Battlecry:</b> Deal 2 damage to all enemy minions. + + + + + Cauldron + + + + + + + + <b>Taunt</b> +<b>Deathrattle:</b> Save Sir Finley and stop the Naga onslaught! + + + + + + + + Cauldron + + + + + + + Cauldron + + + + + + <b>Taunt</b> +<b>Deathrattle:</b> Save Sir Finley! + + + + + + + + + + Slithering Guard + + + + + + + + <b>Taunt</b> + + + + + Slithering Guard + + + + + + <b>Taunt</b> + + + + + 7e306f56-0a31-4fb9-93d3-37eb0df2d131 + Naga Repellent + + + + Destroy all Hungry Naga. + + + + + + Naga Repellent + + + + Change the Attack of all Hungry Naga to 1. + + + 325b94ab-5d90-411d-a1db-003cb12a3603 + Giantfin + + + + + + + + + + + + + + + + + + ea84f40e-789f-4725-8be9-a6c5b7b45ffd + Heroic Giantfin + + + + + + + + + + + + + + + + + + Mrglmrgl MRGL! + + + + + + <b>Hero Power</b> +Draw cards until you have as many in hand as your opponent. + + + + + 8055a996-253b-4ea2-bf76-b43fc502c7c3 + Mrglmrgl MRGL! + + + + <b>Hero Power</b> +Draw 2 cards. + + + + + + + Murloc Tinyfin + + + + + + + + + + + High mortality rate, from often being hugged to death. + Oliver Chipping + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + daf61443-8d5f-43ec-9d11-1a4ed6a8eb5b + Mrgl Mrgl Nyah Nyah + + + + + Summon 3 Murlocs that died this game. + + + + + + 4bafb0f5-f374-4a18-bd07-657de526d3d3 + Mrgl Mrgl Nyah Nyah + + + + + + + Summon 5 Murlocs that died this game. + + + + 176ce212-4d66-4d68-91fb-1db55eeacc69 + Lady Naz'jar + + + + + + + + + + beb171f3-4c23-4996-bdcc-074832a16259 + Heroic Naz'jar + + + + + + + + + + + + Pearl of the Tides + + + At the end of your turn, replace all minions with new ones that cost (1) more. + + + + + + + + + + Pearl of the Tides + + + At the end of your turn, replace all minions with new ones. Yours cost (1) more. + + + + + + + + + + 61603e12-e097-4f15-87fe-e79f130156d7 + Skelesaurus Hex + + + + + + + + + + f7dbd9d1-c41a-4e41-9192-e91c69c8b71a + Heroic Skelesaurus + + + + + + + + + + b7a92802-20f5-4f72-96ed-1586fb9ad804 + Ancient Power + + + + <b>Hero Power</b> +Give each player a random card. It costs (0). + + + + + + + 1a151b14-2c77-4f7a-ae02-48dc83872936 + Ancient Power + + + + <b>Hero Power</b> +Add a random card to your hand. It costs (0). + + + + + 174ebfc3-0b52-41f5-a3ef-36dac9e0eb68 + The Steel Sentinel + + + + + + + + + + 08986aca-3ec7-44f7-8f90-d6308a4638f8 + Heroic Sentinel + + + + + + + + + + Platemail Armor + + + <b>Passive Hero Power</b> +Your Hero can only take 1 damage at a time. + + + + + + + + + Platemail Armor + + + <b>Passive Hero Power</b> +Your Hero and your minions can only take 1 damage at a time. + + + + + + + 50f2de1f-6ddc-4cd7-ae3b-97f02a6aa5af + Rafaam + + + + + + + + + + + + 57ebec97-6f68-4346-9501-866771a15894 + Heroic Rafaam + + + + + + + + + + 3ad4669f-aebb-4fc7-b5e9-605eb2614eb4 + Unstable Portal + + + + <b>Hero Power</b> +Add a random minion to your hand. It costs (3) less. + + + + + + f854c221-12f5-4bcd-b089-14569719827b + Unstable Portal + + <b>Hero Power</b> +Add a random minion to your hand. It costs (3) less. + + + + + + + 8fbd85f6-7139-4d9c-95e7-c6cb8063cb53 + Boneraptor + + + + + + <b>Battlecry:</b>Take control of your opponent's weapon. + + + + + + 34e33502-ac7d-47e0-8a9a-47500aa010de + Boneraptor + + + + + + <b>Battlecry:</b>Take control of your opponent's weapon. + + + + 1d6e771b-a5a7-4217-b586-a55b941a2de9 + Rafaam + + + + + + + + + + + + + + + + + + + + + + + + + + + 09949649-1d57-4f0a-ad50-22d9115363b5 + Hakkari Blood Goblet + + + + Transform a minion into a 2/1 Pit Snake. + + + + + + + + + 675834cf-e2d1-4492-b952-3246e62335fb + Crown of Kael'thas + + + + Deal $10 damage randomly split among ALL characters. + + + + + + + c99658b0-6bcb-4e1a-b857-2a17dc2642d8 + Medivh's Locket + + + + Replace your hand with Unstable Portals. + + + + + + b6b2a2e7-23be-4784-8a9e-cb0112b74975 + Eye of Orsis + + + + <b>Discover</b> a minion and gain 3 copies of it. + + + + + + + dcefe903-9a75-4d92-8e7a-ca93bf1f6760 + Khadgar's Pipe + + + + Put a random spell into each player's hand. Yours costs (0). + + + + + + ffe40ce0-7b60-4462-84ee-834eb9b56690 + Ysera's Tear + + + + Gain 4 Mana Crystals this turn only. + + + + + + a4060080-391e-412b-8018-729fa0e0bdd0 + Rummage + + + + Find an artifact. + + + + + + + + + + + + + + + + + + 7d021105-17b8-4192-a429-11c3fbec4df4 + Rummage + + + + Find an artifact. + + + + + + + + + + + + + + + + Animated Statue + + + + + + + + Zinaar + + + + + + At the end of your turn, gain a wish. + + + + + + + Zinaar + + + + + + + At the end of your turn, gain a wish. + + + + + + Sun Raider Phaerix + + At the end of your turn, add a Blessing of the Sun to your hand. + + + + + + + + + + + Sun Raider Phaerix + + + + + + Your other minions are <b>Immune</b>. + + + + + + 58fb5cfb-c5fe-4b20-8688-537a33fdef2b + Heroic Rafaam + + + + + + + + + + + + + + + + + + + + + + + + + + + Staff of Origination + + + <b>Passive Hero Power</b> +Your hero is <b>Immune</b> while the staff charges. + + + + + + + 7931ecb8-d4b7-4f7f-b66b-66f6667f3982 + Blessing of the Sun + + Give a minion <b>Immune</b> this turn. + + + + + + + + + + Blessed + + + <b>Immune</b> this turn. + + + + + + Blessing of the Sun + + + <b>Immune</b>. + + + + Chieftain Scarvash + + Enemy cards cost (1) more. + + + + + + + + + + Chieftain Scarvash + + + + + + Enemy cards cost (2) more. + + + + + + Archaedas + + At the end of your turn, turn a random enemy minion into a 0/2 Statue. + + + + + + + + + + + Archaedas + + + + + + + At the end of your turn, turn a random enemy minion into a 0/2 Statue. + + + + + + Lord Slitherspear + + At the end of your turn, summon 1/1 Hungry Naga for each enemy minion. + + + + + + + + + + + Lord Slitherspear + + + + + + + At the end of your turn, summon 1/1 Hungry Naga for each enemy minion. + + + + + + Giantfin + + At the end of your turn, draw until you have as many cards as your opponent. + + + + + + + + + + + + Giantfin + + + + + + + + At the end of your turn, draw 2 cards. + + + + + + Lady Naz'jar + + At the end of your turn, replace all other minions with new ones of the same Cost. + + + + + + + + + + + Lady Naz'jar + + + + + + + At the end of your turn, replace all other minions with new ones of the same Cost. + + + + + + Skelesaurus Hex + + At the end of your turn, give each player a random card. It costs (0). + + + + + + + + + + + Skelesaurus Hex + + + + + + + At the end of your turn, put a random card in your hand. It costs (0). + + + + + + The Steel Sentinel + + This minion can only take 1 damage at a time. + + + + + + + + + + + The Steel Sentinel + + + + + + + This minion can only take 1 damage at a time. + + + + + + Staff of Origination + + + <b>Passive Hero Power</b> +Your hero is <b>Immune</b>. + + + + + a45a4c0e-2558-45cc-bced-fba6f933088d + Lantern of Power + + + + Give a minion +10/+10. + + + + + + + + + Lantern of Power + + + +10/+10. + + + + + + 3fe53473-1b1e-4d21-a102-5d20fe42b1af + Timepiece of Horror + + + + Deal $10 damage randomly split among all enemies. + + + + + + + 79977b1b-c115-4b32-8c62-714e1cf152fd + Mirror of Doom + + + + Fill your board with 3/3 Mummy Zombies. + + + + + + + + Mummy Zombie + + + + + + + + + + adeaf15a-d97c-4161-9c19-cd18cb6af8e1 + Shard of Sulfuras + + + + Deal $5 damage to ALL characters. + + + + + + 970ff69c-039e-4b5c-80a5-7d4ce804f643 + Benediction Splinter + + + + Restore #10 Health to ALL characters. + + + + + + 92074a12-7d71-4233-a14f-0cb0a3194eff + Putress' Vial + + + + Destroy a random enemy minion. + + + + + + Putressed + + Attack and Health swapped. + + + + + + + 2c32f340-5ef6-4df7-9c18-6e408ff48693 + Lothar's Left Greave + + + + Deal 3 damage to all enemies. + + + + + + f707b080-8863-4868-a3d1-e0b39bdb2a2b + Looming Presence + + + + Draw 2 cards. Gain 4 Armor. + + + + + + 7a3238a0-0e01-4491-8687-571f858a84b4 + Looming Presence + + + + Draw 3 cards. Gain 6 Armor. + + + + + + cb4f6231-2ccb-4c64-bfa5-222d6e346fb9 + Forgotten Torch + + + + + + + + + Deal $3 damage. Shuffle a 'Roaring Torch' into your deck that deals 6 damage. + Why does a forgotten torch turn into a roaring torch with no provocation? It's one of life's many mysteries. + Richard Wright + Unlocked by starting the League of Explorers adventure. + Can be crafted after starting the League of Explorers adventure. + + + + + + df5ba55a-afab-4233-9a8f-b73082c15e1d + Roaring Torch + + + + + Deal $6 damage. + + + Richard Wright + + + + + + e97e3952-c7f5-41fa-b68d-91ea57634738 + Ethereal Conjurer + + + + + + + <b>Battlecry: Discover</b> a spell. + + + + + Despite the name, he's a solid conjurer. + Ben Zhang + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + dab8c622-a68e-4663-800c-ac2d6aa7d809 + Museum Curator + + + + + + + + + <b>Battlecry: Discover</b> a <b>Deathrattle</b> card. + + + He is forever cursing the kids who climb on the rails and the evil archeologists who animate the exhibits. + Steve Prescott + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + + 7b0c517f-eaf6-4940-8afb-80d9a975b4b2 + Curse of Rafaam + + + + + + + Give your opponent a 'Cursed!' card. +While they hold it, they take 2 damage on their turn. + + + This is what happens when Rafaam stubs his toe unexpectedly. + Alex Horley Orlandelli + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + Cursed! + + + + + While this is in your hand, take 2 damage at the start of your turn. + + + Jim Nelson + + + + + + + + + + f3b53085-92b7-4ca0-9d4c-eb6f0db2ad49 + Eye of Hakkar + + + + Take a secret from your opponent's deck and put it into the battlefield. + - + + + + + + + + c4f46bc0-d1ba-4136-b3c2-2fdae0c4d840 + Eye of Hakkar + + + + Take a secret from your opponent's deck and put it into the battlefield. + + + + Obsidian Destroyer + + + + + + + At the end of your turn, summon a 1/1 Scarab with <b>Taunt</b>. + + + + + No obsidian is safe around the Obsidian Destroyer! + Anton Zemskov + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Sinister Power + + + + +4/+4. + + + + + + Scarab + + + + + + + + <b>Taunt</b> + + Jaemin Kim + + + + + + Pit Snake + + + + + + + Destroy any minion damaged by this minion. + + + + + + It could be worse. It could be a Snake Pit. + Bernie Kang + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + d0ac73b1-6b85-4767-aee5-02e8810a9e9f + Reno Jackson + + + + + + + + <b>Battlecry:</b> If your deck contains no more than 1 of any card, fully heal your hero. + + + + Reno is a four-time winner of the 'Best Accessorized Explorer' award. + Tyson Murphy + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Tomb Pillager + + + + + + + <b>Deathrattle:</b> Add a Coin to your hand. + + + + + After the guild broke up, he could no longer raid the tombs. + Dave Allsop + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + Rumbling Elemental + + + + + + + After you play a <b>Battlecry</b> minion, deal 2 damage to a random enemy. + + + + + He's a very hungry elemental. + Cole Eastburn + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + + Rock + + + + + + <b>Taunt.</b> + + + + + + + 357bf519-a8e4-4740-b97e-f6ad02586978 + Keeper of Uldaman + + + + + + + + + <b>Battlecry:</b> Set a minion's Attack and Health to 3. + Change to 3/3. + + + U da man! No, U da man! + James Ryman + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + + + Watched + + + + Stats changed to 3/3. + + + + + + Tunnel Trogg + + + + + + + + + Whenever you <b>Overload</b>, gain +1 Attack per locked Mana Crystal. + + + Sure, they're ugly, but they live in tunnels. You try your beauty routine without natural light. + Andrew Hou + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + + Trogg No Stupid + + + + Increased Attack. + + + + + + bc335cf1-6816-48ce-ae51-5a2783797d5a + Unearthed Raptor + + + + + + + <b>Battlecry:</b> Choose a friendly minion. Gain a copy of its <b>Deathrattle</b> effect. + + + + + Still hunting for the ones who earthed him. + Trent Kaniuga + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + + + + + Unearthed Raptor + + + + + + + + 76dacd09-5d96-477b-94e3-3e403932dae9 + Map to the Golden Monkey + + + + Shuffle the Golden Monkey into your deck. Draw a card. + + + Milivoj Ceran + + + + Golden Monkey + + + + + + <b>Taunt</b> +<b>Battlecry:</b> Replace your hand and deck with <b>Legendary</b> minions. + + + A.J. Nazzaro + + + + + + + acc77346-9843-4b71-85d5-ae89982f04ac + Desert Camel + + + + + + + + + <b>Battlecry:</b> Put a 1-Cost minion from each deck into the battlefield. + + + + Dang. This card is sweet. Almost as sweet as Dessert Camel. + Matt Dixon + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + Dart Trap + + + + + + + <b>Secret:</b> After an opposing <b>Hero Power</b> is used, deal $5 damage to a random enemy. + + + Five years of tap-dancing lessons are FINALLY going to pay off! + Zoltan Boros + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + + Fierce Monkey + + + + + + + + + <b>Taunt</b> + + + Fierce monkey. That funky monkey. + + Peter Stapleton + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + 31c99344-ed66-4893-891f-a3fc588d0229 + Dark Peddler + + + + + + + + + <b>Battlecry: Discover</b> a +1-Cost card. + + + I'm offering you a bargain here! This amazing vacuum cleaner for your soul! + George Davis + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Rolling Boulder + + + + + + At the end of your turn, destroy the minion to the left. + + + Richard Wright + + + + + + 488efb5e-b992-4b6d-a27b-8c1a3e36426d + Anyfin Can Happen + + + + + + + Summon 7 Murlocs that died this game. + Theme song by Ellie Goldfin and Blagghghlrlrl Harris. + + + Ryan Metcalf + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + Sacred Trial + + + + + + + <b>Secret:</b> After your opponent has at least 3 minions and plays another, destroy it. + + + You have chosen poorly. + Zoltan Boros + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + + + Jeweled Scarab + + + + + + + + <b>Battlecry: Discover</b> a +3-Cost card. + It's amazing what you can do with super glue! + + + + Jaemin Kim + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Hollow + + + Stats copied. + + + + + + Naga Sea Witch + + + + + + + + Your cards cost (5). + + + If she had studied harder, she would have been a C+ witch. + Ben Zhang + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + Gorillabot A-3 + + + + + + + + <b>Battlecry:</b> If you control another Mech, <b>Discover</b> a Mech. + A-1 and A-2 went nuts, when they should have gone bolts. + + + + Skan Srisuwan + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + + + Huge Toad + + + + + + + + <b>Deathrattle:</b> Deal 1 damage to a random enemy. + + + + Deals damage when he croaks. + Matt Dixon + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + + Tomb Spider + + + + + + + + <b>Battlecry: Discover</b> a Beast. + Less serious than its cousin, the Grave Spider. + + + + Turovec Konstantin + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + Mounted Raptor + + + + + + + + <b>Deathrattle:</b> Summon a random 1-Cost minion. + Clever girl! + + + + + Ben Zhang + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + Jungle Moonkin + + + + + + + + Both players have +<b>Spell Damage +2</b>. + + + + + The REAL angry chicken! + Mike Sass + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + + Djinni of Zephyrs + + + + + + + + After you cast a spell on another friendly minion, cast a copy of it on this one. + + + If you want your wish granted, don't rub him the wrong way. + Jakub Kasper + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Anubisath Sentinel + + + + + + + + <b>Deathrattle:</b> Give a random friendly minion +3/+3. + + + He's actually a 1/1 who picked up the hammer from the last guy. + Paul Mafayon + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Power of the Titans + + + +3/+3. + + + + + + 8411cf88-5015-46f4-8524-95ab8e0bf1da + Fossilized Devilsaur + + + + + + + + <b>Battlecry:</b> If you control a Beast, gain <b>Taunt</b>. + + + This was the only job he could get after the dinosaur theme park debacle. + Trent Kaniuga + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + + Fossilized + + + Has <b>Taunt</b>. + + + + + + d2992705-a675-4b37-afb9-914a911d83b0 + Sir Finley Mrrgglton + + + + + + + + + <b>Battlecry: Discover</b> a new basic Hero Power. + + + + In addition to fluent Common, he also speaks fourteen dialects of 'mrgl'. + Matt Dixon + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + + + + + + + + + + + Brann Bronzebeard + + + + + + + + + Your <b>Battlecries</b> trigger twice. + + + Trigger a <b>Deathrattle</b>. + Contains 75% more fiber than his brother Magni! + Sam Nielson + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + Elise Starseeker + + + + + + + + + <b>Battlecry:</b> Shuffle the 'Map to the Golden Monkey' into your deck. + + + A large part of her job entails not mixing up the Map to the Golden Monkey with the Map to Monkey Island. + Luke Mancini + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + + + Summoning Stone + + + + + + + + Whenever you cast a spell, summon a random minion of the same Cost. + + + Sometimes it feels like it's always the same slackers that are waiting for a summon. + Jason Kang + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + + Wobbling Runts + + + + + + + + <b>Deathrattle:</b> Summon three 2/2 Runts. + + + The fourth one fell off in a tragic accident. They don't talk about it. + Sam Nielson + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + Rascally Runt + + + + + + + + Matt Dixon + + + Wily Runt + + + + + + + + Matt Dixon + + + Grumbly Runt + + + + + + Matt Dixon + + + 23067734-0f72-4858-87d4-70b6795c834b + Arch-Thief Rafaam + + + + + + + + + <b>Battlecry: Discover</b> a powerful Artifact. + + + He's very good at retrieving artifacts. From other people's museums. + Alex Horley Orlandelli + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + 9b890453-948c-4a6d-a0c3-11fb5ed913a0 + Entomb + + + + + + Choose an enemy minion. +Shuffle it into your deck. + + + + It's perfectly safe as long as you remember to put in air holes. + Alex Konstad + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + + + + adfc6c29-6be2-49bc-9131-ec208fdaeeb4 + Explorer's Hat + + + + + + Give a minion +1/+1 and "<b>Deathrattle:</b> Add an Explorer's Hat to your hand." + + + + Harrison Jones was disappointed that he didn't get to be part of the League of Explorers, but his hat did. + Joe Wilson + Unlocked by starting the League of Explorers adventure. + Can be crafted after starting the League of Explorers adventure. + + + + + + + + Explorer's Hat + + + + + +1/+1. <b>Deathrattle:</b> Add an Explorer's Hat to your hand. + + + + + Eerie Statue + + + + + + + + Can’t attack unless it’s the only minion in the battlefield. + + + Don't blink! Don't turn your back, don't look away, and DON'T BLINK. + Jim Nelson + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + d90a4371-6777-4a32-89d4-2115aa6d309e + Ancient Shade + + + + + + + + <b>Battlecry:</b> Shuffle an 'Ancient Curse' into your deck that deals 7 damage to you when drawn. + + + Warning: Do not expose to direct sunlight. + Slawomir Maniak + Unlocked in the Temple of Orsis, in the League of Explorers adventure. + Crafting unlocked in the Temple of Orsis, in the League of Explorers adventure. + + + + + Ancient Curse + + + + When you draw this, take 7 damage and draw a card. + + + Slawomir Maniak + + + + + + + 0ce50e91-436c-4d4e-819c-f230bc9cb3d8 + Excavated Evil + + + + + + Deal $3 damage to all minions. +Shuffle this card into your opponent's deck. + + + + MOM! DAD! DON'T TOUCH IT! IT'S EVIL!!!!!! + Raymond Swanland + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + d2665460-6feb-4f91-aa01-ea4b015ffe90 + Everyfin is Awesome + + + + + + Give your minions +2/+2. +Costs (1) less for each Murloc you control. + + + + Everyfin is cool when you're part of a murloc team! + Andrius Matijoshius + Unlocked in The Ruined City, in the League of Explorers adventure. + Crafting unlocked in The Ruined City, in the League of Explorers adventure. + + + + + Mrglllraawrrrglrur! + + + +2/+2. + + + + + + f6fe30c1-70f5-43fd-87ee-5b96495d9c8d + Raven Idol + + + + + + + <b>Choose One -</b> +<b>Discover</b> a minion; or <b>Discover</b> a spell. + + + Was petrified when it found out it didn't make the cut for Azerothean Idol. + A.J. Nazzaro + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + d7cce7a3-a9fc-49da-99bf-08e472eebd05 + Raven Idol + + + + + <b>Discover</b> a minion. + + + A.J. Nazzaro + + + + c7fafb8c-efcd-4f41-96d5-dd4846138502 + Raven Idol + + + + + <b>Discover</b> a spell. + + + A.J. Nazzaro + + + + Reliquary Seeker + + + + + + + + + <b>Battlecry:</b> If you have 6 other minions, gain +4/+4. + + + The Reliquary considers itself the equal of the League of Explorers. The League of Explorers doesn't. + Wayne Reynolds + Unlocked in Uldaman, in the League of Explorers adventure. + Crafting unlocked in Uldaman, in the League of Explorers adventure. + + + + + + Cursed Blade + + + + + + + + + Double all damage dealt to your hero. + + + The Curse is that you have to listen to "MMMBop" on repeat. + Craig Mullins + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + Cursed Blade + + + + Double all damage dealt to your hero. + + + + + + Animated Armor + + + + + + + + Your hero can only take 1 damage at a time. + + + + Try putting it on. Wait, let me get my camera. + Mike Sass + Unlocked in the Hall of Explorers, in the League of Explorers adventure. + Crafting unlocked in the Hall of Explorers, in the League of Explorers adventure. + + + + + + + b582d16e-3f48-438b-874b-edca2a10efa7 + Vilefin Inquisitor + + + + + + + + + + <b>Battlecry:</b> Your Hero Power becomes 'Summon a 1/1 Murloc.' + + + Jerry Mascho + Nobody expects the Vilefin Inquisition! + + + + + Silver Hand Murloc + + + + + + + + Andrew Hou + + + b13aacef-c516-4ca9-bce8-b44fe5339234 + The Tidal Hand + + + + + <b>Hero Power</b> +Summon a 1/1 Silver Hand Murloc. + Andrew Hou + + + + 8154ef6c-dc59-4a03-a061-05ba16e70750 + Primal Fusion + + + + + + + Give a minion +1/+1 for each of your Totems. + + + Jimmy Lo + Golce and Dabbana have a new line of Earth Totems available at vendors everywhere this holiday season. + + + + + + + Primally Infused + + + Increased stats. + + + + + + Flamewreathed Faceless + + + + + + + + + <b>Overload:</b> (2) + + + E. M. Gist + He's on fire! Boomshakalaka! + + + + + 0229cfd1-5564-4b7a-86fa-fe182c212608 + Eternal Sentinel + + + + + + + + + <b>Battlecry:</b> Unlock your <b>Overloaded</b> Mana Crystals. + + + J. Meyers & Nutchapol + Just try to avoid eye contact. + + + + + 1c0fad26-fdfe-4bd7-ac62-a3fb77aa21ea + Evolve + + + + + + + Transform your minions into random minions that cost (1) more. + + + Luca Zontini + So you say you want an evolution. Well, you know. We all want to change the board. + + + + Thing from Below + + + + + + + + + [x]<b>Taunt</b> +Costs (1) less for each +Totem you've summoned +this game. + + + Slawomir Maniak + Just can't resist the opportunity to hang around with a bunch of totems. + + + + + + Hammer of Twilight + + + + + + + + + <b>Deathrattle:</b> Summon a 4/2 Elemental. + + + James Ryman + Stop! It's Twlight Hammer time. + + + + + + Twilight Elemental + + + + + + + + + + A. J. Nazzaro + + + Tentacles for Arms + + + + + + + <b>Deathrattle:</b> Return this to your hand. + + + + + Alex Konstad + That's right. Garrosh just slapped you to death with a tentacle. + + + + + + Silithid Swarmer + + + + + + + + Can only attack if your hero attacked this turn. + + + Jakub Kasber + If your hero doesn't attack, it's just "Silithid Loner". + + + + Y'Shaarj, Rage Unbound + + + + + + + + At the end of your turn, put a minion from your deck into the battlefield. + + + + Samwise + When he's working out, he binds all that rage back into a ponytail. + + + + + + Fandral Staghelm + + + + + + + + + + Your <b>Choose One</b> cards have both effects combined. + + + Anton Zemskov + Always manages to mention "Back when I was creating the World Tree…" in EVERY conversation. Sheesh! Enough already. + + + + + 0ca5eb86-9bb1-41d1-925e-0957c2834f85 + Infest + + + + + + + Give your minions "<b>Deathrattle:</b> Add a random Beast to your hand." + + + Anton Zemskov + The best part is the look on their face when you jump out of the cake! Err… corpse. + + + + + Nerubian Spores + + + + + Get a Beast when this dies. + + + + + 7c2e5641-4da2-4019-b2a4-f5f4491dc845 + Feral Rage + + + + + + + <b>Choose One</b> - Give your hero +4 Attack this turn; or Gain 8 Armor. + + + Alex Alexandrov + Let's be honest. One option is a lot ragier than the other. + + + + + 8c21c630-3f2d-4e8c-8ddd-c8c04667f5e1 + Evolve Spines + + + + Give your hero +4 Attack this turn. + + + + Alex Alexandrov + + + + 8d7e2fd8-786c-4d47-88e2-96d6eb3749c2 + Evolve Scales + + + + Gain 8 Armor. + + + + Alex Alexandrov + + + + Spines + + + + + +4 Attack this turn. + + + + + + + + beaf7d7a-4aed-40d0-b383-4c6d23dc65c4 + Mark of Y'Shaarj + + + + + + + Give a minion +2/+2. +If it's a Beast, draw +a card. + + + Efrem Palacios + Y'shaarj had three sons: Mark, Theodore, and Chris. + + + + + + + + Mark of Y'Shaarj + + + + + +2/+2. + + + + + + 0fc94477-12da-4193-8bc4-6686d7b3cee2 + Forbidden Ancient + + + + + + + + + <b>Battlecry:</b> Spend all your Mana. Gain +1/+1 for each mana spent. + + + Grace Liu + This Ancient was banned from the local tavern after tucking a 'Dr. Boom' up its sleeve. + + + + + Forbidden Power + + + + Increased stats. + + + + + + Rusty Hook + + + + + + + + + + Grace Liu + + + 768395f3-32b1-4ae9-a6b0-53825eb03812 + On the Hunt + + + + + + + Deal $1 damage. +Summon a 1/1 Mastiff. + + + Zoltan Boros + The mastiff giggles if you don't hit any ducks. + + + + + + Mastiff + + + + + + + + Zoltan Boros + + + fd0c4fc3-4371-4489-9afd-9ef1e874a22d + Bladed Cultist + + + + + + + + + <b>Combo</b>: Gain +1/+1. + + + Jakub Kasber + He has a poor understanding of the law of diminishing returns. + + + + + Thirsty Blades + + + + + +1/+1. + + + + + + c69933b6-2bf4-4781-af7a-b79e86d32ebc + Journey Below + + + + + + + <b>Discover</b> a <b>Deathrattle</b> card. + + + Zoltan Boros + Don't stop believing there's something below. + + + + + + 8214d19a-77d5-499b-b037-2feab2290f86 + Thistle Tea + + + + + + + Draw a card. Add 2 extra copies of it to your hand. + + + Matthew O'Connor + Aren't Thistles prickly? Why would you drink them? I don't get Rogues. + + + + + + 53733a88-e09a-44b2-879b-0bbe3f24996a + Xaril, Poisoned Mind + + + + + + + + + <b>Battlecry and Deathrattle:</b> Add a random Toxin card to your hand. + + + + Jaemin Kim + It's basically your own fault if you go around drinking weird green potions handed out by creepy mantid dudes. + + + + + + + + + + + + + Bloodthistle + + + Costs (2) less. + + + + + + 37433e81-fea0-4d3e-a22a-2f96d96c963a + Kingsblood Toxin + + + + + Draw a card. + Tyler Walpole + + + + 02f483a5-809c-41f5-b2a2-11c69b4a461c + Bloodthistle Toxin + + + + + Return a friendly minion to your hand. +It costs (2) less. + Nutchapol Thitinunthakorn + + + + + + + + 6f8e14b1-8a6c-4cbe-aab3-2646bfb69176 + Briarthorn Toxin + + + + + Give a minion +3 Attack. + Matthew O'Connor + + + + + + + Fadeleaf + + + Stealthed until your next turn. + + + + + a27b6152-0651-4b1c-8228-89f89e7d444e + Fadeleaf Toxin + + + + + Give a friendly minion Stealth until your next turn. + Joe Wilson + + + + + + + + Briarthorn + + + +3 Attack. + + + + 8d8f15b7-d78f-443a-875e-b2e10a02a546 + Firebloom Toxin + + + + + Deal $2 damage. + Izzy Hoover + + + + + + 7b742d71-63fa-43fd-9e48-b5cccfe359ae + Shatter + + + + + + + Destroy a <b>Frozen</b> minion. + + + Trent Kaniuga + What's cooler than being cool? + + + + + + + + + Evolved Kobold + + + + + + + + <b>Spell Damage +2</b> + + + Genevieve Tsai & Nutchapol + You no take tentacle! + + + + + + cb72de70-b39d-4fa3-a022-85597b125e41 + Twilight Flamecaller + + + + + + + + + <b>Battlecry:</b> Deal 1 damage to all enemy minions. + + + Anton Zemskov + Make sure you summon a Twilight Marshmallowcaller too! Mmmm Mmm Mmm!! + + + + + Demented Frostcaller + + + + + + + + + After you cast a spell, <b>Freeze</b> a random enemy. + + + Arthur Gimaldinov + He prefers that you refer to him by his nickname: 'Frostwaker.' + + + + + + + 38a63c30-00ce-478e-abce-f64f5dabf17d + Forbidden Flame + + + + + + + Spend all your Mana. Deal that much damage to a minion. + + + Hideaki Takamura + WARNING: This flame is not to be used unless you are a licensed acolyte of the Old Gods. + + + + + + + c4e8f5b1-cf86-4d6e-96df-2848f8e0081d + Servant of Yogg-Saron + + + + + + + <b>Battlecry:</b> Cast a random spell that costs (5) or less <i>(targets chosen randomly)</i>. + + + + + Slawomir Maniak + Yogg-Saron always likes to complain about how he has too many servants and there are too many mouths to feed. + + + + + 2de25bd4-80fc-41f8-83cf-645a807aaad0 + Cabalist's Tome + + + + + + + Add 3 random Mage spells to your hand. + + + Milivoj Ceran + What's in there? I bet it's cookie recipes! + + + + b0fb97c9-e73c-47db-b661-cf795562a10c + Power Word: Tentacles + + + + + + + Give a minion +2/+6. + + + Jesper Ejsing + Because you're wrapped in a protective layer of… tentacles? + + + + + + + Tentacles + + + + +2/+6 + + + + + + f15c67d3-b209-4231-abbe-c752657aca5c + Twilight Darkmender + + + + + + + + + <b>Battlecry:</b> If your C'Thun has at least 10 Attack, restore 10 Health to your hero. + + + + Alex Garner + First she separates them from the lights, washes them in cold water, and hang-dries. + + + + + + 4fbd4fc1-edf9-49f3-a92d-ecf7f1668c1a + Shadow Word: Horror + + + + + + + Destroy all minions with 2 or less Attack. + + + Andrew Hou + It's more succinct than "Shadow Word: Suck Into Vortex." + + + + f6bd4d0b-c220-481a-aae1-b0045981b570 + Forbidden Shaping + + + + + + + Spend all your Mana. Summon a random minion that costs that much. + + + A.J. Nazzaro + But the minion arrives covered in goo. + + + + 83c662d4-e819-4bd0-b72e-3cf0fded4144 + Darkspeaker + + + + + + + + <b>Battlecry</b>: Swap stats with a friendly minion. + + + Phroi Gardner + People often think that Darkspeaker is the arch nemesis of Lightspeaker, but that title actually belongs to Heavyspeaker. + + + + + + + + + Power Transfer + + + Swapped stats. + + + + + + e140be41-f87b-40ab-b835-3ee4aa900784 + Embrace the Shadow + + + + + + + This turn, your healing effects deal damage instead. + + + Rafael Zanchetin + For when your Auchenai Soulpriests call in sick. + + + + Embracing the Shadow + + + Your healing effects are dealing damage. + + + + + + + + 74b5737d-a46f-4bc8-a592-3cfc23531940 + Darkshire Librarian + + + + + + + + + + + <b>Battlecry:</b> +Discard a random card. <b>Deathrattle:</b> +Draw a card. + Rafael Zanchetin + Do NOT be late with your overdue fines. + + + + + + + + Darkshire Councilman + + + + + + + + After you summon a minion, gain +1 Attack. + + + + Garrett Hanna + Democracy in action! + + + + + + Power of the People + + + + Increased Attack. + + + + 5852f4e0-e913-410e-a64d-f29cd108ec91 + Forbidden Ritual + + + + + + + Spend all your Mana. Summon that many 1/1 Tentacles. + + + Evgeniy Zagumennyy + Actually, C'Thun gives his full support for this ritual. + + + + Icky Tentacle + + + + + + + + + Arthur Bozonnet + + + d2220583-7ae2-4380-9cca-a1a50f0a16f0 + Spreading Madness + + + + + + + Deal $9 damage randomly split among ALL characters. + + + Mauricio Herrera + Most citizens of Darkshire wear those surgical masks to prevent spreading Madness to tourists. + + + + + 39f8c615-4dd4-4875-8941-4801eb61ea05 + Renounce Darkness + + + + + + + Replace your Hero Power and Warlock cards with another class's. The cards cost (1) less. + + + Dan Scott + SEE YA DARKNESS! + + + + Renounce Darkness Deck Ench + + + + + + + + + New Calling + + + Cost reduced. + + + + + + Anomalus + + + + + + + + + + <b>Deathrattle:</b> Deal 8 damage to all minions. + + + Kan Lui + That's short for "Anomnomnomnomalus". + + + + + + b8c04cfc-0b36-4fb9-b7f0-1ea6840d01f4 + Cho'gall + + + + + + + + + + <b>Battlecry:</b> The next spell you cast this turn costs Health instead of Mana. + + + James Ryman + Even after all this time, Gul'dan still makes Cho'gall go get donuts and coffee. + + + + + Dark Power + + + Your next spell costs Health instead of Mana. + + + + + + + + f7de79ff-b480-4fa7-8c91-23bbdf079d6b + Mukla, Tyrant of the Vale + + + + + + + + + <b>Battlecry:</b> Add 2 Bananas to your hand. + + + + Sam Nielson + Pro tip: DO NOT BOGART THE BANANAS. + + + + + Shifter Zerus + + + + + + + Each turn this is in your hand, transform it into a random minion. + + + + + Daria Tuzova + It's like being able to play with THREE angry chickens! + + + + + Shifting + + + Transforming into random minions. + + + + + + + + + + e7168a14-f583-4850-8172-ca24dfef6bd5 + Twin Emperor Vek'lor + + + + + + + + [x]<b><b>Taunt</b> +Battlecry:</b> If your C'Thun has +at least 10 Attack, summon +another Emperor. + + + + + Mike Sass + Do they make decisions based on age? "I'm two minutes older therefore we burn this village." + + + + + + + + 96067365-2fef-4cc9-83aa-4a98232a4a6d + N'Zoth, the Corruptor + + + + + + + + + <b>Battlecry:</b> Summon your <b>Deathrattle</b> minions that died this game. + + + Tyson Murphy + Has not been able to get "Under the Sea" out of his head for like FIVE THOUSAND YEARS. + + + + + + + 335492c9-ebef-4b58-bb70-5ef58c5536b0 + Yogg-Saron, Hope's End + + + + + + + + + <b>Battlecry:</b> Cast a random spell for each spell you've cast this game <i>(targets chosen randomly)</i>. + + + Tooth + I spell your doom... Y-O-U-R D-O-O-M! + + + + + Nerubian Prophet + + + + + + + + At the start of your turn, reduce this card's +Cost by (1). + + + Lars Grant-West + It’s a self-reducing prophecy. + + + + + Will of the Vizier + + + Reduced Cost. + + + + + + + + Faceless Behemoth + + + + + + + + + + Zoltan Boros + Rejected names: Forty-Foot Faceless, Big ol' No-face, Huge Creature Sans Face, Teddy. + + + Eldritch Horror + + + + + + + + + + Mike Sass + Often wonders what path his life might have taken if he wasn't named, you know, "Eldritch Horror". + + + Psych-o-Tron + + + + + + + + <b>Taunt</b> +<b>Divine Shield</b> + + + + Matt Dixon + "Annoyinger-o-Tron" was just too unwieldy. And accurate. + + + + + + + Corrupted Healbot + + + + + + + + + <b>Deathrattle:</b> Restore 8 Health to the enemy hero. + + + Jesper Esjing + Not so much "corrupted" as "has terrible aim". + + + + + + 4d3a9240-a64a-4d08-9ea8-82a6ba68c710 + Ravaging Ghoul + + + + + + + + <b>Battlecry:</b> Deal 1 damage to all other minions. + + + + Dany Orizio + But goes by "Ravishing Ghoul" when he hits the club. + + + + + Aberrant Berserker + + + + + + + + <b>Enrage:</b> +2 Attack. + + + Jim Nelson + I berserk, therefore I am. + + + + + Enraged + + + + + + +2 Attack. + + + + + Tentacle of N'Zoth + + + + + + + + + + <b>Deathrattle:</b> Deal 1 damage to all minions. + J. Meyers & T. Washington + Because EVERYDAY is the Day of the Tentacle of N'zoth. + + + + + + Grotesque Dragonhawk + + + + + + + + <b>Windfury</b> + + + + Jim Nelson + They say that "grotesque is in the eye of the beholder," but that's just because they've never seen a Grotesque Dragonhawk. Yikes! + + + + + Bog Creeper + + + + + + + + <b>Taunt</b> + + + Matt Dixon + He's tried other things, but bog sidling, bog ambling, and bog trundling just aren't as effective as bog creeping. + + + + + 72b5269e-bd56-4819-a9ea-eead5e093d9f + Bilefin Tidehunter + + + + + + + + <b>Battlecry:</b> Summon a 1/1 Ooze with <b>Taunt</b>. + + + + James Ryman + Bile actually makes for surprisingly sturdy fins. + + + + + Ooze + + + + + + + <b>Taunt</b> + + + Anton Magdalin + + + + + Zealous Initiate + + + + + + + + <b>Deathrattle:</b> Give a random friendly minion +1/+1. + + + Cole Eastburn + Ok, Initiate. You need to settle down and do your job. In this case, that means die so someone else can get a minor buff. + + + + + + Secrets of the Cult + + + +1/+1. + + + + + + 35f372b2-5aeb-4581-925f-fc14609cd21f + Corrupted Seer + + + + + + + + <b>Battlecry:</b> Deal 2 damage to all non-Murloc minions. + + + + Ryan Metcalf + For seers, it's very handy to have your crystal ball hanging right in front of your face. + + + + + 64afd175-b171-4900-9870-4dc3972ba4c7 + Disciple of C'Thun + + + + + + + + <b>Battlecry:</b> Deal 2 damage. Give your C'Thun +2/+2 <i>(wherever it is)</i>. + + + + Dan Scott + C’Thun’s recruiting pitch involves cookies, which is why it’s the most popular Old God. + + + + + + + + Blood of The Ancient One + + + + + + + + If you control two of these +at the end of your turn, merge them into 'The Ancient One'. + + + A. J. Nazzaro + Add two cups of Blood of the Ancient One to one cup of lemon juice. Add just a dash of sugar and stir. Delicious! + + + + + + The Ancient One + + + + + + + + + Wei Wang + + + + b4b75186-9952-4c71-a324-03d2b714bde1 + Faceless Shambler + + + + + + + + <b>Taunt</b> +<b>Battlecry:</b> Copy a friendly minion's Attack and Health. + + + Alex Alexandrov + "What is that thing?!" "I'm not sure, but it seems to be sort of Y'sera shaped." + + + + + + + + + + + Faceless + + + Copying stats. + + + + + + 72191e64-d37a-4123-b752-d5f703b5d67f + Shadow Strike + + + + + + Deal $5 damage to an undamaged character. + + + + Dave Allsop + It's like a backstab, only from the front. And with two more stabs. + + + + + + + Fiery Bat + + + + + + + + <b>Deathrattle:</b> Deal 1 damage to a random enemy. + + + + + Andrew Hou + He'll always be our first. + + + + + + e2a60333-f11a-42ba-8a43-95c730d36d8f + Klaxxi Amber-Weaver + + + + + + + + + <b>Battlecry:</b> If your C'Thun has at least 10 Attack, gain +5 Health. + + + + Cole Eastburn + Amberweaving is a specialty course at the local trade school. + + + + + + Amber Carapace + + + +5 Health. + + + + + + 4767f044-f874-43dd-bc51-7a2c490eaf81 + Wisps of the Old Gods + + + + + + + <b>Choose One -</b> Summon seven 1/1 Wisps; or Give your minions +2/+2. + + + Skan Srisuwan + They're just normal wisps, actually. The "Of the Old Gods" bit is just marketing. + + + + + 8f95383e-9ba4-48a4-8acb-6e1ad48f1399 + Many Wisps + + + + + Summon seven 1/1 Wisps. + + + Skan Srisuwan + + + + 34d25f3c-3c5f-41e1-89c6-09b149e99808 + Big Wisps + + + + + Give your minions +2/+2. + + + Skan Srisuwan + + + + Wisp + + + + + + + + + + Skan Srisuwan + + + Enormous + + + +2/+2. + + + + + + 74f3afcf-f8aa-4652-adef-82d34bf89d8a + Forbidden Healing + + + + + Spend all your Mana. Restore twice that much Health. + + + Mike Franchina + No one's quite sure why it's forbidden. And yes, that should make you nervous. + + + + + + Validated Doomsayer + + + + + + + + At the start of your turn, set this minion's Attack to 7. + Dan Orizio + Really feels good about himself and is in a much better place now. But… he sure does miss piloting those shredders. + + + + + + Doom Free + + + Attack set to 7. + + + + 14c127fe-f816-45c6-9f22-e2cdae83e689 + Mire Keeper + + + + + + + + + [x]<b>Choose One -</b>Summon a +2/2 Slime; or Gain an +empty Mana Crystal. + Zoltan Boros + "Hey.... Is that Mire for sale?" + "No. I'm keeping it." + + + + + fae596b7-5398-4576-93a6-88c6b322eb44 + Y'Shaarj's Strength + + + + Summon a 2/2 Slime. + + L. Lullabi & S. Srisuwan + + + + Y'Shaarj's Strength + + + + +3/+3. + + + + + 9bb67a81-f8fa-4413-b457-9ba0dadae1b3 + Yogg-Saron's Magic + + + + Gain an empty Mana Crystal. + + L. Lullabi & S. Srisuwan + + + + Slime + + + + + + + Anton Kagounkin + + + 7864accd-8542-4768-a556-76045fba5369 + Stormcrack + + + + + + + Deal $4 damage to a minion. <b>Overload:</b> (1) + Maurico Herrera + WARNING: DO NOT TOUCH THE PURPLE BALL OF LIGHTNING + + + + + + + + + 39b6fc6a-baa6-43b9-9ff1-5aea28ed2e2b + Faceless Summoner + + + + + + + + + <b>Battlecry:</b> Summon a random 3-Cost minion. + Mark Abadier + They never get the recognition they deserve. + + + + + Hallazeal the Ascended + + + + + + + + + + Whenever your spells deal damage, restore that much Health to your hero. + Wayne Reynolds + Hallazeals all your dallazamage. + + + + + + d0ae378a-d3dd-4610-8f39-c0de6782f116 + Call of the Wild + + + + + + + Summon all three Animal Companions. + Peter Stapleton + "Hello. Misha, Leokk and Huffer aren't here right now, but if you leave a message we'll get back to you right away." BEEP. + + + + Infested Wolf + + + + + + + + + <b>Deathrattle:</b> Summon two 1/1 Spiders. + + E. Guiton & A. Bozonnet + A little flea powder will fix that right up. + + + + + + Spider + + + + + + + + Luca Zontini + + + Bloodhoof Brave + + + + + + + + + <b>Taunt</b> +<b>Enrage:</b> +3 Attack. + Paul Mafayon + He thought the set was called "Flippers of the Old Cods" and hungrily volunteered to be in it. He is definitely going to get his hearing checked. + + + + + + + + Enraged + + + + + + +3 Attack. + + + + + ac033dfb-2b72-4de9-a5eb-372f3c796c7c + Malkorok + + + + + + + + + + <b>Battlecry:</b> Equip a random weapon. + E. Guiton & Nutchapol + Garrosh's best buddy. It's true. Look it up. + + + + + Selfless Hero + + + + + + + + + <b>Deathrattle:</b> Give a random friendly minion <b>Divine Shield</b>. + Rafael Zanchetin + "Don't worry about me… I'll just be here... under these tentacles." + + + + + + + 139ac16b-d78d-4910-908e-844606022539 + Rallying Blade + + + + + + + + + <b>Battlecry:</b> Give +1/+1 to your minions with <b>Divine Shield</b>. + J. Curtis Cranford + As far as blades go, this one is pretty great in the motivation department. + + + + + + Rally + + + + +1/+1. + + + + 7a34d00c-1f0d-44c9-be13-9dd79742047a + Divine Strength + + + + + + + Give a minion +1/+2. + Eva Wilderman + Every year a few paladins get disqualified from the Westfall weight lifting championship for using Divine Strength. + + + + + + + Optimism + + + +1/+2. + + + + Ragnaros, Lightlord + + + + + + + + + + At the end of your turn, restore 8 Health to a damaged friendly character. + James Ryman + What happens when you try and corrupt a corrupted firelord? DOUBLE NEGATIVE, INSECT! + + + + + + Darkshire Alchemist + + + + + + + + + <b>Battlecry:</b> Restore 5 Health. + Chris Seaman + The secret ingredient: liquified funnel cake. + + + + + + + + 9ca908a7-7abe-44b9-b6c2-4a3b29bb71bf + DOOM! + + + + + + + Destroy all minions. Draw a card for each. + Raymond Swanland + We ran out of space for "DOOOOOOOOOOOM!!!!!" + + + + Possessed Villager + + + + + + + + + <b>Deathrattle:</b> Summon a 1/1 Shadowbeast. + Matt Dixon + It's like a pinata! A lame disgusting horrific pinata. + + + + + + Shadowbeast + + + + + + + L. Lullabi & A. Bozonnet + + + Twisted Worgen + + + + + + + + <b>Stealth</b> + Trent Kaniuga + Sometimes the Old Gods' corruptions gives you power untold, sometimes you get +1 Attack. We can’t all be winners in the Eldritch lottery. + + + + + Am'gam Rager + + + + + + + + Matt Gaser + peerc rewop + + + Infested Tauren + + + + + + + + <b>Taunt</b> +<b>Deathrattle:</b> Summon a 2/2 Slime. + Paul Mafayon + The Overmind and the Old Gods are surprisingly similar. + + + + + + + + Slime + + + + + + + Anton Kagounkin + + + 6ee69ab1-6fcc-4089-bb6b-165beec68fb8 + Eater of Secrets + + + + + + + + <b>Battlecry:</b> Destroy all enemy <b>Secrets</b>. Gain +1/+1 for each. + Dan Scott + You don't want to be around after it has eaten an explosive trap. You thought Sludge Belcher was bad... + + + + + Secretly Sated + + + Increased stats. + + + + + + 5078632d-705d-4bb7-b7a1-114e28504f44 + Doomcaller + + + + + + + + <b>Battlecry:</b> Give your C'Thun +2/+2 <i>(wherever it is).</i> If it's dead, shuffle it into your deck. + + Ben Zhang + "Hello, is Doom there? No? Can I leave a message?" + + + + + Spawn of N'Zoth + + + + + + + + <b>Deathrattle:</b> Give your minions +1/+1. + Peter Stapleton + Who's a cute widdle N'Zoth? You are! Yes you are! Yes you're the cutest widdle N'Zoth in the whole world!!! + + + + + + Slimed + + + +1/+1. + + + + Southsea Squidface + + + + + + + + + <b>Deathrattle:</b> Give your weapon +2 Attack. + + Mike Sass + Quick! Before I drown! Let me sharpen your sword for you. + + + + + + Squid Oil Sheen + + + +2 Attack + + + + + + + Nerubian Soldier + + + + + + + + Scaled Nightmare + + + + + + + + At the start of your turn, double this minion's Attack. + + Luke Mancini + I like it because it scales. + + + + + + Terrifying Visage + + + Attack increased. + + + + Twilight Summoner + + + + + + + + <b>Deathrattle:</b> Summon a 5/5 Faceless Destroyer. + Jim Nelson + If you strike him down, he shall become more powerful than you can possibly imagine. + + + + + + Faceless Destroyer + + + + + + Josh Harris + + + f333fb71-7ac8-4089-98ac-c771947e52eb + Stand Against Darkness + + + + + + Summon five 1/1 Silver Hand Recruits. + + Ralph Horsley + Or if you're too tired, you can just kind of lean against the darkness. + + + + 7d133602-58e0-4587-b204-61952556ed1d + Blood Warriors + + + + + + Add a copy of each damaged friendly minion to your hand. + + A.J. Nazzaro + They have an uneasy rivalry with the Blood Paladins. + + + + + + C'Thun + + + + <b>Battlecry:</b> Deal damage equal to this minion's Attack randomly split among all enemies. + + This is actually Proxy C'thun + + + + c9a97e46-e6e0-420a-b58c-338199ecf449 + C'Thun + + + + + + <b>Battlecry:</b> Deal damage equal to this minion's Attack randomly split among all enemies. + + + + James Ryman + Unlocked when opening a Whispers of the Old Gods pack. + Crafting unlocked after opening a Whispers of the Old Gods pack. + C'Thun's least favorite Hearthstone card: Eye for an Eye. + + + + + + + + + 634ec204-5817-4d8e-8836-7a09968803fd + Beckoner of Evil + + + + + + + + <b>Battlecry:</b> Give your C'Thun +2/+2 <i>(wherever it is).</i> + + Eva Wilderman + Unlocked when opening a Whispers of the Old Gods pack. + Crafting unlocked after opening a Whispers of the Old Gods pack. + Here, Evil! C'mon boy! + + + + + Fanatic Devotion + + + Increased Stats. + + + + 8481727b-c7a6-454a-b6d2-298aed2ffcab + Blade of C'Thun + + + + + + + + <b>Battlecry:</b> Destroy a minion. Add its Attack and Health to C'Thun's <i>(wherever it is).</i> + + + Steve Prescott + C'Thun demands a sacrifice! Preferably a Deathwing. + + + + + + + + Devotion of the Blade + + + Increased stats. + + + + + 4f926191-1f15-4b12-9d74-563fb3a5f6ef + C'Thun's Chosen + + + + + + + + [x]<b>Divine Shield</b> +<b>Battlecry:</b> Give your C'Thun ++2/+2 <i>(wherever it is).</i> + + Jesper Esjing + He gave her a promise ring and everything. + + + + + + + 6422b6a8-b525-4610-9e15-3246d83fee34 + Twilight Geomancer + + + + + + + + [x]<b>Taunt</b> +<b>Battlecry:</b> Give your C'Thun +<b>Taunt</b> <i>(wherever it is).</i> + + Eric Braddock + "Ok C'Thun, repeat after me: 'Your mother was a hamster.'" + + + + + + + Geomancy + + Has <b>Taunt</b>. + + + + + Twilight Elder + + + + + + + + At the end of your turn, give your C'Thun +1/+1 <i>(wherever it is).</i> + + Tooth + Just doesn't understand those Twilight Youngsters any more - with their comic books and their rock music. + + + + + + Ancient Harbinger + + + + + + + + At the start of your turn, put a 10-Cost minion from your deck into your hand. + Zoltan Boros + "honey, can u run down to the store and pick up some 10 cost minions? thx" + + + + + + Caller Devotion + + + +1/+1. + + + + e5435438-792a-47d5-8e08-dd8bc0d85150 + Shadowcaster + + + + + + + + <b>Battlecry:</b> Choose a friendly minion. Add a 1/1 copy to your hand that costs (1). + + J. Meyers & A. Bozonnet + I mean, it's not creepy if you ASK before you steal their shadow to make a small replica of them to keep on your shelf. + + + + + + + + + Flickering Darkness + + + Shadowcaster made this 1/1. + + + + d3f3c095-7957-4e32-8255-ad4399473e46 + Forlorn Stalker + + + + + + + + <b>Battlecry:</b> Give all <b>Deathrattle</b> minions in your hand +1/+1. + + Peter Stapleton + He's going to leave the dying up to you, if that's cool. + + + + + + Night's Devotion + + + +1/+1. + + + + 64be784c-94c5-4120-8f67-968d2e0daffc + Dark Arakkoa + + + + + + + + [x]<b>Taunt</b> +<b>Battlecry:</b> Give your C'Thun ++3/+3 <i>(wherever it is).</i> + + + Nutchapol Thitinunthakorn + There's a whole gradient of Arakkoa! This one is on the darker side. + + + + + + + Arrakoa Devotion + + + +5/+5. + + + + Dark Guardian + + + Increased Stats. + + + + f0002533-96f6-4116-adc4-b3820527c749 + Cult Apothecary + + + + + + + + <b>Battlecry:</b> For each enemy minion, restore 2 Health to your hero. + Paul Mafayon + Cults need pharmacists too. + + + + + The Boogeymonster + + + + + + + + Whenever this attacks and kills a minion, gain +2/+2. + + Alex Horley Orlandelli + Has 20 years of training in classical ballet, but ALLLLLL he ever gets asked to do is boogie. + + + + + + Tasty! + + + Increased stats. + + + + 3a6b9f71-c1ad-442e-b949-3e402bd8f3dc + Ancient Shieldbearer + + + + + + + + <b>Battlecry:</b> If your C'Thun has at least 10 Attack, gain 10 Armor. + + + Alex Konstad + Back in her day, each shield weighed two tons and she had to carry four of them on each arm! + + + + + + Usher of Souls + + + + + + + + + Whenever a friendly minion dies, give your C'Thun +1/+1 +<i>(wherever it is).</i> + + Dave Allsop + Nothing unburdens your soul like a good ushing! + + + + + + Soul Power + + + Increased Attack. + + + + Cult Sorcerer + + + + + + + + [x]<b><b>Spell Damage</b> +1</b> +After you cast a spell, +give your C'Thun +1/+1 +<i>(wherever it is).</i> + + + J. Meyers & T. Washington + No matter how many times we tell her not to, she keeps feeding C'Thun scraps under the table. + + + + + + + + Sorcerous Devotion + + + +1/+1. + + + + Giant Sand Worm + + + + + + + + + Whenever this attacks and kills a minion, it may attack again. + + Slawomir Maniak + Banned from every all-you-can-eat buffet on Azeroth. + + + + + + 90657dc7-96a0-4365-89e3-ecb3aad85a13 + Princess Huhuran + + + + + + + + + + <b>Battlecry:</b> Trigger a friendly minion's <b>Deathrattle</b> effect. + + Jaemin Kim + She flitters around Ahn'Qiraj dreaming of the day she will meet a sweet prince, whom she can lay thousands of eggs with. + + + + + + + + + + + Steward of Darkshire + + + + + + + Whenever you summon a 1-Health minion, give it <b>Divine Shield</b>. + + + Phroi Gardner + Turns out divine shields are way cheaper if you buy in bulk. + + + + + + 91c23a05-5b10-469f-a130-f0cbbfc669e0 + A Light in the Darkness + + + + + + + <b>Discover</b> a minion. +Give it +1/+1. + Zoltan Boros + Wait, how can you have a light in the dark? If you turn on a light while it’s dark, doesn’t that mean it’s no longer dark? + + + + Beacon of Hope + + + +1/+1. + + + + c50b6c98-fa27-4eda-b34a-2a7b61eb17cf + N'Zoth's First Mate + + + + + + + + + + <b>Battlecry:</b> Equip a 1/3 Rusty Hook. + Paul Mafayon + Hates when N'Zoth yells "Ahoy Matey!!", but there's not really much he can do about it. + + + + + Upgraded + + + + Increased Durability. + + + + Addled Grizzly + + + + + + + + + After you summon a minion, give it +1/+1. + + Andrew Hou + Druids who spend too long in bear form are more susceptible to the whispers of the Old Gods. Right now they are whispering the lyrics to "La Bamba". + + + + + + Addled + + + +1/+1. + + + + + + c63b7175-7f27-404c-a508-99735ed8b3cc + Blood To Ichor + + + + + + + Deal $1 damage to a minion. If it survives, summon a 2/2 Slime. + Jim Nelson + For his next trick, he turns the ichor back to blood and stuffs it back in you. + + + + + + + Slime + + + + + + + + + 116fba9b-d1a7-4a63-b24d-9ad44293362b + Bloodsail Cultist + + + + + + + + + <b>Battlecry:</b> If you control a Pirate, give your weapon +1/+1. + + Matt Dixon + They're really just in it for the Blood Parrot. + + + + + + Reforged + + + +1/+1. + + + + 4a321470-b513-4fdd-9cfe-1b96e790c1c7 + Herald Volazj + + + + + + + + + + <b>Battlecry:</b> Summon a 1/1 copy of each of your other minions. + Luke Mancini + His whole job is yelling "Yogg-Saron comin'!" + + + + + Shadowy + + + 1/1. + + + + Deathwing, Dragonlord + + + + + + + + + + <b>Deathrattle:</b> Put all Dragons from your hand into the battlefield. + Alex Horley Orlandelli + To his credit, Deathwing really took to heart the feedback he was receiving that he needed to be "more of a team player". + + + + + + Hogger, Doom of Elwynn + + + + + + + + + Whenever this minion takes damage, summon a 2/2 Gnoll with <b>Taunt</b>. + Matt Dixon + When C'thun went to sleep, he checked under his bed for Hogger. + + + + + + + Gnoll + + + + + + <b>Taunt</b> + Greg Staples + + + + + Twin Emperor Vek'nilash + + + + + + + + <b>Taunt</b> + Mike Sass + + + + + 0062713c-5611-45a4-8679-fa3896899906 + Midnight Drake + + + + + + + + + <b>Battlecry:</b> Gain +1 Attack for each other card +in your hand. + Todd Lockwood + Still fearsome in the daytime. + + + + + Hour of Corruption + + + Increased Attack. + + + + + + Crazed Worshipper + + + + + + + + <b>Taunt.</b> Whenever this minion takes damage, give your C'Thun +1/+1 <i>(wherever it is).</i> + + Gonzalo Ordonez + Every month they share a pancake breakfast with the Perfectly Rational Worshippers. + + + + + + + + Power of Faith + + +1/+1. + + + + + Blackwater Pirate + + + + + + + + Your weapons cost (2) less. + + Max Grecke + "Look, they fell off the back of a ship, do you want them or not? I have a meeting with Y'Shaarj in like ten minutes." + + + + Polluted Hoarder + + + + + + + + <b>Deathrattle:</b> Draw a card. + Matt Dixon + Roll ‘greed’ OR THIS COULD HAPPEN TO YOU. + + + + + + Carrion Grub + + + + + + + + + + Kan Lui + Carrion, my wayward grub. + + + Duskboar + + + + + + + + + Samwise + Often excluded from dinner parties. To be fair, he is very boaring. + + + Squirming Tentacle + + + + + + + + <b>Taunt</b> + L. Lullabi & Nutchapol + Yeah, I think we can agree that killing the squirming tentacle first is a good idea. + + + + + 6e17ee9e-1900-443c-9f8b-82b959e7fec8 + Master of Evolution + + + + + + + + + <b>Battlecry:</b> Transform a friendly minion into a random one that costs (1) more. + Dan Scott + Will be really useful in the new "Hearthémon" game. + + + + + + + + + Undercity Huckster + + + + + + + + + <b>Deathrattle:</b> Add a random class card to your hand <i>(from your opponent's class)</i>. + Jon Neimeister + Psst! Wanna buy a random class card (from your opponent's class)? + + + + + + Hooded Acolyte + + + + + + + + + Whenever a character is healed, give your +C'Thun +1/+1 <i>(wherever it is).</i> + + Adam Byrne + Wait, what kind of acolyte doesn't wear a hood? + + + + + + Shifting Shade + + + + + + + + + <b>Deathrattle:</b> Copy a card from your opponent's deck and add it to your hand. + Tyler Walpole + Yeah, it's cooler in the shade, but you're also more likely to get JACKED. + + + + + + Cyclopian Horror + + + + + + + + <b>Taunt</b>. <b>Battlecry:</b> Gain +1 Health for each enemy minion. + Garrett Hanna + What are the qualifications for being a 'Horror?' Just how horrible do you have to be? + + + + + + + Eve of Destruction + + + Stats increased. + + + + Nat, the Darkfisher + + + + + + + + + At the start of your opponent's turn, they have a 50% chance to draw an extra card. + Steve Prescott + You can take away his humanity, but you will never take away his fishing pole. + + + + + + + b70f36d2-1b52-4142-b9c2-d0bb0a2966aa + Skeram Cultist + + + + + + + + <b>Battlecry:</b> Give your C'Thun +2/+2 <i>(wherever it is).</i> + + Jaemin Kim + Just before he comes into play, there is an AWESOME training montage with C'thun. + + + + + Vassal's Subservience + + + +2/+2. + + + + + Soggoth the Slitherer + + + + + + + + + <b>Taunt</b> +Can't be targeted by spells or Hero Powers. + James Ryman + Don't tell Soggoth, but in the future he gets totally owned by the Master's Glaive and his skull becomes a tourist attraction. + + + + + + Old Murk-Eye + + + + + + + + + + <b>Charge</b>. Has +1 Attack for each other Murloc on the battlefield. + + + He's a legend among murlocs. "Mrghllghghllghg!", they say. + Unlocked when you have all the Murlocs from the Classic Set. + Unlocked when you have all the Golden Murlocs from the Expert and Basic Sets. + Dan Scott + + + + + + + + ff7a9db7-89dc-4667-92f5-017e023ac0c7 + Captain's Parrot + + + + + + + <b>Battlecry:</b> Put a random Pirate from your deck into your hand. + + + + + Pirates and Parrots go together like Virmen and Carrots. + Daren Bader + Unlocked when you have all the Pirates from the Classic Set. + Unlocked when you have all the Golden Pirates from the Expert Set. + + + + + Hogger + + + + + + + + + + + 5e9219aa-eb9e-44d6-a47d-18981a0f514f + Riverpaw Gnoll + + + + + + + + + + Gnoll + + + + + + + + + + + + + + c5effb2f-1741-43e9-94e0-d04ad1cb979b + Hogger SMASH! + + + + + Deal 4 damage. + + + + + + + + + + Massive Gnoll + + + + + + + + + + + + + + Jaina Proudmoore + + + + + + + + Millhouse Manastorm + + + + + + + + + + + + King Mukla + + + + + + + + + + + + + ffa01d9c-6b4b-45c1-8563-5f1115e4c1a8 + Barrel Toss + + + + + + + Deal 2 damage. + + + + + + + + + + Barrel + + + + + + + + Is something in this barrel? + + + + + + 0fe987bb-9015-4bef-bc77-7cad642ef0cf + Stomp + + + + + + Deal 2 damage to all enemies. + + + + + + Hidden Gnome + + + + + + + + + Was hiding in a barrel! + + + + + 7f180298-6289-4d27-ab70-4ea6697717f2 + Bananas + + + + + + + Give a friendly minion +1/+1. <i>(+1 Attack/+1 Health)</i> + + + + + + + + + + Bananas + + + This minion has +1/+1. <i>(+1 Attack/+1 Health)</i> + + + + + + Mukla's Big Brother + + + + + So strong! And only 6 Mana?! + + + + + + + + ed93e085-4e8f-42b0-9155-96b1cacb9464 + Will of Mukla + + + + + Restore 8 Health. + + + + + + Might of Mukla + + + King Mukla has +8 Attack this turn. + + + + + + Hemet Nesingwary + + + + + + + + + + + + + + + + + 95225d89-31ae-4d65-ba9f-1001d247c1ab + Crazed Hunter + + + + + + + + + + + + 4fd1fa66-a777-4deb-9ce8-72b48f23d6be + Shotgun Blast + <b>Hero Power</b> +Deal 1 damage. + + + + + + + + + + + + + + Illidan Stormrage + + + + + + + + + + + + + + + + + + + fea9bf79-22c9-46d5-9301-f1eb1522b969 + Flames of Azzinoth + + + + <b>Hero Power</b> +Summon two 2/1 minions. + + + + + + + + Flame of Azzinoth + + + + + + + + + Naga Myrmidon + + + + + + + <b></b> + + + + + e62b99b5-f7df-47e6-8439-3da3289f6f6f + Warglaive of Azzinoth + + + + + + + + + + + + 4deaba2a-cd0e-481e-b192-eacdfaa5ec52 + Flame Burst + + + + + Shoot 5 missiles at random enemies for $1 damage each. + + + + + + aaf7f013-85bc-4d4a-8d1e-52fbc5894e0f + Dual Warglaives + + + + + + + + + + + + Lorewalker Cho + + + + + + + + + + + + + + Pandaren Scout + + + + + + + + + + + Shado-Pan Monk + + + + + + + + + db37c987-f1fc-4260-bbe2-ced6d207ea29 + Legacy of the Emperor + + + + + Give your minions +2/+2. <i>(+2 Attack/+2 Health)</i> + + + + + + Legacy of the Emperor + + + Has +2/+2. <i>(+2 Attack/+2 Health)</i> + + + + + + Brewmaster + + + + + + + + + 19f5c650-aae8-4417-a2a3-6f04ed1a09bc + Transcendence + + + + + Until you kill Cho's minions, he can't be attacked. + + + + + + Transcendence + + + Until you kill Cho's minions, he can't be attacked. + + + + + + + ff114a76-2ffe-4bab-a7d7-18b2adc57018 + Crazy Monkey + + + + + + + + + <b>Battlecry:</b> Throw Bananas. + + + + + + 636a1791-3162-4f1d-af8c-e994acd8e16f + Damage 1 + + + + + Deal 1 damage. + + + + + + + + + 3df23c8c-a405-47c9-92c4-c94b109ad00d + Damage 5 + + + + + Deal 5 damage. + + + + + + + + + 0d22aa00-43ee-48a0-9f4c-4a7353fcd7bb + Restore 1 + + + + + Restore 1 Health to a character. + + + + + + 204ba703-abcc-40ab-8cb2-b6f2c83424ce + Restore 5 + + + + + Restore 5 Health to a character. + + + + + + ddac5dae-7344-4a52-ad10-dce4913c1fa7 + Destroy + + + + + Destroy a minion or hero. + + + + + + 3f23cfa7-f4ac-4df1-9801-df90e253a10e + Break Weapon + + + + + Destroy a hero's weapon. + + + + + + + 5e2a3068-d677-40ee-af4b-791268d4c00b + Enable for Attack + + + + + Give a character Charge and make him able to attack! + + + + + + + + 4ea2e34f-de89-480c-b9d9-78f0dd6bb8c5 + Freeze + + + + + <b>Freeze</b> a character. + + + + + + + 1c554ff2-9e54-48e8-832b-9de638895314 + Enchant + + + + + Enchant a minion with an empty enchant. + + + + + + + Empty Enchant + + + + This enchantment does nothing. + + + + + 9db28764-1f95-4ba4-ad5d-fa8d7e08397d + Silence - debug + + + + + Remove all enchantments and powers from a minion. + + + + + + + + + + 1457516b-4676-4b10-8de9-27e004c22eb9 + Summon a random Secret + + + + + Summon a secret from your deck. + + + + + + 6793b439-cbb9-462f-8572-bb9694c51fa5 + Bounce + + + + + Return a minion to its owner's hand. + + + + + + + 33da35c9-bd09-4dcb-b30c-da2d3908f351 + Discard + + + + + Choose a hero. That hero's controller discards his hand. + + + + + + + 9bda2d13-d3b4-46f1-88af-fd37c588b886 + Mill 10 + + + + + Put 10 cards from a hero's deck into his graveyard. + + + + + + + Crash + + + + + Crash the game. + + + 58f83c75-f130-4c61-b7a7-d5c1b3dec4c2 + Snake Ball + + + + Summon five 1/1 snakes. + + + + c6d2b166-fbf0-49b4-9e57-9e81c297f4ec + Draw 3 Cards + + + + + Draw 3 cards. + + + + 41d487e8-7e00-4690-81fa-7425185a707d + Destroy All Minions + + + + + Destroy all minions. + + + + + + e1050677-1f0b-446c-80fb-011a6fb869d0 + Molasses + + + + You can take as long as you want on your turn. + + + + d49abda2-5d11-43e6-948e-545d8a112e4e + Damage all but 1 + + + + + Set the Health of a character to 1. + + + + + + + + + 29565a2e-992b-4605-8e55-4e58c5a098f2 + Restore All Health + + + + + Restore all Health to a character. + + + + + + + + 7e125b50-e193-4a93-be3e-8a9d67afe10c + Free Cards + + + + + Your cards cost (0) for the rest of the game. + + + + + + Free Cards + + + Your cards cost (0) for the rest of the game. + + + + + + 0e449e12-b087-4853-a652-fe70fb453a84 + Destroy All Heroes + + + + Destroy all heroes. + + + + + + + Damage Reflector + + + + + + + Whenever this minion takes damage, deal 1 damage to ALL other characters. + + + + + + + + Do Nothing + + + + + This does nothing. + + + + + db250e15-8ad7-40cb-afe5-95b2d2371cd5 + Enable Emotes + + + + + Enable emotes for your VS.AI game. (not in tutorials, though) + + + + + + a1b5d1f4-c7f3-4142-9230-165d16ceb097 + Server Crash + + + + + Crash the Server. DON'T BE A FOOL. + + + + f0051203-b961-4a85-8a5a-922d03a16d80 + Reveal Hand + + + + + + + + + 9d09fe17-3ede-4a54-9eb2-7df896d620f9 + Opponent Concede + + + + Force your opponent to concede. + + + + + + cb41e334-67e7-4032-9dd5-e202382cd0df + Opponent Disconnect + + + + + Force your opponnet to disconnect. + + + + + + ce655e9f-848e-4dcd-a051-1c0eab9863bd + Become Hogger + + + + Become Hogger for Video Recording. + + + + + + Hogger + + + + + + + 0513c58a-fcdf-451f-b6ad-60a5eab48713 + Destroy Hero Power + + + + + Destroy a player's Hero Power. + + + + + + + + + 421b9d6b-f05e-440d-ba8a-d610803fb682 + Hand to Deck + + + + + Shuffle a player's hand into his deck. + + + + + + + + + 8a02e87e-7114-408b-b53f-58860bcca94f + Mill 30 + + + + + Put 30 cards from a hero's deck into his graveyard. + + + + + + + + + 64424702-46ce-4629-bb12-b77e886c8a4d + + Hand Swapper Minion + + + + + + <b>Battlecry:</b> Discard 3 cards, then draw 3 cards. + + + + + + 6f39259a-9c90-4540-a257-db8588fa0472 + Steal Card + + + + + Steal a random card from your opponent. + + + + + + ccaa1d16-e256-4795-b281-2277f71fe0f5 + Force AI to Use Hero Power + + + + + Force the AI to use their Hero Power every turn from now on. + + + + + + 1a0ae41a-9281-4f79-86da-c0d1a8e43e91 + Destroy Deck + + + + + Delete an opponent's deck + + + + + + + + + fb2db5f3-e3bf-4d53-9abe-3ce22506c881 + -1 Durability + + + + + Give a player's weapon -1 Durability. + + + + + + + + + 4573013f-fc54-4b86-b7ba-81c8e157c674 + Destroy all Mana + + + + + Destroy all of a player's Mana Crystals. + + + + + + + + + a3ce5a61-35cb-4484-8480-cff4462843f8 + Destroy a Mana Crystal + + + + + Pick a player and destroy one of his Mana Crystals. + + + + + + + + + 8a99ff2e-b5e0-4f51-9ee3-dd7a28795502 + Make Immune + + + + + Permanently make a character <b>Immune</b>. + + + + + + + + f82b047f-9f15-4b24-84c3-1e5719515b1a + Grant Mega-Windfury + + + + + Give a minion <b>Mega-Windfury</b>. + + + + + + + + aac2ae6e-541a-4d10-86a7-2fb25420cd88 + Armor 100 + + + + Give target Hero +100 Armor + + + + + + + + + 26c3fb5e-b6ab-4554-b406-b1b28f081cf8 + Weapon Buff + + + + Give your Weapon +100/+100 + + + + + + Weapon Buff Enchant + + + + + + + + 99b1634f-c9d2-426e-85aa-5fbca7082915 + 1000 Stats + + + Give a Minion +1000/+1000 + + + + + + + + + + 1000 Stats Enchant + + + + + + + + Silence and Destroy All Minions + + + + + + Destroy all minions without triggering deathrattles. + + + + 148ff83a-1bf1-4556-be55-1018087e5f82 + Destroy Target Secrets + + + + Choose a hero. Destroy all <b>Secrets</b> controlled by that hero. + + + + + + + + + 44e67c97-2ec3-4988-a1c9-20d5486aa641 + Weapon Nerf + + + + + Give a weapon a negative enchantment. + + + + + + Weapon Nerf Enchant + + + Red Sparkles! + + + + + 4830196d-506f-47b3-9e73-4a066a3cf4b4 + Destroy Hero's Stuff + + + + + + Destroy target hero's hero power, weapon, deck, hand, minions, and secrets. + + + + + + + b0ac8fa5-2222-4224-9c0b-56da77df626c + Damage All + + + + Set the Health of a character to 0. + + + + + + + + + 380d32c8-b1a4-4d49-9d41-c5c918025631 + Armor 1 + + Give target Hero +1 Armor + + + + + + + + + + + 2ece0c21-ac62-426f-9527-bfb89c54e43f + Armor 5 + + Give target Hero +5 Armor + + + + + + + + + + + 37c6ee52-199d-4531-a390-dba68a9a7137 + Destroy ALL Secrets + + + + Destroy all <b>Secrets:</b>. + + + + + + 756403dc-a102-4090-b4b1-015fc38fc8d4 + The Song That Ends the World + + + + Crash the game server. No, really. + Some men just want to watch the world burn. + + + + + 2ddf19e7-b431-403b-a8db-4c2ac3f265c0 + Remove All Immune + + + + Remove <b>Immune</b> from ALL characters. + + + + + AI Buddy - Blank Slate + + + + + Spawn into play to clear the entire board, both hands, both decks, all mana and all secrets. + + + + + + AI Buddy - All Charge! + + + + + + Spawn into play to give all minions <b>Charge</b>. + + + + + + AI Buddy - Damage Own Hero 5 + + + + + + Spawn into play to smack your own hero for 5. + + + + + + AI Buddy - Destroy Minions + + + + + + + Spawn into play to destroy all minions. + + + + + + AI Buddy - No Deck/Hand + + + + + + + Spawn into play to destroy the AI's Hand and Deck. + + + + + + AI Helper Buddy + + + + + + + + + + Get the AI ready for testing. + + + + + + 2cdf4c9a-b2bf-42ec-b58a-c66eb5f28282 + Yogg-Saron Test (Manual) + + + + + + + + + <b>Battlecry:</b> Cast each spell you've cast this game. <i>(targets chosen randomly)</i>. + + + + + + + edd4d43a-04c0-47cd-9680-cf3a91ade767 + Set health to full + + + + + + + Set a character's health to full, and removes armour. + + + + + + + d8699466-3cb4-40ca-a8e5-4308f8584df1 + + + + + + + Adds 1 health to a damaged character. Does NOT heal. + Add 1 to Health. + + + + + + + 158b3c08-19e9-4cf8-969c-bb2f8c7164c5 + + + + + + + Adds 2 health to a damaged character. Does NOT heal. + Add 2 to Health + + + + + + + dee8fa6f-486d-462a-8041-cb3d8d2228ee + + + + + + + Adds 4 health to a damaged character. Does NOT heal. + Add 4 to Health. + + + + + + + 115207fc-b17f-4452-90fe-58718975a3cc + + + + + + + Adds 8 health to a damaged character. Does NOT heal. + Add 8 to Health. + + + + + + + 11df223b-5545-4e2a-adaa-ae6b6104f8a3 + Set Health to 1 + + + + + + + Set a character's health to 1, and remove all armour. + + + + + + + + + + + + Set every minion's health to 1, and then explode in nothingness. + Set all minions to 1 health + + + + Illidan Stormrage Cheat + + + + + + + + + Whenever you play a card, deal 1 damage to all minions. + + + + + + + + + + + 4bc455a3-4229-45b7-a970-798ebb072ec4 + Yogg-Saron Test (Auto) + + + + + + + + + + + <b>Battlecry:</b> Cast 30 random spells. <i>(targets chosen randomly)</i>. + + + + + AI Buddy - All Charge, All Windfury! + + + Play this card to give all minions <b>Charge</b> and <b>Windfury</b>. + + + + + + + All Charge, All Windfury, All The Time + + + Your minions always have <b>Charge</b> and <b>Windfury</b> + + + + + + Crash the server + + + + + Crash the server + + + + + + 2203d6c9-3572-49c7-a8c7-f8d2095237db + Gelbin Mekkatorque + + + + + + + + + <b>Battlecry:</b> Summon an AWESOME invention. + + + He's the leader of the gnomes, and an incredible inventor. He's getting better, too; He turns things into chickens WAY less than he used to. + Ludo Lullabi + This was rewarded to players who helped test the Store during the Beta. + + + + + + + + + + + Homing Chicken + + + + + + + At the start of your turn, destroy this minion and draw 3 cards. + + + + + + + + + + + Repair Bot + + + + + + + + + At the end of your turn, restore 6 Health to a damaged character. + + + + + + + + + Emboldener 3000 + + + + + + At the end of your turn, give a random minion +1/+1. + + + + + + + + + + + + Emboldened! + + + Increased Stats. + + + + + + Poultryizer + + + + + + + + + At the start of your turn, transform a random minion into a 1/1 Chicken. + + + + + + + + + Transformed + + + Has been transformed into a chicken! + + + + + + + Chicken + + + + + <i>Hey Chicken!</i> + + + + + 3f0c00bd-9382-4ce6-b16f-bd009cc5e1ec + Elite Tauren Chieftain + + + + + + + <b>Battlecry:</b> Give both players the power to ROCK! (with a Power Chord card) + Awarded at BlizzCon 2013. + + + + Samwise Didier + + He's looking for a drummer. The current candidates are: Novice Engineer, Sen'jin Shieldmasta', and Ragnaros the Firelord. + + + + + + + + 129391e2-531b-495b-a5ff-8dc0d7747e01 + I Am Murloc + + + + Summon three, four, or five 1/1 Murlocs. + + + + + + + + Murloc + + + + + + + + + de8cb346-c077-4e41-8154-cabc6c2dac90 + Rogues Do It... + + + + Deal $4 damage. Draw a card. + + + + + + + + 7020fa24-5c5c-4005-a9a7-4e2412b715cf + Power of the Horde + + + + Summon a random Horde Warrior. + + + + + + + + + + + + + + Zombie Chow + + + + + <b>Deathrattle:</b> Restore 5 Health to the enemy hero. + + + + + + Zombie. It's what's for dinner. + E. M. Gist + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + Haunted Creeper + + + + + + + + <b>Deathrattle:</b> Summon two 1/1 Spectral Spiders. + + + + Arachnofauxbia: Fear of fake spiders. + J. Curtis Cranford + Unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Crafting unlocked in The Arachnid Quarter, in the Naxxramas adventure. + + + + + + Spectral Spider + + + + + + + + Echoing Ooze + + + + + + + + <b>Battlecry:</b> Summon an exact copy of this minion at the end of the turn. + + + OOZE... Ooze... Ooze... (ooze...) + Eric Browning + Unlocked in Frostwyrm Lair, in the Naxxramas adventure. + Crafting unlocked in Frostwyrm Lair, in the Naxxramas adventure. + + + + + + + + Mad Scientist + + + + + + + + <b>Deathrattle:</b> Put a <b>Secret</b> from your deck into the battlefield. + + + His mother wanted him to be a mage or a warlock, but noooooooo, he had to go and be a scientist like his father. + James Ryman + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + + Shade of Naxxramas + + + + + + + + <b>Stealth.</b> At the start of your turn, gain +1/+1. + + + The Shades of Naxxramas <i>hate</i> the living. They even have a slur they use to refer them: <i>Livers</i>. + Ittoku Seta + Unlocked in Frostwyrm Lair, in the Naxxramas adventure. + Crafting unlocked in Frostwyrm Lair, in the Naxxramas adventure. + + + + + + + + + Consume + + Increased stats. + + + + + + Deathcharger + + + + + + <b>Charge. Deathrattle:</b> Deal 3 damage to your hero. + + + + + + + + + + Nerubian Egg + + + + + + + + <b>Deathrattle:</b> Summon a 4/4 Nerubian. + + + Eggs are a good source of protein and Nerubians. + Justin Thavirat + Unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Crafting unlocked in The Arachnid Quarter, in the Naxxramas adventure. + + + + + + Nerubian + + + + + + + + + Spectral Knight + + + + + + + + Can't be targeted by spells or Hero Powers. + + + What do Faerie Dragons and Spectral Knights have in common? They both love pasta! + Chris Rahn + Unlocked in The Military Quarter, in the Naxxramas adventure. + Crafting unlocked in The Military Quarter, in the Naxxramas adventure. + + + + Deathlord + + + + + + + + <b>Taunt. Deathrattle:</b> Your opponent puts a minion from their deck into the battlefield. + + + Ben Olson + Unlocked in The Military Quarter, in the Naxxramas adventure. + "Rise from your grave!" - Kel'Thuzad + Crafting unlocked in The Military Quarter, in the Naxxramas adventure. + + + + + + + + + Maexxna + + + + + + + + Destroy any minion damaged by this minion. + + + + + Maexxna gets super mad when people introduce her as "Maxina" or "Maxxy". + Howard Lyon + Unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Crafting unlocked in The Arachnid Quarter, in the Naxxramas adventure. + + + + + + + + + + + + + <b>Deathrattle:</b> Add a random Beast card to your hand. + + + + Webspinner + Spider cocoons are like little piñatas! + Dan Brereton + Unlocked in The Plague Quarter, in the Naxxramas adventure. + Crafting unlocked in The Plague Quarter, in the Naxxramas adventure. + + + + + + Sludge Belcher + + + + + + + + <b>Taunt +Deathrattle:</b> Summon a 1/2 Slime with <b>Taunt</b>. + + + DO NOT GIVE HIM A ROOT BEER. + Nate Bowden + Unlocked in The Plague Quarter, in the Naxxramas adventure. + Crafting unlocked in The Plague Quarter, in the Naxxramas adventure. + + + + + + + + Slime + + + + + + <b>Taunt</b> + + + + + + + Kel'Thuzad + + + + + + + + + At the end of each turn, summon all friendly minions that died this turn. + + + Kel'Thuzad could not resist the call of the Lich King. Even when it's just a robo-call extolling the Lich King's virtues. + Chris Robinson + Unlocked in Frostwyrm Lair, in the Naxxramas adventure. + Crafting unlocked in Frostwyrm Lair, in the Naxxramas adventure. + + + + + + + Stalagg + + + + + + + + + <b>Deathrattle:</b> If Feugen also died this game, summon Thaddius. + + + Stalagg want to write own flavor text. "STALAGG AWESOME!" + Dany Orizio + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + Thaddius + + + + + + + + + + Feugen + + + + + + + + + <b>Deathrattle:</b> If Stalagg also died this game, summon Thaddius. + + + Feugen is sad because everyone likes Stalagg better. + Dany Orizio + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + a6b8a176-55ea-4332-aa09-e9ac154187a9 + Wailing Soul + + + + + + + + <b>Battlecry: Silence</b> your other minions. + + + This soul just <i>wails</i> on you. Dang, soul, let up already. + Glenn Rane + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + Nerub'ar Weblord + + + + + + + + Minions with <b>Battlecry</b> cost (2) more. + + + Weblords spend all day making giant trampoline parks. + Alex Horley Orlandelli + Unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Crafting unlocked in The Arachnid Quarter, in the Naxxramas adventure. + + + + + + Duplicate + + + + + + + <b>Secret:</b> When a friendly minion dies, put 2 copies of it into your hand. + + + The one time when duping cards won't get your account banned! + Alex Garner + Unlocked in The Plague Quarter, in the Naxxramas adventure. + Crafting unlocked in The Plague Quarter, in the Naxxramas adventure. + + + + + + e4c1281b-f417-4755-8cdc-43667314b6cb + Poison Seeds + + + + + + + Destroy all minions and summon 2/2 Treants to replace them. + + + "Poisonseed Bagel" is the least popular bagel at McTiggin's Druidic Bagel Emporium. + Brian Despain + Unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Crafting unlocked in The Arachnid Quarter, in the Naxxramas adventure. + + + + Treant + + + + + + + + + Avenge + + + + + + + <b>Secret:</b> When one of your minions dies, give a random friendly minion +3/+2. + + + Several paladins have joined together to deliver justice under the name "Justice Force". Their lawyer talked them out of calling themselves the Justice League. + Zoltan & Gabor + Unlocked in Frostwyrm Lair, in the Naxxramas adventure. + Crafting unlocked in Frostwyrm Lair, in the Naxxramas adventure. + + + + + + Vengeance + + + + +3/+2. + + + + + + Death's Bite + + + + + + + + + <b>Deathrattle:</b> Deal 1 damage to all minions. + + + "Take a bite outta Death." - McScruff the Deathlord + Jim Nelson + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + Voidcaller + + + + + + + <b>Deathrattle:</b> Put a random Demon from your hand into the battlefield. + + + + + + Robb Shoberg + Unlocked in The Military Quarter, in the Naxxramas adventure. + "Void! Here, void! Here, buddy!" + Crafting unlocked in The Military Quarter, in the Naxxramas adventure. + + + + + + Dark Cultist + + + + + + + + + <b>Deathrattle:</b> Give a random friendly minion +3 Health. + + + The Cult of the Damned has found it's best not to mention their name when recruiting new cultists. + Phroilan Gardner + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + Power of the Ziggurat + + + + +3 Health. + + + + + + Unstable Ghoul + + + + + + + + <b>Taunt</b>. <b>Deathrattle:</b> Deal 1 damage to all minions. + + + Filling your Ghouls with Rocket Fuel is all the rage at Necromancer school. + Mike Nicholson + Unlocked in The Plague Quarter, in the Naxxramas adventure. + Crafting unlocked in The Plague Quarter, in the Naxxramas adventure. + + + + + + + + bde87a59-e21f-4a9e-8f8d-3ad357ebfc1b + Reincarnate + + + + + + + Destroy a minion, then return it to life with full Health. + + + It's like birth, except you're an adult and you were just dead a second ago. + Dan Scott + Unlocked in The Military Quarter, in the Naxxramas adventure. + Crafting unlocked in The Military Quarter, in the Naxxramas adventure. + + + + + + + Anub'ar Ambusher + + + + + + + <b>Deathrattle:</b> Return a random friendly minion to your hand. + + + + + Nate Bowden + Unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Crafting unlocked in The Arachnid Quarter, in the Naxxramas adventure. + Originally he was called "Anub'ar Guy who bounces a guy back to your hand", but it lacked a certain zing. + + + + + + + + Stoneskin Gargoyle + + + + + + + At the start of your turn, restore this minion to full Health. + + + Stoneskin Gargoyles love freeze tag. + Matt Smith + Unlocked in The Plague Quarter, in the Naxxramas adventure. + Crafting unlocked in The Plague Quarter, in the Naxxramas adventure. + + + + + + + Undertaker + + + + + + + + Whenever you summon a minion with <b>Deathrattle</b>, gain +1 Attack. + + + In a world where you can run to a spirit healer and resurrect yourself, Undertakers do pretty light business. + Jonboy Meyers + Unlocked in The Construct Quarter, in the Naxxramas adventure. + Crafting unlocked in The Construct Quarter, in the Naxxramas adventure. + + + + + + + Darkness Calls + + + Increased stats. + + + + + + Dancing Swords + + + + + + + + <b>Deathrattle:</b> Your opponent draws a card. + + + They like to dance to reggae. + Jon McConnell + Unlocked in The Military Quarter, in the Naxxramas adventure. + Crafting unlocked in The Military Quarter, in the Naxxramas adventure. + + + + + + f33285db-71f9-4ef1-9b83-67ac9176ce6a + Loatheb + + + + + + + + <b>Battlecry:</b> Enemy spells cost (5) more next turn. + + + + Loatheb used to be a simple Bog Beast. This is why we need stricter regulations on mining and agriculture. + Samwise + Unlocked in The Plague Quarter, in the Naxxramas adventure. + Crafting unlocked in The Plague Quarter, in the Naxxramas adventure. + + + + + Necrotic Aura + + + Your spells cost (5) more this turn. + + + + + + + + Baron Rivendare + + + + + + + + + Your minions trigger their <b>Deathrattles</b> twice. + + + Ralph Horsley + Unlocked in The Military Quarter, in the Naxxramas adventure. + There used to be five Horsemen but one of them left because a job opened up in the deadmines and the benefits were better. + Crafting unlocked in The Military Quarter, in the Naxxramas adventure. + + + + + + 2988cbae-66af-41b0-96ff-68ef80a08a52 + Patchwerk + + + + + + + + + + + caa21f26-a539-4272-8975-b73c9ce6733a + Patchwerk + + + + + + + + + + + Hook + + + + + + <b>Deathrattle:</b> Put this weapon into your hand. + + + + + + + + Hook + + + + + + <b>Windfury</b> +<b>Deathrattle:</b> Put this weapon into your hand. + + + + + + + + + + abd20d6f-3dd8-43b8-91c9-122229719018 + Hateful Strike + + + + <b>Hero Power</b> +Destroy a minion. + + + + + + + + + c5f35038-efcc-412c-abde-fc0be3f4b97d + Hateful Strike + + + + <b>Hero Power</b> +Destroy a minion. + + + + + + + + + 4c535d78-7017-4085-bef7-4b4652a81500 + Grobbulus + + + + + + + + + cd083650-0539-4bf2-bd62-80d0f27e6854 + Grobbulus + + + + + + + + + a172acd0-d259-47fe-8757-19091fd532fb + Poison Cloud + + + + <b>Hero Power</b> +Deal 1 damage to all minions. If any die, summon a slime. + + + + + + d25da2d4-57b3-4171-b2af-d06125ad907b + Poison Cloud + + + + <b>Hero Power</b> +Deal 2 damage to all enemies. If any die, summon a slime. + + + + + + + Fallout Slime + + + + + + + + + + 6a693488-f69b-421c-af4d-1897ec1613c8 + Mutating Injection + + + + Give a minion +4/+4 and <b>Taunt</b>. + + + + + + + + + + Mutating Injection + + + +4/+4 and <b>Taunt</b>. + + + + + + + 9a1afb6e-f48a-40bd-ad2a-8bc632eef790 + Gluth + + + + + + + + + 22527e30-7dae-4fc9-af28-d83e23b2bb71 + Gluth + + + + + + + + + d4ce57c7-fa0b-4df4-9796-28529d61d598 + Decimate + + + + <b>Hero Power</b> +Change the Health of all minions to 1. + + + + + + + + Decimate + + + Health changed to 1. + + + + + + 425a518b-35e3-43d9-93cf-3086066ca17d + Decimate + + + + <b>Hero Power</b> +Change the Health of enemy minions to 1. + + + + + + + + + Jaws + + + + + + Whenever a minion with <b>Deathrattle</b> dies, gain +2 Attack. + + + + + + + + + Extra Teeth + + Increased Attack. + + + + + + Jaws + + + + + + Whenever a minion with <b>Deathrattle</b> dies, gain +2 Attack. + + + + + + + + 8e2cba3b-5b8e-44a0-944c-ef1316d3bfe9 + Enrage + + + + Give your hero +6 Attack this turn. + + + + + + Enrage + + + +6 Attack this turn. + + + + + + + + 14ee5f0b-2705-4f3a-b9b1-2d87f4bc7dce + Thaddius + + + + + + + + + 3eb64597-c780-49f8-a959-e9a3ad954cc2 + Thaddius + + + + + + + + + + + 34411d1e-7168-49c9-b94c-1cd23b2f1fa6 + Polarity Shift + + + <b>Hero Power</b> +Swap the Attack and Health of all minions. + + + + + + + + Polarity + + + Attack and Health swapped. + + + + + + 96a7a029-6570-4638-bb93-e69de3fbed26 + Supercharge + + + + Give your minions +2 Health. + + + + + + Supercharged + + + +2 Health. + + + + + + Feugen + + + + + + + + + + Stalagg + + + + + + + + + + ca468a08-2f8d-4e99-ba4b-dcfb80d308f0 + Sapphiron + + + + + + + + + + + def1a6e5-0037-44d3-a30d-4e504c2cbd72 + Sapphiron + + + + + + + + + + + 3401781a-d13c-4125-b980-ca27cfd2b322 + Frost Breath + + + + <b>Hero Power</b> +Destroy all enemy minions that aren't <b>Frozen</b>. + + + + + + + + + Frozen Champion + + + + + + Permanently Frozen. Adjacent minions are Immune to Frost Breath. + + + + + + + 6d7596dd-25a2-498a-ac59-62833418653d + + Pure Cold + + + Deal $8 damage to the enemy hero, and <b>Freeze</b> it. + + + + + + + 9ef20d68-173a-4d62-affb-f2ecea3bff6e + Kel'Thuzad + + + + + + + + + + + + + + + + + Interloper! + + + + + + + + + cad5b94f-1803-4d39-90da-7059a1ee020e + Kel'Thuzad + + + + + + + + + + + + + + + + + + + Interloper! + + + + + + + + + 4c7404e6-fc99-4f07-8360-9f598aebf204 + Frost Blast + + + + <b>Hero Power</b> +Deal 2 damage to the enemy hero and <b>Freeze</b> it. + + + + + + + + + 5721e0c5-43d0-46d0-b493-60bdc0dad0d9 + Frost Blast + + + + <b>Hero Power</b> +Deal 3 damage to the enemy hero and <b>Freeze</b> it. + + + + + + + + + Guardian of Icecrown + + + + + + + + <b>Taunt</b> + + + + + Guardian of Icecrown + + + + + + <b>Taunt</b> + + + + + + + 9a08373f-5118-4285-b9fd-84e4dc5f6d54 + Chains + + + + <b>Hero Power</b> +Take control of a random enemy minion until end of turn. + + + + + + + + Slave of Kel'Thuzad + + MINE! + + + + + + + + + 2cca9dd7-4ed3-45ed-b96f-98aa6c31f505 + Chains + + + + <b>Hero Power</b> +Take control of a random enemy minion. + + + + + + + + Mr. Bigglesworth + + + + + + + + <i>This is Kel'Thuzad's kitty.</i> + + + + + + + + + + 63b291b2-5223-4ccd-a0ae-7187a48b97f6 + Anub'Rekhan + + + + + + + + + + + Nerubian + + + + + + + + edb113ee-9918-4133-a1da-48e0914b1518 + Skitter + + + + <b>Hero Power</b> +Summon a 4/4 Nerubian. + + + + + + eba4ff15-726a-474c-8fa7-edce26efbc49 + Anub'Rekhan + + + + + + + + + + + Nerubian + + + + + + + + + + 46c9355b-087b-4d58-a44b-f051f733e6c5 + Skitter + + + <b>Hero Power</b> +Summon a 3/1 Nerubian. + + + + + + + + + 6331d7be-761a-4bfa-851b-621368a01371 + Locust Swarm + + + Deal $3 damage to all enemy minions. Restore #3 Health to your hero. + + + + + + + d80a8962-6dcd-42be-870b-deb89e3b46a2 + Grand Widow Faerlina + + + + + + + + + 9b9656f6-e3ec-40bf-a47b-4bc095b0ef04 + Grand Widow Faerlina + + + + + + + + + 9d2672dd-539f-4a9a-b590-8e6a68d9a83e + Rain of Fire + + + <b>Hero Power</b> +Fire a missile for each card in your opponent's hand. + + + + + + + + 25edad6f-123d-45a7-ba6c-c5dbecb9eb74 + Rain of Fire + + + + <b>Hero Power</b> +Fire a missile for each card in your opponent's hand. + + + + + + + Worshipper + + + + + + Your hero has +1 Attack on your turn. + + + + + + + + + + Worshipper + + + + + + + + Your hero has +3 Attack on your turn. + + + + + + + + 04bf41c0-b571-43f9-af15-6fb02aa49de1 + + Maexxna + + + + + + + + 0b400f3f-d49d-4458-a430-9278cb228ec3 + Maexxna + + + + + + + + + bf9160d0-b213-4445-88a4-eefcd6fce46b + Web Wrap + + + + <b>Hero Power</b> +Return a random enemy minion to your opponent's hand. + + + + + + + + 7e056ed7-fb6d-40eb-bf7b-3c256037f346 + Web Wrap + + + + <b>Hero Power</b> +Return 2 random enemy minions to your opponent's hand. + + + + + + + 7eba94dd-a341-45f4-b03e-4450a2601234 + Necrotic Poison + + + + Destroy a minion. + + + + + + + + + f05ca50f-c35a-4fd8-bbff-bc7a77957426 + Noth the Plaguebringer + + + + + + + + + + 546042cd-9e80-4aca-a9eb-dd9436a22be0 + Noth the Plaguebringer + + + + + + + + + + Skeleton + + + + + + + + + + Skeleton + + + + + + + + Raise Dead + + + + <b>Passive Hero Power</b> +Whenever an enemy dies, raise a 1/1 Skeleton. + + + + + + + + Raise Dead + + + + <b>Passive Hero Power</b> +Whenever an enemy dies, raise a 5/5 Skeleton. + + + + + + + + 84b8a7f2-0cac-4eec-a268-00284ee9b72f + Plague + + + + Destroy all non-Skeleton minions. + + + + + + c28022ba-7ff6-48f3-95a0-877e222c1230 + Heigan the Unclean + + + + + + + + + + 67b849e2-80c4-43fe-9c42-ddbe3c12d0ef + Heigan the Unclean + + + + + + + + + + 7cea5361-5064-4db5-b158-9fa072ece8c5 + Eruption + + + + <b>Hero Power</b> +Deal 2 damage to the left-most enemy minion. + + + + + + + + f9c943b9-a007-45bc-ab80-5a2d933b8fe4 + Eruption + + + + <b>Hero Power</b> +Deal 3 damage to the left-most enemy minion. + + + + + + + + + 03b31a68-67e6-42b1-9881-baf622ad1e81 + Mindpocalypse + + + + Both players draw 2 cards and gain a Mana Crystal. + + + + + + cf9abce8-ee7c-4244-ae00-f45ad99a89f2 + Loatheb + + + + + + + + + 2130ac44-f776-4ec0-bb8e-9d2aa04c1c31 + Loatheb + + + + + + + + + + + 8317a498-b823-4f0b-9425-b33a6d703736 + Necrotic Aura + + + + <b>Hero Power</b> +Deal 3 damage to the enemy hero. + + + + + + f4fc93b3-65cf-419a-8da6-8e80001c054a + Necrotic Aura + + + + <b>Hero Power</b> +Deal 3 damage to the enemy hero. + + + + + + 5e048ab7-71db-4ae7-af30-3167e81c52eb + Deathbloom + + + + Deal $5 damage to a minion. Summon a Spore. + + + + + + + + + Spore + + + + + + <b>Deathrattle:</b> Give all enemy minions +8 Attack. + + + + + + + + Fungal Growth + + + Increased Attack. + + + + + + 0ce32cf1-dd9d-4cc3-a5a4-a53d041a8c33 + Sporeburst + + + + Deal $1 damage to all enemy minions. Summon a Spore. + + + + + + b0acb534-ba78-4ccc-8d28-38916af20417 + Instructor Razuvious + + + + + + + + + + + + + b0f01399-fc54-4cc6-9bf2-327d0a2a4e01 + Instructor Razuvious + + + + + + + + + + + + + Understudy + + + + + + <b>Taunt</b> + + + + + + + b5099f69-82aa-4d37-8391-e798c77578be + Unbalancing Strike + + + + <b>Hero Power</b> +Deal 3 damage. + + + + + + + + 69345623-f4c7-4737-8a69-8022aaba6134 + Unbalancing Strike + + + + <b>Hero Power</b> +Deal 4 damage. + + + + + + + + Massive Runeblade + + + + + Deals double damage to heroes. + + + + + + + Massive Runeblade + + + + + + Deals double damage to heroes. + + + + + + d9075a8e-77e9-4e7e-bef2-be65b10444af + Mind Control Crystal + + + + Activate the Crystal to control the Understudies! + + + + + + 91404e44-e303-476a-a303-80ee8385321f + Gothik the Harvester + + + + + + + + + c67a1ebf-9cc9-4f82-8231-91dec9f3fef6 + Gothik the Harvester + + + + + + + + + 14bcf48c-f52e-4d66-ba5a-9da0119bf5b7 + Harvest + + + + <b>Hero Power</b> +Draw a card. + + + + + + 75d20742-2c73-4893-8a8c-a4a91612f189 + Harvest + + + + <b>Hero Power</b> +Draw a card. Gain a Mana Crystal. + + + + + + + Unrelenting Trainee + + + + + + <b>Deathrattle:</b> Summon a Spectral Trainee for your opponent. + + + + + + + + Spectral Trainee + + + + + + At the start of your turn, deal 1 damage to your hero. + + + + + + + + Unrelenting Warrior + + + + + + <b>Deathrattle:</b> Summon a Spectral Warrior for your opponent. + + + + + + + + Spectral Warrior + + + + + + At the start of your turn, deal 1 damage to your hero. + + + + + + + + Unrelenting Rider + + + + + + <b>Deathrattle:</b> Summon a Spectral Rider for your opponent. + + + + + + + + Spectral Rider + + + + + + At the start of your turn, deal 1 damage to your hero. + + + + + + + + 2430845f-830b-484f-8388-3d110b28eb32 + Baron Rivendare + + + + + + + + + + + 78bed5c2-292a-4d76-96b3-cba7d2a9b1fd + Baron Rivendare + + + + + + + + + + + + + + + Lady Blaumeux + + + + + + + Your hero is <b>Immune</b>. + + + + + + + Lady Blaumeux + + + + + + + Your hero is <b>Immune</b>. + + + + + + + Thane Korth'azz + + + + + + + Your hero is <b>Immune</b>. + + + + + + + Thane Korth'azz + + + + + + + Your hero is <b>Immune</b>. + + + + + + + + Sir Zeliek + + + + + + Your hero is <b>Immune</b>. + + + + + + + Sir Zeliek + + + + + + + Your hero is <b>Immune</b>. + + + + + + + Runeblade + + + + + + Has +3 Attack if the other Horsemen are dead. + + + + + + Runeblade + + + + + + Has +6 Attack if the other Horsemen are dead. + + + + + + ad62653d-2dab-408b-b651-b67606bdb9e5 + Unholy Shadow + + + + <b>Hero Power</b> +Draw 2 cards. + + + + + + b06ec173-0de1-4dc9-ad42-219626e68d75 + Mark of the Horsemen + + + + Give your minions and your weapon +1/+1. + + + + + + Mark of the Horsemen + + + +1/+1. + + + + + + Necroknight + + + + + + <b>Deathrattle:</b> Destroy the minions next to this one as well. + + + + + + + + + Skeletal Smith + + + + + + <b>Deathrattle:</b> Destroy your opponent's weapon. + + + + + + + + 0345bc6d-10d7-4c35-8054-ed03e97ca2b9 + Flamecannon + + + + + + + Deal $4 damage to a random enemy minion. + + + Mauricio Herrera + Calling something a flamecannon really doesn't do much to distinguish it from other goblin devices. + + + + + + Snowchugger + + + + + + + + + <b>Freeze</b> any character damaged by this minion. + + + + Gabor Szikszai + Do the slow chant when he waddles by: "Chug! Chug! Chug!" + + + + + + + Unstable Portal + + + + + + + Add a random minion to your hand. It costs (3) less. + + + Sean O'Daniels + The denizens of Azeroth have no idea how much work goes into stabilizing portals. We spend like 30% of GDP on portal upkeep. + + + + Goblin Blastmage + + + + + + + + <b>Battlecry:</b> If you have a Mech, deal 4 damage randomly split among all enemies. + + + + Glenn Rane + If you can't find a bomb to throw, just pick up any goblin invention and throw that. + + + + + + 4ad1f03a-5383-45c0-8cf5-d77cc52d5f23 + Echo of Medivh + + + + + + Put a copy of each friendly minion into your hand. + + + + Alex Garner + Medivh's echo haunts Karazhan, eternally cheating at chess and <i>Hearthstone</i>. + + + + Mechwarper + + + + + + + Your Mechs cost (1) less. + + + + + Mechs that summon mechs? What's next? Donuts that summon donuts? Mmmmm. + Phil Saunders + + + + + Flame Leviathan + + + + + + + + + When you draw this, deal 2 damage to all characters. + + + + + Aleksi Briclot + Mimiron likes to take the Flame Leviathan out on some sweet joyrides. + + + + + + 650f7f23-b545-4223-a7c5-b1a1079b2bcd + Lightbomb + + + + + + Deal damage to each minion equal to its Attack. + + + + Luca Zontini + This is what happens when you allow goblins to be priests. + + + + + bdc3e1d5-f369-4d11-95e6-bb53d67a0f20 + Shadowbomber + + + + + + + + <b>Battlecry:</b> Deal 3 damage to each hero. + + + + Matt Dixon + Shadowbomber does her job, but she's kind of phoning it in at this point. + + + + + 8ed3773f-d3e9-4fe9-b848-721ed1b7cbf0 + Velen's Chosen + + + + + + Give a minion +2/+4 and <b>Spell Damage +1</b>. + + + + Alex Horley Orlandelli + Velen wrote a "Lovely Card" for Tyrande with a picture of the Deeprun Tram that said "I Choo-Choo-Choose you!" + + + + + + + + Velen's Chosen + + + + + +2/+4 and <b>Spell Damage +1</b>. + + + + 251b2863-dbf3-4baf-8321-48a3ca809c9e + Shrinkmeister + + + + + + + + <b>Battlecry:</b> Give a minion -2 Attack this turn. + + + + Give -2 Attack this turn. + Jim Nelson + After the debacle of the Gnomish World Enlarger, gnomes are wary of size-changing inventions. + + + + + + + + Shrink Ray + + + + + -2 Attack this turn. + + + + + + b5f5ac09-15b9-4903-b840-f111ef02d3c3 + Light of the Naaru + + + + + + Restore #3 Health. If the target is still damaged, summon a Lightwarden. + + + + Jesper Ejsing + "Light it up!" - Command given to both Lightwardens and Goblins holding Flamecannons. + + + + + + Cogmaster + + + + + + + Has +2 Attack while you have a Mech. + + + + Trent Kaniuga + After a while, you don't see the cogs and sprockets. All you see is a robot, a spider tank, a deathray... + + + + + c1b3351b-050d-431c-a34f-5ef861af1a0a + Vol'jin + + + + + + + + <b>Battlecry:</b> Swap Health with another minion. + + + + + Raymond Swanland + Swap Health. + Vol'jin is a shadow hunter, which is like a shadow priest except more voodoo. + + + + + + + + Shadowed + + + Health was swapped. + + + + + + + 7fa2c115-0cd2-436c-aaf4-9430bf7d3d31 + Darkbomb + + + + + + + Deal $3 damage. + + + Jeff Haynie + If you're looking to make an "Emo" deck, this card is perfect! + + + + + + Fel Reaver + + + + + + + + + Whenever your opponent plays a card, remove the top 3 cards of your deck. + + + Zoltan & Gabor + So reaver. Much fel. Wow. + + + + + + Call Pet + + + + + + + Draw a card. +If it's a Beast, it costs (4) less. + + + E.M. Gist + Real hunters tame hungry crabs. + + + + Mistress of Pain + + + + + + + + Whenever this minion deals damage, restore that much Health to your hero. + + + + + Carl Critchlow + Her sister is the Mistress of Pane who sells windows and shower doors. + + + + + + 08cff336-e900-43db-b006-959339814cb9 + Demonheart + + + + + + + Deal $5 damage to a minion. If it's a friendly Demon, give it +5/+5 instead. + + + Kerem Beyit + Virtually every member of the pro demon lobby is a warlock. Weird. + + + + + + + Demonheart + + + + +5/+5. + + + + + + Fel Cannon + + + + + + + + + At the end of your turn, deal 2 damage to a non-Mech minion. + + + + Matt Gaser + The box says, "New and improved, with 200% more fel!" + + + + + + Mal'Ganis + + + + + + + + + Your other Demons have +2/+2. +Your hero is <b>Immune</b>. + + + + + Wayne Reynolds + Mal'Ganis doesn't like being betrayed, so if you discard him, watch out. + + + + + + + Grasp of Mal'Ganis + + + + Mal'Ganis is granting +2/+2. + + + + + + c572869d-f1a3-4b75-87f7-2768d2d7f896 + Tinker's Sharpsword Oil + + + + + + + Give your weapon +3 Attack. <b>Combo:</b> Give a random friendly minion +3 Attack. + + + Den + "Get ready to strike oil!" - Super-cheesy battle cry + + + + + + + Tinker's Sharpsword Oil + + + +3 Attack. + + + + + + Tinker's Sharpsword Oil + + + +3 Attack. + + + + + + b11538c6-830e-4165-9f09-7870adf2ea5c + Goblin Auto-Barber + + + + + + + + + <b>Battlecry</b>: Give your weapon +1 Attack. + + + + Zolton Boros + This guy is excellent at adjusting your haircut and/or height. + + + + + Extra Sharp + + + +1 Attack. + + + + + + Cogmaster's Wrench + + + + + + + + Has +2 Attack while you have a Mech. + + + + Richard Wright + For tightening cogs and smashin' troggs! + + + + + One-eyed Cheat + + + + + + + + + Whenever you summon a Pirate, gain <b>Stealth</b>. + + + + Danny Beck + When pirates say there is no "Eye" in "team," they are very literal about it. + + + + + + + ae2df762-bc93-40c9-a5f7-946d5cbd757e + Feign Death + + + + + + + Trigger all <b>Deathrattles</b> on your minions. + + + The hardest part about doing a "Feign Death" convincingly is learning how to make the right smell. It takes a lot of commitment. + Luca Zontini + + + + + Iron Sensei + + + + + + + + + At the end of your turn, give another friendly Mech +2/+2. + + + + Brian Despain + Mechs like learning from him because he really speaks their language. + +0110100001101001 + + + + + + Ironed Out + + + + Increased stats. + + + + + + Trade Prince Gallywix + + + + + + + + Whenever your opponent casts a spell, gain a copy of it and give them a Coin. + + + + + Wei Wang + Gallywix believes in supply and demand. He supplies the beatings and demands you pay up! + + + + + + 100df36c-74b0-45ea-a451-56e6d1bf6ad5 + Gallywix's Coin + + + + + + Gain 1 Mana Crystal this turn only. +<i>(Won't trigger Gallywix.)</i> + + + + 65727305-c642-4418-9d66-b5e420730473 + Ancestor's Call + + + + + + + Put a random minion from each player's hand into the battlefield. + + + Dan Scott + "Hey! Ancestors!" - Ancestor's call + + + + Anodized Robo Cub + + + + + + + + + <b>Taunt</b>. <b>Choose One -</b> ++1 Attack; or +1 Health. + + + + Eva Widermann + + It's adorable! AND OH MY GOODNESS WHY IS IT EATING MY FACE + + + + + + + f3a73794-49c7-42c3-b7ac-e70cc80cfab2 + Attack Mode + + + + +1 Attack. + + + + + + Attack Mode + + + + +1 Attack. + + + + + + e13f0937-0216-4c27-95ec-5bacf45b84d0 + Tank Mode + + + + +1 Health. + + + + + + Tank Mode + + + + +1 Health. + + + + + + 3708c4ea-f0f2-45cf-9eb7-cc64c1dee65b + Recycle + + + + + + + Shuffle an enemy minion into your opponent's deck. + + + Efrem Palacios + Druidic recycling involves putting plastics in one bin and enemy minions in another bin. + + + + + + + + 51a08731-2b3c-4f3c-9a7d-64df47c9e56c + Grove Tender + + + + + + + + + <b>Choose One -</b> Give each player a Mana Crystal; or Each player draws a card. + + + Chris Rahn + Likes: Hiking and the great outdoors. Dislikes: Goblin shredders and sandals. (Can’t find any that fit!). + + + + + 493911eb-b71c-4c33-bcec-7c7c5d391703 + Gift of Mana + + + + Give each player a Mana Crystal. + + + + + + e8a3744a-0d75-4b4d-8d29-a1908117a8b1 + Gift of Cards + + + + Each player draws a card. + + + + + + 1467352a-dc91-4ba7-9425-533eadfb1498 + Tree of Life + + + + + + + Restore all characters to full Health. + + + Steve Prescott + Healing: It grows on trees! + + + + Mech-Bear-Cat + + + + + + + + + Whenever this minion takes damage, add a <b>Spare Part</b> card to your hand. + + + + Trent Kaniuga + Crushes buildings with his BEAR hands. + + + + + + + + + + + + + + Malorne + + + + + + + + + + <b>Deathrattle:</b> Shuffle this minion into your deck. + + + Oliver Chipping + When Malorne isn't mauling hordes of demons, he enjoys attending parties, though he prefers to go stag. + + + + + + + + Powermace + + + + + + + <b>Deathrattle</b>: Give a random friendly Mech +2/+2. + + + + + Zoltan and Gabor + People assume that shamans control the elements, but really, they have to ask them stuff and the elements are like, "Yeah ok, sure." + + + + + + Powered + + + + +2/+2. + + + + + + Whirling Zap-o-matic + + + + + + + + + + + <b>Windfury</b> + + Jim Nelson + If you pay a little extra, you can get it in "candy-apple red." + + + + + 8eaffe67-5bf1-4ecf-b212-b95b417a18a0 + Crackle + + + + + + + Deal $3-$6 damage. <b>Overload:</b> (1) + + + Warren Mahy + Snap! This card! Pop! + + + + + + + + Vitality Totem + + + + + + + At the end of your turn, restore 4 Health to your hero. + + + + + + Guangjian Huang + You can usually find these at the totemist's market on Saturdays. + + + + + + Siltfin Spiritwalker + + + + + + + + + Whenever another friendly Murloc dies, draw a card. <b>Overload</b>: (1) + + + + Clint Langley + The elements respond to anyone who calls them for a worthy cause, even if you call them by yelling, "MRGHRGLGLGL!" + + + + + + + + c0d2425f-0029-4c89-a753-ea5df09ba605 + Dark Wispers + + + + + + + + + <b>Choose One -</b> Summon 5 Wisps; or Give a minion +5/+5 and <b>Taunt</b>. + Trent Kaniuga + Don't worry; we fired the person who named this card. + + + + + + + + 2c9ea073-5086-42ff-adb5-dd52aa27efea + Dark Wispers + + + + +5/+5 and <b>Taunt</b>. + + + + + + + + + 3ea52f46-42d4-4112-b3e5-294f06eb02fb + Dark Wispers + + + + Summon 5 Wisps. + + + + + + + + + Dark Wispers + + + + +5/+5 and <b>Taunt</b>. + + + + + + 286c76fb-fc01-4dc3-abe3-f68c174a370d + Neptulon + + + + + + + + + + + + <b>Battlecry:</b> Add 4 random Murlocs to your hand. <b>Overload:</b> (3) + Ruan Jia + Neptulon is "The Tidehunter". He’s one of the four elemental lords. And he and Ragnaros get together and make really amazing saunas. + + + + + + + bc46e110-5995-43f7-a80d-04832e93cfa7 + Glaivezooka + + + + + + + + <b>Battlecry:</b> Give a random friendly minion +1 Attack. + + + + For the times when a regular bazooka just isn't enough. + Gino Whitehall + + + + + Glaivezooka + + + + + + +1 Attack. + + + + Spider Tank + + + + + + + + + + + Dany Orizio + "What if we put guns on it?" -Fizzblitz, staring at the spider-transportation-machine + + + Imp-losion + + + + + + + Deal $2-$4 damage to a minion. Summon a 1/1 Imp for each damage dealt. + + + Jaemin Kim + The shrapnel is waaaaay worse than the explosion. + + + + + + + Imp + + + + + + + + + + cb7cbd5f-4646-4970-aff2-609ce9c132a3 + King of Beasts + + + + + + + + + + <b>Taunt</b>. <b>Battlecry:</b> Gain +1 Attack for each other Beast you have. + + + Seamus Gallagher + He never sleeps. Not even in the mighty jungle. + + + + + + + The King + + + + Increased Attack. + + + + + + c9dc751f-09cc-44eb-952c-1861cfeeab67 + Sabotage + + + + + + + Destroy a random enemy minion. <b>Combo</b>: And your opponent's weapon. + + + Dave Allsop + Rogues can't stand it. They know you planned it! They are going to set you straight! + + + + + + + + + Metaltooth Leaper + + + + + + + + + + <b>Battlecry</b>: Give your other Mechs +2 Attack. + + + Don't leave them out in the rain. In Un'Goro Crater there is a whole colony of rust-tooth leapers. + Hideaki Takamura + + + + + Metal Teeth + + + + +2 Attack. + + + + + + Gahz'rilla + + + + + + + + + + Whenever this minion takes damage, double its Attack. + + + + The Sen'jin High football team is The Gahz'rillas. + Raymond Swanland + + + + + + + Might of Zul'Farrak + + + + Multiplying Attack. + + + + + + 9c6ce3c8-50de-4f9a-9979-2b86640d1e5a + Bouncing Blade + + + + + + + Deal $1 damage to a random minion. Repeat until a minion dies. + + + Andrew Hou + Only goblins would think this was a good idea. Even they are starting to have their doubts. + + + + + + Warbot + + + + + + + + + <b>Enrage:</b> +1 Attack. + + + + Tyler Walpole + Mass production of warbots was halted when it was discovered that they were accidentally being produced at "sample size." + + + + + Enraged + + + + + +1 Attack + + + + + + 62bf832b-15a4-486f-b96f-e4070f26c60c + Crush + + + + + + + Destroy a minion. If you have a damaged minion, this costs (4) less. + + + Michael Sutfin + Using this card on your enemies is one of the best things in life, according to some barbarians. + + + + + + + + 14d6fc43-415f-4893-bc7f-c7a7ec333553 + Shieldmaiden + + + + + + + + + <b>Battlecry:</b> Gain 5 Armor. + + + Alex Horley Orlandelli + She has three shieldbearers in her party to supply her with back ups when she gets low on durability. + + + + + Ogre Warmaul + + + + + + + + + 50% chance to attack the wrong enemy. + + + Richard Wright + Simple, misguided, and incredibly dangerous. You know, like most things ogre. + + + + + + + + b669b9b7-bae3-4aef-adba-bef8856caa36 + Screwjank Clunker + + + + + + + + + <b>Battlecry</b>: Give a friendly Mech +2/+2. + + + + Give +2/+2. + If it breaks, just kick it a couple of times while yelling "Durn thing!" + Jesper Ejsing + + + + + + + + + + Screwy Jank + + + + +2/+2. + + + + + + + + 43cea392-4861-42ee-b916-9a7b2538b0d0 + Iron Juggernaut + + + + + + + + + + <b>Battlecry:</b> Shuffle a Mine into your opponent's deck. When drawn, it explodes for 10 damage. + + + + Raymond Swanland + The Iron Juggernaut guards Orgrimmar and has just earned the "Employee of the Month" award! + + + + + Burrowing Mine + + + + When you draw this, it explodes. You take 10 damage and draw a card. + + + Chris Seaman + + + + + + + + + 1d8e21f9-1eac-40b3-9e7e-ab3dcb97b773 + Seal of Light + + + + + + + Restore #4 Health to your hero and gain +2 Attack this turn. + + + The walrus of Light restores EIGHT Health. + Jason Chan + + + + Seal of Light + + + +2 Attack this turn. + + + + + + + + Shielded Minibot + + + + + + + + + <b>Divine Shield</b> + + + + He chooses to believe what he is programmed to believe! + Raymond Swanland + + + + + 9de8c7c8-94b1-4710-b625-963271e72bf5 + Coghammer + + + + + + + + <b>Battlecry:</b> Give a random friendly minion <b>Divine Shield</b> and <b>Taunt</b>. + + + + So you ripped this out of a machine, carved some runes on it, stuck it on a handle, and now it's a weapon of great divine power? Seems legit. + Dany Orizio + + + + + + + 7e3ba6ab-107d-4f77-9fe6-3078b6456d06 + Quartermaster + + + + + + + + + <b>Battlecry:</b> Give your Silver Hand Recruits +2/+2. + + + His specialty? Dividing things into four pieces. + Phroilan Gardner + + + + + Well Equipped + + + + +2/+2. + + + + + + 930442b2-3ab7-4fe3-a936-35c0457a6aa5 + Muster for Battle + + + + + + + Summon three 1/1 Silver Hand Recruits. Equip a 1/4 Weapon. + + + "I'm bringing the guacamole!" – One of the most successful (yet rare) Silver Hand rallying cries + Mike Hayes + + + + Cobalt Guardian + + + + + + + + + Whenever you summon a Mech, gain <b>Divine Shield</b>. + + + + Guardians used to be built out of Adamantium, but production got moved to Gadgetzan and Cobalt was cheap. + Jim Nelson + + + + + + + Bolvar Fordragon + + + + + + + + + + Whenever a friendly minion dies while this is in your hand, gain +1 Attack. + + + Spoiler alert: Bolvar gets melted and then sits on an ice throne and everyone forgets about him. + Tooth + + + + + Retribution + + + Increased Attack + + + + + + Puddlestomper + + + + + + + + + He pays homage to Morgl, the great murloc oracle! (Who doesn't??) + Jaemin Kim + + + Ogre Brute + + + + + + + + 50% chance to attack the wrong enemy. + + + Ogres have really terrible short-term chocolate. + Vinod Rams + + + + + + + + Dunemaul Shaman + + + + + + <b>Windfury, Overload: (1)</b> +50% chance to attack the wrong enemy. + + + + + + José Ladrönn + He just closes his eyes and goes for it. Raarararrrarar! + + + + + + + + + + + + Stonesplinter Trogg + + + + + + + + Whenever your opponent casts a spell, gain +1 Attack. + + + The only thing worse than smelling troggs is listening to their poetry. + Peet Cooper + + + + + + Metabolized Magic + + + Increased Attack. + + + + + + + Burly Rockjaw Trogg + + + + + + Whenever your opponent casts a spell, gain +2 Attack. + + + + + He's burly because he does CrossFit. + Aleksi Briclot + + + + + + Metabolized Magic + + Increased Attack. + + + + + + + + 58b990b9-1e8a-46cd-8796-2793e18cf680 + Antique Healbot + + + + + + + + + + <b>Battlecry:</b> Restore 8 Health to your hero. + + Jesper Ejsing + They don't make 'em like they used to! (Because of explosions, mostly.) + + + + + Repairs! + + + +4 Health. + + + + + + + Salty Dog + + + + + + + + + Alex Horley Orlandelli + He's recently recovered from being a "scurvy dog." + + + Lost Tallstrider + + + + + + + + + + + Benjamin Zhang + The message, "If found, please return to Mulgore," is tattooed on his rear. + + + Shadowboxer + + + + + + Whenever a character is healed, deal 1 damage to a random enemy. + + + + + + + Dan Scott + Punching is its primary function. Also, its secondary function. + + + + + + 1632247f-f344-42ff-8820-129870a1498b + Cobra Shot + + + + + + Deal $3 damage to a minion and the enemy hero. + + + + Howard Lyon + "Cobra Shot" hurts way, way, way more than "Cobra Cuddle." + + + + + + + 8499050b-927e-4c1f-9ebc-66c9d0c1891a + Kezan Mystic + + + + + + + + <b>Battlecry:</b> Take control of a random enemy <b>Secret</b>. + + + They pretend to be wise and enlightened, but they mostly just hate to be left out of a secret. + Jakub Kasper + + + + + + Ship's Cannon + + + + + + + + After you summon a Pirate, deal 2 damage to a random enemy. + + + If you hear someone yell, "Cannonball!" you're about to get wet. Or crushed. + Warren Mahy + + + + + + Explosive Sheep + + + + + + + + <b>Deathrattle:</b> Deal 2 damage to all minions. + + + + Ralph Horsley + How is this supposed to work? Your enemies think, "<i>Hey!</i> Cute sheep!" and run over to cuddle it? + + + + + + Pistons + + + Increased Attack. + + + + + + Anima Golem + + + + + + + + + + At the end of each turn, destroy this minion if it's your only one. + + + Josh Harris + The Dark Animus is evil and mysterious and huge and unable to write sentences that utilize proper grammar. + + + + + + Mechanical Yeti + + + + + + + + <b>Deathrattle:</b> Give each player a <b>Spare Part.</b> + + + + The yetis of Chillwind Point are a source of both inspiration and savage beatings. + Chris Seaman + + + + + + + Force-Tank MAX + + + + + + + + <b>Divine Shield</b> + + + + There is a factory in Tanaris for crafting force-tanks, but it only ever made two, because of cost overruns. + Nutchapol Thitinunthakorn + + + + + 2366e87b-5605-4d66-b47f-d37ea6fe23a4 + Druid of the Fang + + + + + + + + + <b>Battlecry:</b> If you have a Beast, transform this minion into a 7/7. + + + Brandon Kitkouski + The Druids of the Fang live in the Wailing Caverns. They wear cool snake shirts and tell snake jokes and say "bro" a lot. + + + + + + Druid of the Fang + + + + + + + + Massive Black + + + Gilblin Stalker + + + + + + + + <b>Stealth</b> + + + "Shhh, I think I hear something." + +"Ah, it's probably nothing." - Every Henchman + Seamus Gallagher + + + + + Clockwork Gnome + + + + + + <b>Deathrattle:</b> Add a <b>Spare Part</b> card to your hand. + + + + + + Clockwork gnomes are always asking what time it is. + Matt Dixon + + + + + + + 3dbc6447-6011-44d7-bcf5-121893485202 + Upgraded Repair Bot + + + + + + + + <b>Battlecry:</b> Give a friendly Mech +4 Health. + + + + Nutchapol Thitinunthakorn + It's the same as the previous generation but they slapped the word "upgraded" on it to sell it for double. + Give a Mech +4 Health. + + + + + + + + + + + + Flying Machine + + + + + + <b>Windfury</b> + + + + + + To operate, this contraption needs a hula doll on the dashboard. Otherwise it's just a “falling machine.” + Matt Dixon + + + + + Annoy-o-Tron + + + + + + + + <b>Taunt</b> +<b>Divine Shield</b> + + + + Matt Dixon + The inventor of the Annoy-o-Tron was immediately expelled from Tinkerschool, Tinkertown, and was eventually exiled from the Eastern Kingdoms altogether. + + + + + + + Siege Engine + + + + + + + + + Whenever you gain Armor, give this minion +1 Attack. + + + + Wintergrasp Keep's only weakness! + Zero Yue + + + + + + Armor Plated + + + + Increased Attack. + + + + + + Steamwheedle Sniper + + + + + + + + + Your Hero Power can target minions. + + + Jun Kang + Goblins seldom have the patience for sniping. Most prefer lobbing explosives. + + + + Ogre Ninja + + + + + + + + <b>Stealth</b> +50% chance to attack the wrong enemy. + + + + Samwise + He didn't have the grades to get into ninja school, but his dad pulled some strings. + + + + + + + + + + Illuminator + + + + + + + + If you control a <b>Secret</b> at the end of your turn, restore 4 Health to your hero. + + + "LUMOS!" is not what they yell. What do you think this is, Hogwarts? + Jim Nelson + + + + + + + 8a947ff6-895b-40cd-a599-a91a943a04aa + Madder Bomber + + + + + + + + + + <b>Battlecry:</b> Deal 6 damage randomly split between all other characters. + Dang, Bomber, calm down. + Alex Horley Orlandelli + + + + + Arcane Nullifier X-21 + + + + + + + + <b>Taunt</b> +Can't be targeted by spells or Hero Powers. + + + + There was some hard talk between gnome magi and engineers about inventing this mech. + Zero Yue + + + + + + ff89f0a5-1195-4e2c-8638-58febaca06e6 + Gnomish Experimenter + + + + + + + + <b>Battlecry:</b> Draw a card. If it's a minion, transform it into a Chicken. + + + He's legitimately surprised every time he turns himself into a chicken. + Jesper Ejsing + + + + + Chicken + + + + + + + + + Target Dummy + + + + + + + + + <b>Taunt</b> + + + The engineering equivalent of a "Kick Me" sticker. + Matt Dixon + + + + + Jeeves + + + + + + + + At the end of each player's turn, that player draws until they have 3 cards. + + + + This robot is a lean, mean, butlerin' machine. + Matt Dixon + + + + + + Goblin Sapper + + + + + + + + + + Has +4 Attack while your opponent has 6 or more cards in hand. + He’s not such a binge exploder anymore. These days, he only explodes socially. + Jesper Ejsing + + + + + Piloted Shredder + + + + + + <b>Deathrattle:</b> Summon a random 2-Cost minion. + + + + + + Once upon a time, only goblins piloted shredders. These days, everyone from Doomsayer to Lorewalker Cho seems to ride one. + Dan Scott + + + + + + Lil' Exorcist + + + + + + + + + + <b>Taunt</b> +<b>Battlecry:</b> Gain +1/+1 for each enemy <b>Deathrattle</b> minion. + Warlocks have the town exorcist on speed dial in case they unleash the wrong demon. + Jim Nelson + + + + + + + + Gnomeregan Infantry + + + + + + + + <b>Charge</b> +<b>Taunt</b> + + + The gnomes are valiant and ready to return to their irradiated, poorly ventilated homeland! + Zoltan & Gabor + + + + + + + cd461b1c-a1e4-401b-8198-c1446955c217 + Bomb Lobber + + + + + + + + <b>Battlecry:</b> Deal 4 damage to a random enemy minion. + + + He lobbies Orgrimmar daily on behalf of bombs. + Luca Zontini + + + + + Floating Watcher + + + + + + + + + Whenever your hero takes damage on your turn, gain +2/+2. + + + + Todd Lockwood + "Evil Eye Watcher of Doom" was the original name, but marketing felt it was a bit too aggressive. + + + + + + Brow Furrow + + + + Increased stats. + + + + + + 5815b14c-7ebc-40a0-b296-e5e0a390e31c + Scarlet Purifier + + + + + + + + + <b>Battlecry</b>: Deal 2 damage to all minions with <b>Deathrattle</b>. + + + The Scarlet Crusade is doing market research to find out if the "Mauve Crusade" would be better received. + Anton Zemskov + + + + + + Pure + + + + Increased Stats. + + + + + + a04c06c5-8399-4314-b5ee-c7eaf20a6649 + Tinkertown Technician + + + + + + + + <b>Battlecry:</b> If you have a Mech, gain +1/+1 and add a <b>Spare Part</b> to your hand. + + + Won't you take me to... Tinkertown? + Gabor Szikszai + + + + + + + Might of Tinkertown + + + +1/+1. + + + + + + Micro Machine + + + + + + + + + + + Skan Srisuwan + At the start of each turn, gain +1 Attack. + This card is the real thing. + + + + + + Hobgoblin + + + + + + + + + + Whenever you play a 1-Attack minion, give it +2/+2. + Hobgoblins are meeting next week to discuss union benefits. First on the list: dental plan. + Laurel D. Austin + + + + + + HERE, TAKE BUFF. + + + +2/+2. + + + + + + Piloted Sky Golem + + + + + + + + <b>Deathrattle:</b> Summon a random 4-Cost minion. + + + + Michael Phillippi + The pinnacle of goblin engineering. Includes an espresso machine and foot massager. + + + + + + Junkbot + + + + + + + + Whenever a friendly Mech dies, gain +2/+2. + + + + One bot's junk is another bot's AWESOME UPGRADE! + Zoltan Boros + + + + + + Junked Up + + + Increased stats. + + + + + + cace4989-61db-4406-9c3a-b6c45709b458 + Enhance-o Mechano + + + + + + + + <b>Battlecry:</b> Give your other minions <b>Windfury</b>, <b>Taunt</b>, or <b>Divine Shield</b>. +<i>(at random)</i> + + + + His enhancements are gluten free! + Zoltan Boros + + + + + + + + 51c6806e-6f56-4985-bcab-d7d9f383ad7b + Recombobulator + + + + + + + + <b>Battlecry:</b> Transform a friendly minion into a random minion with the same Cost. + + + Ben Olson + Transform! + For when you didn’t combobulate quite right the first time around. + + + + + + + + + Mini-Mage + + + + + + <b>Stealth</b> +<b>Spell Damage +1</b> + + + + + He is sometimes found hiding in the treasure chest in the Gurubashi Arena. + Ben Olson + + + + + + + Dr. Boom + + + + + + + + + <b>Battlecry</b>: Summon two 1/1 Boom Bots. <i>WARNING: Bots may explode.</i> + + + MARVEL AT HIS MIGHT! + Alex Garner + + + + + Boom Bot + + + + + + <b>Deathrattle</b>: Deal 1-4 damage to a random enemy. + + + + + + + + + Mimiron's Head + + + + + + + + + At the start of your turn, if you have at least 3 Mechs, destroy them all and form V-07-TR-0N. + + + + Do not push the big red button! + Trent Kaniuga + + + + + + V-07-TR-0N + + + + + + + + <b>Charge</b> +<b>Mega-Windfury</b> <i>(Can attack four times a turn.)</i> + + + + Chris Seaman + + + + + + Mogor the Ogre + + + + + + + + + All minions have a 50% chance to attack the wrong enemy. + + + Mogor helped reopen the Dark Portal once. You know you're in trouble when you have to rely on an ogre. + Michal Ivan + + + + + + + + Foe Reaper 4000 + + + + + + + Also damages the minions next to whomever he attacks. + + + + + + Foe reaping is really not so different from harvest reaping, at the end of the day. + James Ryman + + + + + Sneed's Old Shredder + + + + + + + + + + + <b>Deathrattle:</b> Summon a random <b>Legendary</b> minion. + + Christopher Moeller + When Sneed was defeated in the Deadmines, his shredder was sold at auction to an anonymous buyer. (Probably Hogger.) + + + + + + 65f42e5f-9f2f-4747-b99c-b29d742fb32b + Toshley + + + + + + + + + <b>Battlecry and Deathrattle:</b> Add a <b>Spare Part</b> card to your hand. + + + Something about power converters. + Zoltan & Gabor + + + + + + + + + Mekgineer Thermaplugg + + + + + + + + + Whenever an enemy minion dies, summon a Leper Gnome. + + + + He was obsessed with explosives until he discovered knitting. Now he yells, “SWEATERS! MORE SWEATERS!” + Trent Kaniuga + + + + + + Gazlowe + + + + + + + + + Whenever you cast a 1-mana spell, add a random Mech to your hand. + + + Gazlowe was voted "Most Likely to Explode" in high school. + Luke Mancini + + + + + + Troggzor the Earthinator + + + + + + + + + Whenever your opponent casts a spell, summon a Burly Rockjaw Trogg. + + + He keeps earthinating the countryside despite attempts to stop him. + Mike Sass + + + + + + d5a9d725-2528-4298-ada5-48816e5fa0f9 + Blingtron 3000 + + + + + + + + + <b>Battlecry:</b> Equip a random weapon for each player. + + + + PREPARE PARTY SERVOS FOR IMMEDIATE DEPLOYMENT. + Jomaro Kindred + + + + + 0865353b-fedc-4a06-93d7-187923a1f808 + Hemet Nesingwary + + + + + + + + + <b>Battlecry:</b> Destroy a Beast. + Destroy a Beast. + + + It's hard to make a living as a hunter in a world where beasts instantly reappear minutes after you kill them. + Ralph Horsley + + + + + + + + Clockwork Giant + + + + + + + + Costs (1) less for each card in your opponent's hand. + + + + He and Mountain Giant don't get along. + Dan Scott + + + + Wee Spellstopper + + + + + + + + Adjacent minions can't be targeted by spells or Hero Powers. + + + + Jonboy Meyers + Bane of spellcasters and spelling bees everywhere. + + + + + Soot Spewer + + + + + + + + + <b>Spell Damage +1</b> + + + + Phil Saunders + Give <b>Spell Damage +2</b>. + The inventor of the goblin shredder is involved in several patent disputes with the inventor of the soot spewer. + + + + + + Overclocked + + + + Spell Damage +2. + + + + + + + 818e1c57-df7b-40cb-b01a-9b33d2724de5 + Armor Plating + + + + Give a minion +1 Health. + + + Nutchapol Thitinunthakorn + + + + + + + Armor Plating + + +1 Health. + + + + + + + 14311ddf-110b-48a6-ab55-6c090b6a1f75 + Time Rewinder + + + + Return a friendly minion to your hand. + + + Nutthapon Petthai + + + + + + + + d7db3a0c-6eec-48d8-bbd4-307ec51189a3 + Rusty Horn + + + + Give a minion <b>Taunt</b>. + + + Peerasak Senalai + + + + + + + + bab507b0-6fab-48ee-99a4-d75c8aed0923 + Finicky Cloakfield + + + + Give a friendly minion <b>Stealth</b> until your next turn. + + + Nutchapol Thitinunthakorn + + + + + + + + + Cloaked + + Stealthed until your next turn. + + + + + + + + 1a5274f2-188c-4688-af79-b8baf66fd289 + Emergency Coolant + + + + <b>Freeze</b> a minion. + + + Peerasak Senalai + + + + + + + + 9e811512-4bb8-4e8d-babe-6bf82c1b648c + Reversing Switch + + + Swap a minion's Attack and Health. + + + Nutthapon Petthai + + + + + + + + Switched + + + Attack and Health have been swapped by Reversing Switch. + + + + + + 19305184-cd49-4e13-92aa-0261507b98fd + Whirling Blades + + + + Give a minion +1 Attack. + + + Nutchapol Thitinunthakorn + + + + + + + Whirling Blades + + + + + +1 Attack. + + + + 6971342d-b99e-44b8-acaa-5aaf4c833aaa + Coren Direbrew + + + + + + + + + + + + + + + + + + + e1279ebf-5a94-4546-81d5-5cb2305de1ed + Coren Direbrew + + + + + + + + + + + + + + + + + + + d6f94668-adec-48b5-be4a-86961df44bed + Pile On! + + + + <b>Hero Power</b> +Put a minion from each deck into the battlefield. + + + + + + + + + 79960d14-67a6-480a-b0bc-b21258f1ba3a + Pile On! + + + + <b>Hero Power</b> +Put two minions from your deck and one from your opponent's into the battlefield. + + + + + + + Dark Iron Bouncer + + + + + + Always wins Brawls. + + + + + 0e9adb3a-a5be-48d0-90da-acee111b693f + Get 'em! + + + + Summon four 1/1 Dwarves with <b>Taunt</b>. + + + + + + Guzzler + + + + + + <b>Taunt</b> + + + + + + + 9554f3c1-4a03-4ddb-bc2e-cb26d371b477 + High Justice Grimstone + + + + + + + + + + f7205807-e735-47e6-9beb-ddd4651e335a + High Justice Grimstone + + + + + + + + + + + + f9463f87-85b8-4352-bd35-29a4a24fb895 + Jeering Crowd + + + + <b>Hero Power</b> +Summon a 1/1 Spectator with <b>Taunt</b>. + + + + + + + + e0dc4e9c-6d71-495b-9b59-fae2ab46585e + Jeering Crowd + + + + <b>Hero Power</b> +Summon a 1/1 Spectator with <b>Taunt</b>. + + + + + + + + Dark Iron Spectator + + + + + + <b>Taunt</b> + + + + + + + d260b101-0507-4b53-9a19-d5347745062c + Emperor Thaurissan + + + + + + + + + + + + b5f06f9b-25ae-48ce-ba79-9d3340b9574f + Emperor Thaurissan + + + + + + + + + + + + + + ef0c07a3-acfe-4115-8737-f1eb27b53707 + Power of the Firelord + + + <b>Hero Power</b> +Deal 30 damage. + + + + + + + + + Moira Bronzebeard + + + + + + Thaurissan's Hero Power can't be used. +Never attacks minions unless they have <b>Taunt</b>. + + + + + + + + + + Moira Bronzebeard + + + + + + Thaurissan's Hero Power can't be used. +Never attacks minions unless they have <b>Taunt</b>. + + + + + + + + + + 54c67bc3-dc92-43a7-a9af-53b3f39d49cf + Garr + + + + + + + + + + 5c9c74e6-6e20-4a63-9fcb-5665c2a7f8ce + Garr + + + + + + + + + + 070fc57a-fe9d-4754-bc3c-d8195a5ff653 + Magma Pulse + + + + <b>Hero Power</b> +Deal 1 damage to all minions. + + + + + + + Firesworn + + + + + + <b>Deathrattle:</b> Deal 1 damage to the enemy hero for each Firesworn that died this turn. + + + + + + + + Firesworn + + + + + + <b>Deathrattle:</b> Deal 3 damage to the enemy hero for each Firesworn that died this turn. + + + + + + + + ee40147a-e1ec-4df3-a31e-edb45ed94592 + Rock Out + + + + Summon 3 Firesworn. <b>Overload:</b> (2) + + + + + + + + 40dddfb0-2ca2-41b9-9fcb-6cc1a42ccc36 + Rock Out + + Summon 3 Firesworn. <b>Overload:</b> (2) + + + + + + + + + + 95bc33a7-ff61-4b5a-9e57-a462f392d097 + Baron Geddon + + + + + + + + + + a3c536c2-92fa-4d8c-86ab-5c55fb7c0efa + Baron Geddon + + + + + + + + + + + + ffa8845e-dc93-48e6-8af1-5faa67c29e49 + Ignite Mana + + + + <b>Hero Power</b> +Deal 5 damage to the enemy hero if they have any unspent Mana. + + + + + + + 2a8c8aa0-80bd-47fb-b192-2b290d883894 + Ignite Mana + + + + <b>Hero Power</b> +Deal 10 damage to the enemy hero if they have any unspent Mana. + + + + + + + 80c76d4a-3e10-4683-9b4e-bd84b879da73 + Living Bomb + + + + Choose an enemy minion. If it lives until your next turn, deal $5 damage to all enemies. + + + + + + + + + + Living Bomb + + + On Geddon's turn, deal 5 damage to all of your stuff. + + + + + + + + b2bb76b0-f428-4223-9f11-d16a7f4f6bd9 + Living Bomb + + + + Choose an enemy minion. If it lives until your next turn, deal $10 damage to all enemies. + + + + + + + + + + Living Bomb + + + On Geddon's turn, deal 10 damage to all of your stuff. + + + + + + + + 2ee5dfdf-c312-46d9-9cf5-85bdd4c39ff7 + Majordomo Executus + + + + + + + + + + + + 874ed53e-6890-48e9-95e9-0ea0adae0308 + Majordomo Executus + + + + + + + + + + + + + + f4c81693-7c4d-45a1-8ef9-6917911d203d + The Majordomo + + + <b>Hero Power</b> +Summon a 1/3 Flamewaker Acolyte. + + + + + + + + + 12251dfc-74ef-4ff9-9c2e-7ae9d017d0d3 + The Majordomo + + + + <b>Hero Power</b> +Summon a 3/3 Flamewaker Acolyte. + + + + + + + + Ragnaros the Firelord + + + + + + + + + Ragnaros the Firelord + + + + + + + + + Flamewaker Acolyte + + + + + + + + + + Flamewaker Acolyte + + + + + + + + 7d79047d-fbed-40df-a194-6e46156778f9 + Highlord Omokk + + + + + + + + + + c8be0380-3f9b-4361-82f3-1284f7db2d2d + Highlord Omokk + + + + + + + + + + + + fe01db75-4d40-43ce-9ab3-afe66a093f51 + ME SMASH + + + + <b>Hero Power</b> +Destroy a random damaged enemy minion. + + + + + + + + + 44102aa4-f170-48fa-b3e1-e0bb0fc6ae74 + ME SMASH + + + <b>Hero Power</b> +Destroy a random enemy minion. + + + + + + + + + dd39ab0e-7ac7-4eaf-af92-581f9871daa5 + TIME FOR SMASH + + + + Deal $5 damage to a random enemy. Gain 5 Armor. + + + + + + b4413efa-09db-4e4c-b854-406d3e6c4673 + General Drakkisath + + + + + + + + + + 98308fab-323c-4fd2-b08f-c901cc34df88 + General Drakkisath + + + + + + + + + + + + Intense Gaze + + + <b>Passive Hero Power</b> +All cards cost (1). Players are capped at 1 Mana Crystal. + + + + + + + Intense Gaze + + + <b>Passive Hero Power</b> +All cards cost (1). You are capped at 2 Mana Crystals, and opponent at 1. + + + + + + + 604e89d6-32b3-472a-aec0-bbb4fb7537f7 + Drakkisath's Command + + + Destroy a minion. Gain 10 Armor. + + + + + + + + + + 6bfe29cd-346b-4f54-9b21-c612756093c9 + Rend Blackhand + + + + + + + + + + d64b3601-76df-450c-8fc3-684a964f944a + Rend Blackhand + + + + + + + + + + + + aa626ce8-ab2a-4a35-a092-57b2eb442ddf + Open the Gates + + + + <b>Hero Power</b> +Summon three 1/1 Whelps. Get a new Hero Power. + + + + + + + + + + 9fd797eb-fd9c-4340-87e2-9d6de647f3c9 + Open the Gates + + + + <b>Hero Power</b> +Summon three 2/2 Whelps. Get a new Hero Power. + + + + + + + + Whelp + + + + + + + + + Whelp + + + + + + + + + 9fe0c819-ecaa-482a-9620-1d79d9c3704d + Old Horde + + + + <b>Hero Power</b> +Summon two 1/1 Orcs with <b>Taunt</b>. Get a new Hero Power. + + + + + + + + + + + 3b132f3e-934f-463a-a51f-2cd8da85a332 + Old Horde + + + + <b>Hero Power</b> +Summon two 2/2 Orcs with <b>Taunt</b>. Get a new Hero Power. + + + + + + + + + Old Horde Orc + + + + + + <b>Taunt</b> + + + + + + + Old Horde Orc + + + + + + <b>Taunt</b> + + + + + + + 8bc6797a-9f59-4296-bb22-c83b39718b34 + Blackwing + + + + <b>Hero Power</b> +Summon a 3/1 Dragonkin. Get a new Hero Power. + + + + + + + + + + + 2011d103-a35d-4ead-814e-74216704d1d3 + Blackwing + + + + <b>Hero Power</b> +Summon a 5/4 Dragonkin. Get a new Hero Power. + + + + + + + + + Dragonkin + + + + + + + + + Dragonkin + + + + + + + + + + + 0df65e31-a6ef-4c20-8e8d-6b0d0a605146 + Dismount + + + + <b>Hero Power</b> +Summon Gyth. Get a new Hero Power. + + + + + + + + + + + 6ca746fe-d2cc-4b4d-8012-63a191f0db84 + Dismount + + + + <b>Hero Power</b> +Summon Gyth. Get a new Hero Power. + + + + + + + + + Gyth + + + + + + + + + + + Gyth + + + + + + + + + + + 37fea072-9df1-4f7f-8d6a-8f51a9f58e8b + The True Warchief + + + + Destroy a Legendary minion. + + + + + + + + + + + 3fb1f31d-0438-42ae-883c-42dc8c1c023f + Razorgore the Untamed + + + + + + + + + + + + ec759b8b-a558-4911-a585-9547d0acf521 + Razorgore the Untamed + + + + + + + + + + + + + + 350cc9eb-d144-40d0-8873-569295307a62 + The Rookery + + + <b>Hero Power</b> +Give all Corrupted Eggs +1 Health, then summon one. + + + + + + + + Incubation + + + Increased Health. + + + + + + 80ee41b9-c501-4fb4-9fba-cb9373865145 + The Rookery + + + <b>Hero Power</b> +Give all Corrupted Eggs +1 Health, then summon one. + + + + + + + + Corrupted Egg + + + + + + + + When this minion has 4 or more Health, it hatches. + + + + + + + + + + + + Corrupted Egg + + + + + + When this minion has 5 or more Health, it hatches. + + + + + + + + + + + + + + Chromatic Drake + + + + + + + + + + + Chromatic Drake + + + + + + + + + + + Razorgore's Claws + + + + + + Whenever a Corrupted Egg dies, gain +1 Attack. + + + + + + + Blind With Rage + + + Increased Attack. + + + + + + d1030573-ce30-42c8-bb5b-303d96755257 + Vaelastrasz the Corrupt + + + + + + + + + + + + faf6af81-9d6b-44f0-b2f4-2d751d82ed4f + Vaelastrasz the Corrupt + + + + + + + + + + + + + + 7dced09a-4f67-486b-a5c3-b1ab9005acd2 + Essence of the Red + + + + <b>Hero Power</b> +Each player draws 2 cards. + + + + + + + 1096e7c9-1be5-42b5-ac00-4eeb7b67cce3 + Essence of the Red + + + + <b>Hero Power</b> +Each player draws 3 cards. Gain a Mana Crystal. + + + + + + + b10fc00b-532b-4d32-b7cd-7b8e77ee81ae + Burning Adrenaline + + + + Deal $2 damage to the enemy hero. + + + + + + 0b8039a0-ce0e-452e-93f9-12b0b1d1127a + Chromaggus + + + + + + + + + + + + a610db33-fafe-47c2-85c5-82f4fd460d08 + Mutation + + + + <b>Hero Power</b> +Discard a random card. + + + + + + 7bac0cab-af55-4e4a-b8a4-2a00d8f5cdfe + Chromaggus + + + + + + + + + + Brood Affliction + + + + <b>Hero Power</b> +At the end of your turn, add a Brood Affliction card to your opponent's hand. + + + + + + + + + + + + + Brood Affliction + + + <b>Hero Power</b> +At the end of your turn, add a Brood Affliction card to your opponent's hand. + + + + + + + + + + + + + + Brood Affliction: Red + + + + While this is in your hand, take 1 damage at the start of your turn. + + + + + + + + + + Brood Affliction: Red + + While this is in your hand, take 3 damage at the start of your turn. + + + + + + + + + + + + Brood Affliction: Green + + + + While this is in your hand, restore 2 health to your opponent at the start of your turn. + + + + + + + + Brood Affliction: Green + + + + + + While this is in your hand, restore 6 health to your opponent at the start of your turn. + + + + + + Brood Affliction: Blue + + + + While this is in your hand, Chromaggus' spells cost (1) less. + + + + + + + Brood Affliction: Blue + + While this is in your hand, Chromaggus' spells cost (3) less. + + + + + + + + + Brood Affliction: Black + + + + While this is in your hand, whenever Chromaggus draws a card, he gets another copy of it. + + + + + + + + + Brood Affliction: Black + + + + While this is in your hand, whenever Chromaggus draws a card, he gets another copy of it. + + + + + + + + + Brood Affliction: Bronze + + + + While this is in your hand, Chromaggus' minions cost (1) less. + + + + + + + Brood Affliction: Bronze + + + + While this is in your hand, Chromaggus' minions cost (3) less. + + + + + + + e87a8ec4-473a-4955-841a-c59b4114db56 + Chromatic Mutation + + + + Transform a minion into a 2/2 Chromatic Dragonkin. + + + + + + + + + Chromatic Dragonkin + + + + + + + + Whenever your opponent casts a spell, gain +2/+2. + + + + + + + Draconic Lineage + + + +2/+2 + + + + Chromatic Dragonkin + + + + + + 10cdad5b-beed-41c5-9f6d-42cdce64858e + Lord Victor Nefarius + + + + + + + + + + 4682b0eb-f696-4647-a8ff-7e7dff9dee13 + Lord Victor Nefarius + + + + + + + + + + bee1bdc9-9540-4c1f-bcbd-972ea15027d8 + True Form + + + + <b>Hero Power</b> +Let the games begin! + + + + + + + + + + + fd31fe74-bfa2-4d76-97da-2e538c3e75a5 + True Form + + + + <b>Hero Power</b> +Let the games begin! + + + + + + + + + + + Nefarian + + + + + + + + + + + + + + + + + + + + + Nefarian + + + + + + + + + + + + + + + + + + + + + + + 1a6e8244-6019-496f-a357-42f4df3034d8 + Wild Magic + + + + <b>Hero Power</b> +Put a random spell from your opponent's class into your hand. + + + + + + + 0b4d639e-c33d-465b-9f6c-2757516be108 + Wild Magic + + + + <b>Hero Power</b> +Put a random spell from your opponent's class into your hand. + + + + + + + 597eab8c-4e6f-4fb9-b930-494a0da85c15 + Son of the Flame + + + + + + <b>Battlecry:</b> Deal 6 damage. + Deal 6 damage. + + + + + + + + + Living Lava + + + + + + <b>Taunt</b> + + + + + + + Whirling Ash + + + + + + <b>Windfury</b> + + + + + + + 65723ea7-1788-4e75-826a-86ea5f890191 + DIE, INSECT! + + + + Deal $8 damage to a random enemy. + + + + + + + 2513c534-19c6-4f07-82b5-b61dcdb8028e + Omnotron Defense System + + + + + + + + + + d858fa55-5f1c-4e51-a36a-94b364337800 + Activate! + + + + <b>Hero Power</b> +Activate a random Tron. + + + + + + + + + + 8051c077-c344-4ec2-aa6f-6d8c8722c83f + Activate! + + + + <b>Hero Power</b> +Activate a random Tron. + + + + + + + + + + 777fbb47-06e6-47d2-93a2-2fe8517f20c0 + Recharge + + + + Fill all empty Mana Crystals. + + + + + + Magmaw + + + + + + <b>Taunt</b> + + + + + + + + + c34c83a3-93d9-4f36-80be-2a558b0f472d + Omnotron Defense System + + + + + + + + + + + + 660dbf43-c558-4f66-bb9a-d82c67d81462 + Activate Arcanotron + + + <b>Hero Power</b> +Activate Arcanotron! + + + + + + + + 556b4d71-1430-444c-ae80-b03da48815b3 + Activate Arcanotron + + + + <b>Hero Power</b> +Activate Arcanotron! + + + + + + + Arcanotron + + + + + + + Both players have <b>Spell Damage +2</b>. + + + + + + + + + edbbc200-9f54-4146-8c65-09227a2c562f + Activate Toxitron + + + + <b>Hero Power</b> +Activate Toxitron! + + + + + + + e31744fe-25bb-4ef2-9c40-c42e76f557ba + Activate Toxitron + + + + <b>Hero Power</b> +Activate Toxitron! + + + + + + + Toxitron + + + + + + + At the start of your turn, deal 1 damage to all other minions. + + + + + + + + + + Toxitron + + + + + + + At the start of your turn, deal 1 damage to all other minions. + + + + + + + + + + 4d6e8bc3-894b-484e-9f5f-7832a5c1aef7 + Activate Electron + + + + <b>Hero Power</b> +Activate Electron! + + + + + + + 9f991fec-7855-4678-bc35-ca5d56890079 + Activate Electron + + + + <b>Hero Power</b> +Activate Electron! + + + + + + + Electron + + + + + + + All spells cost (3) less. + + + + + + + + + Electron + + + + + + All spells cost (3) less. + + + + + + + + + 32536bac-b190-4049-9680-5e61c29a97c6 + Activate Magmatron + + + + <b>Hero Power</b> +Activate Magmatron! + + + + + + + 74309a43-a600-4173-8e00-83ff9f22c9b8 + Activate Magmatron + + + + <b>Hero Power</b> +Activate Magmatron! + + + + + + + Magmatron + + + + + + + Whenever a player plays a card, Magmatron deals 2 damage to them. + + + + + + + + + + + + Magmatron + + + + + + + Whenever a player plays a card, Magmatron deals 2 damage to them. + + + + + + + + + + 0ebacc1c-f3de-446a-8dc7-47c0bc073568 + Maloriak + + + + + + + + + + 7cf1084f-2297-47c8-8265-fe2a8b9f6f72 + Maloriak + + + + + + + + + + + + The Alchemist + + + <b>Passive Hero Power</b> +Whenever a minion is summoned, swap its Attack and Health. + + + + + + + + The Alchemist + + + <b>Passive Hero Power</b> +Minions' Attack and Health are swapped. +Your minions have +2/+2. + + + + + + + + Potion of Might + + + +2/+2. + + + + + + 089955fc-c537-47c4-b637-8970b88f5624 + Release the Aberrations! + + + Summon 3 Aberrations. + + + + + + + + + Aberration + + + + + + <b>Charge</b> + + + + + + + 45567c70-465b-4b4d-a7ab-97738a16147f + Atramedes + + + + + + + + + + + + + + f80ca878-4d74-4e9a-a01e-af66f0bf3bb3 + Atramedes + + + + + + + + + + + + + + d2d44bc1-d175-470b-a841-cde630f2370d + Echolocate + + + <b>Hero Power</b> +Equip a weapon that grows as your opponent plays cards. + + + + + + + + 02af5cf0-fc57-483c-82ea-b165e30252c0 + Echolocate + + + + <b>Hero Power</b> +Equip a weapon that grows as your opponent plays cards. + + + + + + + fd8a6c09-b8c8-4a0b-a5e4-eb3b61bc6a3d + Sonic Breath + + + + Deal $3 damage to a minion. Give your weapon +3 Attack. + + + + + + + + + + Sonic Breath + + + +3 Attack. + + + + + + eb6493ff-a0e8-4634-a634-9a427740917d + Reverberating Gong + + + + Destroy your opponent's weapon. + + + + + + + + Dragonteeth + + + + + Whenever your opponent plays a card, gain +1 Attack. + + + + + + + + + I hear you... + + + Increased Attack. + + + + + + 905b653f-8229-453e-9e00-d805568f73e0 + Nefarian + + + + + + + + + + + + + + + + + + + + + + + + e5e3d51e-b8d5-4c5b-aa65-3f5303b977c5 + Nefarian + + + + + + + + + + + + + + + + + + + + + + + + Onyxia + + + + + + + + + + + Onyxia + + + + + + + + + + + a9caf980-9937-4515-9ff6-8c36eabbdb55 + LAVA! + + + + Deal $2 damage to all minions. + + + + + + 3298364c-abcc-4613-ba1e-1ab4da0ed345 + Bone Minions + + + + <b>Hero Power</b> +Summon two 2/1 Bone Constructs. + + + + + + + + f5249391-0311-404a-9b7e-1a3b4b08e657 + Bone Minions + + + + <b>Hero Power</b> +Summon two 4/2 Bone Constructs. + + + + + + + + Bone Construct + + + + + + + + + + Bone Construct + + + + + + + + Chromatic Prototype + + + + + + <b>Taunt</b> + + + + + + + 6071a0fe-9295-4287-bf30-5d4220362c0b + Nefarian Strikes! + + + <b>Hero Power</b> +Nefarian rains fire from above! + + + + + + + + + + 2252cf25-2e72-48c8-bf8f-b535690fb82a + Nefarian Strikes! + + + + <b>Hero Power</b> +Nefarian rains fire from above! + + + + + + + Onyxiclaw + + + + + + + + 102e2f97-d5e0-438b-9c17-ee104c65f346 + Flameheart + + + + Draw 2 cards. +Gain 4 Armor. + + + + + + d108222b-8e61-4b5c-8f39-085e495e3a0e + Solemn Vigil + + + + + + + Draw 2 cards. Costs (1) less for each minion that died this turn. + + + Each year, folk gather in front of Blackrock Mountain to mourn those who were mind-controlled into the lava. + Jaime Jones + Crafting unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + Unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + + + + + Melt + + + + Attack changed to 0 this turn. + + + + + + + + Flamewaker + + + + + + + + + After you cast a spell, deal 2 damage randomly split among all enemies. + + + Flamewakers HATE being confused for Flamewalkers. They just wake up fire, they don’t walk on it. Walking on fire is CRAZY. + Alex Horley Orlandelli + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + + Dragon's Breath + + + + + + + Deal $4 damage. Costs (1) less for each minion that died this turn. + + + Dragons breathe fire, sure, but did you know they can also breathe Cotton Candy? It's harder to give them a reason to do that, though. + Mauricio Herrera + Crafting unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + Unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + + + + + + + Dragon's Might + + + + Costs (3) less this turn. + + + + + + + + 77f9c4bd-752c-434d-a7a1-8a4cc05a269d + Twilight Whelp + + + + + + + + + <b>Battlecry:</b> If you're holding a Dragon, gain +2 Health. + + + + The twilight whelps are basically magic-vampires. Despite this, they are not a reference to any popular series of novels. + Sam Nielson + Crafting unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + Unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + + + + + + Twilight Endurance + + + Increased Health. + + + + + + Whelp + + + + + + + + + + c06cfe2a-7e57-44ae-b876-b82fda0598c9 + Demonwrath + + + + + + + Deal $2 damage to all non-Demon minions. + + + Demons are not angry most of the time. You have to play this card in order to really bring it out of them. + Raymond Swanland + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + Imp Gang Boss + + + + + + + + + Whenever this minion takes damage, summon a 1/1 Imp. + + + + His imp gang likes to sneak into Stormwind to spraypaint "Ragnaros Rulez" on the Mage Tower. + Steve Prescott + Crafting unlocked in Molten Core, in the Blackrock Mountain adventure. + Unlocked in Molten Core, in the Blackrock Mountain adventure. + + + + + + Imp + + + + + + + + + + 30e432f2-6a20-43ff-920c-c6b49b3ed261 + Gang Up + + + + + + + Choose a minion. Shuffle 3 copies of it into your deck. + + + If you are thinking about visiting Moonbrook, you better roll deep. + Jim Nelson + Crafting unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + Unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + + + + + + + f8986e64-348f-477e-988f-180c1697150e + Dark Iron Skulker + + + + + + + + + <b>Battlecry:</b> Deal 2 damage to all undamaged enemy minions. + + + He loves skulking. He skulks after hours just for the joy of it, but his friends are pretty worried he'll get burnt out. + Eric Braddock + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + a89e833a-4236-485d-918e-e47d13e9b1b3 + Volcanic Lumberer + + + + + + + <b>Taunt</b> +Costs (1) less for each minion that died this turn. + + + + + The roots, the roots, the roots is on fire! + Trent Kaniuga + Crafting unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + Unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + + + + + + + 10fbe3df-54e2-43ec-aa23-fa7f8091faf6 + Druid of the Flame + + + + + + + + + <b>Choose One</b> - Transform into a 5/2 minion; or a 2/5 minion. + + + Druids who fought too long in Northrend were easily seduced by Ragnaros; a mug of hot chocolate was generally all it took. + Stanley Lau + Crafting unlocked in Molten Core, in the Blackrock Mountain adventure. + Unlocked in Molten Core, in the Blackrock Mountain adventure. + + + + + 029c40d0-0087-4dc6-93cd-d9ee871c04ea + Firecat Form + + + + + Transform into a 5/2 minion. + + + + + + + 21261a4a-b830-42d1-b02f-b003820815dc + Fire Hawk Form + + + + + Transform into a 2/5 minion. + + + + + + + Druid of the Flame + + + + + + + + + Ben Zhang + + + Druid of the Flame + + + + + + + + + Hideaki Takamura + + + c2f09ca9-5327-4123-80cf-93ab98b3c4cd + Lava Shock + + + + + + + Deal $2 damage. +Unlock your <b>Overloaded</b> Mana Crystals. + + + Chocolate lava cake is shockingly delicious. + Zoltan Boros + Crafting unlocked in Molten Core, in the Blackrock Mountain adventure. + Unlocked in Molten Core, in the Blackrock Mountain adventure. + + + + + + Lava Shock + + + + Cards you play this turn don't cause <b>Overload</b>. + + + + + + + + 8e9b14dc-7937-49ba-a14c-cd7075c32aa1 + Fireguard Destroyer + + + + + + + + + <b>Battlecry:</b> Gain 1-4 Attack. <b>Overload:</b> (1) + + + Ragnaros interviews hundreds of Fire Elementals for the position of "Destroyer" but very few have what it takes. + Paul Mafayon + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + + + On Fire! + + + + + Increased Attack. + + + + bb198bde-42b9-4831-a6af-73be0e748aa8 + Quick Shot + + + + + + + Deal $3 damage. +If your hand is empty, draw a card. + + + Han shot first. + Jonboy Meyers + Crafting unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + Unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + + + + + + + + 50e2844d-425b-43df-8927-b06066dd65a4 + Core Rager + + + + + + + + + <b>Battlecry:</b> If your hand is empty, gain +3/+3. + + + + It takes a special kind of hunter to venture deep into a firey lava pit and convince a monster who lives there to come home and be a cuddly housepet. + Jomaro Kindred + Crafting unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + Unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + + + + + + Power Rager + + + +3/+3 + + + + + + + 8723c146-b0ef-49ca-8d4e-8bed192ccc09 + Revenge + + + + + + Deal $1 damage to all minions. If you have 12 or less Health, deal $3 damage instead. + + + + This is better than Arcane Explosion, so I guess warriors are finally getting revenge on mages for Mortal Strike being worse than Fireball. + Ben Olson + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + Axe Flinger + + + + + + + + + Whenever this minion takes damage, deal 2 damage to the enemy hero. + + + Once a lowly "Stick Flinger", he's been relentless on the path to his ultimate dream: "Tauren Flinger". + Efrem Palacios + Crafting unlocked in Molten Core, in the Blackrock Mountain adventure. + Unlocked in Molten Core, in the Blackrock Mountain adventure. + + + + + + 307341a9-9e63-422b-b3e0-64520504ee7f + Resurrect + + + + + + + Summon a random friendly minion that died this game. + + + I walked into the dungeon and noticed a slain adventurer. In his final moments, he had scrawled out a message in the dust on the wall beside him. Two words: "rez plz" + Luke Mancini + Crafting unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + Unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + + + + + + + cb922037-0640-489f-a62c-5f00a606f6d9 + Dragon Consort + + + + + + + + + <b>Battlecry:</b> The next Dragon you play costs (2) less. + + + + Everybody wants someone to snuggle with. Even giant armored scaly draconic beasts of destruction. + Raymond Swanland + Crafting unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + Unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + + + + + Unchained! + + + + Your next Dragon costs (2) less. + + + + + + + + Grim Patron + + + + + + + + Whenever this minion survives damage, summon another Grim Patron. + + + If you love getting your face punched, come to the Grim Guzzler! + Bobby Chiu + Crafting unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + Unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + + + + + + + Dragonkin Sorcerer + + + + + + + Whenever <b>you</b> target this minion with a spell, gain +1/+1. + + + + + Dragonkin Sorcerers be all "I'm a wizard" and everyone else be all "daaaaang". + Edouard Guiton & Stuido HIVE + Crafting unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + Unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + + + + + + Draconic Power + + + Increased stats. + + + + + + Dragon Egg + + + + + + + + Whenever this minion takes damage, summon a 2/1 Whelp. + + + Think of them as bullets for your dragon gun. + Jaemin Kim + Crafting unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + Unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + + + + + + + Black Whelp + + + + + + + + + + Jaemin Kim + + + Drakonid Crusher + + + + + + + + <b>Battlecry:</b> If your opponent has 15 or less Health, gain +3/+3. + + + + Drakonids were created to have all the bad parts of a dragon in the form of a humaniod. But, like, why? + Slawomir Maniak + Crafting unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + Unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + + + + + + Large Talons + + +3/+3. + + + + + + + Volcanic Drake + + + + + + + + + + + Costs (1) less for each minion that died this turn. + Volcanic Drakes breathe lava instead of fire. The antacid vendor at Thorium Point does a brisk business with them. + Lucas Graciano + Unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + Crafting unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + + + + b4fdb4df-17ae-45fd-a77a-31ea2cbf9169 + Hungry Dragon + + + + + + + <b>Battlecry:</b> Summon a random 1-Cost minion for your opponent. + + + + + Hungry Hungry Dragon is NOT a fun game. + John Polidora + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + Majordomo Executus + + + + + + + + + <b>Deathrattle:</b> Replace your hero with Ragnaros, the Firelord. + + + You thought Executus turned you into Ragnaros, but really Ragnaros was in you the whole time. + Alex Horley Orlandelli + Crafting unlocked in Molten Core, in the Blackrock Mountain adventure. + Unlocked in Molten Core, in the Blackrock Mountain adventure. + + + + + + Ragnaros the Firelord + + + + + + + + cd017d6f-ce26-4684-8084-2d20f6206b26 + DIE, INSECT! + + + + <b>Hero Power</b> +Deal $8 damage to a random enemy. + + + + + + b3116152-764c-46b9-a42a-5f9b5861aa15 + DIE, INSECTS! + + + + <b>Hero Power</b> +Deal $8 damage to a random enemy. TWICE. + + + + + + Emperor Thaurissan + + + + + + + + + At the end of your turn, reduce the Cost of cards in your hand by (1). + + + His second greatest regret is summoning an evil Firelord who enslaved his entire people. + Wayne Reynolds + Crafting unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + Unlocked in Blackrock Depths, in the Blackrock Mountain adventure. + + + + + + Imperial Favor + + + Costs (1) less. + + + + + + + + b73f789f-49d4-4ce7-9575-7dac07d943c5 + Rend Blackhand + + + + + + + <b>Battlecry:</b> If you're holding a Dragon, destroy a <b>Legendary</b> minion. + Destroy a Legend. + + + + + Rend believes he is the True Warchief of the Horde and he keeps editing the wikipedia page for "Warchief of the Horde" to include his picture. + Alex Horley + Crafting unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + Unlocked in Blackrock Spire, in the Blackrock Mountain adventure. + + + + + + + + + + 53314cea-d1cd-4427-b81f-3656d2483a6a + Nefarian + + + + + + + + + <b>Battlecry:</b> Add 2 random spells to your hand <i>(from your opponent's class)</i>. + + + + They call him "Blackwing" because he's a black dragon...... and he's got wings. + Ruan Jia + Crafting unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + Unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + + + + + 08f9c982-ce76-4607-811e-8be046b930d8 + Tail Swipe + + + + + + Deal $4 damage. + + + + + + Chromaggus + + + + + + + + + Whenever you draw a card, put another copy into your hand. + + + + Left head and right head can never agree about what to eat for dinner, so they always end up just eating ramen again. + Todd Lockwood + Crafting unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + Unlocked in Blackwing Lair, in the Blackrock Mountain adventure. + + + + + + 26d8ee9b-29bd-4623-a247-a9ca4febbabe + Blackwing Technician + + + + <b>Battlecry:</b> If you're holding a Dragon, gain +1/+1. + + + + + + + + This is who you go to when your Blackwing needs a tune up. Don't go to a cut rate Blackwing tune up shop! + Matt Dixon + Crafting unlocked in Molten Core, in the Blackrock Mountain adventure. + Unlocked in Molten Core, in the Blackrock Mountain adventure. + + + + + + Dragon Blood + + + +1/+1 + + + + + + a86449fe-3ea4-4fee-97cb-ea8df777e2b1 + Blackwing Corruptor + + + + + + + + <b>Battlecry</b>: If you're holding a Dragon, deal 3 damage. + + + + He got his name when he gave Blackwing some comic books and rock & roll records. + Greg Staples + Deal 3 damage. + Crafting unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + Unlocked in Hidden Laboratory, in the Blackrock Mountain adventure. + + + + + + + + Druid of the Flame + + + + + + + + + + + + + 7741f56d-95c5-424c-9586-266a51d27290 + Flame Lance + + + + + + + Deal $8 damage to a minion. + + + It's on the rack next to ice lance, acid lance, and English muffin lance. + Nutthapon Petchthai + + + + + + + Effigy + + + + + + + <b>Secret:</b> When a friendly minion dies, summon a random minion with the same Cost. + + + Burning man, brah. + Tooth + + + + + + Fallen Hero + + + + + + + + + Your Hero Power deals 1 extra damage. + + + And he can't get up. + Arthur Bozonnet + + + + + f11c4a8c-558a-4323-91ec-8f818c03d5f8 + Arcane Blast + + + + + + + Deal $2 damage to a minion. This spell gets double bonus from <b>Spell Damage</b>. + + + Now with 100% more blast! + Gabor Szikszai + + + + + + + + + a5f78a46-efd4-4aa6-ae66-7435ffa0a305 + Polymorph: Boar + + + + + + + Transform a minion into a 4/2 Boar with <b>Charge</b>. + + + It's always Huffer. + Mike Sass + + + + + + + Boar + + + + + + + <b>Charge</b> + + + + + + + Dalaran Aspirant + + + + + + + + + <b>Inspire:</b> Gain <b>Spell Damage +1</b>. + + + Is he aspiring or inspiring? Make up your mind! + Dan Scott + + + + + + Power of Dalaran + + + + Increased Spell Damage. + + + + + + 458cde43-7a80-4976-ac8f-d0adf0f6004d + Spellslinger + + + + + + + <b>Battlecry:</b> Add a random spell to each player's hand. + + + + + Does he sling spells, or do his spells linger about. Who can say? + Andrew Hou + + + + + Coldarra Drake + + + + + + + + + You can use your Hero Power any number of times. + + + + Christopher Moeller + The Grand Tournament has a "No dragons allowed" policy, but it's rarely enforced. + + + + Rhonin + + + + + + + + + <b>Deathrattle:</b> Add 3 copies of Arcane Missiles to your hand. + + + + A masterless shamurai. + Zoltan & Gabor + + + + + + ebf76925-9074-4662-8456-816ffdb4f802 + Ram Wrangler + + + + + + + <b>Battlecry:</b> If you have a Beast, summon a +random Beast. + + + + + Not getting trampled is really the trick here. + Brandon Kitkouski + + + + + + Holy Champion + + + + + + + + + Whenever a character is healed, gain +2 Attack. + + + She really likes seeing people get better. That's why she hurts them in the first place. + Alex Garner + + + + + + Light's Blessing + + + Increased Attack. + + + + + + + Spawn of Shadows + + + + + + + + + <b>Inspire:</b> Deal 4 damage to each hero. + + + What did you expect to happen? He's a Spawn. Of Shadows. + Dave Allsop + + + + + + 4b4405d0-3cbf-4e93-9921-1cf1a1148694 + Power Word: Glory + + + + + + + Choose a minion. Whenever it attacks, restore 4 Health to +your hero. + + + The promise of glory is a powerful tool to get minions to do your bidding. Only slightly less powerful than the promise of an ice cream bar! + Mike Sass + + + + + + + Power Word: Glory + + + When this attacks, restore 4 Health to the hero of the player who buffed it. + + + + + + + + Shadowfiend + + + + + + + + + Whenever you draw a card, reduce its Cost by (1). + + + Hopes to be promoted to "Shadowfriend" someday. + Warren Mahy + + + + + + Shadowfiended + + + + Costs (1) less. + + + + + + + + 344072c0-2a33-44f8-b108-d3860de53bc9 + Convert + + + + + + + Put a copy of an enemy minion into your hand. + + + "Are you interested in... HEALTH benefits?!" + Dan Dos Santos + + + + + + + + 3b685b03-94e0-43f1-afb3-cb4fc2a53cfc + Confuse + + + + + + + Swap the Attack and Health of all minions. + + + This minion is really powerful! + Sean O'Danield + + + + Confused + + + + Swapped Attack and Health. + + + + + + 32770142-420e-4049-9b63-ba4c6354dea1 + Twilight Guardian + + + + + + + + <b>Battlecry:</b> If you're holding a Dragon, gain +1 Attack and <b>Taunt</b>. + + + + A result of magical experiments carried out by the Black Dragonflight, it's not his fault that he's a vicious killer. + Slawomir Maniak + + + + + + + Twilight's Embrace + + + +1 Attack and <b>Taunt</b>. + + + + + + Confessor Paletress + + + + + + + + + + <b>Inspire:</b> Summon a random <b>Legendary</b> minion. + + + She sees into your past and makes you face your fears. Most common fear: Getting Majordomo out of Sneed's Old Shredder. + Chris Rahn + + + + + + Dreadsteed + + + + + + + <b>Deathrattle:</b> Summon a Dreadsteed. + + + + + + Crescendo himself summoned this steed, riding it to victory in the Grand Tournament. Wherever he rides, an army of riders ride behind him, supporting the legendary champion. + Alex Horley Orlandelli + + + + + + Fearsome Doomguard + + + + + + + + + + + + They were originally called Cuddleguards, but they were not inspiring the proper amount of fear. + Anton Zemskov + + + Tiny Knight of Evil + + + + + + + + + Whenever you discard a card, gain +1/+1. + + + + "No, no, no. I asked for a tiny JESTER of evil." + Raymond Swanland + + + + + + Felrage + + + + Increased stats. + + + + + + f8b76a76-b53d-4ae0-abdb-91e44608e148 + Fist of Jaraxxus + + + + + + + When you play or discard this, deal $4 damage to a random enemy. + + + * Not actually Jaraxxus' fist. + Matt Dixon + + + + + + + Void Crusher + + + + + + + + + <b>Inspire:</b> Destroy a random minion for each player. + + + + We like to call him "Wesley". + Skan Srisuwan + + + + + + 8303fdfd-b09e-4c44-afc1-a627fdad9866 + Demonfuse + + + + + + + + + Give a Demon +3/+3. Give your opponent a Mana Crystal. + Very dangerous when attached to a demonbomb. + Kevin Chen + + + + + + + + Dark Fusion + + + +3/+3. + + + + + + ca58425e-25d7-4dc3-aa3e-df8bcc8bdff2 + Dark Bargain + + + + + + + Destroy 2 random enemy minions. Discard 2 random cards. + + + A prime example of lose-lose negotiating. + Paul Mafayon + + + + + + Wrathguard + + + + + + + + + Whenever this minion takes damage, also deal that amount to your hero. + + + + After playing against 5 Annoy-O-Trons, any normal guard will become a Wrathguard. + Sojin Hwang + + + + + + Wilfred Fizzlebang + + + + + + + + + + Cards you draw from your Hero Power cost (0). + + + He can summon anything, even a FEARSOME DOOMGUARD*. + +*He's pretty sure this is going to work out. + Tooth + + + + + Master Summoner + + + + Costs (0). + + + + + + + + 8e69a47e-c5a6-4ade-9ffd-676594719191 + Shado-Pan Rider + + + + + + + + + <b>Combo:</b> Gain +3 Attack. + + + He needed a break after that business in the Vale of Eternal Blossoms. Naturally, he chose to spend his vacation in an icy snowscape killing monsters. + Ryan Metcalf + + + + + Chi Lance + + + +3 Attack. + + + + + + Buccaneer + + + + Whenever you equip a weapon, give it +1 Attack. + + + + + + + + + The best part of buccaneering is the pants. + Matt Dixon + + + + + + Extra Stabby + + + +1 Attack + + + + + + 14bbe956-0711-4a82-b620-0b4121c1de17 + Undercity Valiant + + + + + + + + + <b>Combo:</b> Deal 1 damage. + + + Almost went to play for Stormwind before signing with Undercity. + Deal 1 damage. + Zoltan Boros + + + + + + + Cutpurse + + + + + + + + + Whenever this minion attacks a hero, add the Coin to your hand. + + + He has a giant collection of purses now. One for every outfit! + Alex Horley Orlandelli + + + + + + 562ba226-53fc-44cd-bb63-cf14f3d2a3f5 + Shady Dealer + + + + + + + + + <b>Battlecry:</b> If you have a Pirate, gain +1/+1. + + + I have great deal for you... for 4 damage to your face! + Tooth + + + + + + Shady Deals + + + + +1/+1. + + + + + + 300bf071-bcd0-4759-bf11-f4ec4fefb2ec + Burgle + + + + + + + Add 2 random class cards to your hand <i>(from your opponent's class)</i>. + + + Yoink! + Matt Dixon + + + + Poisoned Blade + + + + + + + + Your Hero Power gives this weapon +1 Attack instead of replacing it. + + + + How much more poisoned can a blade get? The answer is a lot. A lot more poisoned. + Nutthapon Petchthai + + + + + Laced + + + + Increased Attack. + + + + + + 804375b9-5448-40a7-9655-81e57f71bf4f + Beneath the Grounds + + + + + + + Shuffle 3 Ambushes into your opponent's deck. When drawn, you summon a 4/4 Nerubian. + + + Can you hold these eggs for just a second? I promise they're not full of giant enraged undead spider things. + Daren Bader + + + + Ambush! + + + + + When you draw this, summon a 4/4 Nerubian for your opponent. Draw a card. + + + + + + + + Anub'arak + + + + + + + + + + <b>Deathrattle:</b> Return this to your hand and summon a 4/4 Nerubian. + + + Was actually a pretty nice guy before, you know, the whole Lich King thing. + Eric Braddock + + + + + + + Nerubian + + + + + + + + + + + 349788d0-fd49-4ad2-b526-ff1885c69235 + Living Roots + + + + + + + <b>Choose One</b> - Deal $2 damage; or Summon two 1/1 Saplings. + + + 2 out of 2 saplings recommend that you summon the saplings. + Dan Brereton + + + + + + + a3b9d393-6576-4684-b83a-1c2e76a43984 + Living Roots + + + + + Deal $2 damage. + + + + + + 185ed6a5-cbef-4aed-ac67-dc5eec498294 + Living Roots + + + + + Summon two 1/1 Saplings. + + + + Sapling + + + + + + + + + + + 88f49e13-90e9-4bbd-8a26-146371d8ddd1 + Darnassus Aspirant + + + + + + + + + <b>Battlecry:</b> Gain an empty Mana Crystal. +<b>Deathrattle:</b> Lose a Mana Crystal. + + + She loves mana crystals, she hates mana crystals. So fickle! + Laurel Austin + + + + + + + + Savage Combatant + + + + + + + + + <b>Inspire:</b> Give your hero ++2 Attack this turn. + + + + Maybe if you whistle a tune it will soothe him. Yeah... Try that. + Alex Pascenko + + + + + + Savage + + + + +2 Attack this turn. + + + + + + + + 9e6b39cd-26b4-4972-93d3-ed0f03407205 + Wildwalker + + + + + + + + + <b>Battlecry:</b> Give a friendly Beast +3 Health. + + + She was born to be something. She is just not quite sure what yet... + James Ryman + + + + + + + + + + + Kindred Spirit + + + + +3 Health. + + + + + + Knight of the Wild + + + + + + + + + Whenever you summon a Beast, reduce the Cost of this card by (1). + + + He gets a discount on the tournament entry fee because he is his own horse. + Ralph Horsley + + + + + Call of the Wild + + + + + Cost reduced. + + + + + + 06e1e128-845a-4d0e-9623-498774bd42e3 + Druid of the Saber + + + + + + + + + <b>Choose One -</b> Transform to gain <b>Charge</b>; or +1/+1 and <b>Stealth</b>. + + + That's saberTEETH, not like curved pirate blades. That's a different kind of druid. Druid of the Curved Pirate Blades. + Arthur Gimaldinov + + + + + + + 4a7f206c-e8f7-42c2-a225-b0fe36ecbb11 + Lion Form + + + + + <b>Charge</b> + + + + + + 3b9f6989-445b-41b2-9723-12b70cd818f0 + Panther Form + + + + + +1/+1 and <b>Stealth</b> + + + + + + Sabertooth Lion + + + + + + + + <b>Charge</b> + + + + + + + + Sabertooth Panther + + + + + + + + + <b>Stealth</b> + + + + + + + 54c825d2-07d5-4cc0-a77c-35bcb841b679 + Astral Communion + + + + + + + Gain 10 Mana Crystals. Discard your hand. + + + Hey! Moon! Can I have some mana crystals? + Christopher Moeller + + + + 28db5c74-2641-4122-98a8-179537c68d10 + Mulch + + + + + + Destroy a minion. +Add a random minion to your opponent's hand. + + + + Is this a noun or a verb? We will never know. + Dan Scott + + + + + + + Aviana + + + + + + + + Your minions cost (1). + + + + + Call her "Tweety". She'll find it real funny. I PROMISE. + Velvet Engine + + + + + Empowering Mist + + + +1/+1. + + + + + + Mistcaller Deck Ench + + + + + + + + + 31251cd7-b58f-4d2e-b49a-8130c0696a24 + Tuskarr Totemic + + + + + + + + + <b>Battlecry:</b> Summon ANY random Totem. + + + Turns out the tuskarr aren't real choosy about their totems. + Eva Widermann + + + + + Draenei Totemcarver + + + + + + + + + <b>Battlecry:</b> Gain +1/+1 for each friendly Totem. + + + It's nice to find a real craftsman in this day and age of mass-produced totems. + RK Post + + + + + Experienced + + + + Increased stats. + + + + + + 74a02653-fa11-4b72-9497-fdea12b55f56 + Healing Wave + + + + + + + Restore #7 Health. Reveal a minion in each deck. If yours costs more, Restore #14 instead. + + + Favored by shaman who study the art of restoration and healing, this spell would feel smug, if it had feelings. + Luca Zontini + + + + + + Thunder Bluff Valiant + + + + + + + + + <b>Inspire:</b> Give your Totems +2 Attack. + + + Allowing totems to attack is not cheating. I mean, there isn't anything in the rule books about it. + Sean McNally + + + + + + Power of the Bluff + + + + Increased Attack. + + + + + + Charged Hammer + + + + + + + + + <b>Deathrattle:</b> Your Hero Power becomes 'Deal 2 damage.' + + + You can only pick it up if you are worthy. + Peet Cooper + + + + + + + + a8b86b11-5b27-4fc7-bc72-c5c401ea9fce + Lightning Jolt + + + + + <b>Hero Power</b> +Deal $2 damage. + + + + + + + + 96696c1e-2bf0-479e-8377-2eba51f41d20 + Elemental Destruction + + + + + + + Deal $4-$5 damage to all minions. <b>Overload: (5)</b> + + + I'm not a shaman or anything, but isn't Elemental Destruction the opposite of what they want to do? + Tyler Walpole + + + + + + Totem Golem + + + + + + + + + <b>Overload: (1)</b> + + + + What happens when you glue a buncha totems together. + Steve Prescott + + + + + 4730f071-b345-4b09-9893-2c12f512506a + Ancestral Knowledge + + + + + + + Draw 2 cards. <b>Overload: (2)</b> + + + MOMMMMMYYYYYYYYY!!! + Zoltan & Gabor + + + + + + a01a907d-8494-4e15-911b-642b70de624c + The Mistcaller + + + + + + + + + <b>Battlecry:</b> Give all minions in your hand and deck +1/+1. + + + + Calling the mist doesn't sound all that great. "Ooooh, it is slightly damp now!" + Wei Wang + + + + + 9b3e1b38-b3ef-482e-a110-5d4e48deb986 + Flash Heal + + + + + + + Restore #5 Health. + + + Flash! Ahhhhhhh~ + Marcelo Vignali + + + + + + 2ee8eca5-0b66-4803-8ec7-9c9c8c0b65cd + Powershot + + + + + + + Deal $2 damage to a minion and the minions next to it. + + + pow POW pow + Jonboy Meyers + + + + + + + Stablemaster + + + + + + + + + <b>Battlecry:</b> Give a friendly Beast <b>Immune</b> this turn. + + + Takes way better care of her pets than her brother, Unstablemaster. + Grant <b>Immune</b> this turn. + Tyson Murphy + + + + + + + + + + Groomed + + + + <b>Immune</b> this turn. + + + + + + + + King's Elekk + + + + + + + + + <b>Battlecry:</b> Reveal a minion in each deck. If yours costs more, draw it. + + + + Elekk jousting is AWESOME. + James Zhang + + + + + Brave Archer + + + + + + + + + <b>Inspire:</b> If your hand is empty, deal 2 damage to the enemy hero. + + + This is a "bearly" concealed reference. + Eva Widermann + + + + + + + Bear Trap + + + + + + + <b>Secret:</b> After your hero is attacked, summon a 3/3 Bear with <b>Taunt</b>. + + + You'll never guess what's in that conveniently bear-sized, bear-smelling box. + Richard Wright + + + + + + 845f206e-7994-4d08-9290-130a77033764 + Lock and Load + + + + + + + Each time you cast a spell this turn, add a random Hunter card to your hand. + + + Rexxar narrowed his eyes, grabbed his machine gun, and said: "It's go time. Lock and load." + +This card pays homage to that special moment. + Matt Dixon + + + + Lock and Load + + + + + + + + + + + + + d216f31a-6b02-4bbd-9518-fe9573cef366 + Ball of Spiders + + + + + + + Summon three 1/1 Webspinners. + + + "THEY'RE EVERYWHERE GET THEM OFF!!!" - Everyone + Skan Srisuwan + + + + + + Acidmaw + + + + + + + Whenever another minion takes damage, destroy it. + + + + + + + With the help of his trusty sidekick Dreadscale, the giant jormungar Acidmaw is ready to face any knight! + Andrew Hou + + + + + + Dreadscale + + + + + + + + + At the end of your turn, deal 1 damage to all other minions. + + + + + Let's be clear about this: ACIDMAW is the sidekick. + Zoltan Boros + + + + + + 1681b95a-d115-4083-9e30-027f39729aa4 + Bash + + + + + + + Deal $3 damage. +Gain 3 Armor. + + + You might think bashing doesn't take a lot of practice. It doesn't. + Dany Orizio + + + + + + King's Defender + + + + + + + + <b>Battlecry</b>: If you have a minion with <b>Taunt</b>, gain +1 Durability. + + + + "King's Attacker" is a shield. Funny, huh? + Michael Franchina + + + + + + King's Defender + + + +1 Durability. + + + + + + Orgrimmar Aspirant + + + + + + + <b>Inspire:</b> Give your weapon +1 Attack. + + + + + "Four out of three orcs struggle with math." - Angry Zurge + Hideaki Takamura + + + + + + Forges of Orgrimmar + + + + Increased Attack. + + + + + + Magnataur Alpha + + + + + + + + + Also damages the minions next to whomever +he attacks. + + + Playing him also gets you into the Magnataur Beta. + Alex Horley Orlandelli + + + + + 97bacb4c-d0bf-4424-81c9-545a254bebcb + Bolster + + + + + + Give your <b>Taunt</b> minions +2/+2. + + + + The best offense is a good defense. + Mishi McCaig + + + + Bolstered + + + + +2/+2. + + + + + + Sparring Partner + + + + + + + + + <b>Taunt</b> +<b>Battlecry:</b> Give a +minion <b>Taunt</b>. + Grant <b>Taunt</b>. + + + Come at me, bro. + Jim Nelson + + + + + + + + + + Training Complete + + + + <b>Taunt</b> + + + + + + Skycap'n Kragg + + + + + + + + <b>Charrrrrge</b> +Costs (1) less for each friendly Pirate. + + + + + What's more boss than riding a parrot with a jawbone for a shoulderpad while wielding a giant hook-lance-thing and wearing a pirate hat? NOTHING. + Alex Horley Orlandelli + + + + + + 99dfff8b-7ab2-4f0a-8c3d-9ef3d1fb9ba9 + Alexstrasza's Champion + + + + + + + + + <b>Battlecry:</b> If you're holding a Dragon, gain +1 Attack and <b>Charge</b>. + + + "Put more spikes on her. No, more spikes. What part of 'more spikes' do you not understand? MORE SPIKES!" - Alexstrasza + Evgeniy Zagumennyy + + + + + + Alexstrasza's Boon + + + + +1 Attack and <b>Charge</b>. + + + + + + 09aa6240-79ba-4c5c-bd32-fbace2d0c88b + Varian Wrynn + + + + + + + + + <b>Battlecry:</b> Draw 3 cards. +Put any minions you drew directly into the battlefield. + + + + Leader of the Alliance! Father of Anduin! Also he likes to play Arena, and he averages 12 wins. + Wei Wang + + + + + Competitive Spirit + + + + + + + <b>Secret:</b> When your turn starts, give your minions +1/+1. + + + Competition can be an inspiration to improve oneself. Or kill all the competitors. + Jim Nelson + + + + + + Competitive Spirit + + + +1/+1. + + + + + + db6484e3-6248-4e18-a13e-9a3ea66aff12 + Seal of Champions + + + + + + + Give a minion ++3 Attack and <b>Divine Shield</b>. + + + "Arf! Arf! Arf!" - Seal of Champions + Jonboy Meyers + + + + + + + + Seal of Champions + + + + +3 Attack and <b>Divine Shield</b>. + + + + + + Warhorse Trainer + + + + + + + + + Your Silver Hand Recruits have +1 Attack. + + + He doesn't even get Sundays off. Every day he's hostling. + Zoltan & Gabor + + + + + Might of the Hostler + + + + Warhorse Trainer is granting this minion +1 Attack. + + + + + + Murloc Knight + + + + + + + + + <b>Inspire:</b> Summon a random Murloc. + + + + Hee hee! Look at his cute little feet. + Sam Nielson + + + + + + 2f933f38-bdcd-4ced-8c6e-2a94b42184d3 + Argent Lance + + + + + + + + <b>Battlecry:</b> Reveal a minion in each deck. If yours costs more, +1 Durability. + + + + The stripes make it look like a candy cane, but we recommend against licking it. + Joe Wilson + + + + + Extra Poke + + + +1 Durability. + + + + + + 478cdc77-2a07-4e7e-ae27-ffae70ebdf25 + Enter the Coliseum + + + + + + + Destroy all minions except each player's highest Attack minion. + + + You have to get past the vendors first. So many are lost to shopping... + Mauricio Herrera + + + + 32496e29-9cf6-43e3-8ad0-0652934171b3 + Mysterious Challenger + + + + + + + + + <b>Battlecry:</b> Put one of each <b>Secret</b> from your deck into the battlefield. + + + He may sound surly and antisocial, but he's actually just really shy. + Zoltan Boros + + + + + + Garrison Commander + + + + + + + + You can use your Hero Power twice a turn. + + + He'll never admit it, but he pushes you hard because he really cares about you. + Jesper Ejsing + + + + d3daaad7-dfb0-4c44-bebe-e5f570423a1c + Eadric the Pure + + + + + + + + + <b>Battlecry:</b> Change all enemy minions' +Attack to 1. + + + + Nobody rocks a monocle like Eadric. + James Ryman + + + + + Purified + + + + Attack changed to 1. + + + + + + Lowly Squire + + + + + + + + <b>Inspire:</b> Gain +1 Attack. + + + But not the lowliest! + Ron Spears + + + + + + Training + + + Increased Attack. + + + + + + Dragonhawk Rider + + + + + + + + <b>Inspire:</b> Gain <b>Windfury</b> +this turn. + + + Check it out. You can do barrel rolls on this thing. + Anton Zemskov + + + + + + Dragonhawkery + + + <b>Windfury</b> this turn. + + + + + + + + e0c51d91-5c08-469b-8bb2-22d13713a2ff + Lance Carrier + + + + + + + + <b>Battlecry:</b> Give a friendly minion +2 Attack. + + + Give +2 Attack. + Lance Carrier is an obscure entry level position in orcish armies. A mystery, since orcs don't generally use lances. + Tyson Murphy + + + + + + + + + Equipped + + + +2 Attack. + + + + + + Maiden of the Lake + + + + + + + + Your Hero Power costs (1). + + + Not a good basis for a system of government. + Froilan Gardner + + + + + ce75b73b-1501-4104-93b3-e29c6fb31dce + Saboteur + + + + + + + + <b>Battlecry:</b> Your opponent's Hero Power costs (5) more next turn. + + + Listen all y'all it's a saboteur! + Greg Staples + + + + + Villainy + + + Your Hero Power costs (5) more this turn. + + + + + + + + Argent Horserider + + + + + + + + <b>Charge</b> +<b>Divine Shield</b> + + + His horse's name is Betsy. + Evgeniy Zagumennyy + + + + + + + Mogor's Champion + + + + + + + + + + 50% chance to attack the wrong enemy. + This champion has learned from the best. Except for his target selection. + Steve Prescott + + + + + + + + Boneguard Lieutenant + + + + + + + + <b>Inspire:</b> Gain +1 Health. + + + Underneath all that impressive armor, he's just skin and bones. Okay, maybe just bones. + Slawomir Maniak + + + + + + Boneguarded + + + Increased Health. + + + + + + Mukla's Champion + + + + + + + + <b>Inspire:</b> Give your other minions +1/+1. + + + + An elegant gorilla, for a more civilized age. + Andrew Hou + + + + + + Might of the Monkey + + + +1/+1. + + + + + + Tournament Medic + + + + + + + + <b>Inspire:</b> Restore 2 Health to your hero. + + + The medic tournament is less entertaining than the Grand Tournament. + Sean McNally + + + + + + Ice Rager + + + + + + + + He's a lot cooler than Magma Rager. + Anton Zemskov + + + Frigid Snobold + + + + + + + + <b>Spell Damage +1</b> + + + Ironically, the natural enemy of the snobold is THE CANDLE. + Matt Dixon + + + + + Flame Juggler + + + + + + + + <b>Battlecry:</b> Deal 1 damage to a random enemy. + + + At first he liked juggling chain saws, but then he thought, "Flames are better! Because FIRE!" + James Zhang + + + + + Silent Knight + + + + + + + + <b>Stealth</b> +<b>Divine Shield</b> + + + He used to be a librarian. Old habits die hard. + Esad Ribic + + + + + + + Clockwork Knight + + + + + + + + <b>Battlecry:</b> Give a friendly Mech +1/+1. + + + + It takes a lot to wind him up. + Give +1/+1. + Skan Srisuwan + + + + + + + + + + + Wound Up + + + +1/+1. + + + + + + Tournament Attendee + + + + + + + + <b>Taunt</b> + + + He was so excited to get season tickets to this year's Grand Tournament. He normally doesn't get them at first and has to buy them from Ogre scalpers. + Adam Byrne + + + + + 466793cd-b974-4497-850c-64692e673379 + Sideshow Spelleater + + + + + + + + <b>Battlecry:</b> Copy your opponent's Hero Power. + + + Hey! Let me try that... + Wayne Reynolds + + + + + Kodorider + + + + + + + + <b>Inspire:</b> Summon a 3/5 War Kodo. + + + Someone called her a Rhinorider, and she's NOT HAPPY. + Ben Wootten + + + + + + War Kodo + + + + + + + + + + + Silver Hand Regent + + + + + + + + <b>Inspire:</b> Summon a 1/1 Silver Hand Recruit. + + + The Silver Hand is the best paladin organization. The Argent Crusaders are super jealous. + John Polidora + + + + + + Pit Fighter + + + + + + + + + + What did the pits ever do to you? + Alex Horley Orlandelli + + + Captured Jormungar + + + + + + + + + You can keep him, but you have to promise to feed him and clean out his tank every day! + Gonzalo Ordonez + + + 1e067e1c-a3c9-4cb3-a682-399e8dc17130 + North Sea Kraken + + + + + + + + <b>Battlecry:</b> Deal 4 damage. + + + Deal 4 damage. + You have no idea how tired this guy is of being released. + Seamus Gallagher + + + + + + + 2facc9e7-61bf-4d6c-8f67-1496ac9faa75 + Tuskarr Jouster + + + + + + + + <b>Battlecry:</b> Reveal a minion in each deck. If yours costs more, restore 7 Health to your hero. + + + + Just could not be talked out of using his turtle for the joust... + Skan Srisuwan + + + + + 98dc9d2b-6407-4089-bf05-1b2d920694dd + Injured Kvaldir + + + + + + + + <b>Battlecry:</b> Deal 3 damage to this minion. + + + Don't worry. With a little skin cream he's going to clear right up. + Zoltan Boros + + + + + 905b8a1a-5781-499e-a7e7-896ce0d9228d + Light's Champion + + + + + + + + <b>Battlecry:</b> <b>Silence</b> a Demon. + + + <b>Silence</b> a Demon. + When there's something strange (say, a gibbering demon) in your neighborhood, who are you going to call? + Andrea Uderzo + + + + + + + + + 78347522-c8e0-4f9c-9f83-9572bded7346 + Armored Warhorse + + + + + + + + <b>Battlecry:</b> Reveal a minion in each deck. If yours costs more, gain <b>Charge</b>. + + + + Yep. It's a horse... wearing armor... going to war. + Edouard Guiton & Tony Washington + + + + + + Argent Watchman + + + + + + + + Can't attack. +<b>Inspire:</b> Can attack as normal this turn. + + + Who argent watches the Argent Watchman? + Ben Zhang + + + + + + + Inspired + + + Can attack this turn. + + + + + + + + Coliseum Manager + + + + + + + + <b>Inspire:</b> Return this minion to your hand. + + + Meets monthly with the gladiators to discuss career goals. + Dan Scott + + + + + + e4481845-2fa3-4c37-9f2e-a757c797d755 + Refreshment Vendor + + + + + + + + <b>Battlecry:</b> Restore 4 Health to each hero. + + + Menu: Funnel cakes, carrots, popcorn, jormungar steaks. It's hard serving a diverse clientele. + Ron Spears + + + + + Master Jouster + + + + + + + + <b>Battlecry:</b> Reveal a minion in each deck. If yours costs more, gain <b>Taunt</b> and <b>Divine Shield</b>. + + + Needs just a few more ratings points to become Grandmaster Jouster. + Penny Arcade + + + + + + + Recruiter + + + + + + + + <b>Inspire:</b> Add a 2/2 Squire to your hand. + + + Join the Argent Crusade! We have attractive tabards and you get to carry really nice swords! + Jim Nelson + + + + + + Evil Heckler + + + + + + + + <b>Taunt</b> + + + To be honest, heckling is not the most effective form of evil. + Dan Scott + + + + + 749d5dec-f539-4b4a-8c6d-b72f2ba9d47b + Fencing Coach + + + + + + + + <b>Battlecry:</b> The next time you use your Hero Power, it costs (2) less. + + + Good fencers make good neighbors, right? + Howard Lyon + + + + + + + Fencing Practice + + Your Hero Power costs (2) less. + + + + + + + + + 448290a1-cb01-49d9-8d39-74ac800295b3 + Wyrmrest Agent + + + + + + + + <b>Battlecry:</b> If you're holding a Dragon, gain +1 Attack and <b>Taunt</b>. + + + + Keeping tabs on the Grand Tournament is priority #1 for the five mighty Dragonflights! + Jeff Easley + + + + + + + Bring it on! + + + +1 Attack and <b>Taunt</b>. + + + + + + + 78d6932e-8acd-4212-9dda-862b369b37ca + Master of Ceremonies + + + + + + + + <b>Battlecry:</b> If you have a minion with <b>Spell Damage</b>, gain +2/+2. + + + Goes by "MC ElfyElf". + Jesper Ejsing + + + + + + Ceremony + + + +2/+2. + + + + + + b8979bab-cbb3-4b62-8f33-1bd95b2b219b + Grand Crusader + + + + + + + + <b>Battlecry:</b> Add a random Paladin card to your hand. + + + A veteran of a number of crusades, she is a force for light and goodness. Her latest crusade is against goblin telemarketers. + Todd Lockwood + + + + + Kvaldir Raider + + + + + + + + <b>Inspire:</b> Gain +2/+2. + + + Coming soon... to a tuskarr village near you! + Trent Kaniuga + + + + + + Inspired + + + Increased stats. + + + + + + Frost Giant + + + + + + + + Costs (1) less for each time you used your Hero Power this game. + + + Don't ask him about the beard. JUST DON'T. + Greg Staples + + + + Crowd Favorite + + + + + + + + Whenever you play a card with <b>Battlecry</b>, gain +1/+1. + + + The crowd ALWAYS yells lethal. + Jakub Kasper + + + + + + + Huge Ego + + + Increased stats. + + + + + + 81c72cd7-3d89-4beb-87b0-05972e073876 + Gormok the Impaler + + + + + + + + + <b>Battlecry:</b> If you have at least 4 other minions, deal 4 damage. + Deal 4 damage. + + + Gormok has been giving impaling lessons in a small tent near the tournament grounds. For only 25g you too could learn the fine art of impaling! + Nutthapon Petchthai + + + + + + + + Chillmaw + + + + + + + + + <b>Taunt</b> +<b>Deathrattle:</b> If you're holding a Dragon, deal 3 damage to all minions. + + + + Chillmaw keeps trying to ruin the Grand Tournament, and she would've done it too, if it weren't for those dang kids! + Raymond Swanland + + + + + + + + Bolf Ramshield + + + + + + + + + Whenever your hero takes damage, this minion takes it instead. + + + Bolf keeps coming in 2nd at the Grand Tournament. It might be his year this year, if Lebron doesn't enter. + Wayne Reynolds + + + + + + Icehowl + + + + + + + + + <b>Charge</b> +Can't attack heroes. + + + This massive yeti just closes his eyes and charges at the nearest target. The nearest Target is a couple blocks away and has sick deals on skateboards. + John Polidora + + + + + + Nexus-Champion Saraad + + + + + + + + + <b>Inspire:</b> Add a random spell to your hand. + + + The ethereals have their own jousting tournament, and Saraad is the reigning champion. Also he won the ethereal hot dog eating contest. + Marcleo Vignali + + + + + + The Skeleton Knight + + + + + + + + + <b>Deathrattle:</b> Reveal a minion in each deck. If yours costs more, return this to your hand. + + + Apparently it really was just a flesh wound. + Mike Sass + + + + + + Fjola Lightbane + + + + + + + + + Whenever <b>you</b> target this minion with a spell, gain <b>Divine Shield.</b> + + + LOVES being called "the wonder twins". + Mark Zug + + + + + + + Sea Reaver + + + + + + + + When you draw this, deal 1 damage to your minions. + + + + A little better than Sea Minus Reaver. + James Ryman + + + + + + Eydis Darkbane + + + + + + + + + Whenever <b>you</b> target this minion with a spell, deal 3 damage to a random enemy. + + + HATES being called "the wonder twins". + Ben Thompson + + + + + + dd0ef72c-b66f-4731-935e-0deae6f58d80 + Justicar Trueheart + + + + + + + + + <b>Battlecry:</b> Replace your starting Hero Power with a better one. + + + It's like putting racing stripes and a giant spoiler on your hero power. + Jomaro Kindred + + + + + ff931aa0-692b-4ffa-b1d6-a21cfe4fb7a4 + Dire Shapeshift + + + + <b>Hero Power</b> +Gain 2 Armor and +2 Attack this turn. + + + + + + + Dire Claws + + + +2 Attack this turn. + + + + + + + + + 8cdd655d-cffd-488e-8d78-d836940c2019 + Ballista Shot + + + + <b>Hero Power</b> +Deal $3 damage to the enemy hero. + + + + + + + + + + 75474e1c-d29e-4465-abbb-5c837d977bf1 + Fireblast Rank 2 + + + + <b>Hero Power</b> +Deal $2 damage. + + + + + + + + + ff890604-8e6a-48c5-88ce-2d3895d7e659 + The Silver Hand + + + + <b>Hero Power</b> +Summon two 1/1 Recruits. + + + + + + + + + 1de158cf-d777-40fe-a872-0b0eed085c69 + Heal + + + + <b>Hero Power</b> +Restore #4 Health. + + + + + + + + + 6a4cd65c-0698-4151-83c2-b938c611e3b4 + Poisoned Daggers + + + + <b>Hero Power</b> +Equip a 2/2 Weapon. + + + + + + + Poisoned Dagger + + + + + + + + + 5b26dba6-7d2f-424a-b322-5fa21db6644c + Totemic Slam + + + + <b>Hero Power</b> +Summon a Totem of your choice. + + + + + + + + + a3de9b02-d553-491a-878d-5d85476481b1 + Healing Totem + + + + At the end of your turn, restore 1 Health to all friendly minions. + + + + + + + + e90c48cd-74df-4db3-8c52-1a63407577b8 + Searing Totem + + + + + + + + + + + 835c9aea-52f9-477a-a1c4-eaab04c52006 + Stoneclaw Totem + + + + <b>Taunt</b> + + + + + + + + 35e47236-ee17-4a18-af72-b0bac7687a27 + Wrath of Air Totem + + + + <b>Spell Damage +1</b> + + + + + + + + 5fdb9afa-94da-43f0-a410-eae049bd16cc + Soul Tap + + + + <b>Hero Power</b> +Draw a card. + + + + + + + 1642cd9d-c757-4ed7-bfb5-1354ad879769 + Tank Up! + + + + <b>Hero Power</b> +Gain 4 Armor. + + + + + + + Gadgetzan Jouster + + + + + + + + <b>Battlecry:</b> Reveal a minion in each deck. If yours costs more, gain +1/+1. + + + It's not HER fault you didn't put a spinning saw blade on your horse. + Skan Srisuwan + + + + + Victory! + + + +1/+1. + + + + + + Tiger Form + + + + + + + + + <b>Charge, Stealth</b> + + + + + + + + + Placeholder Card + + + + + + + + + Battlecry: Someone remembers to publish this card. + + diff --git a/hm_web/cache/cards.basic b/hm_web/cache/cards.basic new file mode 100644 index 0000000..8fca198 --- /dev/null +++ b/hm_web/cache/cards.basic @@ -0,0 +1,731 @@ +#!/bin/sh +# Game entity +name="Game Entity" card=GAME_ENTITY tags={10:85,20:1,49:1,198:4,202:1,204:2} + +# Mana Card +name="Coin" card=GAME_005 tags={49:3,202:5,313:1} + +# Player1 +name="Player1" card=PLAYER1 tags={7:75,17:1,27:64,28:10,29:4,30:1,31:1,49:1,176:10,202:2,272:1,399:4} + +# Player2 +name="Player2" card=PLAYER2 tags={7:75,17:1,23:1,24:1,27:66,28:10,29:4,30:2,31:2,49:1,176:10,202:2,272:1,399:3} + +# Power of the Horde +[PRO_001c] + +# The Sentinel +[TB_SPT_Boss] + +# The Scourge +[LOEA04_01] + +# Enrage +[NAX12_04e] flags=(CARD_ATTACHMENT) + +# Lantern of Power +[LOEA16_3e] flags=(CARD_ATTACHMENT) + +# Lothar's Left Greave +[LOEA16_9] + +# Mountain Giant +[EX1_105] attachment=LOEA16_3e + +# Youthful Brewmaster +[EX1_049] + +# Brann Bronzebeard +[LOE_077] + +# Abomination +[EX1_097] + +# Piloted Sky Golem +[GVG_105] + +# Icehowl +[AT_125] + +# Skeleton +[NAX4_03H] + +# Skeleton Knight +[AT_128] + +# Deathwing +[NEW1_030] + +# Treant +[EX1_158t] + +# Velen's Chosen +[GVG_010] + +# Cabalist's Tome +[OG_090] + +# Seal of Champions +[AT_074] attachment=AT_074e2 + +# Seal of Champions E +[AT_074e2] flags=(CARD_ATTACHMENT) + +# Dagon +[BRMA11_3] + +# Sparring Partner +[AT_069] + +# Divine Rapier E +[FP1_020e] flags=(CARD_ATTACHMENT) + +# Desolator +[LOEA06_03] attachment=LOEA06_03e + +# Desolator E +[LOEA06_03e] flags=(CARD_ATTACHMENT) + +# Rooted +[EX1_178ae] flags=(CARD_ATTACHMENT) + +# Inner Rage +[EX1_607] attachment=EX1_607e + +# Angry Chicken +[EX1_009] + +# Repel +[LOEA16_20] + +# Cursed Blade +[LOE_118] + +# Shadowflame +[EX1_303] + +# Demonfire E +[EX1_596e] flags=(CARD_ATTACHMENT) + +# Void Crusher +[AT_023] + +# Forbidden Shaping +[OG_101] + +# Charge E +[CS2_103e2] flags=(CARD_ATTACHMENT) + +# Inner Rage E +[EX1_607e] flags=(CARD_ATTACHMENT) + +# Inner Fire E +[CS1_129e] flags=(CARD_ATTACHMENT) + +# Twisting Nether +[EX1_312] + +# Mal Ganis +[GVG_021] + +# Lay on Hands +[EX1_354] + +# Flame Lance +[AT_001] + +# Dragon's Breath +[BRM_003] + +# Confessor Paletress +[AT_018] level2=BRM_003 level3=AT_001 + +# Lightning Storm +[EX1_259] + +# Forked Lightning +[EX1_251] + +# Archmage Antonidas +[EX1_559] level2=EX1_251 level3=EX1_259 + +# Commanding Shout +[NEW1_036] attachment=NEW1_036e + +# Commanding Shout +[NEW1_036e] flags=(CARD_ATTACHMENT) + +# Druid of the Claw +[EX1_165t2] level2=CS2_012 level3=CS2_011 + +# Open Wounds +[AT_039e] flags=(CARD_ATTACHMENT) + +# Divine Strength +[OG_223] attachment=OG_223e + +# Optimism +[OG_223e] flags=(CARD_ATTACHMENT) + +# Tirion Fordring +[EX1_383] level2=NEW1_036 level3=OG_223 + +# Windfury +[CS2_039] + +# Corruption +[CS2_063] attachment=CS2_063e +# Corruption E +[CS2_063e] flags=(CARD_ATTACHMENT) + +# Hunter's Mark +[CS2_084] attachment=CS2_084e +# Hunter's Mark E +name="Hunter's Mark E" card=CS2_084e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Assasinate +[CS2_076] + +# Shadow Word: Death +[EX1_622] + +# Shadow Word: Pain +[CS2_234] + +# Execute +[CS2_108] + +# Illidan +[EX1_614] + +# Hand of Protection +[EX1_371] + +# Polymorph +[CS2_022] attachment=CS2_022e +name="Polymorph E" card=CS2_022e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Hex +[EX1_246] attachment=EX1_246e +# Hex E +name="Hex E" card="EX1_246e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Blessing of Kings +[CS2_092] attachment=CS2_092e +# Blessing of Kings E +name="Blessing of Kings E" card="CS2_092e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Blessing of Might +[CS2_087] attachment=CS2_087e +# Blessing of Might E +name="Blessing of Might E" card="CS2_087e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Power Word: Shield +[CS2_004] attachment=CS2_004e +# Power Word: Shield E +name="Power Word: Shield E" card="CS2_004e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Charge +[CS2_103] attachment=CS2_103e2 +# Charge E +#name="Charge E" card="CS2_103e2" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Mark of the Wild +[CS2_009] attachment=CS2_009e +# Mark of the Wild E +name="Mark of the Wild E" card="CS2_009e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Ancestral Healing +[CS2_041] attachment=CS2_041e +# Ancestral Infusion +name="Ancestral Infusion" card="CS2_041e" tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Rockbiter Weapon +[CS2_045] attachment=CS2_045e +# Rockbiter Weapon E +name="Rockbiter Weapon E" card=CS2_045e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Divine spirit +[CS2_236] + +# Bloodlust +[CS2_046] attachment=CS2_046e +# Bloodlust E +name="Bloodlust E" card=CS2_046e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Claw +[CS2_005] attachment=CS2_005o +# Claw E +name="Claw E" card=CS2_005o tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Heroic Strike +[CS2_105] attachment=CS2_105e +# Heroic Strike E +name="Heroic Strike E" card=CS2_105e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Savage Roar +[CS2_011] attachment=CS2_011o +# Savage Roar E +[CS2_011o] flags=(CARD_ATTACHMENT) + +# Warrior +name="Warrior" card=HERO_01 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Shamman +name="Shamman" card=HERO_02 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Rogue +#name="Rogue" card=TB_SPT_Boss tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Paladin +name="Paladin" card=HERO_04 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Hunter +name="Hunter" card=HERO_05 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Druid +name="Druid" card=HERO_06 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Warlock +name="Warlock" card=HERO_07 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Mage +name="Mage" card=HERO_08 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Priest +#name="Priest" card=LOEA04_01 tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# King of Khaz Modan +name="King of Khaz Modan" card=HERO_01a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Blood Knight Matriarch +name="Blood Knight Matriarch" card=HERO_04a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Alleria Windranger +name="Alleria Windranger" card=HERO_05a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Guardian Medivh +name="Guardian Medivh" card=HERO_08a tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) +# Khadgar +name="Khadgar" card=HERO_08b tags={12:1,45:30,49:1,201:3,202:3,203:2} flags=(CARD_HERO) + +# Ice lance +#CS2_031 tags={12:1,47:0,48:1,49:3,201:3,202:5,203:2,264:1} flags=(CARD_SPELL|CARD_SPELL_DAMAGE|CARD_TARGETING|CARD_FREEZE|CARD_TARGET_FROZEN_4_DMG) + +# Holy Smite +[CS1_130] + +# Fireball +[CS2_029] + +# Swipe +[CS2_012] attachment=AT_039e + +# Hammer of Wrath +[CS2_094] + +# Backstab +[CS2_072] + +# Drain Life +[CS2_061] + +# Sacrificial Pact +[NEW1_003] + +# Arcane Shot +[DS1_185] + +# Soulfire +[EX1_308] + +# Mortal Coil +[EX1_302] + +# Shield Block +[EX1_606] + +# Shiv +[EX1_278] + +# Starfire +[EX1_173] + +# Moonfire +[CS2_008] + +# Kill Command +[EX1_539] + +# Frostbolt +[CS2_024] + +# Frost Shock +[CS2_037] + +# Shadow Bolt +[CS2_057] + +# Feral Rage - choose one +#OG_047 tags={12:1,48:2,49:3,201:3,202:5,203:2,264:1} flags=(CARD_SPELL|CARD_SPELL_DAMAGE|CARD_NONTARGET) + +# Arcane intellect +[CS2_023] + +# Sprint +[CS2_077] + +# Arcane Explosion +[CS2_025] + +# Arcane Missiles +[EX1_277] + +# Tracking +[DS1_184] + +# Sinister Strike +[CS2_075] + +# Mind Blast +[DS1_233] + +# Frost Nova +[CS2_026] + +# Fan of Knives +[EX1_129] + +# Cleave +[CS2_114] + +# Multishot +[DS1_183] + +# Mind Vision +[CS2_003] + +# Flamestrike +[CS2_032] + +# Whirlwind +[EX1_400] + +# Consecration +[CS2_093] + +# Holy Nova +[CS1_112] + +# Hellfire +[CS2_062] + +# Water Elemental +[CS2_033] + +################ +# Aura +############### + +# Raid leader +[CS2_122] attachment=CS2_122e +# Enhanced +name="Enhanced" card=CS2_122e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Stormwind champion +[CS2_222] attachment=CS2_222o +# Might of Stormwind +[CS2_222o] flags=(CARD_ATTACHMENT) + +# Warsong Commander +[EX1_084] attachment=EX1_084e +# Charge +name="Charge" card=EX1_084e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Timber Wolf +[DS1_175] attachment=DS1_175o +# Furious Howl +name="Furious Howl" card=DS1_175o tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Gurubashi Berserker +[EX1_399] attachment=EX1_399e +# Berserking +name="Berserking" card=EX1_399e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + + +################ +# Battlecry +############### + +# Dread Infernal +[CS2_064] + +# Novice engineer +[EX1_015] + +# Gnomish Inventor +[CS2_147] + +# Darkscale Healer +[DS1_055] + +# Guardian of Kings +[CS2_088] + +# Nightblade +[EX1_593] + +# Acidic Swamp Ooze +[EX1_066] + +# Voodoo doctor +[EX1_011] + +# Elven Archer +[CS2_189] + +# Fire Elemental +[CS2_042] + +# Ironforge Rifleman +[CS2_141] + +# Stormpike Commando +[CS2_150] + +# Frostwolf Warlord +[CS2_226] attachment=CS2_226e +# Frostwolf Banner +[CS2_226e] flags=(CARD_ATTACHMENT) + +# Succubus +[EX1_306] + +# Sap +[EX1_581] + +# Mind Control +[CS1_113] attachment=CS1_113e +# Mind Control E +name="Mind Control E" card=CS1_113e tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +# Vanish +[NEW1_004] + +################ +# Spell damage +############### + +# Archmage +[CS2_155] + +# Dalaran mage +[EX1_582] + +# Kobold geomancer +[CS2_142] + +# Ogre magi +[CS2_197] + +################ +# Charge +############### + +# Wolfirder +[CS2_124] + +# Bluegill warrior +[CS2_173] + +# Kor'kron elite +[NEW1_011] level3=CS2_108 + +# Stormwind knight +[CS2_131] + +# Reckless rocketeer +[CS2_213] + +# Stonetusk boar +[CS2_171] + +# Huffer +[NEW1_034] flags=(CARD_UNCOLLECTIBLE) + +################ +# Divine shield +############### + +# Scarlet Crusader +[EX1_020] + +################ +# Taunt +############### + +# Lord of the Arena +[CS2_162] + +# Booty bay bodyguard +[CS2_187] + +# Frostwolf Grunt +[CS2_121] + +# Goldshire footman +[CS1_042] + +# Ironbark protector +[CS2_232] + +# Sen'jin Shieldmasta +[CS2_179] + +# Voidwalker +[CS2_065] level2=OG_101 level3=EX1_312 + +# Misha +[NEW1_032] flags=(CARD_UNCOLLECTIBLE) + +# Frog +[hexfrog] flags=(CARD_UNCOLLECTIBLE) + +################ +# Totem +############### + +# Wrath of Air Totem +[CS2_052] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Stoneclaw Totem +[CS2_051] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Searing Totem +[CS2_050] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Healing Totem +[NEW1_009] flags=(CARD_UNCOLLECTIBLE|CARD_TOTEMIC_CALL_CHILD) +# Flametongue Totem +[EX1_565] attachment=EX1_565o +# Flametongue +name="Flametongue" card=EX1_565o tags={12:1,49:6,202:6} flags=(CARD_ATTACHMENT) + +################ +# Summon +############### + +# Mirror Image +[CS2_027] +# Mirror Image +[CS2_mirror] + +# Animal Companion +[NEW1_031] + +# Dragonling Mechanic +[EX1_025] +# Mechanical Dragonling +[EX1_025t] flags=(CARD_UNCOLLECTIBLE) + +# Murloc Tidehunter +[EX1_506] +# Murloc Scout +[EX1_506a] flags=(CARD_UNCOLLECTIBLE) + +# Razorfen Hunter +[CS2_196] + +# Leokk +[NEW1_033] flags=(CARD_UNCOLLECTIBLE) + +# Starving Buzzard +[CS2_237] + +# Sheep +[CS2_tk1] flags=(CARD_UNCOLLECTIBLE) + +# Avator of the Coin +[GAME_002] flags=(CARD_UNCOLLECTIBLE) + +# Boar +[CS2_boar] flags=(CARD_UNCOLLECTIBLE) +# Oasis Snapjaw +[CS2_119] +# Bloodfen Raptor +[CS2_172] +# Magma Rager +[CS2_118] level3=EX1_303 + +# Puddlestomper +#GVG_064 tags={12:1,45:2,47:3,48:2,49:3,202:4,203:2} flags=(CARD_MINION) +# Wisp +[CS2_231] attachment=NAX12_04e + +# Core Hound +[CS2_201] + +# Murloc Raider +[CS2_168] + +# River Crocolisk +[CS2_120] + +# Boulderfist Ogre +[CS2_200] + +# Chillwind Yeti +[CS2_182] + +# Fireblast +name="Fireblast" card=CS2_034 tags={12:1,47:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_TARGETING|CARD_SPELL|CARD_HP_SPELL_DAMAGE) + +# Lesser Heal +# name="Lesser Heal" card=CS1h_001 tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_TARGETING|CARD_SPELL|CARD_SPELL_HEAL) + +# Lesser Heal +[CS1h_001] + +# Healing Touch +[CS2_007] + +# Holy Light +[CS2_089] + +# Reinforce +name="Reinforce" card=CS2_101 tags={12:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_REINFORCE|CARD_SUMMON) +# Silverhand Recruit +[CS2_101t] flags=(CARD_MINION|CARD_UNCOLLECTIBLE) + +# Dagger Mastery +name="Dagger Mastery" card=CS2_083b tags={12:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_DAGGERMASTERY|CARD_SUMMON) + +################ +# Weapon +############### + +# Wicked Knife +[CS2_082] flags=(CARD_UNCOLLECTIBLE) + +# Assassin's Blade +[CS2_080] + +# Truesilver Champion +[CS2_097] + +# Fiery War Axe +[CS2_106] + +# Light's Justice +[CS2_091] + +# Arcanite reaper +[CS2_112] + +############## + +# Totemic Call +[CS2_049] tags={12:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_SUMMON|CARD_HP_TOTEMIC_CALL) + +# Shapeshift +[CS2_017] tags={12:1,47:1,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_SHAPESHIFT|CARD_SUMMON) + +# Armor Up +[CS2_102] tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_ARMORUP|CARD_SUMMON) + +# Life Tap +[CS2_056] tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_SPELL|CARD_NONTARGET|CARD_HP_LIFETAP|CARD_SUMMON) + +# Steady Shot +[DS1h_292] tags={12:1,47:2,48:2,49:1,201:3,202:10,203:2} flags=(CARD_HEROPOWER|CARD_TARGETING|CARD_SPELL|CARD_HP_SPELL_DAMAGE|CARD_TARGET_HERO) + +# Empty mana card +name="Empty card" card=MANA_CARD tags={12:1,49:3,263:5} flags=(CARD_UNCOLLECTIBLE) + +# No card +name="No Card" card=NO_CARD tags={49:2} flags=(CARD_UNCOLLECTIBLE) diff --git a/hm_web/cache/cardsxml_p1 b/hm_web/cache/cardsxml_p1 new file mode 100644 index 0000000..5553673 Binary files /dev/null and b/hm_web/cache/cardsxml_p1 differ diff --git a/hm_web/cache/cardsxml_p3 b/hm_web/cache/cardsxml_p3 new file mode 100644 index 0000000..a1a2dc6 Binary files /dev/null and b/hm_web/cache/cardsxml_p3 differ diff --git a/hm_web/generate.py b/hm_web/generate.py new file mode 100644 index 0000000..189cee5 --- /dev/null +++ b/hm_web/generate.py @@ -0,0 +1,111 @@ +import urllib2 +import os +from time import sleep + +def gen(inp): + type = "" + name = "" + inhand = "" + health = "" + attack = "" + cost = "" + rarity = "" + cardname = "" + durability = "" + hero = "" + + for l in inp: + if(l[0] == '202'): + type = l[1] + elif(l[0] == '__name'): + name = l[1] + elif(l[0] == '184'): + inhand = l[1].replace("\n", " ") + elif(l[0] == '48'): + cost = l[1] + elif(l[0] == '47'): + attack = l[1] + elif(l[0] == '45'): + health = l[1] + elif(l[0] == '187'): + durability = l[1] + elif(l[0] == '203'): + rarity = l[1] + elif(l[0] == '185'): + cardname = l[1] + elif(l[0] == '__code'): + if(l[1].find("\"boss\"") > -1): + hero = 'HERO' + + + out = "{" + + if(len(cost) > 0): + out += "\"cost\":%s," % cost + + if(type == '5'): + out += "\"type\":\"SPELL\"," + elif(type == '4'): + out += "\"type\":\"MINION\"," + out += "\"attack\":%s," % attack + out += "\"health\":%s," % health + if(len(hero) > 0): + out += "\"race\":\"%s\"," % hero + elif(type == '7'): + out += "\"type\":\"WEAPON\"," + out += "\"attack\":%s," % attack + out += "\"durability\":%s," % durability + elif(type == '6'): + return + + elif(type == '10'): + out += "\"type\":\"HEROPOWER\"," + + elif(type == '3'): + out += "\"type\":\"MINION\"," + out += "\"attack\":0," + out += "\"health\":%s," % health + out += "\"rarity\":5," + out += "\"cost\":0," + else: + print 'wrong ', type + exit(1) + + out += "\"texture\":\"%s\"," % name + + out += "\"id\":\"%s\"," % name + + out += "\"text\":\"%s\"," % inhand + + out += "\"name\":\"%s\"," % cardname + + r = "" + if(rarity == '1'): + r = "FREE" + elif(rarity == '2'): + r = "COMMON" + elif(rarity == '3'): + r = "COMMON" + elif(rarity == '4'): + r = "RARE" + elif(rarity == '5'): + r = "LEGENDARY" + + out += "\"rarity\":\"%s\"," % r + + out +="\ + \"artist\":\"Zoltan Boros\",\ + \"set\":\"CORE\",\ + \"flavor\":\"asdf\",\ + \"playRequirements\":{\"REQ_TARGET_TO_PLAY\":0,\"REQ_MINION_TARGET\":0},\ + \"collectible\":true,\ + \"playerClass\":\"NEUTRAL\",\ + \"howToEarnGolden\":\"Unlocked at Level 45.\",\ + \"howToEarn\":\"Unlocked at Level 1.\"\ + }" + + f = open("../hm_sunwell/examples/carddata", "w") + f.write(out) + f.close() + + urllib2.urlopen("http://localhost:8081/").read() diff --git a/hm_web/static/cards.js b/hm_web/static/cards.js new file mode 100644 index 0000000..2f6d94a --- /dev/null +++ b/hm_web/static/cards.js @@ -0,0 +1,112 @@ +var cards = [ +["CS2_039", "# Windfury"], +["CS2_063", "# Corruption"], +["CS2_084", "# Hunter's Mark"], +["CS2_076", "# Assasinate"], +["EX1_622", "# Shadow Word: Death"], +["CS2_234", "# Shadow Word: Pain"], +["CS2_108", "# Execute"], +["EX1_371", "# Hand of Protection"], +["CS2_022", "# Polymorph"], +["EX1_246", "# Hex"], +["CS2_092", "# Blessing of Kings"], +["CS2_087", "# Blessing of Might"], +["CS2_004", "# Power Word: Shield"], +["CS2_103", "# Charge"], +["CS2_009", "# Mark of the Wild"], +["CS2_041", "# Ancestral Healing"], +["CS2_045", "# Rockbiter Weapon"], +["CS2_236", "# Divine spirit"], +["CS2_046", "# Bloodlust"], +["CS2_005", "# Claw"], +["CS2_011", "# Savage Roar"], +["CS1_130", "# Holy Smite"], +["CS2_029", "# Fireball"], +["CS2_012", "# Swipe"], +["CS2_094", "# Hammer of Wrath"], +["CS2_072", "# Backstab"], +["CS2_061", "# Drain Life"], +["NEW1_003", "# Sacrificial Pact"], +["DS1_185", "# Arcane Shot"], +["EX1_308", "# Soulfire"], +["EX1_302", "# Mortal Coil"], +["EX1_606", "# Shield Block"], +["EX1_278", "# Shiv"], +["EX1_173", "# Starfire"], +["CS2_008", "# Moonfire"], +["EX1_539", "# Kill Command"], +["CS2_024", "# Frostbolt"], +["CS2_037", "# Frost Shock"], +["CS2_057", "# Shadow Bolt"], +["CS2_023", "# Arcane intellect"], +["CS2_077", "# Sprint"], +["CS2_025", "# Arcane Explosion"], +["EX1_277", "# Arcane Missiles"], +["DS1_184", "# Tracking"], +["CS2_075", "# Sinister Strike"], +["DS1_233", "# Mind Blast"], +["CS2_026", "# Frost Nova"], +["EX1_129", "# Fan of Knives"], +["CS2_114", "# Cleave"], +["DS1_183", "# Multishot"], +["CS2_003", "# Mind Vision"], +["CS2_032", "# Flamestrike"], +["EX1_400", "# Whirlwind"], +["CS2_093", "# Consecration"], +["CS1_112", "# Holy Nova"], +["CS2_062", "# Hellfire"], +["CS2_122", "# Raid leader"], +["CS2_222", "# Stormwind champion"], +["EX1_084", "# Warsong Commander"], +["DS1_175", "# Timber Wolf"], +["EX1_399", "# Gurubashi Berserker"], +["EX1_011", "# Voodoo doctor"], +["CS2_189", "# Elven Archer"], +["CS2_042", "# Fire Elemental"], +["CS2_141", "# Ironforge Rifleman"], +["CS2_150", "# Stormpike Commando"], +["CS2_226", "# Frostwolf Warlord"], +["EX1_306", "# Succubus"], +["EX1_581", "# Sap"], +["CS1_113", "# Mind Control"], +["NEW1_004", "# Vanish"], +["CS2_155", "# Archmage"], +["EX1_582", "# Dalaran mage"], +["CS2_142", "# Kobold geomancer"], +["CS2_197", "# Ogre magi"], +["CS2_124", "# Wolfirder"], +["CS2_173", "# Bluegill warrior"], +["NEW1_011", "# Kor'kron elite"], +["CS2_131", "# Stormwind knight"], +["CS2_213", "# Reckless rocketeer"], +["CS2_171", "# Stonetusk boar"], +["CS2_162", "# Lord of the Arena"], +["CS2_187", "# Booty bay bodyguard"], +["CS2_121", "# Frostwolf Grunt"], +["CS1_042", "# Goldshire footman"], +["CS2_232", "# Ironbark protector"], +["CS2_179", "# Sen'jin Shieldmasta"], +["CS2_065", "# Voidwalker"], +["EX1_565", "# Flametongue Totem"], +["CS2_027", "# Mirror Image"], +["NEW1_031", "# Animal Companion"], +["EX1_025", "# Dragonling Mechanic"], +["EX1_506", "# Murloc Tidehunter"], +["CS2_196", "# Razorfen Hunter"], +["CS2_237", "# Starving Buzzard"], +["CS2_119", "# Oasis Snapjaw"], +["CS2_172", "# Bloodfen Raptor"], +["CS2_118", "# Magma Rager"], +["CS2_201", "# Core Hound"], +["CS2_168", "# Murloc Raider"], +["CS2_120", "# River Crocolisk"], +["CS2_200", "# Boulderfist Ogre"], +["CS2_182", "# Chillwind Yeti"], +["CS2_007", "# Healing Touch"], +["CS2_089", "# Holy Light"], +["CS2_080", "# Assassin's Blade"], +["CS2_097", "# Truesilver Champion"], +["CS2_106", "# Fiery War Axe"], +["CS2_091", "# Light's Justice"], +["CS2_112", "# Arcanite reaper"], +]; \ No newline at end of file diff --git a/hm_web/static/cards_hero.js b/hm_web/static/cards_hero.js new file mode 100644 index 0000000..4f39bf7 --- /dev/null +++ b/hm_web/static/cards_hero.js @@ -0,0 +1,16 @@ +var cards_hero = [ +["HERO_01", "# Warrior"], +["HERO_02", "# Shamman"], +["HERO_03", "# Rogue"], +["HERO_04", "# Paladin"], +["HERO_05", "# Hunter"], +["HERO_06", "# Druid"], +["HERO_07", "# Warlock"], +["HERO_08", "# Mage"], +["HERO_09", "# Priest"], +["HERO_01a", "# King of Khaz Modan"], +["HERO_04a", "# Blood Knight Matriarch"], +["HERO_05a", "# Alleria Windranger"], +["HERO_08a", "# Guardian Medivh"], +["HERO_08b", "# Khadgar"], +]; \ No newline at end of file diff --git a/hm_web/static/cards_hp.js b/hm_web/static/cards_hp.js new file mode 100644 index 0000000..7bb416c --- /dev/null +++ b/hm_web/static/cards_hp.js @@ -0,0 +1,3 @@ +var cards_hp = [ +["CS1h_001", "Lesser Heal"], +]; diff --git a/hm_web/static/cardxml0.unity3d b/hm_web/static/cardxml0.unity3d new file mode 100644 index 0000000..31be099 Binary files /dev/null and b/hm_web/static/cardxml0.unity3d differ diff --git a/hm_web/static/checksum b/hm_web/static/checksum new file mode 100644 index 0000000..07a401d --- /dev/null +++ b/hm_web/static/checksum @@ -0,0 +1 @@ +74d2dfa2dabf9111e06635fa618a438c ./static/cardxml0.unity3d diff --git a/hm_web/static/custom/AT_001.jpg b/hm_web/static/custom/AT_001.jpg new file mode 100644 index 0000000..b853938 Binary files /dev/null and b/hm_web/static/custom/AT_001.jpg differ diff --git a/hm_web/static/custom/AT_018.jpg b/hm_web/static/custom/AT_018.jpg new file mode 100644 index 0000000..59352a9 Binary files /dev/null and b/hm_web/static/custom/AT_018.jpg differ diff --git a/hm_web/static/custom/AT_023.jpg b/hm_web/static/custom/AT_023.jpg new file mode 100644 index 0000000..b85b44e Binary files /dev/null and b/hm_web/static/custom/AT_023.jpg differ diff --git a/hm_web/static/custom/AT_074.jpg b/hm_web/static/custom/AT_074.jpg new file mode 100644 index 0000000..dda5182 Binary files /dev/null and b/hm_web/static/custom/AT_074.jpg differ diff --git a/hm_web/static/custom/AT_125.jpg b/hm_web/static/custom/AT_125.jpg new file mode 100644 index 0000000..5f7bfce Binary files /dev/null and b/hm_web/static/custom/AT_125.jpg differ diff --git a/hm_web/static/custom/AT_128.jpg b/hm_web/static/custom/AT_128.jpg new file mode 100644 index 0000000..2850d00 Binary files /dev/null and b/hm_web/static/custom/AT_128.jpg differ diff --git a/hm_web/static/custom/BRMA11_3.jpg b/hm_web/static/custom/BRMA11_3.jpg new file mode 100644 index 0000000..0bf8bcc Binary files /dev/null and b/hm_web/static/custom/BRMA11_3.jpg differ diff --git a/hm_web/static/custom/BRM_003.jpg b/hm_web/static/custom/BRM_003.jpg new file mode 100644 index 0000000..df3511e Binary files /dev/null and b/hm_web/static/custom/BRM_003.jpg differ diff --git a/hm_web/static/custom/CS1_112.jpg b/hm_web/static/custom/CS1_112.jpg new file mode 100644 index 0000000..d538ede Binary files /dev/null and b/hm_web/static/custom/CS1_112.jpg differ diff --git a/hm_web/static/custom/CS1h_001.jpg b/hm_web/static/custom/CS1h_001.jpg new file mode 100644 index 0000000..574e3cd Binary files /dev/null and b/hm_web/static/custom/CS1h_001.jpg differ diff --git a/hm_web/static/custom/CS2_011.jpg b/hm_web/static/custom/CS2_011.jpg new file mode 100644 index 0000000..3f8625d Binary files /dev/null and b/hm_web/static/custom/CS2_011.jpg differ diff --git a/hm_web/static/custom/CS2_023.jpg b/hm_web/static/custom/CS2_023.jpg new file mode 100644 index 0000000..1d00478 Binary files /dev/null and b/hm_web/static/custom/CS2_023.jpg differ diff --git a/hm_web/static/custom/CS2_024.jpg b/hm_web/static/custom/CS2_024.jpg new file mode 100644 index 0000000..ee420ec Binary files /dev/null and b/hm_web/static/custom/CS2_024.jpg differ diff --git a/hm_web/static/custom/CS2_026.jpg b/hm_web/static/custom/CS2_026.jpg new file mode 100644 index 0000000..844d299 Binary files /dev/null and b/hm_web/static/custom/CS2_026.jpg differ diff --git a/hm_web/static/custom/CS2_042.jpg b/hm_web/static/custom/CS2_042.jpg new file mode 100644 index 0000000..675fc01 Binary files /dev/null and b/hm_web/static/custom/CS2_042.jpg differ diff --git a/hm_web/static/custom/CS2_063.jpg b/hm_web/static/custom/CS2_063.jpg new file mode 100644 index 0000000..a955cca Binary files /dev/null and b/hm_web/static/custom/CS2_063.jpg differ diff --git a/hm_web/static/custom/CS2_065.jpg b/hm_web/static/custom/CS2_065.jpg new file mode 100644 index 0000000..b4940e8 Binary files /dev/null and b/hm_web/static/custom/CS2_065.jpg differ diff --git a/hm_web/static/custom/CS2_072.jpg b/hm_web/static/custom/CS2_072.jpg new file mode 100644 index 0000000..172174c Binary files /dev/null and b/hm_web/static/custom/CS2_072.jpg differ diff --git a/hm_web/static/custom/CS2_076.jpg b/hm_web/static/custom/CS2_076.jpg new file mode 100644 index 0000000..61b9854 Binary files /dev/null and b/hm_web/static/custom/CS2_076.jpg differ diff --git a/hm_web/static/custom/CS2_077.jpg b/hm_web/static/custom/CS2_077.jpg new file mode 100644 index 0000000..aac1e37 Binary files /dev/null and b/hm_web/static/custom/CS2_077.jpg differ diff --git a/hm_web/static/custom/CS2_088.jpg b/hm_web/static/custom/CS2_088.jpg new file mode 100644 index 0000000..830b4f3 Binary files /dev/null and b/hm_web/static/custom/CS2_088.jpg differ diff --git a/hm_web/static/custom/CS2_097.jpg b/hm_web/static/custom/CS2_097.jpg new file mode 100644 index 0000000..b2f820e Binary files /dev/null and b/hm_web/static/custom/CS2_097.jpg differ diff --git a/hm_web/static/custom/CS2_108.jpg b/hm_web/static/custom/CS2_108.jpg new file mode 100644 index 0000000..0f7eb3a Binary files /dev/null and b/hm_web/static/custom/CS2_108.jpg differ diff --git a/hm_web/static/custom/CS2_118.jpg b/hm_web/static/custom/CS2_118.jpg new file mode 100644 index 0000000..6ec1c20 Binary files /dev/null and b/hm_web/static/custom/CS2_118.jpg differ diff --git a/hm_web/static/custom/CS2_119.jpg b/hm_web/static/custom/CS2_119.jpg new file mode 100644 index 0000000..3b03f43 Binary files /dev/null and b/hm_web/static/custom/CS2_119.jpg differ diff --git a/hm_web/static/custom/CS2_120.jpg b/hm_web/static/custom/CS2_120.jpg new file mode 100644 index 0000000..a453bbf Binary files /dev/null and b/hm_web/static/custom/CS2_120.jpg differ diff --git a/hm_web/static/custom/CS2_122.jpg b/hm_web/static/custom/CS2_122.jpg new file mode 100644 index 0000000..5ebda80 Binary files /dev/null and b/hm_web/static/custom/CS2_122.jpg differ diff --git a/hm_web/static/custom/CS2_168.jpg b/hm_web/static/custom/CS2_168.jpg new file mode 100644 index 0000000..4b78ed5 Binary files /dev/null and b/hm_web/static/custom/CS2_168.jpg differ diff --git a/hm_web/static/custom/CS2_171.jpg b/hm_web/static/custom/CS2_171.jpg new file mode 100644 index 0000000..e84f3c9 Binary files /dev/null and b/hm_web/static/custom/CS2_171.jpg differ diff --git a/hm_web/static/custom/CS2_172.jpg b/hm_web/static/custom/CS2_172.jpg new file mode 100644 index 0000000..4facc4d Binary files /dev/null and b/hm_web/static/custom/CS2_172.jpg differ diff --git a/hm_web/static/custom/CS2_182.jpg b/hm_web/static/custom/CS2_182.jpg new file mode 100644 index 0000000..10c1c92 Binary files /dev/null and b/hm_web/static/custom/CS2_182.jpg differ diff --git a/hm_web/static/custom/CS2_200.jpg b/hm_web/static/custom/CS2_200.jpg new file mode 100644 index 0000000..f756f76 Binary files /dev/null and b/hm_web/static/custom/CS2_200.jpg differ diff --git a/hm_web/static/custom/CS2_201.jpg b/hm_web/static/custom/CS2_201.jpg new file mode 100644 index 0000000..0399b62 Binary files /dev/null and b/hm_web/static/custom/CS2_201.jpg differ diff --git a/hm_web/static/custom/CS2_222.jpg b/hm_web/static/custom/CS2_222.jpg new file mode 100644 index 0000000..417c50b Binary files /dev/null and b/hm_web/static/custom/CS2_222.jpg differ diff --git a/hm_web/static/custom/CS2_226.jpg b/hm_web/static/custom/CS2_226.jpg new file mode 100644 index 0000000..5db2694 Binary files /dev/null and b/hm_web/static/custom/CS2_226.jpg differ diff --git a/hm_web/static/custom/CS2_231.jpg b/hm_web/static/custom/CS2_231.jpg new file mode 100644 index 0000000..d6194a2 Binary files /dev/null and b/hm_web/static/custom/CS2_231.jpg differ diff --git a/hm_web/static/custom/CS2_234.jpg b/hm_web/static/custom/CS2_234.jpg new file mode 100644 index 0000000..bcf8180 Binary files /dev/null and b/hm_web/static/custom/CS2_234.jpg differ diff --git a/hm_web/static/custom/CS2_237.jpg b/hm_web/static/custom/CS2_237.jpg new file mode 100644 index 0000000..ff14cc2 Binary files /dev/null and b/hm_web/static/custom/CS2_237.jpg differ diff --git a/hm_web/static/custom/CS2_boar.jpg b/hm_web/static/custom/CS2_boar.jpg new file mode 100644 index 0000000..3efd50e Binary files /dev/null and b/hm_web/static/custom/CS2_boar.jpg differ diff --git a/hm_web/static/custom/DS1_185.jpg b/hm_web/static/custom/DS1_185.jpg new file mode 100644 index 0000000..ffc252e Binary files /dev/null and b/hm_web/static/custom/DS1_185.jpg differ diff --git a/hm_web/static/custom/EX1_009.jpg b/hm_web/static/custom/EX1_009.jpg new file mode 100644 index 0000000..b841b15 Binary files /dev/null and b/hm_web/static/custom/EX1_009.jpg differ diff --git a/hm_web/static/custom/EX1_011.jpg b/hm_web/static/custom/EX1_011.jpg new file mode 100644 index 0000000..f8dc474 Binary files /dev/null and b/hm_web/static/custom/EX1_011.jpg differ diff --git a/hm_web/static/custom/EX1_049.jpg b/hm_web/static/custom/EX1_049.jpg new file mode 100644 index 0000000..38d671e Binary files /dev/null and b/hm_web/static/custom/EX1_049.jpg differ diff --git a/hm_web/static/custom/EX1_097.jpg b/hm_web/static/custom/EX1_097.jpg new file mode 100644 index 0000000..d684e27 Binary files /dev/null and b/hm_web/static/custom/EX1_097.jpg differ diff --git a/hm_web/static/custom/EX1_105.jpg b/hm_web/static/custom/EX1_105.jpg new file mode 100644 index 0000000..ca5b4fb Binary files /dev/null and b/hm_web/static/custom/EX1_105.jpg differ diff --git a/hm_web/static/custom/EX1_158t.jpg b/hm_web/static/custom/EX1_158t.jpg new file mode 100644 index 0000000..be03a17 Binary files /dev/null and b/hm_web/static/custom/EX1_158t.jpg differ diff --git a/hm_web/static/custom/EX1_165t2.jpg b/hm_web/static/custom/EX1_165t2.jpg new file mode 100644 index 0000000..19b654c Binary files /dev/null and b/hm_web/static/custom/EX1_165t2.jpg differ diff --git a/hm_web/static/custom/EX1_251.jpg b/hm_web/static/custom/EX1_251.jpg new file mode 100644 index 0000000..0d669b3 Binary files /dev/null and b/hm_web/static/custom/EX1_251.jpg differ diff --git a/hm_web/static/custom/EX1_259.jpg b/hm_web/static/custom/EX1_259.jpg new file mode 100644 index 0000000..6041f74 Binary files /dev/null and b/hm_web/static/custom/EX1_259.jpg differ diff --git a/hm_web/static/custom/EX1_303.jpg b/hm_web/static/custom/EX1_303.jpg new file mode 100644 index 0000000..7cc8ab1 Binary files /dev/null and b/hm_web/static/custom/EX1_303.jpg differ diff --git a/hm_web/static/custom/EX1_306.jpg b/hm_web/static/custom/EX1_306.jpg new file mode 100644 index 0000000..c5f1320 Binary files /dev/null and b/hm_web/static/custom/EX1_306.jpg differ diff --git a/hm_web/static/custom/EX1_312.jpg b/hm_web/static/custom/EX1_312.jpg new file mode 100644 index 0000000..8297ae8 Binary files /dev/null and b/hm_web/static/custom/EX1_312.jpg differ diff --git a/hm_web/static/custom/EX1_383.jpg b/hm_web/static/custom/EX1_383.jpg new file mode 100644 index 0000000..785cf81 Binary files /dev/null and b/hm_web/static/custom/EX1_383.jpg differ diff --git a/hm_web/static/custom/EX1_400.jpg b/hm_web/static/custom/EX1_400.jpg new file mode 100644 index 0000000..ccf8608 Binary files /dev/null and b/hm_web/static/custom/EX1_400.jpg differ diff --git a/hm_web/static/custom/EX1_506a.jpg b/hm_web/static/custom/EX1_506a.jpg new file mode 100644 index 0000000..32504ca Binary files /dev/null and b/hm_web/static/custom/EX1_506a.jpg differ diff --git a/hm_web/static/custom/EX1_559.jpg b/hm_web/static/custom/EX1_559.jpg new file mode 100644 index 0000000..19ea9ec Binary files /dev/null and b/hm_web/static/custom/EX1_559.jpg differ diff --git a/hm_web/static/custom/EX1_581.jpg b/hm_web/static/custom/EX1_581.jpg new file mode 100644 index 0000000..2526729 Binary files /dev/null and b/hm_web/static/custom/EX1_581.jpg differ diff --git a/hm_web/static/custom/EX1_593.jpg b/hm_web/static/custom/EX1_593.jpg new file mode 100644 index 0000000..cc97662 Binary files /dev/null and b/hm_web/static/custom/EX1_593.jpg differ diff --git a/hm_web/static/custom/EX1_607.jpg b/hm_web/static/custom/EX1_607.jpg new file mode 100644 index 0000000..9c2ddde Binary files /dev/null and b/hm_web/static/custom/EX1_607.jpg differ diff --git a/hm_web/static/custom/EX1_614.jpg b/hm_web/static/custom/EX1_614.jpg new file mode 100644 index 0000000..a0dd75b Binary files /dev/null and b/hm_web/static/custom/EX1_614.jpg differ diff --git a/hm_web/static/custom/GVG_010.jpg b/hm_web/static/custom/GVG_010.jpg new file mode 100644 index 0000000..b6e61c5 Binary files /dev/null and b/hm_web/static/custom/GVG_010.jpg differ diff --git a/hm_web/static/custom/GVG_105.jpg b/hm_web/static/custom/GVG_105.jpg new file mode 100644 index 0000000..b46a84a Binary files /dev/null and b/hm_web/static/custom/GVG_105.jpg differ diff --git a/hm_web/static/custom/LOEA04_01.jpg b/hm_web/static/custom/LOEA04_01.jpg new file mode 100644 index 0000000..d3e1988 Binary files /dev/null and b/hm_web/static/custom/LOEA04_01.jpg differ diff --git a/hm_web/static/custom/LOEA06_03.jpg b/hm_web/static/custom/LOEA06_03.jpg new file mode 100644 index 0000000..dc0844d Binary files /dev/null and b/hm_web/static/custom/LOEA06_03.jpg differ diff --git a/hm_web/static/custom/LOEA16_3.jpg b/hm_web/static/custom/LOEA16_3.jpg new file mode 100644 index 0000000..66c939a Binary files /dev/null and b/hm_web/static/custom/LOEA16_3.jpg differ diff --git a/hm_web/static/custom/LOEA16_9.jpg b/hm_web/static/custom/LOEA16_9.jpg new file mode 100644 index 0000000..ab2ce5e Binary files /dev/null and b/hm_web/static/custom/LOEA16_9.jpg differ diff --git a/hm_web/static/custom/LOE_077.jpg b/hm_web/static/custom/LOE_077.jpg new file mode 100644 index 0000000..bc71514 Binary files /dev/null and b/hm_web/static/custom/LOE_077.jpg differ diff --git a/hm_web/static/custom/LOE_118.jpg b/hm_web/static/custom/LOE_118.jpg new file mode 100644 index 0000000..f9d394d Binary files /dev/null and b/hm_web/static/custom/LOE_118.jpg differ diff --git a/hm_web/static/custom/NAX4_03.jpg b/hm_web/static/custom/NAX4_03.jpg new file mode 100644 index 0000000..18658b3 Binary files /dev/null and b/hm_web/static/custom/NAX4_03.jpg differ diff --git a/hm_web/static/custom/NAX4_03H.jpg b/hm_web/static/custom/NAX4_03H.jpg new file mode 100644 index 0000000..3fed830 Binary files /dev/null and b/hm_web/static/custom/NAX4_03H.jpg differ diff --git a/hm_web/static/custom/NEW1_011.jpg b/hm_web/static/custom/NEW1_011.jpg new file mode 100644 index 0000000..bc64830 Binary files /dev/null and b/hm_web/static/custom/NEW1_011.jpg differ diff --git a/hm_web/static/custom/NEW1_030.jpg b/hm_web/static/custom/NEW1_030.jpg new file mode 100644 index 0000000..0e5c7d0 Binary files /dev/null and b/hm_web/static/custom/NEW1_030.jpg differ diff --git a/hm_web/static/custom/NEW1_036.jpg b/hm_web/static/custom/NEW1_036.jpg new file mode 100644 index 0000000..2b96e19 Binary files /dev/null and b/hm_web/static/custom/NEW1_036.jpg differ diff --git a/hm_web/static/custom/OG_090.jpg b/hm_web/static/custom/OG_090.jpg new file mode 100644 index 0000000..8223edf Binary files /dev/null and b/hm_web/static/custom/OG_090.jpg differ diff --git a/hm_web/static/custom/OG_101.jpg b/hm_web/static/custom/OG_101.jpg new file mode 100644 index 0000000..cf4e6b6 Binary files /dev/null and b/hm_web/static/custom/OG_101.jpg differ diff --git a/hm_web/static/custom/OG_223.jpg b/hm_web/static/custom/OG_223.jpg new file mode 100644 index 0000000..71ea221 Binary files /dev/null and b/hm_web/static/custom/OG_223.jpg differ diff --git a/hm_web/static/custom/PRO_001c.jpg b/hm_web/static/custom/PRO_001c.jpg new file mode 100644 index 0000000..26d8cb0 Binary files /dev/null and b/hm_web/static/custom/PRO_001c.jpg differ diff --git a/hm_web/static/custom/TB_SPT_Boss.jpg b/hm_web/static/custom/TB_SPT_Boss.jpg new file mode 100644 index 0000000..5e8f985 Binary files /dev/null and b/hm_web/static/custom/TB_SPT_Boss.jpg differ diff --git a/hm_web/static/custom/custom_AT_018.png b/hm_web/static/custom/custom_AT_018.png new file mode 100644 index 0000000..d63462c Binary files /dev/null and b/hm_web/static/custom/custom_AT_018.png differ diff --git a/hm_web/static/custom/custom_CS1_112.png b/hm_web/static/custom/custom_CS1_112.png new file mode 100644 index 0000000..11efdc6 Binary files /dev/null and b/hm_web/static/custom/custom_CS1_112.png differ diff --git a/hm_web/static/custom/custom_CS2_065.png b/hm_web/static/custom/custom_CS2_065.png new file mode 100644 index 0000000..4702c88 Binary files /dev/null and b/hm_web/static/custom/custom_CS2_065.png differ diff --git a/hm_web/static/custom/custom_CS2_097.png b/hm_web/static/custom/custom_CS2_097.png new file mode 100644 index 0000000..1dfcc0f Binary files /dev/null and b/hm_web/static/custom/custom_CS2_097.png differ diff --git a/hm_web/static/custom/custom_CS2_118.png b/hm_web/static/custom/custom_CS2_118.png new file mode 100644 index 0000000..e153df1 Binary files /dev/null and b/hm_web/static/custom/custom_CS2_118.png differ diff --git a/hm_web/static/custom/custom_EX1_165t2.png b/hm_web/static/custom/custom_EX1_165t2.png new file mode 100644 index 0000000..a4a15c6 Binary files /dev/null and b/hm_web/static/custom/custom_EX1_165t2.png differ diff --git a/hm_web/static/custom/custom_EX1_383.png b/hm_web/static/custom/custom_EX1_383.png new file mode 100644 index 0000000..350926f Binary files /dev/null and b/hm_web/static/custom/custom_EX1_383.png differ diff --git a/hm_web/static/custom/custom_EX1_559.png b/hm_web/static/custom/custom_EX1_559.png new file mode 100644 index 0000000..e15a8b8 Binary files /dev/null and b/hm_web/static/custom/custom_EX1_559.png differ diff --git a/hm_web/static/custom/custom_EX1_607.png b/hm_web/static/custom/custom_EX1_607.png new file mode 100644 index 0000000..b554425 Binary files /dev/null and b/hm_web/static/custom/custom_EX1_607.png differ diff --git a/hm_web/static/custom/custom_LOE_118.png b/hm_web/static/custom/custom_LOE_118.png new file mode 100644 index 0000000..a190503 Binary files /dev/null and b/hm_web/static/custom/custom_LOE_118.png differ diff --git a/hm_web/static/custom/custom_NEW1_011.png b/hm_web/static/custom/custom_NEW1_011.png new file mode 100644 index 0000000..ef6ed6c Binary files /dev/null and b/hm_web/static/custom/custom_NEW1_011.png differ diff --git a/hm_web/static/hbs.css b/hm_web/static/hbs.css new file mode 100644 index 0000000..2fcc0e0 --- /dev/null +++ b/hm_web/static/hbs.css @@ -0,0 +1,35 @@ +body { + color: #3E3E3E; + background-color: #FBFFFF; + margin: 30px; + font-family: Verdana; +} + + +.form { + display: block; + position: relative; + margin-left: auto; + margin-right: auto; + width: 700px; + } + +.textfield { + width: 600px; + } + + +.button { + position: absolute; + top: 10%; + right: 10px; + font-family: Verdana; + font-weight: bold; + background-color:#FBFFF; + border:1px solid; + border-color: #696 #363 #363 #696; + } + + + + \ No newline at end of file diff --git a/hm_web/static/hsf/bootstrap-theme.min.css b/hm_web/static/hsf/bootstrap-theme.min.css new file mode 100644 index 0000000..5e39401 --- /dev/null +++ b/hm_web/static/hsf/bootstrap-theme.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} +/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/hm_web/static/hsf/bootstrap.min.css b/hm_web/static/hsf/bootstrap.min.css new file mode 100644 index 0000000..ed3905e --- /dev/null +++ b/hm_web/static/hsf/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/hm_web/static/hsf/cayman.css b/hm_web/static/hsf/cayman.css new file mode 100644 index 0000000..232882b --- /dev/null +++ b/hm_web/static/hsf/cayman.css @@ -0,0 +1,471 @@ +* { + box-sizing: border-box; +} + +body { + padding: 0; + margin: 0; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 1.5; + color: #F3F9FA; + background-color: #000; + background-size: contain; + background-repeat: repeat; + background-attachment: scroll; + background-position: center top; + overflow: hidden; + overflow-x:hidden; +} + +img { + margin-left: 20px; + margin-right: 20px; +} + +a { + color: #1e6bb8; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +#video-container { + overflow: hidden; + overflow-x:hidden; +} +video { + z-index:-100; + overflow: hidden; + overflow-x:hidden; + + position: absolute; + top: 50%; + left: 50%; + width: auto; + height: 100%; + min-width: 100%; + min-height: 100%; + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +button { + background: #1C491E; + background-image: -webkit-radial-gradient(top, #4CAF50, #1C491E); + background-image: -moz-radial-gradient(top, #4CAF50, #1C491E); + background-image: -ms-radial-gradient(top, #4CAF50, #1C491E); + background-image: -o-radial-gradient(top, #4CAF50, #1C491E); + background-image: radial-gradient(to bottom, #4CAF50, #1C491E); + -webkit-border-radius: 10; + -moz-border-radius: 10; + border-radius: 10px; + font-family: Arial; + color: #ffffff; + font-size: 20px; + padding: 5px 20px 5px 20px; + border: solid #1f628d 0px; + text-decoration: none; +} + +button:hover { + background: #66BB6A; + background-image: -webkit-radial-gradient(top, #74D378, #1C491E); + background-image: -moz-radial-gradient(top, #74D378, #1C491E); + background-image: -ms-radial-gradient(top, #74D378, #1C491E); + background-image: -o-radial-gradient(top, #74D378, #1C491E); + background-image: radial-gradient(to bottom, #74D378, #1C491E); + text-decoration: none; +} + +.btn { + position: relative; + display: inline-block; + margin-bottom: 1rem; + color: rgba(255, 255, 255, 0.7); + background-color: rgba(0, 0, 0, 0.65); + border-color: rgba(255, 255, 255, 0.2); + border-style: solid; + border-width: 1px; + border-radius: 0.3rem; + transition: color 0.2s, background-color 0.2s, border-color 0.2s; +} + +.btn:hover { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + background-color: rgba(255, 255, 255, 0.2); + border-color: rgba(255, 255, 255, 0.3); +} + +.btn+ .btn { + margin-left: 1rem; +} + +@media screen and (min-width: 64em) { + .btn { + padding: 0.75rem 1rem; + } +} + +@media screen and (min-width: 42em) and (max-width: 64em) { + .btn { + padding: 0.6rem 0.9rem; + font-size: 0.9rem; + } +} + +@media screen and (max-width: 42em) { + .btn { + display: block; + width: 100%; + padding: 0.75rem; + font-size: 0.9rem; + } + .btn+ .btn { + margin-top: 1rem; + margin-left: 0; + } +} + +.page-header { + color: #fff; + text-align: center; + vertical-align: middle; + position: absolute; + top: 25%; left: 0; bottom: 25%; right: 0; + border-bottom: 0px; +} + +@media screen and (min-width: 64em) { + .page-header { + padding: 5rem 6rem; + } +} + +@media screen and (min-width: 42em) and (max-width: 64em) { + .page-header { + padding: 3rem 4rem; + } +} + +@media screen and (max-width: 42em) { + .page-header { + padding: 2rem 1rem; + } +} + +.project-name { + margin-top: 0; + margin-bottom: 0.1rem; + color: #fff; + text-shadow:0 0 40px #000, 0 0 20px #000; +} + +@media screen and (min-width: 64em) { + .project-name { + font-size: 3.25rem; + } +} + +@media screen and (min-width: 42em) and (max-width: 64em) { + .project-name { + font-size: 2.25rem; + } +} + +@media screen and (max-width: 42em) { + .project-name { + font-size: 1.75rem; + } +} + +.project-tagline { + margin-top: 2rem; + margin-bottom: 1rem; + font-weight: normal; + color: #fff; + text-shadow:0 0 150px #000, 0 0 100px #000, 0 0 50px #000, 0 0 20px #000; +} + +@media screen and (min-width: 64em) { + .project-tagline { + font-size: 1.25rem; + } +} + +@media screen and (min-width: 42em) and (max-width: 64em) { + .project-tagline { + font-size: 1.15rem; + } +} + +@media screen and (max-width: 42em) { + .project-tagline { + font-size: 1rem; + } +} + +.main-content { + word-wrap: break-word; +} + +.main-content:first-child { + margin-top: 0; +} + +@media screen and (min-width: 64em) { + .main-content { + max-width: 75rem; + padding: 2rem 6rem; + margin: 0 auto; + font-size: 1.1rem; + } +} + +@media screen and (min-width: 42em) and (max-width: 64em) { + .main-content { + padding: 2rem 4rem; + font-size: 1.1rem; + } +} + +@media screen and (max-width: 42em) { + .main-content { + padding: 2rem 1rem; + font-size: 1rem; + } +} + +.main-content img { + max-width: 100%; +} + +.main-content h1 { + margin-top: 2rem; + margin-bottom: 1rem; + font-weight: normal; + color: #13ff29; + text-shadow:0 0 80px #10d222, 0 0 60px rgba(16, 210, 34, 0.9), 0 0 40px rgba(16, 210, 34, 0.8), 0 0 20px rgba(16, 210, 34, 0.7); +} +.main-content h2, +.main-content h3, +.main-content h4, +.main-content h5, +.main-content h6 { + margin-top: 2rem; + margin-bottom: 1rem; + font-weight: normal; + color: #13ff29; + text-shadow:0 0 40px rgba(16, 210, 34, 0.8), 0 0 20px rgba(16, 210, 34, 0.7); +} + +.main-content h4w { + margin-top: 2rem; + margin-bottom: 1em; + font-weight: normal; + color: #F3F9FA; + text-shadow:0 0 0 #000; +} + +.main-content p { + margin-bottom: 1em; + text-shadow: 0 0 6px rgba(255, 191, 55, 0.5) +} + +.main-content green { + color: #13ff29; + text-shadow:0 0 40px rgba(16, 210, 34, 0.8), 0 0 20px rgba(16, 210, 34, 0.7); +} + +.main-content code { + padding: 2px 4px; + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 0.9rem; + color: #567482; + background-color: #f3f6fa; + border-radius: 0.3rem; +} + +.main-content pre { + padding: 0.8rem; + margin-top: 0; + margin-bottom: 1rem; + font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace; + color: #567482; + word-wrap: normal; + background-color: #f3f6fa; + border: solid 1px #dce6f0; + border-radius: 0.3rem; +} + +.main-content pre> code { + padding: 0; + margin: 0; + font-size: 0.9rem; + color: #567482; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.main-content .highlight { + margin-bottom: 1rem; +} + +.main-content .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.main-content .highlight pre, +.main-content pre { + padding: 0.8rem; + overflow: auto; + font-size: 0.9rem; + line-height: 1.45; + border-radius: 0.3rem; + -webkit-overflow-scrolling: touch; +} + +.main-content pre code, +.main-content pre tt { + display: inline; + max-width: initial; + padding: 0; + margin: 0; + overflow: initial; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.main-content pre code:before, +.main-content pre code:after, +.main-content pre tt:before, +.main-content pre tt:after { + content: normal; +} + +.main-content ul, +.main-content ol { + margin-top: 0; +} + +.main-content blockquote { + padding: 0 1rem; + margin-left: 0; + color: #819198; + border-left: 0.3rem solid #dce6f0; +} + +.main-content blockquote>:first-child { + margin-top: 0; +} + +.main-content blockquote>:last-child { + margin-bottom: 0; +} + +.main-content table { + display: block; + width: 100%; + overflow: auto; + word-break: normal; + word-break: keep-all; + -webkit-overflow-scrolling: touch; +} + +.main-content table th { + font-weight: bold; +} + +.main-content table th, +.main-content table td { + padding: 0.5rem 1rem; + border: 1px solid #e9ebec; +} + +.main-content dl { + padding: 0; +} + +.main-content dl dt { + padding: 0; + margin-top: 1rem; + font-size: 1rem; + font-weight: bold; +} + +.main-content dl dd { + padding: 0; + margin-bottom: 1rem; +} + +.main-content hr { + height: 2px; + padding: 0; + margin: 1rem 0; + background-color: #eff0f1; + border: 0; +} + +.site-footer { + padding-top: 2rem; + margin-top: 2rem; +} + +@media screen and (min-width: 64em) { + .site-footer { + font-size: 1rem; + } +} + +@media screen and (min-width: 42em) and (max-width: 64em) { + .site-footer { + font-size: 1rem; + } +} + +@media screen and (max-width: 42em) { + .site-footer { + font-size: 0.9rem; + } +} + +.site-footer-owner { + display: block; + font-weight: bold; +} + +.site-footer-credits { + color: #819198; +} + +.sldr { + max-width: 500px; + margin: 0 auto; + overflow: visible; + position: relative; + clear: both; + display: block; +} + +.sldr> ul.animate { + -webkit-transition: margin 0.75s cubic-bezier(0.860, 0.000, 0.070, 1.000); + -moz-transition: margin 0.75s cubic-bezier(0.860, 0.000, 0.070, 1.000); + -o-transition: margin 0.75s cubic-bezier(0.860, 0.000, 0.070, 1.000); + transition: margin 0.75s cubic-bezier(0.860, 0.000, 0.070, 1.000); + /* ease-in-out */ +} + +.sldr> ul> li { + float: left; + display: block; +} diff --git a/hm_web/static/hsf/ic_chat_black_48px.svg b/hm_web/static/hsf/ic_chat_black_48px.svg new file mode 100644 index 0000000..eedda2a --- /dev/null +++ b/hm_web/static/hsf/ic_chat_black_48px.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/hm_web/static/hsf/normalize.css b/hm_web/static/hsf/normalize.css new file mode 100644 index 0000000..30366a6 --- /dev/null +++ b/hm_web/static/hsf/normalize.css @@ -0,0 +1,424 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/hm_web/static/images/AT_001.png b/hm_web/static/images/AT_001.png new file mode 100644 index 0000000..933c0fb Binary files /dev/null and b/hm_web/static/images/AT_001.png differ diff --git a/hm_web/static/images/AT_002.png b/hm_web/static/images/AT_002.png new file mode 100644 index 0000000..78e8c02 Binary files /dev/null and b/hm_web/static/images/AT_002.png differ diff --git a/hm_web/static/images/AT_003.png b/hm_web/static/images/AT_003.png new file mode 100644 index 0000000..c306ca0 Binary files /dev/null and b/hm_web/static/images/AT_003.png differ diff --git a/hm_web/static/images/AT_004.png b/hm_web/static/images/AT_004.png new file mode 100644 index 0000000..548d628 Binary files /dev/null and b/hm_web/static/images/AT_004.png differ diff --git a/hm_web/static/images/AT_005.png b/hm_web/static/images/AT_005.png new file mode 100644 index 0000000..0f18958 Binary files /dev/null and b/hm_web/static/images/AT_005.png differ diff --git a/hm_web/static/images/AT_005t.png b/hm_web/static/images/AT_005t.png new file mode 100644 index 0000000..dff7494 Binary files /dev/null and b/hm_web/static/images/AT_005t.png differ diff --git a/hm_web/static/images/AT_006.png b/hm_web/static/images/AT_006.png new file mode 100644 index 0000000..fcc2923 Binary files /dev/null and b/hm_web/static/images/AT_006.png differ diff --git a/hm_web/static/images/AT_006e.png b/hm_web/static/images/AT_006e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_006e.png differ diff --git a/hm_web/static/images/AT_007.png b/hm_web/static/images/AT_007.png new file mode 100644 index 0000000..1880bbf Binary files /dev/null and b/hm_web/static/images/AT_007.png differ diff --git a/hm_web/static/images/AT_008.png b/hm_web/static/images/AT_008.png new file mode 100644 index 0000000..63f6350 Binary files /dev/null and b/hm_web/static/images/AT_008.png differ diff --git a/hm_web/static/images/AT_009.png b/hm_web/static/images/AT_009.png new file mode 100644 index 0000000..cb2d930 Binary files /dev/null and b/hm_web/static/images/AT_009.png differ diff --git a/hm_web/static/images/AT_010.png b/hm_web/static/images/AT_010.png new file mode 100644 index 0000000..284449e Binary files /dev/null and b/hm_web/static/images/AT_010.png differ diff --git a/hm_web/static/images/AT_011.png b/hm_web/static/images/AT_011.png new file mode 100644 index 0000000..d09b74a Binary files /dev/null and b/hm_web/static/images/AT_011.png differ diff --git a/hm_web/static/images/AT_011e.png b/hm_web/static/images/AT_011e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_011e.png differ diff --git a/hm_web/static/images/AT_012.png b/hm_web/static/images/AT_012.png new file mode 100644 index 0000000..9ad07e1 Binary files /dev/null and b/hm_web/static/images/AT_012.png differ diff --git a/hm_web/static/images/AT_013.png b/hm_web/static/images/AT_013.png new file mode 100644 index 0000000..b1e9fd0 Binary files /dev/null and b/hm_web/static/images/AT_013.png differ diff --git a/hm_web/static/images/AT_013e.png b/hm_web/static/images/AT_013e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_013e.png differ diff --git a/hm_web/static/images/AT_014.png b/hm_web/static/images/AT_014.png new file mode 100644 index 0000000..5cdf062 Binary files /dev/null and b/hm_web/static/images/AT_014.png differ diff --git a/hm_web/static/images/AT_014e.png b/hm_web/static/images/AT_014e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_014e.png differ diff --git a/hm_web/static/images/AT_015.png b/hm_web/static/images/AT_015.png new file mode 100644 index 0000000..8f879f7 Binary files /dev/null and b/hm_web/static/images/AT_015.png differ diff --git a/hm_web/static/images/AT_016.png b/hm_web/static/images/AT_016.png new file mode 100644 index 0000000..540e1a1 Binary files /dev/null and b/hm_web/static/images/AT_016.png differ diff --git a/hm_web/static/images/AT_016e.png b/hm_web/static/images/AT_016e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_016e.png differ diff --git a/hm_web/static/images/AT_017.png b/hm_web/static/images/AT_017.png new file mode 100644 index 0000000..e3425fc Binary files /dev/null and b/hm_web/static/images/AT_017.png differ diff --git a/hm_web/static/images/AT_017e.png b/hm_web/static/images/AT_017e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_017e.png differ diff --git a/hm_web/static/images/AT_018.png b/hm_web/static/images/AT_018.png new file mode 100644 index 0000000..f62a8e2 Binary files /dev/null and b/hm_web/static/images/AT_018.png differ diff --git a/hm_web/static/images/AT_019.png b/hm_web/static/images/AT_019.png new file mode 100644 index 0000000..e0ccd0b Binary files /dev/null and b/hm_web/static/images/AT_019.png differ diff --git a/hm_web/static/images/AT_020.png b/hm_web/static/images/AT_020.png new file mode 100644 index 0000000..0100794 Binary files /dev/null and b/hm_web/static/images/AT_020.png differ diff --git a/hm_web/static/images/AT_021.png b/hm_web/static/images/AT_021.png new file mode 100644 index 0000000..7a768a1 Binary files /dev/null and b/hm_web/static/images/AT_021.png differ diff --git a/hm_web/static/images/AT_021e.png b/hm_web/static/images/AT_021e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_021e.png differ diff --git a/hm_web/static/images/AT_022.png b/hm_web/static/images/AT_022.png new file mode 100644 index 0000000..a99bb80 Binary files /dev/null and b/hm_web/static/images/AT_022.png differ diff --git a/hm_web/static/images/AT_023.png b/hm_web/static/images/AT_023.png new file mode 100644 index 0000000..ce691e5 Binary files /dev/null and b/hm_web/static/images/AT_023.png differ diff --git a/hm_web/static/images/AT_024.png b/hm_web/static/images/AT_024.png new file mode 100644 index 0000000..c859633 Binary files /dev/null and b/hm_web/static/images/AT_024.png differ diff --git a/hm_web/static/images/AT_024e.png b/hm_web/static/images/AT_024e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_024e.png differ diff --git a/hm_web/static/images/AT_025.png b/hm_web/static/images/AT_025.png new file mode 100644 index 0000000..8b1785a Binary files /dev/null and b/hm_web/static/images/AT_025.png differ diff --git a/hm_web/static/images/AT_026.png b/hm_web/static/images/AT_026.png new file mode 100644 index 0000000..78ff2af Binary files /dev/null and b/hm_web/static/images/AT_026.png differ diff --git a/hm_web/static/images/AT_027.png b/hm_web/static/images/AT_027.png new file mode 100644 index 0000000..fccdcc1 Binary files /dev/null and b/hm_web/static/images/AT_027.png differ diff --git a/hm_web/static/images/AT_027e.png b/hm_web/static/images/AT_027e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_027e.png differ diff --git a/hm_web/static/images/AT_028.png b/hm_web/static/images/AT_028.png new file mode 100644 index 0000000..1d7d4be Binary files /dev/null and b/hm_web/static/images/AT_028.png differ diff --git a/hm_web/static/images/AT_028e.png b/hm_web/static/images/AT_028e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_028e.png differ diff --git a/hm_web/static/images/AT_029.png b/hm_web/static/images/AT_029.png new file mode 100644 index 0000000..a6fa276 Binary files /dev/null and b/hm_web/static/images/AT_029.png differ diff --git a/hm_web/static/images/AT_029e.png b/hm_web/static/images/AT_029e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_029e.png differ diff --git a/hm_web/static/images/AT_030.png b/hm_web/static/images/AT_030.png new file mode 100644 index 0000000..5f6973f Binary files /dev/null and b/hm_web/static/images/AT_030.png differ diff --git a/hm_web/static/images/AT_031.png b/hm_web/static/images/AT_031.png new file mode 100644 index 0000000..ea25125 Binary files /dev/null and b/hm_web/static/images/AT_031.png differ diff --git a/hm_web/static/images/AT_032.png b/hm_web/static/images/AT_032.png new file mode 100644 index 0000000..15ab8b9 Binary files /dev/null and b/hm_web/static/images/AT_032.png differ diff --git a/hm_web/static/images/AT_032e.png b/hm_web/static/images/AT_032e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_032e.png differ diff --git a/hm_web/static/images/AT_033.png b/hm_web/static/images/AT_033.png new file mode 100644 index 0000000..1deb575 Binary files /dev/null and b/hm_web/static/images/AT_033.png differ diff --git a/hm_web/static/images/AT_034.png b/hm_web/static/images/AT_034.png new file mode 100644 index 0000000..f9eb97e Binary files /dev/null and b/hm_web/static/images/AT_034.png differ diff --git a/hm_web/static/images/AT_034e.png b/hm_web/static/images/AT_034e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_034e.png differ diff --git a/hm_web/static/images/AT_035.png b/hm_web/static/images/AT_035.png new file mode 100644 index 0000000..1539c89 Binary files /dev/null and b/hm_web/static/images/AT_035.png differ diff --git a/hm_web/static/images/AT_035t.png b/hm_web/static/images/AT_035t.png new file mode 100644 index 0000000..84e417a Binary files /dev/null and b/hm_web/static/images/AT_035t.png differ diff --git a/hm_web/static/images/AT_036.png b/hm_web/static/images/AT_036.png new file mode 100644 index 0000000..45fd378 Binary files /dev/null and b/hm_web/static/images/AT_036.png differ diff --git a/hm_web/static/images/AT_036t.png b/hm_web/static/images/AT_036t.png new file mode 100644 index 0000000..c98701a Binary files /dev/null and b/hm_web/static/images/AT_036t.png differ diff --git a/hm_web/static/images/AT_037.png b/hm_web/static/images/AT_037.png new file mode 100644 index 0000000..99764e2 Binary files /dev/null and b/hm_web/static/images/AT_037.png differ diff --git a/hm_web/static/images/AT_037a.png b/hm_web/static/images/AT_037a.png new file mode 100644 index 0000000..b701276 Binary files /dev/null and b/hm_web/static/images/AT_037a.png differ diff --git a/hm_web/static/images/AT_037b.png b/hm_web/static/images/AT_037b.png new file mode 100644 index 0000000..5f105d5 Binary files /dev/null and b/hm_web/static/images/AT_037b.png differ diff --git a/hm_web/static/images/AT_037t.png b/hm_web/static/images/AT_037t.png new file mode 100644 index 0000000..f1a776f Binary files /dev/null and b/hm_web/static/images/AT_037t.png differ diff --git a/hm_web/static/images/AT_038.png b/hm_web/static/images/AT_038.png new file mode 100644 index 0000000..cade99a Binary files /dev/null and b/hm_web/static/images/AT_038.png differ diff --git a/hm_web/static/images/AT_039.png b/hm_web/static/images/AT_039.png new file mode 100644 index 0000000..c879f00 Binary files /dev/null and b/hm_web/static/images/AT_039.png differ diff --git a/hm_web/static/images/AT_039e.png b/hm_web/static/images/AT_039e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_039e.png differ diff --git a/hm_web/static/images/AT_040.png b/hm_web/static/images/AT_040.png new file mode 100644 index 0000000..ef40cb0 Binary files /dev/null and b/hm_web/static/images/AT_040.png differ diff --git a/hm_web/static/images/AT_040e.png b/hm_web/static/images/AT_040e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_040e.png differ diff --git a/hm_web/static/images/AT_041.png b/hm_web/static/images/AT_041.png new file mode 100644 index 0000000..278907b Binary files /dev/null and b/hm_web/static/images/AT_041.png differ diff --git a/hm_web/static/images/AT_041e.png b/hm_web/static/images/AT_041e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_041e.png differ diff --git a/hm_web/static/images/AT_042.png b/hm_web/static/images/AT_042.png new file mode 100644 index 0000000..89b80da Binary files /dev/null and b/hm_web/static/images/AT_042.png differ diff --git a/hm_web/static/images/AT_042a.png b/hm_web/static/images/AT_042a.png new file mode 100644 index 0000000..0140afc Binary files /dev/null and b/hm_web/static/images/AT_042a.png differ diff --git a/hm_web/static/images/AT_042b.png b/hm_web/static/images/AT_042b.png new file mode 100644 index 0000000..e2e29f8 Binary files /dev/null and b/hm_web/static/images/AT_042b.png differ diff --git a/hm_web/static/images/AT_042t.png b/hm_web/static/images/AT_042t.png new file mode 100644 index 0000000..6abb42a Binary files /dev/null and b/hm_web/static/images/AT_042t.png differ diff --git a/hm_web/static/images/AT_042t2.png b/hm_web/static/images/AT_042t2.png new file mode 100644 index 0000000..675e886 Binary files /dev/null and b/hm_web/static/images/AT_042t2.png differ diff --git a/hm_web/static/images/AT_043.png b/hm_web/static/images/AT_043.png new file mode 100644 index 0000000..13ddfba Binary files /dev/null and b/hm_web/static/images/AT_043.png differ diff --git a/hm_web/static/images/AT_044.png b/hm_web/static/images/AT_044.png new file mode 100644 index 0000000..151d22b Binary files /dev/null and b/hm_web/static/images/AT_044.png differ diff --git a/hm_web/static/images/AT_045.png b/hm_web/static/images/AT_045.png new file mode 100644 index 0000000..2e521ce Binary files /dev/null and b/hm_web/static/images/AT_045.png differ diff --git a/hm_web/static/images/AT_045e.png b/hm_web/static/images/AT_045e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_045e.png differ diff --git a/hm_web/static/images/AT_045ee.png b/hm_web/static/images/AT_045ee.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_045ee.png differ diff --git a/hm_web/static/images/AT_046.png b/hm_web/static/images/AT_046.png new file mode 100644 index 0000000..42211da Binary files /dev/null and b/hm_web/static/images/AT_046.png differ diff --git a/hm_web/static/images/AT_047.png b/hm_web/static/images/AT_047.png new file mode 100644 index 0000000..07e7389 Binary files /dev/null and b/hm_web/static/images/AT_047.png differ diff --git a/hm_web/static/images/AT_047e.png b/hm_web/static/images/AT_047e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_047e.png differ diff --git a/hm_web/static/images/AT_048.png b/hm_web/static/images/AT_048.png new file mode 100644 index 0000000..e2b9212 Binary files /dev/null and b/hm_web/static/images/AT_048.png differ diff --git a/hm_web/static/images/AT_049.png b/hm_web/static/images/AT_049.png new file mode 100644 index 0000000..bcf9b51 Binary files /dev/null and b/hm_web/static/images/AT_049.png differ diff --git a/hm_web/static/images/AT_049e.png b/hm_web/static/images/AT_049e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_049e.png differ diff --git a/hm_web/static/images/AT_050.png b/hm_web/static/images/AT_050.png new file mode 100644 index 0000000..1ca17d7 Binary files /dev/null and b/hm_web/static/images/AT_050.png differ diff --git a/hm_web/static/images/AT_050t.png b/hm_web/static/images/AT_050t.png new file mode 100644 index 0000000..8b9a3ca Binary files /dev/null and b/hm_web/static/images/AT_050t.png differ diff --git a/hm_web/static/images/AT_051.png b/hm_web/static/images/AT_051.png new file mode 100644 index 0000000..9386aab Binary files /dev/null and b/hm_web/static/images/AT_051.png differ diff --git a/hm_web/static/images/AT_052.png b/hm_web/static/images/AT_052.png new file mode 100644 index 0000000..c0e6b70 Binary files /dev/null and b/hm_web/static/images/AT_052.png differ diff --git a/hm_web/static/images/AT_053.png b/hm_web/static/images/AT_053.png new file mode 100644 index 0000000..b15e998 Binary files /dev/null and b/hm_web/static/images/AT_053.png differ diff --git a/hm_web/static/images/AT_054.png b/hm_web/static/images/AT_054.png new file mode 100644 index 0000000..68479ec Binary files /dev/null and b/hm_web/static/images/AT_054.png differ diff --git a/hm_web/static/images/AT_055.png b/hm_web/static/images/AT_055.png new file mode 100644 index 0000000..e4d8571 Binary files /dev/null and b/hm_web/static/images/AT_055.png differ diff --git a/hm_web/static/images/AT_056.png b/hm_web/static/images/AT_056.png new file mode 100644 index 0000000..ab47bbc Binary files /dev/null and b/hm_web/static/images/AT_056.png differ diff --git a/hm_web/static/images/AT_057.png b/hm_web/static/images/AT_057.png new file mode 100644 index 0000000..36f1249 Binary files /dev/null and b/hm_web/static/images/AT_057.png differ diff --git a/hm_web/static/images/AT_057o.png b/hm_web/static/images/AT_057o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_057o.png differ diff --git a/hm_web/static/images/AT_058.png b/hm_web/static/images/AT_058.png new file mode 100644 index 0000000..aabe869 Binary files /dev/null and b/hm_web/static/images/AT_058.png differ diff --git a/hm_web/static/images/AT_059.png b/hm_web/static/images/AT_059.png new file mode 100644 index 0000000..b77ce28 Binary files /dev/null and b/hm_web/static/images/AT_059.png differ diff --git a/hm_web/static/images/AT_060.png b/hm_web/static/images/AT_060.png new file mode 100644 index 0000000..ab13b4a Binary files /dev/null and b/hm_web/static/images/AT_060.png differ diff --git a/hm_web/static/images/AT_061.png b/hm_web/static/images/AT_061.png new file mode 100644 index 0000000..c0bbafd Binary files /dev/null and b/hm_web/static/images/AT_061.png differ diff --git a/hm_web/static/images/AT_061e.png b/hm_web/static/images/AT_061e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_061e.png differ diff --git a/hm_web/static/images/AT_062.png b/hm_web/static/images/AT_062.png new file mode 100644 index 0000000..083b056 Binary files /dev/null and b/hm_web/static/images/AT_062.png differ diff --git a/hm_web/static/images/AT_063.png b/hm_web/static/images/AT_063.png new file mode 100644 index 0000000..2640a90 Binary files /dev/null and b/hm_web/static/images/AT_063.png differ diff --git a/hm_web/static/images/AT_063t.png b/hm_web/static/images/AT_063t.png new file mode 100644 index 0000000..d028a23 Binary files /dev/null and b/hm_web/static/images/AT_063t.png differ diff --git a/hm_web/static/images/AT_064.png b/hm_web/static/images/AT_064.png new file mode 100644 index 0000000..2be5bf4 Binary files /dev/null and b/hm_web/static/images/AT_064.png differ diff --git a/hm_web/static/images/AT_065.png b/hm_web/static/images/AT_065.png new file mode 100644 index 0000000..f5b1f46 Binary files /dev/null and b/hm_web/static/images/AT_065.png differ diff --git a/hm_web/static/images/AT_065e.png b/hm_web/static/images/AT_065e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_065e.png differ diff --git a/hm_web/static/images/AT_066.png b/hm_web/static/images/AT_066.png new file mode 100644 index 0000000..3633c55 Binary files /dev/null and b/hm_web/static/images/AT_066.png differ diff --git a/hm_web/static/images/AT_066e.png b/hm_web/static/images/AT_066e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_066e.png differ diff --git a/hm_web/static/images/AT_067.png b/hm_web/static/images/AT_067.png new file mode 100644 index 0000000..af94d26 Binary files /dev/null and b/hm_web/static/images/AT_067.png differ diff --git a/hm_web/static/images/AT_068.png b/hm_web/static/images/AT_068.png new file mode 100644 index 0000000..2b03233 Binary files /dev/null and b/hm_web/static/images/AT_068.png differ diff --git a/hm_web/static/images/AT_068e.png b/hm_web/static/images/AT_068e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_068e.png differ diff --git a/hm_web/static/images/AT_069.png b/hm_web/static/images/AT_069.png new file mode 100644 index 0000000..1e4f0e3 Binary files /dev/null and b/hm_web/static/images/AT_069.png differ diff --git a/hm_web/static/images/AT_069e.png b/hm_web/static/images/AT_069e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_069e.png differ diff --git a/hm_web/static/images/AT_070.png b/hm_web/static/images/AT_070.png new file mode 100644 index 0000000..9a9ffc7 Binary files /dev/null and b/hm_web/static/images/AT_070.png differ diff --git a/hm_web/static/images/AT_071.png b/hm_web/static/images/AT_071.png new file mode 100644 index 0000000..32bad4b Binary files /dev/null and b/hm_web/static/images/AT_071.png differ diff --git a/hm_web/static/images/AT_071e.png b/hm_web/static/images/AT_071e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_071e.png differ diff --git a/hm_web/static/images/AT_072.png b/hm_web/static/images/AT_072.png new file mode 100644 index 0000000..f280f5b Binary files /dev/null and b/hm_web/static/images/AT_072.png differ diff --git a/hm_web/static/images/AT_073.png b/hm_web/static/images/AT_073.png new file mode 100644 index 0000000..4f00b52 Binary files /dev/null and b/hm_web/static/images/AT_073.png differ diff --git a/hm_web/static/images/AT_073e.png b/hm_web/static/images/AT_073e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_073e.png differ diff --git a/hm_web/static/images/AT_074.png b/hm_web/static/images/AT_074.png new file mode 100644 index 0000000..400d301 Binary files /dev/null and b/hm_web/static/images/AT_074.png differ diff --git a/hm_web/static/images/AT_074e2.png b/hm_web/static/images/AT_074e2.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_074e2.png differ diff --git a/hm_web/static/images/AT_075.png b/hm_web/static/images/AT_075.png new file mode 100644 index 0000000..1de033d Binary files /dev/null and b/hm_web/static/images/AT_075.png differ diff --git a/hm_web/static/images/AT_075e.png b/hm_web/static/images/AT_075e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_075e.png differ diff --git a/hm_web/static/images/AT_076.png b/hm_web/static/images/AT_076.png new file mode 100644 index 0000000..40eb855 Binary files /dev/null and b/hm_web/static/images/AT_076.png differ diff --git a/hm_web/static/images/AT_077.png b/hm_web/static/images/AT_077.png new file mode 100644 index 0000000..0258b07 Binary files /dev/null and b/hm_web/static/images/AT_077.png differ diff --git a/hm_web/static/images/AT_077e.png b/hm_web/static/images/AT_077e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_077e.png differ diff --git a/hm_web/static/images/AT_078.png b/hm_web/static/images/AT_078.png new file mode 100644 index 0000000..5196262 Binary files /dev/null and b/hm_web/static/images/AT_078.png differ diff --git a/hm_web/static/images/AT_079.png b/hm_web/static/images/AT_079.png new file mode 100644 index 0000000..2eeafb9 Binary files /dev/null and b/hm_web/static/images/AT_079.png differ diff --git a/hm_web/static/images/AT_080.png b/hm_web/static/images/AT_080.png new file mode 100644 index 0000000..2e183d6 Binary files /dev/null and b/hm_web/static/images/AT_080.png differ diff --git a/hm_web/static/images/AT_081.png b/hm_web/static/images/AT_081.png new file mode 100644 index 0000000..d1d1349 Binary files /dev/null and b/hm_web/static/images/AT_081.png differ diff --git a/hm_web/static/images/AT_081e.png b/hm_web/static/images/AT_081e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_081e.png differ diff --git a/hm_web/static/images/AT_082.png b/hm_web/static/images/AT_082.png new file mode 100644 index 0000000..eda0871 Binary files /dev/null and b/hm_web/static/images/AT_082.png differ diff --git a/hm_web/static/images/AT_082e.png b/hm_web/static/images/AT_082e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_082e.png differ diff --git a/hm_web/static/images/AT_083.png b/hm_web/static/images/AT_083.png new file mode 100644 index 0000000..b915695 Binary files /dev/null and b/hm_web/static/images/AT_083.png differ diff --git a/hm_web/static/images/AT_083e.png b/hm_web/static/images/AT_083e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_083e.png differ diff --git a/hm_web/static/images/AT_084.png b/hm_web/static/images/AT_084.png new file mode 100644 index 0000000..ed3c1ce Binary files /dev/null and b/hm_web/static/images/AT_084.png differ diff --git a/hm_web/static/images/AT_084e.png b/hm_web/static/images/AT_084e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_084e.png differ diff --git a/hm_web/static/images/AT_085.png b/hm_web/static/images/AT_085.png new file mode 100644 index 0000000..27266a4 Binary files /dev/null and b/hm_web/static/images/AT_085.png differ diff --git a/hm_web/static/images/AT_086.png b/hm_web/static/images/AT_086.png new file mode 100644 index 0000000..e934db3 Binary files /dev/null and b/hm_web/static/images/AT_086.png differ diff --git a/hm_web/static/images/AT_086e.png b/hm_web/static/images/AT_086e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_086e.png differ diff --git a/hm_web/static/images/AT_087.png b/hm_web/static/images/AT_087.png new file mode 100644 index 0000000..7e560b5 Binary files /dev/null and b/hm_web/static/images/AT_087.png differ diff --git a/hm_web/static/images/AT_088.png b/hm_web/static/images/AT_088.png new file mode 100644 index 0000000..6e75f42 Binary files /dev/null and b/hm_web/static/images/AT_088.png differ diff --git a/hm_web/static/images/AT_089.png b/hm_web/static/images/AT_089.png new file mode 100644 index 0000000..d1a2408 Binary files /dev/null and b/hm_web/static/images/AT_089.png differ diff --git a/hm_web/static/images/AT_089e.png b/hm_web/static/images/AT_089e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_089e.png differ diff --git a/hm_web/static/images/AT_090.png b/hm_web/static/images/AT_090.png new file mode 100644 index 0000000..6a2c478 Binary files /dev/null and b/hm_web/static/images/AT_090.png differ diff --git a/hm_web/static/images/AT_090e.png b/hm_web/static/images/AT_090e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_090e.png differ diff --git a/hm_web/static/images/AT_091.png b/hm_web/static/images/AT_091.png new file mode 100644 index 0000000..9931f4f Binary files /dev/null and b/hm_web/static/images/AT_091.png differ diff --git a/hm_web/static/images/AT_092.png b/hm_web/static/images/AT_092.png new file mode 100644 index 0000000..efcefae Binary files /dev/null and b/hm_web/static/images/AT_092.png differ diff --git a/hm_web/static/images/AT_093.png b/hm_web/static/images/AT_093.png new file mode 100644 index 0000000..ccb41a6 Binary files /dev/null and b/hm_web/static/images/AT_093.png differ diff --git a/hm_web/static/images/AT_094.png b/hm_web/static/images/AT_094.png new file mode 100644 index 0000000..790e206 Binary files /dev/null and b/hm_web/static/images/AT_094.png differ diff --git a/hm_web/static/images/AT_095.png b/hm_web/static/images/AT_095.png new file mode 100644 index 0000000..5e12c35 Binary files /dev/null and b/hm_web/static/images/AT_095.png differ diff --git a/hm_web/static/images/AT_096.png b/hm_web/static/images/AT_096.png new file mode 100644 index 0000000..f81e610 Binary files /dev/null and b/hm_web/static/images/AT_096.png differ diff --git a/hm_web/static/images/AT_096e.png b/hm_web/static/images/AT_096e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_096e.png differ diff --git a/hm_web/static/images/AT_097.png b/hm_web/static/images/AT_097.png new file mode 100644 index 0000000..8b1548c Binary files /dev/null and b/hm_web/static/images/AT_097.png differ diff --git a/hm_web/static/images/AT_098.png b/hm_web/static/images/AT_098.png new file mode 100644 index 0000000..a95fd2a Binary files /dev/null and b/hm_web/static/images/AT_098.png differ diff --git a/hm_web/static/images/AT_099.png b/hm_web/static/images/AT_099.png new file mode 100644 index 0000000..beb8e70 Binary files /dev/null and b/hm_web/static/images/AT_099.png differ diff --git a/hm_web/static/images/AT_099t.png b/hm_web/static/images/AT_099t.png new file mode 100644 index 0000000..cd3734f Binary files /dev/null and b/hm_web/static/images/AT_099t.png differ diff --git a/hm_web/static/images/AT_100.png b/hm_web/static/images/AT_100.png new file mode 100644 index 0000000..b539140 Binary files /dev/null and b/hm_web/static/images/AT_100.png differ diff --git a/hm_web/static/images/AT_101.png b/hm_web/static/images/AT_101.png new file mode 100644 index 0000000..9e6a1dc Binary files /dev/null and b/hm_web/static/images/AT_101.png differ diff --git a/hm_web/static/images/AT_102.png b/hm_web/static/images/AT_102.png new file mode 100644 index 0000000..f467040 Binary files /dev/null and b/hm_web/static/images/AT_102.png differ diff --git a/hm_web/static/images/AT_103.png b/hm_web/static/images/AT_103.png new file mode 100644 index 0000000..ba3e14f Binary files /dev/null and b/hm_web/static/images/AT_103.png differ diff --git a/hm_web/static/images/AT_104.png b/hm_web/static/images/AT_104.png new file mode 100644 index 0000000..4907944 Binary files /dev/null and b/hm_web/static/images/AT_104.png differ diff --git a/hm_web/static/images/AT_105.png b/hm_web/static/images/AT_105.png new file mode 100644 index 0000000..184aae0 Binary files /dev/null and b/hm_web/static/images/AT_105.png differ diff --git a/hm_web/static/images/AT_106.png b/hm_web/static/images/AT_106.png new file mode 100644 index 0000000..c73cef1 Binary files /dev/null and b/hm_web/static/images/AT_106.png differ diff --git a/hm_web/static/images/AT_108.png b/hm_web/static/images/AT_108.png new file mode 100644 index 0000000..0d5226f Binary files /dev/null and b/hm_web/static/images/AT_108.png differ diff --git a/hm_web/static/images/AT_109.png b/hm_web/static/images/AT_109.png new file mode 100644 index 0000000..fb128a9 Binary files /dev/null and b/hm_web/static/images/AT_109.png differ diff --git a/hm_web/static/images/AT_109e.png b/hm_web/static/images/AT_109e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_109e.png differ diff --git a/hm_web/static/images/AT_110.png b/hm_web/static/images/AT_110.png new file mode 100644 index 0000000..508cfc8 Binary files /dev/null and b/hm_web/static/images/AT_110.png differ diff --git a/hm_web/static/images/AT_111.png b/hm_web/static/images/AT_111.png new file mode 100644 index 0000000..54b3b94 Binary files /dev/null and b/hm_web/static/images/AT_111.png differ diff --git a/hm_web/static/images/AT_112.png b/hm_web/static/images/AT_112.png new file mode 100644 index 0000000..bdb9604 Binary files /dev/null and b/hm_web/static/images/AT_112.png differ diff --git a/hm_web/static/images/AT_113.png b/hm_web/static/images/AT_113.png new file mode 100644 index 0000000..c6e6d3d Binary files /dev/null and b/hm_web/static/images/AT_113.png differ diff --git a/hm_web/static/images/AT_114.png b/hm_web/static/images/AT_114.png new file mode 100644 index 0000000..ec10257 Binary files /dev/null and b/hm_web/static/images/AT_114.png differ diff --git a/hm_web/static/images/AT_115.png b/hm_web/static/images/AT_115.png new file mode 100644 index 0000000..708ec12 Binary files /dev/null and b/hm_web/static/images/AT_115.png differ diff --git a/hm_web/static/images/AT_115e.png b/hm_web/static/images/AT_115e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_115e.png differ diff --git a/hm_web/static/images/AT_116.png b/hm_web/static/images/AT_116.png new file mode 100644 index 0000000..053f25b Binary files /dev/null and b/hm_web/static/images/AT_116.png differ diff --git a/hm_web/static/images/AT_116e.png b/hm_web/static/images/AT_116e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_116e.png differ diff --git a/hm_web/static/images/AT_117.png b/hm_web/static/images/AT_117.png new file mode 100644 index 0000000..85cc4d9 Binary files /dev/null and b/hm_web/static/images/AT_117.png differ diff --git a/hm_web/static/images/AT_117e.png b/hm_web/static/images/AT_117e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_117e.png differ diff --git a/hm_web/static/images/AT_118.png b/hm_web/static/images/AT_118.png new file mode 100644 index 0000000..3f33540 Binary files /dev/null and b/hm_web/static/images/AT_118.png differ diff --git a/hm_web/static/images/AT_119.png b/hm_web/static/images/AT_119.png new file mode 100644 index 0000000..7b30748 Binary files /dev/null and b/hm_web/static/images/AT_119.png differ diff --git a/hm_web/static/images/AT_119e.png b/hm_web/static/images/AT_119e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_119e.png differ diff --git a/hm_web/static/images/AT_120.png b/hm_web/static/images/AT_120.png new file mode 100644 index 0000000..8e4ffdc Binary files /dev/null and b/hm_web/static/images/AT_120.png differ diff --git a/hm_web/static/images/AT_121.png b/hm_web/static/images/AT_121.png new file mode 100644 index 0000000..6af7c53 Binary files /dev/null and b/hm_web/static/images/AT_121.png differ diff --git a/hm_web/static/images/AT_121e.png b/hm_web/static/images/AT_121e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_121e.png differ diff --git a/hm_web/static/images/AT_122.png b/hm_web/static/images/AT_122.png new file mode 100644 index 0000000..8f6ca51 Binary files /dev/null and b/hm_web/static/images/AT_122.png differ diff --git a/hm_web/static/images/AT_123.png b/hm_web/static/images/AT_123.png new file mode 100644 index 0000000..c972787 Binary files /dev/null and b/hm_web/static/images/AT_123.png differ diff --git a/hm_web/static/images/AT_124.png b/hm_web/static/images/AT_124.png new file mode 100644 index 0000000..e941499 Binary files /dev/null and b/hm_web/static/images/AT_124.png differ diff --git a/hm_web/static/images/AT_125.png b/hm_web/static/images/AT_125.png new file mode 100644 index 0000000..9492f20 Binary files /dev/null and b/hm_web/static/images/AT_125.png differ diff --git a/hm_web/static/images/AT_127.png b/hm_web/static/images/AT_127.png new file mode 100644 index 0000000..a636bbe Binary files /dev/null and b/hm_web/static/images/AT_127.png differ diff --git a/hm_web/static/images/AT_127.png.1 b/hm_web/static/images/AT_127.png.1 new file mode 100644 index 0000000..a636bbe Binary files /dev/null and b/hm_web/static/images/AT_127.png.1 differ diff --git a/hm_web/static/images/AT_128.png b/hm_web/static/images/AT_128.png new file mode 100644 index 0000000..a2a537d Binary files /dev/null and b/hm_web/static/images/AT_128.png differ diff --git a/hm_web/static/images/AT_129.png b/hm_web/static/images/AT_129.png new file mode 100644 index 0000000..3704f29 Binary files /dev/null and b/hm_web/static/images/AT_129.png differ diff --git a/hm_web/static/images/AT_130.png b/hm_web/static/images/AT_130.png new file mode 100644 index 0000000..569a84b Binary files /dev/null and b/hm_web/static/images/AT_130.png differ diff --git a/hm_web/static/images/AT_131.png b/hm_web/static/images/AT_131.png new file mode 100644 index 0000000..915f410 Binary files /dev/null and b/hm_web/static/images/AT_131.png differ diff --git a/hm_web/static/images/AT_132.png b/hm_web/static/images/AT_132.png new file mode 100644 index 0000000..8d00718 Binary files /dev/null and b/hm_web/static/images/AT_132.png differ diff --git a/hm_web/static/images/AT_132_DRUID.png b/hm_web/static/images/AT_132_DRUID.png new file mode 100644 index 0000000..cc8402a Binary files /dev/null and b/hm_web/static/images/AT_132_DRUID.png differ diff --git a/hm_web/static/images/AT_132_DRUIDe.png b/hm_web/static/images/AT_132_DRUIDe.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_132_DRUIDe.png differ diff --git a/hm_web/static/images/AT_132_HUNTER.png b/hm_web/static/images/AT_132_HUNTER.png new file mode 100644 index 0000000..9bc7a7d Binary files /dev/null and b/hm_web/static/images/AT_132_HUNTER.png differ diff --git a/hm_web/static/images/AT_132_MAGE.png b/hm_web/static/images/AT_132_MAGE.png new file mode 100644 index 0000000..6f8a874 Binary files /dev/null and b/hm_web/static/images/AT_132_MAGE.png differ diff --git a/hm_web/static/images/AT_132_PALADIN.png b/hm_web/static/images/AT_132_PALADIN.png new file mode 100644 index 0000000..b83e500 Binary files /dev/null and b/hm_web/static/images/AT_132_PALADIN.png differ diff --git a/hm_web/static/images/AT_132_PRIEST.png b/hm_web/static/images/AT_132_PRIEST.png new file mode 100644 index 0000000..bb1db33 Binary files /dev/null and b/hm_web/static/images/AT_132_PRIEST.png differ diff --git a/hm_web/static/images/AT_132_ROGUE.png b/hm_web/static/images/AT_132_ROGUE.png new file mode 100644 index 0000000..9e0590a Binary files /dev/null and b/hm_web/static/images/AT_132_ROGUE.png differ diff --git a/hm_web/static/images/AT_132_ROGUEt.png b/hm_web/static/images/AT_132_ROGUEt.png new file mode 100644 index 0000000..ca617f6 Binary files /dev/null and b/hm_web/static/images/AT_132_ROGUEt.png differ diff --git a/hm_web/static/images/AT_132_SHAMAN.png b/hm_web/static/images/AT_132_SHAMAN.png new file mode 100644 index 0000000..690f6db Binary files /dev/null and b/hm_web/static/images/AT_132_SHAMAN.png differ diff --git a/hm_web/static/images/AT_132_SHAMANa.png b/hm_web/static/images/AT_132_SHAMANa.png new file mode 100644 index 0000000..a5400f7 Binary files /dev/null and b/hm_web/static/images/AT_132_SHAMANa.png differ diff --git a/hm_web/static/images/AT_132_SHAMANb.png b/hm_web/static/images/AT_132_SHAMANb.png new file mode 100644 index 0000000..1b25488 Binary files /dev/null and b/hm_web/static/images/AT_132_SHAMANb.png differ diff --git a/hm_web/static/images/AT_132_SHAMANc.png b/hm_web/static/images/AT_132_SHAMANc.png new file mode 100644 index 0000000..c9602df Binary files /dev/null and b/hm_web/static/images/AT_132_SHAMANc.png differ diff --git a/hm_web/static/images/AT_132_SHAMANd.png b/hm_web/static/images/AT_132_SHAMANd.png new file mode 100644 index 0000000..eca1fde Binary files /dev/null and b/hm_web/static/images/AT_132_SHAMANd.png differ diff --git a/hm_web/static/images/AT_132_WARLOCK.png b/hm_web/static/images/AT_132_WARLOCK.png new file mode 100644 index 0000000..ea79d83 Binary files /dev/null and b/hm_web/static/images/AT_132_WARLOCK.png differ diff --git a/hm_web/static/images/AT_132_WARRIOR.png b/hm_web/static/images/AT_132_WARRIOR.png new file mode 100644 index 0000000..0b5db0d Binary files /dev/null and b/hm_web/static/images/AT_132_WARRIOR.png differ diff --git a/hm_web/static/images/AT_133.png b/hm_web/static/images/AT_133.png new file mode 100644 index 0000000..a232f11 Binary files /dev/null and b/hm_web/static/images/AT_133.png differ diff --git a/hm_web/static/images/AT_133e.png b/hm_web/static/images/AT_133e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/AT_133e.png differ diff --git a/hm_web/static/images/BRMA01_1.png b/hm_web/static/images/BRMA01_1.png new file mode 100644 index 0000000..3a4ac87 Binary files /dev/null and b/hm_web/static/images/BRMA01_1.png differ diff --git a/hm_web/static/images/BRMA01_1H.png b/hm_web/static/images/BRMA01_1H.png new file mode 100644 index 0000000..003ddac Binary files /dev/null and b/hm_web/static/images/BRMA01_1H.png differ diff --git a/hm_web/static/images/BRMA01_2.png b/hm_web/static/images/BRMA01_2.png new file mode 100644 index 0000000..3ff9807 Binary files /dev/null and b/hm_web/static/images/BRMA01_2.png differ diff --git a/hm_web/static/images/BRMA01_2H.png b/hm_web/static/images/BRMA01_2H.png new file mode 100644 index 0000000..a98e02d Binary files /dev/null and b/hm_web/static/images/BRMA01_2H.png differ diff --git a/hm_web/static/images/BRMA01_2H_2_TB.png b/hm_web/static/images/BRMA01_2H_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA01_2H_2_TB.png differ diff --git a/hm_web/static/images/BRMA01_3.png b/hm_web/static/images/BRMA01_3.png new file mode 100644 index 0000000..bc9d728 Binary files /dev/null and b/hm_web/static/images/BRMA01_3.png differ diff --git a/hm_web/static/images/BRMA01_4.png b/hm_web/static/images/BRMA01_4.png new file mode 100644 index 0000000..989cc91 Binary files /dev/null and b/hm_web/static/images/BRMA01_4.png differ diff --git a/hm_web/static/images/BRMA01_4t.png b/hm_web/static/images/BRMA01_4t.png new file mode 100644 index 0000000..8663b14 Binary files /dev/null and b/hm_web/static/images/BRMA01_4t.png differ diff --git a/hm_web/static/images/BRMA02_1.png b/hm_web/static/images/BRMA02_1.png new file mode 100644 index 0000000..2cf91da Binary files /dev/null and b/hm_web/static/images/BRMA02_1.png differ diff --git a/hm_web/static/images/BRMA02_1H.png b/hm_web/static/images/BRMA02_1H.png new file mode 100644 index 0000000..ff0f004 Binary files /dev/null and b/hm_web/static/images/BRMA02_1H.png differ diff --git a/hm_web/static/images/BRMA02_2.png b/hm_web/static/images/BRMA02_2.png new file mode 100644 index 0000000..92fa888 Binary files /dev/null and b/hm_web/static/images/BRMA02_2.png differ diff --git a/hm_web/static/images/BRMA02_2H.png b/hm_web/static/images/BRMA02_2H.png new file mode 100644 index 0000000..8fb3d68 Binary files /dev/null and b/hm_web/static/images/BRMA02_2H.png differ diff --git a/hm_web/static/images/BRMA02_2_2_TB.png b/hm_web/static/images/BRMA02_2_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA02_2_2_TB.png differ diff --git a/hm_web/static/images/BRMA02_2_2c_TB.png b/hm_web/static/images/BRMA02_2_2c_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA02_2_2c_TB.png differ diff --git a/hm_web/static/images/BRMA02_2t.png b/hm_web/static/images/BRMA02_2t.png new file mode 100644 index 0000000..bbb20f8 Binary files /dev/null and b/hm_web/static/images/BRMA02_2t.png differ diff --git a/hm_web/static/images/BRMA03_1.png b/hm_web/static/images/BRMA03_1.png new file mode 100644 index 0000000..1acc56b Binary files /dev/null and b/hm_web/static/images/BRMA03_1.png differ diff --git a/hm_web/static/images/BRMA03_1H.png b/hm_web/static/images/BRMA03_1H.png new file mode 100644 index 0000000..47f35d9 Binary files /dev/null and b/hm_web/static/images/BRMA03_1H.png differ diff --git a/hm_web/static/images/BRMA03_2.png b/hm_web/static/images/BRMA03_2.png new file mode 100644 index 0000000..c4ec0d9 Binary files /dev/null and b/hm_web/static/images/BRMA03_2.png differ diff --git a/hm_web/static/images/BRMA03_3.png b/hm_web/static/images/BRMA03_3.png new file mode 100644 index 0000000..45b22fc Binary files /dev/null and b/hm_web/static/images/BRMA03_3.png differ diff --git a/hm_web/static/images/BRMA03_3H.png b/hm_web/static/images/BRMA03_3H.png new file mode 100644 index 0000000..933aa5e Binary files /dev/null and b/hm_web/static/images/BRMA03_3H.png differ diff --git a/hm_web/static/images/BRMA04_1.png b/hm_web/static/images/BRMA04_1.png new file mode 100644 index 0000000..22a917f Binary files /dev/null and b/hm_web/static/images/BRMA04_1.png differ diff --git a/hm_web/static/images/BRMA04_1H.png b/hm_web/static/images/BRMA04_1H.png new file mode 100644 index 0000000..3b73ce1 Binary files /dev/null and b/hm_web/static/images/BRMA04_1H.png differ diff --git a/hm_web/static/images/BRMA04_2.png b/hm_web/static/images/BRMA04_2.png new file mode 100644 index 0000000..016a635 Binary files /dev/null and b/hm_web/static/images/BRMA04_2.png differ diff --git a/hm_web/static/images/BRMA04_3.png b/hm_web/static/images/BRMA04_3.png new file mode 100644 index 0000000..12991cf Binary files /dev/null and b/hm_web/static/images/BRMA04_3.png differ diff --git a/hm_web/static/images/BRMA04_3H.png b/hm_web/static/images/BRMA04_3H.png new file mode 100644 index 0000000..69b4682 Binary files /dev/null and b/hm_web/static/images/BRMA04_3H.png differ diff --git a/hm_web/static/images/BRMA04_4.png b/hm_web/static/images/BRMA04_4.png new file mode 100644 index 0000000..6264aa5 Binary files /dev/null and b/hm_web/static/images/BRMA04_4.png differ diff --git a/hm_web/static/images/BRMA04_4H.png b/hm_web/static/images/BRMA04_4H.png new file mode 100644 index 0000000..fe6d4d8 Binary files /dev/null and b/hm_web/static/images/BRMA04_4H.png differ diff --git a/hm_web/static/images/BRMA05_1.png b/hm_web/static/images/BRMA05_1.png new file mode 100644 index 0000000..166da54 Binary files /dev/null and b/hm_web/static/images/BRMA05_1.png differ diff --git a/hm_web/static/images/BRMA05_1H.png b/hm_web/static/images/BRMA05_1H.png new file mode 100644 index 0000000..de8cdcb Binary files /dev/null and b/hm_web/static/images/BRMA05_1H.png differ diff --git a/hm_web/static/images/BRMA05_2.png b/hm_web/static/images/BRMA05_2.png new file mode 100644 index 0000000..bbf6e7f Binary files /dev/null and b/hm_web/static/images/BRMA05_2.png differ diff --git a/hm_web/static/images/BRMA05_2H.png b/hm_web/static/images/BRMA05_2H.png new file mode 100644 index 0000000..b0617ae Binary files /dev/null and b/hm_web/static/images/BRMA05_2H.png differ diff --git a/hm_web/static/images/BRMA05_3.png b/hm_web/static/images/BRMA05_3.png new file mode 100644 index 0000000..8871739 Binary files /dev/null and b/hm_web/static/images/BRMA05_3.png differ diff --git a/hm_web/static/images/BRMA05_3H.png b/hm_web/static/images/BRMA05_3H.png new file mode 100644 index 0000000..c51ce97 Binary files /dev/null and b/hm_web/static/images/BRMA05_3H.png differ diff --git a/hm_web/static/images/BRMA05_3He.png b/hm_web/static/images/BRMA05_3He.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA05_3He.png differ diff --git a/hm_web/static/images/BRMA05_3e.png b/hm_web/static/images/BRMA05_3e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA05_3e.png differ diff --git a/hm_web/static/images/BRMA06_1.png b/hm_web/static/images/BRMA06_1.png new file mode 100644 index 0000000..a09aa63 Binary files /dev/null and b/hm_web/static/images/BRMA06_1.png differ diff --git a/hm_web/static/images/BRMA06_1H.png b/hm_web/static/images/BRMA06_1H.png new file mode 100644 index 0000000..94f9686 Binary files /dev/null and b/hm_web/static/images/BRMA06_1H.png differ diff --git a/hm_web/static/images/BRMA06_2.png b/hm_web/static/images/BRMA06_2.png new file mode 100644 index 0000000..67727df Binary files /dev/null and b/hm_web/static/images/BRMA06_2.png differ diff --git a/hm_web/static/images/BRMA06_2H.png b/hm_web/static/images/BRMA06_2H.png new file mode 100644 index 0000000..5652c6b Binary files /dev/null and b/hm_web/static/images/BRMA06_2H.png differ diff --git a/hm_web/static/images/BRMA06_2H_TB.png b/hm_web/static/images/BRMA06_2H_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA06_2H_TB.png differ diff --git a/hm_web/static/images/BRMA06_3.png b/hm_web/static/images/BRMA06_3.png new file mode 100644 index 0000000..e38da0b Binary files /dev/null and b/hm_web/static/images/BRMA06_3.png differ diff --git a/hm_web/static/images/BRMA06_3H.png b/hm_web/static/images/BRMA06_3H.png new file mode 100644 index 0000000..c15748a Binary files /dev/null and b/hm_web/static/images/BRMA06_3H.png differ diff --git a/hm_web/static/images/BRMA06_4.png b/hm_web/static/images/BRMA06_4.png new file mode 100644 index 0000000..b86cafa Binary files /dev/null and b/hm_web/static/images/BRMA06_4.png differ diff --git a/hm_web/static/images/BRMA06_4H.png b/hm_web/static/images/BRMA06_4H.png new file mode 100644 index 0000000..49d1f96 Binary files /dev/null and b/hm_web/static/images/BRMA06_4H.png differ diff --git a/hm_web/static/images/BRMA07_1.png b/hm_web/static/images/BRMA07_1.png new file mode 100644 index 0000000..de13fb8 Binary files /dev/null and b/hm_web/static/images/BRMA07_1.png differ diff --git a/hm_web/static/images/BRMA07_1H.png b/hm_web/static/images/BRMA07_1H.png new file mode 100644 index 0000000..6aa7484 Binary files /dev/null and b/hm_web/static/images/BRMA07_1H.png differ diff --git a/hm_web/static/images/BRMA07_2.png b/hm_web/static/images/BRMA07_2.png new file mode 100644 index 0000000..b511944 Binary files /dev/null and b/hm_web/static/images/BRMA07_2.png differ diff --git a/hm_web/static/images/BRMA07_2H.png b/hm_web/static/images/BRMA07_2H.png new file mode 100644 index 0000000..c1c5344 Binary files /dev/null and b/hm_web/static/images/BRMA07_2H.png differ diff --git a/hm_web/static/images/BRMA07_2_2_TB.png b/hm_web/static/images/BRMA07_2_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA07_2_2_TB.png differ diff --git a/hm_web/static/images/BRMA07_2_2c_TB.png b/hm_web/static/images/BRMA07_2_2c_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA07_2_2c_TB.png differ diff --git a/hm_web/static/images/BRMA07_3.png b/hm_web/static/images/BRMA07_3.png new file mode 100644 index 0000000..320b907 Binary files /dev/null and b/hm_web/static/images/BRMA07_3.png differ diff --git a/hm_web/static/images/BRMA08_1.png b/hm_web/static/images/BRMA08_1.png new file mode 100644 index 0000000..a29e7a2 Binary files /dev/null and b/hm_web/static/images/BRMA08_1.png differ diff --git a/hm_web/static/images/BRMA08_1H.png b/hm_web/static/images/BRMA08_1H.png new file mode 100644 index 0000000..5e9ef98 Binary files /dev/null and b/hm_web/static/images/BRMA08_1H.png differ diff --git a/hm_web/static/images/BRMA08_2.png b/hm_web/static/images/BRMA08_2.png new file mode 100644 index 0000000..1ae3d1d Binary files /dev/null and b/hm_web/static/images/BRMA08_2.png differ diff --git a/hm_web/static/images/BRMA08_2H.png b/hm_web/static/images/BRMA08_2H.png new file mode 100644 index 0000000..5d6d544 Binary files /dev/null and b/hm_web/static/images/BRMA08_2H.png differ diff --git a/hm_web/static/images/BRMA08_3.png b/hm_web/static/images/BRMA08_3.png new file mode 100644 index 0000000..7f3d96f Binary files /dev/null and b/hm_web/static/images/BRMA08_3.png differ diff --git a/hm_web/static/images/BRMA09_1.png b/hm_web/static/images/BRMA09_1.png new file mode 100644 index 0000000..bde7cdf Binary files /dev/null and b/hm_web/static/images/BRMA09_1.png differ diff --git a/hm_web/static/images/BRMA09_1H.png b/hm_web/static/images/BRMA09_1H.png new file mode 100644 index 0000000..e8e08ce Binary files /dev/null and b/hm_web/static/images/BRMA09_1H.png differ diff --git a/hm_web/static/images/BRMA09_2.png b/hm_web/static/images/BRMA09_2.png new file mode 100644 index 0000000..05473f8 Binary files /dev/null and b/hm_web/static/images/BRMA09_2.png differ diff --git a/hm_web/static/images/BRMA09_2H.png b/hm_web/static/images/BRMA09_2H.png new file mode 100644 index 0000000..85c6242 Binary files /dev/null and b/hm_web/static/images/BRMA09_2H.png differ diff --git a/hm_web/static/images/BRMA09_2Ht.png b/hm_web/static/images/BRMA09_2Ht.png new file mode 100644 index 0000000..c53ce2d Binary files /dev/null and b/hm_web/static/images/BRMA09_2Ht.png differ diff --git a/hm_web/static/images/BRMA09_2_TB.png b/hm_web/static/images/BRMA09_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA09_2_TB.png differ diff --git a/hm_web/static/images/BRMA09_2t.png b/hm_web/static/images/BRMA09_2t.png new file mode 100644 index 0000000..ba04618 Binary files /dev/null and b/hm_web/static/images/BRMA09_2t.png differ diff --git a/hm_web/static/images/BRMA09_3.png b/hm_web/static/images/BRMA09_3.png new file mode 100644 index 0000000..d32d77c Binary files /dev/null and b/hm_web/static/images/BRMA09_3.png differ diff --git a/hm_web/static/images/BRMA09_3H.png b/hm_web/static/images/BRMA09_3H.png new file mode 100644 index 0000000..e424490 Binary files /dev/null and b/hm_web/static/images/BRMA09_3H.png differ diff --git a/hm_web/static/images/BRMA09_3Ht.png b/hm_web/static/images/BRMA09_3Ht.png new file mode 100644 index 0000000..6601dd5 Binary files /dev/null and b/hm_web/static/images/BRMA09_3Ht.png differ diff --git a/hm_web/static/images/BRMA09_3t.png b/hm_web/static/images/BRMA09_3t.png new file mode 100644 index 0000000..208100d Binary files /dev/null and b/hm_web/static/images/BRMA09_3t.png differ diff --git a/hm_web/static/images/BRMA09_4.png b/hm_web/static/images/BRMA09_4.png new file mode 100644 index 0000000..5bfaaa2 Binary files /dev/null and b/hm_web/static/images/BRMA09_4.png differ diff --git a/hm_web/static/images/BRMA09_4H.png b/hm_web/static/images/BRMA09_4H.png new file mode 100644 index 0000000..a8e1063 Binary files /dev/null and b/hm_web/static/images/BRMA09_4H.png differ diff --git a/hm_web/static/images/BRMA09_4Ht.png b/hm_web/static/images/BRMA09_4Ht.png new file mode 100644 index 0000000..6592bb3 Binary files /dev/null and b/hm_web/static/images/BRMA09_4Ht.png differ diff --git a/hm_web/static/images/BRMA09_4t.png b/hm_web/static/images/BRMA09_4t.png new file mode 100644 index 0000000..6cbc068 Binary files /dev/null and b/hm_web/static/images/BRMA09_4t.png differ diff --git a/hm_web/static/images/BRMA09_5.png b/hm_web/static/images/BRMA09_5.png new file mode 100644 index 0000000..b373877 Binary files /dev/null and b/hm_web/static/images/BRMA09_5.png differ diff --git a/hm_web/static/images/BRMA09_5H.png b/hm_web/static/images/BRMA09_5H.png new file mode 100644 index 0000000..1e8ff0f Binary files /dev/null and b/hm_web/static/images/BRMA09_5H.png differ diff --git a/hm_web/static/images/BRMA09_5Ht.png b/hm_web/static/images/BRMA09_5Ht.png new file mode 100644 index 0000000..21b4dbc Binary files /dev/null and b/hm_web/static/images/BRMA09_5Ht.png differ diff --git a/hm_web/static/images/BRMA09_5t.png b/hm_web/static/images/BRMA09_5t.png new file mode 100644 index 0000000..533c182 Binary files /dev/null and b/hm_web/static/images/BRMA09_5t.png differ diff --git a/hm_web/static/images/BRMA09_6.png b/hm_web/static/images/BRMA09_6.png new file mode 100644 index 0000000..2eff251 Binary files /dev/null and b/hm_web/static/images/BRMA09_6.png differ diff --git a/hm_web/static/images/BRMA10_1.png b/hm_web/static/images/BRMA10_1.png new file mode 100644 index 0000000..1191044 Binary files /dev/null and b/hm_web/static/images/BRMA10_1.png differ diff --git a/hm_web/static/images/BRMA10_1H.png b/hm_web/static/images/BRMA10_1H.png new file mode 100644 index 0000000..be7fa59 Binary files /dev/null and b/hm_web/static/images/BRMA10_1H.png differ diff --git a/hm_web/static/images/BRMA10_3.png b/hm_web/static/images/BRMA10_3.png new file mode 100644 index 0000000..43f1a9a Binary files /dev/null and b/hm_web/static/images/BRMA10_3.png differ diff --git a/hm_web/static/images/BRMA10_3H.png b/hm_web/static/images/BRMA10_3H.png new file mode 100644 index 0000000..4299e08 Binary files /dev/null and b/hm_web/static/images/BRMA10_3H.png differ diff --git a/hm_web/static/images/BRMA10_3e.png b/hm_web/static/images/BRMA10_3e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA10_3e.png differ diff --git a/hm_web/static/images/BRMA10_4.png b/hm_web/static/images/BRMA10_4.png new file mode 100644 index 0000000..909d79c Binary files /dev/null and b/hm_web/static/images/BRMA10_4.png differ diff --git a/hm_web/static/images/BRMA10_4H.png b/hm_web/static/images/BRMA10_4H.png new file mode 100644 index 0000000..ff98e9c Binary files /dev/null and b/hm_web/static/images/BRMA10_4H.png differ diff --git a/hm_web/static/images/BRMA10_5.png b/hm_web/static/images/BRMA10_5.png new file mode 100644 index 0000000..25a0809 Binary files /dev/null and b/hm_web/static/images/BRMA10_5.png differ diff --git a/hm_web/static/images/BRMA10_5H.png b/hm_web/static/images/BRMA10_5H.png new file mode 100644 index 0000000..69e5f80 Binary files /dev/null and b/hm_web/static/images/BRMA10_5H.png differ diff --git a/hm_web/static/images/BRMA10_6.png b/hm_web/static/images/BRMA10_6.png new file mode 100644 index 0000000..433e513 Binary files /dev/null and b/hm_web/static/images/BRMA10_6.png differ diff --git a/hm_web/static/images/BRMA10_6e.png b/hm_web/static/images/BRMA10_6e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA10_6e.png differ diff --git a/hm_web/static/images/BRMA11_1.png b/hm_web/static/images/BRMA11_1.png new file mode 100644 index 0000000..b272cba Binary files /dev/null and b/hm_web/static/images/BRMA11_1.png differ diff --git a/hm_web/static/images/BRMA11_1H.png b/hm_web/static/images/BRMA11_1H.png new file mode 100644 index 0000000..32a4125 Binary files /dev/null and b/hm_web/static/images/BRMA11_1H.png differ diff --git a/hm_web/static/images/BRMA11_2.png b/hm_web/static/images/BRMA11_2.png new file mode 100644 index 0000000..9da786e Binary files /dev/null and b/hm_web/static/images/BRMA11_2.png differ diff --git a/hm_web/static/images/BRMA11_2H.png b/hm_web/static/images/BRMA11_2H.png new file mode 100644 index 0000000..fd3e555 Binary files /dev/null and b/hm_web/static/images/BRMA11_2H.png differ diff --git a/hm_web/static/images/BRMA11_3.png b/hm_web/static/images/BRMA11_3.png new file mode 100644 index 0000000..022fe90 Binary files /dev/null and b/hm_web/static/images/BRMA11_3.png differ diff --git a/hm_web/static/images/BRMA12_1.png b/hm_web/static/images/BRMA12_1.png new file mode 100644 index 0000000..5c787e0 Binary files /dev/null and b/hm_web/static/images/BRMA12_1.png differ diff --git a/hm_web/static/images/BRMA12_10.png b/hm_web/static/images/BRMA12_10.png new file mode 100644 index 0000000..3d4c128 Binary files /dev/null and b/hm_web/static/images/BRMA12_10.png differ diff --git a/hm_web/static/images/BRMA12_1H.png b/hm_web/static/images/BRMA12_1H.png new file mode 100644 index 0000000..d7f2c5c Binary files /dev/null and b/hm_web/static/images/BRMA12_1H.png differ diff --git a/hm_web/static/images/BRMA12_2.png b/hm_web/static/images/BRMA12_2.png new file mode 100644 index 0000000..111bd1f Binary files /dev/null and b/hm_web/static/images/BRMA12_2.png differ diff --git a/hm_web/static/images/BRMA12_2H.png b/hm_web/static/images/BRMA12_2H.png new file mode 100644 index 0000000..23d437b Binary files /dev/null and b/hm_web/static/images/BRMA12_2H.png differ diff --git a/hm_web/static/images/BRMA12_3.png b/hm_web/static/images/BRMA12_3.png new file mode 100644 index 0000000..19efec6 Binary files /dev/null and b/hm_web/static/images/BRMA12_3.png differ diff --git a/hm_web/static/images/BRMA12_3H.png b/hm_web/static/images/BRMA12_3H.png new file mode 100644 index 0000000..d537872 Binary files /dev/null and b/hm_web/static/images/BRMA12_3H.png differ diff --git a/hm_web/static/images/BRMA12_4.png b/hm_web/static/images/BRMA12_4.png new file mode 100644 index 0000000..e20687c Binary files /dev/null and b/hm_web/static/images/BRMA12_4.png differ diff --git a/hm_web/static/images/BRMA12_4H.png b/hm_web/static/images/BRMA12_4H.png new file mode 100644 index 0000000..1b5db4e Binary files /dev/null and b/hm_web/static/images/BRMA12_4H.png differ diff --git a/hm_web/static/images/BRMA12_5.png b/hm_web/static/images/BRMA12_5.png new file mode 100644 index 0000000..8f33b5e Binary files /dev/null and b/hm_web/static/images/BRMA12_5.png differ diff --git a/hm_web/static/images/BRMA12_5H.png b/hm_web/static/images/BRMA12_5H.png new file mode 100644 index 0000000..07613db Binary files /dev/null and b/hm_web/static/images/BRMA12_5H.png differ diff --git a/hm_web/static/images/BRMA12_6.png b/hm_web/static/images/BRMA12_6.png new file mode 100644 index 0000000..bb6327f Binary files /dev/null and b/hm_web/static/images/BRMA12_6.png differ diff --git a/hm_web/static/images/BRMA12_6H.png b/hm_web/static/images/BRMA12_6H.png new file mode 100644 index 0000000..afe1ea5 Binary files /dev/null and b/hm_web/static/images/BRMA12_6H.png differ diff --git a/hm_web/static/images/BRMA12_7.png b/hm_web/static/images/BRMA12_7.png new file mode 100644 index 0000000..97f874e Binary files /dev/null and b/hm_web/static/images/BRMA12_7.png differ diff --git a/hm_web/static/images/BRMA12_7H.png b/hm_web/static/images/BRMA12_7H.png new file mode 100644 index 0000000..adee484 Binary files /dev/null and b/hm_web/static/images/BRMA12_7H.png differ diff --git a/hm_web/static/images/BRMA12_8.png b/hm_web/static/images/BRMA12_8.png new file mode 100644 index 0000000..d23afee Binary files /dev/null and b/hm_web/static/images/BRMA12_8.png differ diff --git a/hm_web/static/images/BRMA12_8t.png b/hm_web/static/images/BRMA12_8t.png new file mode 100644 index 0000000..1d03f63 Binary files /dev/null and b/hm_web/static/images/BRMA12_8t.png differ diff --git a/hm_web/static/images/BRMA12_8te.png b/hm_web/static/images/BRMA12_8te.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA12_8te.png differ diff --git a/hm_web/static/images/BRMA12_9.png b/hm_web/static/images/BRMA12_9.png new file mode 100644 index 0000000..2d7a26e Binary files /dev/null and b/hm_web/static/images/BRMA12_9.png differ diff --git a/hm_web/static/images/BRMA13_1.png b/hm_web/static/images/BRMA13_1.png new file mode 100644 index 0000000..f20e078 Binary files /dev/null and b/hm_web/static/images/BRMA13_1.png differ diff --git a/hm_web/static/images/BRMA13_1H.png b/hm_web/static/images/BRMA13_1H.png new file mode 100644 index 0000000..069654f Binary files /dev/null and b/hm_web/static/images/BRMA13_1H.png differ diff --git a/hm_web/static/images/BRMA13_2.png b/hm_web/static/images/BRMA13_2.png new file mode 100644 index 0000000..51f0cca Binary files /dev/null and b/hm_web/static/images/BRMA13_2.png differ diff --git a/hm_web/static/images/BRMA13_2H.png b/hm_web/static/images/BRMA13_2H.png new file mode 100644 index 0000000..977c14e Binary files /dev/null and b/hm_web/static/images/BRMA13_2H.png differ diff --git a/hm_web/static/images/BRMA13_3.png b/hm_web/static/images/BRMA13_3.png new file mode 100644 index 0000000..a0505f1 Binary files /dev/null and b/hm_web/static/images/BRMA13_3.png differ diff --git a/hm_web/static/images/BRMA13_3H.png b/hm_web/static/images/BRMA13_3H.png new file mode 100644 index 0000000..36caed5 Binary files /dev/null and b/hm_web/static/images/BRMA13_3H.png differ diff --git a/hm_web/static/images/BRMA13_4.png b/hm_web/static/images/BRMA13_4.png new file mode 100644 index 0000000..eaa9aef Binary files /dev/null and b/hm_web/static/images/BRMA13_4.png differ diff --git a/hm_web/static/images/BRMA13_4H.png b/hm_web/static/images/BRMA13_4H.png new file mode 100644 index 0000000..d3534f0 Binary files /dev/null and b/hm_web/static/images/BRMA13_4H.png differ diff --git a/hm_web/static/images/BRMA13_4_2_TB.png b/hm_web/static/images/BRMA13_4_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA13_4_2_TB.png differ diff --git a/hm_web/static/images/BRMA13_5.png b/hm_web/static/images/BRMA13_5.png new file mode 100644 index 0000000..a0bd9bd Binary files /dev/null and b/hm_web/static/images/BRMA13_5.png differ diff --git a/hm_web/static/images/BRMA13_6.png b/hm_web/static/images/BRMA13_6.png new file mode 100644 index 0000000..4d2c865 Binary files /dev/null and b/hm_web/static/images/BRMA13_6.png differ diff --git a/hm_web/static/images/BRMA13_7.png b/hm_web/static/images/BRMA13_7.png new file mode 100644 index 0000000..5fd38e4 Binary files /dev/null and b/hm_web/static/images/BRMA13_7.png differ diff --git a/hm_web/static/images/BRMA13_8.png b/hm_web/static/images/BRMA13_8.png new file mode 100644 index 0000000..4409132 Binary files /dev/null and b/hm_web/static/images/BRMA13_8.png differ diff --git a/hm_web/static/images/BRMA14_1.png b/hm_web/static/images/BRMA14_1.png new file mode 100644 index 0000000..caaa4d3 Binary files /dev/null and b/hm_web/static/images/BRMA14_1.png differ diff --git a/hm_web/static/images/BRMA14_10.png b/hm_web/static/images/BRMA14_10.png new file mode 100644 index 0000000..7095aac Binary files /dev/null and b/hm_web/static/images/BRMA14_10.png differ diff --git a/hm_web/static/images/BRMA14_10H.png b/hm_web/static/images/BRMA14_10H.png new file mode 100644 index 0000000..3098c64 Binary files /dev/null and b/hm_web/static/images/BRMA14_10H.png differ diff --git a/hm_web/static/images/BRMA14_10H_TB.png b/hm_web/static/images/BRMA14_10H_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA14_10H_TB.png differ diff --git a/hm_web/static/images/BRMA14_11.png b/hm_web/static/images/BRMA14_11.png new file mode 100644 index 0000000..0a97562 Binary files /dev/null and b/hm_web/static/images/BRMA14_11.png differ diff --git a/hm_web/static/images/BRMA14_12.png b/hm_web/static/images/BRMA14_12.png new file mode 100644 index 0000000..15eb2f4 Binary files /dev/null and b/hm_web/static/images/BRMA14_12.png differ diff --git a/hm_web/static/images/BRMA14_1H.png b/hm_web/static/images/BRMA14_1H.png new file mode 100644 index 0000000..cb5b56f Binary files /dev/null and b/hm_web/static/images/BRMA14_1H.png differ diff --git a/hm_web/static/images/BRMA14_2.png b/hm_web/static/images/BRMA14_2.png new file mode 100644 index 0000000..551f31a Binary files /dev/null and b/hm_web/static/images/BRMA14_2.png differ diff --git a/hm_web/static/images/BRMA14_2H.png b/hm_web/static/images/BRMA14_2H.png new file mode 100644 index 0000000..0a8f73f Binary files /dev/null and b/hm_web/static/images/BRMA14_2H.png differ diff --git a/hm_web/static/images/BRMA14_3.png b/hm_web/static/images/BRMA14_3.png new file mode 100644 index 0000000..63eeda6 Binary files /dev/null and b/hm_web/static/images/BRMA14_3.png differ diff --git a/hm_web/static/images/BRMA14_4.png b/hm_web/static/images/BRMA14_4.png new file mode 100644 index 0000000..9816035 Binary files /dev/null and b/hm_web/static/images/BRMA14_4.png differ diff --git a/hm_web/static/images/BRMA14_4H.png b/hm_web/static/images/BRMA14_4H.png new file mode 100644 index 0000000..06cc59a Binary files /dev/null and b/hm_web/static/images/BRMA14_4H.png differ diff --git a/hm_web/static/images/BRMA14_5.png b/hm_web/static/images/BRMA14_5.png new file mode 100644 index 0000000..b62a38c Binary files /dev/null and b/hm_web/static/images/BRMA14_5.png differ diff --git a/hm_web/static/images/BRMA14_5H.png b/hm_web/static/images/BRMA14_5H.png new file mode 100644 index 0000000..74732b4 Binary files /dev/null and b/hm_web/static/images/BRMA14_5H.png differ diff --git a/hm_web/static/images/BRMA14_6.png b/hm_web/static/images/BRMA14_6.png new file mode 100644 index 0000000..dd38a4c Binary files /dev/null and b/hm_web/static/images/BRMA14_6.png differ diff --git a/hm_web/static/images/BRMA14_6H.png b/hm_web/static/images/BRMA14_6H.png new file mode 100644 index 0000000..8fbb989 Binary files /dev/null and b/hm_web/static/images/BRMA14_6H.png differ diff --git a/hm_web/static/images/BRMA14_7.png b/hm_web/static/images/BRMA14_7.png new file mode 100644 index 0000000..d88f439 Binary files /dev/null and b/hm_web/static/images/BRMA14_7.png differ diff --git a/hm_web/static/images/BRMA14_7H.png b/hm_web/static/images/BRMA14_7H.png new file mode 100644 index 0000000..7d3b27c Binary files /dev/null and b/hm_web/static/images/BRMA14_7H.png differ diff --git a/hm_web/static/images/BRMA14_8.png b/hm_web/static/images/BRMA14_8.png new file mode 100644 index 0000000..4ab00c0 Binary files /dev/null and b/hm_web/static/images/BRMA14_8.png differ diff --git a/hm_web/static/images/BRMA14_8H.png b/hm_web/static/images/BRMA14_8H.png new file mode 100644 index 0000000..00f2489 Binary files /dev/null and b/hm_web/static/images/BRMA14_8H.png differ diff --git a/hm_web/static/images/BRMA14_9.png b/hm_web/static/images/BRMA14_9.png new file mode 100644 index 0000000..4426df2 Binary files /dev/null and b/hm_web/static/images/BRMA14_9.png differ diff --git a/hm_web/static/images/BRMA14_9H.png b/hm_web/static/images/BRMA14_9H.png new file mode 100644 index 0000000..fa30b60 Binary files /dev/null and b/hm_web/static/images/BRMA14_9H.png differ diff --git a/hm_web/static/images/BRMA15_1.png b/hm_web/static/images/BRMA15_1.png new file mode 100644 index 0000000..b966b04 Binary files /dev/null and b/hm_web/static/images/BRMA15_1.png differ diff --git a/hm_web/static/images/BRMA15_1H.png b/hm_web/static/images/BRMA15_1H.png new file mode 100644 index 0000000..ba726d7 Binary files /dev/null and b/hm_web/static/images/BRMA15_1H.png differ diff --git a/hm_web/static/images/BRMA15_2.png b/hm_web/static/images/BRMA15_2.png new file mode 100644 index 0000000..cc619fc Binary files /dev/null and b/hm_web/static/images/BRMA15_2.png differ diff --git a/hm_web/static/images/BRMA15_2H.png b/hm_web/static/images/BRMA15_2H.png new file mode 100644 index 0000000..9095d68 Binary files /dev/null and b/hm_web/static/images/BRMA15_2H.png differ diff --git a/hm_web/static/images/BRMA15_2He.png b/hm_web/static/images/BRMA15_2He.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA15_2He.png differ diff --git a/hm_web/static/images/BRMA15_3.png b/hm_web/static/images/BRMA15_3.png new file mode 100644 index 0000000..c992571 Binary files /dev/null and b/hm_web/static/images/BRMA15_3.png differ diff --git a/hm_web/static/images/BRMA15_4.png b/hm_web/static/images/BRMA15_4.png new file mode 100644 index 0000000..cebfdf7 Binary files /dev/null and b/hm_web/static/images/BRMA15_4.png differ diff --git a/hm_web/static/images/BRMA16_1.png b/hm_web/static/images/BRMA16_1.png new file mode 100644 index 0000000..0d46e7c Binary files /dev/null and b/hm_web/static/images/BRMA16_1.png differ diff --git a/hm_web/static/images/BRMA16_1H.png b/hm_web/static/images/BRMA16_1H.png new file mode 100644 index 0000000..c315b65 Binary files /dev/null and b/hm_web/static/images/BRMA16_1H.png differ diff --git a/hm_web/static/images/BRMA16_2.png b/hm_web/static/images/BRMA16_2.png new file mode 100644 index 0000000..c74071a Binary files /dev/null and b/hm_web/static/images/BRMA16_2.png differ diff --git a/hm_web/static/images/BRMA16_2H.png b/hm_web/static/images/BRMA16_2H.png new file mode 100644 index 0000000..994112c Binary files /dev/null and b/hm_web/static/images/BRMA16_2H.png differ diff --git a/hm_web/static/images/BRMA16_3.png b/hm_web/static/images/BRMA16_3.png new file mode 100644 index 0000000..ad82d73 Binary files /dev/null and b/hm_web/static/images/BRMA16_3.png differ diff --git a/hm_web/static/images/BRMA16_3e.png b/hm_web/static/images/BRMA16_3e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA16_3e.png differ diff --git a/hm_web/static/images/BRMA16_4.png b/hm_web/static/images/BRMA16_4.png new file mode 100644 index 0000000..6ffd024 Binary files /dev/null and b/hm_web/static/images/BRMA16_4.png differ diff --git a/hm_web/static/images/BRMA16_5.png b/hm_web/static/images/BRMA16_5.png new file mode 100644 index 0000000..a0629cb Binary files /dev/null and b/hm_web/static/images/BRMA16_5.png differ diff --git a/hm_web/static/images/BRMA16_5e.png b/hm_web/static/images/BRMA16_5e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA16_5e.png differ diff --git a/hm_web/static/images/BRMA17_2.png b/hm_web/static/images/BRMA17_2.png new file mode 100644 index 0000000..b2b644c Binary files /dev/null and b/hm_web/static/images/BRMA17_2.png differ diff --git a/hm_web/static/images/BRMA17_2H.png b/hm_web/static/images/BRMA17_2H.png new file mode 100644 index 0000000..9a5ecf1 Binary files /dev/null and b/hm_web/static/images/BRMA17_2H.png differ diff --git a/hm_web/static/images/BRMA17_3.png b/hm_web/static/images/BRMA17_3.png new file mode 100644 index 0000000..2220155 Binary files /dev/null and b/hm_web/static/images/BRMA17_3.png differ diff --git a/hm_web/static/images/BRMA17_3H.png b/hm_web/static/images/BRMA17_3H.png new file mode 100644 index 0000000..d060c4f Binary files /dev/null and b/hm_web/static/images/BRMA17_3H.png differ diff --git a/hm_web/static/images/BRMA17_4.png b/hm_web/static/images/BRMA17_4.png new file mode 100644 index 0000000..a44a58e Binary files /dev/null and b/hm_web/static/images/BRMA17_4.png differ diff --git a/hm_web/static/images/BRMA17_5.png b/hm_web/static/images/BRMA17_5.png new file mode 100644 index 0000000..22d0363 Binary files /dev/null and b/hm_web/static/images/BRMA17_5.png differ diff --git a/hm_web/static/images/BRMA17_5H.png b/hm_web/static/images/BRMA17_5H.png new file mode 100644 index 0000000..3890a45 Binary files /dev/null and b/hm_web/static/images/BRMA17_5H.png differ diff --git a/hm_web/static/images/BRMA17_5_TB.png b/hm_web/static/images/BRMA17_5_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMA17_5_TB.png differ diff --git a/hm_web/static/images/BRMA17_6.png b/hm_web/static/images/BRMA17_6.png new file mode 100644 index 0000000..2402275 Binary files /dev/null and b/hm_web/static/images/BRMA17_6.png differ diff --git a/hm_web/static/images/BRMA17_6H.png b/hm_web/static/images/BRMA17_6H.png new file mode 100644 index 0000000..fc58bfc Binary files /dev/null and b/hm_web/static/images/BRMA17_6H.png differ diff --git a/hm_web/static/images/BRMA17_7.png b/hm_web/static/images/BRMA17_7.png new file mode 100644 index 0000000..87de494 Binary files /dev/null and b/hm_web/static/images/BRMA17_7.png differ diff --git a/hm_web/static/images/BRMA17_8.png b/hm_web/static/images/BRMA17_8.png new file mode 100644 index 0000000..035e5c8 Binary files /dev/null and b/hm_web/static/images/BRMA17_8.png differ diff --git a/hm_web/static/images/BRMA17_8H.png b/hm_web/static/images/BRMA17_8H.png new file mode 100644 index 0000000..14094dd Binary files /dev/null and b/hm_web/static/images/BRMA17_8H.png differ diff --git a/hm_web/static/images/BRMA17_9.png b/hm_web/static/images/BRMA17_9.png new file mode 100644 index 0000000..2b79d81 Binary files /dev/null and b/hm_web/static/images/BRMA17_9.png differ diff --git a/hm_web/static/images/BRMA_01.png b/hm_web/static/images/BRMA_01.png new file mode 100644 index 0000000..8cf0ffa Binary files /dev/null and b/hm_web/static/images/BRMA_01.png differ diff --git a/hm_web/static/images/BRMC_100.png b/hm_web/static/images/BRMC_100.png new file mode 100644 index 0000000..7a49ea5 Binary files /dev/null and b/hm_web/static/images/BRMC_100.png differ diff --git a/hm_web/static/images/BRMC_100e.png b/hm_web/static/images/BRMC_100e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMC_100e.png differ diff --git a/hm_web/static/images/BRMC_83.png b/hm_web/static/images/BRMC_83.png new file mode 100644 index 0000000..761cecb Binary files /dev/null and b/hm_web/static/images/BRMC_83.png differ diff --git a/hm_web/static/images/BRMC_84.png b/hm_web/static/images/BRMC_84.png new file mode 100644 index 0000000..b937852 Binary files /dev/null and b/hm_web/static/images/BRMC_84.png differ diff --git a/hm_web/static/images/BRMC_85.png b/hm_web/static/images/BRMC_85.png new file mode 100644 index 0000000..650303b Binary files /dev/null and b/hm_web/static/images/BRMC_85.png differ diff --git a/hm_web/static/images/BRMC_86.png b/hm_web/static/images/BRMC_86.png new file mode 100644 index 0000000..9cd595c Binary files /dev/null and b/hm_web/static/images/BRMC_86.png differ diff --git a/hm_web/static/images/BRMC_86e.png b/hm_web/static/images/BRMC_86e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMC_86e.png differ diff --git a/hm_web/static/images/BRMC_87.png b/hm_web/static/images/BRMC_87.png new file mode 100644 index 0000000..09b9198 Binary files /dev/null and b/hm_web/static/images/BRMC_87.png differ diff --git a/hm_web/static/images/BRMC_88.png b/hm_web/static/images/BRMC_88.png new file mode 100644 index 0000000..65abe87 Binary files /dev/null and b/hm_web/static/images/BRMC_88.png differ diff --git a/hm_web/static/images/BRMC_89.png b/hm_web/static/images/BRMC_89.png new file mode 100644 index 0000000..6475b16 Binary files /dev/null and b/hm_web/static/images/BRMC_89.png differ diff --git a/hm_web/static/images/BRMC_90.png b/hm_web/static/images/BRMC_90.png new file mode 100644 index 0000000..3cd450c Binary files /dev/null and b/hm_web/static/images/BRMC_90.png differ diff --git a/hm_web/static/images/BRMC_91.png b/hm_web/static/images/BRMC_91.png new file mode 100644 index 0000000..53a37c7 Binary files /dev/null and b/hm_web/static/images/BRMC_91.png differ diff --git a/hm_web/static/images/BRMC_92.png b/hm_web/static/images/BRMC_92.png new file mode 100644 index 0000000..958b3ef Binary files /dev/null and b/hm_web/static/images/BRMC_92.png differ diff --git a/hm_web/static/images/BRMC_93.png b/hm_web/static/images/BRMC_93.png new file mode 100644 index 0000000..f6fa0eb Binary files /dev/null and b/hm_web/static/images/BRMC_93.png differ diff --git a/hm_web/static/images/BRMC_94.png b/hm_web/static/images/BRMC_94.png new file mode 100644 index 0000000..7e69af5 Binary files /dev/null and b/hm_web/static/images/BRMC_94.png differ diff --git a/hm_web/static/images/BRMC_95.png b/hm_web/static/images/BRMC_95.png new file mode 100644 index 0000000..6af394e Binary files /dev/null and b/hm_web/static/images/BRMC_95.png differ diff --git a/hm_web/static/images/BRMC_95h.png b/hm_web/static/images/BRMC_95h.png new file mode 100644 index 0000000..2f04045 Binary files /dev/null and b/hm_web/static/images/BRMC_95h.png differ diff --git a/hm_web/static/images/BRMC_95he.png b/hm_web/static/images/BRMC_95he.png new file mode 100644 index 0000000..0bbb245 Binary files /dev/null and b/hm_web/static/images/BRMC_95he.png differ diff --git a/hm_web/static/images/BRMC_96.png b/hm_web/static/images/BRMC_96.png new file mode 100644 index 0000000..37275bd Binary files /dev/null and b/hm_web/static/images/BRMC_96.png differ diff --git a/hm_web/static/images/BRMC_97.png b/hm_web/static/images/BRMC_97.png new file mode 100644 index 0000000..51db4a9 Binary files /dev/null and b/hm_web/static/images/BRMC_97.png differ diff --git a/hm_web/static/images/BRMC_97e.png b/hm_web/static/images/BRMC_97e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMC_97e.png differ diff --git a/hm_web/static/images/BRMC_98.png b/hm_web/static/images/BRMC_98.png new file mode 100644 index 0000000..0abff91 Binary files /dev/null and b/hm_web/static/images/BRMC_98.png differ diff --git a/hm_web/static/images/BRMC_98e.png b/hm_web/static/images/BRMC_98e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRMC_98e.png differ diff --git a/hm_web/static/images/BRMC_99.png b/hm_web/static/images/BRMC_99.png new file mode 100644 index 0000000..9dbf7aa Binary files /dev/null and b/hm_web/static/images/BRMC_99.png differ diff --git a/hm_web/static/images/BRMC_99e.png b/hm_web/static/images/BRMC_99e.png new file mode 100644 index 0000000..423d5df Binary files /dev/null and b/hm_web/static/images/BRMC_99e.png differ diff --git a/hm_web/static/images/BRM_001.png b/hm_web/static/images/BRM_001.png new file mode 100644 index 0000000..a9e4ccf Binary files /dev/null and b/hm_web/static/images/BRM_001.png differ diff --git a/hm_web/static/images/BRM_001e.png b/hm_web/static/images/BRM_001e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_001e.png differ diff --git a/hm_web/static/images/BRM_002.png b/hm_web/static/images/BRM_002.png new file mode 100644 index 0000000..d6776fd Binary files /dev/null and b/hm_web/static/images/BRM_002.png differ diff --git a/hm_web/static/images/BRM_003.png b/hm_web/static/images/BRM_003.png new file mode 100644 index 0000000..83836d8 Binary files /dev/null and b/hm_web/static/images/BRM_003.png differ diff --git a/hm_web/static/images/BRM_003e.png b/hm_web/static/images/BRM_003e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_003e.png differ diff --git a/hm_web/static/images/BRM_004.png b/hm_web/static/images/BRM_004.png new file mode 100644 index 0000000..4645d6a Binary files /dev/null and b/hm_web/static/images/BRM_004.png differ diff --git a/hm_web/static/images/BRM_004e.png b/hm_web/static/images/BRM_004e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_004e.png differ diff --git a/hm_web/static/images/BRM_004t.png b/hm_web/static/images/BRM_004t.png new file mode 100644 index 0000000..694da10 Binary files /dev/null and b/hm_web/static/images/BRM_004t.png differ diff --git a/hm_web/static/images/BRM_005.png b/hm_web/static/images/BRM_005.png new file mode 100644 index 0000000..44a1049 Binary files /dev/null and b/hm_web/static/images/BRM_005.png differ diff --git a/hm_web/static/images/BRM_006.png b/hm_web/static/images/BRM_006.png new file mode 100644 index 0000000..95aff64 Binary files /dev/null and b/hm_web/static/images/BRM_006.png differ diff --git a/hm_web/static/images/BRM_006t.png b/hm_web/static/images/BRM_006t.png new file mode 100644 index 0000000..393ef92 Binary files /dev/null and b/hm_web/static/images/BRM_006t.png differ diff --git a/hm_web/static/images/BRM_007.png b/hm_web/static/images/BRM_007.png new file mode 100644 index 0000000..7696bef Binary files /dev/null and b/hm_web/static/images/BRM_007.png differ diff --git a/hm_web/static/images/BRM_008.png b/hm_web/static/images/BRM_008.png new file mode 100644 index 0000000..6a948d0 Binary files /dev/null and b/hm_web/static/images/BRM_008.png differ diff --git a/hm_web/static/images/BRM_009.png b/hm_web/static/images/BRM_009.png new file mode 100644 index 0000000..0465bfe Binary files /dev/null and b/hm_web/static/images/BRM_009.png differ diff --git a/hm_web/static/images/BRM_010.png b/hm_web/static/images/BRM_010.png new file mode 100644 index 0000000..061176b Binary files /dev/null and b/hm_web/static/images/BRM_010.png differ diff --git a/hm_web/static/images/BRM_010a.png b/hm_web/static/images/BRM_010a.png new file mode 100644 index 0000000..2a4f84e Binary files /dev/null and b/hm_web/static/images/BRM_010a.png differ diff --git a/hm_web/static/images/BRM_010b.png b/hm_web/static/images/BRM_010b.png new file mode 100644 index 0000000..0a032b3 Binary files /dev/null and b/hm_web/static/images/BRM_010b.png differ diff --git a/hm_web/static/images/BRM_010t.png b/hm_web/static/images/BRM_010t.png new file mode 100644 index 0000000..434079f Binary files /dev/null and b/hm_web/static/images/BRM_010t.png differ diff --git a/hm_web/static/images/BRM_010t2.png b/hm_web/static/images/BRM_010t2.png new file mode 100644 index 0000000..6e6b2e9 Binary files /dev/null and b/hm_web/static/images/BRM_010t2.png differ diff --git a/hm_web/static/images/BRM_011.png b/hm_web/static/images/BRM_011.png new file mode 100644 index 0000000..06facb6 Binary files /dev/null and b/hm_web/static/images/BRM_011.png differ diff --git a/hm_web/static/images/BRM_011t.png b/hm_web/static/images/BRM_011t.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_011t.png differ diff --git a/hm_web/static/images/BRM_012.png b/hm_web/static/images/BRM_012.png new file mode 100644 index 0000000..85a39fc Binary files /dev/null and b/hm_web/static/images/BRM_012.png differ diff --git a/hm_web/static/images/BRM_012e.png b/hm_web/static/images/BRM_012e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_012e.png differ diff --git a/hm_web/static/images/BRM_013.png b/hm_web/static/images/BRM_013.png new file mode 100644 index 0000000..0472c24 Binary files /dev/null and b/hm_web/static/images/BRM_013.png differ diff --git a/hm_web/static/images/BRM_014.png b/hm_web/static/images/BRM_014.png new file mode 100644 index 0000000..6e7a292 Binary files /dev/null and b/hm_web/static/images/BRM_014.png differ diff --git a/hm_web/static/images/BRM_014e.png b/hm_web/static/images/BRM_014e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_014e.png differ diff --git a/hm_web/static/images/BRM_015.png b/hm_web/static/images/BRM_015.png new file mode 100644 index 0000000..72f04bb Binary files /dev/null and b/hm_web/static/images/BRM_015.png differ diff --git a/hm_web/static/images/BRM_016.png b/hm_web/static/images/BRM_016.png new file mode 100644 index 0000000..941d33b Binary files /dev/null and b/hm_web/static/images/BRM_016.png differ diff --git a/hm_web/static/images/BRM_017.png b/hm_web/static/images/BRM_017.png new file mode 100644 index 0000000..0c5fa52 Binary files /dev/null and b/hm_web/static/images/BRM_017.png differ diff --git a/hm_web/static/images/BRM_018.png b/hm_web/static/images/BRM_018.png new file mode 100644 index 0000000..24e3559 Binary files /dev/null and b/hm_web/static/images/BRM_018.png differ diff --git a/hm_web/static/images/BRM_018e.png b/hm_web/static/images/BRM_018e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_018e.png differ diff --git a/hm_web/static/images/BRM_019.png b/hm_web/static/images/BRM_019.png new file mode 100644 index 0000000..b991f5a Binary files /dev/null and b/hm_web/static/images/BRM_019.png differ diff --git a/hm_web/static/images/BRM_020.png b/hm_web/static/images/BRM_020.png new file mode 100644 index 0000000..f01759c Binary files /dev/null and b/hm_web/static/images/BRM_020.png differ diff --git a/hm_web/static/images/BRM_020e.png b/hm_web/static/images/BRM_020e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_020e.png differ diff --git a/hm_web/static/images/BRM_022.png b/hm_web/static/images/BRM_022.png new file mode 100644 index 0000000..e978006 Binary files /dev/null and b/hm_web/static/images/BRM_022.png differ diff --git a/hm_web/static/images/BRM_022t.png b/hm_web/static/images/BRM_022t.png new file mode 100644 index 0000000..702293b Binary files /dev/null and b/hm_web/static/images/BRM_022t.png differ diff --git a/hm_web/static/images/BRM_024.png b/hm_web/static/images/BRM_024.png new file mode 100644 index 0000000..ed2a45b Binary files /dev/null and b/hm_web/static/images/BRM_024.png differ diff --git a/hm_web/static/images/BRM_024e.png b/hm_web/static/images/BRM_024e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_024e.png differ diff --git a/hm_web/static/images/BRM_025.png b/hm_web/static/images/BRM_025.png new file mode 100644 index 0000000..4fb814f Binary files /dev/null and b/hm_web/static/images/BRM_025.png differ diff --git a/hm_web/static/images/BRM_026.png b/hm_web/static/images/BRM_026.png new file mode 100644 index 0000000..3960b9a Binary files /dev/null and b/hm_web/static/images/BRM_026.png differ diff --git a/hm_web/static/images/BRM_027.png b/hm_web/static/images/BRM_027.png new file mode 100644 index 0000000..1d93f7d Binary files /dev/null and b/hm_web/static/images/BRM_027.png differ diff --git a/hm_web/static/images/BRM_027h.png b/hm_web/static/images/BRM_027h.png new file mode 100644 index 0000000..a50cacc Binary files /dev/null and b/hm_web/static/images/BRM_027h.png differ diff --git a/hm_web/static/images/BRM_027p.png b/hm_web/static/images/BRM_027p.png new file mode 100644 index 0000000..bc640ce Binary files /dev/null and b/hm_web/static/images/BRM_027p.png differ diff --git a/hm_web/static/images/BRM_027pH.png b/hm_web/static/images/BRM_027pH.png new file mode 100644 index 0000000..6788e35 Binary files /dev/null and b/hm_web/static/images/BRM_027pH.png differ diff --git a/hm_web/static/images/BRM_028.png b/hm_web/static/images/BRM_028.png new file mode 100644 index 0000000..3f549bc Binary files /dev/null and b/hm_web/static/images/BRM_028.png differ diff --git a/hm_web/static/images/BRM_028e.png b/hm_web/static/images/BRM_028e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_028e.png differ diff --git a/hm_web/static/images/BRM_029.png b/hm_web/static/images/BRM_029.png new file mode 100644 index 0000000..ae8587b Binary files /dev/null and b/hm_web/static/images/BRM_029.png differ diff --git a/hm_web/static/images/BRM_030.png b/hm_web/static/images/BRM_030.png new file mode 100644 index 0000000..288f9c7 Binary files /dev/null and b/hm_web/static/images/BRM_030.png differ diff --git a/hm_web/static/images/BRM_030t.png b/hm_web/static/images/BRM_030t.png new file mode 100644 index 0000000..78d741b Binary files /dev/null and b/hm_web/static/images/BRM_030t.png differ diff --git a/hm_web/static/images/BRM_031.png b/hm_web/static/images/BRM_031.png new file mode 100644 index 0000000..f3e7967 Binary files /dev/null and b/hm_web/static/images/BRM_031.png differ diff --git a/hm_web/static/images/BRM_033.png b/hm_web/static/images/BRM_033.png new file mode 100644 index 0000000..7f8ece0 Binary files /dev/null and b/hm_web/static/images/BRM_033.png differ diff --git a/hm_web/static/images/BRM_033e.png b/hm_web/static/images/BRM_033e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/BRM_033e.png differ diff --git a/hm_web/static/images/BRM_034.png b/hm_web/static/images/BRM_034.png new file mode 100644 index 0000000..6eca636 Binary files /dev/null and b/hm_web/static/images/BRM_034.png differ diff --git a/hm_web/static/images/CRED_01.png b/hm_web/static/images/CRED_01.png new file mode 100644 index 0000000..ff44894 Binary files /dev/null and b/hm_web/static/images/CRED_01.png differ diff --git a/hm_web/static/images/CRED_02.png b/hm_web/static/images/CRED_02.png new file mode 100644 index 0000000..44b9981 Binary files /dev/null and b/hm_web/static/images/CRED_02.png differ diff --git a/hm_web/static/images/CRED_03.png b/hm_web/static/images/CRED_03.png new file mode 100644 index 0000000..3338dde Binary files /dev/null and b/hm_web/static/images/CRED_03.png differ diff --git a/hm_web/static/images/CRED_04.png b/hm_web/static/images/CRED_04.png new file mode 100644 index 0000000..d73e879 Binary files /dev/null and b/hm_web/static/images/CRED_04.png differ diff --git a/hm_web/static/images/CRED_05.png b/hm_web/static/images/CRED_05.png new file mode 100644 index 0000000..64f2e4d Binary files /dev/null and b/hm_web/static/images/CRED_05.png differ diff --git a/hm_web/static/images/CRED_06.png b/hm_web/static/images/CRED_06.png new file mode 100644 index 0000000..c51756e Binary files /dev/null and b/hm_web/static/images/CRED_06.png differ diff --git a/hm_web/static/images/CRED_07.png b/hm_web/static/images/CRED_07.png new file mode 100644 index 0000000..1453b5c Binary files /dev/null and b/hm_web/static/images/CRED_07.png differ diff --git a/hm_web/static/images/CRED_08.png b/hm_web/static/images/CRED_08.png new file mode 100644 index 0000000..c575f34 Binary files /dev/null and b/hm_web/static/images/CRED_08.png differ diff --git a/hm_web/static/images/CRED_09.png b/hm_web/static/images/CRED_09.png new file mode 100644 index 0000000..c038570 Binary files /dev/null and b/hm_web/static/images/CRED_09.png differ diff --git a/hm_web/static/images/CRED_10.png b/hm_web/static/images/CRED_10.png new file mode 100644 index 0000000..ddca2ad Binary files /dev/null and b/hm_web/static/images/CRED_10.png differ diff --git a/hm_web/static/images/CRED_11.png b/hm_web/static/images/CRED_11.png new file mode 100644 index 0000000..cdf9a4b Binary files /dev/null and b/hm_web/static/images/CRED_11.png differ diff --git a/hm_web/static/images/CRED_12.png b/hm_web/static/images/CRED_12.png new file mode 100644 index 0000000..c8b7da0 Binary files /dev/null and b/hm_web/static/images/CRED_12.png differ diff --git a/hm_web/static/images/CRED_13.png b/hm_web/static/images/CRED_13.png new file mode 100644 index 0000000..faa240f Binary files /dev/null and b/hm_web/static/images/CRED_13.png differ diff --git a/hm_web/static/images/CRED_14.png b/hm_web/static/images/CRED_14.png new file mode 100644 index 0000000..9307aba Binary files /dev/null and b/hm_web/static/images/CRED_14.png differ diff --git a/hm_web/static/images/CRED_15.png b/hm_web/static/images/CRED_15.png new file mode 100644 index 0000000..80e1742 Binary files /dev/null and b/hm_web/static/images/CRED_15.png differ diff --git a/hm_web/static/images/CRED_16.png b/hm_web/static/images/CRED_16.png new file mode 100644 index 0000000..7449711 Binary files /dev/null and b/hm_web/static/images/CRED_16.png differ diff --git a/hm_web/static/images/CRED_17.png b/hm_web/static/images/CRED_17.png new file mode 100644 index 0000000..c520d46 Binary files /dev/null and b/hm_web/static/images/CRED_17.png differ diff --git a/hm_web/static/images/CRED_18.png b/hm_web/static/images/CRED_18.png new file mode 100644 index 0000000..185a7f6 Binary files /dev/null and b/hm_web/static/images/CRED_18.png differ diff --git a/hm_web/static/images/CRED_19.png b/hm_web/static/images/CRED_19.png new file mode 100644 index 0000000..09cbf6e Binary files /dev/null and b/hm_web/static/images/CRED_19.png differ diff --git a/hm_web/static/images/CRED_20.png b/hm_web/static/images/CRED_20.png new file mode 100644 index 0000000..2b13adc Binary files /dev/null and b/hm_web/static/images/CRED_20.png differ diff --git a/hm_web/static/images/CRED_21.png b/hm_web/static/images/CRED_21.png new file mode 100644 index 0000000..3825931 Binary files /dev/null and b/hm_web/static/images/CRED_21.png differ diff --git a/hm_web/static/images/CRED_22.png b/hm_web/static/images/CRED_22.png new file mode 100644 index 0000000..da3a28d Binary files /dev/null and b/hm_web/static/images/CRED_22.png differ diff --git a/hm_web/static/images/CRED_23.png b/hm_web/static/images/CRED_23.png new file mode 100644 index 0000000..81218f4 Binary files /dev/null and b/hm_web/static/images/CRED_23.png differ diff --git a/hm_web/static/images/CRED_24.png b/hm_web/static/images/CRED_24.png new file mode 100644 index 0000000..59bf015 Binary files /dev/null and b/hm_web/static/images/CRED_24.png differ diff --git a/hm_web/static/images/CRED_25.png b/hm_web/static/images/CRED_25.png new file mode 100644 index 0000000..385079c Binary files /dev/null and b/hm_web/static/images/CRED_25.png differ diff --git a/hm_web/static/images/CRED_26.png b/hm_web/static/images/CRED_26.png new file mode 100644 index 0000000..6f15a47 Binary files /dev/null and b/hm_web/static/images/CRED_26.png differ diff --git a/hm_web/static/images/CRED_27.png b/hm_web/static/images/CRED_27.png new file mode 100644 index 0000000..10d8867 Binary files /dev/null and b/hm_web/static/images/CRED_27.png differ diff --git a/hm_web/static/images/CRED_28.png b/hm_web/static/images/CRED_28.png new file mode 100644 index 0000000..6b283db Binary files /dev/null and b/hm_web/static/images/CRED_28.png differ diff --git a/hm_web/static/images/CRED_29.png b/hm_web/static/images/CRED_29.png new file mode 100644 index 0000000..5098a1c Binary files /dev/null and b/hm_web/static/images/CRED_29.png differ diff --git a/hm_web/static/images/CRED_30.png b/hm_web/static/images/CRED_30.png new file mode 100644 index 0000000..ad81a27 Binary files /dev/null and b/hm_web/static/images/CRED_30.png differ diff --git a/hm_web/static/images/CRED_31.png b/hm_web/static/images/CRED_31.png new file mode 100644 index 0000000..de5d280 Binary files /dev/null and b/hm_web/static/images/CRED_31.png differ diff --git a/hm_web/static/images/CRED_32.png b/hm_web/static/images/CRED_32.png new file mode 100644 index 0000000..c8c1455 Binary files /dev/null and b/hm_web/static/images/CRED_32.png differ diff --git a/hm_web/static/images/CRED_33.png b/hm_web/static/images/CRED_33.png new file mode 100644 index 0000000..1380e32 Binary files /dev/null and b/hm_web/static/images/CRED_33.png differ diff --git a/hm_web/static/images/CRED_34.png b/hm_web/static/images/CRED_34.png new file mode 100644 index 0000000..3a21012 Binary files /dev/null and b/hm_web/static/images/CRED_34.png differ diff --git a/hm_web/static/images/CRED_35.png b/hm_web/static/images/CRED_35.png new file mode 100644 index 0000000..d3cc7ff Binary files /dev/null and b/hm_web/static/images/CRED_35.png differ diff --git a/hm_web/static/images/CRED_36.png b/hm_web/static/images/CRED_36.png new file mode 100644 index 0000000..8de1c07 Binary files /dev/null and b/hm_web/static/images/CRED_36.png differ diff --git a/hm_web/static/images/CRED_37.png b/hm_web/static/images/CRED_37.png new file mode 100644 index 0000000..6be1528 Binary files /dev/null and b/hm_web/static/images/CRED_37.png differ diff --git a/hm_web/static/images/CRED_38.png b/hm_web/static/images/CRED_38.png new file mode 100644 index 0000000..3794825 Binary files /dev/null and b/hm_web/static/images/CRED_38.png differ diff --git a/hm_web/static/images/CRED_39.png b/hm_web/static/images/CRED_39.png new file mode 100644 index 0000000..73793fd Binary files /dev/null and b/hm_web/static/images/CRED_39.png differ diff --git a/hm_web/static/images/CRED_40.png b/hm_web/static/images/CRED_40.png new file mode 100644 index 0000000..14f17a7 Binary files /dev/null and b/hm_web/static/images/CRED_40.png differ diff --git a/hm_web/static/images/CRED_41.png b/hm_web/static/images/CRED_41.png new file mode 100644 index 0000000..5f17992 Binary files /dev/null and b/hm_web/static/images/CRED_41.png differ diff --git a/hm_web/static/images/CRED_42.png b/hm_web/static/images/CRED_42.png new file mode 100644 index 0000000..4727ae6 Binary files /dev/null and b/hm_web/static/images/CRED_42.png differ diff --git a/hm_web/static/images/CRED_43.png b/hm_web/static/images/CRED_43.png new file mode 100644 index 0000000..66bd468 Binary files /dev/null and b/hm_web/static/images/CRED_43.png differ diff --git a/hm_web/static/images/CRED_44.png b/hm_web/static/images/CRED_44.png new file mode 100644 index 0000000..c117757 Binary files /dev/null and b/hm_web/static/images/CRED_44.png differ diff --git a/hm_web/static/images/CRED_45.png b/hm_web/static/images/CRED_45.png new file mode 100644 index 0000000..532c7ae Binary files /dev/null and b/hm_web/static/images/CRED_45.png differ diff --git a/hm_web/static/images/CRED_46.png b/hm_web/static/images/CRED_46.png new file mode 100644 index 0000000..3119077 Binary files /dev/null and b/hm_web/static/images/CRED_46.png differ diff --git a/hm_web/static/images/CS1_042.png b/hm_web/static/images/CS1_042.png new file mode 100644 index 0000000..5c90ed7 Binary files /dev/null and b/hm_web/static/images/CS1_042.png differ diff --git a/hm_web/static/images/CS1_069.png b/hm_web/static/images/CS1_069.png new file mode 100644 index 0000000..95bbeec Binary files /dev/null and b/hm_web/static/images/CS1_069.png differ diff --git a/hm_web/static/images/CS1_112.png b/hm_web/static/images/CS1_112.png new file mode 100644 index 0000000..06da713 Binary files /dev/null and b/hm_web/static/images/CS1_112.png differ diff --git a/hm_web/static/images/CS1_113.png b/hm_web/static/images/CS1_113.png new file mode 100644 index 0000000..02b7eef Binary files /dev/null and b/hm_web/static/images/CS1_113.png differ diff --git a/hm_web/static/images/CS1_129.png b/hm_web/static/images/CS1_129.png new file mode 100644 index 0000000..415a7d6 Binary files /dev/null and b/hm_web/static/images/CS1_129.png differ diff --git a/hm_web/static/images/CS1_129e.png b/hm_web/static/images/CS1_129e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS1_129e.png differ diff --git a/hm_web/static/images/CS1_130.png b/hm_web/static/images/CS1_130.png new file mode 100644 index 0000000..81516a7 Binary files /dev/null and b/hm_web/static/images/CS1_130.png differ diff --git a/hm_web/static/images/CS1h_001.png b/hm_web/static/images/CS1h_001.png new file mode 100644 index 0000000..b4ece13 Binary files /dev/null and b/hm_web/static/images/CS1h_001.png differ diff --git a/hm_web/static/images/CS2_003.png b/hm_web/static/images/CS2_003.png new file mode 100644 index 0000000..a3e02d5 Binary files /dev/null and b/hm_web/static/images/CS2_003.png differ diff --git a/hm_web/static/images/CS2_004.png b/hm_web/static/images/CS2_004.png new file mode 100644 index 0000000..b522092 Binary files /dev/null and b/hm_web/static/images/CS2_004.png differ diff --git a/hm_web/static/images/CS2_004e.png b/hm_web/static/images/CS2_004e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_004e.png differ diff --git a/hm_web/static/images/CS2_005.png b/hm_web/static/images/CS2_005.png new file mode 100644 index 0000000..ed7e542 Binary files /dev/null and b/hm_web/static/images/CS2_005.png differ diff --git a/hm_web/static/images/CS2_005o.png b/hm_web/static/images/CS2_005o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_005o.png differ diff --git a/hm_web/static/images/CS2_007.png b/hm_web/static/images/CS2_007.png new file mode 100644 index 0000000..e623a6f Binary files /dev/null and b/hm_web/static/images/CS2_007.png differ diff --git a/hm_web/static/images/CS2_008.png b/hm_web/static/images/CS2_008.png new file mode 100644 index 0000000..a45a33b Binary files /dev/null and b/hm_web/static/images/CS2_008.png differ diff --git a/hm_web/static/images/CS2_009.png b/hm_web/static/images/CS2_009.png new file mode 100644 index 0000000..462b861 Binary files /dev/null and b/hm_web/static/images/CS2_009.png differ diff --git a/hm_web/static/images/CS2_009e.png b/hm_web/static/images/CS2_009e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_009e.png differ diff --git a/hm_web/static/images/CS2_011.png b/hm_web/static/images/CS2_011.png new file mode 100644 index 0000000..3bb8753 Binary files /dev/null and b/hm_web/static/images/CS2_011.png differ diff --git a/hm_web/static/images/CS2_011o.png b/hm_web/static/images/CS2_011o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_011o.png differ diff --git a/hm_web/static/images/CS2_012.png b/hm_web/static/images/CS2_012.png new file mode 100644 index 0000000..7a405d1 Binary files /dev/null and b/hm_web/static/images/CS2_012.png differ diff --git a/hm_web/static/images/CS2_013.png b/hm_web/static/images/CS2_013.png new file mode 100644 index 0000000..6e379e6 Binary files /dev/null and b/hm_web/static/images/CS2_013.png differ diff --git a/hm_web/static/images/CS2_013t.png b/hm_web/static/images/CS2_013t.png new file mode 100644 index 0000000..3b52dcf Binary files /dev/null and b/hm_web/static/images/CS2_013t.png differ diff --git a/hm_web/static/images/CS2_017.png b/hm_web/static/images/CS2_017.png new file mode 100644 index 0000000..78df41e Binary files /dev/null and b/hm_web/static/images/CS2_017.png differ diff --git a/hm_web/static/images/CS2_017o.png b/hm_web/static/images/CS2_017o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_017o.png differ diff --git a/hm_web/static/images/CS2_022.png b/hm_web/static/images/CS2_022.png new file mode 100644 index 0000000..8557855 Binary files /dev/null and b/hm_web/static/images/CS2_022.png differ diff --git a/hm_web/static/images/CS2_022e.png b/hm_web/static/images/CS2_022e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_022e.png differ diff --git a/hm_web/static/images/CS2_023.png b/hm_web/static/images/CS2_023.png new file mode 100644 index 0000000..986cf0d Binary files /dev/null and b/hm_web/static/images/CS2_023.png differ diff --git a/hm_web/static/images/CS2_024.png b/hm_web/static/images/CS2_024.png new file mode 100644 index 0000000..8502b7e Binary files /dev/null and b/hm_web/static/images/CS2_024.png differ diff --git a/hm_web/static/images/CS2_025.png b/hm_web/static/images/CS2_025.png new file mode 100644 index 0000000..78a5377 Binary files /dev/null and b/hm_web/static/images/CS2_025.png differ diff --git a/hm_web/static/images/CS2_026.png b/hm_web/static/images/CS2_026.png new file mode 100644 index 0000000..20ba2da Binary files /dev/null and b/hm_web/static/images/CS2_026.png differ diff --git a/hm_web/static/images/CS2_027.png b/hm_web/static/images/CS2_027.png new file mode 100644 index 0000000..644cd93 Binary files /dev/null and b/hm_web/static/images/CS2_027.png differ diff --git a/hm_web/static/images/CS2_028.png b/hm_web/static/images/CS2_028.png new file mode 100644 index 0000000..2e559de Binary files /dev/null and b/hm_web/static/images/CS2_028.png differ diff --git a/hm_web/static/images/CS2_029.png b/hm_web/static/images/CS2_029.png new file mode 100644 index 0000000..df42ef4 Binary files /dev/null and b/hm_web/static/images/CS2_029.png differ diff --git a/hm_web/static/images/CS2_031.png b/hm_web/static/images/CS2_031.png new file mode 100644 index 0000000..ccfccfb Binary files /dev/null and b/hm_web/static/images/CS2_031.png differ diff --git a/hm_web/static/images/CS2_032.png b/hm_web/static/images/CS2_032.png new file mode 100644 index 0000000..cfa18b6 Binary files /dev/null and b/hm_web/static/images/CS2_032.png differ diff --git a/hm_web/static/images/CS2_033.png b/hm_web/static/images/CS2_033.png new file mode 100644 index 0000000..523802b Binary files /dev/null and b/hm_web/static/images/CS2_033.png differ diff --git a/hm_web/static/images/CS2_034.png b/hm_web/static/images/CS2_034.png new file mode 100644 index 0000000..2b7d681 Binary files /dev/null and b/hm_web/static/images/CS2_034.png differ diff --git a/hm_web/static/images/CS2_034_H1.png b/hm_web/static/images/CS2_034_H1.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_034_H1.png differ diff --git a/hm_web/static/images/CS2_034_H1_AT_132.png b/hm_web/static/images/CS2_034_H1_AT_132.png new file mode 100644 index 0000000..3320aec Binary files /dev/null and b/hm_web/static/images/CS2_034_H1_AT_132.png differ diff --git a/hm_web/static/images/CS2_034_H2.png b/hm_web/static/images/CS2_034_H2.png new file mode 100644 index 0000000..1bdd9d4 Binary files /dev/null and b/hm_web/static/images/CS2_034_H2.png differ diff --git a/hm_web/static/images/CS2_034_H2_AT_132.png b/hm_web/static/images/CS2_034_H2_AT_132.png new file mode 100644 index 0000000..0872291 Binary files /dev/null and b/hm_web/static/images/CS2_034_H2_AT_132.png differ diff --git a/hm_web/static/images/CS2_037.png b/hm_web/static/images/CS2_037.png new file mode 100644 index 0000000..c94af8c Binary files /dev/null and b/hm_web/static/images/CS2_037.png differ diff --git a/hm_web/static/images/CS2_038.png b/hm_web/static/images/CS2_038.png new file mode 100644 index 0000000..2cc78cb Binary files /dev/null and b/hm_web/static/images/CS2_038.png differ diff --git a/hm_web/static/images/CS2_038e.png b/hm_web/static/images/CS2_038e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_038e.png differ diff --git a/hm_web/static/images/CS2_039.png b/hm_web/static/images/CS2_039.png new file mode 100644 index 0000000..c10ff3c Binary files /dev/null and b/hm_web/static/images/CS2_039.png differ diff --git a/hm_web/static/images/CS2_041.png b/hm_web/static/images/CS2_041.png new file mode 100644 index 0000000..0ca146a Binary files /dev/null and b/hm_web/static/images/CS2_041.png differ diff --git a/hm_web/static/images/CS2_041e.png b/hm_web/static/images/CS2_041e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_041e.png differ diff --git a/hm_web/static/images/CS2_042.png b/hm_web/static/images/CS2_042.png new file mode 100644 index 0000000..206ea24 Binary files /dev/null and b/hm_web/static/images/CS2_042.png differ diff --git a/hm_web/static/images/CS2_045.png b/hm_web/static/images/CS2_045.png new file mode 100644 index 0000000..808f13c Binary files /dev/null and b/hm_web/static/images/CS2_045.png differ diff --git a/hm_web/static/images/CS2_045e.png b/hm_web/static/images/CS2_045e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_045e.png differ diff --git a/hm_web/static/images/CS2_046.png b/hm_web/static/images/CS2_046.png new file mode 100644 index 0000000..36b437e Binary files /dev/null and b/hm_web/static/images/CS2_046.png differ diff --git a/hm_web/static/images/CS2_046e.png b/hm_web/static/images/CS2_046e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_046e.png differ diff --git a/hm_web/static/images/CS2_049.png b/hm_web/static/images/CS2_049.png new file mode 100644 index 0000000..bbf1ba7 Binary files /dev/null and b/hm_web/static/images/CS2_049.png differ diff --git a/hm_web/static/images/CS2_050.png b/hm_web/static/images/CS2_050.png new file mode 100644 index 0000000..da49bbc Binary files /dev/null and b/hm_web/static/images/CS2_050.png differ diff --git a/hm_web/static/images/CS2_051.png b/hm_web/static/images/CS2_051.png new file mode 100644 index 0000000..e7ced15 Binary files /dev/null and b/hm_web/static/images/CS2_051.png differ diff --git a/hm_web/static/images/CS2_052.png b/hm_web/static/images/CS2_052.png new file mode 100644 index 0000000..ae32b30 Binary files /dev/null and b/hm_web/static/images/CS2_052.png differ diff --git a/hm_web/static/images/CS2_053.png b/hm_web/static/images/CS2_053.png new file mode 100644 index 0000000..3050bd8 Binary files /dev/null and b/hm_web/static/images/CS2_053.png differ diff --git a/hm_web/static/images/CS2_053e.png b/hm_web/static/images/CS2_053e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_053e.png differ diff --git a/hm_web/static/images/CS2_056.png b/hm_web/static/images/CS2_056.png new file mode 100644 index 0000000..44bf5e1 Binary files /dev/null and b/hm_web/static/images/CS2_056.png differ diff --git a/hm_web/static/images/CS2_057.png b/hm_web/static/images/CS2_057.png new file mode 100644 index 0000000..93b8093 Binary files /dev/null and b/hm_web/static/images/CS2_057.png differ diff --git a/hm_web/static/images/CS2_059.png b/hm_web/static/images/CS2_059.png new file mode 100644 index 0000000..7a7dc60 Binary files /dev/null and b/hm_web/static/images/CS2_059.png differ diff --git a/hm_web/static/images/CS2_059o.png b/hm_web/static/images/CS2_059o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_059o.png differ diff --git a/hm_web/static/images/CS2_061.png b/hm_web/static/images/CS2_061.png new file mode 100644 index 0000000..6c301d0 Binary files /dev/null and b/hm_web/static/images/CS2_061.png differ diff --git a/hm_web/static/images/CS2_062.png b/hm_web/static/images/CS2_062.png new file mode 100644 index 0000000..95f1258 Binary files /dev/null and b/hm_web/static/images/CS2_062.png differ diff --git a/hm_web/static/images/CS2_063.png b/hm_web/static/images/CS2_063.png new file mode 100644 index 0000000..0d4eb73 Binary files /dev/null and b/hm_web/static/images/CS2_063.png differ diff --git a/hm_web/static/images/CS2_063e.png b/hm_web/static/images/CS2_063e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_063e.png differ diff --git a/hm_web/static/images/CS2_064.png b/hm_web/static/images/CS2_064.png new file mode 100644 index 0000000..869fa13 Binary files /dev/null and b/hm_web/static/images/CS2_064.png differ diff --git a/hm_web/static/images/CS2_065.png b/hm_web/static/images/CS2_065.png new file mode 100644 index 0000000..d891c36 Binary files /dev/null and b/hm_web/static/images/CS2_065.png differ diff --git a/hm_web/static/images/CS2_072.png b/hm_web/static/images/CS2_072.png new file mode 100644 index 0000000..1be5929 Binary files /dev/null and b/hm_web/static/images/CS2_072.png differ diff --git a/hm_web/static/images/CS2_073.png b/hm_web/static/images/CS2_073.png new file mode 100644 index 0000000..a2342cb Binary files /dev/null and b/hm_web/static/images/CS2_073.png differ diff --git a/hm_web/static/images/CS2_073e.png b/hm_web/static/images/CS2_073e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_073e.png differ diff --git a/hm_web/static/images/CS2_073e2.png b/hm_web/static/images/CS2_073e2.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_073e2.png differ diff --git a/hm_web/static/images/CS2_074.png b/hm_web/static/images/CS2_074.png new file mode 100644 index 0000000..00b9985 Binary files /dev/null and b/hm_web/static/images/CS2_074.png differ diff --git a/hm_web/static/images/CS2_074e.png b/hm_web/static/images/CS2_074e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_074e.png differ diff --git a/hm_web/static/images/CS2_075.png b/hm_web/static/images/CS2_075.png new file mode 100644 index 0000000..41827cd Binary files /dev/null and b/hm_web/static/images/CS2_075.png differ diff --git a/hm_web/static/images/CS2_076.png b/hm_web/static/images/CS2_076.png new file mode 100644 index 0000000..369be56 Binary files /dev/null and b/hm_web/static/images/CS2_076.png differ diff --git a/hm_web/static/images/CS2_077.png b/hm_web/static/images/CS2_077.png new file mode 100644 index 0000000..1a53766 Binary files /dev/null and b/hm_web/static/images/CS2_077.png differ diff --git a/hm_web/static/images/CS2_080.png b/hm_web/static/images/CS2_080.png new file mode 100644 index 0000000..9218de3 Binary files /dev/null and b/hm_web/static/images/CS2_080.png differ diff --git a/hm_web/static/images/CS2_082.png b/hm_web/static/images/CS2_082.png new file mode 100644 index 0000000..896cc5a Binary files /dev/null and b/hm_web/static/images/CS2_082.png differ diff --git a/hm_web/static/images/CS2_083b.png b/hm_web/static/images/CS2_083b.png new file mode 100644 index 0000000..bc9b88f Binary files /dev/null and b/hm_web/static/images/CS2_083b.png differ diff --git a/hm_web/static/images/CS2_083e.png b/hm_web/static/images/CS2_083e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_083e.png differ diff --git a/hm_web/static/images/CS2_084.png b/hm_web/static/images/CS2_084.png new file mode 100644 index 0000000..819cbc2 Binary files /dev/null and b/hm_web/static/images/CS2_084.png differ diff --git a/hm_web/static/images/CS2_084e.png b/hm_web/static/images/CS2_084e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_084e.png differ diff --git a/hm_web/static/images/CS2_087.png b/hm_web/static/images/CS2_087.png new file mode 100644 index 0000000..5a96b7a Binary files /dev/null and b/hm_web/static/images/CS2_087.png differ diff --git a/hm_web/static/images/CS2_087e.png b/hm_web/static/images/CS2_087e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_087e.png differ diff --git a/hm_web/static/images/CS2_088.png b/hm_web/static/images/CS2_088.png new file mode 100644 index 0000000..8efba0b Binary files /dev/null and b/hm_web/static/images/CS2_088.png differ diff --git a/hm_web/static/images/CS2_089.png b/hm_web/static/images/CS2_089.png new file mode 100644 index 0000000..85fb1af Binary files /dev/null and b/hm_web/static/images/CS2_089.png differ diff --git a/hm_web/static/images/CS2_091.png b/hm_web/static/images/CS2_091.png new file mode 100644 index 0000000..10f0b68 Binary files /dev/null and b/hm_web/static/images/CS2_091.png differ diff --git a/hm_web/static/images/CS2_092.png b/hm_web/static/images/CS2_092.png new file mode 100644 index 0000000..e800db4 Binary files /dev/null and b/hm_web/static/images/CS2_092.png differ diff --git a/hm_web/static/images/CS2_092e.png b/hm_web/static/images/CS2_092e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_092e.png differ diff --git a/hm_web/static/images/CS2_093.png b/hm_web/static/images/CS2_093.png new file mode 100644 index 0000000..518347e Binary files /dev/null and b/hm_web/static/images/CS2_093.png differ diff --git a/hm_web/static/images/CS2_094.png b/hm_web/static/images/CS2_094.png new file mode 100644 index 0000000..300fa1f Binary files /dev/null and b/hm_web/static/images/CS2_094.png differ diff --git a/hm_web/static/images/CS2_097.png b/hm_web/static/images/CS2_097.png new file mode 100644 index 0000000..9940156 Binary files /dev/null and b/hm_web/static/images/CS2_097.png differ diff --git a/hm_web/static/images/CS2_101.png b/hm_web/static/images/CS2_101.png new file mode 100644 index 0000000..a3ee783 Binary files /dev/null and b/hm_web/static/images/CS2_101.png differ diff --git a/hm_web/static/images/CS2_101_H1.png b/hm_web/static/images/CS2_101_H1.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_101_H1.png differ diff --git a/hm_web/static/images/CS2_101_H1_AT_132.png b/hm_web/static/images/CS2_101_H1_AT_132.png new file mode 100644 index 0000000..82567fd Binary files /dev/null and b/hm_web/static/images/CS2_101_H1_AT_132.png differ diff --git a/hm_web/static/images/CS2_101t.png b/hm_web/static/images/CS2_101t.png new file mode 100644 index 0000000..b733702 Binary files /dev/null and b/hm_web/static/images/CS2_101t.png differ diff --git a/hm_web/static/images/CS2_102.png b/hm_web/static/images/CS2_102.png new file mode 100644 index 0000000..991bba5 Binary files /dev/null and b/hm_web/static/images/CS2_102.png differ diff --git a/hm_web/static/images/CS2_102_H1.png b/hm_web/static/images/CS2_102_H1.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_102_H1.png differ diff --git a/hm_web/static/images/CS2_102_H1_AT_132.png b/hm_web/static/images/CS2_102_H1_AT_132.png new file mode 100644 index 0000000..49ec50d Binary files /dev/null and b/hm_web/static/images/CS2_102_H1_AT_132.png differ diff --git a/hm_web/static/images/CS2_103.png b/hm_web/static/images/CS2_103.png new file mode 100644 index 0000000..f09bf85 Binary files /dev/null and b/hm_web/static/images/CS2_103.png differ diff --git a/hm_web/static/images/CS2_103e2.png b/hm_web/static/images/CS2_103e2.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_103e2.png differ diff --git a/hm_web/static/images/CS2_104.png b/hm_web/static/images/CS2_104.png new file mode 100644 index 0000000..28d302f Binary files /dev/null and b/hm_web/static/images/CS2_104.png differ diff --git a/hm_web/static/images/CS2_104e.png b/hm_web/static/images/CS2_104e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_104e.png differ diff --git a/hm_web/static/images/CS2_105.png b/hm_web/static/images/CS2_105.png new file mode 100644 index 0000000..ed7b4b7 Binary files /dev/null and b/hm_web/static/images/CS2_105.png differ diff --git a/hm_web/static/images/CS2_105e.png b/hm_web/static/images/CS2_105e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_105e.png differ diff --git a/hm_web/static/images/CS2_106.png b/hm_web/static/images/CS2_106.png new file mode 100644 index 0000000..08a5ee9 Binary files /dev/null and b/hm_web/static/images/CS2_106.png differ diff --git a/hm_web/static/images/CS2_108.png b/hm_web/static/images/CS2_108.png new file mode 100644 index 0000000..ca11ef7 Binary files /dev/null and b/hm_web/static/images/CS2_108.png differ diff --git a/hm_web/static/images/CS2_112.png b/hm_web/static/images/CS2_112.png new file mode 100644 index 0000000..5d17c3f Binary files /dev/null and b/hm_web/static/images/CS2_112.png differ diff --git a/hm_web/static/images/CS2_114.png b/hm_web/static/images/CS2_114.png new file mode 100644 index 0000000..11da6ae Binary files /dev/null and b/hm_web/static/images/CS2_114.png differ diff --git a/hm_web/static/images/CS2_117.png b/hm_web/static/images/CS2_117.png new file mode 100644 index 0000000..09a7758 Binary files /dev/null and b/hm_web/static/images/CS2_117.png differ diff --git a/hm_web/static/images/CS2_118.png b/hm_web/static/images/CS2_118.png new file mode 100644 index 0000000..cb2adcf Binary files /dev/null and b/hm_web/static/images/CS2_118.png differ diff --git a/hm_web/static/images/CS2_119.png b/hm_web/static/images/CS2_119.png new file mode 100644 index 0000000..f44803a Binary files /dev/null and b/hm_web/static/images/CS2_119.png differ diff --git a/hm_web/static/images/CS2_120.png b/hm_web/static/images/CS2_120.png new file mode 100644 index 0000000..77a5548 Binary files /dev/null and b/hm_web/static/images/CS2_120.png differ diff --git a/hm_web/static/images/CS2_121.png b/hm_web/static/images/CS2_121.png new file mode 100644 index 0000000..e827399 Binary files /dev/null and b/hm_web/static/images/CS2_121.png differ diff --git a/hm_web/static/images/CS2_122.png b/hm_web/static/images/CS2_122.png new file mode 100644 index 0000000..1568349 Binary files /dev/null and b/hm_web/static/images/CS2_122.png differ diff --git a/hm_web/static/images/CS2_122e.png b/hm_web/static/images/CS2_122e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_122e.png differ diff --git a/hm_web/static/images/CS2_124.png b/hm_web/static/images/CS2_124.png new file mode 100644 index 0000000..6aa07e1 Binary files /dev/null and b/hm_web/static/images/CS2_124.png differ diff --git a/hm_web/static/images/CS2_125.png b/hm_web/static/images/CS2_125.png new file mode 100644 index 0000000..e1d72fe Binary files /dev/null and b/hm_web/static/images/CS2_125.png differ diff --git a/hm_web/static/images/CS2_127.png b/hm_web/static/images/CS2_127.png new file mode 100644 index 0000000..f86903b Binary files /dev/null and b/hm_web/static/images/CS2_127.png differ diff --git a/hm_web/static/images/CS2_131.png b/hm_web/static/images/CS2_131.png new file mode 100644 index 0000000..6ab45d1 Binary files /dev/null and b/hm_web/static/images/CS2_131.png differ diff --git a/hm_web/static/images/CS2_141.png b/hm_web/static/images/CS2_141.png new file mode 100644 index 0000000..3e6b2a2 Binary files /dev/null and b/hm_web/static/images/CS2_141.png differ diff --git a/hm_web/static/images/CS2_142.png b/hm_web/static/images/CS2_142.png new file mode 100644 index 0000000..9173922 Binary files /dev/null and b/hm_web/static/images/CS2_142.png differ diff --git a/hm_web/static/images/CS2_146.png b/hm_web/static/images/CS2_146.png new file mode 100644 index 0000000..a12706d Binary files /dev/null and b/hm_web/static/images/CS2_146.png differ diff --git a/hm_web/static/images/CS2_147.png b/hm_web/static/images/CS2_147.png new file mode 100644 index 0000000..c2b3ec9 Binary files /dev/null and b/hm_web/static/images/CS2_147.png differ diff --git a/hm_web/static/images/CS2_150.png b/hm_web/static/images/CS2_150.png new file mode 100644 index 0000000..3fb109a Binary files /dev/null and b/hm_web/static/images/CS2_150.png differ diff --git a/hm_web/static/images/CS2_151.png b/hm_web/static/images/CS2_151.png new file mode 100644 index 0000000..49899b4 Binary files /dev/null and b/hm_web/static/images/CS2_151.png differ diff --git a/hm_web/static/images/CS2_152.png b/hm_web/static/images/CS2_152.png new file mode 100644 index 0000000..b375ee5 Binary files /dev/null and b/hm_web/static/images/CS2_152.png differ diff --git a/hm_web/static/images/CS2_155.png b/hm_web/static/images/CS2_155.png new file mode 100644 index 0000000..1ffd92d Binary files /dev/null and b/hm_web/static/images/CS2_155.png differ diff --git a/hm_web/static/images/CS2_161.png b/hm_web/static/images/CS2_161.png new file mode 100644 index 0000000..d0e850f Binary files /dev/null and b/hm_web/static/images/CS2_161.png differ diff --git a/hm_web/static/images/CS2_162.png b/hm_web/static/images/CS2_162.png new file mode 100644 index 0000000..911ed59 Binary files /dev/null and b/hm_web/static/images/CS2_162.png differ diff --git a/hm_web/static/images/CS2_168.png b/hm_web/static/images/CS2_168.png new file mode 100644 index 0000000..1c6f8fc Binary files /dev/null and b/hm_web/static/images/CS2_168.png differ diff --git a/hm_web/static/images/CS2_169.png b/hm_web/static/images/CS2_169.png new file mode 100644 index 0000000..ced99dd Binary files /dev/null and b/hm_web/static/images/CS2_169.png differ diff --git a/hm_web/static/images/CS2_171.png b/hm_web/static/images/CS2_171.png new file mode 100644 index 0000000..c470b09 Binary files /dev/null and b/hm_web/static/images/CS2_171.png differ diff --git a/hm_web/static/images/CS2_172.png b/hm_web/static/images/CS2_172.png new file mode 100644 index 0000000..72ec904 Binary files /dev/null and b/hm_web/static/images/CS2_172.png differ diff --git a/hm_web/static/images/CS2_173.png b/hm_web/static/images/CS2_173.png new file mode 100644 index 0000000..5cd02f9 Binary files /dev/null and b/hm_web/static/images/CS2_173.png differ diff --git a/hm_web/static/images/CS2_179.png b/hm_web/static/images/CS2_179.png new file mode 100644 index 0000000..b703166 Binary files /dev/null and b/hm_web/static/images/CS2_179.png differ diff --git a/hm_web/static/images/CS2_181.png b/hm_web/static/images/CS2_181.png new file mode 100644 index 0000000..29eb94a Binary files /dev/null and b/hm_web/static/images/CS2_181.png differ diff --git a/hm_web/static/images/CS2_181e.png b/hm_web/static/images/CS2_181e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_181e.png differ diff --git a/hm_web/static/images/CS2_182.png b/hm_web/static/images/CS2_182.png new file mode 100644 index 0000000..023b42d Binary files /dev/null and b/hm_web/static/images/CS2_182.png differ diff --git a/hm_web/static/images/CS2_186.png b/hm_web/static/images/CS2_186.png new file mode 100644 index 0000000..2304e16 Binary files /dev/null and b/hm_web/static/images/CS2_186.png differ diff --git a/hm_web/static/images/CS2_187.png b/hm_web/static/images/CS2_187.png new file mode 100644 index 0000000..106518b Binary files /dev/null and b/hm_web/static/images/CS2_187.png differ diff --git a/hm_web/static/images/CS2_188.png b/hm_web/static/images/CS2_188.png new file mode 100644 index 0000000..d76aff7 Binary files /dev/null and b/hm_web/static/images/CS2_188.png differ diff --git a/hm_web/static/images/CS2_188o.png b/hm_web/static/images/CS2_188o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_188o.png differ diff --git a/hm_web/static/images/CS2_189.png b/hm_web/static/images/CS2_189.png new file mode 100644 index 0000000..a91e906 Binary files /dev/null and b/hm_web/static/images/CS2_189.png differ diff --git a/hm_web/static/images/CS2_196.png b/hm_web/static/images/CS2_196.png new file mode 100644 index 0000000..b09cd00 Binary files /dev/null and b/hm_web/static/images/CS2_196.png differ diff --git a/hm_web/static/images/CS2_197.png b/hm_web/static/images/CS2_197.png new file mode 100644 index 0000000..14882cb Binary files /dev/null and b/hm_web/static/images/CS2_197.png differ diff --git a/hm_web/static/images/CS2_200.png b/hm_web/static/images/CS2_200.png new file mode 100644 index 0000000..86322c9 Binary files /dev/null and b/hm_web/static/images/CS2_200.png differ diff --git a/hm_web/static/images/CS2_201.png b/hm_web/static/images/CS2_201.png new file mode 100644 index 0000000..eb4077f Binary files /dev/null and b/hm_web/static/images/CS2_201.png differ diff --git a/hm_web/static/images/CS2_203.png b/hm_web/static/images/CS2_203.png new file mode 100644 index 0000000..0402c59 Binary files /dev/null and b/hm_web/static/images/CS2_203.png differ diff --git a/hm_web/static/images/CS2_213.png b/hm_web/static/images/CS2_213.png new file mode 100644 index 0000000..09f2bc5 Binary files /dev/null and b/hm_web/static/images/CS2_213.png differ diff --git a/hm_web/static/images/CS2_221.png b/hm_web/static/images/CS2_221.png new file mode 100644 index 0000000..44d7f71 Binary files /dev/null and b/hm_web/static/images/CS2_221.png differ diff --git a/hm_web/static/images/CS2_221e.png b/hm_web/static/images/CS2_221e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_221e.png differ diff --git a/hm_web/static/images/CS2_222.png b/hm_web/static/images/CS2_222.png new file mode 100644 index 0000000..8cf9e5e Binary files /dev/null and b/hm_web/static/images/CS2_222.png differ diff --git a/hm_web/static/images/CS2_222o.png b/hm_web/static/images/CS2_222o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_222o.png differ diff --git a/hm_web/static/images/CS2_226.png b/hm_web/static/images/CS2_226.png new file mode 100644 index 0000000..6d56122 Binary files /dev/null and b/hm_web/static/images/CS2_226.png differ diff --git a/hm_web/static/images/CS2_226e.png b/hm_web/static/images/CS2_226e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_226e.png differ diff --git a/hm_web/static/images/CS2_227.png b/hm_web/static/images/CS2_227.png new file mode 100644 index 0000000..8582ee8 Binary files /dev/null and b/hm_web/static/images/CS2_227.png differ diff --git a/hm_web/static/images/CS2_231.png b/hm_web/static/images/CS2_231.png new file mode 100644 index 0000000..0df60f8 Binary files /dev/null and b/hm_web/static/images/CS2_231.png differ diff --git a/hm_web/static/images/CS2_232.png b/hm_web/static/images/CS2_232.png new file mode 100644 index 0000000..4f4b795 Binary files /dev/null and b/hm_web/static/images/CS2_232.png differ diff --git a/hm_web/static/images/CS2_233.png b/hm_web/static/images/CS2_233.png new file mode 100644 index 0000000..51a6378 Binary files /dev/null and b/hm_web/static/images/CS2_233.png differ diff --git a/hm_web/static/images/CS2_234.png b/hm_web/static/images/CS2_234.png new file mode 100644 index 0000000..92947da Binary files /dev/null and b/hm_web/static/images/CS2_234.png differ diff --git a/hm_web/static/images/CS2_235.png b/hm_web/static/images/CS2_235.png new file mode 100644 index 0000000..d0408f1 Binary files /dev/null and b/hm_web/static/images/CS2_235.png differ diff --git a/hm_web/static/images/CS2_236.png b/hm_web/static/images/CS2_236.png new file mode 100644 index 0000000..36cee28 Binary files /dev/null and b/hm_web/static/images/CS2_236.png differ diff --git a/hm_web/static/images/CS2_236e.png b/hm_web/static/images/CS2_236e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/CS2_236e.png differ diff --git a/hm_web/static/images/CS2_237.png b/hm_web/static/images/CS2_237.png new file mode 100644 index 0000000..9236587 Binary files /dev/null and b/hm_web/static/images/CS2_237.png differ diff --git a/hm_web/static/images/CS2_boar.png b/hm_web/static/images/CS2_boar.png new file mode 100644 index 0000000..ae99129 Binary files /dev/null and b/hm_web/static/images/CS2_boar.png differ diff --git a/hm_web/static/images/CS2_mirror.png b/hm_web/static/images/CS2_mirror.png new file mode 100644 index 0000000..ce45daa Binary files /dev/null and b/hm_web/static/images/CS2_mirror.png differ diff --git a/hm_web/static/images/CS2_tk1.png b/hm_web/static/images/CS2_tk1.png new file mode 100644 index 0000000..7effe96 Binary files /dev/null and b/hm_web/static/images/CS2_tk1.png differ diff --git a/hm_web/static/images/DREAM_01.png b/hm_web/static/images/DREAM_01.png new file mode 100644 index 0000000..9c919f6 Binary files /dev/null and b/hm_web/static/images/DREAM_01.png differ diff --git a/hm_web/static/images/DREAM_02.png b/hm_web/static/images/DREAM_02.png new file mode 100644 index 0000000..b165662 Binary files /dev/null and b/hm_web/static/images/DREAM_02.png differ diff --git a/hm_web/static/images/DREAM_03.png b/hm_web/static/images/DREAM_03.png new file mode 100644 index 0000000..8500ac5 Binary files /dev/null and b/hm_web/static/images/DREAM_03.png differ diff --git a/hm_web/static/images/DREAM_04.png b/hm_web/static/images/DREAM_04.png new file mode 100644 index 0000000..9156ada Binary files /dev/null and b/hm_web/static/images/DREAM_04.png differ diff --git a/hm_web/static/images/DREAM_05.png b/hm_web/static/images/DREAM_05.png new file mode 100644 index 0000000..5e1748c Binary files /dev/null and b/hm_web/static/images/DREAM_05.png differ diff --git a/hm_web/static/images/DREAM_05e.png b/hm_web/static/images/DREAM_05e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/DREAM_05e.png differ diff --git a/hm_web/static/images/DS1_055.png b/hm_web/static/images/DS1_055.png new file mode 100644 index 0000000..8e0e254 Binary files /dev/null and b/hm_web/static/images/DS1_055.png differ diff --git a/hm_web/static/images/DS1_070.png b/hm_web/static/images/DS1_070.png new file mode 100644 index 0000000..662b678 Binary files /dev/null and b/hm_web/static/images/DS1_070.png differ diff --git a/hm_web/static/images/DS1_070o.png b/hm_web/static/images/DS1_070o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/DS1_070o.png differ diff --git a/hm_web/static/images/DS1_175.png b/hm_web/static/images/DS1_175.png new file mode 100644 index 0000000..6503417 Binary files /dev/null and b/hm_web/static/images/DS1_175.png differ diff --git a/hm_web/static/images/DS1_175o.png b/hm_web/static/images/DS1_175o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/DS1_175o.png differ diff --git a/hm_web/static/images/DS1_178.png b/hm_web/static/images/DS1_178.png new file mode 100644 index 0000000..3f0b537 Binary files /dev/null and b/hm_web/static/images/DS1_178.png differ diff --git a/hm_web/static/images/DS1_178e.png b/hm_web/static/images/DS1_178e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/DS1_178e.png differ diff --git a/hm_web/static/images/DS1_183.png b/hm_web/static/images/DS1_183.png new file mode 100644 index 0000000..84db7b4 Binary files /dev/null and b/hm_web/static/images/DS1_183.png differ diff --git a/hm_web/static/images/DS1_184.png b/hm_web/static/images/DS1_184.png new file mode 100644 index 0000000..58a0a48 Binary files /dev/null and b/hm_web/static/images/DS1_184.png differ diff --git a/hm_web/static/images/DS1_185.png b/hm_web/static/images/DS1_185.png new file mode 100644 index 0000000..9f3203e Binary files /dev/null and b/hm_web/static/images/DS1_185.png differ diff --git a/hm_web/static/images/DS1_188.png b/hm_web/static/images/DS1_188.png new file mode 100644 index 0000000..ebf417f Binary files /dev/null and b/hm_web/static/images/DS1_188.png differ diff --git a/hm_web/static/images/DS1_188e.png b/hm_web/static/images/DS1_188e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/DS1_188e.png differ diff --git a/hm_web/static/images/DS1_233.png b/hm_web/static/images/DS1_233.png new file mode 100644 index 0000000..071dfcd Binary files /dev/null and b/hm_web/static/images/DS1_233.png differ diff --git a/hm_web/static/images/DS1h_292.png b/hm_web/static/images/DS1h_292.png new file mode 100644 index 0000000..2330807 Binary files /dev/null and b/hm_web/static/images/DS1h_292.png differ diff --git a/hm_web/static/images/DS1h_292_H1.png b/hm_web/static/images/DS1h_292_H1.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/DS1h_292_H1.png differ diff --git a/hm_web/static/images/DS1h_292_H1_AT_132.png b/hm_web/static/images/DS1h_292_H1_AT_132.png new file mode 100644 index 0000000..8b00dc9 Binary files /dev/null and b/hm_web/static/images/DS1h_292_H1_AT_132.png differ diff --git a/hm_web/static/images/EX1_001.png b/hm_web/static/images/EX1_001.png new file mode 100644 index 0000000..6d01b71 Binary files /dev/null and b/hm_web/static/images/EX1_001.png differ diff --git a/hm_web/static/images/EX1_001e.png b/hm_web/static/images/EX1_001e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_001e.png differ diff --git a/hm_web/static/images/EX1_002.png b/hm_web/static/images/EX1_002.png new file mode 100644 index 0000000..a70a675 Binary files /dev/null and b/hm_web/static/images/EX1_002.png differ diff --git a/hm_web/static/images/EX1_004.png b/hm_web/static/images/EX1_004.png new file mode 100644 index 0000000..45224c4 Binary files /dev/null and b/hm_web/static/images/EX1_004.png differ diff --git a/hm_web/static/images/EX1_004e.png b/hm_web/static/images/EX1_004e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_004e.png differ diff --git a/hm_web/static/images/EX1_005.png b/hm_web/static/images/EX1_005.png new file mode 100644 index 0000000..59ed8da Binary files /dev/null and b/hm_web/static/images/EX1_005.png differ diff --git a/hm_web/static/images/EX1_006.png b/hm_web/static/images/EX1_006.png new file mode 100644 index 0000000..4f8c653 Binary files /dev/null and b/hm_web/static/images/EX1_006.png differ diff --git a/hm_web/static/images/EX1_007.png b/hm_web/static/images/EX1_007.png new file mode 100644 index 0000000..53951fe Binary files /dev/null and b/hm_web/static/images/EX1_007.png differ diff --git a/hm_web/static/images/EX1_008.png b/hm_web/static/images/EX1_008.png new file mode 100644 index 0000000..c05c78b Binary files /dev/null and b/hm_web/static/images/EX1_008.png differ diff --git a/hm_web/static/images/EX1_009.png b/hm_web/static/images/EX1_009.png new file mode 100644 index 0000000..839d05d Binary files /dev/null and b/hm_web/static/images/EX1_009.png differ diff --git a/hm_web/static/images/EX1_009e.png b/hm_web/static/images/EX1_009e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_009e.png differ diff --git a/hm_web/static/images/EX1_010.png b/hm_web/static/images/EX1_010.png new file mode 100644 index 0000000..34bb4b0 Binary files /dev/null and b/hm_web/static/images/EX1_010.png differ diff --git a/hm_web/static/images/EX1_011.png b/hm_web/static/images/EX1_011.png new file mode 100644 index 0000000..4f1c492 Binary files /dev/null and b/hm_web/static/images/EX1_011.png differ diff --git a/hm_web/static/images/EX1_012.png b/hm_web/static/images/EX1_012.png new file mode 100644 index 0000000..34e67e9 Binary files /dev/null and b/hm_web/static/images/EX1_012.png differ diff --git a/hm_web/static/images/EX1_014.png b/hm_web/static/images/EX1_014.png new file mode 100644 index 0000000..e978f53 Binary files /dev/null and b/hm_web/static/images/EX1_014.png differ diff --git a/hm_web/static/images/EX1_014t.png b/hm_web/static/images/EX1_014t.png new file mode 100644 index 0000000..51fe75d Binary files /dev/null and b/hm_web/static/images/EX1_014t.png differ diff --git a/hm_web/static/images/EX1_014te.png b/hm_web/static/images/EX1_014te.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_014te.png differ diff --git a/hm_web/static/images/EX1_015.png b/hm_web/static/images/EX1_015.png new file mode 100644 index 0000000..3a3c2c4 Binary files /dev/null and b/hm_web/static/images/EX1_015.png differ diff --git a/hm_web/static/images/EX1_016.png b/hm_web/static/images/EX1_016.png new file mode 100644 index 0000000..df13178 Binary files /dev/null and b/hm_web/static/images/EX1_016.png differ diff --git a/hm_web/static/images/EX1_017.png b/hm_web/static/images/EX1_017.png new file mode 100644 index 0000000..9c5bca8 Binary files /dev/null and b/hm_web/static/images/EX1_017.png differ diff --git a/hm_web/static/images/EX1_019.png b/hm_web/static/images/EX1_019.png new file mode 100644 index 0000000..245bbfd Binary files /dev/null and b/hm_web/static/images/EX1_019.png differ diff --git a/hm_web/static/images/EX1_019e.png b/hm_web/static/images/EX1_019e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_019e.png differ diff --git a/hm_web/static/images/EX1_020.png b/hm_web/static/images/EX1_020.png new file mode 100644 index 0000000..cf9dbf4 Binary files /dev/null and b/hm_web/static/images/EX1_020.png differ diff --git a/hm_web/static/images/EX1_021.png b/hm_web/static/images/EX1_021.png new file mode 100644 index 0000000..0a2f1fe Binary files /dev/null and b/hm_web/static/images/EX1_021.png differ diff --git a/hm_web/static/images/EX1_023.png b/hm_web/static/images/EX1_023.png new file mode 100644 index 0000000..be33acb Binary files /dev/null and b/hm_web/static/images/EX1_023.png differ diff --git a/hm_web/static/images/EX1_025.png b/hm_web/static/images/EX1_025.png new file mode 100644 index 0000000..d43fff6 Binary files /dev/null and b/hm_web/static/images/EX1_025.png differ diff --git a/hm_web/static/images/EX1_025t.png b/hm_web/static/images/EX1_025t.png new file mode 100644 index 0000000..ae09972 Binary files /dev/null and b/hm_web/static/images/EX1_025t.png differ diff --git a/hm_web/static/images/EX1_028.png b/hm_web/static/images/EX1_028.png new file mode 100644 index 0000000..b007c83 Binary files /dev/null and b/hm_web/static/images/EX1_028.png differ diff --git a/hm_web/static/images/EX1_029.png b/hm_web/static/images/EX1_029.png new file mode 100644 index 0000000..bdfd60f Binary files /dev/null and b/hm_web/static/images/EX1_029.png differ diff --git a/hm_web/static/images/EX1_032.png b/hm_web/static/images/EX1_032.png new file mode 100644 index 0000000..0c86d29 Binary files /dev/null and b/hm_web/static/images/EX1_032.png differ diff --git a/hm_web/static/images/EX1_033.png b/hm_web/static/images/EX1_033.png new file mode 100644 index 0000000..9537e4e Binary files /dev/null and b/hm_web/static/images/EX1_033.png differ diff --git a/hm_web/static/images/EX1_043.png b/hm_web/static/images/EX1_043.png new file mode 100644 index 0000000..e600cac Binary files /dev/null and b/hm_web/static/images/EX1_043.png differ diff --git a/hm_web/static/images/EX1_043e.png b/hm_web/static/images/EX1_043e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_043e.png differ diff --git a/hm_web/static/images/EX1_044.png b/hm_web/static/images/EX1_044.png new file mode 100644 index 0000000..f396c00 Binary files /dev/null and b/hm_web/static/images/EX1_044.png differ diff --git a/hm_web/static/images/EX1_044e.png b/hm_web/static/images/EX1_044e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_044e.png differ diff --git a/hm_web/static/images/EX1_045.png b/hm_web/static/images/EX1_045.png new file mode 100644 index 0000000..a7289f4 Binary files /dev/null and b/hm_web/static/images/EX1_045.png differ diff --git a/hm_web/static/images/EX1_046.png b/hm_web/static/images/EX1_046.png new file mode 100644 index 0000000..f4410c8 Binary files /dev/null and b/hm_web/static/images/EX1_046.png differ diff --git a/hm_web/static/images/EX1_046e.png b/hm_web/static/images/EX1_046e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_046e.png differ diff --git a/hm_web/static/images/EX1_048.png b/hm_web/static/images/EX1_048.png new file mode 100644 index 0000000..e14bcf3 Binary files /dev/null and b/hm_web/static/images/EX1_048.png differ diff --git a/hm_web/static/images/EX1_049.png b/hm_web/static/images/EX1_049.png new file mode 100644 index 0000000..780cc07 Binary files /dev/null and b/hm_web/static/images/EX1_049.png differ diff --git a/hm_web/static/images/EX1_050.png b/hm_web/static/images/EX1_050.png new file mode 100644 index 0000000..29bc39e Binary files /dev/null and b/hm_web/static/images/EX1_050.png differ diff --git a/hm_web/static/images/EX1_055.png b/hm_web/static/images/EX1_055.png new file mode 100644 index 0000000..8fc52c0 Binary files /dev/null and b/hm_web/static/images/EX1_055.png differ diff --git a/hm_web/static/images/EX1_055o.png b/hm_web/static/images/EX1_055o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_055o.png differ diff --git a/hm_web/static/images/EX1_057.png b/hm_web/static/images/EX1_057.png new file mode 100644 index 0000000..6c55f3e Binary files /dev/null and b/hm_web/static/images/EX1_057.png differ diff --git a/hm_web/static/images/EX1_058.png b/hm_web/static/images/EX1_058.png new file mode 100644 index 0000000..dc54713 Binary files /dev/null and b/hm_web/static/images/EX1_058.png differ diff --git a/hm_web/static/images/EX1_059.png b/hm_web/static/images/EX1_059.png new file mode 100644 index 0000000..d1a7e1b Binary files /dev/null and b/hm_web/static/images/EX1_059.png differ diff --git a/hm_web/static/images/EX1_059e.png b/hm_web/static/images/EX1_059e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_059e.png differ diff --git a/hm_web/static/images/EX1_062.png b/hm_web/static/images/EX1_062.png new file mode 100644 index 0000000..39a6f24 Binary files /dev/null and b/hm_web/static/images/EX1_062.png differ diff --git a/hm_web/static/images/EX1_066.png b/hm_web/static/images/EX1_066.png new file mode 100644 index 0000000..05f9b91 Binary files /dev/null and b/hm_web/static/images/EX1_066.png differ diff --git a/hm_web/static/images/EX1_067.png b/hm_web/static/images/EX1_067.png new file mode 100644 index 0000000..0201d21 Binary files /dev/null and b/hm_web/static/images/EX1_067.png differ diff --git a/hm_web/static/images/EX1_076.png b/hm_web/static/images/EX1_076.png new file mode 100644 index 0000000..0050af1 Binary files /dev/null and b/hm_web/static/images/EX1_076.png differ diff --git a/hm_web/static/images/EX1_080.png b/hm_web/static/images/EX1_080.png new file mode 100644 index 0000000..a769533 Binary files /dev/null and b/hm_web/static/images/EX1_080.png differ diff --git a/hm_web/static/images/EX1_080o.png b/hm_web/static/images/EX1_080o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_080o.png differ diff --git a/hm_web/static/images/EX1_082.png b/hm_web/static/images/EX1_082.png new file mode 100644 index 0000000..ead0dba Binary files /dev/null and b/hm_web/static/images/EX1_082.png differ diff --git a/hm_web/static/images/EX1_083.png b/hm_web/static/images/EX1_083.png new file mode 100644 index 0000000..e062ec5 Binary files /dev/null and b/hm_web/static/images/EX1_083.png differ diff --git a/hm_web/static/images/EX1_084.png b/hm_web/static/images/EX1_084.png new file mode 100644 index 0000000..1a30d67 Binary files /dev/null and b/hm_web/static/images/EX1_084.png differ diff --git a/hm_web/static/images/EX1_084e.png b/hm_web/static/images/EX1_084e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_084e.png differ diff --git a/hm_web/static/images/EX1_085.png b/hm_web/static/images/EX1_085.png new file mode 100644 index 0000000..4435997 Binary files /dev/null and b/hm_web/static/images/EX1_085.png differ diff --git a/hm_web/static/images/EX1_089.png b/hm_web/static/images/EX1_089.png new file mode 100644 index 0000000..4ff4f58 Binary files /dev/null and b/hm_web/static/images/EX1_089.png differ diff --git a/hm_web/static/images/EX1_091.png b/hm_web/static/images/EX1_091.png new file mode 100644 index 0000000..0282d0c Binary files /dev/null and b/hm_web/static/images/EX1_091.png differ diff --git a/hm_web/static/images/EX1_093.png b/hm_web/static/images/EX1_093.png new file mode 100644 index 0000000..3bdbabf Binary files /dev/null and b/hm_web/static/images/EX1_093.png differ diff --git a/hm_web/static/images/EX1_093e.png b/hm_web/static/images/EX1_093e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_093e.png differ diff --git a/hm_web/static/images/EX1_095.png b/hm_web/static/images/EX1_095.png new file mode 100644 index 0000000..86b5ca7 Binary files /dev/null and b/hm_web/static/images/EX1_095.png differ diff --git a/hm_web/static/images/EX1_096.png b/hm_web/static/images/EX1_096.png new file mode 100644 index 0000000..6558f47 Binary files /dev/null and b/hm_web/static/images/EX1_096.png differ diff --git a/hm_web/static/images/EX1_097.png b/hm_web/static/images/EX1_097.png new file mode 100644 index 0000000..8bc1136 Binary files /dev/null and b/hm_web/static/images/EX1_097.png differ diff --git a/hm_web/static/images/EX1_100.png b/hm_web/static/images/EX1_100.png new file mode 100644 index 0000000..c953c3e Binary files /dev/null and b/hm_web/static/images/EX1_100.png differ diff --git a/hm_web/static/images/EX1_102.png b/hm_web/static/images/EX1_102.png new file mode 100644 index 0000000..08413ce Binary files /dev/null and b/hm_web/static/images/EX1_102.png differ diff --git a/hm_web/static/images/EX1_103.png b/hm_web/static/images/EX1_103.png new file mode 100644 index 0000000..f6566fc Binary files /dev/null and b/hm_web/static/images/EX1_103.png differ diff --git a/hm_web/static/images/EX1_103e.png b/hm_web/static/images/EX1_103e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_103e.png differ diff --git a/hm_web/static/images/EX1_105.png b/hm_web/static/images/EX1_105.png new file mode 100644 index 0000000..af94575 Binary files /dev/null and b/hm_web/static/images/EX1_105.png differ diff --git a/hm_web/static/images/EX1_110.png b/hm_web/static/images/EX1_110.png new file mode 100644 index 0000000..d10f7f4 Binary files /dev/null and b/hm_web/static/images/EX1_110.png differ diff --git a/hm_web/static/images/EX1_110t.png b/hm_web/static/images/EX1_110t.png new file mode 100644 index 0000000..8a98cf4 Binary files /dev/null and b/hm_web/static/images/EX1_110t.png differ diff --git a/hm_web/static/images/EX1_112.png b/hm_web/static/images/EX1_112.png new file mode 100644 index 0000000..64c6781 Binary files /dev/null and b/hm_web/static/images/EX1_112.png differ diff --git a/hm_web/static/images/EX1_116.png b/hm_web/static/images/EX1_116.png new file mode 100644 index 0000000..fb2902c Binary files /dev/null and b/hm_web/static/images/EX1_116.png differ diff --git a/hm_web/static/images/EX1_116t.png b/hm_web/static/images/EX1_116t.png new file mode 100644 index 0000000..7bb107f Binary files /dev/null and b/hm_web/static/images/EX1_116t.png differ diff --git a/hm_web/static/images/EX1_124.png b/hm_web/static/images/EX1_124.png new file mode 100644 index 0000000..7be4b08 Binary files /dev/null and b/hm_web/static/images/EX1_124.png differ diff --git a/hm_web/static/images/EX1_126.png b/hm_web/static/images/EX1_126.png new file mode 100644 index 0000000..44850ce Binary files /dev/null and b/hm_web/static/images/EX1_126.png differ diff --git a/hm_web/static/images/EX1_128.png b/hm_web/static/images/EX1_128.png new file mode 100644 index 0000000..f147ff7 Binary files /dev/null and b/hm_web/static/images/EX1_128.png differ diff --git a/hm_web/static/images/EX1_128e.png b/hm_web/static/images/EX1_128e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_128e.png differ diff --git a/hm_web/static/images/EX1_129.png b/hm_web/static/images/EX1_129.png new file mode 100644 index 0000000..f3b9a38 Binary files /dev/null and b/hm_web/static/images/EX1_129.png differ diff --git a/hm_web/static/images/EX1_130.png b/hm_web/static/images/EX1_130.png new file mode 100644 index 0000000..c61de8e Binary files /dev/null and b/hm_web/static/images/EX1_130.png differ diff --git a/hm_web/static/images/EX1_130a.png b/hm_web/static/images/EX1_130a.png new file mode 100644 index 0000000..b16c992 Binary files /dev/null and b/hm_web/static/images/EX1_130a.png differ diff --git a/hm_web/static/images/EX1_131.png b/hm_web/static/images/EX1_131.png new file mode 100644 index 0000000..a7f114c Binary files /dev/null and b/hm_web/static/images/EX1_131.png differ diff --git a/hm_web/static/images/EX1_131t.png b/hm_web/static/images/EX1_131t.png new file mode 100644 index 0000000..a8d532d Binary files /dev/null and b/hm_web/static/images/EX1_131t.png differ diff --git a/hm_web/static/images/EX1_132.png b/hm_web/static/images/EX1_132.png new file mode 100644 index 0000000..b8a28d6 Binary files /dev/null and b/hm_web/static/images/EX1_132.png differ diff --git a/hm_web/static/images/EX1_133.png b/hm_web/static/images/EX1_133.png new file mode 100644 index 0000000..0dd262b Binary files /dev/null and b/hm_web/static/images/EX1_133.png differ diff --git a/hm_web/static/images/EX1_134.png b/hm_web/static/images/EX1_134.png new file mode 100644 index 0000000..a9bdfe2 Binary files /dev/null and b/hm_web/static/images/EX1_134.png differ diff --git a/hm_web/static/images/EX1_136.png b/hm_web/static/images/EX1_136.png new file mode 100644 index 0000000..c27e0bf Binary files /dev/null and b/hm_web/static/images/EX1_136.png differ diff --git a/hm_web/static/images/EX1_137.png b/hm_web/static/images/EX1_137.png new file mode 100644 index 0000000..3d79e4a Binary files /dev/null and b/hm_web/static/images/EX1_137.png differ diff --git a/hm_web/static/images/EX1_144.png b/hm_web/static/images/EX1_144.png new file mode 100644 index 0000000..5ec382c Binary files /dev/null and b/hm_web/static/images/EX1_144.png differ diff --git a/hm_web/static/images/EX1_145.png b/hm_web/static/images/EX1_145.png new file mode 100644 index 0000000..a04b6fd Binary files /dev/null and b/hm_web/static/images/EX1_145.png differ diff --git a/hm_web/static/images/EX1_145o.png b/hm_web/static/images/EX1_145o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_145o.png differ diff --git a/hm_web/static/images/EX1_154.png b/hm_web/static/images/EX1_154.png new file mode 100644 index 0000000..2c4aea7 Binary files /dev/null and b/hm_web/static/images/EX1_154.png differ diff --git a/hm_web/static/images/EX1_154a.png b/hm_web/static/images/EX1_154a.png new file mode 100644 index 0000000..e7400ec Binary files /dev/null and b/hm_web/static/images/EX1_154a.png differ diff --git a/hm_web/static/images/EX1_154b.png b/hm_web/static/images/EX1_154b.png new file mode 100644 index 0000000..2a44512 Binary files /dev/null and b/hm_web/static/images/EX1_154b.png differ diff --git a/hm_web/static/images/EX1_155.png b/hm_web/static/images/EX1_155.png new file mode 100644 index 0000000..7ab8e71 Binary files /dev/null and b/hm_web/static/images/EX1_155.png differ diff --git a/hm_web/static/images/EX1_155a.png b/hm_web/static/images/EX1_155a.png new file mode 100644 index 0000000..820e08b Binary files /dev/null and b/hm_web/static/images/EX1_155a.png differ diff --git a/hm_web/static/images/EX1_155ae.png b/hm_web/static/images/EX1_155ae.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_155ae.png differ diff --git a/hm_web/static/images/EX1_155b.png b/hm_web/static/images/EX1_155b.png new file mode 100644 index 0000000..f39b335 Binary files /dev/null and b/hm_web/static/images/EX1_155b.png differ diff --git a/hm_web/static/images/EX1_155be.png b/hm_web/static/images/EX1_155be.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_155be.png differ diff --git a/hm_web/static/images/EX1_158.png b/hm_web/static/images/EX1_158.png new file mode 100644 index 0000000..4d585d8 Binary files /dev/null and b/hm_web/static/images/EX1_158.png differ diff --git a/hm_web/static/images/EX1_158e.png b/hm_web/static/images/EX1_158e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_158e.png differ diff --git a/hm_web/static/images/EX1_158t.png b/hm_web/static/images/EX1_158t.png new file mode 100644 index 0000000..a13c865 Binary files /dev/null and b/hm_web/static/images/EX1_158t.png differ diff --git a/hm_web/static/images/EX1_160.png b/hm_web/static/images/EX1_160.png new file mode 100644 index 0000000..348501c Binary files /dev/null and b/hm_web/static/images/EX1_160.png differ diff --git a/hm_web/static/images/EX1_160a.png b/hm_web/static/images/EX1_160a.png new file mode 100644 index 0000000..5e922d8 Binary files /dev/null and b/hm_web/static/images/EX1_160a.png differ diff --git a/hm_web/static/images/EX1_160b.png b/hm_web/static/images/EX1_160b.png new file mode 100644 index 0000000..9c35ecc Binary files /dev/null and b/hm_web/static/images/EX1_160b.png differ diff --git a/hm_web/static/images/EX1_160be.png b/hm_web/static/images/EX1_160be.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_160be.png differ diff --git a/hm_web/static/images/EX1_160t.png b/hm_web/static/images/EX1_160t.png new file mode 100644 index 0000000..b359c01 Binary files /dev/null and b/hm_web/static/images/EX1_160t.png differ diff --git a/hm_web/static/images/EX1_161.png b/hm_web/static/images/EX1_161.png new file mode 100644 index 0000000..65ad7e2 Binary files /dev/null and b/hm_web/static/images/EX1_161.png differ diff --git a/hm_web/static/images/EX1_162.png b/hm_web/static/images/EX1_162.png new file mode 100644 index 0000000..4a97a16 Binary files /dev/null and b/hm_web/static/images/EX1_162.png differ diff --git a/hm_web/static/images/EX1_162o.png b/hm_web/static/images/EX1_162o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_162o.png differ diff --git a/hm_web/static/images/EX1_164.png b/hm_web/static/images/EX1_164.png new file mode 100644 index 0000000..66a4940 Binary files /dev/null and b/hm_web/static/images/EX1_164.png differ diff --git a/hm_web/static/images/EX1_164a.png b/hm_web/static/images/EX1_164a.png new file mode 100644 index 0000000..3f35d26 Binary files /dev/null and b/hm_web/static/images/EX1_164a.png differ diff --git a/hm_web/static/images/EX1_164b.png b/hm_web/static/images/EX1_164b.png new file mode 100644 index 0000000..add9803 Binary files /dev/null and b/hm_web/static/images/EX1_164b.png differ diff --git a/hm_web/static/images/EX1_165.png b/hm_web/static/images/EX1_165.png new file mode 100644 index 0000000..8c1396c Binary files /dev/null and b/hm_web/static/images/EX1_165.png differ diff --git a/hm_web/static/images/EX1_165a.png b/hm_web/static/images/EX1_165a.png new file mode 100644 index 0000000..9bd96e5 Binary files /dev/null and b/hm_web/static/images/EX1_165a.png differ diff --git a/hm_web/static/images/EX1_165b.png b/hm_web/static/images/EX1_165b.png new file mode 100644 index 0000000..853f1df Binary files /dev/null and b/hm_web/static/images/EX1_165b.png differ diff --git a/hm_web/static/images/EX1_165t1.png b/hm_web/static/images/EX1_165t1.png new file mode 100644 index 0000000..334b3a2 Binary files /dev/null and b/hm_web/static/images/EX1_165t1.png differ diff --git a/hm_web/static/images/EX1_165t2.png b/hm_web/static/images/EX1_165t2.png new file mode 100644 index 0000000..502b3b5 Binary files /dev/null and b/hm_web/static/images/EX1_165t2.png differ diff --git a/hm_web/static/images/EX1_166.png b/hm_web/static/images/EX1_166.png new file mode 100644 index 0000000..c2fc218 Binary files /dev/null and b/hm_web/static/images/EX1_166.png differ diff --git a/hm_web/static/images/EX1_166a.png b/hm_web/static/images/EX1_166a.png new file mode 100644 index 0000000..5759787 Binary files /dev/null and b/hm_web/static/images/EX1_166a.png differ diff --git a/hm_web/static/images/EX1_166b.png b/hm_web/static/images/EX1_166b.png new file mode 100644 index 0000000..d64eb06 Binary files /dev/null and b/hm_web/static/images/EX1_166b.png differ diff --git a/hm_web/static/images/EX1_169.png b/hm_web/static/images/EX1_169.png new file mode 100644 index 0000000..97b98aa Binary files /dev/null and b/hm_web/static/images/EX1_169.png differ diff --git a/hm_web/static/images/EX1_170.png b/hm_web/static/images/EX1_170.png new file mode 100644 index 0000000..c272119 Binary files /dev/null and b/hm_web/static/images/EX1_170.png differ diff --git a/hm_web/static/images/EX1_173.png b/hm_web/static/images/EX1_173.png new file mode 100644 index 0000000..900019b Binary files /dev/null and b/hm_web/static/images/EX1_173.png differ diff --git a/hm_web/static/images/EX1_178.png b/hm_web/static/images/EX1_178.png new file mode 100644 index 0000000..b7a293d Binary files /dev/null and b/hm_web/static/images/EX1_178.png differ diff --git a/hm_web/static/images/EX1_178a.png b/hm_web/static/images/EX1_178a.png new file mode 100644 index 0000000..fe98f25 Binary files /dev/null and b/hm_web/static/images/EX1_178a.png differ diff --git a/hm_web/static/images/EX1_178ae.png b/hm_web/static/images/EX1_178ae.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_178ae.png differ diff --git a/hm_web/static/images/EX1_178b.png b/hm_web/static/images/EX1_178b.png new file mode 100644 index 0000000..432069e Binary files /dev/null and b/hm_web/static/images/EX1_178b.png differ diff --git a/hm_web/static/images/EX1_178be.png b/hm_web/static/images/EX1_178be.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_178be.png differ diff --git a/hm_web/static/images/EX1_238.png b/hm_web/static/images/EX1_238.png new file mode 100644 index 0000000..ea0856e Binary files /dev/null and b/hm_web/static/images/EX1_238.png differ diff --git a/hm_web/static/images/EX1_241.png b/hm_web/static/images/EX1_241.png new file mode 100644 index 0000000..2dde103 Binary files /dev/null and b/hm_web/static/images/EX1_241.png differ diff --git a/hm_web/static/images/EX1_243.png b/hm_web/static/images/EX1_243.png new file mode 100644 index 0000000..10cff01 Binary files /dev/null and b/hm_web/static/images/EX1_243.png differ diff --git a/hm_web/static/images/EX1_244.png b/hm_web/static/images/EX1_244.png new file mode 100644 index 0000000..75dd3d8 Binary files /dev/null and b/hm_web/static/images/EX1_244.png differ diff --git a/hm_web/static/images/EX1_244e.png b/hm_web/static/images/EX1_244e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_244e.png differ diff --git a/hm_web/static/images/EX1_245.png b/hm_web/static/images/EX1_245.png new file mode 100644 index 0000000..ab325ec Binary files /dev/null and b/hm_web/static/images/EX1_245.png differ diff --git a/hm_web/static/images/EX1_246.png b/hm_web/static/images/EX1_246.png new file mode 100644 index 0000000..09f5df6 Binary files /dev/null and b/hm_web/static/images/EX1_246.png differ diff --git a/hm_web/static/images/EX1_246e.png b/hm_web/static/images/EX1_246e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_246e.png differ diff --git a/hm_web/static/images/EX1_247.png b/hm_web/static/images/EX1_247.png new file mode 100644 index 0000000..e0ee3f3 Binary files /dev/null and b/hm_web/static/images/EX1_247.png differ diff --git a/hm_web/static/images/EX1_248.png b/hm_web/static/images/EX1_248.png new file mode 100644 index 0000000..ef3ad08 Binary files /dev/null and b/hm_web/static/images/EX1_248.png differ diff --git a/hm_web/static/images/EX1_249.png b/hm_web/static/images/EX1_249.png new file mode 100644 index 0000000..30304e7 Binary files /dev/null and b/hm_web/static/images/EX1_249.png differ diff --git a/hm_web/static/images/EX1_250.png b/hm_web/static/images/EX1_250.png new file mode 100644 index 0000000..926dd31 Binary files /dev/null and b/hm_web/static/images/EX1_250.png differ diff --git a/hm_web/static/images/EX1_251.png b/hm_web/static/images/EX1_251.png new file mode 100644 index 0000000..1fee52a Binary files /dev/null and b/hm_web/static/images/EX1_251.png differ diff --git a/hm_web/static/images/EX1_258.png b/hm_web/static/images/EX1_258.png new file mode 100644 index 0000000..13775dc Binary files /dev/null and b/hm_web/static/images/EX1_258.png differ diff --git a/hm_web/static/images/EX1_258e.png b/hm_web/static/images/EX1_258e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_258e.png differ diff --git a/hm_web/static/images/EX1_259.png b/hm_web/static/images/EX1_259.png new file mode 100644 index 0000000..81b71ab Binary files /dev/null and b/hm_web/static/images/EX1_259.png differ diff --git a/hm_web/static/images/EX1_274.png b/hm_web/static/images/EX1_274.png new file mode 100644 index 0000000..fb3caef Binary files /dev/null and b/hm_web/static/images/EX1_274.png differ diff --git a/hm_web/static/images/EX1_274e.png b/hm_web/static/images/EX1_274e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_274e.png differ diff --git a/hm_web/static/images/EX1_275.png b/hm_web/static/images/EX1_275.png new file mode 100644 index 0000000..cd64881 Binary files /dev/null and b/hm_web/static/images/EX1_275.png differ diff --git a/hm_web/static/images/EX1_277.png b/hm_web/static/images/EX1_277.png new file mode 100644 index 0000000..10dcaad Binary files /dev/null and b/hm_web/static/images/EX1_277.png differ diff --git a/hm_web/static/images/EX1_278.png b/hm_web/static/images/EX1_278.png new file mode 100644 index 0000000..bff657d Binary files /dev/null and b/hm_web/static/images/EX1_278.png differ diff --git a/hm_web/static/images/EX1_279.png b/hm_web/static/images/EX1_279.png new file mode 100644 index 0000000..09d9ceb Binary files /dev/null and b/hm_web/static/images/EX1_279.png differ diff --git a/hm_web/static/images/EX1_283.png b/hm_web/static/images/EX1_283.png new file mode 100644 index 0000000..cb47322 Binary files /dev/null and b/hm_web/static/images/EX1_283.png differ diff --git a/hm_web/static/images/EX1_284.png b/hm_web/static/images/EX1_284.png new file mode 100644 index 0000000..a652daa Binary files /dev/null and b/hm_web/static/images/EX1_284.png differ diff --git a/hm_web/static/images/EX1_287.png b/hm_web/static/images/EX1_287.png new file mode 100644 index 0000000..8200ad3 Binary files /dev/null and b/hm_web/static/images/EX1_287.png differ diff --git a/hm_web/static/images/EX1_289.png b/hm_web/static/images/EX1_289.png new file mode 100644 index 0000000..ad258e8 Binary files /dev/null and b/hm_web/static/images/EX1_289.png differ diff --git a/hm_web/static/images/EX1_294.png b/hm_web/static/images/EX1_294.png new file mode 100644 index 0000000..b1ecf42 Binary files /dev/null and b/hm_web/static/images/EX1_294.png differ diff --git a/hm_web/static/images/EX1_295.png b/hm_web/static/images/EX1_295.png new file mode 100644 index 0000000..2bad55a Binary files /dev/null and b/hm_web/static/images/EX1_295.png differ diff --git a/hm_web/static/images/EX1_295o.png b/hm_web/static/images/EX1_295o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_295o.png differ diff --git a/hm_web/static/images/EX1_298.png b/hm_web/static/images/EX1_298.png new file mode 100644 index 0000000..42c189b Binary files /dev/null and b/hm_web/static/images/EX1_298.png differ diff --git a/hm_web/static/images/EX1_301.png b/hm_web/static/images/EX1_301.png new file mode 100644 index 0000000..3d5194a Binary files /dev/null and b/hm_web/static/images/EX1_301.png differ diff --git a/hm_web/static/images/EX1_302.png b/hm_web/static/images/EX1_302.png new file mode 100644 index 0000000..63dc143 Binary files /dev/null and b/hm_web/static/images/EX1_302.png differ diff --git a/hm_web/static/images/EX1_303.png b/hm_web/static/images/EX1_303.png new file mode 100644 index 0000000..54c2939 Binary files /dev/null and b/hm_web/static/images/EX1_303.png differ diff --git a/hm_web/static/images/EX1_304.png b/hm_web/static/images/EX1_304.png new file mode 100644 index 0000000..de3245d Binary files /dev/null and b/hm_web/static/images/EX1_304.png differ diff --git a/hm_web/static/images/EX1_304e.png b/hm_web/static/images/EX1_304e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_304e.png differ diff --git a/hm_web/static/images/EX1_306.png b/hm_web/static/images/EX1_306.png new file mode 100644 index 0000000..e1ba69c Binary files /dev/null and b/hm_web/static/images/EX1_306.png differ diff --git a/hm_web/static/images/EX1_308.png b/hm_web/static/images/EX1_308.png new file mode 100644 index 0000000..4a6b02f Binary files /dev/null and b/hm_web/static/images/EX1_308.png differ diff --git a/hm_web/static/images/EX1_309.png b/hm_web/static/images/EX1_309.png new file mode 100644 index 0000000..b778055 Binary files /dev/null and b/hm_web/static/images/EX1_309.png differ diff --git a/hm_web/static/images/EX1_310.png b/hm_web/static/images/EX1_310.png new file mode 100644 index 0000000..26d254f Binary files /dev/null and b/hm_web/static/images/EX1_310.png differ diff --git a/hm_web/static/images/EX1_312.png b/hm_web/static/images/EX1_312.png new file mode 100644 index 0000000..770f212 Binary files /dev/null and b/hm_web/static/images/EX1_312.png differ diff --git a/hm_web/static/images/EX1_313.png b/hm_web/static/images/EX1_313.png new file mode 100644 index 0000000..fc715a9 Binary files /dev/null and b/hm_web/static/images/EX1_313.png differ diff --git a/hm_web/static/images/EX1_315.png b/hm_web/static/images/EX1_315.png new file mode 100644 index 0000000..ae5ec3c Binary files /dev/null and b/hm_web/static/images/EX1_315.png differ diff --git a/hm_web/static/images/EX1_316.png b/hm_web/static/images/EX1_316.png new file mode 100644 index 0000000..9c70555 Binary files /dev/null and b/hm_web/static/images/EX1_316.png differ diff --git a/hm_web/static/images/EX1_316e.png b/hm_web/static/images/EX1_316e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_316e.png differ diff --git a/hm_web/static/images/EX1_317.png b/hm_web/static/images/EX1_317.png new file mode 100644 index 0000000..5f62037 Binary files /dev/null and b/hm_web/static/images/EX1_317.png differ diff --git a/hm_web/static/images/EX1_317t.png b/hm_web/static/images/EX1_317t.png new file mode 100644 index 0000000..423730f Binary files /dev/null and b/hm_web/static/images/EX1_317t.png differ diff --git a/hm_web/static/images/EX1_319.png b/hm_web/static/images/EX1_319.png new file mode 100644 index 0000000..9ee23b5 Binary files /dev/null and b/hm_web/static/images/EX1_319.png differ diff --git a/hm_web/static/images/EX1_320.png b/hm_web/static/images/EX1_320.png new file mode 100644 index 0000000..afccef5 Binary files /dev/null and b/hm_web/static/images/EX1_320.png differ diff --git a/hm_web/static/images/EX1_323.png b/hm_web/static/images/EX1_323.png new file mode 100644 index 0000000..e2f8273 Binary files /dev/null and b/hm_web/static/images/EX1_323.png differ diff --git a/hm_web/static/images/EX1_323h.png b/hm_web/static/images/EX1_323h.png new file mode 100644 index 0000000..afd6224 Binary files /dev/null and b/hm_web/static/images/EX1_323h.png differ diff --git a/hm_web/static/images/EX1_323w.png b/hm_web/static/images/EX1_323w.png new file mode 100644 index 0000000..542956c Binary files /dev/null and b/hm_web/static/images/EX1_323w.png differ diff --git a/hm_web/static/images/EX1_332.png b/hm_web/static/images/EX1_332.png new file mode 100644 index 0000000..dac177f Binary files /dev/null and b/hm_web/static/images/EX1_332.png differ diff --git a/hm_web/static/images/EX1_334.png b/hm_web/static/images/EX1_334.png new file mode 100644 index 0000000..17758c9 Binary files /dev/null and b/hm_web/static/images/EX1_334.png differ diff --git a/hm_web/static/images/EX1_334e.png b/hm_web/static/images/EX1_334e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_334e.png differ diff --git a/hm_web/static/images/EX1_335.png b/hm_web/static/images/EX1_335.png new file mode 100644 index 0000000..3587e91 Binary files /dev/null and b/hm_web/static/images/EX1_335.png differ diff --git a/hm_web/static/images/EX1_339.png b/hm_web/static/images/EX1_339.png new file mode 100644 index 0000000..85c9bb6 Binary files /dev/null and b/hm_web/static/images/EX1_339.png differ diff --git a/hm_web/static/images/EX1_341.png b/hm_web/static/images/EX1_341.png new file mode 100644 index 0000000..e4c8e6f Binary files /dev/null and b/hm_web/static/images/EX1_341.png differ diff --git a/hm_web/static/images/EX1_345.png b/hm_web/static/images/EX1_345.png new file mode 100644 index 0000000..53aee0f Binary files /dev/null and b/hm_web/static/images/EX1_345.png differ diff --git a/hm_web/static/images/EX1_345t.png b/hm_web/static/images/EX1_345t.png new file mode 100644 index 0000000..4b716da Binary files /dev/null and b/hm_web/static/images/EX1_345t.png differ diff --git a/hm_web/static/images/EX1_349.png b/hm_web/static/images/EX1_349.png new file mode 100644 index 0000000..f209895 Binary files /dev/null and b/hm_web/static/images/EX1_349.png differ diff --git a/hm_web/static/images/EX1_350.png b/hm_web/static/images/EX1_350.png new file mode 100644 index 0000000..abfb3e2 Binary files /dev/null and b/hm_web/static/images/EX1_350.png differ diff --git a/hm_web/static/images/EX1_354.png b/hm_web/static/images/EX1_354.png new file mode 100644 index 0000000..01efd19 Binary files /dev/null and b/hm_web/static/images/EX1_354.png differ diff --git a/hm_web/static/images/EX1_355.png b/hm_web/static/images/EX1_355.png new file mode 100644 index 0000000..9af4150 Binary files /dev/null and b/hm_web/static/images/EX1_355.png differ diff --git a/hm_web/static/images/EX1_355e.png b/hm_web/static/images/EX1_355e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_355e.png differ diff --git a/hm_web/static/images/EX1_360.png b/hm_web/static/images/EX1_360.png new file mode 100644 index 0000000..f712224 Binary files /dev/null and b/hm_web/static/images/EX1_360.png differ diff --git a/hm_web/static/images/EX1_360e.png b/hm_web/static/images/EX1_360e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_360e.png differ diff --git a/hm_web/static/images/EX1_362.png b/hm_web/static/images/EX1_362.png new file mode 100644 index 0000000..853d501 Binary files /dev/null and b/hm_web/static/images/EX1_362.png differ diff --git a/hm_web/static/images/EX1_363.png b/hm_web/static/images/EX1_363.png new file mode 100644 index 0000000..d3bedea Binary files /dev/null and b/hm_web/static/images/EX1_363.png differ diff --git a/hm_web/static/images/EX1_363e.png b/hm_web/static/images/EX1_363e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_363e.png differ diff --git a/hm_web/static/images/EX1_363e2.png b/hm_web/static/images/EX1_363e2.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_363e2.png differ diff --git a/hm_web/static/images/EX1_365.png b/hm_web/static/images/EX1_365.png new file mode 100644 index 0000000..ec39c34 Binary files /dev/null and b/hm_web/static/images/EX1_365.png differ diff --git a/hm_web/static/images/EX1_366.png b/hm_web/static/images/EX1_366.png new file mode 100644 index 0000000..90faa33 Binary files /dev/null and b/hm_web/static/images/EX1_366.png differ diff --git a/hm_web/static/images/EX1_366e.png b/hm_web/static/images/EX1_366e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_366e.png differ diff --git a/hm_web/static/images/EX1_371.png b/hm_web/static/images/EX1_371.png new file mode 100644 index 0000000..1b8147c Binary files /dev/null and b/hm_web/static/images/EX1_371.png differ diff --git a/hm_web/static/images/EX1_379.png b/hm_web/static/images/EX1_379.png new file mode 100644 index 0000000..62e335c Binary files /dev/null and b/hm_web/static/images/EX1_379.png differ diff --git a/hm_web/static/images/EX1_379e.png b/hm_web/static/images/EX1_379e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_379e.png differ diff --git a/hm_web/static/images/EX1_382.png b/hm_web/static/images/EX1_382.png new file mode 100644 index 0000000..2bd393d Binary files /dev/null and b/hm_web/static/images/EX1_382.png differ diff --git a/hm_web/static/images/EX1_382e.png b/hm_web/static/images/EX1_382e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_382e.png differ diff --git a/hm_web/static/images/EX1_383.png b/hm_web/static/images/EX1_383.png new file mode 100644 index 0000000..271ba97 Binary files /dev/null and b/hm_web/static/images/EX1_383.png differ diff --git a/hm_web/static/images/EX1_383t.png b/hm_web/static/images/EX1_383t.png new file mode 100644 index 0000000..f33c310 Binary files /dev/null and b/hm_web/static/images/EX1_383t.png differ diff --git a/hm_web/static/images/EX1_384.png b/hm_web/static/images/EX1_384.png new file mode 100644 index 0000000..32ea0b4 Binary files /dev/null and b/hm_web/static/images/EX1_384.png differ diff --git a/hm_web/static/images/EX1_390.png b/hm_web/static/images/EX1_390.png new file mode 100644 index 0000000..a2506df Binary files /dev/null and b/hm_web/static/images/EX1_390.png differ diff --git a/hm_web/static/images/EX1_390e.png b/hm_web/static/images/EX1_390e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_390e.png differ diff --git a/hm_web/static/images/EX1_391.png b/hm_web/static/images/EX1_391.png new file mode 100644 index 0000000..0bba09e Binary files /dev/null and b/hm_web/static/images/EX1_391.png differ diff --git a/hm_web/static/images/EX1_392.png b/hm_web/static/images/EX1_392.png new file mode 100644 index 0000000..e57bcad Binary files /dev/null and b/hm_web/static/images/EX1_392.png differ diff --git a/hm_web/static/images/EX1_393.png b/hm_web/static/images/EX1_393.png new file mode 100644 index 0000000..84ce28b Binary files /dev/null and b/hm_web/static/images/EX1_393.png differ diff --git a/hm_web/static/images/EX1_393e.png b/hm_web/static/images/EX1_393e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_393e.png differ diff --git a/hm_web/static/images/EX1_396.png b/hm_web/static/images/EX1_396.png new file mode 100644 index 0000000..de48658 Binary files /dev/null and b/hm_web/static/images/EX1_396.png differ diff --git a/hm_web/static/images/EX1_398.png b/hm_web/static/images/EX1_398.png new file mode 100644 index 0000000..88a0ae5 Binary files /dev/null and b/hm_web/static/images/EX1_398.png differ diff --git a/hm_web/static/images/EX1_398t.png b/hm_web/static/images/EX1_398t.png new file mode 100644 index 0000000..ed8b2ac Binary files /dev/null and b/hm_web/static/images/EX1_398t.png differ diff --git a/hm_web/static/images/EX1_399.png b/hm_web/static/images/EX1_399.png new file mode 100644 index 0000000..314c0e3 Binary files /dev/null and b/hm_web/static/images/EX1_399.png differ diff --git a/hm_web/static/images/EX1_399e.png b/hm_web/static/images/EX1_399e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_399e.png differ diff --git a/hm_web/static/images/EX1_400.png b/hm_web/static/images/EX1_400.png new file mode 100644 index 0000000..7f7abc1 Binary files /dev/null and b/hm_web/static/images/EX1_400.png differ diff --git a/hm_web/static/images/EX1_402.png b/hm_web/static/images/EX1_402.png new file mode 100644 index 0000000..50ee794 Binary files /dev/null and b/hm_web/static/images/EX1_402.png differ diff --git a/hm_web/static/images/EX1_405.png b/hm_web/static/images/EX1_405.png new file mode 100644 index 0000000..613efff Binary files /dev/null and b/hm_web/static/images/EX1_405.png differ diff --git a/hm_web/static/images/EX1_407.png b/hm_web/static/images/EX1_407.png new file mode 100644 index 0000000..0c4d6c0 Binary files /dev/null and b/hm_web/static/images/EX1_407.png differ diff --git a/hm_web/static/images/EX1_408.png b/hm_web/static/images/EX1_408.png new file mode 100644 index 0000000..afbd999 Binary files /dev/null and b/hm_web/static/images/EX1_408.png differ diff --git a/hm_web/static/images/EX1_409.png b/hm_web/static/images/EX1_409.png new file mode 100644 index 0000000..3996249 Binary files /dev/null and b/hm_web/static/images/EX1_409.png differ diff --git a/hm_web/static/images/EX1_409e.png b/hm_web/static/images/EX1_409e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_409e.png differ diff --git a/hm_web/static/images/EX1_409t.png b/hm_web/static/images/EX1_409t.png new file mode 100644 index 0000000..c72f79a Binary files /dev/null and b/hm_web/static/images/EX1_409t.png differ diff --git a/hm_web/static/images/EX1_410.png b/hm_web/static/images/EX1_410.png new file mode 100644 index 0000000..987ba50 Binary files /dev/null and b/hm_web/static/images/EX1_410.png differ diff --git a/hm_web/static/images/EX1_411.png b/hm_web/static/images/EX1_411.png new file mode 100644 index 0000000..c1f4907 Binary files /dev/null and b/hm_web/static/images/EX1_411.png differ diff --git a/hm_web/static/images/EX1_411e.png b/hm_web/static/images/EX1_411e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_411e.png differ diff --git a/hm_web/static/images/EX1_411e2.png b/hm_web/static/images/EX1_411e2.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_411e2.png differ diff --git a/hm_web/static/images/EX1_412.png b/hm_web/static/images/EX1_412.png new file mode 100644 index 0000000..f2b2a59 Binary files /dev/null and b/hm_web/static/images/EX1_412.png differ diff --git a/hm_web/static/images/EX1_412e.png b/hm_web/static/images/EX1_412e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_412e.png differ diff --git a/hm_web/static/images/EX1_414.png b/hm_web/static/images/EX1_414.png new file mode 100644 index 0000000..58f7bb4 Binary files /dev/null and b/hm_web/static/images/EX1_414.png differ diff --git a/hm_web/static/images/EX1_414e.png b/hm_web/static/images/EX1_414e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_414e.png differ diff --git a/hm_web/static/images/EX1_506.png b/hm_web/static/images/EX1_506.png new file mode 100644 index 0000000..ce5fe22 Binary files /dev/null and b/hm_web/static/images/EX1_506.png differ diff --git a/hm_web/static/images/EX1_506a.png b/hm_web/static/images/EX1_506a.png new file mode 100644 index 0000000..b4ca849 Binary files /dev/null and b/hm_web/static/images/EX1_506a.png differ diff --git a/hm_web/static/images/EX1_507.png b/hm_web/static/images/EX1_507.png new file mode 100644 index 0000000..b63d827 Binary files /dev/null and b/hm_web/static/images/EX1_507.png differ diff --git a/hm_web/static/images/EX1_507e.png b/hm_web/static/images/EX1_507e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_507e.png differ diff --git a/hm_web/static/images/EX1_508.png b/hm_web/static/images/EX1_508.png new file mode 100644 index 0000000..7417394 Binary files /dev/null and b/hm_web/static/images/EX1_508.png differ diff --git a/hm_web/static/images/EX1_508o.png b/hm_web/static/images/EX1_508o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_508o.png differ diff --git a/hm_web/static/images/EX1_509.png b/hm_web/static/images/EX1_509.png new file mode 100644 index 0000000..afb64c6 Binary files /dev/null and b/hm_web/static/images/EX1_509.png differ diff --git a/hm_web/static/images/EX1_509e.png b/hm_web/static/images/EX1_509e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_509e.png differ diff --git a/hm_web/static/images/EX1_522.png b/hm_web/static/images/EX1_522.png new file mode 100644 index 0000000..9ae839a Binary files /dev/null and b/hm_web/static/images/EX1_522.png differ diff --git a/hm_web/static/images/EX1_531.png b/hm_web/static/images/EX1_531.png new file mode 100644 index 0000000..c8fe84f Binary files /dev/null and b/hm_web/static/images/EX1_531.png differ diff --git a/hm_web/static/images/EX1_531e.png b/hm_web/static/images/EX1_531e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_531e.png differ diff --git a/hm_web/static/images/EX1_533.png b/hm_web/static/images/EX1_533.png new file mode 100644 index 0000000..4f92d7d Binary files /dev/null and b/hm_web/static/images/EX1_533.png differ diff --git a/hm_web/static/images/EX1_534.png b/hm_web/static/images/EX1_534.png new file mode 100644 index 0000000..573f60d Binary files /dev/null and b/hm_web/static/images/EX1_534.png differ diff --git a/hm_web/static/images/EX1_534t.png b/hm_web/static/images/EX1_534t.png new file mode 100644 index 0000000..fe9530f Binary files /dev/null and b/hm_web/static/images/EX1_534t.png differ diff --git a/hm_web/static/images/EX1_536.png b/hm_web/static/images/EX1_536.png new file mode 100644 index 0000000..e7c4514 Binary files /dev/null and b/hm_web/static/images/EX1_536.png differ diff --git a/hm_web/static/images/EX1_536e.png b/hm_web/static/images/EX1_536e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_536e.png differ diff --git a/hm_web/static/images/EX1_537.png b/hm_web/static/images/EX1_537.png new file mode 100644 index 0000000..5c0046d Binary files /dev/null and b/hm_web/static/images/EX1_537.png differ diff --git a/hm_web/static/images/EX1_538.png b/hm_web/static/images/EX1_538.png new file mode 100644 index 0000000..393d838 Binary files /dev/null and b/hm_web/static/images/EX1_538.png differ diff --git a/hm_web/static/images/EX1_538t.png b/hm_web/static/images/EX1_538t.png new file mode 100644 index 0000000..e3cbace Binary files /dev/null and b/hm_web/static/images/EX1_538t.png differ diff --git a/hm_web/static/images/EX1_539.png b/hm_web/static/images/EX1_539.png new file mode 100644 index 0000000..bac9979 Binary files /dev/null and b/hm_web/static/images/EX1_539.png differ diff --git a/hm_web/static/images/EX1_543.png b/hm_web/static/images/EX1_543.png new file mode 100644 index 0000000..c541a76 Binary files /dev/null and b/hm_web/static/images/EX1_543.png differ diff --git a/hm_web/static/images/EX1_544.png b/hm_web/static/images/EX1_544.png new file mode 100644 index 0000000..84d19f4 Binary files /dev/null and b/hm_web/static/images/EX1_544.png differ diff --git a/hm_web/static/images/EX1_549.png b/hm_web/static/images/EX1_549.png new file mode 100644 index 0000000..69bd1f1 Binary files /dev/null and b/hm_web/static/images/EX1_549.png differ diff --git a/hm_web/static/images/EX1_549o.png b/hm_web/static/images/EX1_549o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_549o.png differ diff --git a/hm_web/static/images/EX1_554.png b/hm_web/static/images/EX1_554.png new file mode 100644 index 0000000..10d1db6 Binary files /dev/null and b/hm_web/static/images/EX1_554.png differ diff --git a/hm_web/static/images/EX1_554t.png b/hm_web/static/images/EX1_554t.png new file mode 100644 index 0000000..d37b8bc Binary files /dev/null and b/hm_web/static/images/EX1_554t.png differ diff --git a/hm_web/static/images/EX1_556.png b/hm_web/static/images/EX1_556.png new file mode 100644 index 0000000..ff18611 Binary files /dev/null and b/hm_web/static/images/EX1_556.png differ diff --git a/hm_web/static/images/EX1_557.png b/hm_web/static/images/EX1_557.png new file mode 100644 index 0000000..a38e35f Binary files /dev/null and b/hm_web/static/images/EX1_557.png differ diff --git a/hm_web/static/images/EX1_558.png b/hm_web/static/images/EX1_558.png new file mode 100644 index 0000000..4686ead Binary files /dev/null and b/hm_web/static/images/EX1_558.png differ diff --git a/hm_web/static/images/EX1_559.png b/hm_web/static/images/EX1_559.png new file mode 100644 index 0000000..f29ad6b Binary files /dev/null and b/hm_web/static/images/EX1_559.png differ diff --git a/hm_web/static/images/EX1_560.png b/hm_web/static/images/EX1_560.png new file mode 100644 index 0000000..8e4c56d Binary files /dev/null and b/hm_web/static/images/EX1_560.png differ diff --git a/hm_web/static/images/EX1_561.png b/hm_web/static/images/EX1_561.png new file mode 100644 index 0000000..de72d1c Binary files /dev/null and b/hm_web/static/images/EX1_561.png differ diff --git a/hm_web/static/images/EX1_561e.png b/hm_web/static/images/EX1_561e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_561e.png differ diff --git a/hm_web/static/images/EX1_562.png b/hm_web/static/images/EX1_562.png new file mode 100644 index 0000000..fab5713 Binary files /dev/null and b/hm_web/static/images/EX1_562.png differ diff --git a/hm_web/static/images/EX1_563.png b/hm_web/static/images/EX1_563.png new file mode 100644 index 0000000..2881859 Binary files /dev/null and b/hm_web/static/images/EX1_563.png differ diff --git a/hm_web/static/images/EX1_564.png b/hm_web/static/images/EX1_564.png new file mode 100644 index 0000000..253d371 Binary files /dev/null and b/hm_web/static/images/EX1_564.png differ diff --git a/hm_web/static/images/EX1_565.png b/hm_web/static/images/EX1_565.png new file mode 100644 index 0000000..e80cc89 Binary files /dev/null and b/hm_web/static/images/EX1_565.png differ diff --git a/hm_web/static/images/EX1_565o.png b/hm_web/static/images/EX1_565o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_565o.png differ diff --git a/hm_web/static/images/EX1_567.png b/hm_web/static/images/EX1_567.png new file mode 100644 index 0000000..3cf2787 Binary files /dev/null and b/hm_web/static/images/EX1_567.png differ diff --git a/hm_web/static/images/EX1_570.png b/hm_web/static/images/EX1_570.png new file mode 100644 index 0000000..844fa2a Binary files /dev/null and b/hm_web/static/images/EX1_570.png differ diff --git a/hm_web/static/images/EX1_570e.png b/hm_web/static/images/EX1_570e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_570e.png differ diff --git a/hm_web/static/images/EX1_571.png b/hm_web/static/images/EX1_571.png new file mode 100644 index 0000000..9524727 Binary files /dev/null and b/hm_web/static/images/EX1_571.png differ diff --git a/hm_web/static/images/EX1_572.png b/hm_web/static/images/EX1_572.png new file mode 100644 index 0000000..b419ce9 Binary files /dev/null and b/hm_web/static/images/EX1_572.png differ diff --git a/hm_web/static/images/EX1_573.png b/hm_web/static/images/EX1_573.png new file mode 100644 index 0000000..56a75b2 Binary files /dev/null and b/hm_web/static/images/EX1_573.png differ diff --git a/hm_web/static/images/EX1_573a.png b/hm_web/static/images/EX1_573a.png new file mode 100644 index 0000000..c0d780c Binary files /dev/null and b/hm_web/static/images/EX1_573a.png differ diff --git a/hm_web/static/images/EX1_573ae.png b/hm_web/static/images/EX1_573ae.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_573ae.png differ diff --git a/hm_web/static/images/EX1_573b.png b/hm_web/static/images/EX1_573b.png new file mode 100644 index 0000000..20e8fcf Binary files /dev/null and b/hm_web/static/images/EX1_573b.png differ diff --git a/hm_web/static/images/EX1_573t.png b/hm_web/static/images/EX1_573t.png new file mode 100644 index 0000000..744eed8 Binary files /dev/null and b/hm_web/static/images/EX1_573t.png differ diff --git a/hm_web/static/images/EX1_575.png b/hm_web/static/images/EX1_575.png new file mode 100644 index 0000000..f131248 Binary files /dev/null and b/hm_web/static/images/EX1_575.png differ diff --git a/hm_web/static/images/EX1_577.png b/hm_web/static/images/EX1_577.png new file mode 100644 index 0000000..36f8533 Binary files /dev/null and b/hm_web/static/images/EX1_577.png differ diff --git a/hm_web/static/images/EX1_578.png b/hm_web/static/images/EX1_578.png new file mode 100644 index 0000000..7e82135 Binary files /dev/null and b/hm_web/static/images/EX1_578.png differ diff --git a/hm_web/static/images/EX1_581.png b/hm_web/static/images/EX1_581.png new file mode 100644 index 0000000..f1f72a8 Binary files /dev/null and b/hm_web/static/images/EX1_581.png differ diff --git a/hm_web/static/images/EX1_582.png b/hm_web/static/images/EX1_582.png new file mode 100644 index 0000000..8bd23e0 Binary files /dev/null and b/hm_web/static/images/EX1_582.png differ diff --git a/hm_web/static/images/EX1_583.png b/hm_web/static/images/EX1_583.png new file mode 100644 index 0000000..4ed3d96 Binary files /dev/null and b/hm_web/static/images/EX1_583.png differ diff --git a/hm_web/static/images/EX1_584.png b/hm_web/static/images/EX1_584.png new file mode 100644 index 0000000..e48a390 Binary files /dev/null and b/hm_web/static/images/EX1_584.png differ diff --git a/hm_web/static/images/EX1_584e.png b/hm_web/static/images/EX1_584e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_584e.png differ diff --git a/hm_web/static/images/EX1_586.png b/hm_web/static/images/EX1_586.png new file mode 100644 index 0000000..d6479ad Binary files /dev/null and b/hm_web/static/images/EX1_586.png differ diff --git a/hm_web/static/images/EX1_587.png b/hm_web/static/images/EX1_587.png new file mode 100644 index 0000000..d14bc48 Binary files /dev/null and b/hm_web/static/images/EX1_587.png differ diff --git a/hm_web/static/images/EX1_590.png b/hm_web/static/images/EX1_590.png new file mode 100644 index 0000000..d5ca180 Binary files /dev/null and b/hm_web/static/images/EX1_590.png differ diff --git a/hm_web/static/images/EX1_590e.png b/hm_web/static/images/EX1_590e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_590e.png differ diff --git a/hm_web/static/images/EX1_591.png b/hm_web/static/images/EX1_591.png new file mode 100644 index 0000000..a0593db Binary files /dev/null and b/hm_web/static/images/EX1_591.png differ diff --git a/hm_web/static/images/EX1_593.png b/hm_web/static/images/EX1_593.png new file mode 100644 index 0000000..34602d0 Binary files /dev/null and b/hm_web/static/images/EX1_593.png differ diff --git a/hm_web/static/images/EX1_594.png b/hm_web/static/images/EX1_594.png new file mode 100644 index 0000000..80d6f7e Binary files /dev/null and b/hm_web/static/images/EX1_594.png differ diff --git a/hm_web/static/images/EX1_595.png b/hm_web/static/images/EX1_595.png new file mode 100644 index 0000000..00695b5 Binary files /dev/null and b/hm_web/static/images/EX1_595.png differ diff --git a/hm_web/static/images/EX1_596.png b/hm_web/static/images/EX1_596.png new file mode 100644 index 0000000..71ef30b Binary files /dev/null and b/hm_web/static/images/EX1_596.png differ diff --git a/hm_web/static/images/EX1_596e.png b/hm_web/static/images/EX1_596e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_596e.png differ diff --git a/hm_web/static/images/EX1_597.png b/hm_web/static/images/EX1_597.png new file mode 100644 index 0000000..fff46a6 Binary files /dev/null and b/hm_web/static/images/EX1_597.png differ diff --git a/hm_web/static/images/EX1_598.png b/hm_web/static/images/EX1_598.png new file mode 100644 index 0000000..e5a780d Binary files /dev/null and b/hm_web/static/images/EX1_598.png differ diff --git a/hm_web/static/images/EX1_603.png b/hm_web/static/images/EX1_603.png new file mode 100644 index 0000000..f9512c6 Binary files /dev/null and b/hm_web/static/images/EX1_603.png differ diff --git a/hm_web/static/images/EX1_603e.png b/hm_web/static/images/EX1_603e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_603e.png differ diff --git a/hm_web/static/images/EX1_604.png b/hm_web/static/images/EX1_604.png new file mode 100644 index 0000000..8df87c7 Binary files /dev/null and b/hm_web/static/images/EX1_604.png differ diff --git a/hm_web/static/images/EX1_604o.png b/hm_web/static/images/EX1_604o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_604o.png differ diff --git a/hm_web/static/images/EX1_606.png b/hm_web/static/images/EX1_606.png new file mode 100644 index 0000000..285641b Binary files /dev/null and b/hm_web/static/images/EX1_606.png differ diff --git a/hm_web/static/images/EX1_607.png b/hm_web/static/images/EX1_607.png new file mode 100644 index 0000000..2b81afe Binary files /dev/null and b/hm_web/static/images/EX1_607.png differ diff --git a/hm_web/static/images/EX1_607e.png b/hm_web/static/images/EX1_607e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_607e.png differ diff --git a/hm_web/static/images/EX1_608.png b/hm_web/static/images/EX1_608.png new file mode 100644 index 0000000..e1e5984 Binary files /dev/null and b/hm_web/static/images/EX1_608.png differ diff --git a/hm_web/static/images/EX1_609.png b/hm_web/static/images/EX1_609.png new file mode 100644 index 0000000..62ad7b0 Binary files /dev/null and b/hm_web/static/images/EX1_609.png differ diff --git a/hm_web/static/images/EX1_610.png b/hm_web/static/images/EX1_610.png new file mode 100644 index 0000000..25fab6c Binary files /dev/null and b/hm_web/static/images/EX1_610.png differ diff --git a/hm_web/static/images/EX1_611.png b/hm_web/static/images/EX1_611.png new file mode 100644 index 0000000..1ad2118 Binary files /dev/null and b/hm_web/static/images/EX1_611.png differ diff --git a/hm_web/static/images/EX1_611e.png b/hm_web/static/images/EX1_611e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_611e.png differ diff --git a/hm_web/static/images/EX1_612.png b/hm_web/static/images/EX1_612.png new file mode 100644 index 0000000..26c7156 Binary files /dev/null and b/hm_web/static/images/EX1_612.png differ diff --git a/hm_web/static/images/EX1_612o.png b/hm_web/static/images/EX1_612o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_612o.png differ diff --git a/hm_web/static/images/EX1_613.png b/hm_web/static/images/EX1_613.png new file mode 100644 index 0000000..f36bd87 Binary files /dev/null and b/hm_web/static/images/EX1_613.png differ diff --git a/hm_web/static/images/EX1_613e.png b/hm_web/static/images/EX1_613e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_613e.png differ diff --git a/hm_web/static/images/EX1_614.png b/hm_web/static/images/EX1_614.png new file mode 100644 index 0000000..6e457e6 Binary files /dev/null and b/hm_web/static/images/EX1_614.png differ diff --git a/hm_web/static/images/EX1_614t.png b/hm_web/static/images/EX1_614t.png new file mode 100644 index 0000000..3bc4c0c Binary files /dev/null and b/hm_web/static/images/EX1_614t.png differ diff --git a/hm_web/static/images/EX1_616.png b/hm_web/static/images/EX1_616.png new file mode 100644 index 0000000..ea57af6 Binary files /dev/null and b/hm_web/static/images/EX1_616.png differ diff --git a/hm_web/static/images/EX1_617.png b/hm_web/static/images/EX1_617.png new file mode 100644 index 0000000..fca7a77 Binary files /dev/null and b/hm_web/static/images/EX1_617.png differ diff --git a/hm_web/static/images/EX1_619.png b/hm_web/static/images/EX1_619.png new file mode 100644 index 0000000..8d935ec Binary files /dev/null and b/hm_web/static/images/EX1_619.png differ diff --git a/hm_web/static/images/EX1_619e.png b/hm_web/static/images/EX1_619e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_619e.png differ diff --git a/hm_web/static/images/EX1_620.png b/hm_web/static/images/EX1_620.png new file mode 100644 index 0000000..3b823bb Binary files /dev/null and b/hm_web/static/images/EX1_620.png differ diff --git a/hm_web/static/images/EX1_621.png b/hm_web/static/images/EX1_621.png new file mode 100644 index 0000000..0c94a3e Binary files /dev/null and b/hm_web/static/images/EX1_621.png differ diff --git a/hm_web/static/images/EX1_622.png b/hm_web/static/images/EX1_622.png new file mode 100644 index 0000000..33c01d3 Binary files /dev/null and b/hm_web/static/images/EX1_622.png differ diff --git a/hm_web/static/images/EX1_623.png b/hm_web/static/images/EX1_623.png new file mode 100644 index 0000000..32feee8 Binary files /dev/null and b/hm_web/static/images/EX1_623.png differ diff --git a/hm_web/static/images/EX1_623e.png b/hm_web/static/images/EX1_623e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_623e.png differ diff --git a/hm_web/static/images/EX1_624.png b/hm_web/static/images/EX1_624.png new file mode 100644 index 0000000..67dbc37 Binary files /dev/null and b/hm_web/static/images/EX1_624.png differ diff --git a/hm_web/static/images/EX1_625.png b/hm_web/static/images/EX1_625.png new file mode 100644 index 0000000..2221df6 Binary files /dev/null and b/hm_web/static/images/EX1_625.png differ diff --git a/hm_web/static/images/EX1_625t.png b/hm_web/static/images/EX1_625t.png new file mode 100644 index 0000000..716c0ff Binary files /dev/null and b/hm_web/static/images/EX1_625t.png differ diff --git a/hm_web/static/images/EX1_625t2.png b/hm_web/static/images/EX1_625t2.png new file mode 100644 index 0000000..f414fe3 Binary files /dev/null and b/hm_web/static/images/EX1_625t2.png differ diff --git a/hm_web/static/images/EX1_626.png b/hm_web/static/images/EX1_626.png new file mode 100644 index 0000000..3fb4f4e Binary files /dev/null and b/hm_web/static/images/EX1_626.png differ diff --git a/hm_web/static/images/EX1_finkle.png b/hm_web/static/images/EX1_finkle.png new file mode 100644 index 0000000..7993c66 Binary files /dev/null and b/hm_web/static/images/EX1_finkle.png differ diff --git a/hm_web/static/images/EX1_tk11.png b/hm_web/static/images/EX1_tk11.png new file mode 100644 index 0000000..d088707 Binary files /dev/null and b/hm_web/static/images/EX1_tk11.png differ diff --git a/hm_web/static/images/EX1_tk28.png b/hm_web/static/images/EX1_tk28.png new file mode 100644 index 0000000..61b24c5 Binary files /dev/null and b/hm_web/static/images/EX1_tk28.png differ diff --git a/hm_web/static/images/EX1_tk29.png b/hm_web/static/images/EX1_tk29.png new file mode 100644 index 0000000..3ba71b3 Binary files /dev/null and b/hm_web/static/images/EX1_tk29.png differ diff --git a/hm_web/static/images/EX1_tk31.png b/hm_web/static/images/EX1_tk31.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/EX1_tk31.png differ diff --git a/hm_web/static/images/EX1_tk33.png b/hm_web/static/images/EX1_tk33.png new file mode 100644 index 0000000..53f44f8 Binary files /dev/null and b/hm_web/static/images/EX1_tk33.png differ diff --git a/hm_web/static/images/EX1_tk34.png b/hm_web/static/images/EX1_tk34.png new file mode 100644 index 0000000..a48923c Binary files /dev/null and b/hm_web/static/images/EX1_tk34.png differ diff --git a/hm_web/static/images/EX1_tk9.png b/hm_web/static/images/EX1_tk9.png new file mode 100644 index 0000000..9c2ff2a Binary files /dev/null and b/hm_web/static/images/EX1_tk9.png differ diff --git a/hm_web/static/images/FP1_001.png b/hm_web/static/images/FP1_001.png new file mode 100644 index 0000000..cef9090 Binary files /dev/null and b/hm_web/static/images/FP1_001.png differ diff --git a/hm_web/static/images/FP1_002.png b/hm_web/static/images/FP1_002.png new file mode 100644 index 0000000..0bd0514 Binary files /dev/null and b/hm_web/static/images/FP1_002.png differ diff --git a/hm_web/static/images/FP1_002t.png b/hm_web/static/images/FP1_002t.png new file mode 100644 index 0000000..cd1108e Binary files /dev/null and b/hm_web/static/images/FP1_002t.png differ diff --git a/hm_web/static/images/FP1_003.png b/hm_web/static/images/FP1_003.png new file mode 100644 index 0000000..691ad84 Binary files /dev/null and b/hm_web/static/images/FP1_003.png differ diff --git a/hm_web/static/images/FP1_004.png b/hm_web/static/images/FP1_004.png new file mode 100644 index 0000000..a8251f8 Binary files /dev/null and b/hm_web/static/images/FP1_004.png differ diff --git a/hm_web/static/images/FP1_005.png b/hm_web/static/images/FP1_005.png new file mode 100644 index 0000000..bd6a846 Binary files /dev/null and b/hm_web/static/images/FP1_005.png differ diff --git a/hm_web/static/images/FP1_005e.png b/hm_web/static/images/FP1_005e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/FP1_005e.png differ diff --git a/hm_web/static/images/FP1_006.png b/hm_web/static/images/FP1_006.png new file mode 100644 index 0000000..380483b Binary files /dev/null and b/hm_web/static/images/FP1_006.png differ diff --git a/hm_web/static/images/FP1_007.png b/hm_web/static/images/FP1_007.png new file mode 100644 index 0000000..ef0f7aa Binary files /dev/null and b/hm_web/static/images/FP1_007.png differ diff --git a/hm_web/static/images/FP1_007t.png b/hm_web/static/images/FP1_007t.png new file mode 100644 index 0000000..7da6504 Binary files /dev/null and b/hm_web/static/images/FP1_007t.png differ diff --git a/hm_web/static/images/FP1_008.png b/hm_web/static/images/FP1_008.png new file mode 100644 index 0000000..2559906 Binary files /dev/null and b/hm_web/static/images/FP1_008.png differ diff --git a/hm_web/static/images/FP1_009.png b/hm_web/static/images/FP1_009.png new file mode 100644 index 0000000..a23b92e Binary files /dev/null and b/hm_web/static/images/FP1_009.png differ diff --git a/hm_web/static/images/FP1_010.png b/hm_web/static/images/FP1_010.png new file mode 100644 index 0000000..b485648 Binary files /dev/null and b/hm_web/static/images/FP1_010.png differ diff --git a/hm_web/static/images/FP1_011.png b/hm_web/static/images/FP1_011.png new file mode 100644 index 0000000..c54e918 Binary files /dev/null and b/hm_web/static/images/FP1_011.png differ diff --git a/hm_web/static/images/FP1_012.png b/hm_web/static/images/FP1_012.png new file mode 100644 index 0000000..724f54c Binary files /dev/null and b/hm_web/static/images/FP1_012.png differ diff --git a/hm_web/static/images/FP1_012t.png b/hm_web/static/images/FP1_012t.png new file mode 100644 index 0000000..c72e135 Binary files /dev/null and b/hm_web/static/images/FP1_012t.png differ diff --git a/hm_web/static/images/FP1_013.png b/hm_web/static/images/FP1_013.png new file mode 100644 index 0000000..5dbe847 Binary files /dev/null and b/hm_web/static/images/FP1_013.png differ diff --git a/hm_web/static/images/FP1_014.png b/hm_web/static/images/FP1_014.png new file mode 100644 index 0000000..50852f1 Binary files /dev/null and b/hm_web/static/images/FP1_014.png differ diff --git a/hm_web/static/images/FP1_014t.png b/hm_web/static/images/FP1_014t.png new file mode 100644 index 0000000..6f5c594 Binary files /dev/null and b/hm_web/static/images/FP1_014t.png differ diff --git a/hm_web/static/images/FP1_015.png b/hm_web/static/images/FP1_015.png new file mode 100644 index 0000000..6174b66 Binary files /dev/null and b/hm_web/static/images/FP1_015.png differ diff --git a/hm_web/static/images/FP1_016.png b/hm_web/static/images/FP1_016.png new file mode 100644 index 0000000..f06a783 Binary files /dev/null and b/hm_web/static/images/FP1_016.png differ diff --git a/hm_web/static/images/FP1_017.png b/hm_web/static/images/FP1_017.png new file mode 100644 index 0000000..91b8c33 Binary files /dev/null and b/hm_web/static/images/FP1_017.png differ diff --git a/hm_web/static/images/FP1_018.png b/hm_web/static/images/FP1_018.png new file mode 100644 index 0000000..80816dd Binary files /dev/null and b/hm_web/static/images/FP1_018.png differ diff --git a/hm_web/static/images/FP1_019.png b/hm_web/static/images/FP1_019.png new file mode 100644 index 0000000..869a746 Binary files /dev/null and b/hm_web/static/images/FP1_019.png differ diff --git a/hm_web/static/images/FP1_019t.png b/hm_web/static/images/FP1_019t.png new file mode 100644 index 0000000..f61ed65 Binary files /dev/null and b/hm_web/static/images/FP1_019t.png differ diff --git a/hm_web/static/images/FP1_020.png b/hm_web/static/images/FP1_020.png new file mode 100644 index 0000000..32d2f95 Binary files /dev/null and b/hm_web/static/images/FP1_020.png differ diff --git a/hm_web/static/images/FP1_020e.png b/hm_web/static/images/FP1_020e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/FP1_020e.png differ diff --git a/hm_web/static/images/FP1_021.png b/hm_web/static/images/FP1_021.png new file mode 100644 index 0000000..fb2b2a6 Binary files /dev/null and b/hm_web/static/images/FP1_021.png differ diff --git a/hm_web/static/images/FP1_022.png b/hm_web/static/images/FP1_022.png new file mode 100644 index 0000000..3bbf99d Binary files /dev/null and b/hm_web/static/images/FP1_022.png differ diff --git a/hm_web/static/images/FP1_023.png b/hm_web/static/images/FP1_023.png new file mode 100644 index 0000000..e5028f9 Binary files /dev/null and b/hm_web/static/images/FP1_023.png differ diff --git a/hm_web/static/images/FP1_023e.png b/hm_web/static/images/FP1_023e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/FP1_023e.png differ diff --git a/hm_web/static/images/FP1_024.png b/hm_web/static/images/FP1_024.png new file mode 100644 index 0000000..2384ddb Binary files /dev/null and b/hm_web/static/images/FP1_024.png differ diff --git a/hm_web/static/images/FP1_025.png b/hm_web/static/images/FP1_025.png new file mode 100644 index 0000000..4fbff0e Binary files /dev/null and b/hm_web/static/images/FP1_025.png differ diff --git a/hm_web/static/images/FP1_026.png b/hm_web/static/images/FP1_026.png new file mode 100644 index 0000000..0b2305b Binary files /dev/null and b/hm_web/static/images/FP1_026.png differ diff --git a/hm_web/static/images/FP1_027.png b/hm_web/static/images/FP1_027.png new file mode 100644 index 0000000..638d250 Binary files /dev/null and b/hm_web/static/images/FP1_027.png differ diff --git a/hm_web/static/images/FP1_028.png b/hm_web/static/images/FP1_028.png new file mode 100644 index 0000000..d33f21d Binary files /dev/null and b/hm_web/static/images/FP1_028.png differ diff --git a/hm_web/static/images/FP1_028e.png b/hm_web/static/images/FP1_028e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/FP1_028e.png differ diff --git a/hm_web/static/images/FP1_029.png b/hm_web/static/images/FP1_029.png new file mode 100644 index 0000000..a6328e5 Binary files /dev/null and b/hm_web/static/images/FP1_029.png differ diff --git a/hm_web/static/images/FP1_030.png b/hm_web/static/images/FP1_030.png new file mode 100644 index 0000000..28028fc Binary files /dev/null and b/hm_web/static/images/FP1_030.png differ diff --git a/hm_web/static/images/FP1_030e.png b/hm_web/static/images/FP1_030e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/FP1_030e.png differ diff --git a/hm_web/static/images/FP1_031.png b/hm_web/static/images/FP1_031.png new file mode 100644 index 0000000..b3afc9f Binary files /dev/null and b/hm_web/static/images/FP1_031.png differ diff --git a/hm_web/static/images/GAME_001.png b/hm_web/static/images/GAME_001.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GAME_001.png differ diff --git a/hm_web/static/images/GAME_002.png b/hm_web/static/images/GAME_002.png new file mode 100644 index 0000000..63151d9 Binary files /dev/null and b/hm_web/static/images/GAME_002.png differ diff --git a/hm_web/static/images/GAME_003.png b/hm_web/static/images/GAME_003.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GAME_003.png differ diff --git a/hm_web/static/images/GAME_003e.png b/hm_web/static/images/GAME_003e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GAME_003e.png differ diff --git a/hm_web/static/images/GAME_004.png b/hm_web/static/images/GAME_004.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GAME_004.png differ diff --git a/hm_web/static/images/GAME_005.png b/hm_web/static/images/GAME_005.png new file mode 100644 index 0000000..083f595 Binary files /dev/null and b/hm_web/static/images/GAME_005.png differ diff --git a/hm_web/static/images/GAME_005e.png b/hm_web/static/images/GAME_005e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GAME_005e.png differ diff --git a/hm_web/static/images/GAME_006.png b/hm_web/static/images/GAME_006.png new file mode 100644 index 0000000..dce0421 Binary files /dev/null and b/hm_web/static/images/GAME_006.png differ diff --git a/hm_web/static/images/GVG_001.png b/hm_web/static/images/GVG_001.png new file mode 100644 index 0000000..c3bc9e6 Binary files /dev/null and b/hm_web/static/images/GVG_001.png differ diff --git a/hm_web/static/images/GVG_002.png b/hm_web/static/images/GVG_002.png new file mode 100644 index 0000000..2f1bfde Binary files /dev/null and b/hm_web/static/images/GVG_002.png differ diff --git a/hm_web/static/images/GVG_003.png b/hm_web/static/images/GVG_003.png new file mode 100644 index 0000000..f62c5f6 Binary files /dev/null and b/hm_web/static/images/GVG_003.png differ diff --git a/hm_web/static/images/GVG_004.png b/hm_web/static/images/GVG_004.png new file mode 100644 index 0000000..a2cd7b9 Binary files /dev/null and b/hm_web/static/images/GVG_004.png differ diff --git a/hm_web/static/images/GVG_005.png b/hm_web/static/images/GVG_005.png new file mode 100644 index 0000000..31e3301 Binary files /dev/null and b/hm_web/static/images/GVG_005.png differ diff --git a/hm_web/static/images/GVG_006.png b/hm_web/static/images/GVG_006.png new file mode 100644 index 0000000..e9e767b Binary files /dev/null and b/hm_web/static/images/GVG_006.png differ diff --git a/hm_web/static/images/GVG_007.png b/hm_web/static/images/GVG_007.png new file mode 100644 index 0000000..189503c Binary files /dev/null and b/hm_web/static/images/GVG_007.png differ diff --git a/hm_web/static/images/GVG_008.png b/hm_web/static/images/GVG_008.png new file mode 100644 index 0000000..ad00e5c Binary files /dev/null and b/hm_web/static/images/GVG_008.png differ diff --git a/hm_web/static/images/GVG_009.png b/hm_web/static/images/GVG_009.png new file mode 100644 index 0000000..ee6296a Binary files /dev/null and b/hm_web/static/images/GVG_009.png differ diff --git a/hm_web/static/images/GVG_010.png b/hm_web/static/images/GVG_010.png new file mode 100644 index 0000000..c3baba8 Binary files /dev/null and b/hm_web/static/images/GVG_010.png differ diff --git a/hm_web/static/images/GVG_010b.png b/hm_web/static/images/GVG_010b.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_010b.png differ diff --git a/hm_web/static/images/GVG_011.png b/hm_web/static/images/GVG_011.png new file mode 100644 index 0000000..5ee1251 Binary files /dev/null and b/hm_web/static/images/GVG_011.png differ diff --git a/hm_web/static/images/GVG_011a.png b/hm_web/static/images/GVG_011a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_011a.png differ diff --git a/hm_web/static/images/GVG_012.png b/hm_web/static/images/GVG_012.png new file mode 100644 index 0000000..b3c59ec Binary files /dev/null and b/hm_web/static/images/GVG_012.png differ diff --git a/hm_web/static/images/GVG_013.png b/hm_web/static/images/GVG_013.png new file mode 100644 index 0000000..2ca5dfd Binary files /dev/null and b/hm_web/static/images/GVG_013.png differ diff --git a/hm_web/static/images/GVG_014.png b/hm_web/static/images/GVG_014.png new file mode 100644 index 0000000..0b7fc7b Binary files /dev/null and b/hm_web/static/images/GVG_014.png differ diff --git a/hm_web/static/images/GVG_014a.png b/hm_web/static/images/GVG_014a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_014a.png differ diff --git a/hm_web/static/images/GVG_015.png b/hm_web/static/images/GVG_015.png new file mode 100644 index 0000000..4187cf4 Binary files /dev/null and b/hm_web/static/images/GVG_015.png differ diff --git a/hm_web/static/images/GVG_016.png b/hm_web/static/images/GVG_016.png new file mode 100644 index 0000000..e0fb2fe Binary files /dev/null and b/hm_web/static/images/GVG_016.png differ diff --git a/hm_web/static/images/GVG_017.png b/hm_web/static/images/GVG_017.png new file mode 100644 index 0000000..4946733 Binary files /dev/null and b/hm_web/static/images/GVG_017.png differ diff --git a/hm_web/static/images/GVG_018.png b/hm_web/static/images/GVG_018.png new file mode 100644 index 0000000..e6be846 Binary files /dev/null and b/hm_web/static/images/GVG_018.png differ diff --git a/hm_web/static/images/GVG_019.png b/hm_web/static/images/GVG_019.png new file mode 100644 index 0000000..830ce93 Binary files /dev/null and b/hm_web/static/images/GVG_019.png differ diff --git a/hm_web/static/images/GVG_019e.png b/hm_web/static/images/GVG_019e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_019e.png differ diff --git a/hm_web/static/images/GVG_020.png b/hm_web/static/images/GVG_020.png new file mode 100644 index 0000000..278435c Binary files /dev/null and b/hm_web/static/images/GVG_020.png differ diff --git a/hm_web/static/images/GVG_021.png b/hm_web/static/images/GVG_021.png new file mode 100644 index 0000000..adea6cd Binary files /dev/null and b/hm_web/static/images/GVG_021.png differ diff --git a/hm_web/static/images/GVG_021e.png b/hm_web/static/images/GVG_021e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_021e.png differ diff --git a/hm_web/static/images/GVG_022.png b/hm_web/static/images/GVG_022.png new file mode 100644 index 0000000..630ef54 Binary files /dev/null and b/hm_web/static/images/GVG_022.png differ diff --git a/hm_web/static/images/GVG_022a.png b/hm_web/static/images/GVG_022a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_022a.png differ diff --git a/hm_web/static/images/GVG_022b.png b/hm_web/static/images/GVG_022b.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_022b.png differ diff --git a/hm_web/static/images/GVG_023.png b/hm_web/static/images/GVG_023.png new file mode 100644 index 0000000..373cc24 Binary files /dev/null and b/hm_web/static/images/GVG_023.png differ diff --git a/hm_web/static/images/GVG_023a.png b/hm_web/static/images/GVG_023a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_023a.png differ diff --git a/hm_web/static/images/GVG_024.png b/hm_web/static/images/GVG_024.png new file mode 100644 index 0000000..d315461 Binary files /dev/null and b/hm_web/static/images/GVG_024.png differ diff --git a/hm_web/static/images/GVG_025.png b/hm_web/static/images/GVG_025.png new file mode 100644 index 0000000..027bf41 Binary files /dev/null and b/hm_web/static/images/GVG_025.png differ diff --git a/hm_web/static/images/GVG_026.png b/hm_web/static/images/GVG_026.png new file mode 100644 index 0000000..e425f94 Binary files /dev/null and b/hm_web/static/images/GVG_026.png differ diff --git a/hm_web/static/images/GVG_027.png b/hm_web/static/images/GVG_027.png new file mode 100644 index 0000000..08f7d5c Binary files /dev/null and b/hm_web/static/images/GVG_027.png differ diff --git a/hm_web/static/images/GVG_027e.png b/hm_web/static/images/GVG_027e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_027e.png differ diff --git a/hm_web/static/images/GVG_028.png b/hm_web/static/images/GVG_028.png new file mode 100644 index 0000000..071db92 Binary files /dev/null and b/hm_web/static/images/GVG_028.png differ diff --git a/hm_web/static/images/GVG_028t.png b/hm_web/static/images/GVG_028t.png new file mode 100644 index 0000000..5479f16 Binary files /dev/null and b/hm_web/static/images/GVG_028t.png differ diff --git a/hm_web/static/images/GVG_029.png b/hm_web/static/images/GVG_029.png new file mode 100644 index 0000000..386a1ac Binary files /dev/null and b/hm_web/static/images/GVG_029.png differ diff --git a/hm_web/static/images/GVG_030.png b/hm_web/static/images/GVG_030.png new file mode 100644 index 0000000..e194f28 Binary files /dev/null and b/hm_web/static/images/GVG_030.png differ diff --git a/hm_web/static/images/GVG_030a.png b/hm_web/static/images/GVG_030a.png new file mode 100644 index 0000000..71c4c56 Binary files /dev/null and b/hm_web/static/images/GVG_030a.png differ diff --git a/hm_web/static/images/GVG_030ae.png b/hm_web/static/images/GVG_030ae.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_030ae.png differ diff --git a/hm_web/static/images/GVG_030b.png b/hm_web/static/images/GVG_030b.png new file mode 100644 index 0000000..ed92552 Binary files /dev/null and b/hm_web/static/images/GVG_030b.png differ diff --git a/hm_web/static/images/GVG_030be.png b/hm_web/static/images/GVG_030be.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_030be.png differ diff --git a/hm_web/static/images/GVG_031.png b/hm_web/static/images/GVG_031.png new file mode 100644 index 0000000..0057729 Binary files /dev/null and b/hm_web/static/images/GVG_031.png differ diff --git a/hm_web/static/images/GVG_032.png b/hm_web/static/images/GVG_032.png new file mode 100644 index 0000000..ba3f37f Binary files /dev/null and b/hm_web/static/images/GVG_032.png differ diff --git a/hm_web/static/images/GVG_032a.png b/hm_web/static/images/GVG_032a.png new file mode 100644 index 0000000..b1e33cd Binary files /dev/null and b/hm_web/static/images/GVG_032a.png differ diff --git a/hm_web/static/images/GVG_032b.png b/hm_web/static/images/GVG_032b.png new file mode 100644 index 0000000..3fedf00 Binary files /dev/null and b/hm_web/static/images/GVG_032b.png differ diff --git a/hm_web/static/images/GVG_033.png b/hm_web/static/images/GVG_033.png new file mode 100644 index 0000000..a0923f1 Binary files /dev/null and b/hm_web/static/images/GVG_033.png differ diff --git a/hm_web/static/images/GVG_034.png b/hm_web/static/images/GVG_034.png new file mode 100644 index 0000000..972a578 Binary files /dev/null and b/hm_web/static/images/GVG_034.png differ diff --git a/hm_web/static/images/GVG_035.png b/hm_web/static/images/GVG_035.png new file mode 100644 index 0000000..a9ac78d Binary files /dev/null and b/hm_web/static/images/GVG_035.png differ diff --git a/hm_web/static/images/GVG_036.png b/hm_web/static/images/GVG_036.png new file mode 100644 index 0000000..5ed3e6e Binary files /dev/null and b/hm_web/static/images/GVG_036.png differ diff --git a/hm_web/static/images/GVG_036e.png b/hm_web/static/images/GVG_036e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_036e.png differ diff --git a/hm_web/static/images/GVG_037.png b/hm_web/static/images/GVG_037.png new file mode 100644 index 0000000..73789c5 Binary files /dev/null and b/hm_web/static/images/GVG_037.png differ diff --git a/hm_web/static/images/GVG_038.png b/hm_web/static/images/GVG_038.png new file mode 100644 index 0000000..0d3dbfd Binary files /dev/null and b/hm_web/static/images/GVG_038.png differ diff --git a/hm_web/static/images/GVG_039.png b/hm_web/static/images/GVG_039.png new file mode 100644 index 0000000..277c549 Binary files /dev/null and b/hm_web/static/images/GVG_039.png differ diff --git a/hm_web/static/images/GVG_040.png b/hm_web/static/images/GVG_040.png new file mode 100644 index 0000000..f38097a Binary files /dev/null and b/hm_web/static/images/GVG_040.png differ diff --git a/hm_web/static/images/GVG_041.png b/hm_web/static/images/GVG_041.png new file mode 100644 index 0000000..460213d Binary files /dev/null and b/hm_web/static/images/GVG_041.png differ diff --git a/hm_web/static/images/GVG_041a.png b/hm_web/static/images/GVG_041a.png new file mode 100644 index 0000000..3bbfee6 Binary files /dev/null and b/hm_web/static/images/GVG_041a.png differ diff --git a/hm_web/static/images/GVG_041b.png b/hm_web/static/images/GVG_041b.png new file mode 100644 index 0000000..ca264a4 Binary files /dev/null and b/hm_web/static/images/GVG_041b.png differ diff --git a/hm_web/static/images/GVG_041c.png b/hm_web/static/images/GVG_041c.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_041c.png differ diff --git a/hm_web/static/images/GVG_042.png b/hm_web/static/images/GVG_042.png new file mode 100644 index 0000000..58b542c Binary files /dev/null and b/hm_web/static/images/GVG_042.png differ diff --git a/hm_web/static/images/GVG_043.png b/hm_web/static/images/GVG_043.png new file mode 100644 index 0000000..61f14be Binary files /dev/null and b/hm_web/static/images/GVG_043.png differ diff --git a/hm_web/static/images/GVG_043e.png b/hm_web/static/images/GVG_043e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_043e.png differ diff --git a/hm_web/static/images/GVG_044.png b/hm_web/static/images/GVG_044.png new file mode 100644 index 0000000..b37971f Binary files /dev/null and b/hm_web/static/images/GVG_044.png differ diff --git a/hm_web/static/images/GVG_045.png b/hm_web/static/images/GVG_045.png new file mode 100644 index 0000000..695811c Binary files /dev/null and b/hm_web/static/images/GVG_045.png differ diff --git a/hm_web/static/images/GVG_045t.png b/hm_web/static/images/GVG_045t.png new file mode 100644 index 0000000..dde127b Binary files /dev/null and b/hm_web/static/images/GVG_045t.png differ diff --git a/hm_web/static/images/GVG_046.png b/hm_web/static/images/GVG_046.png new file mode 100644 index 0000000..5590aca Binary files /dev/null and b/hm_web/static/images/GVG_046.png differ diff --git a/hm_web/static/images/GVG_046e.png b/hm_web/static/images/GVG_046e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_046e.png differ diff --git a/hm_web/static/images/GVG_047.png b/hm_web/static/images/GVG_047.png new file mode 100644 index 0000000..0604114 Binary files /dev/null and b/hm_web/static/images/GVG_047.png differ diff --git a/hm_web/static/images/GVG_048.png b/hm_web/static/images/GVG_048.png new file mode 100644 index 0000000..55efaf3 Binary files /dev/null and b/hm_web/static/images/GVG_048.png differ diff --git a/hm_web/static/images/GVG_048e.png b/hm_web/static/images/GVG_048e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_048e.png differ diff --git a/hm_web/static/images/GVG_049.png b/hm_web/static/images/GVG_049.png new file mode 100644 index 0000000..af7448e Binary files /dev/null and b/hm_web/static/images/GVG_049.png differ diff --git a/hm_web/static/images/GVG_049e.png b/hm_web/static/images/GVG_049e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_049e.png differ diff --git a/hm_web/static/images/GVG_050.png b/hm_web/static/images/GVG_050.png new file mode 100644 index 0000000..e708064 Binary files /dev/null and b/hm_web/static/images/GVG_050.png differ diff --git a/hm_web/static/images/GVG_051.png b/hm_web/static/images/GVG_051.png new file mode 100644 index 0000000..7b60fb3 Binary files /dev/null and b/hm_web/static/images/GVG_051.png differ diff --git a/hm_web/static/images/GVG_051e.png b/hm_web/static/images/GVG_051e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_051e.png differ diff --git a/hm_web/static/images/GVG_052.png b/hm_web/static/images/GVG_052.png new file mode 100644 index 0000000..badfcf2 Binary files /dev/null and b/hm_web/static/images/GVG_052.png differ diff --git a/hm_web/static/images/GVG_053.png b/hm_web/static/images/GVG_053.png new file mode 100644 index 0000000..782bae3 Binary files /dev/null and b/hm_web/static/images/GVG_053.png differ diff --git a/hm_web/static/images/GVG_054.png b/hm_web/static/images/GVG_054.png new file mode 100644 index 0000000..f9f41eb Binary files /dev/null and b/hm_web/static/images/GVG_054.png differ diff --git a/hm_web/static/images/GVG_055.png b/hm_web/static/images/GVG_055.png new file mode 100644 index 0000000..3544b8d Binary files /dev/null and b/hm_web/static/images/GVG_055.png differ diff --git a/hm_web/static/images/GVG_055e.png b/hm_web/static/images/GVG_055e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_055e.png differ diff --git a/hm_web/static/images/GVG_056.png b/hm_web/static/images/GVG_056.png new file mode 100644 index 0000000..48d3f80 Binary files /dev/null and b/hm_web/static/images/GVG_056.png differ diff --git a/hm_web/static/images/GVG_056t.png b/hm_web/static/images/GVG_056t.png new file mode 100644 index 0000000..1236497 Binary files /dev/null and b/hm_web/static/images/GVG_056t.png differ diff --git a/hm_web/static/images/GVG_057.png b/hm_web/static/images/GVG_057.png new file mode 100644 index 0000000..83777dd Binary files /dev/null and b/hm_web/static/images/GVG_057.png differ diff --git a/hm_web/static/images/GVG_057a.png b/hm_web/static/images/GVG_057a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_057a.png differ diff --git a/hm_web/static/images/GVG_058.png b/hm_web/static/images/GVG_058.png new file mode 100644 index 0000000..f811744 Binary files /dev/null and b/hm_web/static/images/GVG_058.png differ diff --git a/hm_web/static/images/GVG_059.png b/hm_web/static/images/GVG_059.png new file mode 100644 index 0000000..b57232d Binary files /dev/null and b/hm_web/static/images/GVG_059.png differ diff --git a/hm_web/static/images/GVG_060.png b/hm_web/static/images/GVG_060.png new file mode 100644 index 0000000..e1485f3 Binary files /dev/null and b/hm_web/static/images/GVG_060.png differ diff --git a/hm_web/static/images/GVG_060e.png b/hm_web/static/images/GVG_060e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_060e.png differ diff --git a/hm_web/static/images/GVG_061.png b/hm_web/static/images/GVG_061.png new file mode 100644 index 0000000..0f39136 Binary files /dev/null and b/hm_web/static/images/GVG_061.png differ diff --git a/hm_web/static/images/GVG_062.png b/hm_web/static/images/GVG_062.png new file mode 100644 index 0000000..1242e8f Binary files /dev/null and b/hm_web/static/images/GVG_062.png differ diff --git a/hm_web/static/images/GVG_063.png b/hm_web/static/images/GVG_063.png new file mode 100644 index 0000000..45582ad Binary files /dev/null and b/hm_web/static/images/GVG_063.png differ diff --git a/hm_web/static/images/GVG_063a.png b/hm_web/static/images/GVG_063a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_063a.png differ diff --git a/hm_web/static/images/GVG_064.png b/hm_web/static/images/GVG_064.png new file mode 100644 index 0000000..cf7a87d Binary files /dev/null and b/hm_web/static/images/GVG_064.png differ diff --git a/hm_web/static/images/GVG_065.png b/hm_web/static/images/GVG_065.png new file mode 100644 index 0000000..145572a Binary files /dev/null and b/hm_web/static/images/GVG_065.png differ diff --git a/hm_web/static/images/GVG_066.png b/hm_web/static/images/GVG_066.png new file mode 100644 index 0000000..e700bbf Binary files /dev/null and b/hm_web/static/images/GVG_066.png differ diff --git a/hm_web/static/images/GVG_067.png b/hm_web/static/images/GVG_067.png new file mode 100644 index 0000000..c2054a8 Binary files /dev/null and b/hm_web/static/images/GVG_067.png differ diff --git a/hm_web/static/images/GVG_067a.png b/hm_web/static/images/GVG_067a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_067a.png differ diff --git a/hm_web/static/images/GVG_068.png b/hm_web/static/images/GVG_068.png new file mode 100644 index 0000000..111079c Binary files /dev/null and b/hm_web/static/images/GVG_068.png differ diff --git a/hm_web/static/images/GVG_068a.png b/hm_web/static/images/GVG_068a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_068a.png differ diff --git a/hm_web/static/images/GVG_069.png b/hm_web/static/images/GVG_069.png new file mode 100644 index 0000000..81ab6c1 Binary files /dev/null and b/hm_web/static/images/GVG_069.png differ diff --git a/hm_web/static/images/GVG_069a.png b/hm_web/static/images/GVG_069a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_069a.png differ diff --git a/hm_web/static/images/GVG_070.png b/hm_web/static/images/GVG_070.png new file mode 100644 index 0000000..9e54bfe Binary files /dev/null and b/hm_web/static/images/GVG_070.png differ diff --git a/hm_web/static/images/GVG_071.png b/hm_web/static/images/GVG_071.png new file mode 100644 index 0000000..df4d690 Binary files /dev/null and b/hm_web/static/images/GVG_071.png differ diff --git a/hm_web/static/images/GVG_072.png b/hm_web/static/images/GVG_072.png new file mode 100644 index 0000000..fa70d66 Binary files /dev/null and b/hm_web/static/images/GVG_072.png differ diff --git a/hm_web/static/images/GVG_073.png b/hm_web/static/images/GVG_073.png new file mode 100644 index 0000000..2407fa0 Binary files /dev/null and b/hm_web/static/images/GVG_073.png differ diff --git a/hm_web/static/images/GVG_074.png b/hm_web/static/images/GVG_074.png new file mode 100644 index 0000000..a195be1 Binary files /dev/null and b/hm_web/static/images/GVG_074.png differ diff --git a/hm_web/static/images/GVG_075.png b/hm_web/static/images/GVG_075.png new file mode 100644 index 0000000..f1a41f3 Binary files /dev/null and b/hm_web/static/images/GVG_075.png differ diff --git a/hm_web/static/images/GVG_076.png b/hm_web/static/images/GVG_076.png new file mode 100644 index 0000000..3d7b10a Binary files /dev/null and b/hm_web/static/images/GVG_076.png differ diff --git a/hm_web/static/images/GVG_076a.png b/hm_web/static/images/GVG_076a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_076a.png differ diff --git a/hm_web/static/images/GVG_077.png b/hm_web/static/images/GVG_077.png new file mode 100644 index 0000000..600ea27 Binary files /dev/null and b/hm_web/static/images/GVG_077.png differ diff --git a/hm_web/static/images/GVG_078.png b/hm_web/static/images/GVG_078.png new file mode 100644 index 0000000..82ce248 Binary files /dev/null and b/hm_web/static/images/GVG_078.png differ diff --git a/hm_web/static/images/GVG_079.png b/hm_web/static/images/GVG_079.png new file mode 100644 index 0000000..8a2b844 Binary files /dev/null and b/hm_web/static/images/GVG_079.png differ diff --git a/hm_web/static/images/GVG_080.png b/hm_web/static/images/GVG_080.png new file mode 100644 index 0000000..36a53aa Binary files /dev/null and b/hm_web/static/images/GVG_080.png differ diff --git a/hm_web/static/images/GVG_080t.png b/hm_web/static/images/GVG_080t.png new file mode 100644 index 0000000..1f0368f Binary files /dev/null and b/hm_web/static/images/GVG_080t.png differ diff --git a/hm_web/static/images/GVG_081.png b/hm_web/static/images/GVG_081.png new file mode 100644 index 0000000..2519412 Binary files /dev/null and b/hm_web/static/images/GVG_081.png differ diff --git a/hm_web/static/images/GVG_082.png b/hm_web/static/images/GVG_082.png new file mode 100644 index 0000000..95d29b8 Binary files /dev/null and b/hm_web/static/images/GVG_082.png differ diff --git a/hm_web/static/images/GVG_083.png b/hm_web/static/images/GVG_083.png new file mode 100644 index 0000000..023dc88 Binary files /dev/null and b/hm_web/static/images/GVG_083.png differ diff --git a/hm_web/static/images/GVG_084.png b/hm_web/static/images/GVG_084.png new file mode 100644 index 0000000..3b74684 Binary files /dev/null and b/hm_web/static/images/GVG_084.png differ diff --git a/hm_web/static/images/GVG_085.png b/hm_web/static/images/GVG_085.png new file mode 100644 index 0000000..245155b Binary files /dev/null and b/hm_web/static/images/GVG_085.png differ diff --git a/hm_web/static/images/GVG_086.png b/hm_web/static/images/GVG_086.png new file mode 100644 index 0000000..4a64e09 Binary files /dev/null and b/hm_web/static/images/GVG_086.png differ diff --git a/hm_web/static/images/GVG_086e.png b/hm_web/static/images/GVG_086e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_086e.png differ diff --git a/hm_web/static/images/GVG_087.png b/hm_web/static/images/GVG_087.png new file mode 100644 index 0000000..3bd6ece Binary files /dev/null and b/hm_web/static/images/GVG_087.png differ diff --git a/hm_web/static/images/GVG_088.png b/hm_web/static/images/GVG_088.png new file mode 100644 index 0000000..69cbbce Binary files /dev/null and b/hm_web/static/images/GVG_088.png differ diff --git a/hm_web/static/images/GVG_089.png b/hm_web/static/images/GVG_089.png new file mode 100644 index 0000000..7bf6860 Binary files /dev/null and b/hm_web/static/images/GVG_089.png differ diff --git a/hm_web/static/images/GVG_090.png b/hm_web/static/images/GVG_090.png new file mode 100644 index 0000000..a564175 Binary files /dev/null and b/hm_web/static/images/GVG_090.png differ diff --git a/hm_web/static/images/GVG_091.png b/hm_web/static/images/GVG_091.png new file mode 100644 index 0000000..5bb09ad Binary files /dev/null and b/hm_web/static/images/GVG_091.png differ diff --git a/hm_web/static/images/GVG_092.png b/hm_web/static/images/GVG_092.png new file mode 100644 index 0000000..3e285be Binary files /dev/null and b/hm_web/static/images/GVG_092.png differ diff --git a/hm_web/static/images/GVG_092t.png b/hm_web/static/images/GVG_092t.png new file mode 100644 index 0000000..155a296 Binary files /dev/null and b/hm_web/static/images/GVG_092t.png differ diff --git a/hm_web/static/images/GVG_093.png b/hm_web/static/images/GVG_093.png new file mode 100644 index 0000000..8cbdac3 Binary files /dev/null and b/hm_web/static/images/GVG_093.png differ diff --git a/hm_web/static/images/GVG_094.png b/hm_web/static/images/GVG_094.png new file mode 100644 index 0000000..b5c5c18 Binary files /dev/null and b/hm_web/static/images/GVG_094.png differ diff --git a/hm_web/static/images/GVG_095.png b/hm_web/static/images/GVG_095.png new file mode 100644 index 0000000..04e03cf Binary files /dev/null and b/hm_web/static/images/GVG_095.png differ diff --git a/hm_web/static/images/GVG_096.png b/hm_web/static/images/GVG_096.png new file mode 100644 index 0000000..d42db99 Binary files /dev/null and b/hm_web/static/images/GVG_096.png differ diff --git a/hm_web/static/images/GVG_097.png b/hm_web/static/images/GVG_097.png new file mode 100644 index 0000000..b7f59e8 Binary files /dev/null and b/hm_web/static/images/GVG_097.png differ diff --git a/hm_web/static/images/GVG_098.png b/hm_web/static/images/GVG_098.png new file mode 100644 index 0000000..3fb9ed5 Binary files /dev/null and b/hm_web/static/images/GVG_098.png differ diff --git a/hm_web/static/images/GVG_099.png b/hm_web/static/images/GVG_099.png new file mode 100644 index 0000000..e2b5c36 Binary files /dev/null and b/hm_web/static/images/GVG_099.png differ diff --git a/hm_web/static/images/GVG_100.png b/hm_web/static/images/GVG_100.png new file mode 100644 index 0000000..e672764 Binary files /dev/null and b/hm_web/static/images/GVG_100.png differ diff --git a/hm_web/static/images/GVG_100e.png b/hm_web/static/images/GVG_100e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_100e.png differ diff --git a/hm_web/static/images/GVG_101.png b/hm_web/static/images/GVG_101.png new file mode 100644 index 0000000..5880663 Binary files /dev/null and b/hm_web/static/images/GVG_101.png differ diff --git a/hm_web/static/images/GVG_101e.png b/hm_web/static/images/GVG_101e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_101e.png differ diff --git a/hm_web/static/images/GVG_102.png b/hm_web/static/images/GVG_102.png new file mode 100644 index 0000000..92ee5f9 Binary files /dev/null and b/hm_web/static/images/GVG_102.png differ diff --git a/hm_web/static/images/GVG_102e.png b/hm_web/static/images/GVG_102e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_102e.png differ diff --git a/hm_web/static/images/GVG_103.png b/hm_web/static/images/GVG_103.png new file mode 100644 index 0000000..45ebb65 Binary files /dev/null and b/hm_web/static/images/GVG_103.png differ diff --git a/hm_web/static/images/GVG_104.png b/hm_web/static/images/GVG_104.png new file mode 100644 index 0000000..1a3e684 Binary files /dev/null and b/hm_web/static/images/GVG_104.png differ diff --git a/hm_web/static/images/GVG_104a.png b/hm_web/static/images/GVG_104a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_104a.png differ diff --git a/hm_web/static/images/GVG_105.png b/hm_web/static/images/GVG_105.png new file mode 100644 index 0000000..1d5f403 Binary files /dev/null and b/hm_web/static/images/GVG_105.png differ diff --git a/hm_web/static/images/GVG_106.png b/hm_web/static/images/GVG_106.png new file mode 100644 index 0000000..ccfe6d2 Binary files /dev/null and b/hm_web/static/images/GVG_106.png differ diff --git a/hm_web/static/images/GVG_106e.png b/hm_web/static/images/GVG_106e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_106e.png differ diff --git a/hm_web/static/images/GVG_107.png b/hm_web/static/images/GVG_107.png new file mode 100644 index 0000000..e9cd4c8 Binary files /dev/null and b/hm_web/static/images/GVG_107.png differ diff --git a/hm_web/static/images/GVG_108.png b/hm_web/static/images/GVG_108.png new file mode 100644 index 0000000..2ab087d Binary files /dev/null and b/hm_web/static/images/GVG_108.png differ diff --git a/hm_web/static/images/GVG_109.png b/hm_web/static/images/GVG_109.png new file mode 100644 index 0000000..f847ba9 Binary files /dev/null and b/hm_web/static/images/GVG_109.png differ diff --git a/hm_web/static/images/GVG_110.png b/hm_web/static/images/GVG_110.png new file mode 100644 index 0000000..90efafa Binary files /dev/null and b/hm_web/static/images/GVG_110.png differ diff --git a/hm_web/static/images/GVG_110t.png b/hm_web/static/images/GVG_110t.png new file mode 100644 index 0000000..1f78db6 Binary files /dev/null and b/hm_web/static/images/GVG_110t.png differ diff --git a/hm_web/static/images/GVG_111.png b/hm_web/static/images/GVG_111.png new file mode 100644 index 0000000..c8d3a77 Binary files /dev/null and b/hm_web/static/images/GVG_111.png differ diff --git a/hm_web/static/images/GVG_111t.png b/hm_web/static/images/GVG_111t.png new file mode 100644 index 0000000..90956f6 Binary files /dev/null and b/hm_web/static/images/GVG_111t.png differ diff --git a/hm_web/static/images/GVG_112.png b/hm_web/static/images/GVG_112.png new file mode 100644 index 0000000..d24c3d2 Binary files /dev/null and b/hm_web/static/images/GVG_112.png differ diff --git a/hm_web/static/images/GVG_113.png b/hm_web/static/images/GVG_113.png new file mode 100644 index 0000000..74bf188 Binary files /dev/null and b/hm_web/static/images/GVG_113.png differ diff --git a/hm_web/static/images/GVG_114.png b/hm_web/static/images/GVG_114.png new file mode 100644 index 0000000..0ed515c Binary files /dev/null and b/hm_web/static/images/GVG_114.png differ diff --git a/hm_web/static/images/GVG_115.png b/hm_web/static/images/GVG_115.png new file mode 100644 index 0000000..8d8e514 Binary files /dev/null and b/hm_web/static/images/GVG_115.png differ diff --git a/hm_web/static/images/GVG_116.png b/hm_web/static/images/GVG_116.png new file mode 100644 index 0000000..b479f98 Binary files /dev/null and b/hm_web/static/images/GVG_116.png differ diff --git a/hm_web/static/images/GVG_117.png b/hm_web/static/images/GVG_117.png new file mode 100644 index 0000000..a520af8 Binary files /dev/null and b/hm_web/static/images/GVG_117.png differ diff --git a/hm_web/static/images/GVG_118.png b/hm_web/static/images/GVG_118.png new file mode 100644 index 0000000..c18ad8c Binary files /dev/null and b/hm_web/static/images/GVG_118.png differ diff --git a/hm_web/static/images/GVG_119.png b/hm_web/static/images/GVG_119.png new file mode 100644 index 0000000..8f8dd4e Binary files /dev/null and b/hm_web/static/images/GVG_119.png differ diff --git a/hm_web/static/images/GVG_120.png b/hm_web/static/images/GVG_120.png new file mode 100644 index 0000000..110999b Binary files /dev/null and b/hm_web/static/images/GVG_120.png differ diff --git a/hm_web/static/images/GVG_121.png b/hm_web/static/images/GVG_121.png new file mode 100644 index 0000000..56a3dde Binary files /dev/null and b/hm_web/static/images/GVG_121.png differ diff --git a/hm_web/static/images/GVG_122.png b/hm_web/static/images/GVG_122.png new file mode 100644 index 0000000..ebdda78 Binary files /dev/null and b/hm_web/static/images/GVG_122.png differ diff --git a/hm_web/static/images/GVG_123.png b/hm_web/static/images/GVG_123.png new file mode 100644 index 0000000..d75ed40 Binary files /dev/null and b/hm_web/static/images/GVG_123.png differ diff --git a/hm_web/static/images/GVG_123e.png b/hm_web/static/images/GVG_123e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/GVG_123e.png differ diff --git a/hm_web/static/images/HERO_01.png b/hm_web/static/images/HERO_01.png new file mode 100644 index 0000000..32c2b74 Binary files /dev/null and b/hm_web/static/images/HERO_01.png differ diff --git a/hm_web/static/images/HERO_01a.png b/hm_web/static/images/HERO_01a.png new file mode 100644 index 0000000..6e691aa Binary files /dev/null and b/hm_web/static/images/HERO_01a.png differ diff --git a/hm_web/static/images/HERO_02.png b/hm_web/static/images/HERO_02.png new file mode 100644 index 0000000..7a0958e Binary files /dev/null and b/hm_web/static/images/HERO_02.png differ diff --git a/hm_web/static/images/HERO_03.png b/hm_web/static/images/HERO_03.png new file mode 100644 index 0000000..9b76ed5 Binary files /dev/null and b/hm_web/static/images/HERO_03.png differ diff --git a/hm_web/static/images/HERO_04.png b/hm_web/static/images/HERO_04.png new file mode 100644 index 0000000..b360bc6 Binary files /dev/null and b/hm_web/static/images/HERO_04.png differ diff --git a/hm_web/static/images/HERO_04a.png b/hm_web/static/images/HERO_04a.png new file mode 100644 index 0000000..477b0bb Binary files /dev/null and b/hm_web/static/images/HERO_04a.png differ diff --git a/hm_web/static/images/HERO_05.png b/hm_web/static/images/HERO_05.png new file mode 100644 index 0000000..5794080 Binary files /dev/null and b/hm_web/static/images/HERO_05.png differ diff --git a/hm_web/static/images/HERO_05a.png b/hm_web/static/images/HERO_05a.png new file mode 100644 index 0000000..d12782d Binary files /dev/null and b/hm_web/static/images/HERO_05a.png differ diff --git a/hm_web/static/images/HERO_06.png b/hm_web/static/images/HERO_06.png new file mode 100644 index 0000000..17a30ba Binary files /dev/null and b/hm_web/static/images/HERO_06.png differ diff --git a/hm_web/static/images/HERO_07.png b/hm_web/static/images/HERO_07.png new file mode 100644 index 0000000..49acf69 Binary files /dev/null and b/hm_web/static/images/HERO_07.png differ diff --git a/hm_web/static/images/HERO_08.png b/hm_web/static/images/HERO_08.png new file mode 100644 index 0000000..1319451 Binary files /dev/null and b/hm_web/static/images/HERO_08.png differ diff --git a/hm_web/static/images/HERO_08a.png b/hm_web/static/images/HERO_08a.png new file mode 100644 index 0000000..9402536 Binary files /dev/null and b/hm_web/static/images/HERO_08a.png differ diff --git a/hm_web/static/images/HERO_08b.png b/hm_web/static/images/HERO_08b.png new file mode 100644 index 0000000..cc30ad2 Binary files /dev/null and b/hm_web/static/images/HERO_08b.png differ diff --git a/hm_web/static/images/HERO_09.png b/hm_web/static/images/HERO_09.png new file mode 100644 index 0000000..e8d7ed7 Binary files /dev/null and b/hm_web/static/images/HERO_09.png differ diff --git a/hm_web/static/images/HRW02_1.png b/hm_web/static/images/HRW02_1.png new file mode 100644 index 0000000..2cdd63d Binary files /dev/null and b/hm_web/static/images/HRW02_1.png differ diff --git a/hm_web/static/images/HRW02_1e.png b/hm_web/static/images/HRW02_1e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/HRW02_1e.png differ diff --git a/hm_web/static/images/LOEA01_01.png b/hm_web/static/images/LOEA01_01.png new file mode 100644 index 0000000..d85feb2 Binary files /dev/null and b/hm_web/static/images/LOEA01_01.png differ diff --git a/hm_web/static/images/LOEA01_01h.png b/hm_web/static/images/LOEA01_01h.png new file mode 100644 index 0000000..f95fe13 Binary files /dev/null and b/hm_web/static/images/LOEA01_01h.png differ diff --git a/hm_web/static/images/LOEA01_02.png b/hm_web/static/images/LOEA01_02.png new file mode 100644 index 0000000..d6f18da Binary files /dev/null and b/hm_web/static/images/LOEA01_02.png differ diff --git a/hm_web/static/images/LOEA01_02h.png b/hm_web/static/images/LOEA01_02h.png new file mode 100644 index 0000000..ced3081 Binary files /dev/null and b/hm_web/static/images/LOEA01_02h.png differ diff --git a/hm_web/static/images/LOEA01_11.png b/hm_web/static/images/LOEA01_11.png new file mode 100644 index 0000000..6a2fb2d Binary files /dev/null and b/hm_web/static/images/LOEA01_11.png differ diff --git a/hm_web/static/images/LOEA01_11h.png b/hm_web/static/images/LOEA01_11h.png new file mode 100644 index 0000000..15e8eb4 Binary files /dev/null and b/hm_web/static/images/LOEA01_11h.png differ diff --git a/hm_web/static/images/LOEA01_11he.png b/hm_web/static/images/LOEA01_11he.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA01_11he.png differ diff --git a/hm_web/static/images/LOEA01_12.png b/hm_web/static/images/LOEA01_12.png new file mode 100644 index 0000000..b789899 Binary files /dev/null and b/hm_web/static/images/LOEA01_12.png differ diff --git a/hm_web/static/images/LOEA01_12h.png b/hm_web/static/images/LOEA01_12h.png new file mode 100644 index 0000000..01f1477 Binary files /dev/null and b/hm_web/static/images/LOEA01_12h.png differ diff --git a/hm_web/static/images/LOEA02_01.png b/hm_web/static/images/LOEA02_01.png new file mode 100644 index 0000000..f7482a0 Binary files /dev/null and b/hm_web/static/images/LOEA02_01.png differ diff --git a/hm_web/static/images/LOEA02_01h.png b/hm_web/static/images/LOEA02_01h.png new file mode 100644 index 0000000..c96d605 Binary files /dev/null and b/hm_web/static/images/LOEA02_01h.png differ diff --git a/hm_web/static/images/LOEA02_02.png b/hm_web/static/images/LOEA02_02.png new file mode 100644 index 0000000..b0db51c Binary files /dev/null and b/hm_web/static/images/LOEA02_02.png differ diff --git a/hm_web/static/images/LOEA02_02h.png b/hm_web/static/images/LOEA02_02h.png new file mode 100644 index 0000000..50ec2e6 Binary files /dev/null and b/hm_web/static/images/LOEA02_02h.png differ diff --git a/hm_web/static/images/LOEA02_03.png b/hm_web/static/images/LOEA02_03.png new file mode 100644 index 0000000..82eff55 Binary files /dev/null and b/hm_web/static/images/LOEA02_03.png differ diff --git a/hm_web/static/images/LOEA02_04.png b/hm_web/static/images/LOEA02_04.png new file mode 100644 index 0000000..c955990 Binary files /dev/null and b/hm_web/static/images/LOEA02_04.png differ diff --git a/hm_web/static/images/LOEA02_05.png b/hm_web/static/images/LOEA02_05.png new file mode 100644 index 0000000..0e109ca Binary files /dev/null and b/hm_web/static/images/LOEA02_05.png differ diff --git a/hm_web/static/images/LOEA02_06.png b/hm_web/static/images/LOEA02_06.png new file mode 100644 index 0000000..0906e85 Binary files /dev/null and b/hm_web/static/images/LOEA02_06.png differ diff --git a/hm_web/static/images/LOEA02_10.png b/hm_web/static/images/LOEA02_10.png new file mode 100644 index 0000000..701b562 Binary files /dev/null and b/hm_web/static/images/LOEA02_10.png differ diff --git a/hm_web/static/images/LOEA02_10a.png b/hm_web/static/images/LOEA02_10a.png new file mode 100644 index 0000000..b382031 Binary files /dev/null and b/hm_web/static/images/LOEA02_10a.png differ diff --git a/hm_web/static/images/LOEA02_10c.png b/hm_web/static/images/LOEA02_10c.png new file mode 100644 index 0000000..9014c1f Binary files /dev/null and b/hm_web/static/images/LOEA02_10c.png differ diff --git a/hm_web/static/images/LOEA04_01.png b/hm_web/static/images/LOEA04_01.png new file mode 100644 index 0000000..c7b9ba7 Binary files /dev/null and b/hm_web/static/images/LOEA04_01.png differ diff --git a/hm_web/static/images/LOEA04_01e.png b/hm_web/static/images/LOEA04_01e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA04_01e.png differ diff --git a/hm_web/static/images/LOEA04_01eh.png b/hm_web/static/images/LOEA04_01eh.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA04_01eh.png differ diff --git a/hm_web/static/images/LOEA04_01h.png b/hm_web/static/images/LOEA04_01h.png new file mode 100644 index 0000000..17f7725 Binary files /dev/null and b/hm_web/static/images/LOEA04_01h.png differ diff --git a/hm_web/static/images/LOEA04_02.png b/hm_web/static/images/LOEA04_02.png new file mode 100644 index 0000000..cd6faae Binary files /dev/null and b/hm_web/static/images/LOEA04_02.png differ diff --git a/hm_web/static/images/LOEA04_02h.png b/hm_web/static/images/LOEA04_02h.png new file mode 100644 index 0000000..e870294 Binary files /dev/null and b/hm_web/static/images/LOEA04_02h.png differ diff --git a/hm_web/static/images/LOEA04_06.png b/hm_web/static/images/LOEA04_06.png new file mode 100644 index 0000000..a06af14 Binary files /dev/null and b/hm_web/static/images/LOEA04_06.png differ diff --git a/hm_web/static/images/LOEA04_06a.png b/hm_web/static/images/LOEA04_06a.png new file mode 100644 index 0000000..cc3903f Binary files /dev/null and b/hm_web/static/images/LOEA04_06a.png differ diff --git a/hm_web/static/images/LOEA04_06b.png b/hm_web/static/images/LOEA04_06b.png new file mode 100644 index 0000000..68a7154 Binary files /dev/null and b/hm_web/static/images/LOEA04_06b.png differ diff --git a/hm_web/static/images/LOEA04_13bt.png b/hm_web/static/images/LOEA04_13bt.png new file mode 100644 index 0000000..9782c60 Binary files /dev/null and b/hm_web/static/images/LOEA04_13bt.png differ diff --git a/hm_web/static/images/LOEA04_13bth.png b/hm_web/static/images/LOEA04_13bth.png new file mode 100644 index 0000000..5b35ef1 Binary files /dev/null and b/hm_web/static/images/LOEA04_13bth.png differ diff --git a/hm_web/static/images/LOEA04_23.png b/hm_web/static/images/LOEA04_23.png new file mode 100644 index 0000000..453678f Binary files /dev/null and b/hm_web/static/images/LOEA04_23.png differ diff --git a/hm_web/static/images/LOEA04_23h.png b/hm_web/static/images/LOEA04_23h.png new file mode 100644 index 0000000..8186a31 Binary files /dev/null and b/hm_web/static/images/LOEA04_23h.png differ diff --git a/hm_web/static/images/LOEA04_24.png b/hm_web/static/images/LOEA04_24.png new file mode 100644 index 0000000..5709ac1 Binary files /dev/null and b/hm_web/static/images/LOEA04_24.png differ diff --git a/hm_web/static/images/LOEA04_24h.png b/hm_web/static/images/LOEA04_24h.png new file mode 100644 index 0000000..ed09f57 Binary files /dev/null and b/hm_web/static/images/LOEA04_24h.png differ diff --git a/hm_web/static/images/LOEA04_25.png b/hm_web/static/images/LOEA04_25.png new file mode 100644 index 0000000..04a7c8b Binary files /dev/null and b/hm_web/static/images/LOEA04_25.png differ diff --git a/hm_web/static/images/LOEA04_25h.png b/hm_web/static/images/LOEA04_25h.png new file mode 100644 index 0000000..965f437 Binary files /dev/null and b/hm_web/static/images/LOEA04_25h.png differ diff --git a/hm_web/static/images/LOEA04_27.png b/hm_web/static/images/LOEA04_27.png new file mode 100644 index 0000000..13f07f0 Binary files /dev/null and b/hm_web/static/images/LOEA04_27.png differ diff --git a/hm_web/static/images/LOEA04_28.png b/hm_web/static/images/LOEA04_28.png new file mode 100644 index 0000000..d4e6cd1 Binary files /dev/null and b/hm_web/static/images/LOEA04_28.png differ diff --git a/hm_web/static/images/LOEA04_28a.png b/hm_web/static/images/LOEA04_28a.png new file mode 100644 index 0000000..b7eb02a Binary files /dev/null and b/hm_web/static/images/LOEA04_28a.png differ diff --git a/hm_web/static/images/LOEA04_28b.png b/hm_web/static/images/LOEA04_28b.png new file mode 100644 index 0000000..9662cfb Binary files /dev/null and b/hm_web/static/images/LOEA04_28b.png differ diff --git a/hm_web/static/images/LOEA04_29.png b/hm_web/static/images/LOEA04_29.png new file mode 100644 index 0000000..60d3e65 Binary files /dev/null and b/hm_web/static/images/LOEA04_29.png differ diff --git a/hm_web/static/images/LOEA04_29a.png b/hm_web/static/images/LOEA04_29a.png new file mode 100644 index 0000000..fc8f422 Binary files /dev/null and b/hm_web/static/images/LOEA04_29a.png differ diff --git a/hm_web/static/images/LOEA04_29b.png b/hm_web/static/images/LOEA04_29b.png new file mode 100644 index 0000000..7cd27c4 Binary files /dev/null and b/hm_web/static/images/LOEA04_29b.png differ diff --git a/hm_web/static/images/LOEA04_30.png b/hm_web/static/images/LOEA04_30.png new file mode 100644 index 0000000..9c50bf9 Binary files /dev/null and b/hm_web/static/images/LOEA04_30.png differ diff --git a/hm_web/static/images/LOEA04_30a.png b/hm_web/static/images/LOEA04_30a.png new file mode 100644 index 0000000..6735763 Binary files /dev/null and b/hm_web/static/images/LOEA04_30a.png differ diff --git a/hm_web/static/images/LOEA04_31b.png b/hm_web/static/images/LOEA04_31b.png new file mode 100644 index 0000000..707b5c5 Binary files /dev/null and b/hm_web/static/images/LOEA04_31b.png differ diff --git a/hm_web/static/images/LOEA05_01.png b/hm_web/static/images/LOEA05_01.png new file mode 100644 index 0000000..e2702df Binary files /dev/null and b/hm_web/static/images/LOEA05_01.png differ diff --git a/hm_web/static/images/LOEA05_01h.png b/hm_web/static/images/LOEA05_01h.png new file mode 100644 index 0000000..9f09ce1 Binary files /dev/null and b/hm_web/static/images/LOEA05_01h.png differ diff --git a/hm_web/static/images/LOEA05_02.png b/hm_web/static/images/LOEA05_02.png new file mode 100644 index 0000000..ecd9e4e Binary files /dev/null and b/hm_web/static/images/LOEA05_02.png differ diff --git a/hm_web/static/images/LOEA05_02a.png b/hm_web/static/images/LOEA05_02a.png new file mode 100644 index 0000000..80917ca Binary files /dev/null and b/hm_web/static/images/LOEA05_02a.png differ diff --git a/hm_web/static/images/LOEA05_02h.png b/hm_web/static/images/LOEA05_02h.png new file mode 100644 index 0000000..7fd2366 Binary files /dev/null and b/hm_web/static/images/LOEA05_02h.png differ diff --git a/hm_web/static/images/LOEA05_02ha.png b/hm_web/static/images/LOEA05_02ha.png new file mode 100644 index 0000000..53c1b46 Binary files /dev/null and b/hm_web/static/images/LOEA05_02ha.png differ diff --git a/hm_web/static/images/LOEA05_03.png b/hm_web/static/images/LOEA05_03.png new file mode 100644 index 0000000..e39f58a Binary files /dev/null and b/hm_web/static/images/LOEA05_03.png differ diff --git a/hm_web/static/images/LOEA05_03h.png b/hm_web/static/images/LOEA05_03h.png new file mode 100644 index 0000000..87ff11f Binary files /dev/null and b/hm_web/static/images/LOEA05_03h.png differ diff --git a/hm_web/static/images/LOEA06_02.png b/hm_web/static/images/LOEA06_02.png new file mode 100644 index 0000000..c460161 Binary files /dev/null and b/hm_web/static/images/LOEA06_02.png differ diff --git a/hm_web/static/images/LOEA06_02h.png b/hm_web/static/images/LOEA06_02h.png new file mode 100644 index 0000000..85899a3 Binary files /dev/null and b/hm_web/static/images/LOEA06_02h.png differ diff --git a/hm_web/static/images/LOEA06_02t.png b/hm_web/static/images/LOEA06_02t.png new file mode 100644 index 0000000..647c5c2 Binary files /dev/null and b/hm_web/static/images/LOEA06_02t.png differ diff --git a/hm_web/static/images/LOEA06_02th.png b/hm_web/static/images/LOEA06_02th.png new file mode 100644 index 0000000..18b2b78 Binary files /dev/null and b/hm_web/static/images/LOEA06_02th.png differ diff --git a/hm_web/static/images/LOEA06_03.png b/hm_web/static/images/LOEA06_03.png new file mode 100644 index 0000000..0bf395e Binary files /dev/null and b/hm_web/static/images/LOEA06_03.png differ diff --git a/hm_web/static/images/LOEA06_03e.png b/hm_web/static/images/LOEA06_03e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA06_03e.png differ diff --git a/hm_web/static/images/LOEA06_03eh.png b/hm_web/static/images/LOEA06_03eh.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA06_03eh.png differ diff --git a/hm_web/static/images/LOEA06_03h.png b/hm_web/static/images/LOEA06_03h.png new file mode 100644 index 0000000..1d81928 Binary files /dev/null and b/hm_web/static/images/LOEA06_03h.png differ diff --git a/hm_web/static/images/LOEA06_04.png b/hm_web/static/images/LOEA06_04.png new file mode 100644 index 0000000..3f29b0d Binary files /dev/null and b/hm_web/static/images/LOEA06_04.png differ diff --git a/hm_web/static/images/LOEA06_04h.png b/hm_web/static/images/LOEA06_04h.png new file mode 100644 index 0000000..a21c183 Binary files /dev/null and b/hm_web/static/images/LOEA06_04h.png differ diff --git a/hm_web/static/images/LOEA07_01.png b/hm_web/static/images/LOEA07_01.png new file mode 100644 index 0000000..b5072a0 Binary files /dev/null and b/hm_web/static/images/LOEA07_01.png differ diff --git a/hm_web/static/images/LOEA07_02.png b/hm_web/static/images/LOEA07_02.png new file mode 100644 index 0000000..33cc29a Binary files /dev/null and b/hm_web/static/images/LOEA07_02.png differ diff --git a/hm_web/static/images/LOEA07_02h.png b/hm_web/static/images/LOEA07_02h.png new file mode 100644 index 0000000..d9d8ba9 Binary files /dev/null and b/hm_web/static/images/LOEA07_02h.png differ diff --git a/hm_web/static/images/LOEA07_03.png b/hm_web/static/images/LOEA07_03.png new file mode 100644 index 0000000..430b750 Binary files /dev/null and b/hm_web/static/images/LOEA07_03.png differ diff --git a/hm_web/static/images/LOEA07_03h.png b/hm_web/static/images/LOEA07_03h.png new file mode 100644 index 0000000..41436c3 Binary files /dev/null and b/hm_web/static/images/LOEA07_03h.png differ diff --git a/hm_web/static/images/LOEA07_09.png b/hm_web/static/images/LOEA07_09.png new file mode 100644 index 0000000..fbb5550 Binary files /dev/null and b/hm_web/static/images/LOEA07_09.png differ diff --git a/hm_web/static/images/LOEA07_11.png b/hm_web/static/images/LOEA07_11.png new file mode 100644 index 0000000..2c1822c Binary files /dev/null and b/hm_web/static/images/LOEA07_11.png differ diff --git a/hm_web/static/images/LOEA07_12.png b/hm_web/static/images/LOEA07_12.png new file mode 100644 index 0000000..487114d Binary files /dev/null and b/hm_web/static/images/LOEA07_12.png differ diff --git a/hm_web/static/images/LOEA07_14.png b/hm_web/static/images/LOEA07_14.png new file mode 100644 index 0000000..ffc1d34 Binary files /dev/null and b/hm_web/static/images/LOEA07_14.png differ diff --git a/hm_web/static/images/LOEA07_18.png b/hm_web/static/images/LOEA07_18.png new file mode 100644 index 0000000..eb0fbf6 Binary files /dev/null and b/hm_web/static/images/LOEA07_18.png differ diff --git a/hm_web/static/images/LOEA07_20.png b/hm_web/static/images/LOEA07_20.png new file mode 100644 index 0000000..f256cc3 Binary files /dev/null and b/hm_web/static/images/LOEA07_20.png differ diff --git a/hm_web/static/images/LOEA07_21.png b/hm_web/static/images/LOEA07_21.png new file mode 100644 index 0000000..85253d7 Binary files /dev/null and b/hm_web/static/images/LOEA07_21.png differ diff --git a/hm_web/static/images/LOEA07_24.png b/hm_web/static/images/LOEA07_24.png new file mode 100644 index 0000000..5d38907 Binary files /dev/null and b/hm_web/static/images/LOEA07_24.png differ diff --git a/hm_web/static/images/LOEA07_25.png b/hm_web/static/images/LOEA07_25.png new file mode 100644 index 0000000..ae3be36 Binary files /dev/null and b/hm_web/static/images/LOEA07_25.png differ diff --git a/hm_web/static/images/LOEA07_26.png b/hm_web/static/images/LOEA07_26.png new file mode 100644 index 0000000..99313a0 Binary files /dev/null and b/hm_web/static/images/LOEA07_26.png differ diff --git a/hm_web/static/images/LOEA07_28.png b/hm_web/static/images/LOEA07_28.png new file mode 100644 index 0000000..1ab676b Binary files /dev/null and b/hm_web/static/images/LOEA07_28.png differ diff --git a/hm_web/static/images/LOEA07_29.png b/hm_web/static/images/LOEA07_29.png new file mode 100644 index 0000000..7aa3f52 Binary files /dev/null and b/hm_web/static/images/LOEA07_29.png differ diff --git a/hm_web/static/images/LOEA08_01.png b/hm_web/static/images/LOEA08_01.png new file mode 100644 index 0000000..ff0c29b Binary files /dev/null and b/hm_web/static/images/LOEA08_01.png differ diff --git a/hm_web/static/images/LOEA08_01h.png b/hm_web/static/images/LOEA08_01h.png new file mode 100644 index 0000000..5e11cf0 Binary files /dev/null and b/hm_web/static/images/LOEA08_01h.png differ diff --git a/hm_web/static/images/LOEA09_1.png b/hm_web/static/images/LOEA09_1.png new file mode 100644 index 0000000..69bd778 Binary files /dev/null and b/hm_web/static/images/LOEA09_1.png differ diff --git a/hm_web/static/images/LOEA09_10.png b/hm_web/static/images/LOEA09_10.png new file mode 100644 index 0000000..745723d Binary files /dev/null and b/hm_web/static/images/LOEA09_10.png differ diff --git a/hm_web/static/images/LOEA09_11.png b/hm_web/static/images/LOEA09_11.png new file mode 100644 index 0000000..c890c21 Binary files /dev/null and b/hm_web/static/images/LOEA09_11.png differ diff --git a/hm_web/static/images/LOEA09_12.png b/hm_web/static/images/LOEA09_12.png new file mode 100644 index 0000000..b87cb37 Binary files /dev/null and b/hm_web/static/images/LOEA09_12.png differ diff --git a/hm_web/static/images/LOEA09_13.png b/hm_web/static/images/LOEA09_13.png new file mode 100644 index 0000000..2872c80 Binary files /dev/null and b/hm_web/static/images/LOEA09_13.png differ diff --git a/hm_web/static/images/LOEA09_1H.png b/hm_web/static/images/LOEA09_1H.png new file mode 100644 index 0000000..54aea58 Binary files /dev/null and b/hm_web/static/images/LOEA09_1H.png differ diff --git a/hm_web/static/images/LOEA09_2.png b/hm_web/static/images/LOEA09_2.png new file mode 100644 index 0000000..024042e Binary files /dev/null and b/hm_web/static/images/LOEA09_2.png differ diff --git a/hm_web/static/images/LOEA09_2H.png b/hm_web/static/images/LOEA09_2H.png new file mode 100644 index 0000000..54b468b Binary files /dev/null and b/hm_web/static/images/LOEA09_2H.png differ diff --git a/hm_web/static/images/LOEA09_2e.png b/hm_web/static/images/LOEA09_2e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA09_2e.png differ diff --git a/hm_web/static/images/LOEA09_2eH.png b/hm_web/static/images/LOEA09_2eH.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA09_2eH.png differ diff --git a/hm_web/static/images/LOEA09_3.png b/hm_web/static/images/LOEA09_3.png new file mode 100644 index 0000000..06595d4 Binary files /dev/null and b/hm_web/static/images/LOEA09_3.png differ diff --git a/hm_web/static/images/LOEA09_3H.png b/hm_web/static/images/LOEA09_3H.png new file mode 100644 index 0000000..6b7bad8 Binary files /dev/null and b/hm_web/static/images/LOEA09_3H.png differ diff --git a/hm_web/static/images/LOEA09_3a.png b/hm_web/static/images/LOEA09_3a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA09_3a.png differ diff --git a/hm_web/static/images/LOEA09_3aH.png b/hm_web/static/images/LOEA09_3aH.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA09_3aH.png differ diff --git a/hm_web/static/images/LOEA09_3b.png b/hm_web/static/images/LOEA09_3b.png new file mode 100644 index 0000000..33ca50e Binary files /dev/null and b/hm_web/static/images/LOEA09_3b.png differ diff --git a/hm_web/static/images/LOEA09_3c.png b/hm_web/static/images/LOEA09_3c.png new file mode 100644 index 0000000..f7d10cf Binary files /dev/null and b/hm_web/static/images/LOEA09_3c.png differ diff --git a/hm_web/static/images/LOEA09_3d.png b/hm_web/static/images/LOEA09_3d.png new file mode 100644 index 0000000..1f84567 Binary files /dev/null and b/hm_web/static/images/LOEA09_3d.png differ diff --git a/hm_web/static/images/LOEA09_4.png b/hm_web/static/images/LOEA09_4.png new file mode 100644 index 0000000..73adeb8 Binary files /dev/null and b/hm_web/static/images/LOEA09_4.png differ diff --git a/hm_web/static/images/LOEA09_4H.png b/hm_web/static/images/LOEA09_4H.png new file mode 100644 index 0000000..232d7eb Binary files /dev/null and b/hm_web/static/images/LOEA09_4H.png differ diff --git a/hm_web/static/images/LOEA09_5.png b/hm_web/static/images/LOEA09_5.png new file mode 100644 index 0000000..790a4e4 Binary files /dev/null and b/hm_web/static/images/LOEA09_5.png differ diff --git a/hm_web/static/images/LOEA09_5H.png b/hm_web/static/images/LOEA09_5H.png new file mode 100644 index 0000000..9b24535 Binary files /dev/null and b/hm_web/static/images/LOEA09_5H.png differ diff --git a/hm_web/static/images/LOEA09_6.png b/hm_web/static/images/LOEA09_6.png new file mode 100644 index 0000000..309dc91 Binary files /dev/null and b/hm_web/static/images/LOEA09_6.png differ diff --git a/hm_web/static/images/LOEA09_6H.png b/hm_web/static/images/LOEA09_6H.png new file mode 100644 index 0000000..13422d6 Binary files /dev/null and b/hm_web/static/images/LOEA09_6H.png differ diff --git a/hm_web/static/images/LOEA09_7.png b/hm_web/static/images/LOEA09_7.png new file mode 100644 index 0000000..cf72412 Binary files /dev/null and b/hm_web/static/images/LOEA09_7.png differ diff --git a/hm_web/static/images/LOEA09_7H.png b/hm_web/static/images/LOEA09_7H.png new file mode 100644 index 0000000..aad53f8 Binary files /dev/null and b/hm_web/static/images/LOEA09_7H.png differ diff --git a/hm_web/static/images/LOEA09_7e.png b/hm_web/static/images/LOEA09_7e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA09_7e.png differ diff --git a/hm_web/static/images/LOEA09_8.png b/hm_web/static/images/LOEA09_8.png new file mode 100644 index 0000000..9653b2e Binary files /dev/null and b/hm_web/static/images/LOEA09_8.png differ diff --git a/hm_web/static/images/LOEA09_8H.png b/hm_web/static/images/LOEA09_8H.png new file mode 100644 index 0000000..1dca9fa Binary files /dev/null and b/hm_web/static/images/LOEA09_8H.png differ diff --git a/hm_web/static/images/LOEA09_9.png b/hm_web/static/images/LOEA09_9.png new file mode 100644 index 0000000..c1ec0ad Binary files /dev/null and b/hm_web/static/images/LOEA09_9.png differ diff --git a/hm_web/static/images/LOEA09_9H.png b/hm_web/static/images/LOEA09_9H.png new file mode 100644 index 0000000..8555e40 Binary files /dev/null and b/hm_web/static/images/LOEA09_9H.png differ diff --git a/hm_web/static/images/LOEA10_1.png b/hm_web/static/images/LOEA10_1.png new file mode 100644 index 0000000..a47d431 Binary files /dev/null and b/hm_web/static/images/LOEA10_1.png differ diff --git a/hm_web/static/images/LOEA10_1H.png b/hm_web/static/images/LOEA10_1H.png new file mode 100644 index 0000000..8566cc2 Binary files /dev/null and b/hm_web/static/images/LOEA10_1H.png differ diff --git a/hm_web/static/images/LOEA10_2.png b/hm_web/static/images/LOEA10_2.png new file mode 100644 index 0000000..831ce1e Binary files /dev/null and b/hm_web/static/images/LOEA10_2.png differ diff --git a/hm_web/static/images/LOEA10_2H.png b/hm_web/static/images/LOEA10_2H.png new file mode 100644 index 0000000..605184c Binary files /dev/null and b/hm_web/static/images/LOEA10_2H.png differ diff --git a/hm_web/static/images/LOEA10_3.png b/hm_web/static/images/LOEA10_3.png new file mode 100644 index 0000000..3e21a49 Binary files /dev/null and b/hm_web/static/images/LOEA10_3.png differ diff --git a/hm_web/static/images/LOEA10_5.png b/hm_web/static/images/LOEA10_5.png new file mode 100644 index 0000000..bd6b78d Binary files /dev/null and b/hm_web/static/images/LOEA10_5.png differ diff --git a/hm_web/static/images/LOEA10_5H.png b/hm_web/static/images/LOEA10_5H.png new file mode 100644 index 0000000..0e80500 Binary files /dev/null and b/hm_web/static/images/LOEA10_5H.png differ diff --git a/hm_web/static/images/LOEA12_1.png b/hm_web/static/images/LOEA12_1.png new file mode 100644 index 0000000..13727bc Binary files /dev/null and b/hm_web/static/images/LOEA12_1.png differ diff --git a/hm_web/static/images/LOEA12_1H.png b/hm_web/static/images/LOEA12_1H.png new file mode 100644 index 0000000..955e88d Binary files /dev/null and b/hm_web/static/images/LOEA12_1H.png differ diff --git a/hm_web/static/images/LOEA12_2.png b/hm_web/static/images/LOEA12_2.png new file mode 100644 index 0000000..a15970a Binary files /dev/null and b/hm_web/static/images/LOEA12_2.png differ diff --git a/hm_web/static/images/LOEA12_2H.png b/hm_web/static/images/LOEA12_2H.png new file mode 100644 index 0000000..7aed362 Binary files /dev/null and b/hm_web/static/images/LOEA12_2H.png differ diff --git a/hm_web/static/images/LOEA13_1.png b/hm_web/static/images/LOEA13_1.png new file mode 100644 index 0000000..b34e23a Binary files /dev/null and b/hm_web/static/images/LOEA13_1.png differ diff --git a/hm_web/static/images/LOEA13_1h.png b/hm_web/static/images/LOEA13_1h.png new file mode 100644 index 0000000..8c139a6 Binary files /dev/null and b/hm_web/static/images/LOEA13_1h.png differ diff --git a/hm_web/static/images/LOEA13_2.png b/hm_web/static/images/LOEA13_2.png new file mode 100644 index 0000000..d7bff12 Binary files /dev/null and b/hm_web/static/images/LOEA13_2.png differ diff --git a/hm_web/static/images/LOEA13_2H.png b/hm_web/static/images/LOEA13_2H.png new file mode 100644 index 0000000..27da0fe Binary files /dev/null and b/hm_web/static/images/LOEA13_2H.png differ diff --git a/hm_web/static/images/LOEA14_1.png b/hm_web/static/images/LOEA14_1.png new file mode 100644 index 0000000..f02a2c3 Binary files /dev/null and b/hm_web/static/images/LOEA14_1.png differ diff --git a/hm_web/static/images/LOEA14_1H.png b/hm_web/static/images/LOEA14_1H.png new file mode 100644 index 0000000..68f2049 Binary files /dev/null and b/hm_web/static/images/LOEA14_1H.png differ diff --git a/hm_web/static/images/LOEA14_2.png b/hm_web/static/images/LOEA14_2.png new file mode 100644 index 0000000..3d80163 Binary files /dev/null and b/hm_web/static/images/LOEA14_2.png differ diff --git a/hm_web/static/images/LOEA14_2H.png b/hm_web/static/images/LOEA14_2H.png new file mode 100644 index 0000000..46a148c Binary files /dev/null and b/hm_web/static/images/LOEA14_2H.png differ diff --git a/hm_web/static/images/LOEA15_1.png b/hm_web/static/images/LOEA15_1.png new file mode 100644 index 0000000..67713ec Binary files /dev/null and b/hm_web/static/images/LOEA15_1.png differ diff --git a/hm_web/static/images/LOEA15_1H.png b/hm_web/static/images/LOEA15_1H.png new file mode 100644 index 0000000..95d0973 Binary files /dev/null and b/hm_web/static/images/LOEA15_1H.png differ diff --git a/hm_web/static/images/LOEA15_2.png b/hm_web/static/images/LOEA15_2.png new file mode 100644 index 0000000..14f007a Binary files /dev/null and b/hm_web/static/images/LOEA15_2.png differ diff --git a/hm_web/static/images/LOEA15_2H.png b/hm_web/static/images/LOEA15_2H.png new file mode 100644 index 0000000..6d8df4c Binary files /dev/null and b/hm_web/static/images/LOEA15_2H.png differ diff --git a/hm_web/static/images/LOEA15_3.png b/hm_web/static/images/LOEA15_3.png new file mode 100644 index 0000000..6cab907 Binary files /dev/null and b/hm_web/static/images/LOEA15_3.png differ diff --git a/hm_web/static/images/LOEA15_3H.png b/hm_web/static/images/LOEA15_3H.png new file mode 100644 index 0000000..24399ea Binary files /dev/null and b/hm_web/static/images/LOEA15_3H.png differ diff --git a/hm_web/static/images/LOEA16_1.png b/hm_web/static/images/LOEA16_1.png new file mode 100644 index 0000000..d939fbf Binary files /dev/null and b/hm_web/static/images/LOEA16_1.png differ diff --git a/hm_web/static/images/LOEA16_10.png b/hm_web/static/images/LOEA16_10.png new file mode 100644 index 0000000..4b13b68 Binary files /dev/null and b/hm_web/static/images/LOEA16_10.png differ diff --git a/hm_web/static/images/LOEA16_11.png b/hm_web/static/images/LOEA16_11.png new file mode 100644 index 0000000..6ffd794 Binary files /dev/null and b/hm_web/static/images/LOEA16_11.png differ diff --git a/hm_web/static/images/LOEA16_12.png b/hm_web/static/images/LOEA16_12.png new file mode 100644 index 0000000..22485b4 Binary files /dev/null and b/hm_web/static/images/LOEA16_12.png differ diff --git a/hm_web/static/images/LOEA16_13.png b/hm_web/static/images/LOEA16_13.png new file mode 100644 index 0000000..abcb772 Binary files /dev/null and b/hm_web/static/images/LOEA16_13.png differ diff --git a/hm_web/static/images/LOEA16_14.png b/hm_web/static/images/LOEA16_14.png new file mode 100644 index 0000000..76ebe86 Binary files /dev/null and b/hm_web/static/images/LOEA16_14.png differ diff --git a/hm_web/static/images/LOEA16_15.png b/hm_web/static/images/LOEA16_15.png new file mode 100644 index 0000000..b16dff5 Binary files /dev/null and b/hm_web/static/images/LOEA16_15.png differ diff --git a/hm_web/static/images/LOEA16_16.png b/hm_web/static/images/LOEA16_16.png new file mode 100644 index 0000000..77e3f09 Binary files /dev/null and b/hm_web/static/images/LOEA16_16.png differ diff --git a/hm_web/static/images/LOEA16_16H.png b/hm_web/static/images/LOEA16_16H.png new file mode 100644 index 0000000..b047f38 Binary files /dev/null and b/hm_web/static/images/LOEA16_16H.png differ diff --git a/hm_web/static/images/LOEA16_17.png b/hm_web/static/images/LOEA16_17.png new file mode 100644 index 0000000..69066fe Binary files /dev/null and b/hm_web/static/images/LOEA16_17.png differ diff --git a/hm_web/static/images/LOEA16_18.png b/hm_web/static/images/LOEA16_18.png new file mode 100644 index 0000000..11a427a Binary files /dev/null and b/hm_web/static/images/LOEA16_18.png differ diff --git a/hm_web/static/images/LOEA16_18H.png b/hm_web/static/images/LOEA16_18H.png new file mode 100644 index 0000000..214fab5 Binary files /dev/null and b/hm_web/static/images/LOEA16_18H.png differ diff --git a/hm_web/static/images/LOEA16_19.png b/hm_web/static/images/LOEA16_19.png new file mode 100644 index 0000000..71b6a38 Binary files /dev/null and b/hm_web/static/images/LOEA16_19.png differ diff --git a/hm_web/static/images/LOEA16_19H.png b/hm_web/static/images/LOEA16_19H.png new file mode 100644 index 0000000..c5604bd Binary files /dev/null and b/hm_web/static/images/LOEA16_19H.png differ diff --git a/hm_web/static/images/LOEA16_1H.png b/hm_web/static/images/LOEA16_1H.png new file mode 100644 index 0000000..fe1ae4f Binary files /dev/null and b/hm_web/static/images/LOEA16_1H.png differ diff --git a/hm_web/static/images/LOEA16_2.png b/hm_web/static/images/LOEA16_2.png new file mode 100644 index 0000000..e01f660 Binary files /dev/null and b/hm_web/static/images/LOEA16_2.png differ diff --git a/hm_web/static/images/LOEA16_20.png b/hm_web/static/images/LOEA16_20.png new file mode 100644 index 0000000..f4f46f3 Binary files /dev/null and b/hm_web/static/images/LOEA16_20.png differ diff --git a/hm_web/static/images/LOEA16_20H.png b/hm_web/static/images/LOEA16_20H.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA16_20H.png differ diff --git a/hm_web/static/images/LOEA16_20e.png b/hm_web/static/images/LOEA16_20e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA16_20e.png differ diff --git a/hm_web/static/images/LOEA16_21.png b/hm_web/static/images/LOEA16_21.png new file mode 100644 index 0000000..3af5194 Binary files /dev/null and b/hm_web/static/images/LOEA16_21.png differ diff --git a/hm_web/static/images/LOEA16_21H.png b/hm_web/static/images/LOEA16_21H.png new file mode 100644 index 0000000..2aa08d4 Binary files /dev/null and b/hm_web/static/images/LOEA16_21H.png differ diff --git a/hm_web/static/images/LOEA16_22.png b/hm_web/static/images/LOEA16_22.png new file mode 100644 index 0000000..9342a3c Binary files /dev/null and b/hm_web/static/images/LOEA16_22.png differ diff --git a/hm_web/static/images/LOEA16_22H.png b/hm_web/static/images/LOEA16_22H.png new file mode 100644 index 0000000..b6c7e25 Binary files /dev/null and b/hm_web/static/images/LOEA16_22H.png differ diff --git a/hm_web/static/images/LOEA16_23.png b/hm_web/static/images/LOEA16_23.png new file mode 100644 index 0000000..1ef8dee Binary files /dev/null and b/hm_web/static/images/LOEA16_23.png differ diff --git a/hm_web/static/images/LOEA16_23H.png b/hm_web/static/images/LOEA16_23H.png new file mode 100644 index 0000000..0e2861d Binary files /dev/null and b/hm_web/static/images/LOEA16_23H.png differ diff --git a/hm_web/static/images/LOEA16_24.png b/hm_web/static/images/LOEA16_24.png new file mode 100644 index 0000000..228244c Binary files /dev/null and b/hm_web/static/images/LOEA16_24.png differ diff --git a/hm_web/static/images/LOEA16_24H.png b/hm_web/static/images/LOEA16_24H.png new file mode 100644 index 0000000..3afb90c Binary files /dev/null and b/hm_web/static/images/LOEA16_24H.png differ diff --git a/hm_web/static/images/LOEA16_25.png b/hm_web/static/images/LOEA16_25.png new file mode 100644 index 0000000..6e5e220 Binary files /dev/null and b/hm_web/static/images/LOEA16_25.png differ diff --git a/hm_web/static/images/LOEA16_25H.png b/hm_web/static/images/LOEA16_25H.png new file mode 100644 index 0000000..c8e9a2f Binary files /dev/null and b/hm_web/static/images/LOEA16_25H.png differ diff --git a/hm_web/static/images/LOEA16_26.png b/hm_web/static/images/LOEA16_26.png new file mode 100644 index 0000000..a0103c6 Binary files /dev/null and b/hm_web/static/images/LOEA16_26.png differ diff --git a/hm_web/static/images/LOEA16_26H.png b/hm_web/static/images/LOEA16_26H.png new file mode 100644 index 0000000..aa62bee Binary files /dev/null and b/hm_web/static/images/LOEA16_26H.png differ diff --git a/hm_web/static/images/LOEA16_27.png b/hm_web/static/images/LOEA16_27.png new file mode 100644 index 0000000..8dad70b Binary files /dev/null and b/hm_web/static/images/LOEA16_27.png differ diff --git a/hm_web/static/images/LOEA16_27H.png b/hm_web/static/images/LOEA16_27H.png new file mode 100644 index 0000000..85fd29e Binary files /dev/null and b/hm_web/static/images/LOEA16_27H.png differ diff --git a/hm_web/static/images/LOEA16_2H.png b/hm_web/static/images/LOEA16_2H.png new file mode 100644 index 0000000..e5d4691 Binary files /dev/null and b/hm_web/static/images/LOEA16_2H.png differ diff --git a/hm_web/static/images/LOEA16_3.png b/hm_web/static/images/LOEA16_3.png new file mode 100644 index 0000000..04cae84 Binary files /dev/null and b/hm_web/static/images/LOEA16_3.png differ diff --git a/hm_web/static/images/LOEA16_3e.png b/hm_web/static/images/LOEA16_3e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA16_3e.png differ diff --git a/hm_web/static/images/LOEA16_4.png b/hm_web/static/images/LOEA16_4.png new file mode 100644 index 0000000..9e3863b Binary files /dev/null and b/hm_web/static/images/LOEA16_4.png differ diff --git a/hm_web/static/images/LOEA16_5.png b/hm_web/static/images/LOEA16_5.png new file mode 100644 index 0000000..c53e0f2 Binary files /dev/null and b/hm_web/static/images/LOEA16_5.png differ diff --git a/hm_web/static/images/LOEA16_5t.png b/hm_web/static/images/LOEA16_5t.png new file mode 100644 index 0000000..3828fd1 Binary files /dev/null and b/hm_web/static/images/LOEA16_5t.png differ diff --git a/hm_web/static/images/LOEA16_6.png b/hm_web/static/images/LOEA16_6.png new file mode 100644 index 0000000..dcb2ac0 Binary files /dev/null and b/hm_web/static/images/LOEA16_6.png differ diff --git a/hm_web/static/images/LOEA16_7.png b/hm_web/static/images/LOEA16_7.png new file mode 100644 index 0000000..7d04312 Binary files /dev/null and b/hm_web/static/images/LOEA16_7.png differ diff --git a/hm_web/static/images/LOEA16_8.png b/hm_web/static/images/LOEA16_8.png new file mode 100644 index 0000000..eb890c5 Binary files /dev/null and b/hm_web/static/images/LOEA16_8.png differ diff --git a/hm_web/static/images/LOEA16_8a.png b/hm_web/static/images/LOEA16_8a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOEA16_8a.png differ diff --git a/hm_web/static/images/LOEA16_9.png b/hm_web/static/images/LOEA16_9.png new file mode 100644 index 0000000..acd78dc Binary files /dev/null and b/hm_web/static/images/LOEA16_9.png differ diff --git a/hm_web/static/images/LOEA_01.png b/hm_web/static/images/LOEA_01.png new file mode 100644 index 0000000..74cb877 Binary files /dev/null and b/hm_web/static/images/LOEA_01.png differ diff --git a/hm_web/static/images/LOEA_01H.png b/hm_web/static/images/LOEA_01H.png new file mode 100644 index 0000000..cc62d17 Binary files /dev/null and b/hm_web/static/images/LOEA_01H.png differ diff --git a/hm_web/static/images/LOE_002.png b/hm_web/static/images/LOE_002.png new file mode 100644 index 0000000..4a3402b Binary files /dev/null and b/hm_web/static/images/LOE_002.png differ diff --git a/hm_web/static/images/LOE_002t.png b/hm_web/static/images/LOE_002t.png new file mode 100644 index 0000000..cfd43f8 Binary files /dev/null and b/hm_web/static/images/LOE_002t.png differ diff --git a/hm_web/static/images/LOE_003.png b/hm_web/static/images/LOE_003.png new file mode 100644 index 0000000..78496fb Binary files /dev/null and b/hm_web/static/images/LOE_003.png differ diff --git a/hm_web/static/images/LOE_006.png b/hm_web/static/images/LOE_006.png new file mode 100644 index 0000000..950b00f Binary files /dev/null and b/hm_web/static/images/LOE_006.png differ diff --git a/hm_web/static/images/LOE_007.png b/hm_web/static/images/LOE_007.png new file mode 100644 index 0000000..b092c4c Binary files /dev/null and b/hm_web/static/images/LOE_007.png differ diff --git a/hm_web/static/images/LOE_007t.png b/hm_web/static/images/LOE_007t.png new file mode 100644 index 0000000..8dd2705 Binary files /dev/null and b/hm_web/static/images/LOE_007t.png differ diff --git a/hm_web/static/images/LOE_008.png b/hm_web/static/images/LOE_008.png new file mode 100644 index 0000000..392f20a Binary files /dev/null and b/hm_web/static/images/LOE_008.png differ diff --git a/hm_web/static/images/LOE_008H.png b/hm_web/static/images/LOE_008H.png new file mode 100644 index 0000000..d891956 Binary files /dev/null and b/hm_web/static/images/LOE_008H.png differ diff --git a/hm_web/static/images/LOE_009.png b/hm_web/static/images/LOE_009.png new file mode 100644 index 0000000..622d06a Binary files /dev/null and b/hm_web/static/images/LOE_009.png differ diff --git a/hm_web/static/images/LOE_009e.png b/hm_web/static/images/LOE_009e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_009e.png differ diff --git a/hm_web/static/images/LOE_009t.png b/hm_web/static/images/LOE_009t.png new file mode 100644 index 0000000..b06096d Binary files /dev/null and b/hm_web/static/images/LOE_009t.png differ diff --git a/hm_web/static/images/LOE_010.png b/hm_web/static/images/LOE_010.png new file mode 100644 index 0000000..dda2816 Binary files /dev/null and b/hm_web/static/images/LOE_010.png differ diff --git a/hm_web/static/images/LOE_011.png b/hm_web/static/images/LOE_011.png new file mode 100644 index 0000000..454a6dc Binary files /dev/null and b/hm_web/static/images/LOE_011.png differ diff --git a/hm_web/static/images/LOE_012.png b/hm_web/static/images/LOE_012.png new file mode 100644 index 0000000..65b8184 Binary files /dev/null and b/hm_web/static/images/LOE_012.png differ diff --git a/hm_web/static/images/LOE_016.png b/hm_web/static/images/LOE_016.png new file mode 100644 index 0000000..5aaa9c5 Binary files /dev/null and b/hm_web/static/images/LOE_016.png differ diff --git a/hm_web/static/images/LOE_016t.png b/hm_web/static/images/LOE_016t.png new file mode 100644 index 0000000..be0d4fb Binary files /dev/null and b/hm_web/static/images/LOE_016t.png differ diff --git a/hm_web/static/images/LOE_017.png b/hm_web/static/images/LOE_017.png new file mode 100644 index 0000000..d33f4b4 Binary files /dev/null and b/hm_web/static/images/LOE_017.png differ diff --git a/hm_web/static/images/LOE_017e.png b/hm_web/static/images/LOE_017e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_017e.png differ diff --git a/hm_web/static/images/LOE_018.png b/hm_web/static/images/LOE_018.png new file mode 100644 index 0000000..a349ef6 Binary files /dev/null and b/hm_web/static/images/LOE_018.png differ diff --git a/hm_web/static/images/LOE_018e.png b/hm_web/static/images/LOE_018e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_018e.png differ diff --git a/hm_web/static/images/LOE_019.png b/hm_web/static/images/LOE_019.png new file mode 100644 index 0000000..48044e0 Binary files /dev/null and b/hm_web/static/images/LOE_019.png differ diff --git a/hm_web/static/images/LOE_019e.png b/hm_web/static/images/LOE_019e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_019e.png differ diff --git a/hm_web/static/images/LOE_019t.png b/hm_web/static/images/LOE_019t.png new file mode 100644 index 0000000..dac9b46 Binary files /dev/null and b/hm_web/static/images/LOE_019t.png differ diff --git a/hm_web/static/images/LOE_019t2.png b/hm_web/static/images/LOE_019t2.png new file mode 100644 index 0000000..43617f0 Binary files /dev/null and b/hm_web/static/images/LOE_019t2.png differ diff --git a/hm_web/static/images/LOE_020.png b/hm_web/static/images/LOE_020.png new file mode 100644 index 0000000..58c6964 Binary files /dev/null and b/hm_web/static/images/LOE_020.png differ diff --git a/hm_web/static/images/LOE_021.png b/hm_web/static/images/LOE_021.png new file mode 100644 index 0000000..041e870 Binary files /dev/null and b/hm_web/static/images/LOE_021.png differ diff --git a/hm_web/static/images/LOE_022.png b/hm_web/static/images/LOE_022.png new file mode 100644 index 0000000..48df083 Binary files /dev/null and b/hm_web/static/images/LOE_022.png differ diff --git a/hm_web/static/images/LOE_023.png b/hm_web/static/images/LOE_023.png new file mode 100644 index 0000000..c72bdca Binary files /dev/null and b/hm_web/static/images/LOE_023.png differ diff --git a/hm_web/static/images/LOE_024t.png b/hm_web/static/images/LOE_024t.png new file mode 100644 index 0000000..f3892b1 Binary files /dev/null and b/hm_web/static/images/LOE_024t.png differ diff --git a/hm_web/static/images/LOE_026.png b/hm_web/static/images/LOE_026.png new file mode 100644 index 0000000..80ebcd3 Binary files /dev/null and b/hm_web/static/images/LOE_026.png differ diff --git a/hm_web/static/images/LOE_027.png b/hm_web/static/images/LOE_027.png new file mode 100644 index 0000000..47f949d Binary files /dev/null and b/hm_web/static/images/LOE_027.png differ diff --git a/hm_web/static/images/LOE_029.png b/hm_web/static/images/LOE_029.png new file mode 100644 index 0000000..567de44 Binary files /dev/null and b/hm_web/static/images/LOE_029.png differ diff --git a/hm_web/static/images/LOE_030e.png b/hm_web/static/images/LOE_030e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_030e.png differ diff --git a/hm_web/static/images/LOE_038.png b/hm_web/static/images/LOE_038.png new file mode 100644 index 0000000..d4f9bda Binary files /dev/null and b/hm_web/static/images/LOE_038.png differ diff --git a/hm_web/static/images/LOE_039.png b/hm_web/static/images/LOE_039.png new file mode 100644 index 0000000..460bc49 Binary files /dev/null and b/hm_web/static/images/LOE_039.png differ diff --git a/hm_web/static/images/LOE_046.png b/hm_web/static/images/LOE_046.png new file mode 100644 index 0000000..7edbb07 Binary files /dev/null and b/hm_web/static/images/LOE_046.png differ diff --git a/hm_web/static/images/LOE_047.png b/hm_web/static/images/LOE_047.png new file mode 100644 index 0000000..fb52dd2 Binary files /dev/null and b/hm_web/static/images/LOE_047.png differ diff --git a/hm_web/static/images/LOE_050.png b/hm_web/static/images/LOE_050.png new file mode 100644 index 0000000..41bb7a2 Binary files /dev/null and b/hm_web/static/images/LOE_050.png differ diff --git a/hm_web/static/images/LOE_051.png b/hm_web/static/images/LOE_051.png new file mode 100644 index 0000000..88c366b Binary files /dev/null and b/hm_web/static/images/LOE_051.png differ diff --git a/hm_web/static/images/LOE_053.png b/hm_web/static/images/LOE_053.png new file mode 100644 index 0000000..f8fb626 Binary files /dev/null and b/hm_web/static/images/LOE_053.png differ diff --git a/hm_web/static/images/LOE_061.png b/hm_web/static/images/LOE_061.png new file mode 100644 index 0000000..7396e78 Binary files /dev/null and b/hm_web/static/images/LOE_061.png differ diff --git a/hm_web/static/images/LOE_061e.png b/hm_web/static/images/LOE_061e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_061e.png differ diff --git a/hm_web/static/images/LOE_073.png b/hm_web/static/images/LOE_073.png new file mode 100644 index 0000000..ac53a36 Binary files /dev/null and b/hm_web/static/images/LOE_073.png differ diff --git a/hm_web/static/images/LOE_073e.png b/hm_web/static/images/LOE_073e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_073e.png differ diff --git a/hm_web/static/images/LOE_076.png b/hm_web/static/images/LOE_076.png new file mode 100644 index 0000000..f758a00 Binary files /dev/null and b/hm_web/static/images/LOE_076.png differ diff --git a/hm_web/static/images/LOE_077.png b/hm_web/static/images/LOE_077.png new file mode 100644 index 0000000..9f2b678 Binary files /dev/null and b/hm_web/static/images/LOE_077.png differ diff --git a/hm_web/static/images/LOE_079.png b/hm_web/static/images/LOE_079.png new file mode 100644 index 0000000..555ae90 Binary files /dev/null and b/hm_web/static/images/LOE_079.png differ diff --git a/hm_web/static/images/LOE_086.png b/hm_web/static/images/LOE_086.png new file mode 100644 index 0000000..4b12dc9 Binary files /dev/null and b/hm_web/static/images/LOE_086.png differ diff --git a/hm_web/static/images/LOE_089.png b/hm_web/static/images/LOE_089.png new file mode 100644 index 0000000..c4e3f21 Binary files /dev/null and b/hm_web/static/images/LOE_089.png differ diff --git a/hm_web/static/images/LOE_089t.png b/hm_web/static/images/LOE_089t.png new file mode 100644 index 0000000..d8a8cb6 Binary files /dev/null and b/hm_web/static/images/LOE_089t.png differ diff --git a/hm_web/static/images/LOE_089t2.png b/hm_web/static/images/LOE_089t2.png new file mode 100644 index 0000000..c7e4d5e Binary files /dev/null and b/hm_web/static/images/LOE_089t2.png differ diff --git a/hm_web/static/images/LOE_089t3.png b/hm_web/static/images/LOE_089t3.png new file mode 100644 index 0000000..6c78bd0 Binary files /dev/null and b/hm_web/static/images/LOE_089t3.png differ diff --git a/hm_web/static/images/LOE_092.png b/hm_web/static/images/LOE_092.png new file mode 100644 index 0000000..94a36ba Binary files /dev/null and b/hm_web/static/images/LOE_092.png differ diff --git a/hm_web/static/images/LOE_104.png b/hm_web/static/images/LOE_104.png new file mode 100644 index 0000000..998664a Binary files /dev/null and b/hm_web/static/images/LOE_104.png differ diff --git a/hm_web/static/images/LOE_105.png b/hm_web/static/images/LOE_105.png new file mode 100644 index 0000000..50bda11 Binary files /dev/null and b/hm_web/static/images/LOE_105.png differ diff --git a/hm_web/static/images/LOE_105e.png b/hm_web/static/images/LOE_105e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_105e.png differ diff --git a/hm_web/static/images/LOE_107.png b/hm_web/static/images/LOE_107.png new file mode 100644 index 0000000..9f2aba6 Binary files /dev/null and b/hm_web/static/images/LOE_107.png differ diff --git a/hm_web/static/images/LOE_110.png b/hm_web/static/images/LOE_110.png new file mode 100644 index 0000000..cab7c2e Binary files /dev/null and b/hm_web/static/images/LOE_110.png differ diff --git a/hm_web/static/images/LOE_110t.png b/hm_web/static/images/LOE_110t.png new file mode 100644 index 0000000..2c2e825 Binary files /dev/null and b/hm_web/static/images/LOE_110t.png differ diff --git a/hm_web/static/images/LOE_111.png b/hm_web/static/images/LOE_111.png new file mode 100644 index 0000000..a277c36 Binary files /dev/null and b/hm_web/static/images/LOE_111.png differ diff --git a/hm_web/static/images/LOE_113.png b/hm_web/static/images/LOE_113.png new file mode 100644 index 0000000..e324af1 Binary files /dev/null and b/hm_web/static/images/LOE_113.png differ diff --git a/hm_web/static/images/LOE_113e.png b/hm_web/static/images/LOE_113e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_113e.png differ diff --git a/hm_web/static/images/LOE_115.png b/hm_web/static/images/LOE_115.png new file mode 100644 index 0000000..709a2f8 Binary files /dev/null and b/hm_web/static/images/LOE_115.png differ diff --git a/hm_web/static/images/LOE_115a.png b/hm_web/static/images/LOE_115a.png new file mode 100644 index 0000000..46ba906 Binary files /dev/null and b/hm_web/static/images/LOE_115a.png differ diff --git a/hm_web/static/images/LOE_115b.png b/hm_web/static/images/LOE_115b.png new file mode 100644 index 0000000..bde07ef Binary files /dev/null and b/hm_web/static/images/LOE_115b.png differ diff --git a/hm_web/static/images/LOE_116.png b/hm_web/static/images/LOE_116.png new file mode 100644 index 0000000..bdaefe6 Binary files /dev/null and b/hm_web/static/images/LOE_116.png differ diff --git a/hm_web/static/images/LOE_118.png b/hm_web/static/images/LOE_118.png new file mode 100644 index 0000000..cd59830 Binary files /dev/null and b/hm_web/static/images/LOE_118.png differ diff --git a/hm_web/static/images/LOE_118e.png b/hm_web/static/images/LOE_118e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/LOE_118e.png differ diff --git a/hm_web/static/images/LOE_119.png b/hm_web/static/images/LOE_119.png new file mode 100644 index 0000000..fd6f87e Binary files /dev/null and b/hm_web/static/images/LOE_119.png differ diff --git a/hm_web/static/images/Mekka1.png b/hm_web/static/images/Mekka1.png new file mode 100644 index 0000000..022cddd Binary files /dev/null and b/hm_web/static/images/Mekka1.png differ diff --git a/hm_web/static/images/Mekka2.png b/hm_web/static/images/Mekka2.png new file mode 100644 index 0000000..7bfee27 Binary files /dev/null and b/hm_web/static/images/Mekka2.png differ diff --git a/hm_web/static/images/Mekka3.png b/hm_web/static/images/Mekka3.png new file mode 100644 index 0000000..7bba7c1 Binary files /dev/null and b/hm_web/static/images/Mekka3.png differ diff --git a/hm_web/static/images/Mekka3e.png b/hm_web/static/images/Mekka3e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/Mekka3e.png differ diff --git a/hm_web/static/images/Mekka4.png b/hm_web/static/images/Mekka4.png new file mode 100644 index 0000000..6196ca3 Binary files /dev/null and b/hm_web/static/images/Mekka4.png differ diff --git a/hm_web/static/images/Mekka4e.png b/hm_web/static/images/Mekka4e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/Mekka4e.png differ diff --git a/hm_web/static/images/Mekka4t.png b/hm_web/static/images/Mekka4t.png new file mode 100644 index 0000000..1cf84b4 Binary files /dev/null and b/hm_web/static/images/Mekka4t.png differ diff --git a/hm_web/static/images/NAX10_01.png b/hm_web/static/images/NAX10_01.png new file mode 100644 index 0000000..59797ce Binary files /dev/null and b/hm_web/static/images/NAX10_01.png differ diff --git a/hm_web/static/images/NAX10_01H.png b/hm_web/static/images/NAX10_01H.png new file mode 100644 index 0000000..9aaca4d Binary files /dev/null and b/hm_web/static/images/NAX10_01H.png differ diff --git a/hm_web/static/images/NAX10_02.png b/hm_web/static/images/NAX10_02.png new file mode 100644 index 0000000..2fe356d Binary files /dev/null and b/hm_web/static/images/NAX10_02.png differ diff --git a/hm_web/static/images/NAX10_02H.png b/hm_web/static/images/NAX10_02H.png new file mode 100644 index 0000000..be5669e Binary files /dev/null and b/hm_web/static/images/NAX10_02H.png differ diff --git a/hm_web/static/images/NAX10_03.png b/hm_web/static/images/NAX10_03.png new file mode 100644 index 0000000..1eb23a0 Binary files /dev/null and b/hm_web/static/images/NAX10_03.png differ diff --git a/hm_web/static/images/NAX10_03H.png b/hm_web/static/images/NAX10_03H.png new file mode 100644 index 0000000..c8ceae3 Binary files /dev/null and b/hm_web/static/images/NAX10_03H.png differ diff --git a/hm_web/static/images/NAX11_01.png b/hm_web/static/images/NAX11_01.png new file mode 100644 index 0000000..207e410 Binary files /dev/null and b/hm_web/static/images/NAX11_01.png differ diff --git a/hm_web/static/images/NAX11_01H.png b/hm_web/static/images/NAX11_01H.png new file mode 100644 index 0000000..fe9d552 Binary files /dev/null and b/hm_web/static/images/NAX11_01H.png differ diff --git a/hm_web/static/images/NAX11_02.png b/hm_web/static/images/NAX11_02.png new file mode 100644 index 0000000..bd8fa8d Binary files /dev/null and b/hm_web/static/images/NAX11_02.png differ diff --git a/hm_web/static/images/NAX11_02H.png b/hm_web/static/images/NAX11_02H.png new file mode 100644 index 0000000..5dad217 Binary files /dev/null and b/hm_web/static/images/NAX11_02H.png differ diff --git a/hm_web/static/images/NAX11_02H_2_TB.png b/hm_web/static/images/NAX11_02H_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX11_02H_2_TB.png differ diff --git a/hm_web/static/images/NAX11_03.png b/hm_web/static/images/NAX11_03.png new file mode 100644 index 0000000..9788a51 Binary files /dev/null and b/hm_web/static/images/NAX11_03.png differ diff --git a/hm_web/static/images/NAX11_04.png b/hm_web/static/images/NAX11_04.png new file mode 100644 index 0000000..32431c6 Binary files /dev/null and b/hm_web/static/images/NAX11_04.png differ diff --git a/hm_web/static/images/NAX11_04e.png b/hm_web/static/images/NAX11_04e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX11_04e.png differ diff --git a/hm_web/static/images/NAX12_01.png b/hm_web/static/images/NAX12_01.png new file mode 100644 index 0000000..077e4d7 Binary files /dev/null and b/hm_web/static/images/NAX12_01.png differ diff --git a/hm_web/static/images/NAX12_01H.png b/hm_web/static/images/NAX12_01H.png new file mode 100644 index 0000000..29a660d Binary files /dev/null and b/hm_web/static/images/NAX12_01H.png differ diff --git a/hm_web/static/images/NAX12_02.png b/hm_web/static/images/NAX12_02.png new file mode 100644 index 0000000..4859eed Binary files /dev/null and b/hm_web/static/images/NAX12_02.png differ diff --git a/hm_web/static/images/NAX12_02H.png b/hm_web/static/images/NAX12_02H.png new file mode 100644 index 0000000..463fff4 Binary files /dev/null and b/hm_web/static/images/NAX12_02H.png differ diff --git a/hm_web/static/images/NAX12_02H_2_TB.png b/hm_web/static/images/NAX12_02H_2_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX12_02H_2_TB.png differ diff --git a/hm_web/static/images/NAX12_02H_2c_TB.png b/hm_web/static/images/NAX12_02H_2c_TB.png new file mode 100644 index 0000000..c8e49df Binary files /dev/null and b/hm_web/static/images/NAX12_02H_2c_TB.png differ diff --git a/hm_web/static/images/NAX12_02e.png b/hm_web/static/images/NAX12_02e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX12_02e.png differ diff --git a/hm_web/static/images/NAX12_03.png b/hm_web/static/images/NAX12_03.png new file mode 100644 index 0000000..be07c8c Binary files /dev/null and b/hm_web/static/images/NAX12_03.png differ diff --git a/hm_web/static/images/NAX12_03H.png b/hm_web/static/images/NAX12_03H.png new file mode 100644 index 0000000..79cca38 Binary files /dev/null and b/hm_web/static/images/NAX12_03H.png differ diff --git a/hm_web/static/images/NAX12_03e.png b/hm_web/static/images/NAX12_03e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX12_03e.png differ diff --git a/hm_web/static/images/NAX12_04.png b/hm_web/static/images/NAX12_04.png new file mode 100644 index 0000000..05ab81b Binary files /dev/null and b/hm_web/static/images/NAX12_04.png differ diff --git a/hm_web/static/images/NAX12_04e.png b/hm_web/static/images/NAX12_04e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX12_04e.png differ diff --git a/hm_web/static/images/NAX13_01.png b/hm_web/static/images/NAX13_01.png new file mode 100644 index 0000000..4871e1b Binary files /dev/null and b/hm_web/static/images/NAX13_01.png differ diff --git a/hm_web/static/images/NAX13_01H.png b/hm_web/static/images/NAX13_01H.png new file mode 100644 index 0000000..5c128e5 Binary files /dev/null and b/hm_web/static/images/NAX13_01H.png differ diff --git a/hm_web/static/images/NAX13_02.png b/hm_web/static/images/NAX13_02.png new file mode 100644 index 0000000..eb8e3f6 Binary files /dev/null and b/hm_web/static/images/NAX13_02.png differ diff --git a/hm_web/static/images/NAX13_02e.png b/hm_web/static/images/NAX13_02e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX13_02e.png differ diff --git a/hm_web/static/images/NAX13_03.png b/hm_web/static/images/NAX13_03.png new file mode 100644 index 0000000..60d9d56 Binary files /dev/null and b/hm_web/static/images/NAX13_03.png differ diff --git a/hm_web/static/images/NAX13_03e.png b/hm_web/static/images/NAX13_03e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX13_03e.png differ diff --git a/hm_web/static/images/NAX13_04H.png b/hm_web/static/images/NAX13_04H.png new file mode 100644 index 0000000..f6decb0 Binary files /dev/null and b/hm_web/static/images/NAX13_04H.png differ diff --git a/hm_web/static/images/NAX13_05H.png b/hm_web/static/images/NAX13_05H.png new file mode 100644 index 0000000..8ae2acd Binary files /dev/null and b/hm_web/static/images/NAX13_05H.png differ diff --git a/hm_web/static/images/NAX14_01.png b/hm_web/static/images/NAX14_01.png new file mode 100644 index 0000000..bdcd618 Binary files /dev/null and b/hm_web/static/images/NAX14_01.png differ diff --git a/hm_web/static/images/NAX14_01H.png b/hm_web/static/images/NAX14_01H.png new file mode 100644 index 0000000..d489964 Binary files /dev/null and b/hm_web/static/images/NAX14_01H.png differ diff --git a/hm_web/static/images/NAX14_02.png b/hm_web/static/images/NAX14_02.png new file mode 100644 index 0000000..134640b Binary files /dev/null and b/hm_web/static/images/NAX14_02.png differ diff --git a/hm_web/static/images/NAX14_03.png b/hm_web/static/images/NAX14_03.png new file mode 100644 index 0000000..7f0a6de Binary files /dev/null and b/hm_web/static/images/NAX14_03.png differ diff --git a/hm_web/static/images/NAX14_04.png b/hm_web/static/images/NAX14_04.png new file mode 100644 index 0000000..38d1c3c Binary files /dev/null and b/hm_web/static/images/NAX14_04.png differ diff --git a/hm_web/static/images/NAX15_01.png b/hm_web/static/images/NAX15_01.png new file mode 100644 index 0000000..15e0d68 Binary files /dev/null and b/hm_web/static/images/NAX15_01.png differ diff --git a/hm_web/static/images/NAX15_01H.png b/hm_web/static/images/NAX15_01H.png new file mode 100644 index 0000000..c7d04a7 Binary files /dev/null and b/hm_web/static/images/NAX15_01H.png differ diff --git a/hm_web/static/images/NAX15_01He.png b/hm_web/static/images/NAX15_01He.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX15_01He.png differ diff --git a/hm_web/static/images/NAX15_01e.png b/hm_web/static/images/NAX15_01e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX15_01e.png differ diff --git a/hm_web/static/images/NAX15_02.png b/hm_web/static/images/NAX15_02.png new file mode 100644 index 0000000..ff23bd9 Binary files /dev/null and b/hm_web/static/images/NAX15_02.png differ diff --git a/hm_web/static/images/NAX15_02H.png b/hm_web/static/images/NAX15_02H.png new file mode 100644 index 0000000..955682a Binary files /dev/null and b/hm_web/static/images/NAX15_02H.png differ diff --git a/hm_web/static/images/NAX15_03n.png b/hm_web/static/images/NAX15_03n.png new file mode 100644 index 0000000..7e267d9 Binary files /dev/null and b/hm_web/static/images/NAX15_03n.png differ diff --git a/hm_web/static/images/NAX15_03t.png b/hm_web/static/images/NAX15_03t.png new file mode 100644 index 0000000..fc47d86 Binary files /dev/null and b/hm_web/static/images/NAX15_03t.png differ diff --git a/hm_web/static/images/NAX15_04.png b/hm_web/static/images/NAX15_04.png new file mode 100644 index 0000000..7c8ef3d Binary files /dev/null and b/hm_web/static/images/NAX15_04.png differ diff --git a/hm_web/static/images/NAX15_04H.png b/hm_web/static/images/NAX15_04H.png new file mode 100644 index 0000000..04a420b Binary files /dev/null and b/hm_web/static/images/NAX15_04H.png differ diff --git a/hm_web/static/images/NAX15_04a.png b/hm_web/static/images/NAX15_04a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX15_04a.png differ diff --git a/hm_web/static/images/NAX15_05.png b/hm_web/static/images/NAX15_05.png new file mode 100644 index 0000000..9cc7c44 Binary files /dev/null and b/hm_web/static/images/NAX15_05.png differ diff --git a/hm_web/static/images/NAX1_01.png b/hm_web/static/images/NAX1_01.png new file mode 100644 index 0000000..7f57068 Binary files /dev/null and b/hm_web/static/images/NAX1_01.png differ diff --git a/hm_web/static/images/NAX1_03.png b/hm_web/static/images/NAX1_03.png new file mode 100644 index 0000000..67f62a0 Binary files /dev/null and b/hm_web/static/images/NAX1_03.png differ diff --git a/hm_web/static/images/NAX1_04.png b/hm_web/static/images/NAX1_04.png new file mode 100644 index 0000000..60f9ad6 Binary files /dev/null and b/hm_web/static/images/NAX1_04.png differ diff --git a/hm_web/static/images/NAX1_05.png b/hm_web/static/images/NAX1_05.png new file mode 100644 index 0000000..a1d42c5 Binary files /dev/null and b/hm_web/static/images/NAX1_05.png differ diff --git a/hm_web/static/images/NAX1h_01.png b/hm_web/static/images/NAX1h_01.png new file mode 100644 index 0000000..e0203e8 Binary files /dev/null and b/hm_web/static/images/NAX1h_01.png differ diff --git a/hm_web/static/images/NAX1h_03.png b/hm_web/static/images/NAX1h_03.png new file mode 100644 index 0000000..fc94d92 Binary files /dev/null and b/hm_web/static/images/NAX1h_03.png differ diff --git a/hm_web/static/images/NAX1h_04.png b/hm_web/static/images/NAX1h_04.png new file mode 100644 index 0000000..5677fd0 Binary files /dev/null and b/hm_web/static/images/NAX1h_04.png differ diff --git a/hm_web/static/images/NAX2_01.png b/hm_web/static/images/NAX2_01.png new file mode 100644 index 0000000..482aafb Binary files /dev/null and b/hm_web/static/images/NAX2_01.png differ diff --git a/hm_web/static/images/NAX2_01H.png b/hm_web/static/images/NAX2_01H.png new file mode 100644 index 0000000..4919fbe Binary files /dev/null and b/hm_web/static/images/NAX2_01H.png differ diff --git a/hm_web/static/images/NAX2_03.png b/hm_web/static/images/NAX2_03.png new file mode 100644 index 0000000..191f9ea Binary files /dev/null and b/hm_web/static/images/NAX2_03.png differ diff --git a/hm_web/static/images/NAX2_03H.png b/hm_web/static/images/NAX2_03H.png new file mode 100644 index 0000000..33812f5 Binary files /dev/null and b/hm_web/static/images/NAX2_03H.png differ diff --git a/hm_web/static/images/NAX2_05.png b/hm_web/static/images/NAX2_05.png new file mode 100644 index 0000000..29ecb1d Binary files /dev/null and b/hm_web/static/images/NAX2_05.png differ diff --git a/hm_web/static/images/NAX2_05H.png b/hm_web/static/images/NAX2_05H.png new file mode 100644 index 0000000..fceb218 Binary files /dev/null and b/hm_web/static/images/NAX2_05H.png differ diff --git a/hm_web/static/images/NAX3_01.png b/hm_web/static/images/NAX3_01.png new file mode 100644 index 0000000..6d821ad Binary files /dev/null and b/hm_web/static/images/NAX3_01.png differ diff --git a/hm_web/static/images/NAX3_01H.png b/hm_web/static/images/NAX3_01H.png new file mode 100644 index 0000000..5cb8cf4 Binary files /dev/null and b/hm_web/static/images/NAX3_01H.png differ diff --git a/hm_web/static/images/NAX3_02.png b/hm_web/static/images/NAX3_02.png new file mode 100644 index 0000000..f76b200 Binary files /dev/null and b/hm_web/static/images/NAX3_02.png differ diff --git a/hm_web/static/images/NAX3_02H.png b/hm_web/static/images/NAX3_02H.png new file mode 100644 index 0000000..9584e96 Binary files /dev/null and b/hm_web/static/images/NAX3_02H.png differ diff --git a/hm_web/static/images/NAX3_02_TB.png b/hm_web/static/images/NAX3_02_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX3_02_TB.png differ diff --git a/hm_web/static/images/NAX3_03.png b/hm_web/static/images/NAX3_03.png new file mode 100644 index 0000000..567f737 Binary files /dev/null and b/hm_web/static/images/NAX3_03.png differ diff --git a/hm_web/static/images/NAX4_01.png b/hm_web/static/images/NAX4_01.png new file mode 100644 index 0000000..fdd3ece Binary files /dev/null and b/hm_web/static/images/NAX4_01.png differ diff --git a/hm_web/static/images/NAX4_01H.png b/hm_web/static/images/NAX4_01H.png new file mode 100644 index 0000000..12a282e Binary files /dev/null and b/hm_web/static/images/NAX4_01H.png differ diff --git a/hm_web/static/images/NAX4_03.png b/hm_web/static/images/NAX4_03.png new file mode 100644 index 0000000..96b8435 Binary files /dev/null and b/hm_web/static/images/NAX4_03.png differ diff --git a/hm_web/static/images/NAX4_03H.png b/hm_web/static/images/NAX4_03H.png new file mode 100644 index 0000000..33bbed9 Binary files /dev/null and b/hm_web/static/images/NAX4_03H.png differ diff --git a/hm_web/static/images/NAX4_04.png b/hm_web/static/images/NAX4_04.png new file mode 100644 index 0000000..22b7751 Binary files /dev/null and b/hm_web/static/images/NAX4_04.png differ diff --git a/hm_web/static/images/NAX4_04H.png b/hm_web/static/images/NAX4_04H.png new file mode 100644 index 0000000..8702ffc Binary files /dev/null and b/hm_web/static/images/NAX4_04H.png differ diff --git a/hm_web/static/images/NAX4_05.png b/hm_web/static/images/NAX4_05.png new file mode 100644 index 0000000..3ae59b3 Binary files /dev/null and b/hm_web/static/images/NAX4_05.png differ diff --git a/hm_web/static/images/NAX5_01.png b/hm_web/static/images/NAX5_01.png new file mode 100644 index 0000000..8f366ab Binary files /dev/null and b/hm_web/static/images/NAX5_01.png differ diff --git a/hm_web/static/images/NAX5_01H.png b/hm_web/static/images/NAX5_01H.png new file mode 100644 index 0000000..3f29711 Binary files /dev/null and b/hm_web/static/images/NAX5_01H.png differ diff --git a/hm_web/static/images/NAX5_02.png b/hm_web/static/images/NAX5_02.png new file mode 100644 index 0000000..5658e48 Binary files /dev/null and b/hm_web/static/images/NAX5_02.png differ diff --git a/hm_web/static/images/NAX5_02H.png b/hm_web/static/images/NAX5_02H.png new file mode 100644 index 0000000..42671be Binary files /dev/null and b/hm_web/static/images/NAX5_02H.png differ diff --git a/hm_web/static/images/NAX5_03.png b/hm_web/static/images/NAX5_03.png new file mode 100644 index 0000000..336f52c Binary files /dev/null and b/hm_web/static/images/NAX5_03.png differ diff --git a/hm_web/static/images/NAX6_01.png b/hm_web/static/images/NAX6_01.png new file mode 100644 index 0000000..5b25a7e Binary files /dev/null and b/hm_web/static/images/NAX6_01.png differ diff --git a/hm_web/static/images/NAX6_01H.png b/hm_web/static/images/NAX6_01H.png new file mode 100644 index 0000000..c5c1683 Binary files /dev/null and b/hm_web/static/images/NAX6_01H.png differ diff --git a/hm_web/static/images/NAX6_02.png b/hm_web/static/images/NAX6_02.png new file mode 100644 index 0000000..a3d1fbb Binary files /dev/null and b/hm_web/static/images/NAX6_02.png differ diff --git a/hm_web/static/images/NAX6_02H.png b/hm_web/static/images/NAX6_02H.png new file mode 100644 index 0000000..2fb73cc Binary files /dev/null and b/hm_web/static/images/NAX6_02H.png differ diff --git a/hm_web/static/images/NAX6_03.png b/hm_web/static/images/NAX6_03.png new file mode 100644 index 0000000..31e22f1 Binary files /dev/null and b/hm_web/static/images/NAX6_03.png differ diff --git a/hm_web/static/images/NAX6_03t.png b/hm_web/static/images/NAX6_03t.png new file mode 100644 index 0000000..b61a71f Binary files /dev/null and b/hm_web/static/images/NAX6_03t.png differ diff --git a/hm_web/static/images/NAX6_03te.png b/hm_web/static/images/NAX6_03te.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX6_03te.png differ diff --git a/hm_web/static/images/NAX6_04.png b/hm_web/static/images/NAX6_04.png new file mode 100644 index 0000000..fcd1440 Binary files /dev/null and b/hm_web/static/images/NAX6_04.png differ diff --git a/hm_web/static/images/NAX7_01.png b/hm_web/static/images/NAX7_01.png new file mode 100644 index 0000000..6d2c381 Binary files /dev/null and b/hm_web/static/images/NAX7_01.png differ diff --git a/hm_web/static/images/NAX7_01H.png b/hm_web/static/images/NAX7_01H.png new file mode 100644 index 0000000..1a71993 Binary files /dev/null and b/hm_web/static/images/NAX7_01H.png differ diff --git a/hm_web/static/images/NAX7_02.png b/hm_web/static/images/NAX7_02.png new file mode 100644 index 0000000..3ccfcae Binary files /dev/null and b/hm_web/static/images/NAX7_02.png differ diff --git a/hm_web/static/images/NAX7_03.png b/hm_web/static/images/NAX7_03.png new file mode 100644 index 0000000..e1d192b Binary files /dev/null and b/hm_web/static/images/NAX7_03.png differ diff --git a/hm_web/static/images/NAX7_03H.png b/hm_web/static/images/NAX7_03H.png new file mode 100644 index 0000000..89eb4fb Binary files /dev/null and b/hm_web/static/images/NAX7_03H.png differ diff --git a/hm_web/static/images/NAX7_04.png b/hm_web/static/images/NAX7_04.png new file mode 100644 index 0000000..65877c8 Binary files /dev/null and b/hm_web/static/images/NAX7_04.png differ diff --git a/hm_web/static/images/NAX7_04H.png b/hm_web/static/images/NAX7_04H.png new file mode 100644 index 0000000..7febe7f Binary files /dev/null and b/hm_web/static/images/NAX7_04H.png differ diff --git a/hm_web/static/images/NAX7_05.png b/hm_web/static/images/NAX7_05.png new file mode 100644 index 0000000..db87c60 Binary files /dev/null and b/hm_web/static/images/NAX7_05.png differ diff --git a/hm_web/static/images/NAX8_01.png b/hm_web/static/images/NAX8_01.png new file mode 100644 index 0000000..7c20114 Binary files /dev/null and b/hm_web/static/images/NAX8_01.png differ diff --git a/hm_web/static/images/NAX8_01H.png b/hm_web/static/images/NAX8_01H.png new file mode 100644 index 0000000..5d935b3 Binary files /dev/null and b/hm_web/static/images/NAX8_01H.png differ diff --git a/hm_web/static/images/NAX8_02.png b/hm_web/static/images/NAX8_02.png new file mode 100644 index 0000000..d54b63e Binary files /dev/null and b/hm_web/static/images/NAX8_02.png differ diff --git a/hm_web/static/images/NAX8_02H.png b/hm_web/static/images/NAX8_02H.png new file mode 100644 index 0000000..c3d787d Binary files /dev/null and b/hm_web/static/images/NAX8_02H.png differ diff --git a/hm_web/static/images/NAX8_02H_TB.png b/hm_web/static/images/NAX8_02H_TB.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX8_02H_TB.png differ diff --git a/hm_web/static/images/NAX8_03.png b/hm_web/static/images/NAX8_03.png new file mode 100644 index 0000000..fa53184 Binary files /dev/null and b/hm_web/static/images/NAX8_03.png differ diff --git a/hm_web/static/images/NAX8_03t.png b/hm_web/static/images/NAX8_03t.png new file mode 100644 index 0000000..ba3c051 Binary files /dev/null and b/hm_web/static/images/NAX8_03t.png differ diff --git a/hm_web/static/images/NAX8_04.png b/hm_web/static/images/NAX8_04.png new file mode 100644 index 0000000..5bd29e3 Binary files /dev/null and b/hm_web/static/images/NAX8_04.png differ diff --git a/hm_web/static/images/NAX8_04t.png b/hm_web/static/images/NAX8_04t.png new file mode 100644 index 0000000..aa98353 Binary files /dev/null and b/hm_web/static/images/NAX8_04t.png differ diff --git a/hm_web/static/images/NAX8_05.png b/hm_web/static/images/NAX8_05.png new file mode 100644 index 0000000..1f93322 Binary files /dev/null and b/hm_web/static/images/NAX8_05.png differ diff --git a/hm_web/static/images/NAX8_05t.png b/hm_web/static/images/NAX8_05t.png new file mode 100644 index 0000000..658c651 Binary files /dev/null and b/hm_web/static/images/NAX8_05t.png differ diff --git a/hm_web/static/images/NAX9_01.png b/hm_web/static/images/NAX9_01.png new file mode 100644 index 0000000..1cdccac Binary files /dev/null and b/hm_web/static/images/NAX9_01.png differ diff --git a/hm_web/static/images/NAX9_01H.png b/hm_web/static/images/NAX9_01H.png new file mode 100644 index 0000000..e0f096d Binary files /dev/null and b/hm_web/static/images/NAX9_01H.png differ diff --git a/hm_web/static/images/NAX9_02.png b/hm_web/static/images/NAX9_02.png new file mode 100644 index 0000000..460dd86 Binary files /dev/null and b/hm_web/static/images/NAX9_02.png differ diff --git a/hm_web/static/images/NAX9_02H.png b/hm_web/static/images/NAX9_02H.png new file mode 100644 index 0000000..8ac263c Binary files /dev/null and b/hm_web/static/images/NAX9_02H.png differ diff --git a/hm_web/static/images/NAX9_03.png b/hm_web/static/images/NAX9_03.png new file mode 100644 index 0000000..d616946 Binary files /dev/null and b/hm_web/static/images/NAX9_03.png differ diff --git a/hm_web/static/images/NAX9_03H.png b/hm_web/static/images/NAX9_03H.png new file mode 100644 index 0000000..22e9ae7 Binary files /dev/null and b/hm_web/static/images/NAX9_03H.png differ diff --git a/hm_web/static/images/NAX9_04.png b/hm_web/static/images/NAX9_04.png new file mode 100644 index 0000000..5e3e75e Binary files /dev/null and b/hm_web/static/images/NAX9_04.png differ diff --git a/hm_web/static/images/NAX9_04H.png b/hm_web/static/images/NAX9_04H.png new file mode 100644 index 0000000..3791251 Binary files /dev/null and b/hm_web/static/images/NAX9_04H.png differ diff --git a/hm_web/static/images/NAX9_05.png b/hm_web/static/images/NAX9_05.png new file mode 100644 index 0000000..48bcad2 Binary files /dev/null and b/hm_web/static/images/NAX9_05.png differ diff --git a/hm_web/static/images/NAX9_05H.png b/hm_web/static/images/NAX9_05H.png new file mode 100644 index 0000000..42217d1 Binary files /dev/null and b/hm_web/static/images/NAX9_05H.png differ diff --git a/hm_web/static/images/NAX9_06.png b/hm_web/static/images/NAX9_06.png new file mode 100644 index 0000000..319e410 Binary files /dev/null and b/hm_web/static/images/NAX9_06.png differ diff --git a/hm_web/static/images/NAX9_07.png b/hm_web/static/images/NAX9_07.png new file mode 100644 index 0000000..6678258 Binary files /dev/null and b/hm_web/static/images/NAX9_07.png differ diff --git a/hm_web/static/images/NAX9_07e.png b/hm_web/static/images/NAX9_07e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NAX9_07e.png differ diff --git a/hm_web/static/images/NAXM_001.png b/hm_web/static/images/NAXM_001.png new file mode 100644 index 0000000..fc3b34b Binary files /dev/null and b/hm_web/static/images/NAXM_001.png differ diff --git a/hm_web/static/images/NAXM_002.png b/hm_web/static/images/NAXM_002.png new file mode 100644 index 0000000..cad5d4f Binary files /dev/null and b/hm_web/static/images/NAXM_002.png differ diff --git a/hm_web/static/images/NEW1_003.png b/hm_web/static/images/NEW1_003.png new file mode 100644 index 0000000..d3f5f5c Binary files /dev/null and b/hm_web/static/images/NEW1_003.png differ diff --git a/hm_web/static/images/NEW1_004.png b/hm_web/static/images/NEW1_004.png new file mode 100644 index 0000000..89ffd79 Binary files /dev/null and b/hm_web/static/images/NEW1_004.png differ diff --git a/hm_web/static/images/NEW1_005.png b/hm_web/static/images/NEW1_005.png new file mode 100644 index 0000000..f2db3cc Binary files /dev/null and b/hm_web/static/images/NEW1_005.png differ diff --git a/hm_web/static/images/NEW1_007.png b/hm_web/static/images/NEW1_007.png new file mode 100644 index 0000000..4c3741d Binary files /dev/null and b/hm_web/static/images/NEW1_007.png differ diff --git a/hm_web/static/images/NEW1_007a.png b/hm_web/static/images/NEW1_007a.png new file mode 100644 index 0000000..7a731fa Binary files /dev/null and b/hm_web/static/images/NEW1_007a.png differ diff --git a/hm_web/static/images/NEW1_007b.png b/hm_web/static/images/NEW1_007b.png new file mode 100644 index 0000000..2a17b04 Binary files /dev/null and b/hm_web/static/images/NEW1_007b.png differ diff --git a/hm_web/static/images/NEW1_008.png b/hm_web/static/images/NEW1_008.png new file mode 100644 index 0000000..f66d20c Binary files /dev/null and b/hm_web/static/images/NEW1_008.png differ diff --git a/hm_web/static/images/NEW1_008a.png b/hm_web/static/images/NEW1_008a.png new file mode 100644 index 0000000..7d6240a Binary files /dev/null and b/hm_web/static/images/NEW1_008a.png differ diff --git a/hm_web/static/images/NEW1_008b.png b/hm_web/static/images/NEW1_008b.png new file mode 100644 index 0000000..3e5e048 Binary files /dev/null and b/hm_web/static/images/NEW1_008b.png differ diff --git a/hm_web/static/images/NEW1_009.png b/hm_web/static/images/NEW1_009.png new file mode 100644 index 0000000..54f4a63 Binary files /dev/null and b/hm_web/static/images/NEW1_009.png differ diff --git a/hm_web/static/images/NEW1_010.png b/hm_web/static/images/NEW1_010.png new file mode 100644 index 0000000..63985eb Binary files /dev/null and b/hm_web/static/images/NEW1_010.png differ diff --git a/hm_web/static/images/NEW1_011.png b/hm_web/static/images/NEW1_011.png new file mode 100644 index 0000000..680837b Binary files /dev/null and b/hm_web/static/images/NEW1_011.png differ diff --git a/hm_web/static/images/NEW1_012.png b/hm_web/static/images/NEW1_012.png new file mode 100644 index 0000000..6de3a18 Binary files /dev/null and b/hm_web/static/images/NEW1_012.png differ diff --git a/hm_web/static/images/NEW1_012o.png b/hm_web/static/images/NEW1_012o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_012o.png differ diff --git a/hm_web/static/images/NEW1_014.png b/hm_web/static/images/NEW1_014.png new file mode 100644 index 0000000..7ec2b89 Binary files /dev/null and b/hm_web/static/images/NEW1_014.png differ diff --git a/hm_web/static/images/NEW1_014e.png b/hm_web/static/images/NEW1_014e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_014e.png differ diff --git a/hm_web/static/images/NEW1_016.png b/hm_web/static/images/NEW1_016.png new file mode 100644 index 0000000..7d6a3bc Binary files /dev/null and b/hm_web/static/images/NEW1_016.png differ diff --git a/hm_web/static/images/NEW1_017.png b/hm_web/static/images/NEW1_017.png new file mode 100644 index 0000000..c9be16e Binary files /dev/null and b/hm_web/static/images/NEW1_017.png differ diff --git a/hm_web/static/images/NEW1_017e.png b/hm_web/static/images/NEW1_017e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_017e.png differ diff --git a/hm_web/static/images/NEW1_018.png b/hm_web/static/images/NEW1_018.png new file mode 100644 index 0000000..322e3ca Binary files /dev/null and b/hm_web/static/images/NEW1_018.png differ diff --git a/hm_web/static/images/NEW1_018e.png b/hm_web/static/images/NEW1_018e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_018e.png differ diff --git a/hm_web/static/images/NEW1_019.png b/hm_web/static/images/NEW1_019.png new file mode 100644 index 0000000..2721b71 Binary files /dev/null and b/hm_web/static/images/NEW1_019.png differ diff --git a/hm_web/static/images/NEW1_020.png b/hm_web/static/images/NEW1_020.png new file mode 100644 index 0000000..9a8db2f Binary files /dev/null and b/hm_web/static/images/NEW1_020.png differ diff --git a/hm_web/static/images/NEW1_021.png b/hm_web/static/images/NEW1_021.png new file mode 100644 index 0000000..205ba7b Binary files /dev/null and b/hm_web/static/images/NEW1_021.png differ diff --git a/hm_web/static/images/NEW1_022.png b/hm_web/static/images/NEW1_022.png new file mode 100644 index 0000000..0dec42e Binary files /dev/null and b/hm_web/static/images/NEW1_022.png differ diff --git a/hm_web/static/images/NEW1_023.png b/hm_web/static/images/NEW1_023.png new file mode 100644 index 0000000..bee2ba3 Binary files /dev/null and b/hm_web/static/images/NEW1_023.png differ diff --git a/hm_web/static/images/NEW1_024.png b/hm_web/static/images/NEW1_024.png new file mode 100644 index 0000000..0639116 Binary files /dev/null and b/hm_web/static/images/NEW1_024.png differ diff --git a/hm_web/static/images/NEW1_024o.png b/hm_web/static/images/NEW1_024o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_024o.png differ diff --git a/hm_web/static/images/NEW1_025.png b/hm_web/static/images/NEW1_025.png new file mode 100644 index 0000000..157b73f Binary files /dev/null and b/hm_web/static/images/NEW1_025.png differ diff --git a/hm_web/static/images/NEW1_025e.png b/hm_web/static/images/NEW1_025e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_025e.png differ diff --git a/hm_web/static/images/NEW1_026.png b/hm_web/static/images/NEW1_026.png new file mode 100644 index 0000000..7f9f093 Binary files /dev/null and b/hm_web/static/images/NEW1_026.png differ diff --git a/hm_web/static/images/NEW1_026t.png b/hm_web/static/images/NEW1_026t.png new file mode 100644 index 0000000..e6d8ca5 Binary files /dev/null and b/hm_web/static/images/NEW1_026t.png differ diff --git a/hm_web/static/images/NEW1_027.png b/hm_web/static/images/NEW1_027.png new file mode 100644 index 0000000..76a5670 Binary files /dev/null and b/hm_web/static/images/NEW1_027.png differ diff --git a/hm_web/static/images/NEW1_027e.png b/hm_web/static/images/NEW1_027e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_027e.png differ diff --git a/hm_web/static/images/NEW1_029.png b/hm_web/static/images/NEW1_029.png new file mode 100644 index 0000000..7e57482 Binary files /dev/null and b/hm_web/static/images/NEW1_029.png differ diff --git a/hm_web/static/images/NEW1_029t.png b/hm_web/static/images/NEW1_029t.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_029t.png differ diff --git a/hm_web/static/images/NEW1_030.png b/hm_web/static/images/NEW1_030.png new file mode 100644 index 0000000..f5ba8d4 Binary files /dev/null and b/hm_web/static/images/NEW1_030.png differ diff --git a/hm_web/static/images/NEW1_031.png b/hm_web/static/images/NEW1_031.png new file mode 100644 index 0000000..85a7f30 Binary files /dev/null and b/hm_web/static/images/NEW1_031.png differ diff --git a/hm_web/static/images/NEW1_032.png b/hm_web/static/images/NEW1_032.png new file mode 100644 index 0000000..7cef704 Binary files /dev/null and b/hm_web/static/images/NEW1_032.png differ diff --git a/hm_web/static/images/NEW1_033.png b/hm_web/static/images/NEW1_033.png new file mode 100644 index 0000000..01b08a9 Binary files /dev/null and b/hm_web/static/images/NEW1_033.png differ diff --git a/hm_web/static/images/NEW1_033o.png b/hm_web/static/images/NEW1_033o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_033o.png differ diff --git a/hm_web/static/images/NEW1_034.png b/hm_web/static/images/NEW1_034.png new file mode 100644 index 0000000..d4c39ac Binary files /dev/null and b/hm_web/static/images/NEW1_034.png differ diff --git a/hm_web/static/images/NEW1_036.png b/hm_web/static/images/NEW1_036.png new file mode 100644 index 0000000..08155af Binary files /dev/null and b/hm_web/static/images/NEW1_036.png differ diff --git a/hm_web/static/images/NEW1_036e.png b/hm_web/static/images/NEW1_036e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_036e.png differ diff --git a/hm_web/static/images/NEW1_036e2.png b/hm_web/static/images/NEW1_036e2.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_036e2.png differ diff --git a/hm_web/static/images/NEW1_037.png b/hm_web/static/images/NEW1_037.png new file mode 100644 index 0000000..1440207 Binary files /dev/null and b/hm_web/static/images/NEW1_037.png differ diff --git a/hm_web/static/images/NEW1_037e.png b/hm_web/static/images/NEW1_037e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_037e.png differ diff --git a/hm_web/static/images/NEW1_038.png b/hm_web/static/images/NEW1_038.png new file mode 100644 index 0000000..5abdf57 Binary files /dev/null and b/hm_web/static/images/NEW1_038.png differ diff --git a/hm_web/static/images/NEW1_038o.png b/hm_web/static/images/NEW1_038o.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/NEW1_038o.png differ diff --git a/hm_web/static/images/NEW1_040.png b/hm_web/static/images/NEW1_040.png new file mode 100644 index 0000000..c36cc76 Binary files /dev/null and b/hm_web/static/images/NEW1_040.png differ diff --git a/hm_web/static/images/NEW1_040t.png b/hm_web/static/images/NEW1_040t.png new file mode 100644 index 0000000..079ad4e Binary files /dev/null and b/hm_web/static/images/NEW1_040t.png differ diff --git a/hm_web/static/images/NEW1_041.png b/hm_web/static/images/NEW1_041.png new file mode 100644 index 0000000..2676136 Binary files /dev/null and b/hm_web/static/images/NEW1_041.png differ diff --git a/hm_web/static/images/OG_006.png b/hm_web/static/images/OG_006.png new file mode 100644 index 0000000..f08e906 Binary files /dev/null and b/hm_web/static/images/OG_006.png differ diff --git a/hm_web/static/images/OG_006a.png b/hm_web/static/images/OG_006a.png new file mode 100644 index 0000000..3afec5b Binary files /dev/null and b/hm_web/static/images/OG_006a.png differ diff --git a/hm_web/static/images/OG_006b.png b/hm_web/static/images/OG_006b.png new file mode 100644 index 0000000..d550992 Binary files /dev/null and b/hm_web/static/images/OG_006b.png differ diff --git a/hm_web/static/images/OG_023.png b/hm_web/static/images/OG_023.png new file mode 100644 index 0000000..2c37aa7 Binary files /dev/null and b/hm_web/static/images/OG_023.png differ diff --git a/hm_web/static/images/OG_023t.png b/hm_web/static/images/OG_023t.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_023t.png differ diff --git a/hm_web/static/images/OG_024.png b/hm_web/static/images/OG_024.png new file mode 100644 index 0000000..f29bfcc Binary files /dev/null and b/hm_web/static/images/OG_024.png differ diff --git a/hm_web/static/images/OG_026.png b/hm_web/static/images/OG_026.png new file mode 100644 index 0000000..7a01d6d Binary files /dev/null and b/hm_web/static/images/OG_026.png differ diff --git a/hm_web/static/images/OG_027.png b/hm_web/static/images/OG_027.png new file mode 100644 index 0000000..4cae458 Binary files /dev/null and b/hm_web/static/images/OG_027.png differ diff --git a/hm_web/static/images/OG_028.png b/hm_web/static/images/OG_028.png new file mode 100644 index 0000000..a7cc199 Binary files /dev/null and b/hm_web/static/images/OG_028.png differ diff --git a/hm_web/static/images/OG_031.png b/hm_web/static/images/OG_031.png new file mode 100644 index 0000000..5237bea Binary files /dev/null and b/hm_web/static/images/OG_031.png differ diff --git a/hm_web/static/images/OG_031a.png b/hm_web/static/images/OG_031a.png new file mode 100644 index 0000000..57236a1 Binary files /dev/null and b/hm_web/static/images/OG_031a.png differ diff --git a/hm_web/static/images/OG_033.png b/hm_web/static/images/OG_033.png new file mode 100644 index 0000000..7f2547c Binary files /dev/null and b/hm_web/static/images/OG_033.png differ diff --git a/hm_web/static/images/OG_034.png b/hm_web/static/images/OG_034.png new file mode 100644 index 0000000..0344ee2 Binary files /dev/null and b/hm_web/static/images/OG_034.png differ diff --git a/hm_web/static/images/OG_042.png b/hm_web/static/images/OG_042.png new file mode 100644 index 0000000..394cb73 Binary files /dev/null and b/hm_web/static/images/OG_042.png differ diff --git a/hm_web/static/images/OG_044.png b/hm_web/static/images/OG_044.png new file mode 100644 index 0000000..60987df Binary files /dev/null and b/hm_web/static/images/OG_044.png differ diff --git a/hm_web/static/images/OG_044a.png b/hm_web/static/images/OG_044a.png new file mode 100644 index 0000000..4c47a7e Binary files /dev/null and b/hm_web/static/images/OG_044a.png differ diff --git a/hm_web/static/images/OG_044b.png b/hm_web/static/images/OG_044b.png new file mode 100644 index 0000000..ac9c1c1 Binary files /dev/null and b/hm_web/static/images/OG_044b.png differ diff --git a/hm_web/static/images/OG_044c.png b/hm_web/static/images/OG_044c.png new file mode 100644 index 0000000..1169b6c Binary files /dev/null and b/hm_web/static/images/OG_044c.png differ diff --git a/hm_web/static/images/OG_045.png b/hm_web/static/images/OG_045.png new file mode 100644 index 0000000..887c6f4 Binary files /dev/null and b/hm_web/static/images/OG_045.png differ diff --git a/hm_web/static/images/OG_045a.png b/hm_web/static/images/OG_045a.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_045a.png differ diff --git a/hm_web/static/images/OG_047.png b/hm_web/static/images/OG_047.png new file mode 100644 index 0000000..d446b68 Binary files /dev/null and b/hm_web/static/images/OG_047.png differ diff --git a/hm_web/static/images/OG_047a.png b/hm_web/static/images/OG_047a.png new file mode 100644 index 0000000..6d5d5cb Binary files /dev/null and b/hm_web/static/images/OG_047a.png differ diff --git a/hm_web/static/images/OG_047b.png b/hm_web/static/images/OG_047b.png new file mode 100644 index 0000000..dfe1164 Binary files /dev/null and b/hm_web/static/images/OG_047b.png differ diff --git a/hm_web/static/images/OG_047e.png b/hm_web/static/images/OG_047e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_047e.png differ diff --git a/hm_web/static/images/OG_048.png b/hm_web/static/images/OG_048.png new file mode 100644 index 0000000..3ea9738 Binary files /dev/null and b/hm_web/static/images/OG_048.png differ diff --git a/hm_web/static/images/OG_048e.png b/hm_web/static/images/OG_048e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_048e.png differ diff --git a/hm_web/static/images/OG_051.png b/hm_web/static/images/OG_051.png new file mode 100644 index 0000000..df2a45b Binary files /dev/null and b/hm_web/static/images/OG_051.png differ diff --git a/hm_web/static/images/OG_051e.png b/hm_web/static/images/OG_051e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_051e.png differ diff --git a/hm_web/static/images/OG_058.png b/hm_web/static/images/OG_058.png new file mode 100644 index 0000000..438fb07 Binary files /dev/null and b/hm_web/static/images/OG_058.png differ diff --git a/hm_web/static/images/OG_061.png b/hm_web/static/images/OG_061.png new file mode 100644 index 0000000..c103901 Binary files /dev/null and b/hm_web/static/images/OG_061.png differ diff --git a/hm_web/static/images/OG_061t.png b/hm_web/static/images/OG_061t.png new file mode 100644 index 0000000..b21b599 Binary files /dev/null and b/hm_web/static/images/OG_061t.png differ diff --git a/hm_web/static/images/OG_070.png b/hm_web/static/images/OG_070.png new file mode 100644 index 0000000..3d6ab4e Binary files /dev/null and b/hm_web/static/images/OG_070.png differ diff --git a/hm_web/static/images/OG_070e.png b/hm_web/static/images/OG_070e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_070e.png differ diff --git a/hm_web/static/images/OG_072.png b/hm_web/static/images/OG_072.png new file mode 100644 index 0000000..040e341 Binary files /dev/null and b/hm_web/static/images/OG_072.png differ diff --git a/hm_web/static/images/OG_073.png b/hm_web/static/images/OG_073.png new file mode 100644 index 0000000..526b176 Binary files /dev/null and b/hm_web/static/images/OG_073.png differ diff --git a/hm_web/static/images/OG_080.png b/hm_web/static/images/OG_080.png new file mode 100644 index 0000000..86567b1 Binary files /dev/null and b/hm_web/static/images/OG_080.png differ diff --git a/hm_web/static/images/OG_080ae.png b/hm_web/static/images/OG_080ae.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_080ae.png differ diff --git a/hm_web/static/images/OG_080b.png b/hm_web/static/images/OG_080b.png new file mode 100644 index 0000000..4d47253 Binary files /dev/null and b/hm_web/static/images/OG_080b.png differ diff --git a/hm_web/static/images/OG_080c.png b/hm_web/static/images/OG_080c.png new file mode 100644 index 0000000..02a168f Binary files /dev/null and b/hm_web/static/images/OG_080c.png differ diff --git a/hm_web/static/images/OG_080d.png b/hm_web/static/images/OG_080d.png new file mode 100644 index 0000000..a1776c2 Binary files /dev/null and b/hm_web/static/images/OG_080d.png differ diff --git a/hm_web/static/images/OG_080de.png b/hm_web/static/images/OG_080de.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_080de.png differ diff --git a/hm_web/static/images/OG_080e.png b/hm_web/static/images/OG_080e.png new file mode 100644 index 0000000..3b827de Binary files /dev/null and b/hm_web/static/images/OG_080e.png differ diff --git a/hm_web/static/images/OG_080ee.png b/hm_web/static/images/OG_080ee.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_080ee.png differ diff --git a/hm_web/static/images/OG_080f.png b/hm_web/static/images/OG_080f.png new file mode 100644 index 0000000..f9a5b3e Binary files /dev/null and b/hm_web/static/images/OG_080f.png differ diff --git a/hm_web/static/images/OG_081.png b/hm_web/static/images/OG_081.png new file mode 100644 index 0000000..df7b0cf Binary files /dev/null and b/hm_web/static/images/OG_081.png differ diff --git a/hm_web/static/images/OG_082.png b/hm_web/static/images/OG_082.png new file mode 100644 index 0000000..2b46da6 Binary files /dev/null and b/hm_web/static/images/OG_082.png differ diff --git a/hm_web/static/images/OG_083.png b/hm_web/static/images/OG_083.png new file mode 100644 index 0000000..31bd997 Binary files /dev/null and b/hm_web/static/images/OG_083.png differ diff --git a/hm_web/static/images/OG_085.png b/hm_web/static/images/OG_085.png new file mode 100644 index 0000000..c812582 Binary files /dev/null and b/hm_web/static/images/OG_085.png differ diff --git a/hm_web/static/images/OG_086.png b/hm_web/static/images/OG_086.png new file mode 100644 index 0000000..ae6b7f7 Binary files /dev/null and b/hm_web/static/images/OG_086.png differ diff --git a/hm_web/static/images/OG_087.png b/hm_web/static/images/OG_087.png new file mode 100644 index 0000000..85e7ba9 Binary files /dev/null and b/hm_web/static/images/OG_087.png differ diff --git a/hm_web/static/images/OG_090.png b/hm_web/static/images/OG_090.png new file mode 100644 index 0000000..4c514c8 Binary files /dev/null and b/hm_web/static/images/OG_090.png differ diff --git a/hm_web/static/images/OG_094.png b/hm_web/static/images/OG_094.png new file mode 100644 index 0000000..ab4e9e1 Binary files /dev/null and b/hm_web/static/images/OG_094.png differ diff --git a/hm_web/static/images/OG_094e.png b/hm_web/static/images/OG_094e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_094e.png differ diff --git a/hm_web/static/images/OG_096.png b/hm_web/static/images/OG_096.png new file mode 100644 index 0000000..fc83fb4 Binary files /dev/null and b/hm_web/static/images/OG_096.png differ diff --git a/hm_web/static/images/OG_100.png b/hm_web/static/images/OG_100.png new file mode 100644 index 0000000..012ede8 Binary files /dev/null and b/hm_web/static/images/OG_100.png differ diff --git a/hm_web/static/images/OG_101.png b/hm_web/static/images/OG_101.png new file mode 100644 index 0000000..9860679 Binary files /dev/null and b/hm_web/static/images/OG_101.png differ diff --git a/hm_web/static/images/OG_102.png b/hm_web/static/images/OG_102.png new file mode 100644 index 0000000..fd18763 Binary files /dev/null and b/hm_web/static/images/OG_102.png differ diff --git a/hm_web/static/images/OG_102e.png b/hm_web/static/images/OG_102e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_102e.png differ diff --git a/hm_web/static/images/OG_104.png b/hm_web/static/images/OG_104.png new file mode 100644 index 0000000..579841e Binary files /dev/null and b/hm_web/static/images/OG_104.png differ diff --git a/hm_web/static/images/OG_104e.png b/hm_web/static/images/OG_104e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_104e.png differ diff --git a/hm_web/static/images/OG_109.png b/hm_web/static/images/OG_109.png new file mode 100644 index 0000000..0b7fd71 Binary files /dev/null and b/hm_web/static/images/OG_109.png differ diff --git a/hm_web/static/images/OG_113.png b/hm_web/static/images/OG_113.png new file mode 100644 index 0000000..1c8d048 Binary files /dev/null and b/hm_web/static/images/OG_113.png differ diff --git a/hm_web/static/images/OG_113e.png b/hm_web/static/images/OG_113e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_113e.png differ diff --git a/hm_web/static/images/OG_114.png b/hm_web/static/images/OG_114.png new file mode 100644 index 0000000..f193740 Binary files /dev/null and b/hm_web/static/images/OG_114.png differ diff --git a/hm_web/static/images/OG_114a.png b/hm_web/static/images/OG_114a.png new file mode 100644 index 0000000..3d40c1f Binary files /dev/null and b/hm_web/static/images/OG_114a.png differ diff --git a/hm_web/static/images/OG_116.png b/hm_web/static/images/OG_116.png new file mode 100644 index 0000000..1e83fc4 Binary files /dev/null and b/hm_web/static/images/OG_116.png differ diff --git a/hm_web/static/images/OG_118.png b/hm_web/static/images/OG_118.png new file mode 100644 index 0000000..437ee2b Binary files /dev/null and b/hm_web/static/images/OG_118.png differ diff --git a/hm_web/static/images/OG_118e.png b/hm_web/static/images/OG_118e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_118e.png differ diff --git a/hm_web/static/images/OG_118f.png b/hm_web/static/images/OG_118f.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_118f.png differ diff --git a/hm_web/static/images/OG_120.png b/hm_web/static/images/OG_120.png new file mode 100644 index 0000000..e34c9cb Binary files /dev/null and b/hm_web/static/images/OG_120.png differ diff --git a/hm_web/static/images/OG_121.png b/hm_web/static/images/OG_121.png new file mode 100644 index 0000000..a7c57ee Binary files /dev/null and b/hm_web/static/images/OG_121.png differ diff --git a/hm_web/static/images/OG_121e.png b/hm_web/static/images/OG_121e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_121e.png differ diff --git a/hm_web/static/images/OG_122.png b/hm_web/static/images/OG_122.png new file mode 100644 index 0000000..7d32183 Binary files /dev/null and b/hm_web/static/images/OG_122.png differ diff --git a/hm_web/static/images/OG_123.png b/hm_web/static/images/OG_123.png new file mode 100644 index 0000000..09b6a3b Binary files /dev/null and b/hm_web/static/images/OG_123.png differ diff --git a/hm_web/static/images/OG_123e.png b/hm_web/static/images/OG_123e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_123e.png differ diff --git a/hm_web/static/images/OG_131.png b/hm_web/static/images/OG_131.png new file mode 100644 index 0000000..5e11af4 Binary files /dev/null and b/hm_web/static/images/OG_131.png differ diff --git a/hm_web/static/images/OG_133.png b/hm_web/static/images/OG_133.png new file mode 100644 index 0000000..f9b939a Binary files /dev/null and b/hm_web/static/images/OG_133.png differ diff --git a/hm_web/static/images/OG_134.png b/hm_web/static/images/OG_134.png new file mode 100644 index 0000000..21c179b Binary files /dev/null and b/hm_web/static/images/OG_134.png differ diff --git a/hm_web/static/images/OG_138.png b/hm_web/static/images/OG_138.png new file mode 100644 index 0000000..ce7ebfc Binary files /dev/null and b/hm_web/static/images/OG_138.png differ diff --git a/hm_web/static/images/OG_138e.png b/hm_web/static/images/OG_138e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_138e.png differ diff --git a/hm_web/static/images/OG_141.png b/hm_web/static/images/OG_141.png new file mode 100644 index 0000000..006ff75 Binary files /dev/null and b/hm_web/static/images/OG_141.png differ diff --git a/hm_web/static/images/OG_142.png b/hm_web/static/images/OG_142.png new file mode 100644 index 0000000..2048ebe Binary files /dev/null and b/hm_web/static/images/OG_142.png differ diff --git a/hm_web/static/images/OG_145.png b/hm_web/static/images/OG_145.png new file mode 100644 index 0000000..4e5a9f0 Binary files /dev/null and b/hm_web/static/images/OG_145.png differ diff --git a/hm_web/static/images/OG_147.png b/hm_web/static/images/OG_147.png new file mode 100644 index 0000000..39bb0df Binary files /dev/null and b/hm_web/static/images/OG_147.png differ diff --git a/hm_web/static/images/OG_149.png b/hm_web/static/images/OG_149.png new file mode 100644 index 0000000..efbab60 Binary files /dev/null and b/hm_web/static/images/OG_149.png differ diff --git a/hm_web/static/images/OG_150.png b/hm_web/static/images/OG_150.png new file mode 100644 index 0000000..dbf8ab8 Binary files /dev/null and b/hm_web/static/images/OG_150.png differ diff --git a/hm_web/static/images/OG_150e.png b/hm_web/static/images/OG_150e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_150e.png differ diff --git a/hm_web/static/images/OG_151.png b/hm_web/static/images/OG_151.png new file mode 100644 index 0000000..a773d76 Binary files /dev/null and b/hm_web/static/images/OG_151.png differ diff --git a/hm_web/static/images/OG_152.png b/hm_web/static/images/OG_152.png new file mode 100644 index 0000000..e6ceca5 Binary files /dev/null and b/hm_web/static/images/OG_152.png differ diff --git a/hm_web/static/images/OG_153.png b/hm_web/static/images/OG_153.png new file mode 100644 index 0000000..a72e7d8 Binary files /dev/null and b/hm_web/static/images/OG_153.png differ diff --git a/hm_web/static/images/OG_156.png b/hm_web/static/images/OG_156.png new file mode 100644 index 0000000..a90843a Binary files /dev/null and b/hm_web/static/images/OG_156.png differ diff --git a/hm_web/static/images/OG_156a.png b/hm_web/static/images/OG_156a.png new file mode 100644 index 0000000..3191397 Binary files /dev/null and b/hm_web/static/images/OG_156a.png differ diff --git a/hm_web/static/images/OG_158.png b/hm_web/static/images/OG_158.png new file mode 100644 index 0000000..f40b055 Binary files /dev/null and b/hm_web/static/images/OG_158.png differ diff --git a/hm_web/static/images/OG_158e.png b/hm_web/static/images/OG_158e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_158e.png differ diff --git a/hm_web/static/images/OG_161.png b/hm_web/static/images/OG_161.png new file mode 100644 index 0000000..ab4eb73 Binary files /dev/null and b/hm_web/static/images/OG_161.png differ diff --git a/hm_web/static/images/OG_162.png b/hm_web/static/images/OG_162.png new file mode 100644 index 0000000..80a2201 Binary files /dev/null and b/hm_web/static/images/OG_162.png differ diff --git a/hm_web/static/images/OG_173.png b/hm_web/static/images/OG_173.png new file mode 100644 index 0000000..7fb1f77 Binary files /dev/null and b/hm_web/static/images/OG_173.png differ diff --git a/hm_web/static/images/OG_173a.png b/hm_web/static/images/OG_173a.png new file mode 100644 index 0000000..25abf56 Binary files /dev/null and b/hm_web/static/images/OG_173a.png differ diff --git a/hm_web/static/images/OG_174.png b/hm_web/static/images/OG_174.png new file mode 100644 index 0000000..fa001d3 Binary files /dev/null and b/hm_web/static/images/OG_174.png differ diff --git a/hm_web/static/images/OG_174e.png b/hm_web/static/images/OG_174e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_174e.png differ diff --git a/hm_web/static/images/OG_176.png b/hm_web/static/images/OG_176.png new file mode 100644 index 0000000..5c1c96e Binary files /dev/null and b/hm_web/static/images/OG_176.png differ diff --git a/hm_web/static/images/OG_179.png b/hm_web/static/images/OG_179.png new file mode 100644 index 0000000..412efac Binary files /dev/null and b/hm_web/static/images/OG_179.png differ diff --git a/hm_web/static/images/OG_188.png b/hm_web/static/images/OG_188.png new file mode 100644 index 0000000..807efb3 Binary files /dev/null and b/hm_web/static/images/OG_188.png differ diff --git a/hm_web/static/images/OG_188e.png b/hm_web/static/images/OG_188e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_188e.png differ diff --git a/hm_web/static/images/OG_195.png b/hm_web/static/images/OG_195.png new file mode 100644 index 0000000..a752dc0 Binary files /dev/null and b/hm_web/static/images/OG_195.png differ diff --git a/hm_web/static/images/OG_195a.png b/hm_web/static/images/OG_195a.png new file mode 100644 index 0000000..615360c Binary files /dev/null and b/hm_web/static/images/OG_195a.png differ diff --git a/hm_web/static/images/OG_195b.png b/hm_web/static/images/OG_195b.png new file mode 100644 index 0000000..d45789f Binary files /dev/null and b/hm_web/static/images/OG_195b.png differ diff --git a/hm_web/static/images/OG_195c.png b/hm_web/static/images/OG_195c.png new file mode 100644 index 0000000..e720aae Binary files /dev/null and b/hm_web/static/images/OG_195c.png differ diff --git a/hm_web/static/images/OG_195e.png b/hm_web/static/images/OG_195e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_195e.png differ diff --git a/hm_web/static/images/OG_198.png b/hm_web/static/images/OG_198.png new file mode 100644 index 0000000..bed2360 Binary files /dev/null and b/hm_web/static/images/OG_198.png differ diff --git a/hm_web/static/images/OG_200.png b/hm_web/static/images/OG_200.png new file mode 100644 index 0000000..65bf576 Binary files /dev/null and b/hm_web/static/images/OG_200.png differ diff --git a/hm_web/static/images/OG_200e.png b/hm_web/static/images/OG_200e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_200e.png differ diff --git a/hm_web/static/images/OG_202.png b/hm_web/static/images/OG_202.png new file mode 100644 index 0000000..92b9909 Binary files /dev/null and b/hm_web/static/images/OG_202.png differ diff --git a/hm_web/static/images/OG_202a.png b/hm_web/static/images/OG_202a.png new file mode 100644 index 0000000..4ff39ec Binary files /dev/null and b/hm_web/static/images/OG_202a.png differ diff --git a/hm_web/static/images/OG_202ae.png b/hm_web/static/images/OG_202ae.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_202ae.png differ diff --git a/hm_web/static/images/OG_202b.png b/hm_web/static/images/OG_202b.png new file mode 100644 index 0000000..b386e6e Binary files /dev/null and b/hm_web/static/images/OG_202b.png differ diff --git a/hm_web/static/images/OG_202c.png b/hm_web/static/images/OG_202c.png new file mode 100644 index 0000000..aa531c2 Binary files /dev/null and b/hm_web/static/images/OG_202c.png differ diff --git a/hm_web/static/images/OG_206.png b/hm_web/static/images/OG_206.png new file mode 100644 index 0000000..58454cc Binary files /dev/null and b/hm_web/static/images/OG_206.png differ diff --git a/hm_web/static/images/OG_207.png b/hm_web/static/images/OG_207.png new file mode 100644 index 0000000..3863c4c Binary files /dev/null and b/hm_web/static/images/OG_207.png differ diff --git a/hm_web/static/images/OG_209.png b/hm_web/static/images/OG_209.png new file mode 100644 index 0000000..a010b93 Binary files /dev/null and b/hm_web/static/images/OG_209.png differ diff --git a/hm_web/static/images/OG_211.png b/hm_web/static/images/OG_211.png new file mode 100644 index 0000000..0f6fbbf Binary files /dev/null and b/hm_web/static/images/OG_211.png differ diff --git a/hm_web/static/images/OG_216.png b/hm_web/static/images/OG_216.png new file mode 100644 index 0000000..f6517ff Binary files /dev/null and b/hm_web/static/images/OG_216.png differ diff --git a/hm_web/static/images/OG_216a.png b/hm_web/static/images/OG_216a.png new file mode 100644 index 0000000..d35dc32 Binary files /dev/null and b/hm_web/static/images/OG_216a.png differ diff --git a/hm_web/static/images/OG_218.png b/hm_web/static/images/OG_218.png new file mode 100644 index 0000000..51ebc68 Binary files /dev/null and b/hm_web/static/images/OG_218.png differ diff --git a/hm_web/static/images/OG_218e.png b/hm_web/static/images/OG_218e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_218e.png differ diff --git a/hm_web/static/images/OG_220.png b/hm_web/static/images/OG_220.png new file mode 100644 index 0000000..e331932 Binary files /dev/null and b/hm_web/static/images/OG_220.png differ diff --git a/hm_web/static/images/OG_221.png b/hm_web/static/images/OG_221.png new file mode 100644 index 0000000..157f497 Binary files /dev/null and b/hm_web/static/images/OG_221.png differ diff --git a/hm_web/static/images/OG_222.png b/hm_web/static/images/OG_222.png new file mode 100644 index 0000000..59e8f59 Binary files /dev/null and b/hm_web/static/images/OG_222.png differ diff --git a/hm_web/static/images/OG_222e.png b/hm_web/static/images/OG_222e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_222e.png differ diff --git a/hm_web/static/images/OG_223.png b/hm_web/static/images/OG_223.png new file mode 100644 index 0000000..c8565f8 Binary files /dev/null and b/hm_web/static/images/OG_223.png differ diff --git a/hm_web/static/images/OG_223e.png b/hm_web/static/images/OG_223e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_223e.png differ diff --git a/hm_web/static/images/OG_229.png b/hm_web/static/images/OG_229.png new file mode 100644 index 0000000..4cf5460 Binary files /dev/null and b/hm_web/static/images/OG_229.png differ diff --git a/hm_web/static/images/OG_234.png b/hm_web/static/images/OG_234.png new file mode 100644 index 0000000..6c84948 Binary files /dev/null and b/hm_web/static/images/OG_234.png differ diff --git a/hm_web/static/images/OG_239.png b/hm_web/static/images/OG_239.png new file mode 100644 index 0000000..612b556 Binary files /dev/null and b/hm_web/static/images/OG_239.png differ diff --git a/hm_web/static/images/OG_241.png b/hm_web/static/images/OG_241.png new file mode 100644 index 0000000..83bd03d Binary files /dev/null and b/hm_web/static/images/OG_241.png differ diff --git a/hm_web/static/images/OG_241a.png b/hm_web/static/images/OG_241a.png new file mode 100644 index 0000000..d3e2f3e Binary files /dev/null and b/hm_web/static/images/OG_241a.png differ diff --git a/hm_web/static/images/OG_247.png b/hm_web/static/images/OG_247.png new file mode 100644 index 0000000..8721391 Binary files /dev/null and b/hm_web/static/images/OG_247.png differ diff --git a/hm_web/static/images/OG_248.png b/hm_web/static/images/OG_248.png new file mode 100644 index 0000000..b83defc Binary files /dev/null and b/hm_web/static/images/OG_248.png differ diff --git a/hm_web/static/images/OG_249.png b/hm_web/static/images/OG_249.png new file mode 100644 index 0000000..32dd3c3 Binary files /dev/null and b/hm_web/static/images/OG_249.png differ diff --git a/hm_web/static/images/OG_249a.png b/hm_web/static/images/OG_249a.png new file mode 100644 index 0000000..a48ed46 Binary files /dev/null and b/hm_web/static/images/OG_249a.png differ diff --git a/hm_web/static/images/OG_254.png b/hm_web/static/images/OG_254.png new file mode 100644 index 0000000..9064c07 Binary files /dev/null and b/hm_web/static/images/OG_254.png differ diff --git a/hm_web/static/images/OG_254e.png b/hm_web/static/images/OG_254e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_254e.png differ diff --git a/hm_web/static/images/OG_255.png b/hm_web/static/images/OG_255.png new file mode 100644 index 0000000..b8cc666 Binary files /dev/null and b/hm_web/static/images/OG_255.png differ diff --git a/hm_web/static/images/OG_256.png b/hm_web/static/images/OG_256.png new file mode 100644 index 0000000..00516c4 Binary files /dev/null and b/hm_web/static/images/OG_256.png differ diff --git a/hm_web/static/images/OG_256e.png b/hm_web/static/images/OG_256e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_256e.png differ diff --git a/hm_web/static/images/OG_267.png b/hm_web/static/images/OG_267.png new file mode 100644 index 0000000..12bdf17 Binary files /dev/null and b/hm_web/static/images/OG_267.png differ diff --git a/hm_web/static/images/OG_267e.png b/hm_web/static/images/OG_267e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_267e.png differ diff --git a/hm_web/static/images/OG_270a.png b/hm_web/static/images/OG_270a.png new file mode 100644 index 0000000..b39b1c2 Binary files /dev/null and b/hm_web/static/images/OG_270a.png differ diff --git a/hm_web/static/images/OG_271.png b/hm_web/static/images/OG_271.png new file mode 100644 index 0000000..b7a7be2 Binary files /dev/null and b/hm_web/static/images/OG_271.png differ diff --git a/hm_web/static/images/OG_271e.png b/hm_web/static/images/OG_271e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_271e.png differ diff --git a/hm_web/static/images/OG_272.png b/hm_web/static/images/OG_272.png new file mode 100644 index 0000000..28552a5 Binary files /dev/null and b/hm_web/static/images/OG_272.png differ diff --git a/hm_web/static/images/OG_272t.png b/hm_web/static/images/OG_272t.png new file mode 100644 index 0000000..1109741 Binary files /dev/null and b/hm_web/static/images/OG_272t.png differ diff --git a/hm_web/static/images/OG_273.png b/hm_web/static/images/OG_273.png new file mode 100644 index 0000000..c3c1bc0 Binary files /dev/null and b/hm_web/static/images/OG_273.png differ diff --git a/hm_web/static/images/OG_276.png b/hm_web/static/images/OG_276.png new file mode 100644 index 0000000..21d4804 Binary files /dev/null and b/hm_web/static/images/OG_276.png differ diff --git a/hm_web/static/images/OG_279.png b/hm_web/static/images/OG_279.png new file mode 100644 index 0000000..b428a9e Binary files /dev/null and b/hm_web/static/images/OG_279.png differ diff --git a/hm_web/static/images/OG_280.png b/hm_web/static/images/OG_280.png new file mode 100644 index 0000000..8a31749 Binary files /dev/null and b/hm_web/static/images/OG_280.png differ diff --git a/hm_web/static/images/OG_281.png b/hm_web/static/images/OG_281.png new file mode 100644 index 0000000..0948947 Binary files /dev/null and b/hm_web/static/images/OG_281.png differ diff --git a/hm_web/static/images/OG_281e.png b/hm_web/static/images/OG_281e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_281e.png differ diff --git a/hm_web/static/images/OG_282.png b/hm_web/static/images/OG_282.png new file mode 100644 index 0000000..1e2b718 Binary files /dev/null and b/hm_web/static/images/OG_282.png differ diff --git a/hm_web/static/images/OG_282e.png b/hm_web/static/images/OG_282e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_282e.png differ diff --git a/hm_web/static/images/OG_283.png b/hm_web/static/images/OG_283.png new file mode 100644 index 0000000..848e9e0 Binary files /dev/null and b/hm_web/static/images/OG_283.png differ diff --git a/hm_web/static/images/OG_284.png b/hm_web/static/images/OG_284.png new file mode 100644 index 0000000..0221cb7 Binary files /dev/null and b/hm_web/static/images/OG_284.png differ diff --git a/hm_web/static/images/OG_284e.png b/hm_web/static/images/OG_284e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_284e.png differ diff --git a/hm_web/static/images/OG_286.png b/hm_web/static/images/OG_286.png new file mode 100644 index 0000000..ad5baee Binary files /dev/null and b/hm_web/static/images/OG_286.png differ diff --git a/hm_web/static/images/OG_290.png b/hm_web/static/images/OG_290.png new file mode 100644 index 0000000..8026bcf Binary files /dev/null and b/hm_web/static/images/OG_290.png differ diff --git a/hm_web/static/images/OG_290e.png b/hm_web/static/images/OG_290e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_290e.png differ diff --git a/hm_web/static/images/OG_291.png b/hm_web/static/images/OG_291.png new file mode 100644 index 0000000..a30bb67 Binary files /dev/null and b/hm_web/static/images/OG_291.png differ diff --git a/hm_web/static/images/OG_291e.png b/hm_web/static/images/OG_291e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_291e.png differ diff --git a/hm_web/static/images/OG_292.png b/hm_web/static/images/OG_292.png new file mode 100644 index 0000000..4735e21 Binary files /dev/null and b/hm_web/static/images/OG_292.png differ diff --git a/hm_web/static/images/OG_292e.png b/hm_web/static/images/OG_292e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_292e.png differ diff --git a/hm_web/static/images/OG_293.png b/hm_web/static/images/OG_293.png new file mode 100644 index 0000000..e206ef7 Binary files /dev/null and b/hm_web/static/images/OG_293.png differ diff --git a/hm_web/static/images/OG_293e.png b/hm_web/static/images/OG_293e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_293e.png differ diff --git a/hm_web/static/images/OG_293f.png b/hm_web/static/images/OG_293f.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_293f.png differ diff --git a/hm_web/static/images/OG_295.png b/hm_web/static/images/OG_295.png new file mode 100644 index 0000000..9cb5e51 Binary files /dev/null and b/hm_web/static/images/OG_295.png differ diff --git a/hm_web/static/images/OG_300.png b/hm_web/static/images/OG_300.png new file mode 100644 index 0000000..d6141d4 Binary files /dev/null and b/hm_web/static/images/OG_300.png differ diff --git a/hm_web/static/images/OG_300e.png b/hm_web/static/images/OG_300e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_300e.png differ diff --git a/hm_web/static/images/OG_301.png b/hm_web/static/images/OG_301.png new file mode 100644 index 0000000..db9215e Binary files /dev/null and b/hm_web/static/images/OG_301.png differ diff --git a/hm_web/static/images/OG_302.png b/hm_web/static/images/OG_302.png new file mode 100644 index 0000000..3a7895c Binary files /dev/null and b/hm_web/static/images/OG_302.png differ diff --git a/hm_web/static/images/OG_302e.png b/hm_web/static/images/OG_302e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_302e.png differ diff --git a/hm_web/static/images/OG_303.png b/hm_web/static/images/OG_303.png new file mode 100644 index 0000000..75d5b90 Binary files /dev/null and b/hm_web/static/images/OG_303.png differ diff --git a/hm_web/static/images/OG_303e.png b/hm_web/static/images/OG_303e.png new file mode 100644 index 0000000..a81a4db Binary files /dev/null and b/hm_web/static/images/OG_303e.png differ diff --git a/hm_web/static/jquery.js b/hm_web/static/jquery.js new file mode 100644 index 0000000..fff6776 --- /dev/null +++ b/hm_web/static/jquery.js @@ -0,0 +1,6240 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function( window, undefined ) { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwnProperty = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + indexOf = Array.prototype.indexOf; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + if ( elem ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && /^\w+$/.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object literal values or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { + var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src + : jQuery.isArray(copy) ? [] : {}; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // Handle when the DOM is ready + ready: function() { + // Make sure that the DOM is not already loaded + if ( !jQuery.isReady ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor + && !hasOwnProperty.call(obj, "constructor") + && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwnProperty.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") + .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + trim: function( text ) { + return (text || "").replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = []; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + if ( !inv !== !callback( elems[ i ], i ) ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch( error ) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + +// Mutifunctional method to get and set values to a collection +// The value/s can be optionally by executed if its a function +function access( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; +} + +function now() { + return (new Date).getTime(); +} +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + now(); + + div.style.display = "none"; + div.innerHTML = "
a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected, + + parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null, + + // Will be defined later + deleteExpando: true, + checkClone: false, + scriptEval: false, + noCloneEvent: true, + boxModel: null + }; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete script.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + document.body.removeChild( div ).style.display = 'none'; + + div = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; +var expando = "jQuery" + now(), uuid = 0, windowData = {}; + +jQuery.extend({ + cache: {}, + + expando:expando, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + "object": true, + "applet": true + }, + + data: function( elem, name, data ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache; + + if ( !id && typeof name === "string" && data === undefined ) { + return null; + } + + // Compute a unique ID for the element + if ( !id ) { + id = ++uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + elem[ expando ] = id; + thisCache = cache[ id ] = jQuery.extend(true, {}, name); + + } else if ( !cache[ id ] ) { + elem[ expando ] = id; + cache[ id ] = {}; + } + + thisCache = cache[ id ]; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + // Completely remove the data cache + delete cache[ id ]; + } + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" && this.length ) { + return jQuery.data( this[0] ); + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + } + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } else { + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() { + jQuery.data( this, key, value ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i, elem ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); +var rclass = /[\n\t]/g, + rspace = /\s+/, + rreturn = /\r/g, + rspecialurl = /href|src|style/, + rtype = /(button|input)/i, + rfocusable = /(button|input|object|select|textarea)/i, + rclickable = /^(a|area)$/i, + rradiocheck = /radio|checkbox/; + +jQuery.fn.extend({ + attr: function( name, value ) { + return access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", setClass = elem.className; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split(rspace); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Typecast each time if the value is a Function and the appended + // value is therefore different each time. + if ( typeof val === "number" ) { + val += ""; + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + if ( name in elem && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + elem[ name ] = value; + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + + // elem is actually elem.style ... set the style + // Using attr for specific style information is now deprecated. Use style instead. + return jQuery.style( elem, name, value ); + } +}); +var rnamespaces = /\.(.*)$/, + fcleanup = function( nm ) { + return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { + return "\\" + ch; + }); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events = elemData.events || {}, + eventHandle = elemData.handle, eventHandle; + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + handleObj.guid = handler.guid; + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)") + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( var j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( var j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[expando] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery.data( elem, "handle" ); + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var target = event.target, old, + isClick = jQuery.nodeName(target, "a") && type === "click", + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ type ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + type ]; + + if ( old ) { + target[ "on" + type ] = null; + } + + jQuery.event.triggered = true; + target[ type ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( old ) { + target[ "on" + type ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace, events; + + event = arguments[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + var events = jQuery.data(this, "events"), handlers = events[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, arguments ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) { + event.which = event.charCode || event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); + }, + + remove: function( handleObj ) { + var remove = true, + type = handleObj.origType.replace(rnamespaces, ""); + + jQuery.each( jQuery.data(this, "events").live || [], function() { + if ( type === this.origType.replace(rnamespaces, "") ) { + remove = false; + return false; + } + }); + + if ( remove ) { + jQuery.event.remove( this, handleObj.origType, liveHandler ); + } + } + + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( this.setInterval ) { + this.onbeforeunload = eventHandle; + } + + return false; + }, + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +var removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + elem.removeEventListener( type, handle, false ); + } : + function( elem, type, handle ) { + elem.detachEvent( "on" + type, handle ); + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = now(); + + // Mark it as fixed + this[ expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + } + // otherwise set the returnValue property of the original event to false (IE) + e.returnValue = false; + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var formElems = /textarea|input|select/i, + + changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information/focus[in] is not needed anymore + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return formElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return formElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + context.each(function(){ + jQuery.event.add( this, liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + }); + + } else { + // unbind live handler + context.unbind( liveConvert( type, selector ), fn ); + } + } + + return this; + } +}); + +function liveHandler( event ) { + var stop, elems = [], selectors = [], args = arguments, + related, match, handleObj, elem, j, i, l, data, + events = jQuery.data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { + return; + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( match[i].selector === handleObj.selector ) { + elem = match[i].elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) { + stop = false; + break; + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( fn ) { + return fn ? this.bind( name, fn ) : this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + window.attachEvent("onunload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + var origContext = context = context || document; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + var ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + var ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + var cur = parts.pop(), pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set, match; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string"; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return /h\d/i.test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return /input|select|textarea|button/i.test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var i = 0, l = not.length; i < l; i++ ) { + if ( not[i] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){ + return "\\" + (num - 0 + 1); + })); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var i = 0, l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( var i = 0; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date).getTime(); + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +var contains = document.compareDocumentPosition ? function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +var isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = getText; +jQuery.isXMLDoc = isXML; +jQuery.contains = contains; + +return; + +window.Sizzle = Sizzle; + +})(); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + slice = Array.prototype.slice; + +// Implement the identical functionality for filter and not +var winnow = function( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + if ( jQuery.isArray( selectors ) ) { + var ret = [], cur = this[0], match, matches = {}, selector; + + if ( cur && selectors.length ) { + for ( var i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur }); + delete matches[selector]; + } + } + cur = cur.parentNode; + } + } + + return ret; + } + + var pos = jQuery.expr.match.POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + return this.map(function( i, cur ) { + while ( cur && cur.ownerDocument && cur !== context ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) { + return cur; + } + cur = cur.parentNode; + } + return null; + }); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, + rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, + rtagName = /<([\w:]+)/, + rtbody = /"; + }, + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and