From: b Date: Thu, 10 Jan 2019 12:00:00 +0000 (+0000) Subject: Initial state as of 10.01.2019 X-Git-Url: http://bicyclesonthemoon.info/git-projects/?a=commitdiff_plain;h=be3a90461ed0fa0cef571cfeeab2a9310f5d34c9;p=ott%2Fenhance Initial state as of 10.01.2019 --- be3a90461ed0fa0cef571cfeeab2a9310f5d34c9 diff --git a/agpl.txt b/agpl.txt new file mode 100644 index 0000000..70eec1e --- /dev/null +++ b/agpl.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + 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 AGPL, see +. diff --git a/bb2html.awk b/bb2html.awk new file mode 100644 index 0000000..4e488e1 --- /dev/null +++ b/bb2html.awk @@ -0,0 +1,689 @@ +#// bb2html.awk +#// converts bbcode to html. +#// 30.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . +#// + +BEGIN{ + FS="=" + debug="debug=bb2html.awk:" + automome="/eizm/pro/ong1/mome.pl" + memepath="/eizm/mem/ong1/mome.txt" + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i) + dec=sprintf("%u",i) + ch2hex[ch]=hex + ch2dec[ch]=dec + } +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(argtab["disable_bbcode"]!="") + { + debug=debug"###nl;BBcode disabled" + print debug>>outfile + exit 0 + } + text=argtab["BB"] + html=bb2html(text) + print "HTML="html>>outfile + print debug>>outfile + + # if(tempfile!="") + # { + # text=argtab["message"] + # gsub(/%5Bbr%5D/,"\n",text) + # while(sub(/%5Bong%5D/,ong(),text)>0){print text} + # while(sub(/%5Bung%5D/,ung(),text)>0){print text} + # while(sub(/%5Bong%3Ddecree%5D/,ong("decree"),text)>0){print text} + # while(sub(/%5Bung%3Ddecree%5D/,ung("decree"),text)>0){print text} + # if(text!=argtab["message"]) + # print "message="text >> outfile + # } +}; + +function bb2html(text, depth,count,bbtree,html,tag,tagstart,taglength,elm,tagv,tagname,tagvalue,matchname) +{ + depth=0 + count[0]=1 + bbtree["0"]="" + bbtree["0.n"]=0 + bbtree["0.t"]="post" + bbtree["0.v"]=argtab["subject"] + html="" + gsub(/=/,"=",text) + debug = debug "###nl;###nl;Build BBcode tree:" + while(length(text)!=0) + { + tag=match(text, /\[\/?[a-z0-9\*]+(=(([^\[<>\"\]]*)|(\"[^\"<>]*\")))?\]/) + #"#\"" + # debug = debug "###nl;" RSTART " " RLENGTH + if (tag==0) + { + debug = debug "###nl;text: " text + bbtree[ind(count,depth)]=text + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + text="" + break; + } + tagstart=RSTART + taglength=RLENGTH + if(tagstart>1) + { + elm=substr(text,1,tagstart-1) + debug = debug "###nl;text: " elm + bbtree[ind(count,depth)]=elm + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + } + tag=substr(text,tagstart,taglength) + text=substr(text,tagstart+taglength) + debug = debug "###nl;tag: " tag + if(tag!~/^\[\//) + { + tagv=index(tag,"=") + if(tagv<2) + { + tagname=substr(tag,2,length(tag)-2) + tagvalue="" + } + else + { + tagname=substr(tag,2,tagv-2) + tagvalue=substr(tag,tagv+1,length(tag)-tagv-1) + } + if(tagname !~ /^((quote)|b|i|u|(code)|(img)|(url)|(size)|(color)|(center)|(right)|(sub)|(sup)|(s)|(spoiler)|(list)|(\*))$/) + { + debug = debug "###nl;unknown tag" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||bbtree[indt(count,depth)".t"] == "img"||(bbtree[indt(count,depth)".t"] == "spoiler" && tagname=="spoiler")||(bbtree[indt(count,depth)".t"] == "size" && tagname=="size")) + { + debug = debug "###nl;this tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname=="*") + { + if(bbtree[indt(count,depth)".t"]==tagname) + { + debug = debug "###nl;implied tag: [/"tagname"]" + debug = debug "###nl;matched" + bbtree[ind(count,depth)]="[/"tagname"]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + else if(bbtree[indt(count,depth)".t"]!="list") + { + debug = debug "###nl;this tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + } + debug = debug "###nl;name: " tagname " value: " tagvalue + bbtree[ind(count,depth)]=tagname" "tagvalue + bbtree[ind(count,depth)".k"]="s" + bbtree[indt(count,depth)".n"]=count[depth] + ++depth + count[depth]=1 + bbtree[indt(count,depth)]=tag + bbtree[indt(count,depth)".n"]=0 + bbtree[indt(count,depth)".t"]=tagname + bbtree[indt(count,depth)".v"]=tagvalue + } + else + { + if(depth<=0) + { + debug = debug "###nl;""unmatched" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + tagname=substr(tag,3,length(tag)-3) + if(tagname=="list"&&bbtree[indt(count,depth)".t"]=="*") + { + debug = debug "###nl;implied tag: [/*]" + debug = debug "###nl;matched" + bbtree[ind(count,depth)]="[/*]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]="*" + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + debug = debug "###nl;name: " tagname + matchname=bbtree[indt(count,depth)".t"] + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||(bbtree[indt(count,depth)".t"] == "img" && tagname != "img")) + { + debug = debug "###nl;this tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname!=matchname) + { + debug = debug "###nl;mismatched: " matchname + # bbtree[ind(count,depth)]=tag + # bbtree[indt(count,depth)".n"]=count[depth] + # ++count[depth] + # continue + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".t"]=bbtree[indt(count,depth)".t"] + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + count[depth]="" + --depth + ++count[depth] + continue + } + debug = debug "###nl;matched" + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + } + if(depth>0) + debug = debug "###nl;unclosed tags: " depth + + debug = debug "###nl;###nl;""generate HTML:" + depth=0 + count[0]=0 + while(count[0]<=bbtree["0.n"]&&depth>=0) + { + if(count[depth]==0) + { + tag=bbtree[indt(count,depth)] + tagname=bbtree[indt(count,depth)".t"] + tagvalue=bbtree[indt(count,depth)".v"] + debug = debug "###nl;name: "tagname" value: "tagvalue" elements: "bbtree[indt(count,depth)".n"] + if(tagname == "post") + { + } + else if(bbtree[indt(count,depth)".m"]=="") + { + debug = debug "###nl;unmatched" + html = html tag + } + else if(tagname == "quote") + { + if (tagvalue=="") + { + html = html "
" + } + else + { + if(tagvalue !~ /^\".*\"$/) + #"#\"" + tagvalue="You forgot about the quote marks, "tagvalue + else + tagvalue=bb2html(substr(tagvalue,2,length(tagvalue)-2)) + html = html "
"tagvalue" wrote:
" + } + } + else if (tagname == "b") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "i") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "u") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html tag + debug = debug "###nl;not a tag, actually" + } + else + { + html=html"
Code: Select all
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + } + else if (tagname == "img") + html=html"" + } + else if (tagname == "size") + { + if (tagvalue==""||(tagvalue !~ /^[0-9]+$/)||(tagvalue+0)>200) + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname == "color") + { + if (tagvalue==""||tagvalue !~ /^#[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]$/) #for some reason /^([0-9A-F]{6})$/ doesn't work. + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname ~ /^((center)|(right))$/) + { + html=html"
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="s") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sub") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sup") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="spoiler") + { + html=html"
Spoiler:
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="list") + { + if(tagvalue=="") + html=html"
    " + else + { + if (tagvalue=="1") + tagvalue="decimal" + else if (tagvalue=="i") + tagvalue="lower-roman" + else if (tagvalue=="I") + tagvalue="upper-roman" + else if (tagvalue=="a") + tagvalue="lower-alpha" + else if (tagvalue=="A") + tagvalue="upper-alpha" + else + { + html=html"This tag should have a correct value. " + tagvalue="decimal" + } + html=html"
      " + } + } + else if (tagname=="*") + { + html=html"
    1. " + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else + { + debug = debug "###nl;unknown tag" + html = html tag + } + ++count[depth] + } + else if(bbtree[ind(count,depth)".k"]=="s") + { + debug = debug "###nl;entering tag:" + ++depth + count[depth]=0 + } + else if(bbtree[ind(count,depth)".k"]=="e") + { + debug = debug "###nl;leaving tag:" + tag=bbtree[ind(count,depth)] + tagname=bbtree[ind(count,depth)".t"] + tagvalue=bbtree[ind(count,depth)".v"] + debug = debug "###nl;name: "tagname" value: "tagvalue + if (tagname == "post") + { + } + else if(bbtree[ind(count,depth)".m"]=="") + { + debug = debug "###nl;unmatched" + html = html tag + } + else if(tagname == "quote") + html = html "
" + else if (tagname ~/^(b|i|u|(size)|(color))$/) + html = html"" + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html tag + debug = debug "###nl;not a tag, actually" + } + else + html = html"" + } + else if (tagname == "img") + { + html = html"\" alt=\"Image\" />" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if(tagname=="url") + html=html"" + else if (tagname ~ /^((center)|(right))$/) + html=html"
" + else if (tagname =="s") + html=html"" + else if (tagname =="sub") + html=html"" + else if (tagname =="sup") + html=html"" + else if (tagname=="spoiler") + html=html"" + else if (tagname=="list") + { + if (tagvalue=="") + html=html"" + else + html=html"" + } + else if (tagname=="*") + html=html"" + else + { + debug = debug "###nl;unknown tag" + html = html tag + } + count[depth]="" + --depth + ++count[depth] + } + else if(count[depth]>bbtree[indt(count,depth)".n"]) + { + debug = debug "###nl;run out of elements in this tag; leaving" + count[depth]="" + --depth + ++count[depth] + } + else + { + tag=bbtree[ind(count,depth)] + debug = debug "###nl;text: "tag + if(bbtree[indt(count,depth)".t"] == "code") + { + # gsub(/ ?
?/,"
",tag) + gsub(/ /,"\\ ",tag) + gsub(/\t/,"\\ \\ ",tag) + } + if(argtab["disable_magic_url"]==""&& bbtree[indt(count,depth)".t"] !~ /^((code)|(img)|(url))$/) + gsub(/https?:\/\/[^\n\r\t<> ]+/,"&",tag) + if(argtab["disable_smilies"]=="" && bbtree[indt(count,depth)".t"] !~ /^((code)|(img))$/) + { + gsub(/(^|[\n\r\t ]):D($|[\n\r\t ])/," \":D\" ",tag) + gsub(/(^|[\n\r\t ]):\)($|[\n\r\t ])/," \":)\" ",tag) + gsub(/(^|[\n\r\t ]):\(($|[\n\r\t ])/," \":(\" ",tag) + gsub(/(^|[\n\r\t ]):o($|[\n\r\t ])/," \":o\" ",tag) + gsub(/(^|[\n\r\t ]):shock:($|[\n\r\t ])/," \":shock:\" ",tag) + gsub(/(^|[\n\r\t ]):\?($|[\n\r\t ])/," \":?\" ",tag) + gsub(/(^|[\n\r\t ])8-\)($|[\n\r\t ])/," \"8-)\" ",tag) + gsub(/(^|[\n\r\t ]):lol:($|[\n\r\t ])/," \":lol:\" ",tag) + gsub(/(^|[\n\r\t ]):x($|[\n\r\t ])/," \":x\" ",tag) + gsub(/(^|[\n\r\t ]):P($|[\n\r\t ])/," \":P\" ",tag) + gsub(/(^|[\n\r\t ]):oops:($|[\n\r\t ])/," \":oops:\" ",tag) + gsub(/(^|[\n\r\t ]):cry:($|[\n\r\t ])/," \":cry:\" ",tag) + gsub(/(^|[\n\r\t ]):evil:($|[\n\r\t ])/," \":evil:\" ",tag) + gsub(/(^|[\n\r\t ]):twisted:($|[\n\r\t ])/," \":twisted:\" ",tag) + gsub(/(^|[\n\r\t ]):roll:($|[\n\r\t ])/," \":roll:\" ",tag) + gsub(/(^|[\n\r\t ]):wink:($|[\n\r\t ])/," \":wink:\" ",tag) + gsub(/(^|[\n\r\t ]);\)($|[\n\r\t ])/," \":wink:\" ",tag) + gsub(/(^|[\n\r\t ]):!:($|[\n\r\t ])/," \":!:\" ",tag) + gsub(/(^|[\n\r\t ]):\?:($|[\n\r\t ])/," \":?:\" ",tag) + gsub(/(^|[\n\r\t ]):idea:($|[\n\r\t ])/," \":idea:\" ",tag) + gsub(/(^|[\n\r\t ]):arrow:($|[\n\r\t ])/," \":arrow:\" ",tag) + gsub(/(^|[\n\r\t ]):\|($|[\n\r\t ])/," \":|\" ",tag) + gsub(/(^|[\n\r\t ]):mrgreen:($|[\n\r\t ])/," \":mrgreen:\" ",tag) + } + + html = html tag + ++count[depth] + } + } + debug = debug "###nl;done" + return html +} + +function ind(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii<=depth;++ii) + { + if(ii!=0) + iindex = iindex "." + iindex = iindex count[ii] + } + # debug = debug "###nl;" iindex + return iindex +} +function indt(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "###nl;" iindex + return iindex +} +function indtu(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "###nl;" iindex + return iindex +} +function ong(decree, line) +{ + system (automome" -lc 256 -n 67 -d "memepath(decree!=""?" -t \"[decr]\"":"")" > "tempfile) + + while((getline line < tempfile)>0) + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#O-N-G#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/O+N+G+/,"#&#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/DON'T/,"D#ON'G#T",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/[AEIOUY]NG/,"#ONG#",line)>0) + { + if($0!~/TH\[b\]ONG/) + return preparebb(line) + } + if(sub(/ON /,"#ONG# ",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/O\.?$/,"#ONG# ",$0)>0) + { + close(tempfile) + return preparebb(line) + } + } + close(tempfile) + return "Ong" +} + +function ung(decree, line) +{ + system (automome" -lc 256 -n 67 -d "memepath(decree!=""?" -t \"[decr]\"":"")" > "tempfile) + + while((getline line < tempfile)>0) + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#U-N-G#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/U+N+G+/,"#&#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/[AEIOUY]NG/,"#UNG#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/UN /,"#UNG# ",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/U\.?$/,"#UNG# ",$0)>0) + { + close(tempfile) + return preparebb(line) + } + } + close(tempfile) + return "Ung" +} + +function preparebb(rh) +{ + if(nobb=="") + { + gsub(/\*\*/,"¤",rh) + gsub(/\*[^\*]+\*/,"±&±",rh) + gsub(/±\*/,"[i]",rh) + gsub(/\*±/,"[/i]",rh) + gsub(/¤/,"*",rh) + + gsub(/__/,"¤",rh) + gsub(/_[^_]+_/,"±&±",rh) + gsub(/±_/,"[u]",rh) + gsub(/_±/,"[/u]",rh) + gsub(/¤/,"_",rh) + + gsub(/##/,"¤",rh) + gsub(/#[^#]+#/,"±&±",rh) + gsub(/±#/,"[b]",rh) + gsub(/#±/,"[/b]",rh) + gsub(/¤/,"#",rh) + + gsub(/\$\$/,"¤",rh) + gsub(/\$[^\$]+\$/,"±&±",rh) + gsub(/±\$/,"[size=80]",rh) + gsub(/\$±/,"[/size]",rh) + gsub(/¤/,"$",rh) + } + + return rh (nobb==""?" -- [url=http://mrob.com/time/automome]automome[/url]":" -- automome") +} +function urlencode(name,all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +} diff --git a/bot4.awk b/bot4.awk new file mode 100644 index 0000000..d83e267 --- /dev/null +++ b/bot4.awk @@ -0,0 +1,463 @@ +#// bot4.awk +#// The bot to post frames to the OTT +#// 19.06.2018- +#// +#// Copyright (C) 2015, 2018 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="" + # noticepath="/eizm/mem/aftertime/mpost/" + # framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + timecmd="date" + timecmd2="date -u +%N%s" + lastpath ="/eizm/mem/aftertime/lastong/" + temppath ="/eizm/tmp/aftertime/" + ott_address="http://forums.xkcd.com/viewtopic.php?f=7&t=101043&start=" + tto_address="http://1190.bicyclesonthemoon.info/ott/view?start=" + mstd_address="http://1190.bicyclesonthemoon.info/ott/mview?start=" + lastpost_address="http://forums.xkcd.com/viewtopic.php?f=7&t=101043&sd=d" + + wget="/usr/bin/wget" + rm="/bin/rm" + perl="/usr/bin/perl" + mawk="/usr/bin/mawk" + automome="/eizm/pro/ong1/mome.pl" + memedef="/eizm/mem/ong1/mome.txt" + + postawk="/eizm/pro/aftertime/post.awk" + mpostawk="/eizm/pro/aftertime/mpost.awk" + + # timecmd2="date +\"%H%M%S\"" + botcastleurl="http://1190.bicyclesonthemoon.info" + + if(enhance!="" && int(enhance)!="0") + { + enh=int(enhance) + ext="-"enh + } + else + { + ext="" + enh=0 + } + + f=int(frame) + timecmd | getline thistime + close(timecmd) + + timecmd2 | getline ID + close(timecmd2) + ID=int(ID/3600) + ID =int(ID%9999) + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i); + ch2hex[ch]=hex + } + + statefile= datapath story"/ongstate" + getline temp < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + + if(frame=="") + f=last + + # srand(ID + f) + # for(i=0;i0) + { + if(temp ~ regexp) + { + print "Newpage "page" - already ONGed." + system(rm" -f "tempfile) + print page" "f > lasttime + close(lasttime) + exit 1 + } + gsub(/<[^<>]*>/,"",temp) + gsub(/ +/," ",temp) + temp2=tolower(temp) + if((i=match(temp2,/page [0-9]+ of [0-9]+/))!=0) + { + temp2=substr(temp2,i) + temp2=substr(temp2,index(temp2,"of")+3)" " + temp2=substr(temp2,1,index(temp2," ")-1) + lastpage=int(temp2) + } + temp2=tolower(temp) + if((i=match(temp2,/[0-9]+ posts/))!=0) + { + temp2=substr(temp2,index(temp2,"")-1) + posts=int(temp2) + if(posts%40==0) + pope=1 + else + pope="" + } + } + close(tempfile) + print "Newpage "page" - nothing found." + } + mlastpage=1 + for(mpage=1;mpage<=mlastpage;++mpage) + { + url= "\""mstd_address (mpage-1)*40"\"" + + cmd= wget " -q -O "tempfile" -U "useragent" "url + if(system(cmd)!=0) + { + print "Mustardtime newpage "mpage" not downloaded." + break + } + for(j=0;(getline temp < tempfile)>0;++j) + { + if(temp ~ regexp) + { + print "Newpage "mpage" - already ONGed." + system(rm" -f "tempfile) + #writeout + exit 1 + } + gsub(/<[^<>]*>/,"",temp) + gsub(/ +/," ",temp) + temp2=tolower(temp) + if((i=match(temp2,/page [0-9]+ of [0-9]+/))!=0) + { + temp2=substr(temp2,i) + temp2=substr(temp2,index(temp2,"of")+3) + temp2=substr(temp2,1,index(temp2," ")-1) + mlastpage=int(temp2) + } + temp2=tolower(temp) + if((i=match(temp2,/[0-9]+ posts/))!=0) + { + temp2=substr(temp2,index(temp2,"")-1) + posts=int(temp2) + if(posts%40==0) + pope=1 + else + pope="" + } + } + close(tempfile) + print "Mustradtime newpage "mpage" - nothing found." + } + } + + if(argtab["nomeme"]=="") + { + print "Ok, can ONG. Now generate ONGtext" + cmd = perl" "automome" -lc 150 -n 67 -d "memedef (pope!=""?" -t \"[decrall]\"":"") + while ((cmd | getline temp)>0) + { + if(sub(/[AEIOUY]-N-G/,"[b]O-N-G[/b]",temp)>0) + { + ongtext= prepare(temp) + break + } + if(sub(/O+N+G+/,"[b]&[/b]",temp)>0) + { + ongtext= prepare(temp) + break + } + if(sub(/DON'T/,"D[b]ON'G[/b]T",temp)>0) + { + ongtext= prepare(temp) + break + } + if(sub(/[AEIOUY]NG/,"[b]ONG[/b]",temp)>0) + { + if($0!~/TH\[b\]ONG/) + { + ongtext= prepare(temp) + break + } + } + if(sub(/ON G/,"[b]ON G[/b] ",temp)>0) + { + ongtext= prepare(temp) + break + } + if(sub(/ON /,"[b]ONG[/b] ",temp)>0) + { + ongtext= prepare(temp) + break + } + if(sub(/O\.?$/,"[b]ONG[/b] ",temp)>0) + { + ongtext= prepare(temp) + break + } + } + close(cmd) + + if(ongtext=="") + ongtext="ONG" + print ongtext + } + else + ongtext="ONG" + + cmd= wget " -q -O "tempfile" -U "useragent" \""lastpost_address"\"" + if(system(cmd)!=0) + { + print "Can't check last post" + # system(rm" -f "tempfile) + # exit 1 + } + + else + { + while((getline temp < tempfile)>0) + { + if ((i=match(temp, /id=\"p[0-9]+\"/))!=0) #" + { + temp2=substr(temp, i+5) + lastpostid=substr(temp2, 1, index(temp2,"\"")-1) + } + + if (temp ~ /class=\"postprofile\"/) #" + postprofile = "1" + + else if (postprofile=="") + continue + + if(temp ~ /memberlist\.php.*mode=viewprofile[^<>]*>[^<>]+<\/a/) + { + temp2=substr(temp, index(temp, ">")+1) + lastusername=substr(temp2, 1, index(temp2,"<")-1) + break + } + } + close(tempfile) + if(lastusername=="" || lastpostid=="") + { + print "Can't check last post" + # system(rm" -f "tempfile) + # exit 1 + } + } + + srand(ID+lastpostid+f) + + if(rand()<(argtab["npbprob"]+0)) + { + print "Also, let's do some NewpixbOTTification!" + npbsel="npbframe"ext + } + else + npbsel="frame"ext + + + + framedir= (argtab["framedir"]!="" ? argtab["framedir"] : "/aftertime/"argtab["story"]"/") + + print "username="urlencode(username) > tempfile + print "password="urlencode(password,1) >> tempfile + print "subject="urlencode(sprintf(argtab["subject"ext],f)) >> tempfile + print "message="urlencode(ongtext"\n[url="botcastleurl"/aftertime/viewer?story="argtab["story"]"&f="f((enh>0)?"&e="enh:"")"][img]"botcastleurl framedir sprintf(argtab[npbsel],f)"[/img][/url][spoiler]"alt"[/spoiler]\n[right][size=80] -- posted by "botname"[/size][/right]") >> tempfile + print "Send post" + + cmd= mawk" -f "postawk" -v postfile="tempfile_p" -v cookiefile="tempfile_c" -v tempfile="tempfile_t((lastpostid!="" && lastusername!="")?" -v edit="lastpostid" -v user=\""lastusername"\"":"")" "tempfile + cmd2= mawk" -f "mpostawk" -v postfile="tempfile_p" -v cookiefile="tempfile_c" -v tempfile="tempfile_t" "tempfile + + if(system(cmd)!=0) + { + print "Can't post, try again from mirror" + if(system(cmd2)!=0) + { + print "CAN'T POST EITHER!" + system(rm" -f "tempfile) + system(rm" -f "tempfile_t) + system(rm" -f "tempfile_c) + system(rm" -f "tempfile_p) + exit 1 + } + } + print "ONGed" + system(rm" -f "tempfile) + system(rm" -f "tempfile_t) + system(rm" -f "tempfile_c) + system(rm" -f "tempfile_p) + if(force=="") + { + print lastpage" "f > lasttime + close(lasttime) + } + + +} +function urlencode(name, all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if (ch ~ /[a-z]|[A-Z]|[0-9]/ && all=="") + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +}; +function prepare(rh) +{ + gsub(/\*\*/,"¤",rh) + gsub(/\*[^\*]+\*/,"±&±",rh) + gsub(/±\*/,"[i]",rh) + gsub(/\*±/,"[/i]",rh) + gsub(/¤/,"*",rh) + + gsub(/__/,"¤",rh) + gsub(/_[^_]+_/,"±&±",rh) + gsub(/±_/,"[u]",rh) + gsub(/_±/,"[/u]",rh) + gsub(/¤/,"_",rh) + + gsub(/\$\$/,"¤",rh) + gsub(/\$[^\$]+\$/,"±&±",rh) + gsub(/±\$/,"[size=80]",rh) + gsub(/\$±/,"[/size]",rh) + gsub(/¤/,"$",rh) + + return rh " -- [url=http://1190.bicyclesonthemoon.info/ongtext?b=on][b]ong[/b]o[/url][url=http://mrob.com/time/automome/]mome[/url]" +} diff --git a/compare.c b/compare.c new file mode 100644 index 0000000..8585d29 --- /dev/null +++ b/compare.c @@ -0,0 +1,108 @@ +// compare.c +// The tool to compare if two images are identical or not. +// 21.09.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +// Requires Dev Image Library (libdevil) (http://openil.sourceforge.net/) +// on Pentium III libdevil must be recompiled with +// --disable-ssl2 --disable-ssl3 +// (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954) + +#include +#include +#include "IL/il.h" + +#define SAME 0 +#define DIFF_PIX 1 +#define DIFF_SIZE 2 +#define FAIL 3 + +int mustard(const char *t,int m,int e); +int main(int argc, char *argv[]); + +ILuint inpix1, inpix2; +unsigned char q =0; + +int main(int argc, char *argv[]) +{ + + ILubyte *data1, *data2; + + ILuint x1, x2, y1, y2; + unsigned long i,s; + + if (argc<3) + return mustard("compare inpix1 inpix2 ",0,FAIL); + if(argc>3) + q=1; + + ilInit(); + + ilEnable(IL_ORIGIN_SET); + ilEnable(IL_FILE_OVERWRITE); + + ilGenImages(1,&inpix1); + ilGenImages(1,&inpix2); + + ilBindImage(inpix1); + if(!ilLoadImage(argv[1])) + return mustard("inpix1 load fail.",1,FAIL); + if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE)) + return mustard("inpix1 convert fail.",1,FAIL); + + x1=ilGetInteger(IL_IMAGE_WIDTH); + y1=ilGetInteger(IL_IMAGE_HEIGHT); + + data1=ilGetData(); + ilBindImage(inpix2); + if(!ilLoadImage(argv[2])) + return mustard("inpix2 load fail.",1,FAIL); + if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE)) + return mustard("inpix2 convert fail.",1,FAIL); + + x2=ilGetInteger(IL_IMAGE_WIDTH); + if(x1!=x2) + return mustard("different size.",1,DIFF_SIZE); + y2=ilGetInteger(IL_IMAGE_HEIGHT); + if(y1!=y2) + return mustard("different size.",1,DIFF_SIZE); + + data2=ilGetData(); + + s=3*x1*y1; + for(i=0;i. + +BEGIN{ + FS="" + framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + + if(frame ~ /[a-zA-Z]$/) + { + f=int(substr(frame,1,length(frame)-1)) + s=substr(frame, length(frame)) + } + else + { + f=int(frame) + s="" + } + e=int(enhance) + + lastalt=0 + + ch2num[0]="" + num2ch[""]=0 + for(i=1;i<=26;++i) + { + ch=sprintf("%c",i+96) + num2ch[i]=ch + ch2num[ch]=i + } +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + eq=index($0, "=") + + if($0 ~ /^sf-[0-9]+=/) + { + sf=1 + i=int(substr($0, 4, eq-4)) + if(i==f) + this_sf= tolower(substr($0, eq+1)) + if(i==f-1) + prev_sf=tolower(substr($0, eq+1)) + + } + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) +} +END{ + + if (file=="") + exit 1 + + if(this_sf=="") + s="" + else if(s>this_sf && argtab["cfrt"]=="") + s=this_sf + + ongoing=int(argtab["ongoing"]) + if(ongoing>0) + { + statefile= datapath argtab["story"]"/ongstate" + getline temp < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + nextong=int(temptab[3]) + ongfailcount=int(temptab[4]) + } + else + { + last=int(argtab["last"]) + state=3 + nextong=0 + ongfailcount=0 + } + first=int(argtab["first"]) + + if(frame=="") + { + if(ongoing>0) + { + f=last + onlyframe=1 + } + else + { + f=first + onlyframe="" + } + } + + if(flast && argtab["cfrt"]=="") + f=last + + if(argtab["special"] != "") + { + specialfile=datapath argtab["story"]"/"sprintf(argtab["special"],f) + line="" + undertext="" + + while((getline line < specialfile)>0) + { + gsub(/[\r\n]/, "", line) + + if (line == "" && !undertext) + { + undertext=1 + argtab["text"]="" + continue + } + + if (undertext) + { + argtab["text"] = argtab["text"] line "\n" + } + else + { + + eq=index(line, "=") + argtab[substr(line, 1, eq-1)]=substr(line, eq+1) + } + } + close (specialfile) + } + + framedir= (argtab["framedir"]!="" ? argtab["framedir"] : "/aftertime/"argtab["story"]"/") + if(sf!="") + { + frame= framedir sprintf(argtab["frame"(e>0 ? "-"e : "")],f,s) + if (system("[ -f " framepath frame" ]")!=0) + frame= framedir sprintf(argtab["frame"],f,s) + } + else + { + s="" + frame= framedir sprintf(argtab["frame"(e>0 ? "-"e : "")],f) + if (system("[ -f " framepath frame" ]")!=0) + frame=framedir sprintf(argtab["frame"],f) + } + + if(f==last && state==1) + { + print "2 "f" "nextong" "ongfailcount > statefile + close (statefile) + } + + if((f>last || fthis_sf)) || state==0 && argtab["cfrt"]!="") + frame= framedir argtab["cfrt"] + + if(state==0 && argtab["cfrt"]=="") + { + print "Status: 404 Not Found" + print "" + } + + print "Status: 302 Temporal Relocation" + print "Location: "frame + print "" + +} diff --git a/frame.c b/frame.c new file mode 100644 index 0000000..93af30e --- /dev/null +++ b/frame.c @@ -0,0 +1,86 @@ +// frame.c (1190.bicyclesonthemoon.info/aftertime/frame) +// Dynamic frame for the viewer +// 21.06.2018 +// +// Copyright (C) 2015, 2018 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#define STORYDEF_PRINTF "/eizm/data/aftertime/%s/settings" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_FRAME "/eizm/pro/aftertime/frame.awk" + +#include +#include +#include +#include +#include +#include + +s_cgi *cgi; + +int main (int argc, char *argv[]) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char *story; + char *f; + char *enh; + + char arg1[256]; + char arg2[256]; + char arg3[256]; + char storydef[256]; + + cgi=cgiInit(); + + //setvbuf(stdout, NULL, _IONBF, 0); + // dup2(fileno(stdout),fileno(stderr)); + + story=cgiGetValue(cgi,"story"); + f=cgiGetValue(cgi,"f"); + enh=cgiGetValue(cgi,"e"); + + snprintf(arg1,256,"story=%s",story!=NULL ? story : ""); + snprintf(arg2,256,"frame=%s",f!=NULL ? f : ""); + snprintf(arg3,256,"enhance=%s",enh!=NULL ? enh : ""); + + sprintf(storydef,STORYDEF_PRINTF,story!=NULL ? story : "time"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_FRAME,"-v",arg1,"-v",arg2,"-v",arg3,storydef,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + sprintf(storydef,STORYDEF_PRINTF,"default"); + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_FRAME,"-v",arg1,"-v",arg2,"-v",arg3,storydef,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + + return 0; +} diff --git a/info.awk b/info.awk new file mode 100644 index 0000000..47bd110 --- /dev/null +++ b/info.awk @@ -0,0 +1,403 @@ +#// info.awk +#// Info about an aftertime story. +#// 7.01.2019 +#// +#// Copyright (C) 2015-2016, 2018-2019 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + #print"INTERFACE IS BEING DEBUGGED. WAIT FOR IT." + noticepath="/eizm/mem/aftertime/mpost/" + framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + timecmd="date -u +\"%Y%m%d%H\"" + botcastleurl="http://1190.bicyclesonthemoon.info" + + # for(i=0;i<256;++i) + # { + # ch=sprintf("%c",i) + # hex=sprintf("%02X",i) + # dec=sprintf("%u",i) + # ch2hex[ch]=hex + # ch2dec[ch]=dec + # } + + listfile = datapath "stories" + stories=0 + line="" + while((getline line < listfile)>0) + { + gsub(/[\r\n]/,"",line) + eq=index(line,"=") + + storytab[stories]=substr(line, 1, eq-1) + storyname[stories]=substr(line, eq+1) + ++stories + } + close(listfile) + + if(frame !~ /^[0-9]+[a-z]?$/){ + noframe=1 + } + else if(frame ~ /[a-zA-Z]$/) + { + f=int(substr(frame,1,length(frame)-1)) + s=substr(frame, length(frame)) + } + else + { + f=int(frame) + s="" + } + e=int(enhance) + if(notice~/^[0-9]+$/) + n=int(notice) + timecmd | getline thistime + close(timecmd) + + lastalt=0 + + ch2num[0]="" + num2ch[""]=0 + for(i=1;i<=26;++i) + { + ch=sprintf("%c",i+96) + num2ch[i]=ch + ch2num[ch]=i + } + alttabsize=0 + argtabsize=0 +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + eq=index($0, "=") + if($0 ~ /^[0-9]+=/) + { + i=int(substr($0, 1, eq-1)) + alttab[alttabsize]=substr($0, eq+1) + alttabn[alttabsize]=i + ++alttabsize + + # i=int(substr($0, 1, eq-1)) + # if(f>=i && i>=lastalt) + # { + # alt=substr($0, eq+1) + # lastalt=i + # } + } + else if($0 ~ /^sf-[0-9]+=/) + { + sf=1 + i=int(substr($0, 4, eq-4)) + if(i==f) + this_sf= tolower(substr($0, eq+1)) + if(i==f-1) + prev_sf=tolower(substr($0, eq+1)) + + } + if (!(substr($0, 1, eq-1) in argtab)) + { + argtabind[argtabsize]=substr($0, 1, eq-1) + ++argtabsize + } + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) +} +END{ + + if (story=="" && f=="") + { + for (i=0; i0) + { + statefile= datapath argtab["story"]"/ongstate" + getline temp < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + nextong=int(temptab[3]) + ongfailcount=int(temptab[4]) + } + else + { + last=int(argtab["last"]) + state=3 + } + first=int(argtab["first"]) + + if(noframe!=""){ + if(ongoing>0) + { + print "state="state + print "last="last + print "nextong="nextong + print "ongfailcount="ongfailcount + } + for (i=0; i< argtabsize; ++i) + { + if((argtabind[i] ~ /^[0-9]+$/)&&(ongoing>0)) + { + j=int(argtabind[i]) + if(j<=last) + print argtabind[i]"="argtab[argtabind[i]] + } + else if((argtabind[i] ~ /^sf-[0-9]+$/)&&(ongoing>0)) + { + j=int(substr(argtabind[i],3)) + if(j<=last) + print argtabind[i]"="argtab[argtabind[i]] + } + else if((argtabind[i] ~ /^(last|finalreplacetime|finalreplaceframe)$/)&&(ongoing>0)) + { + } + else + print argtabind[i]"="argtab[argtabind[i]] + } + } + else{ + if(f>last || fthis_sf)) + exit 0 + + if(this_sf=="") + s="" + + if (s!="") + { + if(argtab[s] != "") + s2=argtab[s] + else + s2=s + n=-1 + } + + if(n>0) + { + noticepost=noticepath argtab["story"]"-"sprintf("%04u",f)"-"sprintf("%02u",n) + noticetabsize=0 + for(j=0;(getline line < noticepost)>0;++j) + { + gsub(/[\r\n]/,"",line) + eq=index(line,"=") + noticeind=substr(line, 1, eq-1) + noticeval=substr(line, eq+1) + + if (!(noticeind in noticetab)) + { + noticetabind[noticetabsize]=noticeind + ++noticetabsize + } + noticetab[noticeind]=noticeval + + } + if(j==0) + exit 0 + nposttime=noticetab["y"]noticetab["m"]noticetab["d"]noticetab["h"] + if (thistime0) + { + gsub(/[\r\n]/, "", line) + + if (line == "" && !undertext) + { + undertext=1 + argtab["text"]="" + continue + } + + if (undertext) + { + argtab["text"] = argtab["text"] line "\n" + } + else + { + eq=index(line, "=") + argtab[substr(line, 1, eq-1)]=substr(line, eq+1) + } + } + close (specialfile) + } + + ongtimefile= datapath argtab["story"]"/ongtime" + + while((getline line < ongtimefile)>0) + { + ongind=index(line," ") + ongft=substr(line,1,ongind-1) + ongt=substr(line,ongind+1,4) substr(line,ongind+6,2) substr(line,ongind+9,2) substr(line,ongind+12,2) substr(line,ongind+15,2) + if(ongft ~ /^[0-9]+[a-z]$/) + ongf=int(substr(ongft,1,ongind-2)) substr(ongft,ongind-1,1) + else + ongf=int(ongft) + + if(ongf==(f s) && ongt ~ /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/) + ongtime=ongt + } + close(ongtimefile) + + if ("alt" in argtab) + alt=argtab["alt"] + else + { + for(i=0; i=alttabn[i] && alttabn[i]>=lastalt) + { + alt=alttab[i] + lastalt=alttabn[i] + } + } + } + + if(argtab["number"]!="") + numberformat=argtab["number"] + else + { + if (sf!="") + numberformat="%u%s" + else + numberformat="%u" + } + + framedir= "/aftertime/"argtab["story"]"/" + if(sf!="") + { + title=sprintf(argtab["title"(e>0 ? "-"e : "")],f,s2) + frame=framedir sprintf(argtab["frame"(e>0 ? "-"e : "")],f,s) + otherviewerurl=sprintf(argtab["otherviewerurl"], f+int(argtab["othervieweroffset"]),s2) + } + else + { + s="" + title=sprintf(argtab["title"(e>0 ? "-"e : "")],f) + frame= framedir sprintf(argtab["frame"(e>0 ? "-"e : "")],f) + otherviewerurl=sprintf(argtab["otherviewerurl"], f+int(argtab["othervieweroffset"])) + } + + if (system("[ -f " framepath frame" ]")!=0) + exit 0 + + print "story="argtab["story"] + print "f="f s + print "e="e + print "frame="frame + print "alt="alt + print "title="title + if(ongtime!="") + print "ongtime="ongtime + + max_enhance=int(argtab["enhance"]) + + + if(max_enhance>0) + { + for(i=0;i<=max_enhance;++i) + { + if(sf!="") + enhancedframe = framedir sprintf(argtab["frame"(i>0?"-"i:"")],f,s) + else + enhancedframe = framedir sprintf(argtab["frame"(i>0?"-"i:"")],f) + + if (system("[ -f " framepath enhancedframe" ]")==0) + print "enhance-"i"="argtab["enhance-"i] + } + } + + for(i=1; i<=99; ++i) + { + noticepost=noticepath argtab["story"]"-"sprintf("%04u",f)"-"sprintf("%02u",i) + for(j=0;(getline line < noticepost)>0;++j) + { + gsub(/[\r\n]/,"",line) + eq=index(line,"=") + noticetab[substr(line, 1, eq-1)]=substr(line, eq+1) + } + if(j==0) + break; + nposttime=noticetab["y"]noticetab["m"]noticetab["d"]noticetab["h"] + if (thistime/,"\n",ht) + while ((i=match(ht, /&#[0-9]+;/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + j=index(ht, ";") + num=int(substr(ht, 3, j-3)) + un=un sprintf("%c",num) + ht=substr(ht, j+1) + } + un=un ht + return un +} diff --git a/info.c b/info.c new file mode 100644 index 0000000..c73a5ba --- /dev/null +++ b/info.c @@ -0,0 +1,113 @@ +// info.c (1190.bicyclesonthemoon.info/aftertime/info) +// Info about an aftertime story. +// 3.01.2019 +// +// Copyright (C) 2016, 2019 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#define STORYDEF_PRINTF "/eizm/data/aftertime/%s/settings" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_INFO "/eizm/pro/aftertime/info.awk" + +#include +#include +#include +#include +#include +#include + +s_cgi *cgi; + +void escape(char *text); + +int main (int argc, char *argv[]) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char *story; + char *f; + char *enh; + char *notic; + + char arg1[256]; + char arg2[256]; + char arg3[256]; + char arg4[256]; + char storydef[256]; + + cgi=cgiInit(); + + //setvbuf(stdout, NULL, _IONBF, 0); + //dup2(fileno(stdout),fileno(stderr)); + + story=cgiGetValue(cgi,"story"); + f=cgiGetValue(cgi,"f"); + enh=cgiGetValue(cgi,"e"); + notic=cgiGetValue(cgi,"n"); + + if(story!=NULL) + escape(story); + + snprintf(arg1,256,"story=%s",story!=NULL ? story : ""); + snprintf(arg2,256,"frame=%s",f!=NULL ? f : ""); + snprintf(arg3,256,"enhance=%s",enh!=NULL ? enh : ""); + snprintf(arg4,256,"notice=%s",notic!=NULL ? notic : ""); + + sprintf(storydef,STORYDEF_PRINTF,story!=NULL ? story : "time"); + + printf("Content-type: text/plain; charset=utf-8\n\n"); + + // if((story==NULL)&&(f==NULL)){ + // fputs("time\nprickly\npotm\nlucky\nbeany\nbean2\nt1i\nzodiac\nbftf\nt-1\nphys\n",stdout); + // return 0; + // } + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_INFO,"-v",arg1,"-v",arg2,"-v",arg3,"-v",arg4,storydef,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + //if(r) + //{ + // sprintf(storydef,STORYDEF_PRINTF,"default"); + // fflush(stdout); + // sub=fork(); + // if(sub==0) + // { + // r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_INFO,"-v",arg1,"-v",arg1,"-v",arg1,storydef,(char *)0); + // exit(r); + // } + // waitpid(sub,&r,0); + //} + + return 0; +} + +void escape(char *text){ + unsigned short i, len; + + len=strlen(text); + for (i=0;i. + + +BEGIN{ + FS="=" + fora="http://1190.bicyclesonthemoon.info/ott" + useragent="\"bothasar_p (http://1190.bicyclesonthemoon.info/aftertime; time after Time post bot)\"" +}; +{ + argtab[$1]=$2 +}; +END{ + printf ("username=%s",argtab["username"])>postfile + printf ("&password=%s",argtab["password"])>>postfile + printf ("&subject=%s",argtab["subject"])>>postfile + if("&addbbcode20" in argtab) + printf ("&addbbcode20=%s",argtab["addbbcode20"])>>postfile + printf ("&message=%s",argtab["message"])>>postfile + printf ("&post=%s","Submit")>>postfile + if("disable_bbcode" in argtab) + printf ("&disable_bbcode=%s",argtab["disable_bbcode"])>>postfile + if("disable_smilies" in argtab) + printf ("&disable_smilies=%s",argtab["disable_smilies"])>>postfile + if("disable_magic_url" in argtab) + printf ("&disable_magic_url=%s",argtab["disable_magic_url"])>>postfile + if("attach_sig" in argtab) + printf ("&attach_sig=%s",argtab["attach_sig"])>>postfile + if("notify" in argtab) + printf ("¬ify=%s",argtab["notify"])>>postfile + printf ("&creation_time=%s",argtab["creation_time"])>>postfile + printf ("&form_token=%s",argtab["form_token"])>>postfile + close(postfile) + + if(system("wget -q -t 3 --connect-timeout=60 --post-file=" postfile " -U " useragent " -O " tempfile " \""fora "/post\"")) + { + print "Submit fail." + exit 1 + } + + while((getline temp < tempfile)>0) + { + if (temp ~ /

