commit a7012e15c2bf5b8398cfbf1d83175c9d5216a2bf Author: Unrud Date: Sat Jun 23 17:08:30 2018 +0200 import project diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/COPYING @@ -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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..951e288 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Remote Touchpad + +Control mouse and keyboard from the webbrowser of a smartphone (or any other device with a touchscreen). +To take control just open the displayed URL or scan the QR code. + +Supports with Linux/X11 and Windows. + +## Screenshots + +![screenshot 1](https://raw.githubusercontent.com/Unrud/remote-touchpad/master/screenshots/1.png) + +![screenshot 2](https://raw.githubusercontent.com/Unrud/remote-touchpad/master/screenshots/2.png) + +![screenshot 3](https://raw.githubusercontent.com/Unrud/remote-touchpad/master/screenshots/3.png) diff --git a/bindata.generated.go b/bindata.generated.go new file mode 100644 index 0000000..ef99e13 --- /dev/null +++ b/bindata.generated.go @@ -0,0 +1,363 @@ +// Code generated by go-bindata. +// sources: +// webdata/fn.js +// webdata/icon.png +// webdata/index.html +// webdata/main.css +// webdata/sha256.js +// webdata/tex.png +// DO NOT EDIT! + +package main + +import ( + "github.com/elazarl/go-bindata-assetfs" + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _webdataFnJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3a\xdd\x6f\xdb\xb6\xb7\xef\xf9\x2b\x4e\xf5\x50\xc8\x8d\x23\xdb\x29\x7a\x37\xd4\x75\xee\x75\x53\x77\x09\x96\x34\x81\xed\x6c\x35\x82\xa0\xa0\xa5\x63\x5b\xab\x4c\x6a\x22\x15\x27\xbd\xcd\xff\x7e\x41\x7d\x52\x14\x25\x67\x1d\xfa\x72\xf1\x33\xb0\x4e\x21\xcf\x39\x3c\xdf\x1f\x94\x7a\xaf\x0e\xe0\x15\x00\xc0\x29\x0b\x1f\x23\x7f\xbd\x11\x60\xbb\x1d\x38\xee\x0f\x7e\x85\x1b\x1a\xc5\xde\xbb\x58\xfe\xfb\x3f\x2c\x16\x01\x63\x5f\x1d\x97\x6d\x4f\x0e\x20\x47\x9a\x6f\x7c\x0e\x2b\x3f\x40\xf0\x39\x84\x24\x12\xc0\x56\x30\xc5\x2d\x13\x78\x34\x67\xb1\xbb\x09\x89\xe7\x94\xe0\x1f\x19\x5b\x92\x48\xc2\xae\x22\x44\xe0\x6c\x25\x76\x24\xc2\xb7\xf0\xc8\x62\x70\x09\x85\x08\x3d\x9f\x8b\xc8\x5f\xc6\x02\xc1\x17\x40\xa8\xd7\x63\x11\x6c\x99\xe7\xaf\x1e\x33\x22\xbe\x80\x98\x7a\x18\x81\xd8\x20\x08\x8c\xb6\x5c\x1e\x2a\xff\xf8\xed\xd3\x0d\xfc\x86\x14\x23\x12\xc0\x75\xbc\x0c\x7c\x17\x2e\x7c\x17\x29\x47\x20\x1c\x42\xb9\xc2\x37\xe8\xc1\x32\x27\x25\x91\x3e\x4a\x4e\x66\x19\x27\xf0\x91\xc5\xd4\x23\xc2\x67\xb4\x0b\xe8\x8b\x0d\x46\x70\x8f\x11\xf7\x19\x85\xd7\xf9\x31\x19\xcd\x2e\xb0\x28\xa3\x63\x13\x21\x45\x88\x80\x85\x12\xb5\x03\x84\x3e\x42\x40\x44\x89\xad\x28\x41\x53\x8f\xd4\x46\x29\xb4\x07\x3e\x4d\x0e\xd9\xb0\x10\x41\x6c\x88\x90\xf2\xee\xfc\x20\x80\x25\x42\xcc\x71\x15\x07\xdd\x8c\xd0\x32\x16\xf0\xe7\xf9\xfc\xec\xea\x66\x0e\xe3\x4f\x0b\xf8\x73\x3c\x9d\x8e\x3f\xcd\x17\x43\xd8\xf9\x62\xc3\x62\x01\x78\x8f\x29\x35\x7f\x1b\x06\x3e\x7a\xb0\x23\x51\x44\xa8\x78\x04\xb6\xca\x88\x5c\x4e\xa6\xa7\x67\xe3\x4f\xf3\xf1\xfb\xf3\x8b\xf3\xf9\x02\x58\x04\x1f\xcf\xe7\x9f\x26\xb3\x19\x7c\xbc\x9a\xc2\x18\xae\xc7\xd3\xf9\xf9\xe9\xcd\xc5\x78\x0a\xd7\x37\xd3\xeb\xab\xd9\xc4\x01\x98\xa1\x64\x0e\x33\x1a\x2d\x7a\x5f\x25\xd6\x8b\x10\x3c\x14\xc4\x0f\x78\xa9\x87\x05\x8b\x81\x6f\x58\x1c\x78\xb0\x21\xf7\x08\x11\xba\xe8\xdf\xa3\x07\x04\x5c\x16\x3e\xee\xb7\x69\x4a\x86\x04\x8c\xae\x13\x81\x33\xef\x72\x00\xce\x57\x40\x99\xe8\x02\x47\x84\x77\x1b\x21\xc2\xb7\xbd\xde\x6e\xb7\x73\xd6\x34\x76\x58\xb4\xee\x05\x29\x01\xde\x3b\x91\xec\xf4\x0e\x0e\xa0\xd7\x83\xdb\x01\x24\x26\xe9\xc2\x71\xfa\x80\xbc\x0b\xaf\xf3\xc7\xbb\x03\x97\x51\x2e\x60\x7e\x75\x73\x7a\xf6\xe5\xf2\xea\x8f\xc9\x97\xf9\xd9\x74\x32\x3b\xbb\xba\xf8\x00\x23\xb8\x1d\xf4\xbb\x30\x78\x23\xff\xbb\x1b\x56\x40\xe7\xe7\x97\x13\x69\xa0\x11\x1c\xbf\xe9\xe7\x5b\x09\xfe\xe5\xcd\x85\x5c\x1e\xe4\x8b\xb3\xd3\xe9\xd5\xc5\x45\xbe\xdc\x77\xfa\x6f\x86\x07\x92\xaf\xdb\xf0\xa1\xc7\xbb\xb0\x8d\x03\x71\xd7\x05\xc7\x71\x72\x5e\xae\xaf\xce\x3f\xcd\x27\xd3\x2f\xe3\xd3\xd3\xc9\xc5\x64\x3a\x9e\x9f\x5f\x7d\x92\xbc\xdc\xf6\xbb\xd0\xbf\xeb\xc2\xed\xaf\xbf\x74\x61\x20\x1f\x06\xbf\xbc\xce\x9e\xde\xbc\x79\xdd\x85\xe3\xbb\x82\xc9\x9b\xeb\x0f\xe3\xf9\xe4\x4b\x42\xe8\x8f\xf1\x05\x8c\x40\xe1\x72\xfc\xf9\xcb\xf9\x87\x8b\xc9\x97\x14\x68\x26\x99\xed\x0f\x0f\x0e\xee\x49\x04\x3b\x3e\x4c\xfe\x1f\x12\xaf\x78\x08\xc8\x12\x83\x6c\x5f\x48\xb5\x5d\x32\x69\xcf\x11\xac\x48\xc0\x71\x58\xae\xcf\x84\xcc\x14\x23\xe8\x2b\x6b\x17\x84\x8b\x09\xf5\xb4\xd5\x29\x06\x48\x38\x7a\xa7\x2c\xa6\x0a\x06\xa3\x6b\xe6\xd3\x75\x66\x1b\x29\xf3\x5d\xba\xb1\x65\xf7\xf8\x79\x16\x6f\x4b\x50\xb9\xb2\xa8\xac\x70\x37\x62\x41\xf0\xd9\xb0\x56\x85\xf3\x22\xb2\x5e\xfb\x74\x5d\x15\x20\x5f\x9d\xfb\x5b\x94\x21\x36\x02\x1a\x07\x41\xba\x17\x87\x1e\x11\x28\x77\xa2\xca\xba\xef\x05\x78\x93\xec\xf1\x94\xfc\xc1\x2a\xa6\xae\xcc\x14\xb0\x8a\x83\x80\xbb\x11\x22\x9d\x50\xb2\x0c\xd0\xb3\x3b\xf0\xbf\x07\x32\xa8\x22\x14\x71\x44\xc1\xf6\x98\x1b\x6f\x91\x0a\xa7\x06\x0a\xdf\xbf\x27\x90\xf2\x57\x40\xed\x70\xf9\xd5\x17\x1f\x9f\x05\xbb\x65\xdf\x24\xe0\x6c\x3f\x20\x6f\x25\x98\xa8\xa7\x33\x3c\x78\x52\x04\x8b\xf0\xef\x18\xb9\xc2\x88\x8d\xb9\x64\xfe\x0a\x6c\x74\x6a\x00\xf9\xb6\xfc\x19\xb6\xed\xce\x30\xd9\x7e\x02\x0c\x38\x66\x44\x52\x69\xa7\xed\xa4\x1a\x80\x8c\x04\xb7\xec\x9b\x02\x38\x33\x50\x33\x41\x98\x49\xf1\x3d\x7c\x19\x00\x0a\x42\x15\x5d\xe2\x83\x5f\x81\x51\xf4\x58\x98\xa8\x0a\xa3\x1e\xd4\x00\x62\xe0\x59\x73\xa2\xc9\x7e\x92\x26\xc0\x36\xc2\x5b\xf6\xed\x94\x50\x17\x03\xb3\x76\xdb\xe0\x5a\xc9\xf2\x67\xf0\xaa\x03\x99\x75\xad\x44\x59\x80\x12\xef\x59\x01\x99\x82\x3e\x2f\x20\x5b\x60\xab\x01\xd9\x06\xc8\x5b\x09\xca\xd4\xa3\xc5\x23\xf1\xbc\x12\xc5\xdd\x10\xba\xc6\xc9\x3d\x52\x71\xe1\x73\x21\xcb\xab\x1d\x64\x0f\x46\xef\xaa\x8b\xfa\x62\x34\x4a\xda\xb0\x95\x4f\xd1\x33\xea\x9b\x78\x5e\xf5\x04\x6b\xa5\x31\x60\x75\xa1\x38\x75\x9f\x33\xd6\xe5\xfd\x11\x0e\x52\x5a\x3f\xc6\x87\xd1\x38\x3f\xc2\xc4\x96\x7d\xfb\x41\x0e\x0c\x56\xff\x11\x06\x2e\x67\x25\x9d\xd3\xa6\xf3\x2b\xde\x23\x3b\xb2\xa4\xda\xda\x22\xed\x91\x84\xbf\xc5\x99\x20\xdb\x50\x8b\x8e\xf2\x7c\xdf\x43\x2a\xfc\x95\x8f\xd1\xdb\xb4\x96\x3b\xe5\x4a\xb7\x80\x0a\xc9\x1a\x3f\xe7\x00\xc9\x1f\xda\x5e\xd2\x2b\xb4\x00\x2c\xd4\xbd\x85\xb6\x57\x43\x56\x00\x0a\x09\xde\x96\x8f\xa9\xe4\xd5\xc0\x51\x7b\x8d\x73\xea\xe1\xc3\xfb\xc7\x73\xcf\xf6\xbd\x39\xfb\xe8\xd3\x42\xe3\xb2\xcf\xb5\x93\x5a\x9f\x54\x78\xf0\xe1\x9d\xd6\xa5\x38\x01\xd2\xb5\xd8\x0c\xc1\x3f\x3c\x54\xed\x94\x36\x08\x30\xd2\xc0\x6f\xfd\x3b\x45\x61\xc3\x83\x52\xaf\x2b\xb0\x25\xfc\x08\x74\x1e\xf2\x5f\x66\x0a\x7f\x58\xac\x3e\x1d\x94\xff\x66\xbb\x47\x83\xaa\x98\x2e\x09\xdc\x58\x8e\x2c\xd7\xcc\xa7\x02\xa3\xb1\xeb\x62\x80\x51\x32\x0a\x5d\xc6\x81\xb0\x79\x88\xd8\x2a\xae\xa9\x1d\x6d\x12\x9a\x1f\xc3\xc8\x88\x70\xeb\xdf\xdd\xf6\xef\x4a\xce\x49\x1b\xe0\x40\x01\x94\x6a\xe1\xc7\xf0\x6e\x04\x15\x46\xf3\x9f\xcb\xa8\xf0\x69\x8c\xba\x4e\x0a\x8d\x4a\x85\xf6\x1b\x34\x49\x8e\x4d\x68\x7c\xd0\xc8\xda\xd1\x40\x93\xa2\x1d\x54\x95\x23\xaf\x32\xa9\xbe\x8f\xf8\xa0\x03\x3d\x29\x99\x7c\xea\xc0\x2b\xb0\xc9\xf1\x11\x19\x74\xe0\x10\xc8\x60\xa8\x98\x55\x0a\xd1\x62\x01\x38\xa9\x4a\x97\x1d\x63\xe4\xa9\x85\x8c\xca\x6d\xc5\x9d\x06\x7a\xd0\x7c\xa8\xf6\xc9\x45\x15\x6d\xea\x9f\xe5\xde\x8e\x3b\x1c\xa9\x67\x5b\x99\x0f\xbe\x8f\x85\x60\x14\x06\xd0\xb7\xb4\x6a\x96\x76\xda\x72\xbe\x18\x53\x6f\x96\x34\xef\x95\xb6\xa8\xd2\x89\xa7\x47\xa8\xd2\x33\x7a\x53\x00\x24\xcc\x55\xfd\x48\x1f\x8a\x4e\xa0\x0f\x2f\x5f\x56\xdb\x78\x83\xb7\x54\xdb\x7f\x8e\xe2\x5c\x0a\x71\x4f\x02\x5b\x3b\xaf\xab\x8f\x5d\x9d\x7a\xa8\x56\xb5\xa9\xb1\x9b\x4b\xaa\x30\x74\x98\x4c\x92\x79\x42\x49\xe6\x20\x18\xc1\x25\x11\x1b\x47\x44\x31\x75\xed\x7c\x34\xea\x54\xa1\x16\x75\xa8\x45\x09\x25\xb5\x91\xec\x92\x25\x4f\x29\x74\xe0\x64\x04\x03\xf8\xfe\x1d\x2a\xeb\x8b\x74\x5d\x55\x49\x31\x8b\x1d\x8d\xd2\xe7\x61\x65\x6b\xa1\x6c\x2d\x14\xfd\xeb\xb3\x52\xbe\xa1\x3b\x87\x34\x3e\x58\x70\x98\xc9\x7a\x08\x56\xf1\xd7\xa2\xa3\x7a\xa8\x32\xf3\x55\x65\x2d\x07\x41\x45\x27\xd9\x24\x68\x82\x6c\xd2\x4b\x46\xc7\xa0\x99\x0c\xaf\xae\x1b\x65\x06\x3d\x1a\xe5\x7f\x0d\xb5\xed\x45\x65\xfb\x47\x74\x94\x46\x46\xa2\x97\x5c\x03\xb9\x9e\x72\xd6\xf4\x1c\xa2\xd2\x3e\x19\xd5\xee\x00\x54\x21\xdc\x00\x49\x54\xf8\xb8\xe2\xfd\x8a\x3b\x9b\x46\xe2\xba\x83\x6f\x08\xf5\x02\x4c\xaa\xb5\x8d\xf7\x42\x8d\x64\x63\x11\xad\x85\x5f\xe5\x5a\x01\xef\x85\x53\x94\xf4\x61\x15\x46\xbb\x92\xa8\xec\x19\x2e\x1b\xf2\xfd\xfa\x5d\x40\xd5\xbf\x44\x71\x13\x21\x0f\x4f\x7b\x3a\x2f\xe3\x79\xd8\x58\x31\x45\x7b\x67\x20\xc5\x17\x65\x37\x20\x48\xb4\xc6\xb4\xe1\x0b\x89\x27\x13\x52\xe3\x66\x72\x13\xf3\x4f\x4a\xa0\xe4\x3a\x8c\x50\xb6\x89\x1f\x70\x45\x64\xbd\x57\x8c\xa8\xd9\x20\x8c\xf9\xc6\xd6\x3a\xc2\x84\x8b\x6e\x55\xf5\x9d\x8e\xa6\xe0\xca\x1d\x8f\x2a\xe5\x8b\x5c\xbf\x3a\xcf\xca\x7d\x4e\x73\x2a\xab\x65\x95\xb6\x8c\x56\x95\xbb\x72\x17\xd4\x96\x1a\xb4\xa8\x6c\xcf\x0e\xb9\x58\x7a\xad\x7b\x61\x28\x45\x45\x20\xe5\xc9\x5d\x43\xd2\x64\x6c\x2b\x9f\x06\x67\x15\x51\xdd\xde\xa6\xd0\x9b\x50\x4f\x0d\xbc\x9f\xe6\xd2\x69\xb3\xfb\xa0\x75\xbb\x65\x5b\x2d\x4c\xcd\xaf\xa6\x55\x89\xff\xae\x5e\x7d\xdb\xdc\x5b\x73\x60\x1e\x06\xbe\x8b\x92\x50\x17\x06\xba\x93\x56\xb2\xc0\xe1\x61\xa3\x0b\x1b\xb2\x4c\x99\x45\x0d\xf9\xe4\xc4\x78\x77\x9c\x29\xaa\x96\xcb\xf2\x3c\x55\x1a\xf0\xe9\x19\x29\xb1\x48\x0a\xda\xd1\xb2\x2e\xbd\x7c\x69\x74\x12\xf5\xe4\xf6\xfe\xeb\x27\x30\xf1\x42\x91\xf5\xe5\xcb\xaa\x4a\xe1\x48\xcd\xea\xef\xaa\xd7\xe9\xba\x4f\x2d\x53\x4e\x6b\x89\xc5\x94\xd7\xb5\x52\x0c\xe9\x9b\x94\x14\x7d\xa0\x78\x4f\x39\x80\x9b\xa9\x1c\x37\x52\x79\xad\x50\xd9\x43\xe4\x75\x23\x11\xe3\xcc\xd1\x60\x21\x59\xd0\x33\x44\x59\xdf\x07\x96\x16\x32\x39\x51\x83\xe8\xf5\x84\xc2\x51\xe4\xb9\xa8\xd6\xc6\x77\x35\x33\xd4\xd4\x55\x25\xfe\x3c\x76\xfb\xd6\x9e\xfe\x37\xcd\x51\xe9\x85\xe0\x7f\xd2\xd4\xbf\x4e\x53\xd0\x96\x64\xea\x7a\x97\x50\xba\xd6\x79\xbc\xfd\x5c\x46\x5b\xb6\xb2\xa8\xae\xfc\x7f\xb2\x4c\xf2\xe6\xc7\xe7\x22\x2f\xfc\xfc\xef\x48\xa4\x03\x40\xc8\x76\xea\xa1\xc9\x0d\x15\x1c\xd5\x2e\x73\xbc\x87\x6c\x2f\x49\x67\x5d\x99\x3c\x0e\xa1\x89\xc0\xa2\x85\xc0\xa2\x20\xa0\x49\x65\x4e\xc8\xad\x55\x47\xce\x2a\x89\x54\x66\xa8\x5b\x33\xc9\x23\x18\xdc\xe9\xba\x6b\x70\x27\x83\x12\xa5\xe9\xfe\x89\xbe\x86\x55\xf4\xc7\x3a\x7a\xab\xb6\xaa\xe8\x32\x10\x3e\x60\x20\x88\x1e\x18\x0d\x24\x0c\x81\x93\x78\xfe\xe1\x48\x0a\xf2\x6a\xff\xa5\x59\x31\x09\x7a\x0f\x1d\xe8\x29\xe7\xbf\x82\x41\xbf\xdf\xef\x54\xe8\x2e\x12\xba\x8f\xff\x8c\xee\xe3\x1e\xba\x8d\x8a\x35\xd8\x61\x3f\xd6\xc2\xa0\xfe\x76\xac\x52\xc5\xcf\x69\x99\xda\x5b\x81\x3c\xab\x9d\x8c\x9a\xbb\x81\xd6\xde\x24\x99\xce\xf7\xce\x1a\x87\xa3\xd4\xca\xaf\xca\xf7\xf4\x0d\x83\x46\x0a\xb9\x30\x43\x2a\x0d\x44\x23\x43\xb5\x1e\x42\xbb\x18\x48\xd9\x50\xbe\x0c\x18\x1a\xa0\x17\x25\xf4\xa2\x09\xfa\x49\x9b\xc8\xb5\xab\x33\xe3\x9d\xff\x86\x04\x92\x53\x9c\x22\x0f\x19\xe5\x68\x6f\x91\x73\xb2\xc6\x4a\x21\xd8\x90\xab\xe5\x5f\x72\x0c\xc1\x1d\xfc\xc5\x67\x67\x63\xdb\x9a\x9d\x8d\x8f\x8e\xdf\xfc\x97\xd5\x05\x6b\x3e\xf9\x3c\xcf\xab\x7b\x0a\xea\x70\x14\x67\x97\xe3\xd3\xdf\xf1\x31\xa7\x67\x86\x4b\xf9\xb4\x77\x3e\xf5\xd8\xce\x09\x98\x9b\x78\xbf\xb3\x21\x7c\xe3\xf0\x78\xc9\x45\x64\x0f\xf2\x1c\x98\x5d\x42\x2e\x05\x23\x76\x86\xbe\x4e\x8f\xb1\xad\xf7\x8b\xf9\x64\x66\x75\xd2\x0b\xc4\x8c\x5a\xfd\x95\x48\xc0\x88\x67\x75\x21\x17\xde\x56\x65\x24\xb1\xd8\xc8\x52\xe2\x12\xa1\xdf\x1d\x24\x1f\x23\x84\x48\xd3\x69\xab\x78\xe5\xb2\x46\x91\xbd\x9f\x49\x8a\x92\x95\x81\x58\xca\x3d\x93\x1b\x30\x9e\x50\x6b\x44\x4a\x21\x72\x1c\x39\xf2\xb7\x00\x87\x44\x85\x4c\xe6\xff\x3d\xe0\x09\x8c\xca\xd1\x57\x7c\x5c\x32\x12\xb5\x1e\x93\xc3\xa8\x78\xe5\xbb\xac\xa2\x77\x6d\xc4\xd7\x61\x55\x3a\x02\x1f\x44\x1b\xae\xdc\xcf\xe1\x53\xdd\x38\x5c\x3c\x06\xe8\x78\x3e\x0f\x03\x22\x2b\x83\x45\x19\x45\xab\x50\x43\xeb\x7e\x2e\x4a\x2b\x90\x3c\xd3\xb9\x27\x41\x8c\x72\xc3\xca\x5e\xc3\xec\x78\xe6\xf0\x7f\xe2\x72\xc6\xdc\xaf\x28\x6c\x6b\xc7\xdf\xf6\x7a\xb2\xb1\x2d\x3d\x95\x71\x41\xc9\x16\xe1\xb0\x12\xb3\xca\xcf\x2e\x60\x43\x16\x09\xf8\x6f\xb0\xde\x56\x28\x24\xab\x6f\xc1\xb2\x3a\xcd\x34\xac\xde\x8e\x4b\xad\x64\x8c\x39\x8c\x66\x51\x25\x1d\x35\xf7\xe6\xe4\x62\x47\xcf\x92\x15\xb7\xd6\xf3\xd0\x8e\x3b\x89\x8e\x6d\xed\xfe\x21\x8d\x34\x53\x5e\xd1\xa3\xa4\xda\x05\xe4\x93\x40\x3d\xa9\x24\xbc\x39\x1e\x11\x44\xed\x68\xb2\x88\x69\x35\x4e\x2e\xc8\xc6\xe7\x82\x45\x8f\x0e\x17\x44\xa0\xcc\xaa\x8a\x9b\x6a\x62\x35\x1b\x7d\x15\xe0\x83\x55\x95\x35\x31\xfe\x8a\xb9\x31\xb7\xf7\x0d\x3a\x46\x67\xd3\x48\x66\xaa\x7a\xca\xdf\xe5\x25\xc6\x4a\x94\xac\x9a\x4a\xb7\x92\xe1\x7b\x04\x5d\x28\xf3\x77\x1d\x55\xeb\x3c\x57\x9f\xfb\xa2\xa6\x5d\x89\x09\x60\x01\xd7\x14\xa4\xaa\x5e\x72\x6d\xec\xcd\x38\x79\xbe\x30\xe4\x6e\x37\xf0\xdd\xaf\x56\xb7\x29\x42\x9e\xfb\x2b\xa3\xe5\x27\xd9\xe0\xdf\xe9\x56\xf3\x26\xb3\x73\xe6\xa1\x10\xc6\x7c\x33\x93\xe1\xa0\xa4\xec\x2e\x58\xe9\xa7\xa7\xf0\xbb\x96\xc5\x9f\x94\xb7\x1a\x2f\x0c\x5f\xa4\xa9\xc2\xea\x19\xbc\x55\xa2\x54\xf6\x1a\x4a\xa3\x09\x7f\x9a\x0d\x4c\x31\x5b\xff\xc2\x2c\x24\x5e\xfd\x26\x22\x5f\x69\xf4\x50\x99\xd7\x7e\xb2\x77\x36\xab\x45\x29\x50\x2f\x46\x49\xa5\x68\xb8\x81\xc9\x6d\x3e\x97\x55\x56\x56\x99\x12\xb3\x63\x48\x7b\x6a\xcd\xab\x2a\x24\xa1\x9a\xb6\x51\xb9\xb7\x2d\x89\xfb\xd5\xd6\x7c\x29\x03\x61\x34\x64\x61\x96\x98\xf7\xd4\xa3\x26\xd7\xcf\x7d\x5f\x17\xed\x39\x39\x17\x9e\x5b\xe8\xa1\xf1\x0a\xab\x59\xd4\x52\x27\x4f\x65\xcb\x51\x77\x80\x64\x74\xe1\x72\x6a\xb7\xba\xea\x9b\xae\x6e\xf1\xdd\xe4\x1e\x5c\xa4\x5e\x81\x39\xa1\xde\xb3\xf1\xdc\xe4\xc2\xac\x40\x4d\xef\xcf\x9e\x8d\x2d\x87\x9c\x02\x57\x8e\x0b\x25\xe6\x53\xf9\xf8\x7f\x01\x00\x00\xff\xff\x87\xf5\x90\xa3\x3f\x30\x00\x00") + +func webdataFnJsBytes() ([]byte, error) { + return bindataRead( + _webdataFnJs, + "webdata/fn.js", + ) +} + +func webdataFnJs() (*asset, error) { + bytes, err := webdataFnJsBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "webdata/fn.js", size: 12351, mode: os.FileMode(436), modTime: time.Unix(1529766470, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _webdataIconPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\x2a\x06\xd5\xf9\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01\x42\x28\x9b\x78\x00\x00\x05\xdc\x49\x44\x41\x54\x78\xda\xed\x59\xcf\x6b\x17\x39\x14\xff\x24\x93\xf9\xce\xd4\x56\xa4\x88\x15\x6f\x4a\xa1\xa5\xd4\x73\x0b\x05\x11\x6f\xeb\x71\xc1\xed\xa5\x57\xf7\xb8\xfb\x17\xb8\x7b\xd0\xf3\xee\x61\xb7\xff\x44\x57\x3c\x89\x22\x78\xf1\xd2\x53\x11\x85\x9e\x7a\xf0\x26\x75\x29\x54\x51\x4b\x67\xe6\x3b\xc9\x64\x0f\x9a\x21\x93\x6f\x92\xc9\x7c\xeb\xc2\xc2\xe6\x03\xe5\xdb\xc9\xe4\x25\x2f\xef\x57\xde\x7b\x03\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\xfc\xef\x40\x7c\x2f\xa5\x94\x6b\x00\x12\xed\x19\x52\x4a\x34\x4d\xd3\xf9\x35\xc7\x85\x10\x9d\xf9\xe6\xdc\xa6\x69\x26\x68\x6d\xf3\xf4\x31\x00\x1d\x3a\xd7\x3c\x93\x46\x08\xc1\x6f\xdc\xb8\xb1\x37\x48\x00\x65\x59\xfe\x74\x7a\x7a\xfa\xc7\x78\x3c\x86\x94\x52\x17\x88\xf7\x7f\xf5\x4b\x08\x69\x19\x30\x04\xda\x4b\x3b\xe4\xbd\x94\x12\x84\x90\xf6\xd0\xea\x7f\x73\x5e\x5d\xd7\x28\xcb\xf2\xe7\xb5\xb5\xb5\x3f\x7b\x05\x50\x14\xc5\x2f\x9f\x3f\x7f\xbe\xaf\xa4\x78\xf9\xf2\x65\x27\x33\x7d\xbf\xbe\xb1\x21\x34\xd3\x08\xac\x69\x1a\x10\x42\x40\x08\xc1\xbb\x77\xef\x90\x24\x09\x4e\x4e\x4e\x7e\x5d\x5f\x5f\x7f\xe0\x14\x80\x94\xf2\xca\xf1\xf1\xf1\xa1\x32\xa5\xf9\xf9\x79\x5c\xbf\x7e\x1d\x84\x90\x8e\xc4\x4d\xe9\x2b\xad\xb7\x8b\x1a\x9a\x50\xcf\x3a\xad\x49\x73\x26\x3f\x36\xf8\xd0\xf7\xfe\xf0\xe1\x03\xf6\xf7\xf7\x71\x74\x74\x04\x29\x25\xde\xbe\x7d\x7b\xe5\xf6\xed\xdb\x7f\xab\xf7\x4c\x5f\xe8\xe4\xe4\xe4\xbe\x3a\xfc\x57\xff\xc1\xc2\xc2\x42\xd0\xc6\xff\x99\xa0\x66\xf0\xc4\x18\x6b\xdd\x91\x10\x82\x4b\x97\x2e\x3d\x00\xf0\xa3\x7a\x4f\x75\x62\x21\xc4\xf7\x2e\xbf\x75\x04\x49\x2f\x23\x7d\x63\xff\x86\xf0\x7c\xb1\xe7\x2b\x0f\x9d\x33\x52\x63\xe2\x45\x9b\x8f\x85\x9a\xab\xf2\x39\xd7\xe1\x42\xd7\x1c\x2a\x18\xd3\xfd\x7c\x16\x41\x08\xb9\xe8\x13\x80\x73\x71\x97\x60\x4c\x7a\xdd\xd7\xa7\x05\xa5\xb4\xf7\x60\xa1\x42\x31\x03\xa4\xb9\x0e\xf5\x69\xc0\x76\x58\xc5\xdc\xb7\xd0\x8e\x2b\x20\xea\xfb\x87\x0a\x7e\xda\xd8\x44\xcf\x22\xd1\x10\x3f\xec\xbb\xc2\xfa\x2c\x2c\xd4\xf5\xa6\xc9\x37\x9c\x02\x38\x3c\x3c\x74\x26\x15\x43\xb5\x3e\xf4\xbd\x8a\x23\x3e\x6b\x09\x1d\x0f\x51\xda\x44\x0c\x60\x8c\xe1\xe9\xd3\xa7\x60\x8c\x39\x19\xd1\x99\x54\x7f\x7d\x4c\xd8\xc6\x86\x1e\x96\x52\xea\x9c\xaf\xde\xf5\xa4\xf6\x13\xeb\x32\x73\x02\x21\xa4\xe3\xe7\x7a\x46\xa5\x88\xd5\x66\x94\xd2\x4e\x9e\x6e\xfa\xb3\x2d\x45\xd6\xe7\x52\x4a\xdb\x7b\x5a\xed\x63\xbb\xca\xd4\xfe\x42\x88\x8e\xf0\xf4\xb5\x93\x24\x01\xe7\x7c\xb0\x15\x30\x9f\xa4\x5c\xc1\x45\x15\x3b\x59\x96\xa1\xae\x6b\x10\x42\x30\x1a\x8d\xda\xcd\xc6\xe3\x71\x3b\x56\x55\x15\xd2\x34\x85\x94\x12\x9c\x73\x30\xc6\x90\x24\x5f\xea\xab\xaa\xaa\x5a\x81\xa6\x69\x0a\x21\x04\xea\xba\x06\x63\xac\x73\x13\x8c\xc7\xe3\x76\x3f\xc5\x5f\x5d\xd7\xa0\x94\x22\xcb\xb2\x96\x1f\x57\x06\x3a\x38\x08\xea\x1a\xb7\x45\x67\x73\x2e\xa5\x14\x52\x4a\x54\x55\x05\x21\x44\xeb\x3e\x66\xb1\x42\x29\x45\x92\x24\x28\xcb\x12\x55\x55\x75\x34\x5e\x96\x25\x92\x24\x69\xe7\x37\x4d\x83\xba\xae\x21\x84\x40\x92\x24\x68\x9a\x06\x42\x88\xf6\x59\xad\x55\xd7\x75\x2b\x70\xdd\xd2\xcc\xfd\x95\x40\x7b\x83\x60\x48\x81\x13\x72\x53\xa8\xcd\x6d\x99\x99\xcf\x57\x15\x9d\xa2\x55\x73\xd3\x34\x05\x21\x64\xc2\xcc\x6d\x77\xbb\x79\x7d\x4a\x29\xf1\xe4\xc9\x13\x5c\xb8\x70\xa1\x3f\x08\xda\x18\xb1\x05\x1e\x7d\xae\x62\x94\x31\x06\xc6\x18\x84\x10\xed\x58\x9e\xe7\x6d\xcc\x50\x9a\xcd\xb2\x0c\x79\x9e\x5b\x4b\x58\x1d\x79\x9e\xb7\x87\x56\x9a\x57\xd6\x05\x00\x9c\x73\x8c\x46\x23\xa4\x69\xda\x2b\xd8\x2c\xcb\xac\xca\x60\x21\x89\x90\xeb\x6e\x56\x3e\xac\xfc\x5e\xd5\xde\xca\x2d\xca\xb2\x9c\x88\xd4\x9c\xf3\x8e\xa9\x2a\x3a\x42\x08\xca\xb2\xec\x58\x91\x72\x13\x25\xa4\xb2\x2c\x41\x29\xc5\xe9\xe9\x69\x6b\xd2\xe6\x1e\xae\xc4\x6b\x50\x10\xf4\x55\x59\x7d\xa5\xae\xbe\xa1\x8a\x0d\xb6\x2b\xcb\x46\x63\xde\x02\xe6\x7b\x15\x3c\xf5\x5b\xca\xb5\x86\xee\x06\x84\x90\x56\x31\x41\x89\x50\x5f\xe3\x22\x44\xb2\x21\x89\x8b\xbe\x96\xb9\x66\x5f\x23\xc5\x57\x84\xd9\x3a\x46\xb7\x6e\xdd\xc2\xa7\x4f\x9f\xfa\x6f\x01\x97\xb9\xfb\x0e\x1d\x52\xb4\xe8\xb7\x41\x68\xdd\x11\x9a\x0a\x9b\xeb\xea\x3c\xab\xf1\xd1\x68\x64\x8d\x01\xde\x20\x18\x0a\x1f\x9d\xab\x0b\x34\x4d\xc5\x18\x52\x62\x0f\xae\x3c\x5d\xc5\x4c\x68\x19\xec\x2b\x7f\x5d\x9a\x99\x96\xf1\x90\x26\x8b\xcd\xff\x83\x8b\x21\x95\xad\xdd\xbc\x79\xb3\x8d\xd6\x3e\x93\xee\xcb\xb6\x6c\x81\xf1\x2c\xbd\x82\x21\xb4\xba\xcb\xf9\x2c\x94\xda\xb4\xbf\xb8\xb8\x38\x11\x89\x6d\x4d\xcf\x50\x86\x5c\x01\x6e\x68\x05\xa9\x5b\x66\x08\xad\xab\x70\xf2\x16\x43\xa6\xb6\xd4\xdd\xac\x47\x54\xf5\xab\xe7\xff\x43\x7c\xd7\x56\x41\xf6\xb9\x84\x2f\x69\x6a\x9a\x66\x22\x1d\xd6\xbe\x71\x78\x0b\xa2\xde\x44\x48\x3f\xa4\xd9\x12\x2f\x8a\x02\x79\x9e\x4f\xd5\x21\x76\x69\x73\x1a\x14\x45\x81\xb9\xb9\x39\x6b\x94\xcf\xb2\xcc\xcb\x17\x0b\x35\xdf\x6b\xd7\xae\xe1\xdc\xb9\x73\x98\x9d\x9d\xc5\xee\xee\x6e\x5b\x99\xd9\x5a\x5b\x36\x6b\xb1\x7d\x5b\xf8\x56\xed\x76\x5d\x41\x7a\x41\xa6\x2b\xcf\x15\x04\x3b\x02\xe0\x9c\x97\x00\x72\xdb\xa7\xa5\x99\x99\x19\xbc\x7a\xf5\x0a\x57\xaf\x5e\xc5\xf9\xf3\xe7\x3b\x69\xf0\xd0\x62\xaa\xaf\x06\x70\xc5\x88\xbe\xf9\x4d\xd3\x60\x6b\x6b\x0b\xcb\xcb\xcb\x78\xfd\xfa\x35\x1e\x3f\x7e\x3c\xb1\xde\x78\x3c\x2e\x7c\xb7\xc0\x23\x5f\x82\xc2\x39\x3f\x53\xab\x6c\xda\xfb\x7b\x88\x45\x54\x55\x85\x8f\x1f\x3f\x4e\x58\xa8\xd6\x47\x78\x64\xb5\x80\xd5\xd5\x55\xec\xed\xed\xfd\xb6\xb1\xb1\xb1\xa5\x4a\x4e\x15\x79\x93\x24\xc1\xf1\xf1\x31\xd6\xd7\xd7\x41\x08\xc1\x9b\x37\x6f\xda\x46\x84\x2d\x6d\x75\x7d\x3e\x1b\x52\x6b\xf8\x3e\x77\x99\xef\x54\x47\xa9\x69\x1a\xec\xec\xec\xa0\xae\x6b\xa4\x69\x8a\x2c\xcb\x3a\xe5\x33\x21\x04\xcf\x9f\x3f\xff\x7d\x61\x61\x01\x47\x47\x47\x5f\xc6\x4c\x46\xf6\xf7\xf7\xff\x9a\x9f\x9f\xff\x41\xf5\x07\x77\x77\x77\x9d\xbe\xce\x39\xef\x94\xba\xbe\xac\xd0\x3c\x54\xe8\xbc\xbe\x4c\x53\x75\xa8\x54\xa1\x64\x5a\x2f\xe7\x1c\x1b\x1b\x1b\xe0\x9c\xe3\xe0\xe0\xe0\xe1\xe6\xe6\xe6\x66\x47\xf0\x36\x6d\xbc\x78\xf1\xe2\xe1\xca\xca\xca\x9d\xba\xae\x7b\x99\x1d\x32\x36\x0d\x8d\x4f\x20\x21\x63\x4a\x51\x2f\x5f\xbe\x7c\x74\xf7\xee\xdd\x3b\x13\x96\xe7\x32\xc9\xa5\xa5\xa5\xe5\x7b\xf7\xee\x7d\x37\x1a\x8d\x66\xcc\xc5\xf5\x06\xa8\xad\xfb\x62\xeb\x2d\xba\xde\xd9\x7a\x90\xb6\x67\xbd\x4c\x76\xed\x69\xa3\x2b\x8a\xa2\xd8\xde\xde\x7e\xf6\xfe\xfd\xfb\x03\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x00\xc0\x3f\x7d\x90\x35\x14\x7a\x41\x74\xf4\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\x28\x1c\x87\x5b\x2a\x06\x00\x00") + +func webdataIconPngBytes() ([]byte, error) { + return bindataRead( + _webdataIconPng, + "webdata/icon.png", + ) +} + +func webdataIconPng() (*asset, error) { + bytes, err := webdataIconPngBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "webdata/icon.png", size: 1578, mode: os.FileMode(436), modTime: time.Unix(1529766470, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _webdataIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x94\xb1\x8e\xd4\x30\x10\x86\xfb\x7b\x0a\x33\x35\x49\x00\x09\x44\x11\x47\x42\x77\x57\x50\x81\xd0\x21\x41\xe9\xd8\xb3\xc9\x70\x8e\x6d\xec\xc9\xde\xed\x3b\x50\x53\x52\x40\xc3\x73\xf1\x24\x68\x63\xed\x25\x97\xdd\x45\x54\xc9\xfc\xf3\xcf\xe7\x19\xdb\x72\xfd\xe4\xea\xdd\xe5\xcd\xe7\xf7\xd7\xa2\xe7\xc1\x36\x17\xf5\xfe\x23\xac\x72\x9d\x04\x74\xd0\x5c\x08\x21\x44\xdd\xa3\x32\xf9\x77\x0a\x07\x64\x25\x74\xaf\x62\x42\x96\x30\xf2\xa6\x78\x0d\xa2\x5a\x1b\x9c\x1a\x50\xc2\x96\xf0\x2e\xf8\xc8\x20\xb4\x77\x8c\x8e\x25\xdc\x91\xe1\x5e\x1a\xdc\x92\xc6\x62\x0a\x04\x39\x62\x52\xb6\x48\x5a\x59\x94\xcf\x9f\x8a\x41\xdd\xd3\x30\x0e\xb3\x30\x26\x8c\x53\xa4\x5a\x8b\xf2\xd9\x89\xf5\x7a\xe6\x50\xe0\xd7\x91\xb6\x12\x3e\x15\x1f\xdf\x14\x97\x7e\x08\x8a\xa9\xb5\xb8\x58\xfc\xed\xb5\x44\xd3\xe1\xe3\xfa\xa4\x23\x05\x16\x29\x6a\x09\x1b\x57\x7e\x49\xd0\xd4\x55\x16\xcf\xb8\x52\xaf\x5e\xbc\x7c\x75\xce\xc9\xc4\x16\x9b\x0f\x38\x78\x46\x71\xe3\x47\xdd\x07\x65\xea\x2a\xcb\xb3\xcd\x92\xbb\x15\x7d\xc4\x8d\x84\x41\x91\x2b\x75\x4a\x20\x06\x34\xa4\x24\x24\x1d\x11\x1d\x88\x88\x56\x42\xe2\x9d\xc5\xd4\x23\xf2\xe3\xbe\x17\x00\xd2\xde\x95\xc1\x75\x20\x78\x17\x50\x02\x0d\xaa\xc3\x6a\x12\x32\xa2\xf7\x91\xf5\xc8\x62\x6f\x7c\xa0\xd4\xd5\x7c\xb4\x75\xeb\xcd\x6e\x01\x37\xb4\x15\x64\x24\xf8\x80\x8e\x5c\x07\x73\x6a\x4a\x87\xe6\xd2\x3b\x87\x9a\xc9\x75\x65\x59\xd6\x55\x58\xd4\x56\x86\xb6\x27\x50\xda\xfa\x84\xe6\x98\x74\x45\x49\x67\x18\x9a\xff\x02\x05\x75\x4c\x39\x24\xac\x6a\xd1\x42\x33\x6f\x7b\x58\x39\xf7\x10\x6d\x55\x4a\x12\xda\x91\xd9\xbb\xb4\x62\xe5\xdd\x98\x52\x13\x74\x33\x5a\x9b\xcf\x23\x8b\xd0\xfc\xf9\xfe\xb3\xae\x72\xf0\xef\xd2\x5b\xdc\xb5\x5e\x45\xf3\x50\xf8\xed\xf7\xa9\xc2\xf5\x9c\x67\xc6\x3e\xd0\xd6\xb3\x33\xde\xb3\x8a\xa8\x26\xd3\x3e\xd8\xdf\xca\x83\xb8\xf2\x2e\x9a\x4b\xe8\xe6\xc6\x7e\xfc\x3a\x6e\x6c\xd1\x47\x5d\xe5\xeb\x51\x57\xf9\xa1\xf8\x1b\x00\x00\xff\xff\xb9\x03\xa0\x33\x39\x04\x00\x00") + +func webdataIndexHtmlBytes() ([]byte, error) { + return bindataRead( + _webdataIndexHtml, + "webdata/index.html", + ) +} + +func webdataIndexHtml() (*asset, error) { + bytes, err := webdataIndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "webdata/index.html", size: 1081, mode: os.FileMode(436), modTime: time.Unix(1529766470, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _webdataMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x55\xed\xae\x9b\x30\x0c\xfd\xcf\x53\x78\xaa\x26\xdd\x2b\x35\x77\xbd\x1f\x93\xa6\xdc\x3f\x7b\x95\x40\x5c\x9a\x35\xc4\x28\x31\xa2\xdd\xc4\xbb\x4f\x21\x94\x42\x0b\xdd\x1a\xa9\x42\xc7\x71\x7c\x7c\x7c\x02\x07\xae\xec\x16\x72\xd2\xe7\x2d\x6c\x6a\xa5\xb7\xb0\x39\xe2\x39\x27\xe5\xe3\x23\xd5\xe8\x8c\x2b\xb7\xb0\x29\x2c\x05\xd4\xf0\x27\x03\x00\x68\x8d\xe6\x83\x84\xd7\xdd\xee\xeb\x67\x0f\x1c\xd0\x94\x07\x9e\x22\x95\xf2\xa5\x71\x12\x76\x9f\x59\x97\x65\xf1\xfc\x21\x77\x4f\x8e\xc5\x5e\x55\xc6\x9e\x25\x04\xe5\x42\xbf\x61\x28\x1d\xd0\xe9\xbc\x61\x26\xb7\x5e\x3c\x57\xc5\xb1\xf4\xd4\x38\x2d\x0a\xb2\xe4\x25\x6c\x3e\x76\x71\xc1\x17\x53\xd5\xe4\x59\x39\xfe\xbc\xdd\x69\x2a\x55\xa2\x84\xc6\xdb\x27\xc6\xd3\x4b\xed\xca\xe7\x54\x77\xa5\x88\x36\xa1\xb6\xea\x2c\x61\x6f\xf1\x94\x4e\x53\xd6\x94\x4e\x18\xc6\x2a\x48\x28\xd0\x31\xfa\x14\xf8\xd5\x04\x36\xfb\xb3\x28\xc8\x31\x3a\x9e\x07\xfb\x76\x83\xf9\x8d\x12\xde\xb0\x4a\xd8\x40\xbb\x3d\x18\xc6\x84\xb4\xe4\xb5\x68\xbd\xaa\x25\xe4\x1e\xd5\x51\x44\x60\x14\x66\x9d\x53\x7c\x12\xda\x78\x2c\xd8\x90\x93\xf1\xe4\xa6\x72\x63\xa2\x55\x39\xda\x21\x7b\xd4\xea\x2d\xae\x94\xce\x78\x62\x11\x0e\x4a\x53\x2b\x7b\x20\xfe\xc4\x6b\x7d\x4a\x7f\x3b\xd8\xbc\xff\x88\x6b\x3b\x06\x1f\xc5\x7a\xfc\x41\xde\x2c\x34\x51\xa7\x1d\xcc\x93\x93\xd5\x53\xf3\x08\xa6\x5a\x82\x6a\x98\x66\x68\x4e\xcc\x54\x4d\x03\x7d\x1b\xfd\x78\x56\xb5\xff\xb8\x68\xff\x40\xe9\x7d\x63\x6d\x28\x3c\xa2\x1b\x2d\x78\xb9\x0a\x23\x70\x35\xe8\xaa\x1b\xd9\x2b\x17\x6a\xe5\x71\xb4\x21\x79\x8d\x5e\xf6\xfd\x07\xb2\x46\x43\x6e\x55\x71\x9c\x06\xc7\xa6\x1c\x39\xbc\xb9\x52\x2f\xdf\x47\xee\xe9\xda\x8d\x3e\xfa\xb7\xb7\x96\xda\xba\x10\x4f\x85\x2d\xee\xf9\x52\x36\xee\x9e\x77\x3c\xdf\xeb\x13\xa3\x2b\xc7\x61\x22\xe9\x8c\x34\x8f\xe9\x19\xff\xef\x5b\x4f\x6d\x4a\x8d\xa3\xbc\xbc\x28\x2c\x9e\x24\xbc\xcd\x35\xbc\xd6\xf6\x98\x3a\xbf\x22\x4b\x72\xdc\x8f\x67\x72\xeb\x06\x64\x98\x46\x97\x65\x2f\xa9\xeb\xb0\x4c\x3c\xf2\xbb\x9f\xff\x8a\x34\x03\xde\x5b\x78\x61\xa8\xfd\x7b\xb2\xcb\xb2\x9f\x15\x6a\xa3\xe0\xa9\x52\x27\xa1\x42\x8d\x05\x0b\xaf\xd8\x90\x84\x8f\x6f\xef\xcf\x43\x8d\x5b\x41\x1f\xdd\xfc\x18\xeb\xb2\x94\x76\x47\x76\x65\xee\x37\xa1\x9e\xf3\xa2\x59\x57\x7c\xb9\xf8\x49\xe8\xb2\xee\x6f\x00\x00\x00\xff\xff\x19\xc9\xf5\x7f\x5c\x06\x00\x00") + +func webdataMainCssBytes() ([]byte, error) { + return bindataRead( + _webdataMainCss, + "webdata/main.css", + ) +} + +func webdataMainCss() (*asset, error) { + bytes, err := webdataMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "webdata/main.css", size: 1628, mode: os.FileMode(436), modTime: time.Unix(1529766470, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _webdataSha256Js = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5a\x5b\x77\xdb\x38\x92\x7e\xd7\xaf\xa0\x75\xb6\xd5\x84\x55\x96\x01\x10\xe0\x45\x14\x94\x63\x3b\xce\xa5\x3b\x9d\xce\xe4\xb2\xdb\x33\x1a\xe5\x1c\x90\x04\x49\x8d\x28\x4a\xa6\x28\x3b\x8e\xe5\xfd\xed\x7b\x40\x52\x37\xdb\x99\xf4\x65\x1e\xf6\x85\x02\xc0\x62\xa1\x50\xf5\xe1\x43\x15\xa9\xd3\xe3\x96\x71\x66\xfc\x24\xaf\xe5\x87\xb0\x98\x2c\x4a\x63\x32\x5b\x64\x6a\xa6\xf2\x52\x96\x93\x79\x6e\xcc\x63\xa3\x4c\x95\xf1\xe1\xd5\x99\x11\xcb\xd9\x24\xbb\xd5\x23\xa9\x5c\xa6\x6a\x09\x86\x5c\xb6\x8c\x48\xc5\x93\x5c\x45\xc6\x24\x37\x5e\xbc\x7e\xf7\xc1\x78\xf7\xe9\xdc\x20\x2e\x3e\x61\x86\xcc\xa3\xdd\x10\xc5\x54\xcb\x1b\x37\x2a\xcb\xf4\xaf\x56\x1a\xce\x8b\x42\x2d\x17\xf3\x3c\x9a\xe4\x49\xcb\x78\xf5\xcb\xd9\xc5\xc3\xe9\xe5\xf2\xe9\x09\x3c\x57\xb6\x5a\xc6\xc5\x7c\x71\x5b\x4c\x92\xb4\x34\x28\xc6\xee\x09\xc5\xc4\x35\xce\x8b\x89\xcc\x8d\x8f\xab\x42\x4d\xc1\x20\x9e\xa7\x87\xb1\x67\xbc\x93\xab\xcc\xf8\x69\x9e\xe6\xcb\x72\x9e\x1b\x1d\xe3\x62\x9e\x97\xc5\x24\x58\x95\xf3\x62\xd9\x32\x9e\x4f\x96\x75\x4f\x45\xc6\x2a\x8f\x54\x51\xd9\x77\xfe\xe1\xb9\xf1\x66\x12\xaa\x7c\xa9\x5a\xc6\x07\xa5\x8c\xb4\x2c\x17\xfd\xd3\xd3\x50\x66\x93\x44\xdb\xd7\x4b\x26\x65\xba\x0a\x7a\xe1\x7c\x76\xfa\xaf\xe5\x87\x57\x67\xa7\x46\x3c\x2f\x8c\xd9\xbc\x50\xc6\x24\x8f\xe7\xc5\xac\x5a\x45\xeb\xf8\xb4\xf5\xe3\x6a\xa9\x0c\x3d\x49\x58\xfe\xe8\x9b\xf1\x2a\x0f\xf5\x1d\xf3\x35\xba\xdb\xb4\x8d\x1b\x33\x04\x09\x11\xba\xbb\x96\x85\x91\x09\x0c\x81\x18\x8d\x21\x11\x18\x62\xc8\x61\x0a\x0a\x52\xb8\x82\x5b\x58\xc0\x4c\x1c\x11\x28\xf5\xdd\x42\x5f\x56\xf0\x55\x1c\x11\x3f\x12\xd1\x7a\x7d\x77\xef\xc7\x22\xea\xa9\x3c\x9c\x6b\xaf\xae\xd7\xed\x4f\x1f\x5f\xb8\x6d\x7f\x25\xa2\x5e\xbe\x9a\xbd\x9f\xaf\xf2\x68\xb9\x5e\x13\x7f\x12\x9b\xab\x23\x21\x16\xb2\x58\xaa\xd7\x79\x69\xae\x80\x60\xb4\x5e\x93\xe1\x0a\x95\x69\x31\xbf\x31\x2e\x8b\x62\x5e\x98\xed\xed\x43\xc6\x6c\xb5\x2c\x0d\x69\x4c\xf2\x52\x25\xaa\x30\x86\xc2\x20\x6d\xa4\xf5\x60\x21\x44\xd8\xcb\xe4\xb2\x7c\x9d\x47\xea\xcb\xaf\xb1\xd9\xfe\xf0\xea\xec\xa4\x0d\x18\xa1\x49\x6c\x5e\x89\xed\x72\x03\x90\xe8\xae\x50\xe5\xaa\xc8\x8d\x33\xdd\x83\x10\xdd\xc3\xed\x81\x00\x64\x10\xd7\x3e\x48\x40\x69\xf5\x95\x32\x4a\x59\x5b\x4f\xb3\x5e\xd7\x5d\x6e\x57\x5d\x94\x08\x53\x76\x6d\x3e\x1c\x0e\xbd\xc1\x80\xa1\x2e\xe1\xa0\x04\xb1\x7d\x95\x2d\x95\x71\xb0\x90\x4f\xb9\xfa\xb2\x50\xa1\x0e\xb1\xd2\x23\x1a\x50\x95\xaa\x07\x98\x6b\x23\x3f\x9e\x17\xa6\x1f\xf4\x32\x95\x27\x65\x3a\x10\x89\x8f\x82\xde\x62\xb5\x4c\x4d\x8c\xfc\x60\x24\x87\xc3\x21\x1f\xaf\x05\xa1\xee\x60\x40\xd9\x89\xfc\xc1\xa2\xbe\x14\xb2\x9b\xf9\xc1\x28\x19\x0b\xd9\x61\xd4\x63\x9e\xed\x50\x8f\xfb\xad\x60\x94\x9c\x90\xb1\x90\xa7\xdb\x41\x7b\x8d\xfd\x4c\x6c\xd4\x57\x93\x49\x81\x7d\x39\xc8\x7c\xd9\x15\x0a\xc5\xe2\xcc\x0c\x7a\xcb\x6c\x12\x2a\x53\x82\xec\x2a\x04\x31\x84\xe8\x91\x2b\x50\x20\x46\xf1\x08\x8f\x21\x1e\x11\x7d\xa1\xfa\x62\xe9\x0b\xd3\x17\xae\x2f\xf6\x78\x5c\xbb\x62\xfb\xf0\xc6\x71\x81\x88\xff\x9a\x93\x9a\x30\x06\xf7\xb0\xd8\x8b\xdf\x36\xbc\x9b\x15\xa0\x7b\x38\xb4\x3a\x15\x9c\x50\x50\x82\x52\xf6\x0d\xd3\xb6\x12\xfc\xa9\x38\x5e\xa4\xf3\xa5\xaa\xac\x32\xae\xa5\xde\xec\xa5\x31\x59\x1a\xf9\xbc\x34\x96\xab\xc5\x62\x5e\x94\x2a\x6a\xa3\x3f\xfd\xdc\x54\x9c\x9b\x12\x62\xe4\xe7\xe2\x8b\x19\x22\xbf\x4c\x27\xcb\xde\x52\x95\x9a\x9c\x7e\x56\x0f\x90\x9a\xd4\x38\xad\x50\x7a\xa4\x77\xc1\xec\x70\xef\x54\x8c\x36\x55\xb7\x86\xcc\x0a\x25\xa3\x5b\x63\xa9\xca\x36\xf2\x5b\x1b\xf1\xaf\x87\xe2\x17\x32\xaf\xcc\x51\xa5\xb1\x7b\x32\x2e\x55\x61\x84\x32\xcb\x26\x79\x62\xac\x16\x91\x2c\x95\x46\xa8\x30\x13\xbd\xd9\xd1\xe3\x9d\x2e\x9b\x15\x98\x01\xf2\x03\x21\x7b\xc1\x24\x7f\xa3\x72\x0d\xd0\xde\xb5\xcc\x56\xca\x57\x22\x1d\x0e\x87\x96\x9f\x08\x75\xca\x4e\x2a\x26\x50\x83\xe0\xd4\x45\x77\x35\x14\x6f\x4d\x09\x01\x60\xd0\xeb\x47\xbe\xdc\xdf\x06\x72\xbb\x0d\xe4\x28\x19\x77\x44\x83\x69\xcc\xf0\xfd\x26\x94\x6a\xb8\x55\xf5\xbb\x9f\xd5\xc2\x81\xc0\x7e\xa0\x05\x83\xae\x20\xa8\x1c\x05\x63\x21\x47\xc1\xf8\xb3\x87\x3d\x4e\x29\x73\x6d\x28\xb6\x63\x84\x33\x8f\x73\xdb\xa5\xae\x9f\x8b\x2b\xb3\x84\x1c\xf9\x99\x48\xfd\x99\x38\xc2\xf7\x75\xc8\x6a\x4f\xed\xc2\x25\xeb\x50\x85\x10\x83\x82\x48\x60\x58\x54\x5e\xe0\x7e\x28\xa6\xd5\x7a\x13\xe4\x4b\x11\x6e\xbc\x15\x8b\xb0\xf1\x56\x28\xaa\xfd\x5e\x6d\x53\x25\xb0\xaf\x06\xa1\xaf\xba\x62\x81\xa2\x6e\x3a\x10\xb2\xd3\x31\xb5\x09\x71\x83\x76\x05\xaa\xbb\x40\x90\x23\x88\xba\x22\x45\x7e\xd6\x15\x91\x1f\x88\xcd\xed\x68\x38\x1c\xb6\x38\xf2\x13\x21\x7f\x48\xfd\xaf\x3b\x73\x13\x55\xbe\x92\xcb\x74\xcf\xde\x0d\x09\x46\x90\xc2\x14\xae\xbe\x05\xb1\x06\x33\x1a\x20\x46\xa3\xa4\xc1\xcc\x52\x95\xa5\xc6\xcc\x06\x4a\x15\xb8\x2f\xcc\x18\xf9\xcb\x9b\x49\x19\xa6\xda\x25\xa1\x5c\x2a\xa3\xfd\xea\xf2\xb7\x76\x3f\x3a\xf0\x55\xb3\x89\x9f\x9b\x12\x14\x4c\xd1\xbd\x1f\x14\x4a\x4e\xfd\x5a\xfe\xdc\x66\xdf\x90\xbf\x7c\x5a\xfe\xef\x1f\x2f\x3f\x7c\xe3\x89\x17\xfa\x89\x07\xf2\x67\xef\xdf\x9f\xfd\xfd\xfc\xd3\x8b\x17\x97\xef\xdb\xfd\xb2\xb8\xbd\x4b\x45\xae\x6e\x8c\xb3\xa2\x90\xb7\xe7\xab\x38\x56\x85\x89\xd1\x7d\x28\xf5\x22\xae\xd1\xdd\x81\x3f\xf6\x9e\x3d\xdc\xdb\x46\x70\x6b\x68\x57\x1b\x2a\xbf\x9e\x14\xf3\x5c\x53\x59\x1b\xf9\xf7\x4f\x5a\xf5\xf2\xc0\xaa\x48\xc5\x72\x95\x95\xfd\x83\x89\xea\xd3\xbd\x3e\x14\x03\x65\xbc\xba\xfc\x0d\x8c\x73\x9b\x81\x51\xad\x16\x8c\x79\x61\xec\xaf\x03\xf9\xad\xfb\x2b\x71\xbb\x25\x76\x04\x09\x64\xb0\x30\x73\x54\x1f\x37\xa9\x20\x7e\x3a\x58\xf9\xa9\x46\xbf\x16\xbc\x02\xb5\xdd\x83\x8d\x55\x91\x79\x85\xf6\xf0\xf2\xcb\xd9\xc5\x93\x78\x99\x42\x09\xab\x0a\x2f\xe4\xfb\x78\xd1\xe0\xb8\x99\x94\xe9\x7c\x55\x1a\xf1\xa4\x58\x96\x4f\xe1\xa6\xfc\x73\xb8\x29\xff\x20\x6e\x1e\xc9\xff\x55\xdc\x44\xff\x0f\x71\x33\x5f\x95\x8b\x55\xf9\xe2\x8f\xa3\x67\xfa\x0d\xf4\xac\xc4\x95\x59\x34\x40\x59\x89\x5b\xb3\x4e\x14\x57\x7b\xa8\x59\xa1\xfb\xfb\x6d\x96\x39\x33\xd1\xdd\xae\xf7\xfc\x30\xe7\x6c\xb7\x7d\x79\x2a\x5c\x5f\xf7\x02\x48\xfc\x1d\x31\xcb\x9a\x97\x13\x11\x8e\x82\xe1\x70\x48\xc7\xc3\xe1\xd0\x3d\x36\xad\x6e\xf0\x03\x3b\x3e\x21\x08\xb2\xae\x68\x63\x42\x2d\xc6\x6d\xc7\xf5\x64\x10\x46\x2a\x6e\xf7\xc2\x54\x16\x67\xa5\x99\x0c\x87\x43\xd6\x21\x1c\x75\xff\x8d\x8c\xbe\xbf\x35\xba\x57\xfb\xe9\xd3\x62\xa1\x8a\x67\x59\xaf\x9c\x57\xad\x0b\xb9\x54\x26\xea\x67\xbb\x05\x5c\x3e\x5c\x00\x04\x42\x9e\xba\x90\xe8\xa4\xb9\xb2\x3f\x11\xd8\x4f\x06\x81\x9f\x74\x85\x85\xf4\x40\x2c\x92\x2e\x19\x04\xcf\xc2\x51\xd2\x25\xd5\x5a\xfa\x18\x72\x91\x74\x69\x33\x48\x77\x83\x66\x38\x4a\x0e\x96\x9b\xd4\xcb\xed\x50\xce\xd1\x60\x40\xec\xb5\x19\x6f\x6e\x99\x49\x97\xa0\x83\xdb\xee\x3a\xdf\xbb\x49\xf7\x6e\x42\x2c\xb0\xcf\x86\xb1\x1f\x6b\xaf\xba\xc7\x49\xd7\x3e\x8e\x07\x42\x3e\xd3\x6e\x3c\x3b\xbf\x78\x7e\xf9\xe2\xe5\xab\xd7\x3f\xfd\xfc\xe6\x97\xb7\xbf\xbe\xfb\xdb\xfb\x0f\x1f\x3f\xfd\xf7\xff\xfc\xf6\xf7\x7f\xd4\x2e\x4b\xd2\xc9\xbf\xa6\xd9\x2c\x9f\x2f\xae\x8a\x65\xb9\xba\xbe\xf9\x72\xfb\x75\xe7\xd6\xee\xe9\xd6\xa5\x7a\xf6\x96\x7d\x6c\x5a\x27\x31\xea\xd8\x16\xea\xeb\xe3\xa8\x17\xd8\xec\x9d\x8c\x36\x9e\xde\xf3\xe5\x0b\xed\xcb\x86\x45\xb4\x27\xb3\xca\x93\x87\x38\xc8\xbe\x83\x83\x6a\x71\x51\x57\x7c\x28\x8b\x49\x9e\xf4\xe2\x62\x3e\xbb\x48\x65\x71\x31\x8f\x94\x99\xec\xc2\xbb\x9b\xf4\xe5\xfe\xa4\x7a\xbe\x0c\x82\x47\xdb\x36\x42\x90\xf8\x49\x35\xfc\x69\x92\x97\x6e\x75\x4f\x27\x38\xda\xb0\x4c\x60\x3f\x1b\x44\xfa\xac\x25\x28\x19\x65\x63\x11\x8e\xb2\x03\xdb\xb2\x9d\x6d\xbb\xb4\x75\x6b\xc1\x85\x19\xd6\xf3\x4b\x71\xb7\x87\xba\xfe\x11\x81\xda\x55\xfd\xb6\x68\xc3\x32\x95\x53\xf5\x46\xe5\xfd\x13\x72\xef\x87\xba\x10\xb9\xbb\xf7\xe5\x3e\x4c\x45\xb8\xdf\x5b\xaf\x8f\x88\x7f\x54\x97\x46\xa9\x5c\xfe\x7a\x93\xbf\x2b\xe6\x0b\x55\x94\xb7\x66\xbb\x56\xdb\x46\x9d\x8e\x29\x9b\x70\xe8\xd4\xa3\x6a\xd4\x79\x7e\x30\x9f\x67\x4a\xe6\xed\x23\x21\xca\xdb\x85\x9a\xc7\xc6\xc1\x54\x87\x9c\xfe\x3a\xbf\x96\xd9\x24\x32\xf6\x04\x8c\xfa\x78\xaa\x88\x7c\xbe\x68\x32\x76\x9d\x77\xb6\x97\x55\x60\x0e\x14\x37\x13\x3f\xa9\xb3\xbe\xf7\xa4\xba\xc6\x93\x72\xe7\xc9\xf3\xbd\x58\x3e\x3a\x2d\xaa\xec\xb4\xbf\x6d\x13\xfb\xfc\xf2\xa0\xfb\xe6\xb2\xdd\xff\x37\xbc\xb9\xc9\x73\xb7\x9c\xa9\xf5\x81\xd1\x68\xaa\x18\x73\xa3\x06\xf9\xf7\xcd\xe4\xe1\x37\x8f\x2a\x08\xa0\x89\x7a\x2c\x36\x69\x2a\x44\x9b\x2a\xbb\xaa\x6a\x8f\x84\x88\x7f\xa0\x87\x6e\xa9\x61\x6d\xcc\x63\x4d\xd9\x86\xf6\xe0\xd6\x9e\x49\x6e\x04\xb7\xa5\xfe\x0d\x8b\xaa\x50\x5a\xb6\x75\x02\x1e\xac\xd7\x23\x3c\xae\x11\x83\xfd\x2b\x11\x56\xb9\xb7\xc6\x6d\x24\xb0\x1f\x0d\x62\x3f\xea\x0a\x8a\xee\xa6\xbb\x52\x5c\xf6\x96\xab\x60\x59\x16\x66\x04\x14\x01\xb1\x2b\x48\x4c\x96\x6f\xe5\x5b\x73\x8a\xbe\x6b\x4f\x38\xcf\x4b\x39\xc9\x97\xc6\xa4\x09\xa1\x26\x03\x19\x96\xaa\xd0\x06\xb5\x52\x51\x65\xa1\x04\x75\xaf\x9a\x9c\x56\xe7\xc1\x74\xaf\xdc\x55\x87\xe5\xae\x1a\xaf\xc5\x74\x30\xa8\x36\x52\x5a\x6f\xa4\xfb\x3a\xf4\x77\x55\x86\xdc\x0f\xa0\x4e\x9a\xfb\xec\x38\xee\x86\xf7\x87\x67\xf2\xc7\xcb\xdf\x3e\x1e\x78\x3e\x84\x60\x43\xd7\xd5\x6b\x0d\x81\x9b\x17\x1b\x33\x58\x40\xb1\x73\x58\xf5\x36\x43\x3b\x2c\xaa\x1c\xa6\xa1\x5b\x21\x48\x08\x21\x2b\x1a\x2f\x84\x05\x4d\x42\xbe\x29\xa5\x95\x66\x80\x9a\xe2\xc3\x8a\x03\x35\xed\x9c\x95\xa6\x42\x90\x8b\xd1\x18\x08\x75\x87\xf1\xb3\xbc\x5e\x5c\x8c\xfa\x14\x33\x3d\x60\x36\x23\xc4\xa3\x6b\xcd\xe6\x36\x82\xcd\x08\x75\xd7\xb1\x66\x4e\xd4\xe7\x9c\x7a\xf6\x30\x5e\xaf\xb9\x63\x31\x36\x10\x5b\x3d\x94\xb2\xea\x29\x42\xa1\x12\xd7\x0a\x3a\xb6\x05\xdb\x67\xfb\xa6\xb6\x0b\x62\x61\x73\x6e\xd9\x5d\xd3\x8c\x3b\x04\x53\x4b\x1f\x1f\x78\xfd\xc0\xce\xfa\xce\x66\x7a\xca\x70\xad\xda\xdd\xaa\x26\x74\xab\xfb\xd1\x44\x08\x52\x81\xfd\x74\x90\x6f\xfc\x51\x25\x93\x77\x0b\x31\xed\xb6\xea\x60\xcf\xc4\xe2\x41\xb0\x67\x87\xc1\x9e\x8d\xd7\x22\x1f\xa5\xe3\x2a\xde\x45\x77\x51\xc7\xdb\x9f\x76\x05\xd9\x56\x78\xdb\xdd\xab\x43\x51\x97\x9d\xd5\xb6\xdb\x8b\x0c\x85\x5c\x1c\x8c\x77\x3a\x47\x78\x4f\xf4\xa8\x1e\x22\x4f\x06\xf0\xee\x51\xf4\x6a\x1e\xcd\x3b\x1d\x33\x15\x71\x73\x7c\xa6\xfa\x78\xad\xce\x5e\xe4\xeb\x15\xfe\x81\x05\xc6\x8f\x57\x47\xbf\x01\x69\xf7\x78\xda\x8d\xee\xbf\x93\xc6\xee\x73\x09\xde\x91\x88\x46\xb4\xc6\xed\x89\x4e\xc3\x65\x6f\xa9\x64\x11\xa6\xe6\xe9\xe7\x91\x3c\xf9\x7a\x76\xf2\x0f\x7c\xe2\x89\xee\x3f\x4f\xc7\xdd\xff\x3a\x45\x4f\x73\xef\x76\xe3\x56\xdc\x22\x97\xea\xc4\x66\x46\xc3\xdf\xba\x98\x93\xbd\xc9\xe6\x7d\x9b\x68\xa3\xaa\xc2\x2f\xd4\x22\x93\xa1\x32\x4f\xff\x29\x4e\x13\x68\xb5\xeb\x17\x74\x27\xe4\x48\x88\x69\xa7\x33\x1d\x6c\xa8\xee\xe9\x09\x7f\x14\x3f\x1a\xf1\x7c\x95\x47\x4f\x4e\xf8\x90\xcb\x66\x7b\x5c\x36\x15\xd8\xdf\x69\xd7\x1e\x65\xe8\xee\x4a\x6c\x99\x6c\x0a\x0c\x6d\xe8\xa6\x0a\xf9\xd5\x41\xc8\xa3\xff\x44\xd2\xb3\x71\xc6\xd5\x48\x8d\x11\xa4\x6b\x11\x0d\x06\xc4\x3d\xb1\x8f\xd5\x5e\xf1\xbe\x99\xf7\x84\x34\x60\x5b\x88\xb8\x3b\x6b\xf8\xf8\x21\x76\xa2\x43\xec\x44\xe3\xb5\x30\x35\x5b\x12\xfb\xc4\x3d\x56\x9b\x24\x4f\x13\xe3\x06\x4a\x3a\x9d\xbb\xff\x26\x96\x1e\xd3\xe3\x13\x25\xce\x0e\x4d\xd1\xe6\xb5\xef\x23\xd7\x4f\xf7\x5c\x9f\x0b\xec\xe7\x3b\xd7\xe7\x5d\xd1\xd2\x0e\x95\xfb\x5b\x28\xd7\xd4\x90\x77\xa7\xd0\xb0\x3d\xec\xb1\x7d\xa7\xb3\x5d\x23\xd4\x6c\x1f\x1d\xb2\xbd\xff\xad\xe5\x6c\xe6\x7c\xb4\xaa\x3f\x52\x88\x65\xff\xc9\x42\xec\xf7\xf8\x2e\x6f\x7c\x97\x3e\x4c\x27\x25\xda\x3b\x96\x65\x4f\x1f\xe6\x6f\x6a\x9f\x46\x1a\x29\x4a\x44\x5d\x7d\x5e\xa9\x07\x0e\x9c\x1e\x3a\x70\x3a\x5e\x8b\x74\x14\x8d\x1b\x1f\xaa\xef\xfa\x70\x37\xcf\x9e\x1f\x7f\xf7\x2b\x07\x7d\xbe\x7e\xb7\x74\x7c\x9c\x75\x17\x75\xa6\xd6\xdc\xd0\x0e\x91\xeb\x70\x30\xb0\xe8\xc9\x5e\x3a\xf7\xd3\xa6\xb6\xda\x88\x75\xe4\xe7\xff\x0d\x3b\x7b\x6a\x7e\x7e\x42\x22\xec\x44\x9f\xe5\xbe\xd0\x1b\x9d\x86\x35\x02\x7a\x5e\x8a\x3e\xeb\x1f\x62\xd5\xbf\x94\xa2\x9d\xec\x2f\x0f\x64\xed\x46\x96\x34\xb2\x7c\x4f\xf6\xed\x03\x59\xa7\x91\x75\xd1\xe7\x2a\xc2\x3b\xc9\x5f\x1f\x48\x92\x8d\xa8\x57\x8b\x12\xbc\x93\x7d\xb7\x5f\x8f\x98\x61\x47\x1f\xda\x1c\x75\x4d\xd9\xb4\x9a\x48\x9a\x66\xf5\xa0\xad\xef\x6c\x1a\x51\xdd\x68\x04\xab\xea\x30\xaa\x3b\x3b\xf5\x7f\xab\x3d\x06\x59\x3d\x45\xf0\xd4\x14\x5d\x33\xda\xb6\xb2\xdf\x3d\x6d\xd7\xcc\x36\x0d\x5d\x99\xb5\x1e\x58\x12\x3c\xb4\xe4\xfd\xc6\x12\x08\x9a\xcf\x2d\xbf\xd7\x96\xae\x19\xfc\x59\xab\xaa\x46\xf2\xd8\x4f\xc9\x43\xeb\xbe\xec\x8a\xb2\xd1\x18\xa2\xef\x7d\x66\xda\x14\x1b\x62\x64\x51\xcb\xb5\x1c\x82\x2d\x0a\x1e\x61\x84\x63\xdb\xb6\xc0\x25\xd4\xc1\xd4\xf3\x3c\x60\x84\x31\x8f\x50\xdb\x73\x80\x51\x0f\x3b\x0e\x77\xb9\x03\xc4\xe1\xd8\xc6\x16\xa6\x1c\x88\xed\x31\xec\xd8\xae\xe5\x81\x45\x31\xc3\x0e\x67\xd4\x1d\x43\x24\x46\xc4\x71\x3c\x6c\x59\x0e\xb6\xc0\x22\x8c\x11\x8b\x51\xc7\x01\x82\x89\xe5\x61\x46\x19\x05\xea\x38\x16\x73\xb1\x63\x53\x20\x16\xf7\x5c\xcf\x22\xc4\x03\x6a\x63\xec\x52\xea\x51\x06\x9c\xba\x8e\xc5\x6c\x8b\x03\xe1\x8c\x30\xee\x51\xca\xc7\xb0\x2d\x52\x36\x9f\x49\xfa\xfb\x5c\xba\xf9\x32\xd2\x97\x22\xf2\x1f\xde\xb0\x5c\xa6\x6f\x8c\x34\x93\xcd\xa0\xbe\xb6\xf6\x3b\xdf\xb8\x8e\x1f\x69\xe2\x84\x3e\xd2\xf4\x07\x14\x3d\xc9\x57\x9f\xf2\x69\x3e\xbf\x39\xf8\xe4\xa2\x09\xfb\xf1\xa7\x99\xb7\xf3\x7d\x99\xe5\xc1\x07\x99\xc7\x55\xe6\xd9\xc1\x2b\x1f\x08\xea\x77\x3d\x4d\xd6\x35\x83\x02\x16\x70\x03\x25\x7c\x81\x15\x7c\x85\x33\x38\x87\x0b\x78\x0e\x97\xf0\x02\xae\x35\x94\x5e\x3e\xfc\x8e\x16\x1d\x7e\x52\x8c\x50\x21\x6c\x06\x37\x82\xc0\x0b\xf1\x76\x35\x0b\x54\x01\xa5\x78\x07\x5f\xc4\xdf\x60\x25\xde\xc3\x57\xf1\x16\xce\xc4\xaf\x70\x2e\xde\xc0\x85\xf8\x05\x2e\xc5\xcf\xf0\x5c\xfc\x04\x2f\xc5\xab\xbf\xf6\x3d\x2d\x12\x52\x9f\x52\x99\x90\x23\x32\xf6\x03\x21\x47\x74\xec\x27\x42\x8e\xac\xb1\x1f\x0b\x39\x62\x63\x3f\x17\x72\xc4\xc7\x3a\xf3\x1b\xd9\x63\x5f\x09\x39\x72\xc6\xd5\x99\xb5\x10\x2d\xec\x2f\x06\x85\xbf\xd0\x27\x15\xb1\x87\x8b\x67\x3a\x15\x3e\xbe\x81\x54\x84\xbb\x54\xf8\x19\xee\x87\xa3\xd9\x18\x66\xfb\x83\x5d\x52\x0f\x77\xc9\x18\xae\x47\x8b\x71\x75\x2c\xbe\x30\x53\x98\x21\xd4\xaf\x06\xbe\x98\x67\xe6\xf5\x68\x71\x42\xc7\x48\x4b\x9c\x38\x63\xf8\x5a\x0d\x10\xde\x8c\x10\x5b\x67\x5c\x62\x65\x2a\xb8\x30\x63\x04\xcf\xcd\x2a\x22\x08\x5e\x8e\x16\xb5\x56\x04\x33\x51\x9a\xe7\x66\x84\xe0\xd2\xac\x49\x07\x81\x12\x53\x98\x8a\x1c\x72\x11\x43\x2c\x4a\x33\x81\x14\x41\x22\x02\x08\x44\x06\x99\x88\x20\x12\x65\x65\x88\xaf\x5d\x23\x4a\x33\x02\xdd\xd0\x5d\xa2\xbb\x19\xe8\x86\xee\x52\xdd\x0d\x40\x37\x74\xd7\x1a\x57\xda\x74\x43\x77\x99\xee\xc6\xa0\x1b\xba\xcb\x75\x37\x07\xdd\xd0\x5d\x5b\x77\xa7\xa0\x1b\xba\xeb\xe8\xae\x02\xdd\xd8\x43\x9f\xc6\xda\x2b\xff\x95\x18\x11\x42\x6c\x8b\x53\x86\x5d\x20\xae\xe7\x31\xe6\x30\x46\xc0\xc2\xcc\xb3\xa8\xc5\x1c\x02\x96\x47\x09\xc6\x1e\x77\x2c\xf0\x6c\xe2\xb9\x0e\xd1\x35\x1a\xc7\xae\xe7\x60\xcf\xb3\x80\x32\x6e\xd9\x16\x77\x98\x0b\xd4\x75\xb0\x63\x5b\x94\x12\xb0\x6c\xca\x2c\x97\x60\x17\x83\x45\x30\xf7\x5c\x86\x09\xd8\xd8\xa1\x94\x53\xc7\x05\xc2\xa8\xed\xba\x5a\x1b\x10\x8f\x72\xec\xb8\x96\xeb\x02\x25\x36\xc5\x8e\x4b\xb1\x0d\x2d\x6a\x13\xe6\xba\x2e\xd1\xec\x44\x99\x4b\x29\xe5\x5a\x97\x6b\x71\x4d\x4f\x98\x00\xc3\x94\x52\xca\x1c\x87\x01\xb5\x99\xc5\x1c\xec\xb8\x60\xe3\x9a\xb0\x5c\x70\x1c\x4c\x39\xf7\x5c\x5d\x4f\x32\x8f\x70\x4c\x28\x05\xc2\x39\xc7\x2e\xb1\x3d\x0a\xc4\xf3\x6c\x6c\x33\xcf\xb5\x81\x72\xce\x28\xc5\xae\x4b\x81\xba\x94\xb8\x16\xb3\x98\x07\xd4\xe3\xd4\xf3\x6c\x17\xbb\x60\x51\x82\x2d\x62\xd9\xda\x1b\x96\x65\x73\x87\xb8\x1e\x01\x8b\xbb\x4c\x33\x20\x21\x40\x88\xe5\x51\x5b\x7b\xc3\xb2\x5c\xca\x88\xeb\x71\xb0\x6d\xdb\xc2\x0e\xc5\x1c\x1c\xc7\xd2\xaa\xaa\x82\xda\x63\x0e\x77\x2c\x47\x33\xaa\x67\x13\xcd\xa3\x44\x53\x34\x27\xae\xe5\x60\x0c\xc4\x73\x6d\xdb\x26\x98\x13\xa0\x44\x2f\xc1\xb6\x38\xd6\x2e\xb6\x3d\x6e\x63\xcb\x01\xea\x58\x98\xb9\xdc\xa3\x44\xdb\xaa\x29\x9e\x11\x02\x16\xe5\x9e\x63\x61\x17\x63\xb0\x2c\xc6\x1d\x9b\x39\xda\x56\x4e\x6c\x6c\x73\x97\x38\x60\xd9\x18\x5b\x9c\xba\x98\x01\xc3\x1e\xe3\x0e\xf1\xb0\x07\x54\x1f\x06\x96\xc5\x18\x30\x0b\xd3\x8a\xee\x81\x63\xdb\x63\xae\x4d\x6c\xb0\xb9\x87\x6d\xcc\xb9\x0d\xae\x6b\x79\x9e\xe3\x3a\x0e\x78\xdc\x25\x96\xc7\x1d\x02\xc4\xa2\x54\x47\x45\xd7\xf2\x5c\xdb\x4e\xb1\xc6\x85\xc3\x1c\xd7\xb1\x1c\xc7\x03\xe2\x71\xce\x6d\x1d\x23\xa0\xda\x4a\xcc\x5c\xc2\x81\x56\xd3\x60\xc6\x29\x50\xcb\x26\x2e\xa7\x8c\x32\xa0\x8c\xba\xcc\xb2\x99\xc3\xa0\x45\x1d\x6e\x3b\x16\x23\xae\x53\x1f\x58\x16\x61\x8e\x07\x96\x45\x3d\x8b\x72\xea\xb9\x63\xbf\xbd\xa1\x4e\xcd\x6f\xcd\x5b\xbf\xfa\x5f\x35\x9d\x4e\xfd\xdb\x93\xb3\xe8\x59\xdd\xdc\xfd\x37\x65\x9b\x32\xdd\xdc\xa3\x7e\x7b\x95\x37\x7f\xc4\xd9\x7b\x75\xa8\xbe\x68\x9a\x5e\x3e\x33\x9f\xbc\x3b\x9b\x47\xab\x4c\x75\x3a\xf5\x6f\xaf\x11\xee\x74\xcc\xc3\x01\x71\x83\x60\xd7\xec\xbf\xee\x55\xff\xa4\x11\x37\xf7\xc8\xd4\xe9\x3e\xf2\x5b\xff\x17\x00\x00\xff\xff\x8a\x1d\x7d\x6b\xa4\x24\x00\x00") + +func webdataSha256JsBytes() ([]byte, error) { + return bindataRead( + _webdataSha256Js, + "webdata/sha256.js", + ) +} + +func webdataSha256Js() (*asset, error) { + bytes, err := webdataSha256JsBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "webdata/sha256.js", size: 9380, mode: os.FileMode(436), modTime: time.Unix(1529766470, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _webdataTexPng = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\x26\x0f\xd9\xf0\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\x00\x00\x0e\xed\x49\x44\x41\x54\x78\xda\x75\x9b\xe7\x72\x1b\x4b\x0e\x85\x31\xdd\xd3\x13\x49\x51\xf2\x7d\xff\x47\x5c\x8b\x69\x72\xe8\xfb\x63\x01\xd7\x67\xac\xd6\x55\x2a\xd2\x13\x3a\xa0\x81\x83\x83\xc0\x42\x44\x3e\xe5\xbf\xff\xee\x22\xf2\x25\x22\x2f\x11\x29\x44\xe4\x43\x44\x46\x11\xa9\x45\x64\x12\x91\x56\x44\xa2\x88\x3c\x45\xa4\x14\x91\x55\x44\x92\xde\x2f\x74\x8c\xa7\x8e\x21\x22\xf2\x5b\x44\x6e\x22\xf2\xd6\xf7\x2e\x22\xb2\x88\xc8\xa6\x63\x05\x9d\xf3\x43\xaf\x1d\x22\xd2\x8b\xc8\xa0\x9f\x9b\xce\xc3\xb1\x0b\x11\x69\x74\x8d\xb5\x5e\x5f\x74\x9e\x5d\xc7\x4c\x3a\xd6\x53\x44\x3a\x11\xa9\x44\xe4\xd4\x35\x1c\xf8\xbc\x8b\xc8\x67\x21\x22\xff\xe8\x66\xa2\x2e\xf6\xa2\x0f\xd8\xdf\xa9\x93\xd5\xd8\x98\x88\xc8\x2f\xfd\x3c\xf4\xfd\x56\xbf\x8b\x2e\x30\xeb\xe6\x6c\x61\xab\x2e\x5e\x9c\x40\xef\xba\xe8\x02\xf3\x65\x9d\xaf\xd2\xe7\xa3\x7e\x9e\x2a\x98\xac\xe3\x66\xdd\xe4\x43\x85\x60\x07\x79\xc5\xbb\x6f\x9d\x4b\xdc\x7c\x8d\x88\xcc\x85\x4e\x7c\xd3\x81\x1b\x1d\xb8\xd0\xc1\x0b\x11\x99\xf5\x7a\xc4\x06\xc5\xfd\xdf\x16\xde\x38\x21\x5c\xf5\xfb\xa6\xf7\x3b\x3c\x2f\x38\x11\xd1\xb9\x46\x08\xe6\x70\xc2\x7a\xe9\x18\xbf\x70\xf2\xb5\x6a\x4c\x83\x75\xed\x2a\xec\x52\xd7\xde\xeb\xb8\x9d\x8e\x1b\x39\x77\xd0\x53\x8a\xfa\xe2\x1d\x2a\x57\xe8\xf5\x80\x17\x16\x6c\xee\x50\x21\xd9\xa4\xa6\x7a\x0f\x8c\x11\xf5\x1d\x33\x15\x53\xbd\x51\x37\x33\x61\xe1\xd9\x09\x68\xd0\xef\xad\x6e\xe4\xaa\xe6\xfa\x82\x60\xb8\xf9\xbb\xce\x57\xeb\x38\xa7\x0a\x21\xc2\xcc\x0f\x98\x5b\x14\x91\xdf\x51\x17\xbb\xaa\xa4\x0a\x48\x48\x74\xf3\x41\x17\x57\xea\x46\xde\xaa\x5e\xb6\xb9\x52\x27\xb5\x67\x4d\xf5\x6c\xc3\xb3\x7e\x8f\x3a\x8e\x61\x40\xd2\x3f\x5b\x7c\xa3\x8b\x36\xed\xab\x74\x83\x2d\x4e\xae\xd0\x8d\x47\x7d\xbe\xc4\x5a\x7b\x9d\x6f\xd2\xcf\x46\xff\x82\x0a\xcd\x84\x61\x9a\x91\x04\x17\x2e\x6a\xdb\x3d\x06\x7c\xe9\xc9\x6e\xba\x81\x13\xf6\x65\x42\xb2\x05\x3c\x74\xa1\xa3\x5e\xcb\xba\x88\x0a\x9b\x34\x01\x35\xba\x80\x08\xa1\x98\xe9\x94\x18\xdb\xd6\x76\xa8\xd0\x57\x08\xbb\xd0\xb1\x0c\x28\x03\x80\xb2\xd2\xbf\xd5\x1d\x5e\x80\x69\xd9\xbd\x22\x02\x3c\x3a\x7d\x38\xea\xe6\x3f\x75\xa0\x11\xf6\x66\x92\x0b\xb8\xb6\xeb\xe6\xef\x2a\xc0\x87\x6e\x28\xc1\x56\x03\xd4\x3d\xea\xb8\x19\xf3\x65\x00\xe1\x5d\xc7\x34\x01\x6c\x7a\x40\x83\x2e\xdc\xbc\x52\xa9\xd7\x78\x08\x3d\x4e\xb8\xc6\xf5\xc6\x61\x4f\x65\x42\x8c\x58\x68\xd6\x81\x33\x54\x67\x56\xc1\xd4\x58\xd0\xa4\x2f\xdb\x26\x16\x7d\xde\x54\xbf\xd1\x4d\xd4\x50\xbf\x46\x17\x6f\x9a\xf0\x8d\x93\x7c\xe8\x1c\x87\x9d\x8a\x6a\x9b\x01\x6b\x82\x49\x34\xba\xe9\x4e\x3f\x03\xdc\x9c\xcd\x61\x58\xf2\xad\x02\xa9\x60\xb6\x33\xc6\x7a\x89\xc8\x1e\xa0\x3e\x41\x25\x7f\xc0\xdd\x25\x98\xc4\x81\xd3\xb3\xeb\xab\x9e\xce\x7f\x30\xce\xa4\xae\xd5\x5c\xce\x0d\xa7\xdd\xe9\xc4\xbf\x1c\xfa\x8b\x6e\x68\xd7\xcf\x03\x18\x63\xdc\x21\x38\x20\xeb\x01\x9a\x01\x3c\xa2\x71\x60\x6e\xa6\xfa\x82\x8b\xb7\xef\x75\x04\x8a\x07\xd8\x7a\x05\x9b\x35\xa0\x1b\xb1\xf1\x84\x13\x78\x81\x4b\xd8\xf5\x0a\xbe\x3c\x42\xea\x01\x60\x97\x01\x66\xe2\xfe\x7f\x40\xd5\x2b\x77\x10\x27\xd6\x69\x26\x92\xc0\x63\x6c\xbd\x37\x60\x92\x3d\xb7\xa9\xd0\xcc\x63\x55\x11\xf6\x55\x80\x79\x0d\xba\x20\x5b\xb0\xbd\x6c\x98\x30\xeb\x7b\x11\x13\xbc\xf5\x5d\x53\xed\x05\x4c\x72\xc4\x89\x1b\x43\x9b\x70\xca\x04\x28\xdb\xcc\xa4\x9b\x28\x60\xd3\x77\xa0\x7d\x01\xe0\xe4\x49\x07\xc5\x24\x73\x91\x46\x9a\x2e\xd0\x70\xf3\x68\x6b\xd4\xc1\xff\xd1\x9b\xb6\xc1\x5e\xaf\x9b\xcf\x6c\x71\x8a\x09\xee\x2c\xb9\x01\x47\x80\x8f\x81\x57\x80\x86\x99\x80\x32\x3e\xa9\xc2\x11\xdf\x5b\xb0\xd1\x0a\xe6\xb6\x62\xa3\x01\xa0\x9d\x20\x98\x17\x04\xb9\xab\x20\x7e\xeb\xfb\x46\xb8\x0e\x11\x99\x23\x7c\x7a\x09\x9a\x59\x82\xca\xda\xa2\x9e\x40\x6a\xaa\x5e\xa5\x40\x36\x69\x1c\x30\xea\x84\x6f\x9c\x40\x09\xb7\x45\x5a\x3b\x80\x65\x8a\xbe\x6b\x9a\x76\x60\xb1\x76\x30\xb6\xf9\x13\x6e\x74\x83\xd0\x4b\x70\x90\xa8\xcf\x05\xfd\xbc\x80\x94\xd9\x1c\x7d\x00\xe5\x35\x00\xeb\x75\xb3\x27\x98\x9d\xa8\x5b\x0c\xba\x31\x9e\xf4\xa4\x83\x57\x88\x25\x16\xb8\x57\x5b\x28\x37\x62\xe0\x77\xd1\x77\x66\x9c\x76\xeb\xdc\x66\xd6\x67\xae\xc0\xa4\x84\x53\x4c\xba\xde\x08\x0f\x62\x26\xb7\x02\x9b\x04\x87\x1d\xcc\x6c\x2d\x18\x1a\xc1\x9e\xcc\x95\xb4\xb0\xd1\xda\xf9\xf4\xe0\x82\x1e\x0b\x5c\x9e\xba\xf1\x41\xb5\xe7\x70\xbc\x3e\xc3\x76\x2b\x75\x55\x37\x98\x49\x01\xef\x62\x66\x77\x42\x90\xdc\x68\xed\x22\x3c\x7b\x6f\x03\xd0\x06\x77\x7f\x03\x50\xf7\x46\x84\x6a\xd8\x70\x01\x04\x2e\x15\x74\x2e\x70\x4f\x54\xb7\x59\x37\x59\xc1\x9e\x7b\xbc\x7f\x00\x1f\x02\xe8\xee\x0b\x76\xd9\xc2\x23\x9c\xce\x25\x9b\xea\x2e\x18\xaf\x82\xb6\x74\x10\x6a\x00\x6f\x30\x97\x67\xd4\xbe\xc0\xe6\x03\x40\x32\x88\xc8\x14\x41\x64\x22\x1e\x28\xb1\x11\x23\x44\x2d\xc8\x8e\xc0\xed\xb4\xca\x03\x1a\x6c\xe0\xe1\xdc\xcd\x37\x26\x4d\xc0\x86\x8c\xf1\x36\xb8\xd8\x13\xff\x3f\x61\x7a\x15\x02\x2b\x33\x29\xf3\x50\x2b\x22\xc1\x1e\xe6\x69\xf4\xda\x4e\xfd\xd4\xe7\x5e\x22\x72\x58\xa4\xc4\x10\x78\xd0\x17\x8d\x1a\x5b\x58\x6b\x9c\xbc\x03\xb0\x95\x38\x79\xaa\xdb\x0a\xd5\x4d\xf0\xbf\x46\xab\x3b\xb8\x34\xd2\xe1\x12\x66\xb2\xea\x67\x0b\x97\x59\xaa\x19\xf4\xb0\x6f\x86\xb9\xa5\x0a\xd7\x08\x14\x4d\x38\xc1\x3b\x18\x16\x7d\x44\xd0\x5a\x01\x50\xec\x50\xeb\x13\x12\xbc\x42\x48\x25\xc0\xcc\x10\xdd\x62\x85\x15\x82\x12\xa8\x66\x0b\xac\xf8\x70\x82\x37\xe0\xdb\x41\x86\x12\x68\x6e\x02\xf5\xdd\xb0\xc1\xe8\x98\x2a\xd9\x6a\x09\x52\x26\x78\xdf\xf0\xee\x8f\xe4\x09\x28\x25\x5c\x8d\x00\x41\x1b\xa8\x62\x0f\x97\x46\x54\xed\xf4\xfe\x07\x36\xf5\x40\x14\xf7\x5b\xc7\xe9\x60\xe3\x01\x26\x95\x71\x3a\xd1\xd1\x57\x6a\x67\xab\x63\x12\xa0\x4d\xad\x23\x38\xcd\xe0\x58\xe4\x0a\x93\x9f\x44\xa4\x34\x57\x24\x18\x88\xe4\xe3\xff\x65\x80\xcc\x35\x7d\xba\x28\x4b\x5c\x2e\xa1\x70\xd7\x5e\x50\xd9\x03\x99\x1a\xa6\xbd\x98\xde\xb2\x77\x5a\xbd\xfe\x89\x50\x78\x81\x16\xda\x78\x3b\xbc\xc4\x8a\x54\x98\x99\xcd\x1b\xe1\xb2\x88\x48\x8c\x60\x59\x93\xfe\xd5\x88\xa3\x4d\xc2\x4f\x00\xda\x8c\x81\x0b\xe7\x8f\x0b\x4c\x72\xd7\xe7\xde\xce\xc6\x0b\x10\xa0\xb7\x4b\x9e\x10\x7b\x36\x3c\x9b\x10\x01\x8e\x88\x2c\x67\x08\x61\xd6\x79\xc9\x12\x07\xf0\x89\x5d\x35\x73\x82\x00\xc6\xa8\x76\x5d\x20\xa4\x9d\xa1\x22\x3d\x36\x12\x60\x57\xe1\x87\xcd\xbc\x90\x33\xb0\x88\x50\xc0\xe3\x09\x72\x01\x00\xd5\x23\x91\x31\x63\xde\x1d\x1b\x2a\xc1\xfa\x22\x48\x54\x82\x56\x9d\x08\xd5\x4b\x68\x60\x03\x93\x39\x61\xb2\xab\x88\xf4\x11\x2e\xa5\x41\x52\x81\x8b\xad\x61\xab\xa3\x8b\xed\x4d\x4b\x2a\x00\xce\x84\x34\x75\xc4\x73\xb3\x4b\x4e\xee\x48\xc1\x59\xb4\x79\x45\x7e\xb1\x82\x29\xbd\x21\x04\x03\xb8\x87\x6a\xcd\x0d\xb8\x50\x43\x0b\x99\x29\x9a\xa1\xd9\x34\x83\xb7\x05\x43\x5f\x48\x3e\x04\xd8\xdd\xdb\x05\x40\x09\x83\x32\x17\xb7\x21\x26\xb8\x81\xd7\x07\xdc\xcb\x2e\xc1\x61\xdf\x17\x2c\x28\x42\x5b\xc2\x0f\xae\x30\x80\xe4\x78\x52\xb4\xea\x7a\x6b\xcc\xc7\x58\x63\x80\x86\x1a\x6f\x90\x08\xc6\x74\x47\x14\xf8\x01\x5b\x1f\xe1\x0d\x76\xa8\xd0\x03\xd7\x83\x7b\x66\x05\x2b\xec\x90\x59\x12\x00\xac\x05\x58\x44\xfe\x1a\x3e\x9f\xd9\xa6\x03\x99\xe4\x4f\x68\xd5\x06\x8e\x62\x73\x46\xb0\x42\xcb\x78\x59\x2e\xf3\x89\x9a\x41\x25\x22\x39\x42\xba\x09\xd2\x7e\x02\xa4\x2e\x28\x9c\x04\x70\x80\xfa\x07\x6d\x60\xf8\x1c\x91\x27\x68\x70\xd2\x11\x29\xb1\x1a\xb1\xbb\xc0\x8e\x5b\x44\xa6\x15\xee\x5d\x91\x9e\x8f\x00\xe3\x0c\xe1\x0d\x3f\x30\xdb\x0c\x3c\x58\xa0\x65\x4b\x00\xc1\x99\x61\xb3\x01\x19\xa0\x19\x92\xa5\xdb\x9a\x20\x80\x37\x48\x54\xe9\xdc\x29\xdd\xac\x05\x2b\x9f\x18\x83\x2a\x5c\xe9\xf3\x86\x35\x3d\x38\xc0\x0a\x77\xbb\x81\x27\x30\x65\xd7\x20\x0f\xb0\xb8\x02\x8a\xcd\x37\x83\x7d\x1e\x41\x27\xb4\x45\xd9\x64\x17\x9d\x9c\x2a\xb8\x62\xf3\x0f\x80\xd2\x08\x36\x97\x9d\x40\x5e\x8e\x3b\x64\x10\x93\x11\x3e\x9d\x5e\xa3\x44\x91\x66\x45\x76\x89\x87\xf3\xa1\x5a\x7a\x60\xbe\x07\x34\xc5\x12\xb1\x0c\xdb\x23\x68\x78\xe1\x53\x62\x2c\x2b\x31\x32\xeb\x10\xc9\x31\x4a\xeb\x81\xe2\x8d\x63\x90\x25\xd4\x30\x80\x2d\x9e\x2e\x0b\x64\x41\xcd\x03\x14\x75\x46\x4c\x21\xa8\x21\x6c\x60\xab\x77\x1c\xcc\x05\xf7\x78\x40\xc9\x21\xfe\xa9\xdf\x6f\xa0\xfa\x87\x85\xc3\x33\x22\xa4\x06\x3e\xfe\x1b\x68\xda\xc0\xd7\x33\xb9\x90\x91\xc5\xcd\xf0\xcb\x57\x94\xaa\x4a\x64\x62\x1b\x14\x4d\x32\x4c\xc3\x5c\xb0\xd1\xd7\x1b\x5c\x65\xe7\xc2\x6a\x41\xe2\xd6\xb4\x31\x3b\xfe\x6f\x02\x3f\x11\x34\x7d\x41\x0b\x2d\x4c\x5e\xa2\xaa\x5e\x05\xd5\x0b\x88\xf0\xb2\xa3\x9a\x9b\x8b\x1b\x04\x88\xba\x20\x3b\x14\x11\x18\x95\x70\x85\x56\x07\x48\xd0\x86\xa7\x82\x99\xa9\xec\x27\xd8\xde\x82\xf7\x22\x00\xb6\x81\x20\x04\x07\xe8\xf3\x95\x86\x47\x57\x17\x1e\x9b\xa9\xd5\xd1\x51\xdf\x02\xf6\x41\x4e\x3f\x83\x84\x18\x08\xbd\x9d\x26\x54\x08\x79\x23\x88\x51\x44\xc1\x25\xa1\xa6\x77\xba\xe2\xe9\x82\x8d\xd6\x08\x6d\x77\x9c\x6a\x84\x5a\xef\x20\x5e\x87\x9e\x70\x80\x09\x17\x2e\xc8\xf2\x89\xd8\x87\x61\x40\x80\xbd\x58\x9c\x1e\x20\x98\x01\x8b\xb3\xb8\xe0\x82\x4c\xd0\x0e\xf5\x9c\x41\x70\xde\x18\x23\x02\x79\x05\x9b\x58\x5d\xed\xbe\x74\x69\x2e\x82\xe6\x13\x60\xbb\x20\xfb\xfb\x81\x77\x99\x56\x2b\x61\x3a\x19\x40\xfc\x84\x80\xd7\xa8\x03\x04\x54\x67\xbe\x90\x4b\x2f\x5c\x69\xea\x00\x16\x30\x0e\x67\x89\x2b\x63\xe2\xd1\x35\x50\xb0\x36\x38\x22\x91\x92\x5d\x99\xfc\x0d\x77\x76\x80\x9a\xef\x48\x6e\x94\xae\x77\x81\x01\x50\x05\x0f\x62\xda\xb0\x41\xbb\x2c\x31\xd3\x47\xa0\x26\xeb\x7d\xc1\x15\x40\x17\x00\xcf\x13\x19\xda\xf5\x07\xae\xf0\x86\x06\xd5\x30\x05\x6e\x50\x1c\xc3\x4b\xd0\x8c\x12\x38\xf3\xc6\xe6\x8d\x99\x16\xf0\x0c\x57\x6c\x7e\xc7\xdc\xac\x2e\x99\xe6\xec\x38\x08\x9b\x63\x0f\x2e\x81\x39\xb8\x64\xc4\x0e\x1c\x58\xd0\xb0\x10\xf1\xfd\x70\x99\x99\x8c\x7c\x9e\x20\xc5\x1e\x40\xab\x23\xea\x77\xc4\x9b\xe4\xc6\xba\x20\xc0\xb1\x6a\xd2\x0b\xc9\x54\x92\xa3\x02\x39\xbf\x15\x60\xf7\x81\x14\xdd\x87\xcb\x12\x2f\x11\xfc\x7e\xc0\x20\x0f\x98\x46\x09\x4e\xbd\x83\xba\x96\x08\x78\x12\xaa\xcb\x15\xde\xdb\xe0\xc6\x4e\x54\x6d\x3b\x17\x55\xd6\xa0\xc3\x11\x66\x50\x82\x50\x95\xc0\x9d\x08\x00\x1e\x10\x22\x5b\x06\x69\x82\xc9\x4d\x2e\x95\x57\xc3\x2c\xaa\x88\x4d\xb7\x8e\x46\xd2\xfd\x9c\x70\x71\xb6\xc8\x87\xcb\x07\x36\xe8\x05\x6a\xb1\xc0\x27\x18\x58\x86\xbb\x8b\x30\x15\xcb\x11\x32\x93\x64\xbc\xe4\x1b\x6e\xd3\x67\x7f\x4a\xb7\xce\xc2\xa5\xe3\x33\x34\x3c\x62\x0d\x96\xc7\x88\x85\xfa\xdd\x0d\x38\x30\xa2\xf2\x62\x78\x70\x75\x79\xb5\xca\x55\x94\x04\x4c\x6b\xc2\xc4\xe2\x52\x6a\xab\x6b\xc1\x79\x23\x77\x60\x05\xd7\x6f\x20\xfb\xe1\x3c\x47\xeb\xc6\x9c\x74\xcc\x1b\xa8\xb5\x99\xce\x0b\xcc\x50\xe0\xbd\x58\xdd\x6e\x22\x54\x6a\x06\x15\x35\x81\xdc\x90\x99\x2d\x5d\xc5\xa6\x70\x00\x16\x40\x6b\x1b\xe0\x48\x05\x96\x67\xe5\xeb\x03\x0b\x1d\xa0\x19\x02\xce\xc1\x2c\xd1\x0c\x8e\x91\x1c\x66\x34\x2e\xa9\xc2\x1c\x23\xb9\x00\x4b\x6d\x16\x5a\x2f\x6c\x36\x22\xd3\xaa\xa0\x3a\x3b\x22\x3f\xfa\xd4\x15\x9c\x3a\x41\x4d\xd9\xac\x58\x01\xa0\x8c\xe2\x76\x98\xef\xe1\xa8\x2e\xeb\x77\x0d\xd2\x5b\x8c\x0d\xc4\x95\xca\x58\x43\xb8\x20\x0f\x78\x41\x5d\x23\x21\xb2\x3c\x90\xb5\xbe\x46\x50\x48\xf6\xee\x50\xfd\x4e\xd4\xda\x0e\x04\x17\x27\x8a\x9b\xec\xc6\x4a\xe0\x14\x2c\x46\xd2\x3b\x04\x00\xe4\x0a\xf2\x24\x2e\x33\x35\x40\xb8\xc6\x27\x46\xac\x91\xcc\xd3\x12\x1f\xa5\x6b\xb6\x0a\x28\xea\x5c\x71\x20\x95\x55\x86\x7e\xe9\x8b\x33\xc0\xea\x80\xda\x24\xa8\xd3\x82\x0d\x97\x00\xb1\x02\x2e\xae\x43\x71\x95\x02\x99\x71\x2a\x09\x55\x9e\x0b\x28\x6a\xe1\xf2\x09\x7c\xb7\x43\xc2\xc5\xd7\x28\x18\x7d\xd6\xae\x41\x8b\xb1\x0a\xdb\x72\x32\xed\xa4\x07\xad\xdd\x5c\x3f\xd0\x08\x64\x66\x5d\x6f\x72\x6a\xfc\x72\xe9\xaa\x87\x23\x2a\x74\x97\x01\x44\x85\x79\x84\x19\xc5\xcd\x16\xd7\xd9\x5f\x70\x83\x90\x12\xf2\x92\x9e\x09\x0a\x4c\x72\x82\xe9\xb1\x09\x34\x33\x4e\xdf\xc1\xe6\x6a\xd7\x94\xc4\xf6\x94\xe0\xda\x6a\x3b\x3d\x49\x26\x54\xde\xd8\xfc\x81\x14\x9b\x09\xee\xed\x28\xec\x0b\xa6\x26\xe0\x12\x6c\x8e\xfa\x46\xf3\xf5\xe6\x36\x93\x21\xd8\xe4\xdc\xe5\x00\x2d\x9d\x10\x88\xcd\x22\x52\x17\xc8\xc4\x1c\xae\x1a\x9b\x5d\x17\x57\x74\xcf\x19\x08\x5e\x71\xed\x0e\x15\x3c\x51\x20\xf9\x44\x5e\x3f\xb9\xbe\x81\x19\x45\x8b\x13\xc2\x3d\xe0\x21\x76\x34\x3e\xb1\x5c\xee\xf3\x91\x33\xa8\xee\x0b\x60\x2e\xd8\xcb\x84\xac\xd7\x5f\x1d\x9f\xc1\xd5\xe9\x36\xd7\xb5\xc9\xfa\x5c\x0b\xb2\x52\xaa\xba\x6f\x8a\x27\x23\x62\x00\x36\x51\xcd\xa8\xfe\x18\x3e\x8c\xa8\xfa\x9c\xaa\x29\x02\x6f\xd3\xa2\x96\xb8\xbb\x76\x9d\xda\x01\x2c\x35\x77\x41\x7f\xe3\xee\x1a\x3a\xac\xa7\xe1\xb7\x31\xc1\xc3\x15\x0d\x08\x3a\xd9\xb5\xb0\x65\x78\x8a\x15\x51\x56\x46\x51\x23\x38\xb7\xca\x9e\x9f\x05\x1d\x24\x3d\x04\x65\xf7\x2e\x88\x39\x26\x74\x8f\xef\x30\x8d\x07\xf2\x07\x0d\x90\x3e\x83\x2c\x25\xb4\xc3\x1a\x4e\xd5\xd8\xa7\xad\x6b\x89\x40\xc8\x84\x9e\x7e\x06\x13\xa7\x2b\x81\x9d\x00\xc4\x41\x17\xcd\xae\x8c\x0d\x27\xf8\x44\x00\x62\x9d\x9e\x4f\xb6\xa9\xb9\x34\x56\x04\x4e\x04\x0d\xcd\x17\x78\x87\xec\x50\x7e\xc5\x3b\x2f\xf4\x3a\x2c\x20\x75\x09\x07\x90\x60\xa6\xb5\x65\x84\xae\xae\x53\x2c\xba\x82\xe3\xe8\x72\x7e\xec\xf3\x59\xa0\x5e\x1d\x16\x18\x00\x6a\x77\xd7\x11\x52\x38\x92\x53\x80\xd0\x14\x20\x41\x19\xd9\x9d\x13\x4c\x73\x81\x1b\x5e\x50\x43\xb8\x80\x7f\x6c\x88\x02\x2d\x0c\x9e\x51\x3e\x33\x8d\x0e\x11\xc8\xfe\x00\xdd\xb5\x74\xf7\x05\x51\x5c\x85\x8d\x07\xd7\x57\x9c\xa1\x3d\x6f\x47\x43\x7b\x57\xba\x9e\x5c\x35\x89\xe4\x2a\xc2\x64\x28\xc4\x17\xfa\x0f\x7a\xb8\xc9\x0d\x6a\x3e\x40\xb3\x6a\x68\x14\xab\xc1\x33\xb4\x40\x44\x24\x19\x70\x7c\x23\x1a\x13\xd7\x29\xba\x3a\x96\x66\x9b\x3f\x61\x0e\x1d\xea\xf5\xe9\x87\x5c\x1c\x91\xbb\x41\x32\x93\x6c\x8f\x7d\x7f\xc1\xf1\x8f\x1d\x49\xda\x8c\x1f\x51\x74\x18\xff\x84\xfa\x57\xae\x3f\x28\x39\xd0\x36\xc0\xff\xa3\x01\xcc\xb9\x77\xf8\xd5\xc5\x08\xda\x58\x20\x11\xc9\x9e\xe2\x06\x41\x88\xa9\xe8\x0a\x8a\xcd\x3e\x82\xd3\x2d\xa6\xc0\xe6\x03\xdc\xd9\x08\x95\x0e\x48\x7c\xb0\xc3\xfc\xe2\xbc\x0a\x93\xad\x25\x82\xa3\x1a\xa4\xa9\x72\x6c\x31\x47\xd7\xd4\x10\xf1\xd0\x02\x92\xc1\xf6\xf9\xc9\xd5\x06\x5f\xe8\xbe\xf8\xd2\xfb\xbf\x50\xab\xab\xe5\xef\x5f\x89\x08\x2a\x43\x15\x52\x5f\x6c\xd7\x59\xd1\x25\xde\x41\x6b\x4a\x57\x60\x89\x40\xf9\x16\xe6\xc0\xa6\x88\xd2\x71\x1a\x16\x57\xda\x08\x2e\x2e\xb0\xcf\x01\x54\x32\xa1\x43\x24\xc1\x36\x05\xa9\x6b\xf6\xed\x2d\xae\x5a\x94\xdd\x49\xac\xae\x4c\x76\x3a\xee\x51\x40\xcb\x58\x2a\x2f\xf1\xe3\x07\x3b\x8c\x15\x05\x56\x03\xe5\x01\x59\xeb\x04\xe1\x3c\x71\x68\x7f\xea\x0a\x11\x68\x3c\xa2\xbf\x2e\xa1\xb2\xeb\x55\x94\x1d\x60\x33\x3c\x43\x06\x25\xde\x5c\x34\xc8\xae\xed\x84\x45\x0c\xb0\xc9\x37\x4e\x91\xe4\x26\x40\x43\x4e\xb8\x34\x76\xa9\xcf\x08\x7a\xaa\x1f\x92\xaf\xec\x70\x63\xe9\x2d\xb2\x3f\xc0\xab\xe7\x82\x1f\x3b\xcc\x38\x55\x86\x99\x11\x69\xf0\x1d\xa7\x7c\xa2\xb8\x1a\x40\x4b\x83\x6b\x8d\x3b\x21\xfc\x0b\xdc\x22\x69\xee\x6f\x84\xb1\x3e\x1f\x11\x91\x11\xca\x20\x62\x77\xb4\xdf\xcc\x30\x63\xae\x67\x37\x13\x68\x5d\x8a\xea\xd0\x09\xe9\x3e\x76\xc7\x0f\x46\x70\xfa\x80\xd4\xb8\x65\x81\x16\xa4\xca\x99\xe4\xc8\x40\xf8\x16\xaa\x5d\xbb\x5e\xe2\xec\xba\xbd\x3c\xa5\xbd\x23\x5b\xd4\xb9\x0c\x51\x46\x69\x5d\x5c\x5b\xbd\xdd\xef\x08\x82\xbb\x6b\x42\x30\x35\x9d\xe0\x09\x56\xf9\xfb\x57\x5d\x03\x3c\xc7\x02\x21\x4c\x6a\x02\x35\x9a\x9f\x36\x2c\x76\x83\x1b\x23\x7d\xe5\x2f\x4a\x0a\xd7\xdb\x13\x5d\x5d\xb1\x00\x36\x25\xd7\xa3\x90\x1c\x9d\x2f\x5d\xc0\x74\x07\x86\xfc\x71\x83\x2d\xdc\x58\xf1\x43\xda\xc9\xba\xc7\x5a\x9c\x20\x0b\x1d\xac\xb7\xb5\x08\x75\x59\xa6\x0e\x10\x18\x8b\x2f\xd9\xb9\xcc\xdd\x69\xdc\x13\x59\x67\x33\xa9\x2b\xaa\x44\x34\xc9\x09\x58\xd3\x01\xbb\xc8\x26\xaf\xc0\xab\x49\x44\x5e\x11\x7e\x7f\x40\x80\x53\xe0\x94\x03\xea\xeb\xc9\xd9\xe0\x0c\xa2\xb4\x43\x65\x27\xd8\x68\x01\x04\x7e\xfc\xd0\xba\x52\xe1\xf9\x16\xa5\x36\x12\x23\x56\x83\x6b\x04\x37\x95\x63\x83\xb3\x3b\x04\xeb\x48\x99\xc0\x1b\x46\xe4\x22\xfa\xc8\x5a\xb9\xcb\x99\x95\x6e\xb1\x6f\x14\x45\x0e\x54\x6a\x76\x97\x13\xbc\xc8\xff\xfe\xf8\xaa\xc0\x82\x17\x07\xa8\xec\x4a\xb9\xbb\xdc\xc3\xdb\x9d\x78\x03\xd3\xdc\x61\x52\x07\xb0\x24\xff\xd0\xd5\x56\x03\x1c\x4b\x80\x7c\x64\x73\x31\xab\x36\x6c\x56\x64\x58\xb9\x22\x91\x69\xc1\xc8\x17\xcc\xa1\xc3\x09\xda\xa4\xdf\x00\xcc\x0d\x27\x11\xc1\x0e\x2f\xae\x11\xe3\x81\xee\x90\xc6\xc5\x16\x8c\x1c\x93\xeb\x71\x2a\x71\x78\xb3\xfc\xfd\x63\xac\x09\x1d\x22\xe6\x7d\xd2\xbf\x07\xe4\x68\x00\x10\x3b\x06\x69\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\x91\x78\x0d\x81\x26\x0f\x00\x00") + +func webdataTexPngBytes() ([]byte, error) { + return bindataRead( + _webdataTexPng, + "webdata/tex.png", + ) +} + +func webdataTexPng() (*asset, error) { + bytes, err := webdataTexPngBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "webdata/tex.png", size: 3878, mode: os.FileMode(436), modTime: time.Unix(1529766470, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "webdata/fn.js": webdataFnJs, + "webdata/icon.png": webdataIconPng, + "webdata/index.html": webdataIndexHtml, + "webdata/main.css": webdataMainCss, + "webdata/sha256.js": webdataSha256Js, + "webdata/tex.png": webdataTexPng, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} +var _bintree = &bintree{nil, map[string]*bintree{ + "webdata": &bintree{nil, map[string]*bintree{ + "fn.js": &bintree{webdataFnJs, map[string]*bintree{}}, + "icon.png": &bintree{webdataIconPng, map[string]*bintree{}}, + "index.html": &bintree{webdataIndexHtml, map[string]*bintree{}}, + "main.css": &bintree{webdataMainCss, map[string]*bintree{}}, + "sha256.js": &bintree{webdataSha256Js, map[string]*bintree{}}, + "tex.png": &bintree{webdataTexPng, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} + + +func assetFS() *assetfs.AssetFS { + assetInfo := func(path string) (os.FileInfo, error) { + return os.Stat(path) + } + for k := range _bintree.Children { + return &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: assetInfo, Prefix: k} + } + panic("unreachable") +} diff --git a/bindata.go b/bindata.go new file mode 100644 index 0000000..5465368 --- /dev/null +++ b/bindata.go @@ -0,0 +1,3 @@ +package main + +//go:generate go-bindata-assetfs -o ./bindata.generated.go webdata/... diff --git a/desktop/remote-touchpad.appdata.xml b/desktop/remote-touchpad.appdata.xml new file mode 100644 index 0000000..c756511 --- /dev/null +++ b/desktop/remote-touchpad.appdata.xml @@ -0,0 +1,35 @@ + + + remote-touchpad.desktop + CC0-1.0 + AGPL-3.0-or-later + Remote Touchpad + Control mouse and keyboard from a smartphone + +

