From a1c7c0ab010f2e2da32bf73abc2067b268315c8a Mon Sep 17 00:00:00 2001 From: vinzv Date: Fri, 2 Sep 2016 11:34:29 +0200 Subject: [PATCH] Adding SensitiveContent Plugin for nsfw filtering --- plugins/SensitiveContent/LICENSE | 662 ++++++++++++++++++ plugins/SensitiveContent/README.md | 41 ++ .../SensitiveContentPlugin.php | 274 ++++++++ .../actions/sensitivecontentsettings.php | 51 ++ plugins/SensitiveContent/img/blocker.png | Bin 0 -> 32222 bytes .../SensitiveContent/js/sensitivecontent.js | 228 ++++++ 6 files changed, 1256 insertions(+) create mode 100644 plugins/SensitiveContent/LICENSE create mode 100644 plugins/SensitiveContent/README.md create mode 100644 plugins/SensitiveContent/SensitiveContentPlugin.php create mode 100644 plugins/SensitiveContent/actions/sensitivecontentsettings.php create mode 100644 plugins/SensitiveContent/img/blocker.png create mode 100644 plugins/SensitiveContent/js/sensitivecontent.js diff --git a/plugins/SensitiveContent/LICENSE b/plugins/SensitiveContent/LICENSE new file mode 100644 index 0000000000..a871fcfd0f --- /dev/null +++ b/plugins/SensitiveContent/LICENSE @@ -0,0 +1,662 @@ + 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/plugins/SensitiveContent/README.md b/plugins/SensitiveContent/README.md new file mode 100644 index 0000000000..9de210d381 --- /dev/null +++ b/plugins/SensitiveContent/README.md @@ -0,0 +1,41 @@ +# "Sensitive" Content Plugin for GNU Social + +## About + +WARNING: THIS IS ALPHA CODE, IT IS PRERELEASE AND SHOULD ONLY BE INSTALLED TO +HELP TEST OR YOU ARE WILLING TO TAKE RISKS. + +Create user option to allow a user to hide #NSFW-hashtagged notices behind a +blocker image until clicked. + +Works for both vanilla GNUSocial and with the Qvitter plugin. + +## Install + +- Move the project directory to ${GNU_SOCIAL}/plugins +- Add addPlugin('SensitiveContent'); to your config.php + +if you want to customize the blocker image, add a line to your config.php: + + $config['site']['sensitivecontent']['blockerimage'] = "/path/to/image.jpg"; + +## Usage + +Individual users must go to their Settings page. A new sidebar menu item "Sensitive Content" +will be available. User checks or unchecks the checkbox on this page, and presses save. + + +If you have GNU Social open in other browser tabs, refresh them. If you are using Qvitter, also +refresh, but because Qvitter caches notices on the client side, only new sensitive images will +be hidden, it will not apply to notices retroactively unless you clear your browser cache. + +## License + +GNU Affero License + +## Thanks + +Thanks in particular to Hannes and Qvitter because looking at his code helped me a lot. + +A tiny bit of content was taken from Qvitter to enhance Qvitter with this functionality. + diff --git a/plugins/SensitiveContent/SensitiveContentPlugin.php b/plugins/SensitiveContent/SensitiveContentPlugin.php new file mode 100644 index 0000000000..8eb7c4a6ef --- /dev/null +++ b/plugins/SensitiveContent/SensitiveContentPlugin.php @@ -0,0 +1,274 @@ + 'Sensitive Content', + 'version' => self::VERSION, + 'author' => 'MoonMan', + 'homepage' => 'https://gitgud.io/ShitposterClub/SensitiveContent/', + 'description' => + _m('Mark, hide/show sensitive notices like on Twitter.')); + return true; + } + + static function settings($setting) + { + $settings['blockerimage'] = Plugin::staticPath('SensitiveContent', '').'img/blocker.png'; + + $configphpsettings = common_config('site','sensitivecontent') ?: array(); + foreach($configphpsettings as $configphpsetting=>$value) { + $settings[$configphpsetting] = $value; + } + + if(isset($settings[$setting])) { + return $settings[$setting]; + } + else FALSE; + } + + function onNoticeSimpleStatusArray($notice, &$twitter_status, $scoped) + { + $twitter_status['tags'] = $notice->getTags(); + } + + function onTwitterUserArray($profile, &$twitter_user, $scoped) + { + if ($scoped instanceof Profile && $scoped->sameAs($profile)) { + $twitter_user['hide_sensitive'] = $this->getHideSensitive($scoped); + } + } + + public function onRouterInitialized(URLMapper $m) + { + $m->connect('settings/sensitivecontent', + array('action' => 'sensitivecontentsettings')); + } + + + function onEndAccountSettingsNav($action) + { + $action->menuItem(common_local_url('sensitivecontentsettings'), + _m('MENU', 'Sensitive Content'), + _m('Settings for display of sensitive content.')); + + return true; + } + + + public function onQvitterEndShowHeadElements(Action $action) + { + $blocker = static::settings('blockerimage'); + common_log( LOG_DEBUG, "SENSITIVECONTENT " . $blocker ); + + + $styles = <<style($styles); + } + + function onQvitterEndShowScripts(Action $action) + { + $action->script( Plugin::staticPath('SensitiveContent', '').'js/sensitivecontent.js' ); + } + + function onEndShowStyles(Action $action) + { + $blocker = static::settings('blockerimage'); + + $styles = << footer > .attachments > .inline-attachment > .attachment-wrapper > .sensitive-blocker { + display: none; +} + +html[data-hidesensitive='true'] .tagcontainer.data-tag-nsfw > footer > .attachments > .inline-attachment > .attachment-wrapper > .sensitive-blocker { +display: block; +width: 100%; +height: 100%; +position: absolute; +z-index: 100; +/*background-color: #d4baba;*/ +background-color: black; +background-image: url($blocker); +background-repeat: no-repeat; +background-position: center center; +background-size: contain; +transition: opacity 1s ease-in-out; +} + +html[data-hidesensitive='true'] .tagcontainer.data-tag-nsfw > footer > .attachments > .inline-attachment > .attachment-wrapper > .sensitive-blocker.reveal { + opacity: 0; +} + +EOB; + + $action->style($styles); + } + + function onStartShowAttachmentRepresentation($out, $file) + { + $profile = Profile::current(); + + if (!is_null($profile) && $profile instanceof Profile) + { + $hidesensitive = $this->getHideSensitive($profile); + } + else + { + $hidesensitive = false; + } + + + $classes = "sensitive-blocker"; //'sensitive-blocker'; + + $out->elementStart('div', array( + 'class'=>'attachment-wrapper', + 'style'=>'height: ' . $file->getThumbnail()->height . 'px; width: ' . $file->getThumbnail()->width . 'px;' + )); /*needs height of thumb*/ + $out->elementStart('div', array( + 'class'=>$classes, + 'onclick'=>'toggleSpoiler(event)', + 'style'=>'height: ' . $file->getThumbnail()->height . 'px; width: ' . $file->getThumbnail()->width . 'px;' + )); + $out->raw(' '); + $out->elementEnd('div'); + } + + function onEndShowAttachmentRepresentation($out, $file) + { + $out->elementEnd('div'); + } + + function onEndShowScripts(Action $action) + { + $profile = $action->getScoped(); + if (!is_null($profile) && $profile instanceof Profile) + { + $hidesensitive = $this->getHideSensitive($profile) ? "true" : "false"; + } + else + { + $hidesensitive = "false"; + } + + $inline = <<inlineScript($inline); + } + + function onEndOpenNoticeListItemElement(NoticeListItem $nli) + { + $rawtags = $nli->getNotice()->getTags(); + $classes = "tagcontainer"; + + foreach($rawtags as $tag) + { + $classes = $classes . ' data-tag-' . $tag; + } + + + $nli->elementStart('span', array('class' => $classes)); + //$nli->elementEnd('span'); + } + + function onStartCloseNoticeListItemElement(NoticeListItem $nli) + { + $nli->elementEnd('span'); + } + + function onStartHtmlElement($action, &$attrs) { + $profile = Profile::current(); + + if (!is_null($profile) && $profile instanceof Profile) + { + $hidesensitive = $this->getHideSensitive($profile); + } + else + { + $hidesensitive = false; + } + + + $attrs = array_merge($attrs, + array('data-hidesensitive' => ($hidesensitive ? "true" : "false")) + ); + } + + + function getHideSensitive($profile) { + $c = Cache::instance(); + + /* + if (!empty($c)) { + $hidesensitive = $c->get(Cache::key('profile:hide_sensitive:'.$profile->id)); + if (is_numeric($hidesensitive)) { + return (boolean) $hidesensitive; + } + else return FALSE; + } + */ + + $hidesensitive = $profile->getPref('MoonMan', 'hide_sensitive', '0'); + + if (!empty($c)) { + //not using it yet. + $c->set(Cache::key('profile:hide_sensitive:'.$profile->id), $hidesensitive); + } + + //common_log(LOG_DEBUG, "SENSITIVECONTENT hidesensitive? id " . $profile->id . " value " . (boolean)$hidesensitive ); + + if (is_null($hidesensitive)) { + return FALSE; + } else + if (is_numeric($hidesensitive)) { + return (boolean) $hidesensitive; + } + else return FALSE; + } + +} diff --git a/plugins/SensitiveContent/actions/sensitivecontentsettings.php b/plugins/SensitiveContent/actions/sensitivecontentsettings.php new file mode 100644 index 0000000000..482a893958 --- /dev/null +++ b/plugins/SensitiveContent/actions/sensitivecontentsettings.php @@ -0,0 +1,51 @@ +scoped->getUser(); + + $this->elementStart('form', array('method' => 'post', + 'id' => 'sensitivecontent', + 'class' => 'form_settings', + 'action' => common_local_url('sensitivecontentsettings'))); + + $this->elementStart('fieldset'); + $this->hidden('token', common_session_token()); + $this->elementStart('ul', 'form_data'); + + $this->elementStart('li'); + $this->checkbox('hidesensitive', _('Hide attachments in posts hashtagged #NSFW'), + ($this->arg('hidesensitive')) ? + $this->boolean('hidesensitive') : $this->scoped->getPref('MoonMan','hide_sensitive',0)); + $this->elementEnd('li'); + + + $this->elementEnd('ul'); + $this->submit('save', _m('BUTTON','Save')); + + $this->elementEnd('fieldset'); + $this->elementEnd('form'); + } + + function doPost() + { + $hidesensitive = $this->booleanintstring('hidesensitive'); + $this->scoped->setPref('MoonMan','hide_sensitive', $hidesensitive); + return _('Settings saved.'); + } +} diff --git a/plugins/SensitiveContent/img/blocker.png b/plugins/SensitiveContent/img/blocker.png new file mode 100644 index 0000000000000000000000000000000000000000..6866ce4d4acf18ea3a08f8772eb40ea02881101e GIT binary patch literal 32222 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 literal 0 HcmV?d00001 diff --git a/plugins/SensitiveContent/js/sensitivecontent.js b/plugins/SensitiveContent/js/sensitivecontent.js new file mode 100644 index 0000000000..3c9d6584fd --- /dev/null +++ b/plugins/SensitiveContent/js/sensitivecontent.js @@ -0,0 +1,228 @@ +window.buildAttachmentHTML = function(attachments){ + var attachmentHTML = ''; + var oembedHTML = ''; + var quotedNotices = []; + var attachmentNum = 0; + var oembedNum = 0; + var urlsToHide = []; + if(typeof attachments != "undefined") { + $.each(attachments, function(){ + + // quoted notices + if(typeof this.quoted_notice != 'undefined') { + + var quotedContent = this.quoted_notice.content; + + // quoted notice's attachments' thumb urls + var quotedAttachmentsHTML = ''; + var quotedAttachmentsHTMLbefore = ''; + var quotedAttachmentsHTMLafter = ''; + if(typeof this.quoted_notice.attachments != 'undefined' && this.quoted_notice.attachments.length > 0) { + quotedAttachmentsHTML += '