information/) + { + success=1 + } + } + close(tempfile) + + if (success!=1) + { + print "Sent back to preview!" + exit INDELIVERABLE + } +} diff --git a/mpview.c b/mpview.c new file mode 100644 index 0000000..b1fbfd6 --- /dev/null +++ b/mpview.c @@ -0,0 +1,109 @@ +// mpview.c (1190.bicyclesonthemoon.info/aftertime/view) +// Display one post +// 28.03.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include + +#define RM_PATH "/bin/rm" +#define CAT_PATH "/bin/cat" +#define MAWK_PATH "/usr/bin/mawk" + +#define POST_PATH "/eizm/mem/aftertime/mpost/" + +#define AWK_MVIEW "/eizm/pro/aftertime/mview.awk" +#define TEMP_PATH "/eizm/tmp/aftertime/mpview." + +int main() +{ + s_cgi *cgi; + pid_t sub; + int r; + + char line[32]; + // char filename[32]; + char postpath[256]; + // char cat[8]; + + char *arg; + char key[64]; + + char path2[256]; + + cgi=cgiInit(); + + printf("Content-type: text/html\n\n"); + + arg=cgiGetValue(cgi,"v"); + sprintf(line,"%s",arg?arg:"???"); + + arg=cgiGetValue(cgi,"key"); + sprintf(key,"key=%s",arg?arg:"???"); + + // sprintf(filename,"%s",line); + sprintf(postpath,"%s%s",POST_PATH,line); + + + sprintf(path2,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + + printf("\n"); + printf("\n"); + printf("time after Time • Bicycles on the Moon\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\"1190.bicyclesonthemoon.info\"\n"); + printf("