+ Control mouse and keyboard from the webbrowser of a smartphone (or any other device with a touchscreen). + To take control just open the displayed URL or scan the QR code. +

+

+ Supports Linux/X11 and Windows. +

+
+ https://github.com/Unrud/remote-touchpad/issues + https://github.com/Unrud/remote-touchpad + Unrud + + + + + + https://raw.githubusercontent.com/Unrud/remote-touchpad/0.0.1/screenshots/1.png + + + https://raw.githubusercontent.com/Unrud/remote-touchpad/0.0.1/screenshots/2.png + + + https://raw.githubusercontent.com/Unrud/remote-touchpad/0.0.1/screenshots/3.png + + + +
diff --git a/desktop/remote-touchpad.desktop b/desktop/remote-touchpad.desktop new file mode 100644 index 0000000..8ba6773 --- /dev/null +++ b/desktop/remote-touchpad.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=Remote Touchpad +Comment=Control mouse and keyboard from a smartphone +Terminal=true +Exec=remote-touchpad +Icon=remote-touchpad +Categories=Network;RemoteAccess;ConsoleOnly; diff --git a/desktop/remote-touchpad.ico b/desktop/remote-touchpad.ico new file mode 100644 index 0000000..6313008 Binary files /dev/null and b/desktop/remote-touchpad.ico differ diff --git a/desktop/remote-touchpad_128.png b/desktop/remote-touchpad_128.png new file mode 100644 index 0000000..88b612e Binary files /dev/null and b/desktop/remote-touchpad_128.png differ diff --git a/desktop/remote-touchpad_256.png b/desktop/remote-touchpad_256.png new file mode 100644 index 0000000..70eb4d4 Binary files /dev/null and b/desktop/remote-touchpad_256.png differ diff --git a/desktop/remote-touchpad_512.png b/desktop/remote-touchpad_512.png new file mode 100644 index 0000000..03f2fed Binary files /dev/null and b/desktop/remote-touchpad_512.png differ diff --git a/desktop/remote-touchpad_64.png b/desktop/remote-touchpad_64.png new file mode 100644 index 0000000..37844d5 Binary files /dev/null and b/desktop/remote-touchpad_64.png differ diff --git a/flatpak/com.github.unrud.RemoteTouchpad.json b/flatpak/com.github.unrud.RemoteTouchpad.json new file mode 100644 index 0000000..f2b220f --- /dev/null +++ b/flatpak/com.github.unrud.RemoteTouchpad.json @@ -0,0 +1,113 @@ +{ + "app-id" : "com.github.unrud.RemoteTouchpad", + "runtime" : "org.freedesktop.Platform", + "runtime-version" : "1.6", + "sdk" : "org.freedesktop.Sdk", + "command" : "remote-touchpad", + "rename-appdata-file" : "remote-touchpad.appdata.xml", + "rename-desktop-file" : "remote-touchpad.desktop", + "rename-icon" : "remote-touchpad", + "finish-args" : [ + "--socket=x11", + "--share=network" + ], + "build-options" : { + "append-path" : "/app/share/go/bin", + "env" : { + } + }, + "modules" : [ + { + "name" : "go-compiler", + "sources" : [ + { + "only-arches" : [ + "i386" + ], + "type" : "archive", + "strip-components" : 0, + "url" : "https://dl.google.com/go/go1.10.3.linux-386.tar.gz", + "sha256" : "3d5fe1932c904a01acb13dae07a5835bffafef38bef9e5a05450c52948ebdeb4" + }, + { + "only-arches" : [ + "x86_64" + ], + "type" : "archive", + "strip-components" : 0, + "url" : "https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz", + "sha256" : "fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035" + }, + { + "only-arches" : [ + "arm" + ], + "type" : "archive", + "strip-components" : 0, + "url" : "https://dl.google.com/go/go1.10.3.linux-armv6l.tar.gz", + "sha256" : "d3df3fa3d153e81041af24f31a82f86a21cb7b92c1b5552fb621bad0320f06b6" + }, + { + "only-arches" : [ + "aarch64" + ], + "type" : "archive", + "strip-components" : 0, + "url" : "https://dl.google.com/go/go1.10.3.linux-arm64.tar.gz", + "sha256" : "355128a05b456c9e68792143801ad18e0431510a53857f640f7b30ba92624ed2" + } + ], + "buildsystem" : "simple", + "build-commands" : [ + "mkdir -p /app/share", + "cp -r go /app/share" + ], + "build-options" : { + "no-debuginfo" : true + }, + "cleanup" : [ + "*" + ] + }, + { + "name" : "remote-desktop", + "sources" : [ + { + "type" : "git", + "url" : "https://github.com/golang/net", + "commit" : "afe8f62b1d6bbd81f31868121a50b06d8188e1f9", + "dest" : "src/golang.org/x/net" + }, + { + "type" : "git", + "url" : "https://github.com/skip2/go-qrcode", + "commit" : "cf5f9fa2f0d847edb8e038db7ed975e239095e1a", + "dest" : "src/github.com/skip2/go-qrcode" + }, + { + "type" : "git", + "url" : "https://github.com/elazarl/go-bindata-assetfs", + "commit" : "38087fe4dafb822e541b3f7955075cc1c30bd294", + "dest" : "src/github.com/elazarl/go-bindata-assetfs" + }, + { + "type" : "git", + "path" : "..", + "branch" : "master", + "dest" : "src/github.com/unrud/remote-touchpad" + } + ], + "buildsystem" : "simple", + "build-commands" : [ + "env GOPATH=\"$(pwd)\" go build github.com/unrud/remote-touchpad", + "install -Dm0755 -t /app/bin remote-touchpad", + "install -Dm0644 -t /app/share/appdata src/github.com/unrud/remote-touchpad/desktop/remote-touchpad.appdata.xml", + "install -Dm0644 -t /app/share/applications src/github.com/unrud/remote-touchpad/desktop/remote-touchpad.desktop", + "install -Dm0644 src/github.com/unrud/remote-touchpad/desktop/remote-touchpad_64.png /app/share/icons/hicolor/64x64/apps/remote-touchpad.png", + "install -Dm0644 src/github.com/unrud/remote-touchpad/desktop/remote-touchpad_128.png /app/share/icons/hicolor/128x128/apps/remote-touchpad.png", + "install -Dm0644 src/github.com/unrud/remote-touchpad/desktop/remote-touchpad_256.png /app/share/icons/hicolor/256x256/apps/remote-touchpad.png", + "install -Dm0644 src/github.com/unrud/remote-touchpad/desktop/remote-touchpad_512.png /app/share/icons/hicolor/512x512/apps/remote-touchpad.png" + ] + } + ] +} diff --git a/host.go b/host.go new file mode 100644 index 0000000..beb5921 --- /dev/null +++ b/host.go @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +import ( + "fmt" + "net" + "strings" +) + +func FindDefaultHost() string { + fallbackAddr := "" + for _, publicIP := range []string{"2001:4860:4860::8888", "8.8.8.8"} { + addr := fmt.Sprintf("[%s]:80", publicIP) + conn, err := net.Dial("udp", addr) + if err != nil { + continue + } + conn.Close() + host, _, err := net.SplitHostPort(conn.LocalAddr().String()) + if err != nil { + continue + } + return host + } + interfaces, err := net.Interfaces() + if err != nil { + goto fallback + } + for _, inter := range interfaces { + if inter.Flags&net.FlagUp == 0 || inter.Flags&net.FlagLoopback != 0 { + continue + } + addrs, err := inter.Addrs() + if err != nil { + continue + } + addrs: + for _, addr := range addrs { + ip, _, err := net.ParseCIDR(addr.String()) + if err != nil { + continue + } + if fallbackAddr == "" { + fallbackAddr = ip.String() + } + for _, linkLocalPrefix := range []string{"169.254.", "fe8", "fe9", "fea", "feb"} { + if strings.HasPrefix(ip.String(), linkLocalPrefix) { + continue addrs + } + } + return ip.String() + } + + } +fallback: + if fallbackAddr != "" { + return fallbackAddr + } + return "localhost" +} diff --git a/icon.go b/icon.go new file mode 100644 index 0000000..2706811 --- /dev/null +++ b/icon.go @@ -0,0 +1,3 @@ +package main + +//go:generate rsrc -ico desktop/remote-touchpad.ico -o icon.syso diff --git a/icon_windows.syso b/icon_windows.syso new file mode 100644 index 0000000..ac271e9 Binary files /dev/null and b/icon_windows.syso differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..394d5ea --- /dev/null +++ b/main.go @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +import ( + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "errors" + "flag" + "fmt" + "golang.org/x/net/websocket" + "log" + mathrand "math/rand" + "net" + "net/http" + "strconv" + "strings" + "time" +) + +const ( + defaultSecretLength int = 8 + authenticationRateLimit time.Duration = time.Second / 10 + authenticationRateBurst int = 10 + challengeLength int = 8 + defaultBind string = ":0" + version string = "0.0.1" +) + +func processCommand(plugin Plugin, command string) error { + commandParts := strings.Split(command, " ") + if commandParts[0] == "KeyboardText" { + text := strings.Join(commandParts[1:], " ") + return plugin.KeyboardText(text) + } + if len(commandParts) != 3 { + return errors.New("wrong number of arguments") + } + x, err := strconv.ParseInt(commandParts[1], 10, 32) + if err != nil { + return err + } + y, err := strconv.ParseInt(commandParts[2], 10, 32) + if err != nil { + return err + } + if commandParts[0] == "PointerMove" { + return plugin.PointerMove(int(x), int(y)) + } + if commandParts[0] == "PointerScroll" { + return plugin.PointerScroll(int(x), int(y)) + } + if commandParts[0] == "PointerButton" { + if x <= 0 || x > 3 { + return errors.New("unknown pointer button") + } + b := true + if y == 0 { + b = false + } + return plugin.PointerButton(uint(x), b) + } + return errors.New("unknown command") +} + +type challenge struct { + message, expectedResponse string +} + +func (c challenge) verify(response string) bool { + return c.expectedResponse == response +} + +func authenticationChallengeGenerator(secret string, challenges chan<- challenge) { + unsecureSource := mathrand.NewSource(time.Now().UnixNano()) + unsecureRand := mathrand.New(unsecureSource) + b := make([]byte, challengeLength) + for { + if _, err := unsecureRand.Read(b[:]); err != nil { + log.Fatal(err) + } + message := base64.StdEncoding.EncodeToString(b[:]) + mac := hmac.New(sha256.New, []byte(message)) + mac.Write([]byte(secret)) + challenges <- challenge{ + message: message, + expectedResponse: base64.StdEncoding.EncodeToString(mac.Sum(nil)), + } + time.Sleep(authenticationRateLimit) + } +} + +func secureRandBase64(length int) string { + b := make([]byte, length) + if _, err := rand.Read(b[:]); err != nil { + log.Fatal(err) + } + return base64.StdEncoding.EncodeToString(b[:]) +} + +func main() { + var bind, certFile, keyFile, secret string + var showVersion, invert bool + flag.BoolVar(&showVersion, "version", false, "show program's version number and exit") + flag.StringVar(&bind, "bind", defaultBind, "bind server to [IP]:PORT") + flag.StringVar(&secret, "secret", "", "shared secret for client authentication") + flag.StringVar(&certFile, "cert", "", "file containing TLS certificate") + flag.StringVar(&keyFile, "key", "", "file containing TLS private key") + flag.BoolVar(&invert, "invert", false, "use inverse colors for QR code") + flag.Parse() + if showVersion { + fmt.Println(version) + return + } + if certFile != "" && keyFile == "" { + log.Fatal("TLS certificate missing") + } + if certFile == "" && keyFile != "" { + log.Fatal("TLS private key missing") + } + tls := certFile != "" && keyFile != "" + if secret == "" { + secret = secureRandBase64(defaultSecretLength) + } + var plugin Plugin + platformErrors := "" + for _, f := range Plugins { + var err error + plugin, err = f() + if err == nil { + break + } else if _, ok := err.(UnsupportedPlatformError); ok { + platformErrors += err.Error() + "\n" + } else { + log.Fatal(err) + } + } + if plugin == nil { + log.Fatal("unsupported platform:\n" + platformErrors) + } + defer plugin.Close() + authenticationChallenges := make(chan challenge, authenticationRateBurst) + go authenticationChallengeGenerator(secret, authenticationChallenges) + listener, err := net.Listen("tcp", bind) + if err != nil { + log.Fatal(err) + } + addr := listener.Addr().(*net.TCPAddr) + host := "" + bindHost, _, err := net.SplitHostPort(bind) + if err != nil { + log.Fatal(err) + } + for _, b := range addr.IP { + if b != 0 { + host = bindHost + break + } + } + if host == "" { + host = FindDefaultHost() + } + port := addr.Port + mux := http.NewServeMux() + mux.Handle("/", http.FileServer(assetFS())) + mux.Handle("/ws", websocket.Handler(func(ws *websocket.Conn) { + var message string + challenge := <-authenticationChallenges + websocket.Message.Send(ws, challenge.message) + if err := websocket.Message.Receive(ws, &message); err != nil { + return + } + if !challenge.verify(message) { + return + } + for { + if err := websocket.Message.Receive(ws, &message); err != nil { + return + } + if err := processCommand(plugin, message); err != nil { + return + } + } + })) + domain := host + if port != 80 && !tls || port != 443 && tls { + domain = net.JoinHostPort(host, strconv.Itoa(port)) + } + scheme := "http" + if tls { + scheme = "https" + } + url := fmt.Sprintf("%s://%s/#%s\n", scheme, domain, secret) + readyMsg := "ready: " + url + qrCode, _ := GenerateQRCode(url, invert) + readyMsg += qrCode + if !tls { + readyMsg += ("" + + "▌ WARNING: TLS is not enabled ▐\n" + + "▌Don't use in an untrusted network!▐\n") + } + log.Print(readyMsg) + if tls { + err = http.ServeTLS(listener, mux, certFile, keyFile) + } else { + err = http.Serve(listener, mux) + } + log.Fatal(err) +} diff --git a/plugin.go b/plugin.go new file mode 100644 index 0000000..014f6ef --- /dev/null +++ b/plugin.go @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +import "fmt" + +var Plugins [](func() (Plugin, error)) = [](func() (Plugin, error)){ + InitX11Plugin, + InitWindowsPlugin, +} + +type UnsupportedPlatformError struct { + name string + message string +} + +func (e UnsupportedPlatformError) Error() string { + return fmt.Sprintf("%s plugin: %s", e.name, e.message) +} + +type Plugin interface { + Close() error + KeyboardText(text string) error + PointerButton(button uint, press bool) error + PointerMove(deltaX, deltaY int) error + PointerScroll(stepsHorizontal, stepsVertical int) error +} diff --git a/plugin_windows.go b/plugin_windows.go new file mode 100644 index 0000000..34c472f --- /dev/null +++ b/plugin_windows.go @@ -0,0 +1,169 @@ +// +build windows + +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +import ( + "errors" + "syscall" + "unsafe" +) + +const ( + inputMouse uintptr = 0x0 + inputKeyboard uintptr = 0x1 + + keyeventfKeyup uint32 = 0x2 + keyeventfUnicode uint32 = 0x4 + + mouseeventfMove uint32 = 0x1 + mouseeventfLeftdown uint32 = 0x2 + mouseeventfLeftup uint32 = 0x4 + mouseeventfRightdown uint32 = 0x8 + mouseeventfRightup uint32 = 0x10 + mouseeventfMiddledown uint32 = 0x20 + mouseeventfMiddleup uint32 = 0x40 + mouseeventfWheel uint32 = 0x800 + mouseeventfHwheel uint32 = 0x1000 + + wheelDelta int = 120 +) + +type mouseInput struct { + typ uintptr // HACK: padded uint32 + + dx, dy int32 + mouseData, dwFlags, time uint32 + dwExtraInfo uintptr +} + +type keybdInput struct { + typ uintptr // HACK: padded uint32 + + wVk, wScan uint16 + dwFlags, time uint32 + dwExtraInfo uintptr + + padding [8]byte +} + +type windowsPlugin struct { + userDLL *syscall.LazyDLL + sendInputProc *syscall.LazyProc +} + +func InitWindowsPlugin() (Plugin, error) { + p := &windowsPlugin{} + p.userDLL = syscall.NewLazyDLL("user32.dll") + p.sendInputProc = p.userDLL.NewProc("SendInput") + if err := p.sendInputProc.Find(); err != nil { + return nil, UnsupportedPlatformError{"Windows", err.Error()} + } + return p, nil +} + +func (p *windowsPlugin) Close() error { + return nil +} + +func (p *windowsPlugin) KeyboardText(text string) error { + runes := []rune(text) + if len(runes) == 0 { + return nil + } + inputs := make([]keybdInput, len(runes)*2) + for i := range inputs { + inputs[i].typ = inputKeyboard + inputs[i].wScan = uint16(runes[i/2]) + inputs[i].dwFlags = keyeventfUnicode + if i%2 == 1 { + inputs[i].dwFlags |= keyeventfKeyup + } + } + if r, _, err := p.sendInputProc.Call(uintptr(len(inputs)), uintptr(unsafe.Pointer(&inputs[0])), unsafe.Sizeof(inputs[0])); int(r) != len(inputs) { + return err + } + return nil +} + +func (p *windowsPlugin) PointerButton(button uint, press bool) error { + if button == 0 || button > 3 { + return errors.New("unsupported pointer button") + } + input := mouseInput{ + typ: inputMouse, + } + if button == 1 && press { + input.dwFlags = mouseeventfLeftdown + } else if button == 1 { + input.dwFlags = mouseeventfLeftup + } else if button == 2 && press { + input.dwFlags = mouseeventfMiddledown + } else if button == 2 { + input.dwFlags = mouseeventfMiddleup + } else if button == 3 && press { + input.dwFlags = mouseeventfRightdown + } else if button == 3 { + input.dwFlags = mouseeventfRightup + } + if r, _, err := p.sendInputProc.Call(1, uintptr(unsafe.Pointer(&input)), unsafe.Sizeof(input)); int(r) != 1 { + return err + } + return nil +} + +func (p *windowsPlugin) PointerMove(deltaX, deltaY int) error { + input := mouseInput{ + typ: inputMouse, + dx: int32(deltaX), + dy: int32(deltaY), + dwFlags: mouseeventfMove, + } + if r, _, err := p.sendInputProc.Call(1, uintptr(unsafe.Pointer(&input)), unsafe.Sizeof(input)); int(r) != 1 { + return err + } + return nil +} + +func (p *windowsPlugin) PointerScroll(stepsHorizontal, stepsVertical int) error { + inputs := make([]mouseInput, 0, 2) + if stepsHorizontal != 0 { + inputs = append(inputs, mouseInput{ + typ: inputMouse, + dwFlags: mouseeventfHwheel, + mouseData: uint32(stepsHorizontal * wheelDelta), + }) + } + if stepsVertical != 0 { + inputs = append(inputs, mouseInput{ + typ: inputMouse, + dwFlags: mouseeventfWheel, + mouseData: uint32(stepsVertical * wheelDelta), + }) + } + if len(inputs) == 0 { + return nil + } + if r, _, err := p.sendInputProc.Call(uintptr(len(inputs)), uintptr(unsafe.Pointer(&inputs[0])), unsafe.Sizeof(inputs[0])); int(r) != len(inputs) { + return err + } + return nil +} diff --git a/plugin_windows_dummy.go b/plugin_windows_dummy.go new file mode 100644 index 0000000..8db1b06 --- /dev/null +++ b/plugin_windows_dummy.go @@ -0,0 +1,26 @@ +// +build !windows + +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +func InitWindowsPlugin() (Plugin, error) { + return nil, UnsupportedPlatformError{"Windows", "disabled"} +} diff --git a/plugin_x11.go b/plugin_x11.go new file mode 100644 index 0000000..bf520f4 --- /dev/null +++ b/plugin_x11.go @@ -0,0 +1,173 @@ +// +build linux + +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +// #cgo LDFLAGS: -lX11 -lXtst +// #include +// #include +// #include +import "C" +import ( + "errors" + "sync" + "time" + "unsafe" +) + +const typingDelay time.Duration = 100 * time.Millisecond + +type x11Plugin struct { + display *C.Display + lock sync.Mutex +} + +func InitX11Plugin() (Plugin, error) { + display := C.XOpenDisplay(nil) + if display == nil { + return nil, UnsupportedPlatformError{"X11", "failed to connect to X server"} + } + return &x11Plugin{display: display}, nil +} + +func (p *x11Plugin) Close() error { + p.lock.Lock() + defer p.lock.Unlock() + if p.display == nil { + return errors.New("X server connection closed") + } + C.XCloseDisplay(p.display) + p.display = nil + return nil +} + +func (p *x11Plugin) KeyboardText(text string) error { + p.lock.Lock() + defer p.lock.Unlock() + if p.display == nil { + return errors.New("X server connection closed") + } + if text == "" { + return nil + } + var minKeycodes, maxKeycodes C.int + C.XDisplayKeycodes(p.display, &minKeycodes, &maxKeycodes) + var keysymsPerKeycode C.int + keysyms := C.XGetKeyboardMapping(p.display, C.KeyCode(minKeycodes), maxKeycodes-minKeycodes+1, &keysymsPerKeycode) + if keysyms == nil { + return errors.New("failed to get keyboard mapping") + } + emptyKeycode := C.KeyCode(0) +keycodes: + for keycode := C.KeyCode(minKeycodes); keycode <= C.KeyCode(maxKeycodes); keycode++ { + for i := 0; i < int(keysymsPerKeycode); i++ { + keysymsIndex := int(keycode-C.KeyCode(minKeycodes))*int(keysymsPerKeycode) + i + keysym := *(*C.KeySym)(unsafe.Pointer(uintptr(unsafe.Pointer(keysyms)) + uintptr(keysymsIndex)*unsafe.Sizeof(*keysyms))) + if keysym != 0 { + continue keycodes + } + } + emptyKeycode = keycode + break + } + C.XFree(unsafe.Pointer(keysyms)) + if emptyKeycode == 0 { + return errors.New("no empty keycode found") + } + keycodeMapping := make([]C.KeySym, keysymsPerKeycode) + for _, runeValue := range text { + keysym := C.KeySym(0x01000000 + runeValue) + for i := range keycodeMapping { + keycodeMapping[i] = keysym + } + C.XChangeKeyboardMapping(p.display, C.int(emptyKeycode), keysymsPerKeycode, (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1) + C.XTestFakeKeyEvent(p.display, C.uint(emptyKeycode), C.True, 0) + C.XTestFakeKeyEvent(p.display, C.uint(emptyKeycode), C.False, 0) + // race condition! + C.XFlush(p.display) + time.Sleep(typingDelay) + } + for i := range keycodeMapping { + keycodeMapping[i] = 0 + } + C.XChangeKeyboardMapping(p.display, C.int(emptyKeycode), keysymsPerKeycode, (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1) + C.XFlush(p.display) + return nil +} + +func (p *x11Plugin) PointerButton(button uint, press bool) error { + p.lock.Lock() + defer p.lock.Unlock() + if p.display == nil { + return errors.New("X server connection closed") + } + if button == 0 || button > 9 { + return errors.New("unsupported pointer button") + } + var pressC C.int = C.False + if press { + pressC = C.True + } + C.XTestFakeButtonEvent(p.display, C.uint(button), pressC, 0) + C.XFlush(p.display) + return nil +} + +func (p *x11Plugin) PointerMove(deltaX, deltaY int) error { + p.lock.Lock() + defer p.lock.Unlock() + if p.display == nil { + return errors.New("X server connection closed") + } + C.XTestFakeRelativeMotionEvent(p.display, C.int(deltaX), C.int(deltaY), 0) + C.XFlush(p.display) + return nil +} + +func (p *x11Plugin) PointerScroll(stepsHorizontal, stepsVertical int) error { + var buttonHorizontal uint = 7 + if stepsHorizontal < 0 { + buttonHorizontal = 6 + stepsHorizontal = -stepsHorizontal + } + for i := 0; i < stepsHorizontal; i++ { + if err := p.PointerButton(buttonHorizontal, true); err != nil { + return err + } + if err := p.PointerButton(buttonHorizontal, false); err != nil { + return err + } + } + var buttonVertical uint = 5 + if stepsVertical < 0 { + buttonVertical = 4 + stepsVertical = -stepsVertical + } + for i := 0; i < stepsVertical; i++ { + if err := p.PointerButton(buttonVertical, true); err != nil { + return err + } + if err := p.PointerButton(buttonVertical, false); err != nil { + return err + } + } + return nil +} diff --git a/plugin_x11_dummy.go b/plugin_x11_dummy.go new file mode 100644 index 0000000..029f5aa --- /dev/null +++ b/plugin_x11_dummy.go @@ -0,0 +1,26 @@ +// +build !linux + +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +func InitX11Plugin() (Plugin, error) { + return nil, UnsupportedPlatformError{"X11", "disabled"} +} diff --git a/qr.go b/qr.go new file mode 100644 index 0000000..6e9e0f3 --- /dev/null +++ b/qr.go @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + +package main + +import qrcode "github.com/skip2/go-qrcode" + +func GenerateQRCode(message string, invert bool) (string, error) { + q, err := qrcode.New(message, qrcode.Medium) + if err != nil { + return "", err + } + return qrCodeToString(q.Bitmap(), invert), nil +} + +func qrCodeToString(bits [][]bool, invert bool) string { + s := "" + for y := -1; y < len(bits); y += 2 { + for x := range bits[0] { + upper := !invert + if 0 <= y && y < len(bits) { + upper = bits[y][x] + } + lower := !invert + if 0 <= y+1 && y+1 < len(bits) { + lower = bits[y+1][x] + } + if upper != invert && lower != invert { + s += " " + } else if upper == invert && lower != invert { + s += "▀" + } else if upper != invert && lower == invert { + s += "▄" + } else { + s += "█" + } + } + s += "\n" + } + return s +} diff --git a/screenshots/1.png b/screenshots/1.png new file mode 100644 index 0000000..50333e3 Binary files /dev/null and b/screenshots/1.png differ diff --git a/screenshots/2.png b/screenshots/2.png new file mode 100644 index 0000000..578ca6f Binary files /dev/null and b/screenshots/2.png differ diff --git a/screenshots/3.png b/screenshots/3.png new file mode 100644 index 0000000..26f4945 Binary files /dev/null and b/screenshots/3.png differ diff --git a/webdata/fn.js b/webdata/fn.js new file mode 100644 index 0000000..78287c5 --- /dev/null +++ b/webdata/fn.js @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2018 Unrud + * + * This file is part of Remote-Touchpad. + * + * Foobar is free software: you can 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. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + // [1 Touch, 2 Touches, 3 Touches] +const TOUCH_MOVE_THRESHOLD = [10, 15, 15]; +const TOUCH_TIMEOUT = 250; +const MOVE_MULT = 1; +const SCROLL_MULT = 0.05; +// [[px/s, mult], ...] +const POINTER_ACCELERATION = [[0, 0], [87, 1], [173, 1], [553, 2]]; +const UPDATE_INTERVAL = 50; +const MAX_IDLE_UPDATES = 10; + +var ws; +var pad; +var padlabel; + +var touchMoved = false; +var touchStart = 0; +var touchLastEnd = 0; +var touchReleasedCount = 0; +var ongoingTouches = []; +var moveXSum = 0; +var moveYSum = 0; +var scrollXSum = 0; +var scrollYSum = 0; +var dragging = false; +var draggingTimeout = null; +var updateTimer = null; +var idleUpdates = 0; + +function fullscreenEnabled() { + return (document.fullscreenEnabled || + document.webkitFullscreenEnabled || + document.mozFullScreenEnabled || + document.msFullscreenEnabled || + false); +} + +function requestFullscreen(e) { + if (e.requestFullscreen) { + e.requestFullscreen(); + } else if (e.webkitRequestFullscreen) { + e.webkitRequestFullscreen(); + } else if (e.mozRequestFullScreen) { + e.mozRequestFullScreen(); + } else if (e.msRequestFullscreen) { + e.msRequestFullscreen(); + } +} + +function exitFullscreen() { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } +} + +function fullscreenElement() { + return (document.fullscreenElement || + document.webkitFullscreenElement || + document.mozFullScreenElement || + document.msFullscreenElement || + null); +} + +function addFullscreenchangeEventListener(listener) { + if (document.fullscreenElement !== undefined) { + document.addEventListener("fullscreenchange", listener); + } else if (document.webkitFullscreenElement !== undefined) { + document.addEventListener("webkitfullscreenchange", listener); + } else if (document.mozFullScreenElement !== undefined) { + document.addEventListener("mozfullscreenchange", listener); + } else if (document.msFullscreenElement !== undefined) { + document.addEventListener("MSFullscreenChange", listener); + } +} + +function copyTouch(touch, timeStamp) { + return { + identifier: touch.identifier, + pageX: touch.pageX, + pageXStart: touch.pageX, + pageY: touch.pageY, + pageYStart: touch.pageY, + timeStamp: timeStamp + }; +} + +function ongoingTouchIndexById(idToFind) { + for (var i = 0; i < ongoingTouches.length; i++) { + var id = ongoingTouches[i].identifier; + + if (id == idToFind) { + return i; + } + } + return -1; +} + +function calculatePointerAccelerationMult(speed) { + for (var i = 0; i < POINTER_ACCELERATION.length; i++) { + s2 = POINTER_ACCELERATION[i][0]; + a2 = POINTER_ACCELERATION[i][1]; + if (s2 <= speed) { + continue; + } + if (i == 0) { + return a2; + } + s1 = POINTER_ACCELERATION[i-1][0]; + a1 = POINTER_ACCELERATION[i-1][1]; + return ((speed-s1) / (s2-s1)) * (a2-a1) + a1; + } + if (POINTER_ACCELERATION.length > 0) { + return POINTER_ACCELERATION[POINTER_ACCELERATION.length-1][1]; + } + return 1; +} + +function onDraggingTimeout() { + draggingTimeout = null; + ws.send("PointerButton 1 0"); +} + +function updateMoveAndScroll() { + if (updateTimer == null) { + onUpdateTimeout(); + if (UPDATE_INTERVAL > 0 && idleUpdates == 0) { + updateTimer = setInterval(onUpdateTimeout, UPDATE_INTERVAL); + } + } +} + +function onUpdateTimeout() { + idleUpdates += 1; + var moveX = Math.trunc(moveXSum); + var moveY = Math.trunc(moveYSum); + if (Math.abs(moveX) >= 1 || Math.abs(moveY) >= 1) { + moveXSum -= moveX; + moveYSum -= moveY; + idleUpdates = 0; + ws.send("PointerMove " + moveX + " " + moveY); + } + var scrollX = Math.trunc(scrollXSum); + var scrollY = Math.trunc(scrollYSum); + if (Math.abs(scrollX) >= 1 || Math.abs(scrollY) >= 1) { + scrollXSum -= scrollX; + scrollYSum -= scrollY; + idleUpdates = 0; + ws.send("PointerScroll " + scrollX + " " + scrollY); + } + if (idleUpdates >= MAX_IDLE_UPDATES) { + clearInterval(updateTimer); + updateTimer = null; + } +} + +function handleStart(evt) { + if (ongoingTouches.length == 0) { + touchStart = evt.timeStamp; + touchMoved = false; + touchReleasedCount = 0; + dragging = false; + } + var touches = evt.changedTouches; + for (var i = 0; i < touches.length; i++) { + if (touches[i].target !== pad && touches[i].target !== padlabel) { + continue; + } + evt.preventDefault(); + ongoingTouches.push(copyTouch(touches[i], evt.timeStamp)); + touchLastEnd = 0; + if (!dragging) { + moveXSum = Math.trunc(moveXSum); + moveYSum = Math.trunc(moveYSum); + } + scrollXSum = Math.trunc(scrollXSum); + scrollYSum = Math.trunc(scrollYSum); + if (draggingTimeout !== null) { + clearTimeout(draggingTimeout); + draggingTimeout = null; + dragging = true; + } + } +} + +function handleEnd(evt) { + var touches = evt.changedTouches; + for (var i = 0; i < touches.length; i++) { + var idx = ongoingTouchIndexById(touches[i].identifier); + if (idx < 0) { + continue; + } + ongoingTouches.splice(idx, 1); + touchReleasedCount++; + touchLastEnd = evt.timeStamp; + } + if (touchReleasedCount > TOUCH_MOVE_THRESHOLD.length) { + touchMoved = true; + } + if (ongoingTouches.length == 0 && touchReleasedCount >= 1 && + dragging) { + ws.send("PointerButton 1 0"); + } + if (ongoingTouches.length == 0 && touchReleasedCount >= 1 && + !touchMoved && evt.timeStamp - touchStart < TOUCH_TIMEOUT) { + var button = 0; + if (touchReleasedCount == 1) { + button = 1; + } else if (touchReleasedCount == 2) { + button = 3; + }else if (touchReleasedCount == 3) { + button = 2; + } + ws.send("PointerButton " + button + " 1"); + if (button == 1) { + draggingTimeout = setTimeout(onDraggingTimeout, TOUCH_TIMEOUT); + } else { + ws.send("PointerButton " + button + " 0"); + } + } +} + +function handleCancel(evt) { + var touches = evt.changedTouches; + for (var i = 0; i < touches.length; i++) { + var idx = ongoingTouchIndexById(touches[i].identifier); + if (idx < 0) { + continue; + } + ongoingTouches.splice(idx, 1); + touchReleasedCount++; + touchLastEnd = evt.timeStamp; + touchMoved = true; + } +} + +function handleMove(evt) { + var sumX = 0; + var sumY = 0; + var touches = evt.changedTouches; + for (var i = 0; i < touches.length; i++) { + var idx = ongoingTouchIndexById(touches[i].identifier); + if (idx < 0) { + continue; + } + var dist = Math.sqrt(Math.pow(touches[i].pageX - ongoingTouches[idx].pageXStart, 2) + Math.pow(touches[i].pageY - ongoingTouches[idx].pageYStart, 2)); + if (ongoingTouches.length > TOUCH_MOVE_THRESHOLD.length || dist > TOUCH_MOVE_THRESHOLD[ongoingTouches.length - 1]) { + touchMoved = true; + } + var dx = touches[i].pageX - ongoingTouches[idx].pageX; + var dy = touches[i].pageY - ongoingTouches[idx].pageY; + var timeDelta = evt.timeStamp - ongoingTouches[idx].timeStamp; + sumX += dx * calculatePointerAccelerationMult(Math.abs(dx) / timeDelta * 1000); + sumY += dy * calculatePointerAccelerationMult(Math.abs(dy) / timeDelta * 1000); + ongoingTouches[idx].pageX = touches[i].pageX; + ongoingTouches[idx].pageY = touches[i].pageY; + ongoingTouches[idx].timeStamp = evt.timeStamp; + } + if (touchMoved && evt.timeStamp - touchLastEnd >= TOUCH_TIMEOUT) { + if (ongoingTouches.length == 1 || dragging) { + moveXSum += sumX * MOVE_MULT; + moveYSum += sumY * MOVE_MULT; + } else if (ongoingTouches.length == 2) { + scrollXSum -= sumX * SCROLL_MULT; + scrollYSum -= sumY * SCROLL_MULT; + } + updateMoveAndScroll(); + } +} + +function challengeResponse(message) { + var shaObj = new jsSHA("SHA-256", "TEXT"); + shaObj.setHMACKey(message, "TEXT"); + shaObj.update(window.location.hash.substr(1)); + return btoa(shaObj.getHMAC("BYTES")); +} + +window.addEventListener("load", function() { + var authenticated = false; + var opening = document.getElementById("opening"); + var closed = document.getElementById("closed"); + pad = document.getElementById("pad"); + padlabel = document.getElementById("padlabel"); + var keyboard = document.getElementById("keyboard"); + var fullscreenbutton = document.getElementById("fullscreenbutton"); + var text = document.getElementById("text"); + closed.style.display = "none"; + pad.style.display = "none"; + keyboard.style.display = "none"; + text.value = ""; + + ws = new WebSocket("ws://" + location.hostname + + (location.port ? ":" + location.port : "") + + "/ws"); + + ws.onmessage = function(event) { + if (authenticated) { + ws.close(); + return; + } + authenticated = true; + ws.send(challengeResponse(event.data)); + opening.style.display = "none"; + if (history.state == "keyboard") { + keyboard.style.display = "flex"; + text.focus(); + } else { + pad.style.display = "flex"; + } + }; + + ws.onclose = function() { + if (fullscreenElement()) { + exitFullscreen(); + } + opening.style.display = "none"; + pad.style.display = "none"; + keyboard.style.display = "none" + closed.style.display = "flex"; + }; + + document.getElementById("keyboardbutton").addEventListener("click", + function(e) { + if (fullscreenElement()) { + exitFullscreen(); + } + pad.style.display = "none"; + keyboard.style.display = "flex"; + text.focus(); + history.pushState("keyboard", "Remote Keyboard"); + }); + if (!fullscreenEnabled()) { + fullscreenbutton.style.display = "none"; + } + fullscreenbutton.addEventListener("click", function(e) { + if (fullscreenElement()) { + exitFullscreen(); + } else { + requestFullscreen(pad); + } + }); + document.getElementById("sendbutton").addEventListener("click", + function(e) { + if (text.value != "") { + ws.send("KeyboardText " + text.value); + text.value = ""; + } + window.history.back(); + }); + window.onpopstate = function(event) { + if (keyboard.style.display == "flex") { + pad.style.display = "flex"; + keyboard.style.display = "none"; + } else { + window.history.back(); + } + }; + pad.addEventListener("touchstart", handleStart, false); + pad.addEventListener("touchend", handleEnd, false); + pad.addEventListener("touchcancel", handleCancel, false); + pad.addEventListener("touchmove", handleMove, false); +}, false); diff --git a/webdata/icon.png b/webdata/icon.png new file mode 100644 index 0000000..37844d5 Binary files /dev/null and b/webdata/icon.png differ diff --git a/webdata/index.html b/webdata/index.html new file mode 100644 index 0000000..c93bbe3 --- /dev/null +++ b/webdata/index.html @@ -0,0 +1,32 @@ + + + + + + + + + Remote Touchpad + + + + +
+