' + $.each(this.quoted_notice.attachments,function(k,qAttach){ + quotedAttachmentsHTML += '
'; + // remove attachment string from content + quotedContent = quotedContent.split(window.siteInstanceURL + 'attachment/' + qAttach.attachment_id).join(''); + }); + quotedAttachmentsHTML += '
'; + + // if there is only one attachment, it goes before, otherwise after + if(this.quoted_notice.attachments.length == 1) { + quotedAttachmentsHTMLbefore = quotedAttachmentsHTML; + } + else { + quotedAttachmentsHTMLafter = quotedAttachmentsHTML; + } + } + + var quotedNoticeHTML = quotedAttachmentsHTMLbefore + '\ +
\ + ' + this.quoted_notice.fullname + '\ + ' + this.quoted_notice.nickname + '\ +
\ +
' + $.trim(quotedContent) + '
\ + ' + quotedAttachmentsHTMLafter; + + quotedNotices.push({ + url: this.url, + html: quotedNoticeHTML, + href: window.siteInstanceURL + 'notice/' + this.quoted_notice.id, + class:'quoted-notice' + }); + } + + // if we have Twitter oembed data, we add is as quotes + else if(typeof this.oembed != 'undefined' + && this.oembed !== false + && this.oembed.provider == 'Twitter') { + + var twitterHTML = '
\ + ' + this.oembed.author_name + '\ + ' + this.oembed.title + '\ +
\ +
' + this.oembed.oembedHTML + '
\ + '; + quotedNotices.push({ + url: this.url, + html: twitterHTML, + href: this.url, + class:'oembed-item' + }); + } + // if we have other oembed data (but not for photos and youtube, we handle those later) + else if(typeof this.oembed != 'undefined' + && this.oembed !== false + && this.oembed.title !== null + && this.oembed.provider != 'YouTube' + && this.oembed.provider != 'Vimeo' + && this.oembed.type != 'photo') { + + var oembedImage = ''; + // only local images + if(typeof this.thumb_url != 'undefined' + && this.thumb_url !== null + && isLocalURL(this.thumb_url)) { + oembedImage = '
'; + } + + var oembedBody = ''; + + // don't add body if html it's too similar (80%) to the title (wordpress does this..) + if(this.oembed.oembedHTML !== null + && this.oembed.oembedHTML.length > 0) { + if(this.oembed.oembedHTML.length > 200) { + this.oembed.oembedHTML = this.oembed.oembedHTML.substring(0,200) + '…'; + } + if(stringSimilarity(this.oembed.oembedHTML,this.oembed.title.substring(0,200)) < 80) { + oembedBody = this.oembed.oembedHTML; + } + } + + if(this.oembed.provider === null) { + var oembedProvider = this.url; + var oembedProviderURL = ''; + } + else { + var oembedProvider = this.oembed.provider; + var oembedProviderURL = removeProtocolFromUrl(this.oembed.provider_url); + // remove trailing / + if(oembedProviderURL.slice(-1) == '/') { + oembedProviderURL = oembedProviderURL.slice(0,-1); + } + } + + // If the oembed data is generated by Qvitter, we know a better way of showing the title + var oembedTitle = this.oembed.title; + var oembedTitleHTML = '' + oembedTitle + ''; + if(oembedTitle.slice(-10) == ' (Qvitter)') { + var oembedTimePosted = parseTwitterLongDate(oembedTitle.slice(0,-10)); + var oembedGNUsocialUsername = this.oembed.author_name.substring(this.oembed.author_name.lastIndexOf('(')+1,this.oembed.author_name.lastIndexOf(')')); + var oembedGNUsocialFullname = this.oembed.author_name.slice(0,-(oembedGNUsocialUsername.length+3)); + oembedTitleHTML = '' + oembedGNUsocialFullname + '\ + @' + oembedGNUsocialUsername + ''; + } + + + oembedHTML += '\ + ' + oembedImage + '\ +
\ + ' + oembedTitleHTML + '\ +
\ +
' + oembedBody + '
\ + \ +
'; + oembedNum++; + } + // if there's a local thumb_url we assume this is a image or video + else if(typeof this.thumb_url != 'undefined' + && this.thumb_url !== null + && isLocalURL(this.thumb_url)) { + var bigThumbW = 1000; + var bigThumbH = 3000; + if(bigThumbW > window.siteMaxThumbnailSize) { + bigThumbW = window.siteMaxThumbnailSize; + } + if(bigThumbH > window.siteMaxThumbnailSize) { + bigThumbH = window.siteMaxThumbnailSize; + } + + // very long landscape images should not have background-size:cover + var noCoverClass=''; + if(this.width/this.height > 2) { + noCoverClass=' no-cover'; + } + + // play button for videos and animated gifs + var playButtonClass = ''; + if(typeof this.animated != 'undefined' && this.animated === true + || (this.url.indexOf('://www.youtube.com') > -1 || this.url.indexOf('://youtu.be') > -1) + || this.url.indexOf('://vimeo.com') > -1) { + playButtonClass = ' play-button'; + } + + // gif-class + var animatedGifClass = ''; + if(typeof this.animated != 'undefined' && this.animated === true) { + var animatedGifClass = ' animated-gif'; + } + + // animated gifs always get default small non-animated thumbnail + if(this.animated === true) { + var img_url = this.thumb_url; + } + // if no dimensions are set, go with default thumb + else if(this.width === null && this.height === null) { + var img_url = this.thumb_url; + } + // large images get large thumbnail + else if(this.width > 1000) { + var img_url = this.large_thumb_url; + } + // no thumbnails for small local images + else if (this.url.indexOf(window.siteInstanceURL) === 0) { + var img_url = this.url; + } + // small thumbnail for small remote images + else { + var img_url = this.thumb_url; + } + + var urlToHide = window.siteInstanceURL + 'attachment/' + this.id; + + attachmentHTML += ''; + urlsToHide.push(urlToHide); // hide this attachment url from the queet text + attachmentNum++; + } + else if (this.mimetype == 'image/svg+xml') { + var urlToHide = window.siteInstanceURL + 'attachment/' + this.id; + attachmentHTML += ''; + urlsToHide.push(urlToHide); // hide this attachment url from the queet text + attachmentNum++; + } + }); + } + return { html: '
' + oembedHTML + '
 
' + attachmentHTML + '
', + urlsToHide: urlsToHide, + quotedNotices: quotedNotices + }; + } + + +window.sensitiveContentOriginalBuildQueetHtml = window.buildQueetHtml; + +window.buildQueetHtml = function(obj, idInStream, extraClasses, requeeted_by, isConversation) { + //add tags to json if they don't exit + if (obj.tags && obj.tags.length > 0) { + for (var tagI = 0; tagI < obj.tags.length; ++tagI) { + extraClasses += (' data-tag-' + obj.tags[tagI]); + if (window.loggedIn.hide_sensitive && obj.tags[tagI] === 'nsfw') extraClasses += ' sensitive-notice'; + } + } + + return window.sensitiveContentOriginalBuildQueetHtml(obj, idInStream, extraClasses, requeeted_by, isConversation); +} \ No newline at end of file -- 2.39.5