time after Time

\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_MVIEW,"-v","bg=1","-v","s=1","-v",key,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + printf("
\n",line); + printf("
\n"); + printf("%s %s POST NOT FOUND.\n",AWK_MVIEW,postpath); + printf("\n
\n"); + printf("
\n"); + } + + printf("back to the list
\n"); + printf("
1190.bicyclesonthemoon.info\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",path2,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("

Ch*rpin* M*stard! file not deleted!

"); + + return 0; +} diff --git a/mview.awk b/mview.awk new file mode 100644 index 0000000..062883e --- /dev/null +++ b/mview.awk @@ -0,0 +1,38 @@ +#// mview.awk +#// Display one post +#// 31.04.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(key!=argtab["key"]) + { + print"Invalid key.

" + exit + } + print "
" + print "
"argtab["story"]"-"argtab["frame"]"-"argtab["round"]" • "argtab["subject_h"]"
" + print "
"argtab["username_h"]" • "argtab["y"]"-"argtab["m"]"-"argtab["d"]" "argtab["h"]":00
quote edit remove"(argtab["ID"]!=""?" OTT":"")"
" + print "
"((argtab["HTML"]!="")?argtab["HTML"]:argtab["BBHTML"])"
" + print "
" +} diff --git a/ong-bsta.awk b/ong-bsta.awk new file mode 100644 index 0000000..179f41b --- /dev/null +++ b/ong-bsta.awk @@ -0,0 +1,938 @@ +#// ong-bsta.awk +#// The bot to ketchup frames from the bsta viewer +#// 6.01.2019 +#// +#// Copyright (C) 2019 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . +#// + +BEGIN{ + FS="" + framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + temppath="/eizm/tmp/aftertime/" + passpath="/eizm/mem/aftertime/pass/" + + bstapath="/eizm/data/bsta/" + bstaviewpath="/eizm/www/time/bsta/" + + timecmd="date -u +%Y%m%d%H%s" + timecmd2="date -u +\"%Y-%m-%d %H:%M:%S\"" + ongtimecmd1="date -u -d@" + ongtimecmd2=" +\"%Y-%m-%d %H:%M:%S\"" + + botcastleurl="http://1190.bicyclesonthemoon.info" + + cp="/bin/cp" + mawk="/usr/bin/mawk" + chmod="/bin/chmod" + + # wget="/usr/bin/wget" + # remap="/eizm/pro/aftertime/remapt-1" + npb="/eizm/pro/ong1/npb" + # bot4awk="/eizm/pro/aftertime/bot4.awk" + # uploadawk="/eizm/pro/aftertime/upload.awk" + + timecmd2 | getline thistime2 + close(timecmd2) + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i) + dec=sprintf("%u",i) + ch2hex[ch]=hex + ch2dec[ch]=dec + } +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + eq=index($0, "=") + + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) +} +END{ + print "" + print thistime2" "argtab ["story"] + + if (file=="") + { + print "No data." + exit 1 + } + + if(argtab["ongoing"]!="2") + { + print "Story is not externally onged." + exit 1 + } + + framedir = "aftertime/"argtab["story"]"/" + + temp="" + statefile= datapath argtab["story"]"/ongstate" + getline temp < statefile + getline alt < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + nextong=int(temptab[3]) + ongfailcount=int(temptab[4]) + + if(state==4) + { + print "Time to start onging." + f=int(argtab["first"]) + } + else if (state==2 || state==1) + f=last+1 + else + { + print "Onging not avtive." + exit 1 + } + + bstasettingsfile = bstapath "settings" + bstastatefile = bstapath "state" + bstadefaultfile = bstapath "default" + + bstaargtab[0]="" + specialtab[0]="" + attachtab[0]="" + + timefile= datapath argtab["story"]"/ongtime" + + while(1) + { + bstaspecialfile = bstapath f + specialfile = datapath argtab["story"]"/"sprintf(argtab["special"],f) + + for (i in bstaargtab) + delete bstaargtab[i] + + readdatafile(bstasettingsfile,bstaargtab) + readdatafile(bstastatefile,bstaargtab) + readdatafile(bstadefaultfile,bstaargtab) + readdatafile(bstaspecialfile,bstaargtab) + + # for (i in bstaargtab) + # print i": "bstaargtab[i] + + if (f > int(bstaargtab["last"])) { + print "Wait for frame "f"." + exit 0 + } + + print "ONG frame "f"." + + for (i in specialtab) + delete specialtab[i] + + #skip NPB frame + + specialtab["title"]=bstaargtab["title"] + # specialtab["alt"]=bstaargtab["title"] + specialtab["frame"]=sprintf(bstaargtab["frame"],f,bstaargtab["ext"]) + specialtab["text"]=bstaargtab["content"] + + inframe = bstaviewpath specialtab["frame"] + frame= framepath framedir specialtab["frame"] + + + text_HTML="" + text_BB="" + text=specialtab["text"] + + while (text!="") + { + eq=match(text,/(###([^#;]*);)/) + + if(eq) + { + text_HTML=text_HTML substr(text, 1, RSTART - 1) + text_BB = text_BB substr(text, 1, RSTART - 1) + tag = substr(text, RSTART +3, RLENGTH -4) + text= substr(text, RSTART + RLENGTH) + + if (match(tag,/^fr&([0-9]+)$/)) + { + id=int(substr(tag,4)) + + tag="/aftertime/frame?story="arrtab["story"]"&f="id + text_HTML=text_HTML tag + text_BB=text_BB botcastleurl tag + } + else if (match(tag,/^vw&([0-9]+)$/)) + { + id=int(substr(tag,4)) + + tag="/aftertime/viewer?story="arrtab["story"]"&f="id + text_HTML=text_HTML tag + text_BB=text_BB botcastleurl tag + + } + else if (match(tag,/^att&([0-9]+)$/)) + { + id=int(substr(tag,5)) + + print "ONG attachment "id"." + + attachfile=bstapath"a"id + for (i in attachtab) + delete attachtab[i] + readdatafile(attachfile, attachtab) + + outfile=framepath framedir attachtab["filename"] + infile= bstapath attachtab["filename"] + + cpcmd = cp" "infile" "outfile + chmodcmd = chmod" +r "outfile + + if (attachtab["content"]!="") + { + printf("%s",attachtab["content"]) > outfile + close(outfile) + } + else if(system(cpcmd)!=0) + { + print "Attachment upload failed." + exit 1 + } + + if(system(chmodcmd)!=0) + { + print "Attachment chmod failed." + exit 1 + } + + tag="/aftertime/"argtab["story"]"/"attachtab["filename"] + text_HTML=text_HTML tag + text_BB=text_BB botcastleurl tag + } + else + { + + } + + } + + else + { + text_HTML = text_HTML text + text_BB = text_BB text + text = "" + } + + } + + # print text_HTML + # print text_BB + + debug="" + specialtab["HTML"]=bb2html(text_HTML) + specialtab["BBHTML"]=bb2bb(text_BB) + + cpcmd = cp" "inframe" "frame + chmodcmd = chmod" +r "frame + + ongtimecmd= ongtimecmd1 bstaargtab["ongtime"] ongtimecmd2 + ongtimecmd | getline ongtime + close(ongtimecmd) + + print ongtime + + if (state==4) + print sprintf("%04u ",f)ongtime > timefile + else + print sprintf("%04u ",f)ongtime >> timefile + close(timefile) + + if(system(cpcmd)!=0) + { + print "Frame upload failed." + exit 1 + } + + if(system(chmodcmd)!=0) + { + print "Frame chmod failed." + exit 1 + } + + # print debug + + for (i in specialtab) + { + if (i!="text") + print i"="specialtab[i] > specialfile + } + print "" > specialfile + if (specialtab["text"]!="") + printf("%s",specialtab["text"]) > specialfile + close (specialfile) + + + print sprintf("%u %u %u %u",2,f,0,0) > statefile + close (statefile) + + state=2 + ++f + + # exit 0 + } +} + +#limited compatibility with bsta data file format +function readdatafile (datafile, argtab, line,undertext,eq) +{ + line="" + while((getline line < datafile)>0) + { + gsub(/[\r\n]/, "", line) + + if (line == "" && !undertext) + { + undertext=1 + argtab["content"]="" + } + else if (undertext) + { + argtab["content"] = argtab["content"] line "\n" + } + else + { + eq = match(line, /(: |=)/) + + if (eq!=0) { + argtab[substr(line, 1, RSTART - 1)]=substr(line, RSTART + RLENGTH) + } + } + } + close (datafile) + + # return bstaargtab +} + +function bb2bb (text) +{ + gsub(/\[(fq|tq)\]/, "[quote]", text) + gsub(/\[\/(fq|tq)\]/, "[/quote]", text) + gsub(/\[br\]/, "[color=#BB6622]", text) + gsub(/\[ni\]/, "[color=#FF8800]", text) + gsub(/\[po\]/, "[color=#0057AF]", text) + gsub(/\[\/(br|ni|po)\]/, "[/color]", text) + + return htmlescape(text,"","br") +} + +function bb2html(text, depth,count,bbtree,html,tag,tagstart,taglength,elm,tagv,tagname,tagvalue,matchname) +{ + depth=0 + count[0]=1 + bbtree["0"]="" + bbtree["0.n"]=0 + bbtree["0.t"]="post" + bbtree["0.v"]=argtab["subject"] + html="" + # gsub(/=/,"=",text) + debug = debug "\n\nBuild BBcode tree:" + while(length(text)!=0) + { + tag=match(text, /\[\/?[a-z0-9\*]+(=(([^\[<>\"\]]*)|(\"[^\"<>]*\")))?\]/) + #"#\"" + if (tag==0) + { + debug = debug "\ntext: " text + bbtree[ind(count,depth)]=text + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + text="" + break; + } + tagstart=RSTART + taglength=RLENGTH + if(tagstart>1) + { + elm=substr(text,1,tagstart-1) + debug = debug "\ntext: " elm + bbtree[ind(count,depth)]=elm + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + } + tag=substr(text,tagstart,taglength) + text=substr(text,tagstart+taglength) + debug = debug "\ntag: " tag + if(tag!~/^\[\//) + { + tagv=index(tag,"=") + if(tagv<2) + { + tagname=substr(tag,2,length(tag)-2) + tagvalue="" + } + else + { + tagname=substr(tag,2,tagv-2) + tagvalue=substr(tag,tagv+1,length(tag)-tagv-1) + } + if(tagname !~ /^((fq)|(tq)|(ni)|(po)|(quote)|b|i|u|(code)|(img)|(url)|(size)|(color)|(center)|(right)|(sub)|(sup)|(s)|(spoiler)|(list)|(br)|(\*))$/) + { + debug = debug "\nunknown tag" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||bbtree[indt(count,depth)".t"] == "img"||(bbtree[indt(count,depth)".t"] == "spoiler" && tagname=="spoiler")||(bbtree[indt(count,depth)".t"] == "size" && tagname=="size")) + { + debug = debug "\nthis tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname=="*") + { + if(bbtree[indt(count,depth)".t"]==tagname) + { + debug = debug "\nimplied tag: [/"tagname"]" + debug = debug "\nmatched" + bbtree[ind(count,depth)]="[/"tagname"]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + else if(bbtree[indt(count,depth)".t"]!="list") + { + debug = debug "\nthis tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + } + debug = debug "\nname: " tagname " value: " tagvalue + bbtree[ind(count,depth)]=tagname" "tagvalue + bbtree[ind(count,depth)".k"]="s" + bbtree[indt(count,depth)".n"]=count[depth] + ++depth + count[depth]=1 + bbtree[indt(count,depth)]=tag + bbtree[indt(count,depth)".n"]=0 + bbtree[indt(count,depth)".t"]=tagname + bbtree[indt(count,depth)".v"]=tagvalue + + # if(tagname=="br") #or other single tags in the future + # { + # debug = debug "\nmatched" + # bbtree[ind(count,depth)]=tag + # bbtree[ind(count,depth)".k"]="e" + # bbtree[ind(count,depth)".m"]=1 + # bbtree[ind(count,depth)".t"]=tagname + # bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + # bbtree[indt(count,depth)".n"]=count[depth] + # bbtree[indt(count,depth)".m"]=1 + # count[depth]="" + # --depth + # ++count[depth] + # } + } + else + { + if(depth<=0) + { + debug = debug "\n""unmatched" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + tagname=substr(tag,3,length(tag)-3) + if(tagname=="list"&&bbtree[indt(count,depth)".t"]=="*") + { + debug = debug "\nimplied tag: [/*]" + debug = debug "\nmatched" + bbtree[ind(count,depth)]="[/*]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]="*" + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + debug = debug "\nname: " tagname + matchname=bbtree[indt(count,depth)".t"] + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||(bbtree[indt(count,depth)".t"] == "img" && tagname != "img")) + { + debug = debug "\nthis tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname!=matchname) + { + debug = debug "\nmismatched: " matchname + # bbtree[ind(count,depth)]=tag + # bbtree[indt(count,depth)".n"]=count[depth] + # ++count[depth] + # continue + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".t"]=bbtree[indt(count,depth)".t"] + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + count[depth]="" + --depth + ++count[depth] + continue + } + debug = debug "\nmatched" + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + } + if(depth>0) + debug = debug "\nunclosed tags: " depth + + debug = debug "\n\n""generate HTML:" + depth=0 + count[0]=0 + while(count[0]<=bbtree["0.n"]&&depth>=0) + { + if(count[depth]==0) + { + tag=bbtree[indt(count,depth)] + tagname=bbtree[indt(count,depth)".t"] + tagvalue=bbtree[indt(count,depth)".v"] + debug = debug "\nname: "tagname" value: "tagvalue" elements: "bbtree[indt(count,depth)".n"] + if(tagname == "post") + { + } + else if(bbtree[indt(count,depth)".m"]=="") + { + debug = debug "\nunmatched" + html = html htmlescape(tag) + } + else if(tagname == "quote") + { + if (tagvalue=="") + { + html = html "
" + } + else + { + if(tagvalue !~ /^\".*\"$/) + #"#\"" + tagvalue="You forgot about the quote marks, "htmlescape(tagvalue) + else + tagvalue=bb2html(substr(tagvalue,2,length(tagvalue)-2)) + html = html "
"tagvalue" wrote:
" + } + } + else if (tagname == "fq") + { + html = html"
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "tq") + { + html = html"
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "br") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "ni") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "po") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "b") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "i") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "u") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html htmlescape(tag) + debug = debug "\nnot a tag, actually" + } + else + { + html=html"
Code: Select all
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + } + else if (tagname == "img") + html=html"" + } + else if (tagname == "size") + { + if (tagvalue==""||(tagvalue !~ /^[0-9]+$/)||(tagvalue+0)>200) + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname == "color") + { + if (tagvalue==""||tagvalue !~ /^#[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]$/) #for some reason /^([0-9A-F]{6})$/ doesn't work. + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname ~ /^((center)|(right))$/) + { + html=html"
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="s") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sub") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sup") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="spoiler") + { + html=html"
Spoiler:
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="list") + { + if(tagvalue=="") + html=html"
    " + else + { + if (tagvalue=="1") + tagvalue="decimal" + else if (tagvalue=="i") + tagvalue="lower-roman" + else if (tagvalue=="I") + tagvalue="upper-roman" + else if (tagvalue=="a") + tagvalue="lower-alpha" + else if (tagvalue=="A") + tagvalue="upper-alpha" + else + { + html=html"This tag should have a correct value. " + tagvalue="decimal" + } + html=html"
      " + } + } + else if (tagname=="*") + { + html=html"
    1. " + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + # else if (tagname == "br") + # { + # html = html"
      " + # if(tagvalue!="") + # html=html"This tag shouldn't have any value. " + # } + else + { + debug = debug "\nunknown tag" + html = html htmlescape(tag) + } + ++count[depth] + } + else if(bbtree[ind(count,depth)".k"]=="s") + { + debug = debug "\nentering tag:" + ++depth + count[depth]=0 + } + else if(bbtree[ind(count,depth)".k"]=="e") + { + debug = debug "\nleaving tag:" + tag=bbtree[ind(count,depth)] + tagname=bbtree[ind(count,depth)".t"] + tagvalue=bbtree[ind(count,depth)".v"] + debug = debug "\nname: "tagname" value: "tagvalue + if (tagname == "post") + { + } + else if(bbtree[ind(count,depth)".m"]=="") + { + debug = debug "\nunmatched" + html = html htmlescape(tag) + } + else if(tagname == "quote") + html = html "
" + else if (tagname ~/^(b|i|u|(size)|(color)|(br)|(ni)|(po))$/) + html = html"" + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html htmlescape(tag) + debug = debug "\nnot a tag, actually" + } + else + html = html"" + } + else if (tagname == "img") + { + html = html"\" alt=\"Image\" />" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if(tagname=="url") + html=html"" + else if (tagname ~ /^((center)|(right)|(fq)|(tq))$/) + html=html"
" + else if (tagname =="s") + html=html"" + else if (tagname =="sub") + html=html"" + else if (tagname =="sup") + html=html"" + else if (tagname=="spoiler") + html=html"" + else if (tagname=="list") + { + if (tagvalue=="") + html=html"" + else + html=html"" + } + else if (tagname=="*") + html=html"" + # else if (tagname == "br") # + # { + # # + # } + else + { + debug = debug "\nunknown tag" + html = html htmlescape(tag) + } + count[depth]="" + --depth + ++count[depth] + } + else if(count[depth]>bbtree[indt(count,depth)".n"]) + { + debug = debug "\nrun out of elements in this tag; leaving" + count[depth]="" + --depth + ++count[depth] + } + else + { + tag=bbtree[ind(count,depth)] + debug = debug "\ntext: "tag + + tag=htmlescape(tag,"","br") + + if(bbtree[indt(count,depth)".t"] == "code") + { + gsub(/ /,"\\ ",tag) + gsub(/\t/,"\\ \\ ",tag) + } + else{ + gsub(/ /,"\\  ",tag) + gsub(/ /," \\ ",tag) + # gsub(/
/,"
\\ ",tag) + } + + + if(nourl==""&& bbtree[indt(count,depth)".t"] !~ /^((code)|(img)|(url))$/) + gsub(/https?:\/\/[^\n\r\t<> ]+/,"&",tag) + # if(nosmil=="" && bbtree[indt(count,depth)".t"] !~ /^((code)|(img))$/) + # { + # gsub(/(^|[\n\r\t ]):D($|[\n\r\t ])/," \":D\" ",tag) + # gsub(/(^|[\n\r\t ]):\)($|[\n\r\t ])/," \":)\" ",tag) + # gsub(/(^|[\n\r\t ]):\(($|[\n\r\t ])/," \":(\" ",tag) + # gsub(/(^|[\n\r\t ]):o($|[\n\r\t ])/," \":o\" ",tag) + # gsub(/(^|[\n\r\t ]):shock:($|[\n\r\t ])/," \":shock:\" ",tag) + # gsub(/(^|[\n\r\t ]):\?($|[\n\r\t ])/," \":?\" ",tag) + # gsub(/(^|[\n\r\t ])8-\)($|[\n\r\t ])/," \"8-)\" ",tag) + # gsub(/(^|[\n\r\t ]):lol:($|[\n\r\t ])/," \":lol:\" ",tag) + # gsub(/(^|[\n\r\t ]):x($|[\n\r\t ])/," \":x\" ",tag) + # gsub(/(^|[\n\r\t ]):P($|[\n\r\t ])/," \":P\" ",tag) + # gsub(/(^|[\n\r\t ]):oops:($|[\n\r\t ])/," \":oops:\" ",tag) + # gsub(/(^|[\n\r\t ]):cry:($|[\n\r\t ])/," \":cry:\" ",tag) + # gsub(/(^|[\n\r\t ]):evil:($|[\n\r\t ])/," \":evil:\" ",tag) + # gsub(/(^|[\n\r\t ]):twisted:($|[\n\r\t ])/," \":twisted:\" ",tag) + # gsub(/(^|[\n\r\t ]):roll:($|[\n\r\t ])/," \":roll:\" ",tag) + # gsub(/(^|[\n\r\t ]):wink:($|[\n\r\t ])/," \":wink:\" ",tag) + # gsub(/(^|[\n\r\t ]);\)($|[\n\r\t ])/," \":wink:\" ",tag) + # gsub(/(^|[\n\r\t ]):!:($|[\n\r\t ])/," \":!:\" ",tag) + # gsub(/(^|[\n\r\t ]):\?:($|[\n\r\t ])/," \":?:\" ",tag) + # gsub(/(^|[\n\r\t ]):idea:($|[\n\r\t ])/," \":idea:\" ",tag) + # gsub(/(^|[\n\r\t ]):arrow:($|[\n\r\t ])/," \":arrow:\" ",tag) + # gsub(/(^|[\n\r\t ]):\|($|[\n\r\t ])/," \":|\" ",tag) + # gsub(/(^|[\n\r\t ]):mrgreen:($|[\n\r\t ])/," \":mrgreen:\" ",tag) + # } + + html = html tag + ++count[depth] + } + } + debug = debug "\ndone\n" + return html +} + +function ind(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii<=depth;++ii) + { + if(ii!=0) + iindex = iindex "." + iindex = iindex count[ii] + } + # debug = debug "\n" iindex + return iindex +} +function indt(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "\n" iindex + return iindex +} +function indtu(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "\n" iindex + return iindex +} +function htmlescape(name,less,br, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if(ch == "\n") + escaped = escaped ((br!="")?"
":"&#"ch2dec[ch]";") + else if(ch =="\r") + escaped = escaped ((br!="")?"":"&#"ch2dec[ch]";") + else if(ch == "\"" && less=="") + escaped = escaped "&#"ch2dec[ch]";" + else if(ch ~ /[=<>&]/) + escaped = escaped "&#"ch2dec[ch]";" + else + escaped = escaped ch + } + return escaped +} +function hexencode(name, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1) + escaped = escaped ch2hex[ch] + } + return escaped +} + diff --git a/ong-mscha-t-1.awk b/ong-mscha-t-1.awk new file mode 100644 index 0000000..b8d1318 --- /dev/null +++ b/ong-mscha-t-1.awk @@ -0,0 +1,189 @@ +#// ong-mscha-t-1.awk +#// The bot to ketchup frames from the mschaviewer, and enhance by remapping +#// 21.12.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . +#// +BEGIN{ + FS="" + framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + temppath="/eizm/tmp/aftertime/" + passpath="/eizm/mem/aftertime/pass/" + + timecmd="date -u +%Y%m%d%H%s" + + cp="/bin/cp" + mawk="/usr/bin/mawk" + wget="/usr/bin/wget" + remap="/eizm/pro/aftertime/remapt-1" + npb="/eizm/pro/ong1/npb" + bot4awk="/eizm/pro/aftertime/bot4.awk" + uploadawk="/eizm/pro/aftertime/upload.awk" +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + eq=index($0, "=") + + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) +} +END{ + + if (file=="") + exit 1 + + if(argtab["ongoing"]!="2") + exit 1 + + # timecmd | getline thistime + # close(timecmd) + + statefile= datapath argtab["story"]"/ongstate" + passfile= passpath argtab["story"] + getline temp < statefile + getline alt < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + + f=last+1 + + nextstate="2" + + tempfile = temppath "ongmscha-"argtab["story"]"--1" + tempfile2 = temppath "ongmscha-"argtab["story"]"--2" + optionfile = datapath argtab["story"]"/settings" + framedir = "aftertime/"argtab["story"]"/" + + system("sleep 15") + while(1) + { + timecmd | getline thistime + close(timecmd) + + timetext = substr(thistime,1,10); + timenumber = substr(thistime,11); + + newalt="" + frameurl= sprintf(argtab["otherviewerframe"],f) + viewerurl= sprintf(argtab["otherviewerurl"],f) + + frame= framepath framedir sprintf(argtab["frame"],f) + npbframe= framepath framedir sprintf(argtab["npbframe"],f) + + remapframe= framepath framedir sprintf(argtab["frame-1"],f) + npbremapframe= framepath framedir sprintf(argtab["npbframe-1"],f) + + getfcmd= wget " -q -O " frame " "frameurl + getvcmd= wget " -q -O " tempfile " "viewerurl + npbcmd= sprintf(npb " %s %s q",frame,npbframe) + ongcmd= mawk" -f " bot4awk" -v story="argtab["story"]" -v frame="last" "optionfile + ongremapcmd= mawk" -f " bot4awk" -v story="argtab["story"]" -v frame="last" -v enhance=1 "optionfile + npbremapcmd= sprintf(npb " %s %s q",remapframe,npbremapframe) + addhashcmd= mawk" -f "uploadawk" -v timenumber="timenumber" -v timetext="timetext" -v tempfile="tempfile" "tempfile2 + + if(system(getfcmd)!=0) + break + system("sleep 5") + + if(system(getvcmd)!=0) + break + system("sleep 1") + + foundalt="" + foundpal="" + while ((getline temp < tempfile) > 0) + { + if(index(temp,frameurl)!=0 && foundalt=="") + { + newalt=substr(temp,index(temp,"title=\"")+7) + newalt=substr(newalt,1,index(newalt,"\"")-1) + foundalt=1 + } + if(index(temp,"class=\"hash\"")!=0 && foundpal=="" ) + { + pal=substr(temp,index(temp,">")+1) + pal=substr(pal,1,index(pal,".")-1) + foundpal=1 + } + if(foundalt!="" && foundpal!="") + break; + } + close(tempfile) + # if(newalt=="") + # break + + remapcmd= remap " "frame" "remapframe" "pal + + if(newalt!=alt) + { + print f"="newalt >> optionfile + close(optionfile) + } + + if(system(npbcmd)!=0) + break + + last=f + print "ONG "f" "((alt==newalt)?"":""newalt) + + if(system(remapcmd)==0) + { + if(system(npbremapcmd)!=0) + break + } + + if(foundpal){ + getline namef < passfile + getline passf < passfile + close (passfile) + if(namef!="" &&passf !="") + { + print namef > tempfile2 + print passf > tempfile2 + print "" > tempfile2 + print argtab["story"]"#"f"#1" > tempfile2 + print "su" > tempfile2 + print substr(timetext,1,4)"-"substr(timetext,5,2)"-"substr(timetext,7,2)" "substr(timetext,9,2) > tempfile2 + print "Original filename" > tempfile2 + print "[code]"pal".png[/code]"> tempfile2 + print "" > tempfile2 + close (tempfile2) + + system(addhashcmd) + } + } + + # must be changed! + # if (post!="") + # { + # system(ongcmd) + # system("sleep 5") + # system(ongremapcmd) + # } + + alt=newalt + + print nextstate" "f > statefile + print newalt > statefile + close(statefile) + + ++f + } +} diff --git a/ong-mscha.awk b/ong-mscha.awk new file mode 100644 index 0000000..7895f64 --- /dev/null +++ b/ong-mscha.awk @@ -0,0 +1,129 @@ +#// ong-mscha.awk +#// The bot to ketchup frames from the mshcaviewer +#// 14.09.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="" + framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + temppath="/eizm/tmp/aftertime/" + + # timecmd="date +\"%H\"" + + cp="/bin/cp" + mawk="/usr/bin/mawk" + wget="/usr/bin/wget" + bot4awk="/eizm/pro/aftertime/bot4.awk" +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + eq=index($0, "=") + + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) +} +END{ + + if (file=="") + exit 1 + + if(argtab["ongoing"]!="2") + exit 1 + + # timecmd | getline thistime + # close(timecmd) + + statefile= datapath argtab["story"]"/ongstate" + getline temp < statefile + getline alt < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + + f=last+1 + + nextstate="2" + + tempfile = temppath "ongmscha-"argtab["story"] + optionfile = datapath argtab["story"]"/settings" + framedir = "aftertime/"argtab["story"]"/" + + while(1) + { + newalt="" + frameurl= sprintf(argtab["otherviewerframe"],f) + viewerurl= sprintf(argtab["otherviewerurl"],f) + + frame= framepath framedir sprintf(argtab["frame"],f) + npbframe= framepath framedir sprintf(argtab["npbframe"],f) + + getfcmd= wget " -q -O " frame " "frameurl + getvcmd= wget " -q -O " tempfile " "viewerurl + npbcmd= sprintf("/eizm/pro/ong1/npb %s %s q",frame,npbframe) + ongcmd = mawk" -f " bot4awk" -v story="argtab["story"]" -v frame="last" "optionfile + + # print getfcmd + if(system(getfcmd)!=0) + break + + + # print getvcmd + if(system(getvcmd)!=0) + break + + while ((getline temp < tempfile) > 0) + { + if(index(temp,frameurl)!=0) + { + newalt=substr(temp,index(temp,"title=\"")+7) + newalt=substr(newalt,1,index(newalt,"\"")-1) + break + } + } + close(tempfile) + # if(newalt=="") + # break + + + if(newalt!=alt) + { + print f"="newalt >> optionfile + close(optionfile) + } + + # print npbcmd + if(system(npbcmd)!=0) + break + + last=f + print "ONG "f" "((alt==newalt)?"":""newalt) + + if (post!="") + system(ongcmd) + + alt=newalt + + print nextstate" "f > statefile + print newalt > statefile + close(statefile) + + ++f + } +} diff --git a/ong.awk b/ong.awk new file mode 100644 index 0000000..9da5f24 --- /dev/null +++ b/ong.awk @@ -0,0 +1,422 @@ +#// ong.awk +#// The bot to ONG new frames to the viewer. +#// 05.01.2019 +#// +#// Copyright (C) 2015, 2018-2019 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + + +BEGIN{ + FS="" + framepath="/eizm/www/time/" + datapath="/eizm/data/aftertime/" + + # timecmd="date +\"%H\"" + timecmd2="date -u +\"%Y-%m-%d %H:%M:%S\"" + timecmd3="date -u +\"%s\"" + + cp="/bin/cp" + mawk="/usr/bin/mawk" + bot4awk="/eizm/pro/aftertime/bot4.awk" + chmod="/bin/chmod" + + timecmd2 | getline thistime2 + close(timecmd2) + timecmd3 | getline thistime3 + close(timecmd3) + # timecmd | getline thistime + # close(timecmd) + + thistime3 -= thistime3%3600 +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + eq=index($0, "=") + + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) +} +END{ + + print "" + print thistime2" "argtab ["story"] + + if (file=="") + { + print "No data." + exit 1 + } + + if(int(argtab["ongoing"])!=1) + { + print "story is not onged from here." + exit 1 + } + + # # replace with actual better conditions + # if(int(thistime) % int(argtab["ongtime"]) != 0) + # { + # print "Not ongtime yet." + # exit 1 + # } + + framedir = "aftertime/"argtab["story"]"/" + + temp="" + statefile= datapath argtab["story"]"/ongstate" + getline temp < statefile + close(statefile) + + split(temp, temptab, " ") + state=int(temptab[1]) + last=int(temptab[2]) + nextong=int(temptab[3]) + ongfailcount=int(temptab[4]) + + # temp="" + # updatefile= datapath argtab["story"]"/update" + # getline temp < updatefile + # close(updatefile) + + if (state == 1 || state ==2) + { + updatefail="" + temp="" + updatefile= datapath argtab["story"]"/update" + + while((getline temp < updatefile)>0) + { + if (temp !~ /^([0-9]+)|(c)$/) + continue + + i = int(temp) + if(temp=="c") + { + print "Update CFRT." + if (argtab["cfrt"]=="") + { + print "There is no cfrt frame." + continue + } + inframe= datapath argtab["story"]"/"argtab["cfrt"] + + frame= framepath framedir argtab["cfrt"] + + cpcmd = cp" "inframe" "frame + chmodcmd = chmod" +r "frame + } + else + { + print "Update frame "i"." + if ((i < int(argtab["first"]))||(i > last)) + { + print (i" not onged yet.") + continue + } + inframe= datapath argtab["story"]"/"sprintf(argtab["inframe"],i) + + frame= framepath framedir sprintf(argtab["frame"],i) + npbframe= framepath framedir sprintf(argtab["npbframe"],i) + + npbcmd= sprintf("/eizm/pro/ong1/npb %s %s q",inframe,npbframe) + cpcmd = cp" "inframe" "frame + chmodcmd = chmod" +r "frame + } + if((argtab["npbframe"]!="") && (temp!="c")) + { + if(system(npbcmd)!=0) + { + print i" NewpixbOTTification failed." + updatefail=1 + continue + } + } + if(system(cpcmd)!=0) + { + print "Upload failed." + updatefail=1 + continue + } + if(system(chmodcmd)!=0) + { + print "Chmod failed." + updatefail=1 + continue + } + print "Updated." + } + close(updatefile) + if (!updatefail) + { + print "" > updatefile + close(updatefile) + } + } + + # # temp ="remove this line!" + # if (temp != "") + # { + # print "Update requested." + # updatefail="" + + # if(state>2 || state <1) + # { + # print "Can't update in this state" + # } + # else + # { + # for(i=int(argtab["first"]);i<=last;++i) + # { + # if (i==int(argtab["first"]) && argtab["cfrt"]!="") + # { + # inframe= datapath argtab["story"]"/"argtab["cfrt"] + # frame= framepath framedir argtab["cfrt"] + # cpcmd = cp" "inframe" "frame + # chmodcmd = chmod" +r "frame + + # # print cpcmd + # if(system(cpcmd)!=0) + # { + # print "CFRT upload failed." + # updatefail=1 + # break + # } + # # print chmodcmd + # if(system(chmodcmd)!=0) + # { + # print "CFRT chmod failed." + # updatefail=1 + # break + # } + # print "CFRT updated." + # } + + # inframe= datapath argtab["story"]"/"sprintf(argtab["inframe"],i) + + # frame= framepath framedir sprintf(argtab["frame"],i) + # npbframe= framepath framedir sprintf(argtab["npbframe"],i) + + # npbcmd= sprintf("/eizm/pro/ong1/npb %s %s q",inframe,npbframe) + # cpcmd = cp" "inframe" "frame + # chmodcmd = chmod" +r "frame + # if(argtab["npbframe"]!="") + # { + # # print npbcmd + # if(system(npbcmd)!=0) + # { + # print i" NewpixbOTTification failed." + # updatefail=1 + # break + # } + # } + # # print cpcmd + # if(system(cpcmd)!=0) + # { + # print i" upload failed." + # updatefail=1 + # break + # } + # # print chmodcmd + # if(system(chmodcmd)!=0) + # { + # print i" chmod failed." + # updatefail=1 + # break + # } + # print i" updated." + # } + # if (!updatefail) + # { + # print "" > updatefile + # close(updatefile) + # } + # } + # } + + firstong="" + if (state==4) { + print "Time to start onging." + firstong=1 + nextong=0 + } + else if(state<1 || state>2) + { + print "Onging not active." + exit 1 + } + else if(thistime3 statefile + close(statefile) + print "Nobody saw frame "last" yet. Wait until "nextong"." + exit 1 + } + + if(thistime3 statefile + close(statefile) + + if((argtab["finalreplaceframe"]!="") && (argtab["finalreplacetime"]!="")) + { + if(((thistime3 - nextong) >= int(argtab["finalreplacetime"])*3600) && (ongfailcount>=int(argtab["finalreplacetime"]))) + { + print "Time to stop trying." + print "ONG final replacement frame." + inframe= datapath argtab["story"]"/"argtab["finalreplaceframe"] + nextstate=3 + } + else + exit 1 + } + else + exit 1 + } + + + frame= framepath framedir sprintf(argtab["frame"],f) + npbframe= framepath framedir sprintf(argtab["npbframe"],f) + # nextong = thistime3 + int(argtab["ongtime"])*3600 + nextong = getnextongtime() + + npbcmd= sprintf("/eizm/pro/ong1/npb %s %s q",inframe,npbframe) + cpcmd = cp" "inframe" "frame + ongcmd = mawk" -f " bot4awk" -v story="argtab["story"]" -v frame="last" "datapath argtab["story"]"/settings" + chmodcmd = chmod" +r "frame + + ### replace this with actual onging!!! + # system("/eizm/pro/ong1/bot4") + + + timefile= datapath argtab["story"]"/ongtime" + print sprintf("%04u ",f)thistime2 >> timefile + close(timefile) + + if(argtab["npbframe"]!="") + { + if(system(npbcmd)!=0) + { + print "NewpixbOTTification failed." + exit 1 + } + } + + if(system(cpcmd)!=0) + { + print "Frame upload failed." + exit 1 + } + + if(system(chmodcmd)!=0) + { + print "Frame chmod failed." + exit 1 + } + + print sprintf("%u %u %u 0",nextstate,f,nextong) > statefile + close(statefile) + + print sprintf("ONGed. Next ong %u.",nextong) + + # add condition here. + # Ok, done. + + if (!firstong) + { + ongbotfile= datapath argtab["story"] "/" ((argtab["ongbot"]!="")?argtab["ongbot"]:"ongbot") + if (system("[ -f " ongbotfile " ]")==0) + system(ongcmd) + } +} + +function getnextongtime( schedulefile,temp,i) +{ + schedulefile= datapath argtab["story"]"/schedule" + + while((getline temp < schedulefile)>0) + { + if (temp !~ /^[0-9]+$/) + continue + + i = int(temp) + # print i + + if(i>thistime3) + { + close(schedulefile) + print "ok" + return i + } + } + close(schedulefile) + return thistime3 + int(argtab["ongtime"])*3600 +} \ No newline at end of file diff --git a/pleaseong.c b/pleaseong.c new file mode 100644 index 0000000..eb81ac0 --- /dev/null +++ b/pleaseong.c @@ -0,0 +1,70 @@ +// pleaseong.c (1190.bicyclesonthemoon.info/aftertime/pleaseongthis) +// Ask the bot to post the frame +// 16.09.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#define STORYDEF_PRINTF "/eizm/data/aftertime/%s/settings" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_BOT4 "/eizm/pro/aftertime/bot4.awk" + +#include +#include +#include +#include +#include +#include + +s_cgi *cgi; + +int main (int argc, char *argv[]) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char *story; + char *e; + char arg1[256]; + char arg2[256]; + char storydef[256]; + + cgi=cgiInit(); + + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + + story=cgiGetValue(cgi,"story"); + e=cgiGetValue(cgi,"e"); + + snprintf(arg1,256,"story=%s",story!=NULL ? story : ""); + snprintf(arg2,256,"enhance=%s",e!=NULL ? e : ""); + + + sprintf(storydef,STORYDEF_PRINTF,story!=NULL ? story : ""); + + printf("Content-type: text\n\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_BOT4,"-v",arg1,"-v",arg2,"-v","please=1",storydef,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + return 0; +} diff --git a/post.awk b/post.awk new file mode 100644 index 0000000..6a99b04 --- /dev/null +++ b/post.awk @@ -0,0 +1,304 @@ +#// post.awk +#// The tool to post to the OTT +#// 08.04.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" + fora="http://forums.xkcd.com" + useragent="\"bothasar_p (http://1190.bicyclesonthemoon.info/aftertime; time after Time post bot)\"" + timecmd="date -u +\"%d %b %Y, %k:%M UTC\"" + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i); + ch2hex[ch]=hex + hex2ch[hex]=ch + } +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(entitydecode(user)!=urldecode(argtab["username"])) + edit="" + + if(system("wget -q -t 3 --connect-timeout=60 --save-cookies=" cookiefile " -U " useragent " -O " tempfile " " fora "/ucp.php?mode=login")) + { + print "Pre-login fail." + exit 1 + } + while((getline cookie < cookiefile)>0) + { + if(cookie ~ /_sid/) + { + split(cookie,arr,"_sid[ \t]*") + SID=arr[2] + } + } + close(cookiefile) + print "username=" argtab["username"] "&password=" argtab["password"] "&sid=" SID "&login=Login" > postfile + close(postfile) + if(system("wget -q -t 3 --connect-timeout=60 --save-cookies=" cookiefile " --post-file=" postfile " -U " useragent " -O " tempfile " \"" fora "/ucp.php?mode=login\"")) + { + print "Login fail." + exit 1 + } + + while((getline temp < tempfile)>0) + { + if (temp ~ /
0) + { + if (tolower(line) ~ /

information/) + { + print "Unexpected h2: information\n" + getline line < tempfile + print line + exit 1 + } + + while (line!="") + { + i=match(line, //) + if(i!=0) + { + tag=substr(line,1,i) + line=substr(line,i+1) + } + else #oh no tag doesn't end on this line - whatever, I don't care. + { + tag=line + line="" + } + + + if(tag ~ /^postfile + if("&addbbcode20" in argtab) + printf ("&addbbcode20=%s",argtab["addbbcode20"])>>postfile + if(edit!="") + printf ("&message=%s",argtab["old_message"] "%0A%5Bsize%3D110%5D%5Bb%5D" argtab["subject"] "%5B%2Fb%5D%5B%2Fsize%5D%0A%5Bsize%3D80%5D" urlencode(posttime) "%5B%2Fsize%5D%0A" argtab["message"])>>postfile + else + printf ("&message=%s",argtab["message"])>>postfile + printf ("&post=%s","Submit")>>postfile + if("disable_bbcode" in argtab) + printf ("&disable_bbcode=%s",argtab["disable_bbcode"])>>postfile + if("disable_smilies" in argtab) + printf ("&disable_smilies=%s",argtab["disable_smilies"])>>postfile + if("disable_magic_url" in argtab) + printf ("&disable_magic_url=%s",argtab["disable_magic_url"])>>postfile + if("attach_sig" in argtab) + printf ("&attach_sig=%s",argtab["attach_sig"])>>postfile + if("notify" in argtab) + printf ("¬ify=%s",argtab["notify"])>>postfile + printf ("&creation_time=%s",argtab["creation_time"])>>postfile + printf ("&form_token=%s",argtab["form_token"])>>postfile + for(i=0; i>postfile + + close(postfile) + + system("sleep 1") + if(system("wget -q -t 3 --connect-timeout=60 --load-cookies=" cookiefile " --save-cookies=" cookiefile " --post-file=" postfile " -U " useragent " -O " tempfile " \"" fora "/posting.php?mode="((edit!="")?"edit&f=7&p="edit:"reply&f=7&t=101043")"\"")) + { + print "Submit fail." + exit 1 + } + + while((getline temp < tempfile)>0) + { + if (temp ~ /

information/) + { + success=1 + } + } + close(tempfile) + + if (success!=1) + { + print "Sent back to preview!" + exit INDELIVERABLE + } + + while((getline cookie < cookiefile)>0) + { + if(cookie ~ /_sid/) + { + split(cookie,arr,"_sid[ \t]*") + SID=arr[2] + break + } + } + close(cookiefile) + if(system("wget -q -t 3 --connect-timeout=60 -U " useragent " -O " tempfile " \"" fora "/ucp.php?mode=logout&sid=" SID"\"")) + { + print "Logout fail." + } + + +} +function urlencode(name,all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +} +function entitydecode(ht ,i,j,un,num) +# quot, amp, lt, gt, nbsp, and decimal numbered. +{ + while ((i=match(ht, /&((#[0-9]+)|([a-zA-Z]+));/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + j=index(ht, ";") + + if(ht~/^&#/) + { + num=int(substr(ht, 3, j-3)) + un=un sprintf("%c",num) + } + else + { + num=tolower(substr(ht, 2, j-2)) + if(num == "quot") + un=un "\"" + else if(num == "amp") + un=un "&" + else if(num == "lt") + un=un "<" + else if(num == "gt") + un=un ">" + else if(num == "nbsp") + un=un "\xA0" + else + un = un ht + } + ht=substr(ht, j+1) + } + un=un ht + return un +} +function urldecode(ht ,i,j,un,num) +# quot, amp, lt, gt, nbsp, and decimal numbered. +{ + while ((i=match(ht, /%[0-9a-fA-F][0-9a-fA-F]/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + num=toupper(substr(ht, 2, 2)) + un=un hex2ch[num] + ht=substr(ht, 4) + } + un=un ht + return un +} diff --git a/post.cpp b/post.cpp new file mode 100644 index 0000000..f5cc701 --- /dev/null +++ b/post.cpp @@ -0,0 +1,652 @@ +// post.cpp (1190.bicyclesonthemoon.info/aftertime/post) +// The post edit interface +// 05.04.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include +#include + +#define RM_PATH "/bin/rm" +#define MV_PATH "/bin/mv" +#define CAT_PATH "/bin/cat" +#define MAWK_PATH "/usr/bin/mawk" + +#define POST_PATH "/eizm/www/time/aftertime/post.htm" +#define INFO_PATH "/eizm/www/time/aftertime/info.htm" +#define MPOST_PATH "/eizm/mem/aftertime/mpost/" + +#define AWK_PREVIEW "/eizm/pro/aftertime/preview.awk" +#define AWK_VIEW "/eizm/pro/aftertime/view.awk" +#define TEMP_PATH "/eizm/tmp/aftertime/preview." +#define AWK_B2H "/eizm/pro/aftertime/bb2html.awk" +#define AWK_VERIFY "/eizm/pro/aftertime/verify.awk" + +s_cgi *cgi; +pid_t sub; +int r; +FILE *tempfile; +FILE *postfile; +bool tf=false; +bool pf=false; +char temppath[256]=""; +char temppath2[256]=""; +char postpath[512]=""; + +char zero='\0'; +char *username = &zero; +char *password = &zero; +char *message = &zero; +char *y = &zero; +char *m = &zero; +char *d = &zero; +char *h = &zero; +char *disable_bbcode = &zero; +char *disable_smilies = &zero; +char *disable_magic_url = &zero; +char *Preview = &zero; +char *post =&zero; +char *addquote =&zero; +char *edit =&zero; +char *forceID =&zero; +char *silent =&zero; +char *story =&zero; +char *frame =&zero; +char *round =&zero; +char *subject =&zero; +char *key =&zero; +char *forcekey =&zero; +char *ID =&zero; + +char wrong[256]; + +void submit(); +void preview (const char *text); +void writeArg(FILE *file,const char *name,const char *value, bool all); +void writeArg(FILE *file,const char *name,const char *value, const char *insert); +void writeArgH(FILE *file,const char *name,const char *value, unsigned char br); +void writeArgH(FILE *file,const char *value); +// void writeArgBR(FILE *file,const char *name, const char *value); +void end(int m); +void id(char *timenumber,char *story, unsigned short frame, unsigned char round); + +void end(int m) +{ + if(tf) + fclose(tempfile); + if(pf) + fclose(postfile); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath2,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(pf) + { + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + exit(m); +} + +void writeArg(FILE *file,const char *name,const char *value, bool all=false) +{ + unsigned short length, i, v; + fprintf(file,"%s=",name); + for(i=0, length=strlen(value);i='0'&&value[i]<='9')||(value[i]>='A'&&value[i]<='Z')||(value[i]>='a'&&value[i]<='z') + ||value[i]=='.'||value[i]=='~'||value[i]=='-'||value[i]=='_')&&(!all)) + fputc(v,file); + else + fprintf(file,"%%%02X",v); + } + fputc('\n',file); +} + +void writeArg(FILE *file,const char *name,const char *value, const char *insert) +{ + unsigned short length, i, v; + fprintf(file,"%s=",name); + for(i=0, length=strlen(value);i='0'&&value[i]<='9')||(value[i]>='A'&&value[i]<='Z')||(value[i]>='a'&&value[i]<='z') + ||value[i]=='.'||value[i]=='~'||value[i]=='-'||value[i]=='_') + fputc(v,file); + else + fprintf(file,"%%%02X",v); + } + for(i=0, length=strlen(insert);i='0'&&insert[i]<='9')||(insert[i]>='A'&&insert[i]<='Z')||(insert[i]>='a'&&insert[i]<='z') + ||insert[i]=='.'||insert[i]=='~'||insert[i]=='-'||insert[i]=='_') + fputc(v,file); + else + fprintf(file,"%%%02X",v); + } + fputc('\n',file); +} + +void writeArgH(FILE *file,const char *name,const char *value, unsigned char br=0) +{ + unsigned short length, i, v; + fprintf(file,"%s=",name); + for(i=0, length=strlen(value);i"); + case '\r': + if(br&0x01) + break; + case '=': + case '<': + case '>': + case '&': + fprintf(file,"&#%hu;",v); + break; + default: + fputc(v,file); + } + } + fputc('\n',file); +} + +void writeArgH(FILE *file,const char *value) +{ + unsigned short length, i, v; + for(i=0, length=strlen(value);i': + case ' ': + case '\r': + case '\n': + case '=': + fprintf(file,"&#%hu;",v); + break; + default: + fputc(v,file); + } + } +} + +// void writeArgBR(FILE *file,const char *name, const char *value) +// { + // unsigned short length, i, v; + // fprintf(file,"%s=",name); + // for(i=0, length=strlen(value);i0x0fff)||(tm>0x0f)||(td>0x1f)||(th>0x1f)) + preview("Time too long"); + // I accept invalid time as long as it's not too long + + id(timenumber,story,tf,tr); + sprintf(postpath,"%s%s",MPOST_PATH,timenumber); + if(forceID[0]!='\0') + sprintf(forcepath,"%s%s",MPOST_PATH,forceID); + + tempfile=fopen(temppath,"wt"); + if(tempfile==NULL) + preview("Couldn't create file."); + tf=true; + writeArgH(tempfile,"timenumber",timenumber); + writeArgH(tempfile,"key",newkey); + writeArgH(tempfile,"username_h",username); + writeArgH(tempfile,"subject_h",subject); + writeArgH(tempfile,"story",story); + if(frame[0]!='\0')writeArgH(tempfile,"frame",ff); + if(round[0]!='\0')writeArgH(tempfile,"round",rr); + writeArgH(tempfile,"BBHTML",message,1); + writeArgH(tempfile,"BB",message,3); + if(h[0]!='\0')writeArgH(tempfile,"h",hh); + if(d[0]!='\0')writeArgH(tempfile,"d",dd); + if(m[0]!='\0')writeArgH(tempfile,"m",mm); + if(y[0]!='\0')writeArgH(tempfile,"y",yy); + if(disable_bbcode[0]!='\0') + writeArg(tempfile,"disable_bbcode",disable_bbcode); + if(disable_smilies[0]!='\0') + writeArg(tempfile,"disable_smilies",disable_smilies); + if(disable_magic_url[0]!='\0') + writeArg(tempfile,"disable_magic_url",disable_magic_url); + if(ID[0]!='\0') + writeArgH(tempfile,"ID",ID); + fclose(tempfile); + tf=false; + + sprintf(arg1,"outfile=%s",temppath); + sprintf(arg2,"tempfile=%s",temppath2); + fflush(stdout); + sub=fork(); + if(sub==0) + { + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_B2H,"-v",arg1,"-v",arg2,temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + sprintf(arg1,"name=%s",username); + sprintf(arg2,"pass=%s",password); + sprintf(arg3,"story=%s",story); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VERIFY,"-v",arg1,"-v",arg2,"-v",arg3,"-v","reversed=1",(forceID[0]!='\0')?forcepath:postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(!r) + preview("Can't submit this post. Not yours or wrong password?"); + + if(forceID[0]!='\0') + { + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,forcepath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + + sub=fork(); + if(sub==0) + { + r=execl(MV_PATH,MV_PATH,temppath,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + // preview("Couldn't add post to queue."); + preview(postpath); + + printf("Content-type: text/html\n\n"); + sprintf(arg1,"info=