Connecting...

+
+
+

Disconnected

+
+
+

Touchpad

+
+ + +
+
+
+ + +
+ + diff --git a/webdata/main.css b/webdata/main.css new file mode 100644 index 0000000..bbd1605 --- /dev/null +++ b/webdata/main.css @@ -0,0 +1,99 @@ +html, body, #pad, #keyboard, #opening, #closed { + width: 100%; + height: 100%; + margin: 0; +} + +body { + font-family: sans; +} + +#pad, #sendbutton, #opening, #closed { + background-color: #404040 !important; + background-image: url(tex.png); +} + +#opening, #closed { + display: flex; + align-items: center; + justify-content: center; + font-size: 2em; + color: white; + word-wrap: break-word; +} + +#pad { + display: flex; + flex-direction: column; +} + +#padlabel { + color: #424242; + text-shadow: + -1px -1px 0 #383838, + 1px -1px 0 #383838, + -1px 1px 0 #383838, + 1px 1px 0 #383838; + font-weight: bold; + margin-top: auto; + margin-bottom: auto; + text-align: center; + font-size: 4em; + word-wrap: break-word; +} + +#fullscreenbutton, #keyboardbutton, #sendbutton { + background-color: transparent; + border: 1px solid black; + border-bottom: none; + height: 1.5em; + width: 2em; + font-size: 2em; + color: white; +} + +#fullscreenbutton { + border-left: none; +} + +#keyboardbutton { + border-right: none; + margin-left: auto; +} + +#keyboard { + display: flex; + flex-direction: row; +} + +#text { + flex: 2; + border: none; + resize: none; + font-size: 2em; + background-color: white; + color: black; +} + +.buttons { + display: flex; +} + +#sendbutton { + border-right: none; + border-top: none; + height: 100%; +} + +@media (max-aspect-ratio: 4/3) { + #keyboard { + flex-direction: column; + } + + #sendbutton { + border-left: none; + border-top: 1px solid black; + height: 1.5em; + width: 100%; + } +} \ No newline at end of file diff --git a/webdata/sha256.js b/webdata/sha256.js new file mode 100644 index 0000000..e62bf9e --- /dev/null +++ b/webdata/sha256.js @@ -0,0 +1,27 @@ +/* + A JavaScript implementation of the SHA family of hashes, as + defined in FIPS PUB 180-4 and FIPS PUB 202, as well as the corresponding + HMAC implementation as defined in FIPS PUB 198a + + Copyright 2008-2018 Brian Turek, 1998-2009 Paul Johnston & Contributors + Distributed under the BSD License + See http://caligatio.github.com/jsSHA/ for more information +*/ +'use strict';(function(I){function w(c,a,d){var l=0,b=[],g=0,f,n,k,e,h,q,y,p,m=!1,t=[],r=[],u,z=!1;d=d||{};f=d.encoding||"UTF8";u=d.numRounds||1;if(u!==parseInt(u,10)||1>u)throw Error("numRounds must a integer >= 1");if(0===c.lastIndexOf("SHA-",0))if(q=function(b,a){return A(b,a,c)},y=function(b,a,l,f){var g,e;if("SHA-224"===c||"SHA-256"===c)g=(a+65>>>9<<4)+15,e=16;else throw Error("Unexpected error in SHA-2 implementation");for(;b.length<=g;)b.push(0);b[a>>>5]|=128<<24-a%32;a=a+l;b[g]=a&4294967295; +b[g-1]=a/4294967296|0;l=b.length;for(a=0;a>>3;g=e/4-1;if(eb/8){for(;a.length<=g;)a.push(0);a[g]&=4294967040}for(b=0;b<=g;b+=1)t[b]=a[b]^909522486,r[b]=a[b]^1549556828;n=q(t,n);l=h;m=!0};this.update=function(a){var c,f,e,d=0,p=h>>>5;c=k(a,b,g);a=c.binLen;f=c.value;c=a>>>5;for(e=0;e>> +5);g=a%h;z=!0};this.getHash=function(a,f){var d,h,k,q;if(!0===m)throw Error("Cannot call getHash after setting HMAC key");k=C(f);switch(a){case "HEX":d=function(a){return D(a,e,k)};break;case "B64":d=function(a){return E(a,e,k)};break;case "BYTES":d=function(a){return F(a,e)};break;case "ARRAYBUFFER":try{h=new ArrayBuffer(0)}catch(v){throw Error("ARRAYBUFFER not supported by this environment");}d=function(a){return G(a,e)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER"); +}q=y(b.slice(),g,l,p(n));for(h=1;h>>2]>>>8*(3+b%4*-1),l+="0123456789abcdef".charAt(g>>>4&15)+"0123456789abcdef".charAt(g&15);return d.outputUpper?l.toUpperCase():l}function E(c,a,d){var l="",b=a/8,g,f,n;for(g=0;g>>2]:0,n=g+2>>2]:0,n=(c[g>>>2]>>>8*(3+g%4*-1)&255)<<16|(f>>>8*(3+(g+1)%4*-1)&255)<<8|n>>>8*(3+(g+2)%4*-1)&255,f=0;4>f;f+=1)8*g+6*f<=a?l+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(n>>> +6*(3-f)&63):l+=d.b64Pad;return l}function F(c,a){var d="",l=a/8,b,g;for(b=0;b>>2]>>>8*(3+b%4*-1)&255,d+=String.fromCharCode(g);return d}function G(c,a){var d=a/8,l,b=new ArrayBuffer(d),g;g=new Uint8Array(b);for(l=0;l>>2]>>>8*(3+l%4*-1)&255;return b}function C(c){var a={outputUpper:!1,b64Pad:"=",shakeLen:-1};c=c||{};a.outputUpper=c.outputUpper||!1;!0===c.hasOwnProperty("b64Pad")&&(a.b64Pad=c.b64Pad);if("boolean"!==typeof a.outputUpper)throw Error("Invalid outputUpper formatting option"); +if("string"!==typeof a.b64Pad)throw Error("Invalid b64Pad formatting option");return a}function B(c,a){var d;switch(a){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE");}switch(c){case "HEX":d=function(a,b,c){var f=a.length,d,k,e,h,q;if(0!==f%2)throw Error("String of HEX type must be in byte increments");b=b||[0];c=c||0;q=c>>>3;for(d=0;d>>1)+q;for(e=h>>>2;b.length<=e;)b.push(0);b[e]|=k<<8*(3+h%4*-1)}return{value:b,binLen:4*f+c}};break;case "TEXT":d=function(c,b,d){var f,n,k=0,e,h,q,m,p,r;b=b||[0];d=d||0;q=d>>>3;if("UTF8"===a)for(r=3,e=0;ef?n.push(f):2048>f?(n.push(192|f>>>6),n.push(128|f&63)):55296>f||57344<=f?n.push(224|f>>>12,128|f>>>6&63,128|f&63):(e+=1,f=65536+((f&1023)<<10|c.charCodeAt(e)&1023),n.push(240|f>>>18,128|f>>>12&63,128|f>>>6&63,128|f&63)),h=0;h>>2;b.length<=m;)b.push(0);b[m]|=n[h]<<8*(r+p%4*-1);k+=1}else if("UTF16BE"===a||"UTF16LE"===a)for(r=2,n="UTF16LE"===a&&!0||"UTF16LE"!==a&&!1,e=0;e>>8);p=k+q;for(m=p>>>2;b.length<=m;)b.push(0);b[m]|=f<<8*(r+p%4*-1);k+=2}return{value:b,binLen:8*k+d}};break;case "B64":d=function(a,b,c){var f=0,d,k,e,h,q,m,p;if(-1===a.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");k=a.indexOf("=");a=a.replace(/\=/g, +"");if(-1!==k&&k