This message has been sent successfully.

View your submitted message

Return to the list

",timenumber,newkey); + // printf("Content-type: text/html\n\n"); + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VIEW,"-v",arg1,INFO_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("%s",arg1); + end(0); +} +void preview (const char *text) +{ + char arg1[256]; + char arg2[256]; + char yy[8]; + char ff[8]; + char rr[4]; + char mm[4]; + char dd[4]; + char hh[4]; + unsigned short ty, tf; + unsigned char tm,td,th, tr; + if(y[0]!='\0'){sscanf(y,"%hu",&ty); ty&=0x0fff;sprintf(yy,"%04hu",ty); } + if(m[0]!='\0'){sscanf(m,"%hhu",&tm);tm&= 0x0f;sprintf(mm,"%02hhu",tm);} + if(d[0]!='\0'){sscanf(d,"%hhu",&td);td&= 0x1f;sprintf(dd,"%02hhu",td);} + if(h[0]!='\0'){sscanf(h,"%hhu",&th);th&= 0x1f;sprintf(hh,"%02hhu",th);} + if(frame[0]!='\0'){sscanf(frame,"%hu",&tf);sprintf(ff,"%04hu",tf);} + if(round[0]!='\0'){sscanf(round,"%hhu",&tr);sprintf(rr,"%02hhu",tr);} + + tempfile=fopen(temppath,"wt"); + if(tempfile==NULL) + end(1); + tf=true; + + writeArgH(tempfile,"message",message); + writeArgH(tempfile,"subject",(subject[0]!='\0')?subject:"Did you notice …"); + writeArgH(tempfile,"wrong",text); + writeArgH(tempfile,"username",username); + writeArgH(tempfile,"message",message); + writeArgH(tempfile,"BB",message,3); + if(h[0]!='\0')writeArgH(tempfile,"h",hh); + if(d[0]!='\0')writeArgH(tempfile,"d",dd); + if(m[0]!='\0')writeArgH(tempfile,"m",mm); + if(y[0]!='\0')writeArgH(tempfile,"y",yy); + writeArgH(tempfile,"story",story); + if(frame[0]!='\0')writeArgH(tempfile,"frame",ff); + writeArgH(tempfile,"round",(round[0]!='\0')?rr:"1"); + writeArgH(tempfile,"disable_bbcode",disable_bbcode); + writeArgH(tempfile,"disable_smilies",disable_smilies); + writeArgH(tempfile,"disable_magic_url",disable_magic_url); + writeArgH(tempfile,"addquote",addquote); + writeArgH(tempfile,"edit",edit); + writeArgH(tempfile,"forceID",forceID); + writeArgH(tempfile,"key",forcekey); + writeArgH(tempfile,"ID",ID); + fclose(tempfile); + tf=false; + + printf("Content-type: text/html\n\n"); + + sprintf(arg1,"outfile=%s",temppath); + sprintf(arg2,"tempfile=%s",temppath2); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_B2H,"-v",arg1,"-v",arg2,temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + // printf("Content-type: text/html\n\n"); + sprintf(arg1,"argfile=%s",temppath); + sprintf(arg2,"key=%s",key[0]?key:"???"); + fflush(stdout); + sub=fork(); + if(sub==0) + { + // setvbuf(stdout, NULL, _IONBF, 0); + // dup2(fileno(stdout),fileno(stderr)); + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_PREVIEW,"-v",arg1,"-v",arg2,POST_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("

Ch*rpin* M*stard

"); + end(0); +} + +int main() +{ + bool missing=false; + + char *arg; + + cgi=cgiInit(); + srand (time (NULL) + getpid()); + + + sprintf(temppath,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + sprintf(temppath2,"%s_%lu",TEMP_PATH,(unsigned long)getpid()); + + arg=cgiGetValue(cgi,"password"); + if(arg!=NULL) + password=arg; + else + { + missing=true; + strcpy(wrong,"Password is missing."); + } + + arg=cgiGetValue(cgi,"username"); + if(arg!=NULL) + username=arg; + else + { + missing=true; + strcpy(wrong,"Name is missing."); + } + + arg=cgiGetValue(cgi,"story"); + if(arg!=NULL) + { + story=arg; + if(!strcmp(story,"t1i")); + else if(!strcmp(story,"bftf")); + else if(!strcmp(story,"zodiac")); + else + { + missing=true; + strcpy(wrong,"Wrong story name."); + } + } + else + { + missing=true; + strcpy(wrong,"Story name is missing."); + } + + arg=cgiGetValue(cgi,"frame"); + if(arg!=NULL) + frame=arg; + else + { + missing=true; + strcpy(wrong,"Frame number is missing."); + } + + arg=cgiGetValue(cgi,"round"); + if(arg!=NULL) + round=arg; + else + { + missing=true; + strcpy(wrong,"Round number was missing. Replaced with default value."); + } + arg=cgiGetValue(cgi,"subject"); + if(arg!=NULL) + subject=arg; + else + { + missing=true; + strcpy(wrong,"Subject was missing. Replaced with default value."); + } + + arg=cgiGetValue(cgi,"message"); + if(arg!=NULL) + message=arg; + else + { + missing=true; + strcpy(wrong,"Post is empty."); + } + + + arg=cgiGetValue(cgi,"y"); + if(arg!=NULL) + y=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"m"); + if(arg!=NULL) + m=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"d"); + if(arg!=NULL) + d=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"h"); + if(arg!=NULL) + h=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"disable_bbcode"); + if(arg!=NULL) + disable_bbcode=arg; + + arg=cgiGetValue(cgi,"disable_smilies"); + if(arg!=NULL) + disable_smilies=arg; + + arg=cgiGetValue(cgi,"disable_magic_url"); + if(arg!=NULL) + disable_magic_url=arg; + + arg=cgiGetValue(cgi,"Preview"); + if(arg!=NULL) + Preview=arg; + + arg=cgiGetValue(cgi,"post"); + if(arg!=NULL) + post=arg; + + arg=cgiGetValue(cgi,"q"); + if(arg!=NULL) + addquote=arg; + + arg=cgiGetValue(cgi,"e"); + if(arg!=NULL) + edit=arg; + + arg=cgiGetValue(cgi,"forceID"); + if(arg!=NULL) + forceID=arg; + + arg=cgiGetValue(cgi,"key"); + if(arg!=NULL) + key=arg; + + arg=cgiGetValue(cgi,"forcekey"); + if(arg!=NULL) + forcekey=arg; + + arg=cgiGetValue(cgi,"ID"); + if(arg!=NULL) + ID=arg; + + if(strcmp(post,"Submit")==0) + { + if(missing) + preview(wrong); + else + submit(); + } + else + preview(""); + + return 0; + +} + +void id(char *timenumber,char *story, unsigned short frame, unsigned char round) +{ + sprintf(timenumber,"%s-%04hu-%02hhu",story,frame,round); +} \ No newline at end of file diff --git a/posted.awk b/posted.awk new file mode 100644 index 0000000..fb6d6f3 --- /dev/null +++ b/posted.awk @@ -0,0 +1,65 @@ +#// posted.awk +#// Display one entry in the post list +#// 31.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + + +BEGIN{ + FS="=" + passpath="/eizm/mem/aftertime/pass/" + # for(i=0;i<256;++i) + # { + # ch=sprintf("%c",i) + # hex=sprintf("%02X",i); + # ch2hex[ch]=hex + # } +}; +{ + gsub(/[\r\n]/,"",$0) + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + passfile = passpath argtab["story"] + getline namef < passfile + getline passf < passfile + close (passfile) + gsub(/[\r\n]/,"",namef) + gsub(/[\r\n]/,"",passf) + + if(namef!=name||passf!=pass) + exit 1; + if (r2==0) + class="plw" + else + class="plv" + print ""argtab["timenumber"]""argtab["y"]"-"argtab["m"]"-"argtab["d"]" "argtab["h"]":00"argtab["subject_h"]"view quote edit remove"(argtab["ID"]!=""?" OTT":"")"" +} +# function urlencode(name,all, len,iii,escaped,ch) +# { + # len=length(name) + # escaped="" + # for(iii=1;iii<=len;++iii) + # { + # ch=substr(name,iii,1); + # if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + # escaped = escaped ch + # else + # escaped = escaped "%" ch2hex[ch] + # } + # return escaped +# } \ No newline at end of file diff --git a/posted.c b/posted.c new file mode 100644 index 0000000..c7218bf --- /dev/null +++ b/posted.c @@ -0,0 +1,141 @@ +// posted.c (1190.bicyclesonthemoon.info/aftertime/list) +// Display the post list +// 29.03.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include + +#define TEMP_PATH "/eizm/tmp/aftertime/posted." +#define POST_PATH "/eizm/mem/aftertime/mpost/" +#define LS_PATH "/bin/ls" +#define RM_PATH "/bin/rm" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_POSTED "/eizm/pro/aftertime/posted.awk" + +s_cgi *cgi; +pid_t sub; +int r; + +int main(int argc, char **argv) +{ + char temppath[256]=""; + char line[512]; + char filename[512]; + char postpath[512]; + char argp1[256]; + char argp2[256]; + FILE *tempfile; + // FILE *postfile; + unsigned char i; + // unsigned char sent; + char zero='\0'; + char *value; + char *username; + char *password; + // dup2(fileno(stdout),fileno(stderr)); + cgi=cgiInit(); + + username=((value=cgiGetValue(cgi,"username"))?value:&zero); + password=((value=cgiGetValue(cgi,"password"))?value:&zero); + // sent=cgiGetValue(cgi,"sent"); + sprintf(argp1,"name=%s",username); + sprintf(argp2,"pass=%s",password); + + + sprintf(temppath,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + + printf("Content-type: text/html\n\n"); + printf("\n"); + printf("\n"); + printf("time after Time • Bicycles on the Moon\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\"1190.bicyclesonthemoon.info\"\n"); + printf("

time after Time

\n"); + // printf("(some explanation)
\n"); + printf("
\n"); + printf("\n",username); + printf("\n"); + printf("
Username:
Password:
\n"); + printf("Write a post

\n"); + printf("
\n"); + printf("


\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + if(freopen(temppath,"wt",stdout)==NULL) + exit(255); + r=execl(LS_PATH,LS_PATH,"-1","--color=never",POST_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("No messages.
\n"); + else + { + printf("\n"); + printf("\n"); + + if(password!=NULL) + { + tempfile=fopen(temppath,"rt"); + if(tempfile!=NULL) + { + for(i=0; fgets(line,511,tempfile)!=NULL; ++i) + { + sscanf(line,"%s",filename); + sprintf(postpath,"%s%s",POST_PATH,filename); + + fflush(stdout); + sub=fork(); + if(!sub) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_POSTED,"-v",i&0x1?"r2=1":"r2=0","-v",argp1,"-v",argp2,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + --i; + + } + fclose(tempfile); + } + } + printf("
Waiting
IDpost timesubjectaction

\n"); + + } + + printf("
1190.bicyclesonthemoon.info\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + return 0; +} diff --git a/preview.awk b/preview.awk new file mode 100644 index 0000000..20b4a61 --- /dev/null +++ b/preview.awk @@ -0,0 +1,198 @@ +#// preview.awk +#// Preview a post in the post edit interface +#// 31.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + postpath="/eizm/mem/aftertime/mpost/" + + HTML="
Preview: %s
%s

" + wrong="
%s
\n" + postid=" frame: round: \n" + subject="\n" + username="\n" + time="Y: M: D: H: \n" + + ottid="\n" + message="\n" + back="back to the list\n" + + disable_bbcode=" Disable BBcode
\n" + disable_smilies=" Disable smilies
\n" + disable_magic_url=" Do not automatically parse URLs
\n" + + + forceID="\n" + forcekey="\n" + + addquote="" + + # print "" + close(argfile) + if(argtab["edit"] ~ /^[a-zA-Z0-9]+\-[0-9]+\-[0-9]+$/) + { + argtab["forceID"]=argtab["edit"] ### reused from where it made more sense + argfile= postpath argtab["forceID"] + + while((getline argline < argfile)>0) + { + gsub(/[\r\n]/,"",argline) + eq=index(argline,"=") + if(argline ~ /^key=/) + { + if(substr(argline,eq+1)!=key) + { + argtab["wrong"]="Invalid key." + break; + } + argtab["key"]=substr(argline,eq+1) + } + else if(argline ~ /^((username)|(subject))_h=/) + argtab[substr(argline,1,eq-3)]=substr(argline,eq+1) + else if(argline ~ /^BBHTML=/) + { + argtab["message"]=substr(argline,eq+1) + gsub(/
/,"\n",argtab["message"]) + } + else if(argline ~ /^((BB)|(username)|(subject)|(message)|(HTML)|(debug))=/) + {} + else + argtab[substr(argline,1,eq-1)]=substr(argline,eq+1) + } + close(argfile) + } + else if(argtab["addquote"] ~ /^[a-zA-Z0-9]+\-[0-9]+\-[0-9]+$/) + { + argfile= postpath argtab["addquote"] + while((getline argline < argfile)>0) + { + gsub(/[\r\n]/,"",argline) + eq=index(argline,"=") + if(argline ~ /^key=/) + { + if(substr(argline,eq+1)!=key) + { + argtab["wrong"]="Invalid key." + break; + } + } + else if(argline ~ /^BBHTML=/) + { + addquotehtml=substr(argline,eq+1) + gsub(/
/,"\n",addquotehtml) + } + if(argline ~ /^username_h=/) + addquotename=substr(argline,eq+1) + if(argline ~ /^subject_h/) + { + addquotesub=substr(argline,eq+1) + if(addquotesub ~ /^Re:/) + argtab["subject"]=addquotesub + else + argtab["subject"]="Re: "addquotesub + } + if(argline ~ /^y=/) + { + argtab["y"]=substr(argline,eq+1) + } + if(argline ~ /^d=/) + { + argtab["d"]=substr(argline,eq+1) + } + if(argline ~ /^m=/) + { + argtab["m"]=substr(argline,eq+1) + } + if(argline ~ /^h=/) + { + argtab["h"]=substr(argline,eq+1) + } + } + close(argfile) + if(addquotehtml!="") + addquote="[quote=""addquotename""]"addquotehtml"[/quote]" + } +}; +{ + if ($0 ~ /^###HTML/) + { + if((argtab["HTML"]!="")&&(argtab["wrong"]=="")) + printf(HTML,(argtab["story"]!=""?argtab["story"]:"???")"-"(argtab["frame"]!=""?argtab["frame"]:"???")"-"(argtab["round"]!=""?argtab["round"]:"???")" • "argtab["subject"],argtab["HTML"]) + } + else if ($0 ~ /^###wrong/) + { + if(argtab["wrong"]!="") + printf(wrong,argtab["wrong"]) + } + else if ($0 ~ /^###subject/) + printf(subject,argtab["subject"]) + else if ($0 ~ /^###username/) + printf(username,argtab["username"]) + else if ($0 ~ /^###message/) + printf(message,argtab["message"],addquote) + else if ($0 ~ /^###time/) + printf(time,argtab["y"],argtab["m"],argtab["d"],argtab["h"]) + else if ($0 ~ /^###postid/) + printf(postid,argtab["story"],argtab["frame"],argtab["round"]) + else if ($0 ~ /^###future/) + { + # + } + else if ($0 ~ /^###forceID/) + { + if(argtab["forceID"]!="") + printf(forceID,argtab["forceID"]) + } + else if ($0 ~ /^###ottid/) + printf(ottid,argtab["ID"]) + else if ($0 ~ /^###forcekey/) + { + if(argtab["key"]!="") + printf(forcekey,argtab["key"]) + } + else if ($0 ~ /^###img/) + { + print img + } + else if ($0 ~ /^###back/) + { + printf(back,"") + } + else if ($0 ~ /^###debug/) + { + gsub(/###nl;/,"\n",argtab["debug"]) + gsub(/-/," - ",argtab["debug"]) + print "" + } + else if ($0 ~ /^###disable_bbcode/) + printf(disable_bbcode,(argtab["disable_bbcode"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###disable_smilies/) + printf(disable_smilies,(argtab["disable_smilies"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###disable_magic_url/) + printf(disable_magic_url,(argtab["disable_magic_url"]=="on")?"checked=\"checked\"":"") + + else + print $0 +}; diff --git a/remapt-1.c b/remapt-1.c new file mode 100644 index 0000000..08b7c15 --- /dev/null +++ b/remapt-1.c @@ -0,0 +1,131 @@ +// remapt-1.c +// The tool to enhance t-1 frames by remapping the palette +// 16.09.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +// Requires Dev Image Library (libdevil) (http://openil.sourceforge.net/) +// on Pentium III libdevil must be recompiled with +// --disable-ssl2 --disable-ssl3 +// (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954) + +//#include +#include +#include +#include "IL/il.h" + +int mustard(const char *t,int m,int e); +int main(int argc, char *argv[]); +unsigned char b642d(char b64); + +ILuint inpix; +unsigned char q =0; + +int main(int argc, char *argv[]) +{ + ILubyte *pal; + unsigned short i; + + if (argc<4) + return mustard("remapt-1 inpix outpix palette [q]",0,1); + else if(argc > 4) + q=1; + + if(strlen(argv[3])<340) + return mustard("Palette too short.",0,1); + + ilInit(); + + ilEnable(IL_ORIGIN_SET); + ilEnable(IL_FILE_OVERWRITE); + + ilGenImages(1,&inpix); + ilBindImage(inpix); + + if(!ilLoadImage(argv[1])) + return mustard("inpix load fail.",1,1); + + if(ilGetInteger(IL_IMAGE_FORMAT)!=IL_COLOUR_INDEX) + return mustard("inpix not indexed.",1,1); + + + ilConvertPal(IL_PAL_RGB24); + if(ilGetInteger(IL_PALETTE_NUM_COLS)!=255) + return mustard("Wrong number of colors.",1,1); + + pal=ilGetPalette(); + + if(strlen(argv[3])<340) + return mustard("Palette too short.",1,1); + + + for(i=0; i<340; ++i) + argv[3][i]=b642d(argv[3][i]); + for(i=0; i<85; ++i) + { + pal[3*i ]=( argv[3][4*i ] <<2)| + ((argv[3][4*i+1]&0x30) >>4); + + pal[3*i+1]=((argv[3][4*i+1]&0x0f) <<4)| + ((argv[3][4*i+2]&0x3c) >>2); + + pal[3*i+2]=((argv[3][4*i+2]&0x03) <<6)| + ( argv[3][4*i+3] ); + + pal[3*i+255]=pal[3*i ]; + pal[3*i+256]=pal[3*i+1]; + pal[3*i+257]=pal[3*i+2]; + + pal[3*i+510]=pal[3*i ]; + pal[3*i+511]=pal[3*i+1]; + pal[3*i+512]=pal[3*i+2]; + } + if(!ilSave(IL_PNG,argv[2])) + return mustard("outpix save fail",1,1); + + return mustard("remapped",1,0); +} + +unsigned char b642d(char b64) +{ + if(b64 >='A' && b64 <='Z') + return b64-'A'; + else if(b64 >= 'a' && b64 <= 'z') + return b64-'a'+26; + else if(b64 >= '0' && b64 <= '9') + return b64-'0'+52; + else if(b64=='+') + return 62; + else if(b64=='-') + return 63; + else + return 0; +} + +int mustard(const char *t, int m,int e) +{ + if(!q) + puts(t); + switch (m) + { + case 1: + ilDeleteImages(1,&inpix); + case 0: + default: + return e; + } +} \ No newline at end of file diff --git a/remove.c b/remove.c new file mode 100644 index 0000000..694be8d --- /dev/null +++ b/remove.c @@ -0,0 +1,108 @@ +// remove.c (1190.bicyclesonthemoon.info/aftertime/remove) +// remove a post +// 28.03.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include +#include +#include +#include +#include + +#define POST_PATH "/eizm/mem/aftertime/mpost/" +#define RMOV_PATH "/eizm/mem/aftertime/mpost/rm/" +#define MV_PATH "/bin/mv" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_VERIFY "/eizm/pro/aftertime/verify.awk" + +int main(int argc, char **argv) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char zero='\0'; + char *rmov = &zero; + char *arg; + char *username; + char *password; + char inpath[256]; + char outpath[256]; + char argp1[256]; + char argp2[256]; + + cgi=cgiInit(); + + + rmov=((arg=cgiGetValue(cgi,"r"))?arg:&zero); + + username=((arg=cgiGetValue(cgi,"username"))?arg:&zero); + password=((arg=cgiGetValue(cgi,"password"))?arg:&zero); + if(username[0]=='\0'||password[0]=='\0') + { + arg=cgiGetValue(cgi,"r"); + if(arg!=NULL) + rmov=arg; + printf("Content-type: text/html\n\n"); + printf("\n"); + printf("\n"); + printf("time after Time • Bicycles on the Moon\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\"1190.bicyclesonthemoon.info\"\n"); + printf("

time after Time

\n"); + printf("
\n"); + printf("Remove post %s?\n",rmov); + printf("\n",username); + printf("\n"); + printf("
Username:
Password:
\n",rmov); + printf("
1190.bicyclesonthemoon.info\n"); + return 0; + } + + sprintf(inpath,"%s%s",POST_PATH,rmov); + + sprintf(argp1,"name=%s",username); + sprintf(argp2,"pass=%s",password); + + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VERIFY,"-v",argp1,"-v",argp2,inpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + cgiRedirect("/aftertime/list"); + return(0); + } + sprintf(outpath,"%s%s",RMOV_PATH,rmov); + + sub=fork(); + if(sub==0) + { + r=execl(MV_PATH,MV_PATH,inpath,outpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + cgiRedirect("/aftertime/list"); + return 0; +} \ No newline at end of file diff --git a/undertext_bb2html.awk b/undertext_bb2html.awk new file mode 100644 index 0000000..2dddb69 --- /dev/null +++ b/undertext_bb2html.awk @@ -0,0 +1,657 @@ +# // undertext_bb2html.awk +# // convert undertext bbcode to html +# // 5.06.2019 +# // +# // Copyright (C) 2015, 2019 Balthasar Szczepański +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU Affero 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 Affero General Public License for more details. +# // +# // You should have received a copy of the GNU Affero General Public License +# // along with this program. If not, see . + +BEGIN{ + FS="" + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i) + hexl=sprintf("%02x",i) + dec=sprintf("%u",i) + ch2hex[ch]=hex + ch2hexl[ch]=hexl + ch2dec[ch]=dec + } + argtabsize=0 + undertext="" +} +{ + file=1 + gsub(/[\r\n]/, "", $0) + + if ($0 == "" && !undertext) + { + undertext=1 + if (!("text" in argtab)) + { + argtabind[argtabsize]="text" + ++argtabsize + } + argtab["text"]="" + } + else if (undertext) + { + argtab["text"] = argtab["text"] $0 "\n" + } + else + { + eq=index($0, "=") + + if (!(substr($0, 1, eq-1) in argtab)) + { + argtabind[argtabsize]=substr($0, 1, eq-1) + ++argtabsize + } + argtab[substr($0, 1, eq-1)]=substr($0, eq+1) + } +} +END{ + if (file=="") + exit 1 + + if (argtab["text"]!="") + { + if (!("HTML" in argtab)) + { + argtabind[argtabsize]="HTML" + ++argtabsize + } + argtab["HTML"]=bb2html(argtab["text"]) + + } + + for (i=0; i\"\]]*)|(\"[^\"<>]*\")))?\]/) + #"#\"" + if (tag==0) + { + debug = debug "\ntext: " text + bbtree[ind(count,depth)]=text + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + text="" + break; + } + tagstart=RSTART + taglength=RLENGTH + if(tagstart>1) + { + elm=substr(text,1,tagstart-1) + debug = debug "\ntext: " elm + bbtree[ind(count,depth)]=elm + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + } + tag=substr(text,tagstart,taglength) + text=substr(text,tagstart+taglength) + debug = debug "\ntag: " tag + if(tag!~/^\[\//) + { + tagv=index(tag,"=") + if(tagv<2) + { + tagname=substr(tag,2,length(tag)-2) + tagvalue="" + } + else + { + tagname=substr(tag,2,tagv-2) + tagvalue=substr(tag,tagv+1,length(tag)-tagv-1) + } + if(tagname !~ /^((quote)|b|i|u|(code)|(img)|(url)|(size)|(color)|(center)|(right)|(sub)|(sup)|(s)|(spoiler)|(list)|(br)|(\*))$/) + { + debug = debug "\nunknown tag" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||bbtree[indt(count,depth)".t"] == "img"||(bbtree[indt(count,depth)".t"] == "spoiler" && tagname=="spoiler")||(bbtree[indt(count,depth)".t"] == "size" && tagname=="size")) + { + debug = debug "\nthis tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname=="*") + { + if(bbtree[indt(count,depth)".t"]==tagname) + { + debug = debug "\nimplied tag: [/"tagname"]" + debug = debug "\nmatched" + bbtree[ind(count,depth)]="[/"tagname"]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + else if(bbtree[indt(count,depth)".t"]!="list") + { + debug = debug "\nthis tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + } + debug = debug "\nname: " tagname " value: " tagvalue + bbtree[ind(count,depth)]=tagname" "tagvalue + bbtree[ind(count,depth)".k"]="s" + bbtree[indt(count,depth)".n"]=count[depth] + ++depth + count[depth]=1 + bbtree[indt(count,depth)]=tag + bbtree[indt(count,depth)".n"]=0 + bbtree[indt(count,depth)".t"]=tagname + bbtree[indt(count,depth)".v"]=tagvalue + + if(tagname=="br") #or other single tags in the future + { + debug = debug "\nmatched" + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + } + else + { + if(depth<=0) + { + debug = debug "\n""unmatched" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + tagname=substr(tag,3,length(tag)-3) + if(tagname=="list"&&bbtree[indt(count,depth)".t"]=="*") + { + debug = debug "\nimplied tag: [/*]" + debug = debug "\nmatched" + bbtree[ind(count,depth)]="[/*]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]="*" + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + debug = debug "\nname: " tagname + matchname=bbtree[indt(count,depth)".t"] + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||(bbtree[indt(count,depth)".t"] == "img" && tagname != "img")) + { + debug = debug "\nthis tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname!=matchname) + { + debug = debug "\nmismatched: " matchname + # bbtree[ind(count,depth)]=tag + # bbtree[indt(count,depth)".n"]=count[depth] + # ++count[depth] + # continue + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".t"]=bbtree[indt(count,depth)".t"] + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + count[depth]="" + --depth + ++count[depth] + continue + } + debug = debug "\nmatched" + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + } + if(depth>0) + debug = debug "\nunclosed tags: " depth + + debug = debug "\n\n""generate HTML:" + depth=0 + count[0]=0 + while(count[0]<=bbtree["0.n"]&&depth>=0) + { + if(count[depth]==0) + { + tag=bbtree[indt(count,depth)] + tagname=bbtree[indt(count,depth)".t"] + tagvalue=bbtree[indt(count,depth)".v"] + debug = debug "\nname: "tagname" value: "tagvalue" elements: "bbtree[indt(count,depth)".n"] + if(tagname == "post") + { + } + else if(bbtree[indt(count,depth)".m"]=="") + { + debug = debug "\nunmatched" + html = html htmlescape(tag) + } + else if(tagname == "quote") + { + if (tagvalue=="") + { + html = html "
" + } + else + { + if(tagvalue !~ /^\".*\"$/) + #"#\"" + tagvalue="You forgot about the quote marks, "htmlescape(tagvalue) + else + tagvalue=bb2html(substr(tagvalue,2,length(tagvalue)-2)) + html = html "
"tagvalue" wrote:
" + } + } + else if (tagname == "b") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "i") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "u") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html htmlescape(tag) + debug = debug "\nnot a tag, actually" + } + else + { + html=html"
Code: Select all
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + } + else if (tagname == "img") + html=html"" + } + else if (tagname == "size") + { + if (tagvalue==""||(tagvalue !~ /^[0-9]+$/)||(tagvalue+0)>200) + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname == "color") + { + if (tagvalue==""||tagvalue !~ /^#[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]$/) #for some reason /^([0-9A-F]{6})$/ doesn't work. + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname ~ /^((center)|(right))$/) + { + html=html"
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="s") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sub") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sup") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="spoiler") + { + html=html"
Spoiler:
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="list") + { + if(tagvalue=="") + html=html"
    " + else + { + if (tagvalue=="1") + tagvalue="decimal" + else if (tagvalue=="i") + tagvalue="lower-roman" + else if (tagvalue=="I") + tagvalue="upper-roman" + else if (tagvalue=="a") + tagvalue="lower-alpha" + else if (tagvalue=="A") + tagvalue="upper-alpha" + else + { + html=html"This tag should have a correct value. " + tagvalue="decimal" + } + html=html"
      " + } + } + else if (tagname=="*") + { + html=html"
    1. " + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "br") + { + html = html"
      " + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else + { + debug = debug "\nunknown tag" + html = html htmlescape(tag) + } + ++count[depth] + } + else if(bbtree[ind(count,depth)".k"]=="s") + { + debug = debug "\nentering tag:" + ++depth + count[depth]=0 + } + else if(bbtree[ind(count,depth)".k"]=="e") + { + debug = debug "\nleaving tag:" + tag=bbtree[ind(count,depth)] + tagname=bbtree[ind(count,depth)".t"] + tagvalue=bbtree[ind(count,depth)".v"] + debug = debug "\nname: "tagname" value: "tagvalue + if (tagname == "post") + { + } + else if(bbtree[ind(count,depth)".m"]=="") + { + debug = debug "\nunmatched" + html = html htmlescape(tag) + } + else if(tagname == "quote") + html = html "
" + else if (tagname ~/^(b|i|u|(size)|(color))$/) + html = html"" + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html htmlescape(tag) + debug = debug "\nnot a tag, actually" + } + else + html = html"" + } + else if (tagname == "img") + { + html = html"\" alt=\"Image\" />" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if(tagname=="url") + html=html"" + else if (tagname ~ /^((center)|(right))$/) + html=html"
" + else if (tagname =="s") + html=html"" + else if (tagname =="sub") + html=html"" + else if (tagname =="sup") + html=html"" + else if (tagname=="spoiler") + html=html"

" + else if (tagname=="list") + { + if (tagvalue=="") + html=html"" + else + html=html"" + } + else if (tagname=="*") + html=html"" + else if (tagname == "br") # + { + # + } + else + { + debug = debug "\nunknown tag" + html = html htmlescape(tag) + } + count[depth]="" + --depth + ++count[depth] + } + else if(count[depth]>bbtree[indt(count,depth)".n"]) + { + debug = debug "\nrun out of elements in this tag; leaving" + count[depth]="" + --depth + ++count[depth] + } + else + { + tag=bbtree[ind(count,depth)] + debug = debug "\ntext: "tag + + tag=htmlescape(tag,"","br") + + if(bbtree[indt(count,depth)".t"] == "code") + { + gsub(/ /,"\\ ",tag) + gsub(/\t/,"\\ \\ ",tag) + } + else{ + gsub(/ /,"\\  ",tag) + gsub(/ /," \\ ",tag) + # gsub(/
/,"
\\ ",tag) + } + + + if(nourl==""&& bbtree[indt(count,depth)".t"] !~ /^((code)|(img)|(url))$/) + gsub(/https?:\/\/[^\n\r\t<> ]+/,"&",tag) + # if(nosmil=="" && bbtree[indt(count,depth)".t"] !~ /^((code)|(img))$/) + # { + # gsub(/(^|[\n\r\t ]):D($|[\n\r\t ])/," \":D\" ",tag) + # gsub(/(^|[\n\r\t ]):\)($|[\n\r\t ])/," \":)\" ",tag) + # gsub(/(^|[\n\r\t ]):\(($|[\n\r\t ])/," \":(\" ",tag) + # gsub(/(^|[\n\r\t ]):o($|[\n\r\t ])/," \":o\" ",tag) + # gsub(/(^|[\n\r\t ]):shock:($|[\n\r\t ])/," \":shock:\" ",tag) + # gsub(/(^|[\n\r\t ]):\?($|[\n\r\t ])/," \":?\" ",tag) + # gsub(/(^|[\n\r\t ])8-\)($|[\n\r\t ])/," \"8-)\" ",tag) + # gsub(/(^|[\n\r\t ]):lol:($|[\n\r\t ])/," \":lol:\" ",tag) + # gsub(/(^|[\n\r\t ]):x($|[\n\r\t ])/," \":x\" ",tag) + # gsub(/(^|[\n\r\t ]):P($|[\n\r\t ])/," \":P\" ",tag) + # gsub(/(^|[\n\r\t ]):oops:($|[\n\r\t ])/," \":oops:\" ",tag) + # gsub(/(^|[\n\r\t ]):cry:($|[\n\r\t ])/," \":cry:\" ",tag) + # gsub(/(^|[\n\r\t ]):evil:($|[\n\r\t ])/," \":evil:\" ",tag) + # gsub(/(^|[\n\r\t ]):twisted:($|[\n\r\t ])/," \":twisted:\" ",tag) + # gsub(/(^|[\n\r\t ]):roll:($|[\n\r\t ])/," \":roll:\" ",tag) + # gsub(/(^|[\n\r\t ]):wink:($|[\n\r\t ])/," \":wink:\" ",tag) + # gsub(/(^|[\n\r\t ]);\)($|[\n\r\t ])/," \":wink:\" ",tag) + # gsub(/(^|[\n\r\t ]):!:($|[\n\r\t ])/," \":!:\" ",tag) + # gsub(/(^|[\n\r\t ]):\?:($|[\n\r\t ])/," \":?:\" ",tag) + # gsub(/(^|[\n\r\t ]):idea:($|[\n\r\t ])/," \":idea:\" ",tag) + # gsub(/(^|[\n\r\t ]):arrow:($|[\n\r\t ])/," \":arrow:\" ",tag) + # gsub(/(^|[\n\r\t ]):\|($|[\n\r\t ])/," \":|\" ",tag) + # gsub(/(^|[\n\r\t ]):mrgreen:($|[\n\r\t ])/," \":mrgreen:\" ",tag) + # } + + html = html tag + ++count[depth] + } + } + debug = debug "\ndone\n" + return html +} + +function ind(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii<=depth;++ii) + { + if(ii!=0) + iindex = iindex "." + iindex = iindex count[ii] + } + # debug = debug "\n" iindex + return iindex +} +function indt(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "\n" iindex + return iindex +} +function indtu(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "\n" iindex + return iindex +} +function htmlescape(name,less,br, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if(ch == "\n") + escaped = escaped ((br!="")?"
":"&#"ch2dec[ch]";") + else if(ch =="\r") + escaped = escaped ((br!="")?"":"&#"ch2dec[ch]";") + else if(ch == "\"" && less=="") + escaped = escaped "&#"ch2dec[ch]";" + else if(ch ~ /[=<>&]/) + escaped = escaped "&#"ch2dec[ch]";" + else + escaped = escaped ch + } + return escaped +} +function hexencode(name, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1) + escaped = escaped ch2hex[ch] + } + return escaped +} + diff --git a/upload.awk b/upload.awk new file mode 100644 index 0000000..2bd7312 --- /dev/null +++ b/upload.awk @@ -0,0 +1,699 @@ +#// upload.awk +#// The post upload interface +#// 21.12.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + postpath="/eizm/mem/aftertime/mpost/" + passpath="/eizm/mem/aftertime/pass/" + rmpath="/eizm/mem/aftertime/rm/" + bb2html="/eizm/pro/aftertime/bb2html.awk" + automome="/eizm/pro/ong1/mome.pl" + memepath="/eizm/mem/ong1/mome.txt" + timecmd="date -u +\"%s\"" + + timecmd | getline thistime + close(timecmd) + + srand(int(thistime) + int( PROCINFO["pid"])) + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i) + hexl=sprintf("%02x",i) + dec=sprintf("%u",i) + ch2hex[ch]=hex + hex2ch[hex]=ch + ch2hexl[ch]=hexl + ch2dec[ch]=dec + } + + # year=substr(timetext,1,4) + # month=substr(timetext,5,2) + # day=substr(timetext,7,2) + # hour=substr(timetext,9,2) + + # yyy=year+0 + # mmm=month+0 + # ddd=day+0 + # hhh=hour+0 + + ln=0 +} +{ + gsub(/[\r\n]/,"",$0) + if (FNR==1) + { + name=$0 + # print "username: "name + next + } + if (FNR==2) + { + pass=$0 + gsub(/./,"*", $0) + # print "password: "$0 + next + } + + if($0=="") + { + if(ln!=0) + { + post() + ln=0 + nobb="" + nosmil="" + nourl="" + quot="" + rmov="" + lst="" + h="" + d="" + m="" + y="" + subject="" + content="" + options="" + story="" + frame="" + round="" + idtab[1]="" + idtab[2]="" + idtab[3]="" + } + next + } + + ++ln + if(ln==1) + { + if($0 ~ /#/) + split($0, idtab, "#") + else + split($0, idtab, "-") + story=idtab[1] + frame=int(idtab[2]) + round=int(idtab[3]) + } + else if(ln==2) + { + options=tolower($0) + if(options ~ /b/) + nobb=1 + if(options ~ /s/) + nosmil=1 + if(options ~ /u/) + nourl=1 + if(options ~ /r/) + rmov=1 + if(options ~ /q/) + quot=1 + if(options ~ /l/) + lst=1 + } + else if(ln==3) + { + y=substr($0,1,4) + m=substr($0,6,2) + d=substr($0,9,2) + h=substr($0,12,2) + } + + else if(ln==4) + { + subject=$0 + } + else + { + if(ln!=5) + content=content "\n" $0 + else + content=$0 + } + +} +END{ + if(ln!=0) + post() +} +function remove( postid,postfile,rmfile,passfile,temp,f,tn,eq,tv,namef,passf) +{ + postid=sprintf("%s-%04u-%02u",story,frame,round) + postfile=postpath postid + rmfile=rmpath postid + passfile=passpath story + printf("%s",postid" ") + + getline namef < passfile + getline passf < passfile + close (passfile) + gsub(/[\r\n]/,"",namef) + gsub(/[\r\n]/,"",passf) + + if(name!=namef) + { + print "Can't remove. Wrong username." + return + } + if(pass!=password) + { + print "Can't remove. Wrong password." + return + } + + if(system("mv -f "postfile" "rmfile)==0) + { + print "removed." + return + } + print "not removed." +} + +function quote( postid,postfile,passfile,temp,f,opt,cont,ongt,subj,eq,tn,tv,id,namef,passf,yy,mm,dd,hh) +{ + postid=sprintf("%s-%04u-%02u",story,frame,round) + postfile=postpath postid + passfile=passpath story + + getline namef < passfile + getline passf < passfile + close (passfile) + gsub(/[\r\n]/,"",namef) + gsub(/[\r\n]/,"",passf) + + if((name!=namef)||(pass!=passf)) + { + print "Can't quote." + return + } + + while((getline temp < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + + if(tn=="BB") + cont=unhtml(tv) + else if(tn=="brtext") + ongt=tv + else if(tn=="y") + yy=tv + else if(tn=="m") + mm=tv + else if(tn=="d") + dd=tv + else if(tn=="h") + hh=tv + else if(tn=="subject_h") + subj=unhtml(tv) + else if(tn=="ID") + id=tv + else if(tn=="disable_bbcode") + { + if(tv=="on") + opt=opt"B" + } + else if(tn=="disable_smilies") + { + if(tv=="on") + opt=opt"S" + } + else if(tn=="disable_magic_url") + { + if(tv=="on") + opt=opt"U" + } + } + if(f!="") + { + close(postfile) + if (opt=="") + opt="_" + print postid" subject "subj + print postid" options "opt + print postid" time "sprintf("%04u-%02u-%02u %02u:00",yy,mm,dd,hh) + print postid" content "((ongt!="")?ongt:cont) + if(id!="") + print postid" ID "id + return + } + + else + print postid " can't quote." #I shouldn't tell why +} + +function list( cmd,id,postfile,passfile,temp,mt,f,eq,tn,tv,namef,passf,yy,mm,dd,hh) +{ + + passfile = passpath story + + getline namef < passfile + getline passf < passfile + close (passfile) + gsub(/[\r\n]/,"",namef) + gsub(/[\r\n]/,"",passf) + + if((name!=namef)||(pass!=passf)) + return + + cmd="/bin/ls -1 --color=never "postpath + while ((cmd | getline id)>0) + { + f="" + mt="^"story"-" + if(id !~ mt) + continue + postfile = postpath id + + while((getline temp < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="y") + yy=tv + else if(tn=="m") + mm=tv + else if(tn=="d") + dd=tv + else if(tn=="h") + hh=tv + + } + if(f!="") + { + close(postfile) + print id" time "sprintf("%04u-%02u-%02u %02u:00",yy,mm,dd,hh) + } + } + close (cmd) +} + +function post( postid,replaceid,postfile,passfile,replacefile,temp,i,eq,tn,tv,namef,passf,key,id) +{ + if(lst!="") + return list() + if(quot!="") + return quote() + if(rmov!="") + return remove() + postid=sprintf("%s-%04u-%02u",story,frame,round) + printf("%s",postid" ") + + postfile=postpath postid + passfile = passpath story + + + if(options=="") + { + print "No options defined." + return + } + + if (name=="") + { + print "Username missing." + return + } + if (pass=="") + { + print "Password missing." + return + } + if (story=="") + { + print "Story name missing." + return + } + if(story !~ /^(t1i|bftf|t-1)$/) + { + print "Unknown story." + return + } + if (frame=="") + { + print "Frame number missing." + return + } + if (round=="") + { + print "Round number missing." + return + } + if (subject=="") + { + print "Subject missing." + return + } + if (content=="") + { + print "Post is empty." + return + } + + yy=y+0 + mm=m+0 + dd=d+0 + hh=h+0 + + getline namef < passfile + getline passf < passfile + close (passfile) + gsub(/[\r\n]/,"",namef) + gsub(/[\r\n]/,"",passf) + + if(name!=namef) + { + print "Wrong username." + return + } + if(pass!=passf) + { + print "Wrong password." + return + } + + split("", ongtable, ":") + while((getline temp < postfile)>0) + { + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + + if(tn ~ /^[ou]ngd?-[0-9]+$/) + { + ongtable[tn]=brunescape(tv) + } + else if(tn == "key") + key=tv + else if(tn == "ID") + id=tv + + } + close(postfile) + + printf("")>postfile + + print "timenumber="htmlescape(postid) >> postfile + print "key="(key==""?newkey():key) >> postfile + print "username_h="htmlescape(name) >> postfile + print "subject_h="htmlescape(subject) >> postfile + print "story="story >> postfile + print "frame="sprintf("%04u",frame) >> postfile + print "round="sprintf("%02u",round) >> postfile + + print "h="htmlescape(h) >> postfile + print "d="htmlescape(d) >> postfile + print "m="htmlescape(m) >> postfile + print "y="htmlescape(y) >> postfile + + if(nobb!="") + print "disable_bbcode=on" >> postfile + if(nosmil!="") + print "disable_smilies=on" >> postfile + if(nourl!="") + print "disable_magic_url=on" >> postfile + + + + print "brtext="brescape(content) >> postfile + + gsub(/\[br\]/,"\n",content) + + for(i=0; content~/\[ong\]/; ++i) + { + tn=sprintf("ong-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ong() + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ong\]/,subescape(ongtext),content) + } + for(i=0; content~/\[ung\]/; ++i) + { + tn=sprintf("ung-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ung() + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ung\]/,subescape(ongtext),content) + } + for(i=0; content~/\[ong=decree\]/; ++i) + { + tn=sprintf("ongd-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ong("decree") + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ong=decree\]/,subescape(ongtext),content) + } + for(i=0; content~/\[ung=decree\]/; ++i) + { + tn=sprintf("ungd-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ung("decree") + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ung=decree\]/,subescape(ongtext),content) + } + + # print "content:\n"content + print "BBHTML="htmlescape(content,"","br") >> postfile + print "BB="htmlescape(content,"less","br") >> postfile + print "message="urlencode(content ((silent=="")?(nobb==""?"[right][size=80]-- posted by SilentBot [img]http://forums.xkcd.com/download/file.php?id=47884[/img][/size][/right]":"\n\n-- posted by SilentBot"):"")) >> postfile + if(id!="") + print"ID="id >> postfile + + print "posted." + system ("mawk -f "bb2html" -v outfile=\""postfile"\" \""postfile"\"") + system ("wait 1") + close (postfile) +} + +function urlencode(name,all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +} +function hexencode(name, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1) + escaped = escaped ch2hex[ch] + } + return escaped +} +function subescape(subtext) +{ + gsub(/&/,"\\\\\\&",subtext) + return subtext +} + +function htmlescape(name,less,br, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if(ch == "\n") + escaped = escaped ((br!="")?"
":"&#"ch2dec[ch]";") + else if(ch =="\r") + escaped = escaped ((br!="")?"":"&#"ch2dec[ch]";") + else if(ch ~ /[\" ]/ && less=="")#"#"\"" + escaped = escaped "&#"ch2dec[ch]";" + else if(ch ~ /[=<>&]/) + escaped = escaped "&#"ch2dec[ch]";" + else + escaped = escaped ch + } + return escaped +} + +function getmeme(decree ,meme,i) +{ + if(decree!="" && lastdecr=="") + { + close(tempfile) + system (automome" -lc 256 -n "memenumber" -d "memepath" -t \"[decr]\" > "tempfile) + } + else if(decree=="" && lastdecr!="") + { + close(tempfile) + system (automome" -lc 256 -n "memenumber" -d "memepath" > "tempfile) + } + for(i=0; ((getline meme < tempfile)<=0) && (i<3); ++i) + { + memenumber=memenumber*2 + close(tempfile) + if(decree!="") + system (automome" -lc 256 -n "memenumber" -d "memepath" -t \"[decr]\" > "tempfile) + else + system (automome" -lc 256 -n "memenumber" -d "memepath" > "tempfile) + } + lastdecr=decree + return meme +} + +function ong(decree, line) +{ + while((line=getmeme(decree))!="") + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#O-N-G#",line)>0) + return preparebb(line) + if(sub(/O+N+G+/,"#&#",line)>0) + return preparebb(line) + if(sub(/DON'T/,"D#ON'G#T",line)>0) + return preparebb(line) + if(sub(/[AEIOUY]NG/,"#ONG#",line)>0) + { + if($0!~/TH\[b\]ONG/) + return preparebb(line) + } + if(sub(/ON /,"#ONG# ",line)>0) + return preparebb(line) + if(sub(/O\.?$/,"#ONG# ",$0)>0) + return preparebb(line) + } + return "Ong" +} + +function ung(decree, line) +{ + while((line=getmeme(decree))!="") + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#U-N-G#",line)>0) + return preparebb(line) + if(sub(/U+N+G+/,"#&#",line)>0) + return preparebb(line) + if(sub(/[AEIOUY]NG/,"#UNG#",line)>0) + return preparebb(line) + if(sub(/UN /,"#UNG# ",line)>0) + return preparebb(line) + if(sub(/U\.?$/,"#UNG# ",$0)>0) + return preparebb(line) + } + return "Ung" +} +function preparebb(rh) +{ + if(nobb=="") + { + gsub(/\*\*/,"¤",rh) + gsub(/\*[^\*]+\*/,"±&±",rh) + gsub(/±\*/,"[i]",rh) + gsub(/\*±/,"[/i]",rh) + gsub(/¤/,"*",rh) + + gsub(/&&/,"¤",rh) + gsub(/&[^&]+&/,"±&±",rh) + gsub(/±&/,"[center][b]",rh) + gsub(/&±/,"[/b][/center]",rh) + gsub(/¤/,"\\&",rh) + + gsub(/__/,"¤",rh) + gsub(/_[^_]+_/,"±&±",rh) + gsub(/±_/,"[u]",rh) + gsub(/_±/,"[/u]",rh) + gsub(/¤/,"_",rh) + + gsub(/##/,"¤",rh) + gsub(/#[^#]+#/,"±&±",rh) + gsub(/±#/,"[b]",rh) + gsub(/#±/,"[/b]",rh) + gsub(/¤/,"#",rh) + + gsub(/\$\$/,"¤",rh) + gsub(/\$[^\$]+\$/,"±&±",rh) + gsub(/±\$/,"[size=80]",rh) + gsub(/\$±/,"[/size]",rh) + gsub(/¤/,"$",rh) + } + + return rh (nobb==""?" -- [url=http://1190.bicyclesonthemoon.info/ongtext?b=on][b]ong[/b]o[/url][url=http://mrob.com/time/automome/]mome[/url]":" -- ongomome") +} +function unhtml(ht ,i,j,un,num) +{ + gsub(//,"[br]",ht) + while ((i=match(ht, /&#[0-9]+;/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + j=index(ht, ";") + num=int(substr(ht, 3, j-3)) + un=un sprintf("%c",num) + ht=substr(ht, j+1) + } + un=un ht + return un +} +function brescape(text) #there will be more +{ + gsub(/\r/,"",text) + gsub(/\n/,"[br]",text) + return text +} +function brunescape(text) #there will be more +{ + gsub(/\[br\]/,"\n",text) + return text +} +function urldecode(ht ,i,j,un,num) +# quot, amp, lt, gt, nbsp, and decimal numbered. +{ + while ((i=match(ht, /%[0-9a-fA-F][0-9a-fA-F]/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + num=toupper(substr(ht, 2, 2)) + un=un hex2ch[num] + ht=substr(ht, 4) + } + un=un ht + return un +} +function newkey( key,i,rn) +{ + for(i=0; i<8; ++i) + { + rn=int(rand()*65536) + key = key sprintf("%04X",rn) + } + return key +} diff --git a/upload.c b/upload.c new file mode 100644 index 0000000..e4286a1 --- /dev/null +++ b/upload.c @@ -0,0 +1,98 @@ +// upload.c (1190.bicyclesonthemoon.info/aftertime/upload) +// The post upload interface +// 28.03.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include +#include +#include +#include +#include +#include + +#define RM_PATH "/bin/rm" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_UPLOAD "/eizm/pro/aftertime/upload.awk" +#define TEMP_PATH "/eizm/tmp/aftertime/upload." +#define RM_PATH "/bin/rm" + +s_cgi *cgi; +pid_t sub; +int r; + +int main(int argc, char **argv) +{ + char *temppath; + char **up; + time_t posttime; + struct tm *nowS; + char timetext[64]; + char timenumber[64]; + char temppath2[247]; + char temppath3[256]; + + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + + cgi=cgiInit(); + + sprintf(temppath2,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + sprintf(temppath3,"tempfile=%s",temppath2); + + printf("Content-type: text\n\n"); + up=cgiGetFiles(cgi); + if (up) + { + temppath=cgiGetFile(cgi,up[0])->tmpfile; + + posttime=time(NULL); + nowS=gmtime(&posttime); + + sprintf(timenumber,"timenumber=%lu",(unsigned long)posttime); + sprintf(timetext,"timetext=%04d%02d%02d%02d",nowS->tm_year+1900,nowS->tm_mon+1,nowS->tm_mday,nowS->tm_hour); + + // printf("%s\n%s\n%s\n",timenumber,timetext,temppath); + + sub=fork(); + if(!sub) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_UPLOAD,"-v",timetext,"-v",timenumber,"-v",temppath3,temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath2,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + return 0; + } + printf("File missing\n"); + return 0; +} diff --git a/verify.awk b/verify.awk new file mode 100644 index 0000000..a4ca33b --- /dev/null +++ b/verify.awk @@ -0,0 +1,77 @@ +#// verify.awk +#// Check if post belongs to user +#// 27.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + passpath="/eizm/mem/aftertime/pass/" + FS="=" + # for(i=0;i<256;++i) + # { + # ch=sprintf("%c",i) + # hex=sprintf("%02X",i); + # ch2hex[ch]=hex + # hex2ch[hex]=ch + # } + if(reversed!="") + { + ok=1 + fail=0 + } + else + { + ok=0 + fail=1 + } +} +{ + gsub(/[\r\n]/,"",$0) + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +} +END{ + if(story=="") + story=argtab["story"] + else if(story!=argtab["story"]) + exit fail + + passfile = passpath story + getline namef < passfile + getline passf < passfile + close (passfile) + gsub(/[\r\n]/,"",namef) + gsub(/[\r\n]/,"",passf) + + if(namef==name&&passf==pass) + exit ok + else + exit fail +} +# function urlencode(name,all, len,iii,escaped,ch) +# { + # len=length(name) + # escaped="" + # for(iii=1;iii<=len;++iii) + # { + # ch=substr(name,iii,1); + # if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + # escaped = escaped ch + # else + # escaped = escaped "%" ch2hex[ch] + # } + # return escaped +# } diff --git a/view.awk b/view.awk new file mode 100644 index 0000000..55d186d --- /dev/null +++ b/view.awk @@ -0,0 +1,59 @@ +#// view.awk +#// insert text +#// 27.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero 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 Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + + +###reusedfrommirror; + +{ + # if ($0 ~ /^###sig&/) + # { + # split ($0 ,arr,"&") + # system("cat " sig arr[2]) + # } + # else if ($0 ~ /^###inf&/) + # { + # split ($0 ,arr,"&") + # system("cat " otterinf arr[2]) + # } + # else if ($0 ~ /^###prev/) + # { + # print left + # } + # else if ($0 ~ /^###next/) + # { + # print right + # } + # else if ($0 ~ /^###links/) + # { + # system ("cat " links); + # } + # else + if ($0 ~ /^###info/) + { + print info; + } + else if ($0 ~ /^###title/) + { + print title; + } + else + { + print $0 + } +}; diff --git a/viewer.c b/viewer.c new file mode 100644 index 0000000..5309b5b --- /dev/null +++ b/viewer.c @@ -0,0 +1,115 @@ +// viewer.c (1190.bicyclesonthemoon.info/aftertime/viewer) +// The viewer +// 21.06.2018 +// +// Copyright (C) 2015-2016, 2018 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#define STORYDEF_PRINTF "/eizm/data/aftertime/%s/settings" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_VIEWER "/eizm/pro/aftertime/viewer.awk" + +#include +#include +#include +#include +#include +#include + +s_cgi *cgi; + +void escape(char *text); + +int main (int argc, char *argv[]) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char *story; + char *f; + char *bb; + char *enh; + char *notic; + char *replay; + + char arg1[256]; + char arg2[256]; + char arg3[256]; + char arg4[256]; + char arg5[256]; + char arg6[256]; + char storydef[256]; + + cgi=cgiInit(); + + //setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + + story=cgiGetValue(cgi,"story"); + if(story!=NULL) + escape(story); + f=cgiGetValue(cgi,"f"); + bb=cgiGetValue(cgi,"b"); + enh=cgiGetValue(cgi,"e"); + notic=cgiGetValue(cgi,"n"); + replay=cgiGetValue(cgi,"r"); + + snprintf(arg1,256,"story=%s",story!=NULL ? story : ""); + snprintf(arg2,256,"frame=%s",f!=NULL ? f : ""); + snprintf(arg3,256,"bbcode=%s",bb!=NULL ? bb : ""); + snprintf(arg4,256,"enhance=%s",enh!=NULL ? enh : ""); + snprintf(arg5,256,"notice=%s",notic!=NULL ? notic : ""); + snprintf(arg6,256,"replay=%s",replay!=NULL ? replay : ""); + + sprintf(storydef,STORYDEF_PRINTF,story!=NULL ? story : "time"); + + printf("Content-type: text/html\n\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VIEWER,"-v",arg1,"-v",arg2,"-v",arg3,"-v",arg4,"-v",arg5,"-v",arg6,storydef,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + sprintf(storydef,STORYDEF_PRINTF,"default"); + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VIEWER,"-v",arg1,"-v",arg2,"-v",arg3,"-v",arg4,"-v",arg5,"-v",arg5,storydef,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + + return 0; +} + +void escape(char *text){ + unsigned short i, len; + + len=strlen(text); + for (i=0;i + +time after Time • Bicycles on the Moon + + + + + + +1190.bicyclesonthemoon.info +

time after Time

+###info +1190.bicyclesonthemoon.info diff --git a/www/post.htm b/www/post.htm new file mode 100644 index 0000000..87c86af --- /dev/null +++ b/www/post.htm @@ -0,0 +1,169 @@ + + +time after Time • Bicycles on the Moon + + + + + + + +1190.bicyclesonthemoon.info +

time after Time

+
+###debug +###future + + + +###HTML +
+
Send a message
+###wrong +
+
+ +
Story: +###postid +
Subject: +###subject +
Username: +###username +
Password: + +
Time (gmt): +###time +
Action: + + +
+
+
+ + + + + + + + + + + + + + + + + + + + Font size:  + +
+###ottid + (optional post ID) +
+ +
+
Write here:
+###message +
Options:
+
+###disable_bbcode +###disable_smilies +###disable_magic_url +###forceID +###forcekey +
+
+###back +

1190.bicyclesonthemoon.info