From b59df00ca88a156022b9ab67ff9fdf29eb05ebde Mon Sep 17 00:00:00 2001 From: Hannes Mannerheim Date: Mon, 19 Aug 2013 15:30:57 +0200 Subject: [PATCH] upload --- API.php | 95 + LICENSE | 661 ++++ README.md | 76 + api-changes-1.1.1/CHANGES | 160 + api-changes-1.1.1/actions/apiattachment.php | 106 + api-changes-1.1.1/actions/apicheckhub.php | 122 + api-changes-1.1.1/actions/apiconversation.php | 244 ++ .../actions/apiexternalprofileshow.php | 99 + api-changes-1.1.1/actions/apisearchjson.php | 143 + api-changes-1.1.1/actions/apistatusesfavs.php | 139 + .../actions/apistatusesupdate.php | 380 ++ api-changes-1.1.1/actions/apitimelinetag.php | 248 ++ api-changes-1.1.1/actions/apitimelineuser.php | 524 +++ api-changes-1.1.1/classes/Notice.php | 2761 +++++++++++++++ api-changes-1.1.1/lib/apiaction.php | 1684 +++++++++ api-changes-1.1.1/lib/router.php | 1193 +++++++ css/1.css | 3088 +++++++++++++++++ favicon.ico | Bin 0 -> 1150 bytes img/birds.png | Bin 0 -> 5996 bytes img/birds_rtl.png | Bin 0 -> 5962 bytes img/button_birds.png | Bin 0 -> 736 bytes img/ekan4.jpg | Bin 0 -> 273956 bytes img/logo.png | Bin 0 -> 5661 bytes img/sprite.png | Bin 0 -> 9376 bytes img/sprite_bgs.png | Bin 0 -> 3913 bytes index.php | 176 + js/ajax-functions-1.js | 397 +++ js/dom-functions-1.js | 1381 ++++++++ js/jquery-2.0.2.min.js | 6 + js/jquery-ui-1.10.3.min.js | 12 + js/jquery.easing.1.3.js | 205 ++ js/lan-1.js | 703 ++++ js/misc-functions-1.js | 401 +++ js/qvitter-1.js | 1296 +++++++ screenshot1.png | Bin 0 -> 752762 bytes screenshot2.png | Bin 0 -> 610405 bytes settings.php | 71 + 37 files changed, 16371 insertions(+) create mode 100644 API.php create mode 100755 LICENSE create mode 100644 README.md create mode 100644 api-changes-1.1.1/CHANGES create mode 100644 api-changes-1.1.1/actions/apiattachment.php create mode 100644 api-changes-1.1.1/actions/apicheckhub.php create mode 100644 api-changes-1.1.1/actions/apiconversation.php create mode 100644 api-changes-1.1.1/actions/apiexternalprofileshow.php create mode 100644 api-changes-1.1.1/actions/apisearchjson.php create mode 100644 api-changes-1.1.1/actions/apistatusesfavs.php create mode 100644 api-changes-1.1.1/actions/apistatusesupdate.php create mode 100644 api-changes-1.1.1/actions/apitimelinetag.php create mode 100644 api-changes-1.1.1/actions/apitimelineuser.php create mode 100644 api-changes-1.1.1/classes/Notice.php create mode 100644 api-changes-1.1.1/lib/apiaction.php create mode 100644 api-changes-1.1.1/lib/router.php create mode 100644 css/1.css create mode 100644 favicon.ico create mode 100644 img/birds.png create mode 100644 img/birds_rtl.png create mode 100644 img/button_birds.png create mode 100644 img/ekan4.jpg create mode 100644 img/logo.png create mode 100644 img/sprite.png create mode 100644 img/sprite_bgs.png create mode 100644 index.php create mode 100644 js/ajax-functions-1.js create mode 100644 js/dom-functions-1.js create mode 100644 js/jquery-2.0.2.min.js create mode 100644 js/jquery-ui-1.10.3.min.js create mode 100644 js/jquery.easing.1.3.js create mode 100644 js/lan-1.js create mode 100644 js/misc-functions-1.js create mode 100644 js/qvitter-1.js create mode 100644 screenshot1.png create mode 100644 screenshot2.png create mode 100644 settings.php diff --git a/API.php b/API.php new file mode 100644 index 0000000..d81539c --- /dev/null +++ b/API.php @@ -0,0 +1,95 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter 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 three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + +include 'settings.php'; + +header("Content-type: application/json; charset=utf-8"); +if(substr($apiroot,-1) != '/') { $apiroot .= '/'; } // add slash if missing + +// post requests +if(isset($_POST['postRequest'])) { + $query = http_build_query($_POST, '', '&'); + $ch=curl_init(); + curl_setopt($ch, CURLOPT_URL, $apiroot.urldecode($_POST['postRequest'])); + curl_setopt($ch, CURLOPT_USERPWD, $_POST['username'].":".$_POST['password']); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $query); + session_write_close(); // fix problem with curling to local + $reply=curl_exec($ch); + curl_close($ch); + session_start(); + + // force ssl on our domain + if($forcessl) { + $reply = str_replace('http://'.$siterootdomain,'https://'.$siterootdomain,$reply); + } + + print $reply; + } + +// get requests +elseif(isset($_POST['getRequest'])) { + $ch=curl_init(); + curl_setopt($ch, CURLOPT_URL, $apiroot.$_POST['getRequest']); + + if(isset($_POST['username'])) { + curl_setopt($ch, CURLOPT_USERPWD, $_POST['username'].":".$_POST['password']); + } + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + session_write_close(); + $reply=curl_exec($ch); + curl_close($ch); + session_start(); + + // force ssl on our domain + if($forcessl) { + $reply = str_replace('http:\/\/'.$siterootdomain,'https:\/\/'.$siterootdomain,$reply); + } + + print $reply; + } + + + + /* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · + · · + · (o> >o) · + · \\\\_\ /_//// . + · \____) (____/ · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */?> \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..dba13ed --- /dev/null +++ b/LICENSE @@ -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/README.md b/README.md new file mode 100644 index 0000000..8267e65 --- /dev/null +++ b/README.md @@ -0,0 +1,76 @@ +Qvitter +========================================== + +* Author: Hannes Mannerheim () +* Last mod.: August, 2013 +* Version: 1 +* Website: +* GitHub: + +Qvitter 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 three of the License or (at +your option) any later version. + +Qvitter is distributed in hope that it will be useful but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see . + +Setup +----- + +You need a webserver with PHP support. + +Edit settings.php. + +(Qvitter uses a slightly modified statusnet API. Some things will not work +if you connect to a site with standard API. Files are included if you want +to Qvitter-mod your Statusnet API.) + + +TODO +---- + +1. Join new external groups and follow new external users + +2. Follow people on other instances + +3. Auto suggest mentions + +4. Register + +5. Background image uploading/editing + +6. Color theme + +7. Auto url-shortening setting under queet box + +10. Settings (e.g. don't show replies to people I don't follow) + +11. Syntax-coloring in queet-box, maybe codemirror (worked nicely for ltr but not rtl text when I tried it) + +12. Image/file upload, drag-n-drop! + +13. Search users + +14. Recommended users + +15. Filters (hide queets containing strings, e.g. mute users) + +18. Better responsive design + +19. More languages + +20. Queet-page + +21. New api for serving _number_ of new items in several streams (to show number of new items in menu/history) + +22. New "expand queet" api for getting conversation, retweets, favs and attachment in the same request + +23. DMs + +24. Node.js long polling server and an new api that serve aggregate of all polling users requests in one go diff --git a/api-changes-1.1.1/CHANGES b/api-changes-1.1.1/CHANGES new file mode 100644 index 0000000..82514aa --- /dev/null +++ b/api-changes-1.1.1/CHANGES @@ -0,0 +1,160 @@ + CHANGES TO API + -------------- + + * actions/apiattachment.php New api action + * actions/apistatusesfavs.php New api action + * actions/apicheckhub.php New api action (not used yet) + * actions/apiexternalprofileshow.php New api action + + * lib/apiaction.php + + - add urls to larger avatars + + ~LINE 213 $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); + $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_STREAM_SIZE); + $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); + $twitter_user['profile_image_url_profile_size'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_PROFILE_SIZE); + $avatar = $profile->getOriginalAvatar(); + $twitter_user['profile_image_url_original'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_PROFILE_SIZE); + $groups = $profile->getGroups(); + $groups_count = 0; while($groups->fetch()) $groups_count++; + $twitter_user['groups_count'] = $groups_count; + + + - add the uri-field + + ~line 320 $twitter_status['uri'] = $notice->uri; + + + - show if a notices is favorited by auth_user + + ~line 345 if (isset($this->auth_user)) { + $this_profile = $this->auth_user->getProfile(); + $twitter_status['favorited'] = $this->auth_user->hasFave($notice); + $twitter_status['repeated'] = $this_profile->hasRepeated($notice->id); + } else { + $twitter_status['favorited'] = false; + $twitter_status['repeated'] = false; + } + + + - show number of admins in group api + + ~line 420 $admins = $group->getAdmins(); + $admin_count = 0; while($admins->fetch()) $admin_count++; + $twitter_group['admin_count'] = $admin_count; + + + - to be able to get group profile by uri. + - hackish though, because if uri get-var is sent, it will discard the id get var + - (but id still needs to be sent and be non-numerical, so I do "?id=foo&uri={uri}") + - should be possible to only supply uri get var, but I was lazy... sry + + ~line 1565 } else if ($this->arg('uri')) { + return User_group::staticGet('uri', urldecode($this->arg('uri'))); + + + * lib/router.php + + - add routing for new api actions + + ~line 467: $m->connect('api/statuses/favs/:id.json', + array('action' => 'ApiStatusesFavs', + 'id' => '[0-9]+')); + + $m->connect('api/attachment/:id.json', + array('action' => 'ApiAttachment', + 'id' => '[0-9]+')); + + $m->connect('api/checkhub.json', + array('action' => 'ApiCheckHub')); + + $m->connect('api/externalprofile/show.json', + array('action' => 'ApiExternalProfileShow')); + + + - also, tags need regexp to work with unicode charachters, e.g. farsi and arabic: + + $m->connect('api/statusnet/tags/timeline/:tag.:format', + array('action' => 'ApiTimelineTag', + 'tag' => self::REGEX_TAG, + 'format' => '(xml|json|rss|atom|as)')); + + + * acitons/apiconversation.php + + - I didn't always get Profile::current() to show me the auth user's profile, so I changed it to the normal $this->auth_user used in other api actions + + ~ line 80: if(isset($this->auth_user)) { + $profile = $this->auth_user->getProfile(); + } + else { + $profile = null; + } + + + + + *actions/apitimelineuser.php + + - this api did only return the public user timeline, not the auth user's. + - e.g. it did not show notices from people who post to "my colleques at quitter" + - changed to return timeline according to which auth user is requesting + + ~ line 238 $user_profile = $this->user->getProfile(); + if(isset($this->auth_user)) { + $auth_user_profile = $this->auth_user->getProfile(); + } + else { + $auth_user_profile = null; + } + + $stream = new ProfileNoticeStream($user_profile, $auth_user_profile); + + $notice = $stream->getNotices(($this->page-1) * $this->count, + $this->count + 1, + $this->since_id, + $this->max_id); + + + * search.json + + - changed response to normal twitter format, maybe I should have created a new api action for that, + - but... i don't see the point in having a special format for searches, it should be same as other streams + + + + * actions/timelinetags.php + + - added max_id and since_id + + ~line 179 $notice = Notice_tag::getStream( + $this->tag, + ($this->page - 1) * $this->count, + $this->count + 1, + $this->since_id, + $this->max_id + ); + + * actions/apistatusesupdate.php + + - we don't want statuses to shorten if sent through the api + + ~ line 290: //$status_shortened = $this->auth_user->shortenlinks($this->status); + $status_shortened = $this->status; + + + * classes/Notice.php + + - to _not_ shorten urls sent through api, we need to comment out this also + + ~ line 352 // if ($user) { + // // Use the local user's shortening preferences, if applicable. + // $final = $user->shortenLinks($content); + // } else { + // $final = common_shorten_links($content); + // } + diff --git a/api-changes-1.1.1/actions/apiattachment.php b/api-changes-1.1.1/actions/apiattachment.php new file mode 100644 index 0000000..9e7cd40 --- /dev/null +++ b/api-changes-1.1.1/actions/apiattachment.php @@ -0,0 +1,106 @@ +. + * + * @category API + * @package StatusNet + * @author Hannes Mannerheim + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; + +/** + * Show a notice's attachment + * + */ +class ApiAttachmentAction extends ApiAuthAction +{ + const MAXCOUNT = 100; + + var $original = null; + var $cnt = self::MAXCOUNT; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + function prepare($args) + { + parent::prepare($args); + + return true; + } + + /** + * Handle the request + * + * Make a new notice for the update, save it, and show it + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + parent::handle($args); + $file = new File(); + $file->selectAdd(); // clears it + $file->selectAdd('url'); + $file->id = $this->trimmed('id'); + $url = $file->fetchAll('url'); + + $file_txt = ''; + if(strstr($url[0],'.html')) { + $file_txt['txt'] = file_get_contents(str_replace('://quitter.se','://127.0.0.1',$url[0])); + $file_txt['body_start'] = strpos($file_txt['txt'],'')+6; + $file_txt['body_end'] = strpos($file_txt['txt'],''); + $file_txt = substr($file_txt['txt'],$file_txt['body_start'],$file_txt['body_end']-$file_txt['body_start']); + } + + $this->initDocument('json'); + $this->showJsonObjects($file_txt); + $this->endDocument('json'); + } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return true; + } +} diff --git a/api-changes-1.1.1/actions/apicheckhub.php b/api-changes-1.1.1/actions/apicheckhub.php new file mode 100644 index 0000000..7074afe --- /dev/null +++ b/api-changes-1.1.1/actions/apicheckhub.php @@ -0,0 +1,122 @@ +. + * + * @category API + * @package StatusNet + * @author Hannes Mannerheim + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; + +/** + * Check if a url have a push-hub, i.e. if it is possible to subscribe + * + */ +class ApiCheckHubAction extends ApiAuthAction +{ + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + function prepare($args) + { + parent::prepare($args); + + $this->url = urldecode($args['url']); + + if (!$this->url) { + $this->clientError(_('No URL.'), 403, 'json'); + return; + } + + if (!Validate::uri( + $this->url, array( + 'allowed_schemes' => + array('http', 'https') + ) + )) { + $this->clientError(_('Invalid URL.'), 403, 'json'); + return; + } + + return true; + } + + /** + * Handle the request + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + + $discover = new FeedDiscovery(); + + try { + $feeduri = $discover->discoverFromURL($this->url); + if($feeduri) { + $huburi = $discover->getHubLink(); + } + } catch (FeedSubNoFeedException $e) { + $this->clientError(_('No feed found'), 403, 'json'); + return; + } catch (FeedSubBadResponseException $e) { + $this->clientError(_('No hub found'), 403, 'json'); + return; + } + + $hub_status = array(); + if ($huburi) { + $hub_status = array('huburi' => $huburi); + } + + $this->initDocument('json'); + $this->showJsonObjects($hub_status); + $this->endDocument('json'); + } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return true; + } +} diff --git a/api-changes-1.1.1/actions/apiconversation.php b/api-changes-1.1.1/actions/apiconversation.php new file mode 100644 index 0000000..86fbe93 --- /dev/null +++ b/api-changes-1.1.1/actions/apiconversation.php @@ -0,0 +1,244 @@ +. + * + * @category API + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +require_once INSTALLDIR . '/lib/apiauth.php'; + +/** + * Show a stream of notices in a particular conversation + * + * @category API + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ +class ApiconversationAction extends ApiAuthAction +{ + protected $conversation = null; + protected $notices = null; + + /** + * For initializing members of the class. + * + * @param array $argarray misc. arguments + * + * @return boolean true + */ + function prepare($argarray) + { + parent::prepare($argarray); + + $convId = $this->trimmed('id'); + + if (empty($convId)) { + // TRANS: Client exception thrown when no conversation ID is given. + throw new ClientException(_('No conversation ID.')); + } + + $this->conversation = Conversation::staticGet('id', $convId); + + if (empty($this->conversation)) { + // TRANS: Client exception thrown when referring to a non-existing conversation ID (%d). + throw new ClientException(sprintf(_('No conversation with ID %d.'), $convId), + 404); + } + +// $profile = Profile::current(); + if(isset($this->auth_user)) { + $profile = $this->auth_user->getProfile(); + } + else { + $profile = null; + } + + $stream = new ConversationNoticeStream($convId, $profile); + + $notice = $stream->getNotices(($this->page-1) * $this->count, + $this->count, + $this->since_id, + $this->max_id); + + $this->notices = $notice->fetchAll(); + + return true; + } + + /** + * Handler method + * + * @param array $argarray is ignored since it's now passed in in prepare() + * + * @return void + */ + function handle($argarray=null) + { + $sitename = common_config('site', 'name'); + // TRANS: Title for conversion timeline. + $title = _m('TITLE', 'Conversation'); + $id = common_local_url('apiconversation', array('id' => $this->conversation->id, 'format' => $this->format)); + $link = common_local_url('conversation', array('id' => $this->conversation->id)); + + $self = $id; + + switch($this->format) { + case 'xml': + $this->showXmlTimeline($this->notices); + break; + case 'rss': + $this->showRssTimeline( + $this->notices, + $title, + $link, + null, + null, + null, + $self + ); + break; + case 'atom': + + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed($this->auth_user); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setUpdated('now'); + + $atom->addLink($link); + $atom->setSelfLink($self); + + $atom->addEntryFromNotices($this->notices); + $this->raw($atom->getString()); + + break; + case 'json': + $this->showJsonTimeline($this->notices); + break; + case 'as': + header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); + $doc = new ActivityStreamJSONDocument($this->auth_user); + $doc->setTitle($title); + $doc->addLink($link, 'alternate', 'text/html'); + $doc->addItemsFromNotices($this->notices); + $this->raw($doc->asString()); + break; + default: + // TRANS: Client error displayed when coming across a non-supported API method. + $this->clientError(_('API method not found.'), $code = 404); + break; + } + } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + function isReadOnly($args) + { + if ($_SERVER['REQUEST_METHOD'] == 'GET' || + $_SERVER['REQUEST_METHOD'] == 'HEAD') { + return true; + } else { + return false; + } + } + + /** + * Return last modified, if applicable. + * + * MAY override + * + * @return string last modified http header + */ + function lastModified() + { + if (!empty($this->notices) && (count($this->notices) > 0)) { + return strtotime($this->notices[0]->created); + } + + return null; + } + + /** + * Return etag, if applicable. + * + * MAY override + * + * @return string etag http header + */ + function etag() + { + if (!empty($this->notices) && (count($this->notices) > 0)) { + + $last = count($this->notices) - 1; + + return '"' . implode( + ':', + array($this->arg('action'), + common_user_cache_hash($this->auth_user), + common_language(), + $this->user->id, + strtotime($this->notices[0]->created), + strtotime($this->notices[$last]->created)) + ) + . '"'; + } + + return null; + } + + /** + * Does this require authentication? + * + * @return boolean true if delete, else false + */ + function requiresAuth() + { + if ($_SERVER['REQUEST_METHOD'] == 'GET' || + $_SERVER['REQUEST_METHOD'] == 'HEAD') { + return false; + } else { + return true; + } + } +} diff --git a/api-changes-1.1.1/actions/apiexternalprofileshow.php b/api-changes-1.1.1/actions/apiexternalprofileshow.php new file mode 100644 index 0000000..7d33624 --- /dev/null +++ b/api-changes-1.1.1/actions/apiexternalprofileshow.php @@ -0,0 +1,99 @@ +. + * + * @category API + * @package StatusNet + * @author Hannes Mannerheim + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiprivateauth.php'; + +/** + * Ouputs information for a user, specified by ID or screen name. + * The user's most recent status will be returned inline. + */ +class ApiExternalProfileShowAction extends ApiPrivateAuthAction +{ + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + function prepare($args) + { + parent::prepare($args); + + $profileurl = urldecode($this->arg('profileurl')); + + $this->profile = Profile::staticGet('profileurl', $profileurl); + + return true; + } + + /** + * Handle the request + * + * Check the format and show the user info + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + parent::handle($args); + + if (empty($this->profile)) { + // TRANS: Client error displayed when requesting profile information for a non-existing profile. + $this->clientError(_('Profile not found.'), 404, 'json'); + return; + } + + $twitter_user = $this->twitterUserArray($this->profile, true); + + $this->initDocument('json'); + $this->showJsonObjects($twitter_user); + $this->endDocument('json'); + } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + function isReadOnly($args) + { + return true; + } +} diff --git a/api-changes-1.1.1/actions/apisearchjson.php b/api-changes-1.1.1/actions/apisearchjson.php new file mode 100644 index 0000000..805cc0a --- /dev/null +++ b/api-changes-1.1.1/actions/apisearchjson.php @@ -0,0 +1,143 @@ +. + * + * @category Search + * @package StatusNet + * @author Zach Copley + * @copyright 2008-2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/apiprivateauth.php'; +require_once INSTALLDIR.'/lib/jsonsearchresultslist.php'; + +/** + * Action handler for Twitter-compatible API search + * + * @category Search + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * @see ApiAction + */ +class ApiSearchJSONAction extends ApiPrivateAuthAction +{ + var $query; + var $lang; + var $rpp; + var $page; + var $since_id; + var $limit; + var $geocode; + + /** + * Initialization. + * + * @param array $args Web and URL arguments + * + * @return boolean true if nothing goes wrong + */ + function prepare($args) + { + parent::prepare($args); + + $this->query = $this->trimmed('q'); + $this->lang = $this->trimmed('lang'); + $this->rpp = $this->trimmed('rpp'); + + if (!$this->rpp) { + $this->rpp = 15; + } + + if ($this->rpp > 100) { + $this->rpp = 100; + } + + $this->page = $this->trimmed('page'); + + if (!$this->page) { + $this->page = 1; + } + + // TODO: Suppport max_id -- we need to tweak the backend + // Search classes to support it. + + $this->since_id = $this->trimmed('since_id'); + $this->geocode = $this->trimmed('geocode'); + + return true; + } + + /** + * Handle a request + * + * @param array $args Arguments from $_REQUEST + * + * @return void + */ + function handle($args) + { + parent::handle($args); + $this->showResults(); + } + + /** + * Show search results + * + * @return void + */ + function showResults() + { + // TODO: Support search operators like from: and to:, boolean, etc. + + $notice = new Notice(); + + // lcase it for comparison + $q = strtolower($this->query); + + $this->notices = array(); + $search_engine = $notice->getSearchEngine('notice'); + $search_engine->set_sort_mode('chron'); + $search_engine->limit(($this->page - 1) * $this->rpp, $this->rpp + 1); + if ($search_engine->query($q)) { + $cnt = $notice->find(); + $this->notices = $notice->fetchAll(); + } + + $this->showJsonTimeline($this->notices); + } + + /** + * Do we need to write to the database? + * + * @return boolean true + */ + function isReadOnly($args) + { + return true; + } +} diff --git a/api-changes-1.1.1/actions/apistatusesfavs.php b/api-changes-1.1.1/actions/apistatusesfavs.php new file mode 100644 index 0000000..e5b8dc3 --- /dev/null +++ b/api-changes-1.1.1/actions/apistatusesfavs.php @@ -0,0 +1,139 @@ +. + * + * @category API + * @package StatusNet + * @author Hannes Mannerheim + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; + +/** + * Show up to 100 favs of a notice + * + */ +class ApiStatusesFavsAction extends ApiAuthAction +{ + const MAXCOUNT = 100; + + var $original = null; + var $cnt = self::MAXCOUNT; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + function prepare($args) + { + parent::prepare($args); + + $id = $this->trimmed('id'); + + $this->original = Notice::staticGet('id', $id); + + if (empty($this->original)) { + // TRANS: Client error displayed trying to display redents of a non-exiting notice. + $this->clientError(_('No such notice.'), + 400, $this->format); + return false; + } + + $cnt = $this->trimmed('count'); + + if (empty($cnt) || !is_integer($cnt)) { + $cnt = 100; + } else { + $this->cnt = min((int)$cnt, self::MAXCOUNT); + } + + return true; + } + + /** + * Handle the request + * + * Get favs and return them as json object + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + parent::handle($args); + + $fave = new Fave(); + $fave->selectAdd(); + $fave->selectAdd('user_id'); + $fave->notice_id = $this->original->id; + $fave->orderBy('modified'); + if (!is_null($this->cnt)) { + $fave->limit(0, $this->cnt); + } + + $ids = $fave->fetchAll('user_id'); + + // get nickname and profile image + $ids_with_profile_data = array(); + $i=0; + foreach($ids as $id) { + $profile = Profile::staticGet('id', $id); + $ids_with_profile_data[$i]['user_id'] = $id; + $ids_with_profile_data[$i]['nickname'] = $profile->nickname; + $ids_with_profile_data[$i]['fullname'] = $profile->fullname; + $ids_with_profile_data[$i]['profileurl'] = $profile->profileurl; + $profile = new Profile(); + $profile->id = $id; + $avatarurl = $profile->avatarUrl(24); + $ids_with_profile_data[$i]['avatarurl'] = $avatarurl; + $i++; + } + + $this->initDocument('json'); + $this->showJsonObjects($ids_with_profile_data); + $this->endDocument('json'); + } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return true; + } +} diff --git a/api-changes-1.1.1/actions/apistatusesupdate.php b/api-changes-1.1.1/actions/apistatusesupdate.php new file mode 100644 index 0000000..3c48393 --- /dev/null +++ b/api-changes-1.1.1/actions/apistatusesupdate.php @@ -0,0 +1,380 @@ +. + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette + * @author Zach Copley + * @copyright 2009-2010 StatusNet, Inc. + * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +/* External API usage documentation. Please update when you change how this method works. */ + +/*! @page statusesupdate statuses/update + + @section Description + Updates the authenticating user's status. Requires the status parameter specified below. + Request must be a POST. + + @par URL pattern + /api/statuses/update.:format + + @par Formats (:format) + xml, json + + @par HTTP Method(s) + POST + + @par Requires Authentication + Yes + + @param status (Required) The URL-encoded text of the status update. + @param source (Optional) The source application name, if using HTTP authentication or an anonymous OAuth consumer. + @param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to. + @param lat (Optional) The latitude the status refers to. + @param long (Optional) The longitude the status refers to. + @param media (Optional) a media upload, such as an image or movie file. + + @sa @ref authentication + @sa @ref apiroot + + @subsection usagenotes Usage notes + + @li The URL pattern is relative to the @ref apiroot. + @li If the @e source parameter is not supplied the source of the status will default to 'api'. When authenticated via a registered OAuth application, the application's registered name and URL will always override the source parameter. + @li The XML response uses GeoRSS + to encode the latitude and longitude (see example response below ). + @li Data uploaded via the @e media parameter should be multipart/form-data encoded. + + @subsection exampleusage Example usage + + @verbatim + curl -u username:password http://example.com/api/statuses/update.xml -d status='Howdy!' -d lat='30.468' -d long='-94.743' + @endverbatim + + @subsection exampleresponse Example response + + @verbatim + + + Howdy! + false + Tue Mar 30 23:28:05 +0000 2010 + + api + 26668724 + + + + 30.468 -94.743 + + false + + 25803 + Jed Sanders + jedsanders + Hoop and Holler, Texas + I like to think of myself as America's Favorite. + http://avatar.example.com/25803-48-20080924200604.png + http://jedsanders.net + false + 5 + + + + + + 2 + Wed Sep 24 20:04:00 +0000 2008 + 0 + 0 + UTC + + false + 70 + true + true + + + @endverbatim +*/ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; + +/** + * Updates the authenticating user's status (posts a notice). + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ +class ApiStatusesUpdateAction extends ApiAuthAction +{ + var $status = null; + var $in_reply_to_status_id = null; + var $lat = null; + var $lon = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + function prepare($args) + { + parent::prepare($args); + + $this->status = $this->trimmed('status'); + $this->lat = $this->trimmed('lat'); + $this->lon = $this->trimmed('long'); + + $this->in_reply_to_status_id + = intval($this->trimmed('in_reply_to_status_id')); + + return true; + } + + /** + * Handle the request + * + * Make a new notice for the update, save it, and show it + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + parent::handle($args); + + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + $this->clientError( + // TRANS: Client error. POST is a HTTP command. It should not be translated. + _('This method requires a POST.'), + 400, + $this->format + ); + return; + } + + // Workaround for PHP returning empty $_POST and $_FILES when POST + // length > post_max_size in php.ini + + if (empty($_FILES) + && empty($_POST) + && ($_SERVER['CONTENT_LENGTH'] > 0) + ) { + // TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit. + // TRANS: %s is the number of bytes of the CONTENT_LENGTH. + $msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.', + 'The server was unable to handle that much POST data (%s bytes) due to its current configuration.', + intval($_SERVER['CONTENT_LENGTH'])); + + $this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); + return; + } + + if (empty($this->status)) { + $this->clientError( + // TRANS: Client error displayed when the parameter "status" is missing. + _('Client must provide a \'status\' parameter with a value.'), + 400, + $this->format + ); + return; + } + + if (empty($this->auth_user)) { + // TRANS: Client error displayed when updating a status for a non-existing user. + $this->clientError(_('No such user.'), 404, $this->format); + return; + } + + /* Do not call shortenlinks until the whole notice has been build */ + + // Check for commands + + $inter = new CommandInterpreter(); + $cmd = $inter->handle_command($this->auth_user, $this->status); + + if ($cmd) { + if ($this->supported($cmd)) { + $cmd->execute(new Channel()); + } + + // Cmd not supported? Twitter just returns your latest status. + // And, it returns your last status whether the cmd was successful + // or not! + + $this->notice = $this->auth_user->getCurrentNotice(); + } else { + $reply_to = null; + + if (!empty($this->in_reply_to_status_id)) { + // Check whether notice actually exists + + $reply = Notice::staticGet($this->in_reply_to_status_id); + + if ($reply) { + $reply_to = $this->in_reply_to_status_id; + } else { + $this->clientError( + // TRANS: Client error displayed when replying to a non-existing notice. + _('Parent notice not found.'), + $code = 404, + $this->format + ); + return; + } + } + + $upload = null; + + try { + $upload = MediaFile::fromUpload('media', $this->auth_user); + } catch (Exception $e) { + $this->clientError($e->getMessage(), $e->getCode(), $this->format); + return; + } + + if (isset($upload)) { + $this->status .= ' ' . $upload->shortUrl(); + + /* Do not call shortenlinks until the whole notice has been build */ + } + + /* Do call shortenlinks here & check notice length since notice is about to be saved & sent */ + //$status_shortened = $this->auth_user->shortenlinks($this->status); + + /* DO NOT! */ + $status_shortened = $this->status; + + if (Notice::contentTooLong($status_shortened)) { + if (isset($upload)) { + $upload->delete(); + } + // TRANS: Client error displayed exceeding the maximum notice length. + // TRANS: %d is the maximum lenth for a notice. + $msg = _m('Maximum notice size is %d character, including attachment URL.', + 'Maximum notice size is %d characters, including attachment URL.', + Notice::maxContent()); + /* Use HTTP 413 error code (Request Entity Too Large) + * instead of basic 400 for better understanding + */ + $this->clientError(sprintf($msg, Notice::maxContent()), + 413, + $this->format); + } + + + $content = html_entity_decode($status_shortened, ENT_NOQUOTES, 'UTF-8'); + + $options = array('reply_to' => $reply_to); + + if ($this->auth_user->shareLocation()) { + + $locOptions = Notice::locationOptions($this->lat, + $this->lon, + null, + null, + $this->auth_user->getProfile()); + + $options = array_merge($options, $locOptions); + } + + try { + $this->notice = Notice::saveNew( + $this->auth_user->id, + $content, + $this->source, + $options + ); + } catch (Exception $e) { + $this->clientError($e->getMessage(), $e->getCode(), $this->format); + return; + } + + if (isset($upload)) { + $upload->attachToNotice($this->notice); + } + } + + $this->showNotice(); + } + + /** + * Show the resulting notice + * + * @return void + */ + function showNotice() + { + if (!empty($this->notice)) { + if ($this->format == 'xml') { + $this->showSingleXmlStatus($this->notice); + } elseif ($this->format == 'json') { + $this->show_single_json_status($this->notice); + } + } + } + + /** + * Is this command supported when doing an update from the API? + * + * @param string $cmd the command to check for + * + * @return boolean true or false + */ + function supported($cmd) + { + static $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand', + 'FavCommand', 'OnCommand', 'OffCommand', 'JoinCommand', 'LeaveCommand'); + + if (in_array(get_class($cmd), $cmdlist)) { + return true; + } + + return false; + } +} diff --git a/api-changes-1.1.1/actions/apitimelinetag.php b/api-changes-1.1.1/actions/apitimelinetag.php new file mode 100644 index 0000000..4b5a675 --- /dev/null +++ b/api-changes-1.1.1/actions/apitimelinetag.php @@ -0,0 +1,248 @@ +. + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Zach Copley + * @copyright 2009-2010 StatusNet, Inc. + * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiprivateauth.php'; + +/** + * Returns the 20 most recent notices tagged by a given tag + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ +class ApiTimelineTagAction extends ApiPrivateAuthAction +{ + var $notices = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + function prepare($args) + { + parent::prepare($args); + + common_debug("apitimelinetag prepare()"); + + $this->tag = $this->arg('tag'); + $this->notices = $this->getNotices(); + + return true; + } + + /** + * Handle the request + * + * Just show the notices + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + parent::handle($args); + $this->showTimeline(); + } + + /** + * Show the timeline of notices + * + * @return void + */ + function showTimeline() + { + $sitename = common_config('site', 'name'); + $sitelogo = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png'); + // TRANS: Title for timeline with lastest notices with a given tag. + // TRANS: %s is the tag. + $title = sprintf(_("Notices tagged with %s"), $this->tag); + $subtitle = sprintf( + // TRANS: Subtitle for timeline with lastest notices with a given tag. + // TRANS: %1$s is the tag, $2$s is the StatusNet sitename. + _('Updates tagged with %1$s on %2$s!'), + $this->tag, + $sitename + ); + $taguribase = TagURI::base(); + $id = "tag:$taguribase:TagTimeline:".$this->tag; + + $link = common_local_url( + 'tag', + array('tag' => $this->tag) + ); + + $self = $this->getSelfUri(); + + switch($this->format) { + case 'xml': + $this->showXmlTimeline($this->notices); + break; + case 'rss': + $this->showRssTimeline( + $this->notices, + $title, + $link, + $subtitle, + null, + $sitelogo, + $self + ); + break; + case 'atom': + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed($this->auth_user); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addLink($link); + $atom->setSelfLink($self); + + $atom->addEntryFromNotices($this->notices); + $this->raw($atom->getString()); + + break; + case 'json': + $this->showJsonTimeline($this->notices); + break; + case 'as': + header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); + $doc = new ActivityStreamJSONDocument($this->auth_user); + $doc->setTitle($title); + $doc->addLink($link, 'alternate', 'text/html'); + $doc->addItemsFromNotices($this->notices); + $this->raw($doc->asString()); + break; + default: + // TRANS: Client error displayed when coming across a non-supported API method. + $this->clientError(_('API method not found.'), $code = 404); + break; + } + } + + /** + * Get notices + * + * @return array notices + */ + function getNotices() + { + $notices = array(); + + $notice = Notice_tag::getStream( + $this->tag, + ($this->page - 1) * $this->count, + $this->count + 1, + $this->since_id, + $this->max_id + ); + + while ($notice->fetch()) { + $notices[] = clone($notice); + } + + return $notices; + } + + /** + * Is this action read only? + * + * @param array $args other arguments + * + * @return boolean true + */ + function isReadOnly($args) + { + return true; + } + + /** + * When was this feed last modified? + * + * @return string datestamp of the latest notice in the stream + */ + function lastModified() + { + if (!empty($this->notices) && (count($this->notices) > 0)) { + return strtotime($this->notices[0]->created); + } + + return null; + } + + /** + * An entity tag for this stream + * + * Returns an Etag based on the action name, language, and + * timestamps of the first and last notice in the timeline + * + * @return string etag + */ + function etag() + { + if (!empty($this->notices) && (count($this->notices) > 0)) { + + $last = count($this->notices) - 1; + + return '"' . implode( + ':', + array($this->arg('action'), + common_user_cache_hash($this->auth_user), + common_language(), + $this->tag, + strtotime($this->notices[0]->created), + strtotime($this->notices[$last]->created)) + ) + . '"'; + } + + return null; + } +} diff --git a/api-changes-1.1.1/actions/apitimelineuser.php b/api-changes-1.1.1/actions/apitimelineuser.php new file mode 100644 index 0000000..9b8fa6d --- /dev/null +++ b/api-changes-1.1.1/actions/apitimelineuser.php @@ -0,0 +1,524 @@ +. + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette + * @author Zach Copley + * @copyright 2009 StatusNet, Inc. + * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apibareauth.php'; + +/** + * Returns the most recent notices (default 20) posted by the authenticating + * user. Another user's timeline can be requested via the id parameter. This + * is the API equivalent of the user profile web page. + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ +class ApiTimelineUserAction extends ApiBareAuthAction +{ + var $notices = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + function prepare($args) + { + parent::prepare($args); + + $this->user = $this->getTargetUser($this->arg('id')); + + if (empty($this->user)) { + // TRANS: Client error displayed requesting most recent notices for a non-existing user. + $this->clientError(_('No such user.'), 404, $this->format); + return; + } + + $this->notices = $this->getNotices(); + + return true; + } + + /** + * Handle the request + * + * Just show the notices + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + function handle($args) + { + parent::handle($args); + + if ($this->isPost()) { + $this->handlePost(); + } else { + $this->showTimeline(); + } + } + + /** + * Show the timeline of notices + * + * @return void + */ + function showTimeline() + { + $profile = $this->user->getProfile(); + + // We'll use the shared params from the Atom stub + // for other feed types. + $atom = new AtomUserNoticeFeed($this->user, $this->auth_user); + + $link = common_local_url( + 'showstream', + array('nickname' => $this->user->nickname) + ); + + $self = $this->getSelfUri(); + + // FriendFeed's SUP protocol + // Also added RSS and Atom feeds + + $suplink = common_local_url('sup', null, null, $this->user->id); + header('X-SUP-ID: ' . $suplink); + + switch($this->format) { + case 'xml': + $this->showXmlTimeline($this->notices); + break; + case 'rss': + $this->showRssTimeline( + $this->notices, + $atom->title, + $link, + $atom->subtitle, + $suplink, + $atom->logo, + $self + ); + break; + case 'atom': + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom->setId($self); + $atom->setSelfLink($self); + + // Add navigation links: next, prev, first + // Note: we use IDs rather than pages for navigation; page boundaries + // change too quickly! + + if (!empty($this->next_id)) { + $nextUrl = common_local_url('ApiTimelineUser', + array('format' => 'atom', + 'id' => $this->user->id), + array('max_id' => $this->next_id)); + + $atom->addLink($nextUrl, + array('rel' => 'next', + 'type' => 'application/atom+xml')); + } + + if (($this->page > 1 || !empty($this->max_id)) && !empty($this->notices)) { + + $lastNotice = $this->notices[0]; + $lastId = $lastNotice->id; + + $prevUrl = common_local_url('ApiTimelineUser', + array('format' => 'atom', + 'id' => $this->user->id), + array('since_id' => $lastId)); + + $atom->addLink($prevUrl, + array('rel' => 'prev', + 'type' => 'application/atom+xml')); + } + + if ($this->page > 1 || !empty($this->since_id) || !empty($this->max_id)) { + + $firstUrl = common_local_url('ApiTimelineUser', + array('format' => 'atom', + 'id' => $this->user->id)); + + $atom->addLink($firstUrl, + array('rel' => 'first', + 'type' => 'application/atom+xml')); + + } + + $atom->addEntryFromNotices($this->notices); + $this->raw($atom->getString()); + + break; + case 'json': + $this->showJsonTimeline($this->notices); + break; + case 'as': + header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); + $doc = new ActivityStreamJSONDocument($this->auth_user); + $doc->setTitle($atom->title); + $doc->addLink($link, 'alternate', 'text/html'); + $doc->addItemsFromNotices($this->notices); + + // XXX: Add paging extension? + + $this->raw($doc->asString()); + break; + default: + // TRANS: Client error displayed when coming across a non-supported API method. + $this->clientError(_('API method not found.'), $code = 404); + break; + } + } + + /** + * Get notices + * + * @return array notices + */ + function getNotices() + { + $notices = array(); + + $user_profile = $this->user->getProfile(); + if(isset($this->auth_user)) { + $auth_user_profile = $this->auth_user->getProfile(); + } + else { + $auth_user_profile = null; + } + + $stream = new ProfileNoticeStream($user_profile, $auth_user_profile); + + $notice = $stream->getNotices(($this->page-1) * $this->count, + $this->count + 1, + $this->since_id, + $this->max_id); + + while ($notice->fetch()) { + if (count($notices) < $this->count) { + $notices[] = clone($notice); + } else { + $this->next_id = $notice->id; + break; + } + } + + return $notices; + } + + /** + * We expose AtomPub here, so non-GET/HEAD reqs must be read/write. + * + * @param array $args other arguments + * + * @return boolean true + */ + + function isReadOnly($args) + { + return ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD'); + } + + /** + * When was this feed last modified? + * + * @return string datestamp of the latest notice in the stream + */ + function lastModified() + { + if (!empty($this->notices) && (count($this->notices) > 0)) { + return strtotime($this->notices[0]->created); + } + + return null; + } + + /** + * An entity tag for this stream + * + * Returns an Etag based on the action name, language, user ID, and + * timestamps of the first and last notice in the timeline + * + * @return string etag + */ + function etag() + { + if (!empty($this->notices) && (count($this->notices) > 0)) { + $last = count($this->notices) - 1; + + return '"' . implode( + ':', + array($this->arg('action'), + common_user_cache_hash($this->auth_user), + common_language(), + $this->user->id, + strtotime($this->notices[0]->created), + strtotime($this->notices[$last]->created)) + ) + . '"'; + } + + return null; + } + + function handlePost() + { + if (empty($this->auth_user) || + $this->auth_user->id != $this->user->id) { + // TRANS: Client error displayed trying to add a notice to another user's timeline. + $this->clientError(_('Only the user can add to their own timeline.')); + return; + } + + // Only handle posts for Atom + if ($this->format != 'atom') { + // TRANS: Client error displayed when using another format than AtomPub. + $this->clientError(_('Only accept AtomPub for Atom feeds.')); + return; + } + + $xml = trim(file_get_contents('php://input')); + if (empty($xml)) { + // TRANS: Client error displayed attempting to post an empty API notice. + $this->clientError(_('Atom post must not be empty.')); + } + + $old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE)); + $dom = new DOMDocument(); + $ok = $dom->loadXML($xml); + error_reporting($old); + if (!$ok) { + // TRANS: Client error displayed attempting to post an API that is not well-formed XML. + $this->clientError(_('Atom post must be well-formed XML.')); + } + + if ($dom->documentElement->namespaceURI != Activity::ATOM || + $dom->documentElement->localName != 'entry') { + // TRANS: Client error displayed when not using an Atom entry. + $this->clientError(_('Atom post must be an Atom entry.')); + return; + } + + $activity = new Activity($dom->documentElement); + + $saved = null; + + if (Event::handle('StartAtomPubNewActivity', array(&$activity, $this->user, &$saved))) { + if ($activity->verb != ActivityVerb::POST) { + // TRANS: Client error displayed when not using the POST verb. Do not translate POST. + $this->clientError(_('Can only handle POST activities.')); + return; + } + + $note = $activity->objects[0]; + + if (!in_array($note->type, array(ActivityObject::NOTE, + ActivityObject::BLOGENTRY, + ActivityObject::STATUS))) { + // TRANS: Client error displayed when using an unsupported activity object type. + // TRANS: %s is the unsupported activity object type. + $this->clientError(sprintf(_('Cannot handle activity object type "%s".'), + $note->type)); + return; + } + + $saved = $this->postNote($activity); + + Event::handle('EndAtomPubNewActivity', array($activity, $this->user, $saved)); + } + + if (!empty($saved)) { + header('HTTP/1.1 201 Created'); + header("Location: " . common_local_url('ApiStatusesShow', array('id' => $saved->id, + 'format' => 'atom'))); + $this->showSingleAtomStatus($saved); + } + } + + function postNote($activity) + { + $note = $activity->objects[0]; + + // Use summary as fallback for content + + if (!empty($note->content)) { + $sourceContent = $note->content; + } else if (!empty($note->summary)) { + $sourceContent = $note->summary; + } else if (!empty($note->title)) { + $sourceContent = $note->title; + } else { + // @fixme fetch from $sourceUrl? + // TRANS: Client error displayed when posting a notice without content through the API. + // TRANS: %d is the notice ID (number). + $this->clientError(sprintf(_('No content for notice %d.'), + $note->id)); + return; + } + + // Get (safe!) HTML and text versions of the content + + $rendered = $this->purify($sourceContent); + $content = html_entity_decode(strip_tags($rendered), ENT_QUOTES, 'UTF-8'); + + $shortened = $this->auth_user->shortenLinks($content); + + $options = array('is_local' => Notice::LOCAL_PUBLIC, + 'rendered' => $rendered, + 'replies' => array(), + 'groups' => array(), + 'tags' => array(), + 'urls' => array()); + + // accept remote URI (not necessarily a good idea) + + common_debug("Note ID is {$note->id}"); + + if (!empty($note->id)) { + $notice = Notice::staticGet('uri', trim($note->id)); + + if (!empty($notice)) { + // TRANS: Client error displayed when using another format than AtomPub. + // TRANS: %s is the notice URI. + $this->clientError(sprintf(_('Notice with URI "%s" already exists.'), + $note->id)); + return; + } + common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'"); + $options['uri'] = $note->id; + } + + // accept remote create time (also maybe not such a good idea) + + if (!empty($activity->time)) { + common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}"); + $options['created'] = common_sql_date($activity->time); + } + + // Check for optional attributes... + + if (!empty($activity->context)) { + + foreach ($activity->context->attention as $uri) { + + $profile = Profile::fromURI($uri); + + if (!empty($profile)) { + $options['replies'][] = $uri; + } else { + $group = User_group::staticGet('uri', $uri); + if (!empty($group)) { + $options['groups'][] = $group->id; + } else { + // @fixme: hook for discovery here + common_log(LOG_WARNING, sprintf('AtomPub post with unknown attention URI %s', $uri)); + } + } + } + + // Maintain direct reply associations + // @fixme what about conversation ID? + + if (!empty($activity->context->replyToID)) { + $orig = Notice::staticGet('uri', + $activity->context->replyToID); + if (!empty($orig)) { + $options['reply_to'] = $orig->id; + } + } + + $location = $activity->context->location; + + if ($location) { + $options['lat'] = $location->lat; + $options['lon'] = $location->lon; + if ($location->location_id) { + $options['location_ns'] = $location->location_ns; + $options['location_id'] = $location->location_id; + } + } + } + + // Atom categories <-> hashtags + + foreach ($activity->categories as $cat) { + if ($cat->term) { + $term = common_canonical_tag($cat->term); + if ($term) { + $options['tags'][] = $term; + } + } + } + + // Atom enclosures -> attachment URLs + foreach ($activity->enclosures as $href) { + // @fixme save these locally or....? + $options['urls'][] = $href; + } + + $saved = Notice::saveNew($this->user->id, + $content, + 'atompub', // TODO: deal with this + $options); + + return $saved; + } + + function purify($content) + { + require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php'; + + $config = array('safe' => 1, + 'deny_attribute' => 'id,style,on*'); + return htmLawed($content, $config); + } +} diff --git a/api-changes-1.1.1/classes/Notice.php b/api-changes-1.1.1/classes/Notice.php new file mode 100644 index 0000000..9f33ad9 --- /dev/null +++ b/api-changes-1.1.1/classes/Notice.php @@ -0,0 +1,2761 @@ +. + * + * @category Notices + * @package StatusNet + * @author Brenda Wallace + * @author Christopher Vollick + * @author CiaranG + * @author Craig Andrews + * @author Evan Prodromou + * @author Gina Haeussge + * @author Jeffery To + * @author Mike Cochrane + * @author Robin Millette + * @author Sarven Capadisli + * @author Tom Adams + * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org + * @license GNU Affero General Public License http://www.gnu.org/licenses/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Table Definition for notice + */ +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/* We keep 200 notices, the max number of notices available per API request, + * in the memcached cache. */ + +define('NOTICE_CACHE_WINDOW', CachingNoticeStream::CACHE_WINDOW); + +define('MAX_BOXCARS', 128); + +class Notice extends Managed_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'notice'; // table name + public $id; // int(4) primary_key not_null + public $profile_id; // int(4) multiple_key not_null + public $uri; // varchar(255) unique_key + public $content; // text + public $rendered; // text + public $url; // varchar(255) + public $created; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00 + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP + public $reply_to; // int(4) + public $is_local; // int(4) + public $source; // varchar(32) + public $conversation; // int(4) + public $lat; // decimal(10,7) + public $lon; // decimal(10,7) + public $location_id; // int(4) + public $location_ns; // int(4) + public $repeat_of; // int(4) + public $verb; // varchar(255) + public $object_type; // varchar(255) + public $scope; // int(4) + + /* Static get */ + function staticGet($k,$v=NULL) + { + return Memcached_DataObject::staticGet('Notice',$k,$v); + } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + public static function schemaDef() + { + $def = array( + 'fields' => array( + 'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'), + 'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'who made the update'), + 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'), + 'content' => array('type' => 'text', 'description' => 'update content', 'collate' => 'utf8_general_ci'), + 'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'), + 'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'), + 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), + 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), + 'reply_to' => array('type' => 'int', 'description' => 'notice replied to (usually a guess)'), + 'is_local' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'notice was generated by a user'), + 'source' => array('type' => 'varchar', 'length' => 32, 'description' => 'source of comment, like "web", "im", or "clientname"'), + 'conversation' => array('type' => 'int', 'description' => 'id of root notice in this conversation'), + 'lat' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'latitude'), + 'lon' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'longitude'), + 'location_id' => array('type' => 'int', 'description' => 'location id if possible'), + 'location_ns' => array('type' => 'int', 'description' => 'namespace for location'), + 'repeat_of' => array('type' => 'int', 'description' => 'notice this is a repeat of'), + 'object_type' => array('type' => 'varchar', 'length' => 255, 'description' => 'URI representing activity streams object type', 'default' => 'http://activitystrea.ms/schema/1.0/note'), + 'verb' => array('type' => 'varchar', 'length' => 255, 'description' => 'URI representing activity streams verb', 'default' => 'http://activitystrea.ms/schema/1.0/post'), + 'scope' => array('type' => 'int', + 'description' => 'bit map for distribution scope; 0 = everywhere; 1 = this server only; 2 = addressees; 4 = followers; null = default'), + ), + 'primary key' => array('id'), + 'unique keys' => array( + 'notice_uri_key' => array('uri'), + ), + 'foreign keys' => array( + 'notice_profile_id_fkey' => array('profile', array('profile_id' => 'id')), + 'notice_reply_to_fkey' => array('notice', array('reply_to' => 'id')), + 'notice_conversation_fkey' => array('conversation', array('conversation' => 'id')), # note... used to refer to notice.id + 'notice_repeat_of_fkey' => array('notice', array('repeat_of' => 'id')), # @fixme: what about repeats of deleted notices? + ), + 'indexes' => array( + 'notice_created_id_is_local_idx' => array('created', 'id', 'is_local'), + 'notice_profile_id_idx' => array('profile_id', 'created', 'id'), + 'notice_repeat_of_created_id_idx' => array('repeat_of', 'created', 'id'), + 'notice_conversation_created_id_idx' => array('conversation', 'created', 'id'), + 'notice_replyto_idx' => array('reply_to') + ) + ); + + if (common_config('search', 'type') == 'fulltext') { + $def['fulltext indexes'] = array('content' => array('content')); + } + + return $def; + } + + function multiGet($kc, $kvs, $skipNulls=true) + { + return Memcached_DataObject::multiGet('Notice', $kc, $kvs, $skipNulls); + } + + /* Notice types */ + const LOCAL_PUBLIC = 1; + const REMOTE = 0; + const LOCAL_NONPUBLIC = -1; + const GATEWAY = -2; + + const PUBLIC_SCOPE = 0; // Useful fake constant + const SITE_SCOPE = 1; + const ADDRESSEE_SCOPE = 2; + const GROUP_SCOPE = 4; + const FOLLOWER_SCOPE = 8; + + protected $_profile = -1; + + function getProfile() + { + if (is_int($this->_profile) && $this->_profile == -1) { + $this->_setProfile(Profile::staticGet('id', $this->profile_id)); + + if (empty($this->_profile)) { + // TRANS: Server exception thrown when a user profile for a notice cannot be found. + // TRANS: %1$d is a profile ID (number), %2$d is a notice ID (number). + throw new ServerException(sprintf(_('No such profile (%1$d) for notice (%2$d).'), $this->profile_id, $this->id)); + } + } + + return $this->_profile; + } + + function _setProfile($profile) + { + $this->_profile = $profile; + } + + function delete() + { + // For auditing purposes, save a record that the notice + // was deleted. + + // @fixme we have some cases where things get re-run and so the + // insert fails. + $deleted = Deleted_notice::staticGet('id', $this->id); + + if (!$deleted) { + $deleted = Deleted_notice::staticGet('uri', $this->uri); + } + + if (!$deleted) { + $deleted = new Deleted_notice(); + + $deleted->id = $this->id; + $deleted->profile_id = $this->profile_id; + $deleted->uri = $this->uri; + $deleted->created = $this->created; + $deleted->deleted = common_sql_now(); + + $deleted->insert(); + } + + if (Event::handle('NoticeDeleteRelated', array($this))) { + + // Clear related records + + $this->clearReplies(); + $this->clearRepeats(); + $this->clearFaves(); + $this->clearTags(); + $this->clearGroupInboxes(); + $this->clearFiles(); + + // NOTE: we don't clear inboxes + // NOTE: we don't clear queue items + } + + $result = parent::delete(); + + $this->blowOnDelete(); + return $result; + } + + /** + * Extract #hashtags from this notice's content and save them to the database. + */ + function saveTags() + { + /* extract all #hastags */ + $count = preg_match_all('/(?:^|\s)#([\pL\pN_\-\.]{1,64})/u', strtolower($this->content), $match); + if (!$count) { + return true; + } + + /* Add them to the database */ + return $this->saveKnownTags($match[1]); + } + + /** + * Record the given set of hash tags in the db for this notice. + * Given tag strings will be normalized and checked for dupes. + */ + function saveKnownTags($hashtags) + { + //turn each into their canonical tag + //this is needed to remove dupes before saving e.g. #hash.tag = #hashtag + for($i=0; $isaveTag($hashtag); + self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, $hashtag); + } + return true; + } + + /** + * Record a single hash tag as associated with this notice. + * Tag format and uniqueness must be validated by caller. + */ + function saveTag($hashtag) + { + $tag = new Notice_tag(); + $tag->notice_id = $this->id; + $tag->tag = $hashtag; + $tag->created = $this->created; + $id = $tag->insert(); + + if (!$id) { + // TRANS: Server exception. %s are the error details. + throw new ServerException(sprintf(_('Database error inserting hashtag: %s.'), + $last_error->message)); + return; + } + + // if it's saved, blow its cache + $tag->blowCache(false); + } + + /** + * Save a new notice and push it out to subscribers' inboxes. + * Poster's permissions are checked before sending. + * + * @param int $profile_id Profile ID of the poster + * @param string $content source message text; links may be shortened + * per current user's preference + * @param string $source source key ('web', 'api', etc) + * @param array $options Associative array of optional properties: + * string 'created' timestamp of notice; defaults to now + * int 'is_local' source/gateway ID, one of: + * Notice::LOCAL_PUBLIC - Local, ok to appear in public timeline + * Notice::REMOTE - Sent from a remote service; + * hide from public timeline but show in + * local "and friends" timelines + * Notice::LOCAL_NONPUBLIC - Local, but hide from public timeline + * Notice::GATEWAY - From another non-OStatus service; + * will not appear in public views + * float 'lat' decimal latitude for geolocation + * float 'lon' decimal longitude for geolocation + * int 'location_id' geoname identifier + * int 'location_ns' geoname namespace to interpret location_id + * int 'reply_to'; notice ID this is a reply to + * int 'repeat_of'; notice ID this is a repeat of + * string 'uri' unique ID for notice; defaults to local notice URL + * string 'url' permalink to notice; defaults to local notice URL + * string 'rendered' rendered HTML version of content + * array 'replies' list of profile URIs for reply delivery in + * place of extracting @-replies from content. + * array 'groups' list of group IDs to deliver to, in place of + * extracting ! tags from content + * array 'tags' list of hashtag strings to save with the notice + * in place of extracting # tags from content + * array 'urls' list of attached/referred URLs to save with the + * notice in place of extracting links from content + * boolean 'distribute' whether to distribute the notice, default true + * string 'object_type' URL of the associated object type (default ActivityObject::NOTE) + * string 'verb' URL of the associated verb (default ActivityVerb::POST) + * int 'scope' Scope bitmask; default to SITE_SCOPE on private sites, 0 otherwise + * + * @fixme tag override + * + * @return Notice + * @throws ClientException + */ + static function saveNew($profile_id, $content, $source, $options=null) { + $defaults = array('uri' => null, + 'url' => null, + 'reply_to' => null, + 'repeat_of' => null, + 'scope' => null, + 'distribute' => true, + 'object_type' => null, + 'verb' => null); + + if (!empty($options) && is_array($options)) { + $options = array_merge($defaults, $options); + extract($options); + } else { + extract($defaults); + } + + if (!isset($is_local)) { + $is_local = Notice::LOCAL_PUBLIC; + } + + $profile = Profile::staticGet('id', $profile_id); + $user = User::staticGet('id', $profile_id); + +// no shortening, only clientside +// if ($user) { +// // Use the local user's shortening preferences, if applicable. +// $final = $user->shortenLinks($content); +// } else { +// $final = common_shorten_links($content); +// } + + $final=$content; + + if (Notice::contentTooLong($final)) { + // TRANS: Client exception thrown if a notice contains too many characters. + throw new ClientException(_('Problem saving notice. Too long.')); + } + + if (empty($profile)) { + // TRANS: Client exception thrown when trying to save a notice for an unknown user. + throw new ClientException(_('Problem saving notice. Unknown user.')); + } + + if (common_config('throttle', 'enabled') && !Notice::checkEditThrottle($profile_id)) { + common_log(LOG_WARNING, 'Excessive posting by profile #' . $profile_id . '; throttled.'); + // TRANS: Client exception thrown when a user tries to post too many notices in a given time frame. + throw new ClientException(_('Too many notices too fast; take a breather '. + 'and post again in a few minutes.')); + } + + if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $final)) { + common_log(LOG_WARNING, 'Dupe posting by profile #' . $profile_id . '; throttled.'); + // TRANS: Client exception thrown when a user tries to post too many duplicate notices in a given time frame. + throw new ClientException(_('Too many duplicate messages too quickly;'. + ' take a breather and post again in a few minutes.')); + } + + if (!$profile->hasRight(Right::NEWNOTICE)) { + common_log(LOG_WARNING, "Attempted post from user disallowed to post: " . $profile->nickname); + + // TRANS: Client exception thrown when a user tries to post while being banned. + throw new ClientException(_('You are banned from posting notices on this site.'), 403); + } + + $notice = new Notice(); + $notice->profile_id = $profile_id; + + $autosource = common_config('public', 'autosource'); + + // Sandboxed are non-false, but not 1, either + + if (!$profile->hasRight(Right::PUBLICNOTICE) || + ($source && $autosource && in_array($source, $autosource))) { + $notice->is_local = Notice::LOCAL_NONPUBLIC; + } else { + $notice->is_local = $is_local; + } + + if (!empty($created)) { + $notice->created = $created; + } else { + $notice->created = common_sql_now(); + } + + $notice->content = $final; + + $notice->source = $source; + $notice->uri = $uri; + $notice->url = $url; + + // Get the groups here so we can figure out replies and such + + if (!isset($groups)) { + $groups = self::groupsFromText($notice->content, $profile); + } + + $reply = null; + + // Handle repeat case + + if (isset($repeat_of)) { + + // Check for a private one + + $repeat = Notice::staticGet('id', $repeat_of); + + if (empty($repeat)) { + // TRANS: Client exception thrown in notice when trying to repeat a missing or deleted notice. + throw new ClientException(_('Cannot repeat; original notice is missing or deleted.')); + } + + if ($profile->id == $repeat->profile_id) { + // TRANS: Client error displayed when trying to repeat an own notice. + throw new ClientException(_('You cannot repeat your own notice.')); + } + + if ($repeat->scope != Notice::SITE_SCOPE && + $repeat->scope != Notice::PUBLIC_SCOPE) { + // TRANS: Client error displayed when trying to repeat a non-public notice. + throw new ClientException(_('Cannot repeat a private notice.'), 403); + } + + if (!$repeat->inScope($profile)) { + // The generic checks above should cover this, but let's be sure! + // TRANS: Client error displayed when trying to repeat a notice you cannot access. + throw new ClientException(_('Cannot repeat a notice you cannot read.'), 403); + } + + if ($profile->hasRepeated($repeat->id)) { + // TRANS: Client error displayed when trying to repeat an already repeated notice. + throw new ClientException(_('You already repeated that notice.')); + } + + $notice->repeat_of = $repeat_of; + } else { + $reply = self::getReplyTo($reply_to, $profile_id, $source, $final); + + if (!empty($reply)) { + + if (!$reply->inScope($profile)) { + // TRANS: Client error displayed when trying to reply to a notice a the target has no access to. + // TRANS: %1$s is a user nickname, %2$d is a notice ID (number). + throw new ClientException(sprintf(_('%1$s has no access to notice %2$d.'), + $profile->nickname, $reply->id), 403); + } + + $notice->reply_to = $reply->id; + $notice->conversation = $reply->conversation; + + // If the original is private to a group, and notice has no group specified, + // make it to the same group(s) + + if (empty($groups) && ($reply->scope | Notice::GROUP_SCOPE)) { + $groups = array(); + $replyGroups = $reply->getGroups(); + foreach ($replyGroups as $group) { + if ($profile->isMember($group)) { + $groups[] = $group->id; + } + } + } + + // Scope set below + } + } + + if (!empty($lat) && !empty($lon)) { + $notice->lat = $lat; + $notice->lon = $lon; + } + + if (!empty($location_ns) && !empty($location_id)) { + $notice->location_id = $location_id; + $notice->location_ns = $location_ns; + } + + if (!empty($rendered)) { + $notice->rendered = $rendered; + } else { + $notice->rendered = common_render_content($final, $notice); + } + + if (empty($verb)) { + if (!empty($notice->repeat_of)) { + $notice->verb = ActivityVerb::SHARE; + $notice->object_type = ActivityObject::ACTIVITY; + } else { + $notice->verb = ActivityVerb::POST; + } + } else { + $notice->verb = $verb; + } + + if (empty($object_type)) { + $notice->object_type = (empty($notice->reply_to)) ? ActivityObject::NOTE : ActivityObject::COMMENT; + } else { + $notice->object_type = $object_type; + } + + if (is_null($scope)) { // 0 is a valid value + if (!empty($reply)) { + $notice->scope = $reply->scope; + } else { + $notice->scope = self::defaultScope(); + } + } else { + $notice->scope = $scope; + } + + // For private streams + + $user = $profile->getUser(); + + if (!empty($user)) { + if ($user->private_stream && + ($notice->scope == Notice::PUBLIC_SCOPE || + $notice->scope == Notice::SITE_SCOPE)) { + $notice->scope |= Notice::FOLLOWER_SCOPE; + } + } + + // Force the scope for private groups + + foreach ($groups as $groupId) { + $group = User_group::staticGet('id', $groupId); + if (!empty($group)) { + if ($group->force_scope) { + $notice->scope |= Notice::GROUP_SCOPE; + break; + } + } + } + + if (Event::handle('StartNoticeSave', array(&$notice))) { + + // XXX: some of these functions write to the DB + + $id = $notice->insert(); + + if (!$id) { + common_log_db_error($notice, 'INSERT', __FILE__); + // TRANS: Server exception thrown when a notice cannot be saved. + throw new ServerException(_('Problem saving notice.')); + } + + // Update ID-dependent columns: URI, conversation + + $orig = clone($notice); + + $changed = false; + + if (empty($uri)) { + $notice->uri = common_notice_uri($notice); + $changed = true; + } + + // If it's not part of a conversation, it's + // the beginning of a new conversation. + + if (empty($notice->conversation)) { + $conv = Conversation::create(); + $notice->conversation = $conv->id; + $changed = true; + } + + if ($changed) { + if (!$notice->update($orig)) { + common_log_db_error($notice, 'UPDATE', __FILE__); + // TRANS: Server exception thrown when a notice cannot be updated. + throw new ServerException(_('Problem saving notice.')); + } + } + + } + + // Clear the cache for subscribed users, so they'll update at next request + // XXX: someone clever could prepend instead of clearing the cache + + $notice->blowOnInsert(); + + // Save per-notice metadata... + + if (isset($replies)) { + $notice->saveKnownReplies($replies); + } else { + $notice->saveReplies(); + } + + if (isset($tags)) { + $notice->saveKnownTags($tags); + } else { + $notice->saveTags(); + } + + // Note: groups may save tags, so must be run after tags are saved + // to avoid errors on duplicates. + // Note: groups should always be set. + + $notice->saveKnownGroups($groups); + + if (isset($urls)) { + $notice->saveKnownUrls($urls); + } else { + $notice->saveUrls(); + } + + if ($distribute) { + // Prepare inbox delivery, may be queued to background. + $notice->distribute(); + } + + return $notice; + } + + function blowOnInsert($conversation = false) + { + $this->blowStream('profile:notice_ids:%d', $this->profile_id); + + if ($this->isPublic()) { + $this->blowStream('public'); + } + + self::blow('notice:list-ids:conversation:%s', $this->conversation); + self::blow('conversation:notice_count:%d', $this->conversation); + + if (!empty($this->repeat_of)) { + // XXX: we should probably only use one of these + $this->blowStream('notice:repeats:%d', $this->repeat_of); + self::blow('notice:list-ids:repeat_of:%d', $this->repeat_of); + } + + $original = Notice::staticGet('id', $this->repeat_of); + + if (!empty($original)) { + $originalUser = User::staticGet('id', $original->profile_id); + if (!empty($originalUser)) { + $this->blowStream('user:repeats_of_me:%d', $originalUser->id); + } + } + + $profile = Profile::staticGet($this->profile_id); + + if (!empty($profile)) { + $profile->blowNoticeCount(); + } + + $ptags = $this->getProfileTags(); + foreach ($ptags as $ptag) { + $ptag->blowNoticeStreamCache(); + } + } + + /** + * Clear cache entries related to this notice at delete time. + * Necessary to avoid breaking paging on public, profile timelines. + */ + function blowOnDelete() + { + $this->blowOnInsert(); + + self::blow('profile:notice_ids:%d;last', $this->profile_id); + + if ($this->isPublic()) { + self::blow('public;last'); + } + + self::blow('fave:by_notice', $this->id); + + if ($this->conversation) { + // In case we're the first, will need to calc a new root. + self::blow('notice:conversation_root:%d', $this->conversation); + } + + $ptags = $this->getProfileTags(); + foreach ($ptags as $ptag) { + $ptag->blowNoticeStreamCache(true); + } + } + + function blowStream() + { + $c = self::memcache(); + + if (empty($c)) { + return false; + } + + $args = func_get_args(); + + $format = array_shift($args); + + $keyPart = vsprintf($format, $args); + + $cacheKey = Cache::key($keyPart); + + $c->delete($cacheKey); + + // delete the "last" stream, too, if this notice is + // older than the top of that stream + + $lastKey = $cacheKey.';last'; + + $lastStr = $c->get($lastKey); + + if ($lastStr !== false) { + $window = explode(',', $lastStr); + $lastID = $window[0]; + $lastNotice = Notice::staticGet('id', $lastID); + if (empty($lastNotice) // just weird + || strtotime($lastNotice->created) >= strtotime($this->created)) { + $c->delete($lastKey); + } + } + } + + /** save all urls in the notice to the db + * + * follow redirects and save all available file information + * (mimetype, date, size, oembed, etc.) + * + * @return void + */ + function saveUrls() { + if (common_config('attachments', 'process_links')) { + common_replace_urls_callback($this->content, array($this, 'saveUrl'), $this->id); + } + } + + /** + * Save the given URLs as related links/attachments to the db + * + * follow redirects and save all available file information + * (mimetype, date, size, oembed, etc.) + * + * @return void + */ + function saveKnownUrls($urls) + { + if (common_config('attachments', 'process_links')) { + // @fixme validation? + foreach (array_unique($urls) as $url) { + File::processNew($url, $this->id); + } + } + } + + /** + * @private callback + */ + function saveUrl($url, $notice_id) { + File::processNew($url, $notice_id); + } + + static function checkDupes($profile_id, $content) { + $profile = Profile::staticGet($profile_id); + if (empty($profile)) { + return false; + } + $notice = $profile->getNotices(0, CachingNoticeStream::CACHE_WINDOW); + if (!empty($notice)) { + $last = 0; + while ($notice->fetch()) { + if (time() - strtotime($notice->created) >= common_config('site', 'dupelimit')) { + return true; + } else if ($notice->content == $content) { + return false; + } + } + } + // If we get here, oldest item in cache window is not + // old enough for dupe limit; do direct check against DB + $notice = new Notice(); + $notice->profile_id = $profile_id; + $notice->content = $content; + $threshold = common_sql_date(time() - common_config('site', 'dupelimit')); + $notice->whereAdd(sprintf("created > '%s'", $notice->escape($threshold))); + + $cnt = $notice->count(); + return ($cnt == 0); + } + + static function checkEditThrottle($profile_id) { + $profile = Profile::staticGet($profile_id); + if (empty($profile)) { + return false; + } + // Get the Nth notice + $notice = $profile->getNotices(common_config('throttle', 'count') - 1, 1); + if ($notice && $notice->fetch()) { + // If the Nth notice was posted less than timespan seconds ago + if (time() - strtotime($notice->created) <= common_config('throttle', 'timespan')) { + // Then we throttle + return false; + } + } + // Either not N notices in the stream, OR the Nth was not posted within timespan seconds + return true; + } + + protected $_attachments = -1; + + function attachments() { + + if ($this->_attachments != -1) { + return $this->_attachments; + } + + $f2ps = Memcached_DataObject::listGet('File_to_post', 'post_id', array($this->id)); + + $ids = array(); + + foreach ($f2ps[$this->id] as $f2p) { + $ids[] = $f2p->file_id; + } + + $files = Memcached_DataObject::multiGet('File', 'id', $ids); + + $this->_attachments = $files->fetchAll(); + + return $this->_attachments; + } + + function _setAttachments($attachments) + { + $this->_attachments = $attachments; + } + + function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0) + { + $stream = new PublicNoticeStream(); + return $stream->getNotices($offset, $limit, $since_id, $max_id); + } + + + function conversationStream($id, $offset=0, $limit=20, $since_id=0, $max_id=0) + { + $stream = new ConversationNoticeStream($id); + + return $stream->getNotices($offset, $limit, $since_id, $max_id); + } + + /** + * Is this notice part of an active conversation? + * + * @return boolean true if other messages exist in the same + * conversation, false if this is the only one + */ + function hasConversation() + { + if (!empty($this->conversation)) { + $conversation = Notice::conversationStream( + $this->conversation, + 1, + 1 + ); + + if ($conversation->N > 0) { + return true; + } + } + return false; + } + + /** + * Grab the earliest notice from this conversation. + * + * @return Notice or null + */ + function conversationRoot($profile=-1) + { + // XXX: can this happen? + + if (empty($this->conversation)) { + return null; + } + + // Get the current profile if not specified + + if (is_int($profile) && $profile == -1) { + $profile = Profile::current(); + } + + // If this notice is out of scope, no root for you! + + if (!$this->inScope($profile)) { + return null; + } + + // If this isn't a reply to anything, then it's its own + // root. + + if (empty($this->reply_to)) { + return $this; + } + + if (is_null($profile)) { + $keypart = sprintf('notice:conversation_root:%d:null', $this->id); + } else { + $keypart = sprintf('notice:conversation_root:%d:%d', + $this->id, + $profile->id); + } + + $root = self::cacheGet($keypart); + + if ($root !== false && $root->inScope($profile)) { + return $root; + } else { + $last = $this; + + do { + $parent = $last->getOriginal(); + if (!empty($parent) && $parent->inScope($profile)) { + $last = $parent; + continue; + } else { + $root = $last; + break; + } + } while (!empty($parent)); + + self::cacheSet($keypart, $root); + } + + return $root; + } + + /** + * Pull up a full list of local recipients who will be getting + * this notice in their inbox. Results will be cached, so don't + * change the input data wily-nilly! + * + * @param array $groups optional list of Group objects; + * if left empty, will be loaded from group_inbox records + * @param array $recipient optional list of reply profile ids + * if left empty, will be loaded from reply records + * @return array associating recipient user IDs with an inbox source constant + */ + function whoGets($groups=null, $recipients=null) + { + $c = self::memcache(); + + if (!empty($c)) { + $ni = $c->get(Cache::key('notice:who_gets:'.$this->id)); + if ($ni !== false) { + return $ni; + } + } + + if (is_null($groups)) { + $groups = $this->getGroups(); + } + + if (is_null($recipients)) { + $recipients = $this->getReplies(); + } + + $users = $this->getSubscribedUsers(); + $ptags = $this->getProfileTags(); + + // FIXME: kind of ignoring 'transitional'... + // we'll probably stop supporting inboxless mode + // in 0.9.x + + $ni = array(); + + // Give plugins a chance to add folks in at start... + if (Event::handle('StartNoticeWhoGets', array($this, &$ni))) { + + foreach ($users as $id) { + $ni[$id] = NOTICE_INBOX_SOURCE_SUB; + } + + foreach ($groups as $group) { + $users = $group->getUserMembers(); + foreach ($users as $id) { + if (!array_key_exists($id, $ni)) { + $ni[$id] = NOTICE_INBOX_SOURCE_GROUP; + } + } + } + + foreach ($ptags as $ptag) { + $users = $ptag->getUserSubscribers(); + foreach ($users as $id) { + if (!array_key_exists($id, $ni)) { + $ni[$id] = NOTICE_INBOX_SOURCE_PROFILE_TAG; + } + } + } + + foreach ($recipients as $recipient) { + if (!array_key_exists($recipient, $ni)) { + $ni[$recipient] = NOTICE_INBOX_SOURCE_REPLY; + } + } + + // Exclude any deleted, non-local, or blocking recipients. + $profile = $this->getProfile(); + $originalProfile = null; + if ($this->repeat_of) { + // Check blocks against the original notice's poster as well. + $original = Notice::staticGet('id', $this->repeat_of); + if ($original) { + $originalProfile = $original->getProfile(); + } + } + + foreach ($ni as $id => $source) { + $user = User::staticGet('id', $id); + if (empty($user) || $user->hasBlocked($profile) || + ($originalProfile && $user->hasBlocked($originalProfile))) { + unset($ni[$id]); + } + } + + // Give plugins a chance to filter out... + Event::handle('EndNoticeWhoGets', array($this, &$ni)); + } + + if (!empty($c)) { + // XXX: pack this data better + $c->set(Cache::key('notice:who_gets:'.$this->id), $ni); + } + + return $ni; + } + + /** + * Adds this notice to the inboxes of each local user who should receive + * it, based on author subscriptions, group memberships, and @-replies. + * + * Warning: running a second time currently will make items appear + * multiple times in users' inboxes. + * + * @fixme make more robust against errors + * @fixme break up massive deliveries to smaller background tasks + * + * @param array $groups optional list of Group objects; + * if left empty, will be loaded from group_inbox records + * @param array $recipient optional list of reply profile ids + * if left empty, will be loaded from reply records + */ + function addToInboxes($groups=null, $recipients=null) + { + $ni = $this->whoGets($groups, $recipients); + + $ids = array_keys($ni); + + // We remove the author (if they're a local user), + // since we'll have already done this in distribute() + + $i = array_search($this->profile_id, $ids); + + if ($i !== false) { + unset($ids[$i]); + } + + // Bulk insert + + Inbox::bulkInsert($this->id, $ids); + + return; + } + + function getSubscribedUsers() + { + $user = new User(); + + if(common_config('db','quote_identifiers')) + $user_table = '"user"'; + else $user_table = 'user'; + + $qry = + 'SELECT id ' . + 'FROM '. $user_table .' JOIN subscription '. + 'ON '. $user_table .'.id = subscription.subscriber ' . + 'WHERE subscription.subscribed = %d '; + + $user->query(sprintf($qry, $this->profile_id)); + + $ids = array(); + + while ($user->fetch()) { + $ids[] = $user->id; + } + + $user->free(); + + return $ids; + } + + function getProfileTags() + { + $profile = $this->getProfile(); + $list = $profile->getOtherTags($profile); + $ptags = array(); + + while($list->fetch()) { + $ptags[] = clone($list); + } + + return $ptags; + } + + /** + * Record this notice to the given group inboxes for delivery. + * Overrides the regular parsing of !group markup. + * + * @param string $group_ids + * @fixme might prefer URIs as identifiers, as for replies? + * best with generalizations on user_group to support + * remote groups better. + */ + function saveKnownGroups($group_ids) + { + if (!is_array($group_ids)) { + // TRANS: Server exception thrown when no array is provided to the method saveKnownGroups(). + throw new ServerException(_('Bad type provided to saveKnownGroups.')); + } + + $groups = array(); + foreach (array_unique($group_ids) as $id) { + $group = User_group::staticGet('id', $id); + if ($group) { + common_log(LOG_ERR, "Local delivery to group id $id, $group->nickname"); + $result = $this->addToGroupInbox($group); + if (!$result) { + common_log_db_error($gi, 'INSERT', __FILE__); + } + + if (common_config('group', 'addtag')) { + // we automatically add a tag for every group name, too + + $tag = Notice_tag::pkeyGet(array('tag' => common_canonical_tag($group->nickname), + 'notice_id' => $this->id)); + + if (is_null($tag)) { + $this->saveTag($group->nickname); + } + } + + $groups[] = clone($group); + } else { + common_log(LOG_ERR, "Local delivery to group id $id skipped, doesn't exist"); + } + } + + return $groups; + } + + /** + * Parse !group delivery and record targets into group_inbox. + * @return array of Group objects + */ + function saveGroups() + { + // Don't save groups for repeats + + if (!empty($this->repeat_of)) { + return array(); + } + + $profile = $this->getProfile(); + + $groups = self::groupsFromText($this->content, $profile); + + /* Add them to the database */ + + foreach ($groups as $group) { + /* XXX: remote groups. */ + + if (empty($group)) { + continue; + } + + + if ($profile->isMember($group)) { + + $result = $this->addToGroupInbox($group); + + if (!$result) { + common_log_db_error($gi, 'INSERT', __FILE__); + } + + $groups[] = clone($group); + } + } + + return $groups; + } + + function addToGroupInbox($group) + { + $gi = Group_inbox::pkeyGet(array('group_id' => $group->id, + 'notice_id' => $this->id)); + + if (empty($gi)) { + + $gi = new Group_inbox(); + + $gi->group_id = $group->id; + $gi->notice_id = $this->id; + $gi->created = $this->created; + + $result = $gi->insert(); + + if (!$result) { + common_log_db_error($gi, 'INSERT', __FILE__); + // TRANS: Server exception thrown when an update for a group inbox fails. + throw new ServerException(_('Problem saving group inbox.')); + } + + self::blow('user_group:notice_ids:%d', $gi->group_id); + } + + return true; + } + + /** + * Save reply records indicating that this notice needs to be + * delivered to the local users with the given URIs. + * + * Since this is expected to be used when saving foreign-sourced + * messages, we won't deliver to any remote targets as that's the + * source service's responsibility. + * + * Mail notifications etc will be handled later. + * + * @param array of unique identifier URIs for recipients + */ + function saveKnownReplies($uris) + { + if (empty($uris)) { + return; + } + + $sender = Profile::staticGet($this->profile_id); + + foreach (array_unique($uris) as $uri) { + + $profile = Profile::fromURI($uri); + + if (empty($profile)) { + common_log(LOG_WARNING, "Unable to determine profile for URI '$uri'"); + continue; + } + + if ($profile->hasBlocked($sender)) { + common_log(LOG_INFO, "Not saving reply to profile {$profile->id} ($uri) from sender {$sender->id} because of a block."); + continue; + } + + $this->saveReply($profile->id); + self::blow('reply:stream:%d', $profile->id); + } + + return; + } + + /** + * Pull @-replies from this message's content in StatusNet markup format + * and save reply records indicating that this message needs to be + * delivered to those users. + * + * Mail notifications to local profiles will be sent later. + * + * @return array of integer profile IDs + */ + + function saveReplies() + { + // Don't save reply data for repeats + + if (!empty($this->repeat_of)) { + return array(); + } + + $sender = Profile::staticGet($this->profile_id); + + $replied = array(); + + // If it's a reply, save for the replied-to author + + if (!empty($this->reply_to)) { + $original = $this->getOriginal(); + if (!empty($original)) { // that'd be weird + $author = $original->getProfile(); + if (!empty($author)) { + $this->saveReply($author->id); + $replied[$author->id] = 1; + self::blow('reply:stream:%d', $author->id); + } + } + } + + // @todo ideally this parser information would only + // be calculated once. + + $mentions = common_find_mentions($this->content, $this); + + // store replied only for first @ (what user/notice what the reply directed, + // we assume first @ is it) + + foreach ($mentions as $mention) { + + foreach ($mention['mentioned'] as $mentioned) { + + // skip if they're already covered + + if (!empty($replied[$mentioned->id])) { + continue; + } + + // Don't save replies from blocked profile to local user + + $mentioned_user = User::staticGet('id', $mentioned->id); + if (!empty($mentioned_user) && $mentioned_user->hasBlocked($sender)) { + continue; + } + + $this->saveReply($mentioned->id); + $replied[$mentioned->id] = 1; + self::blow('reply:stream:%d', $mentioned->id); + } + } + + $recipientIds = array_keys($replied); + + return $recipientIds; + } + + function saveReply($profileId) + { + $reply = new Reply(); + + $reply->notice_id = $this->id; + $reply->profile_id = $profileId; + $reply->modified = $this->created; + + $reply->insert(); + + return $reply; + } + + protected $_replies = -1; + + /** + * Pull the complete list of @-reply targets for this notice. + * + * @return array of integer profile ids + */ + function getReplies() + { + if ($this->_replies != -1) { + return $this->_replies; + } + + $replyMap = Memcached_DataObject::listGet('Reply', 'notice_id', array($this->id)); + + $ids = array(); + + foreach ($replyMap[$this->id] as $reply) { + $ids[] = $reply->profile_id; + } + + $this->_replies = $ids; + + return $ids; + } + + function _setReplies($replies) + { + $this->_replies = $replies; + } + + /** + * Pull the complete list of @-reply targets for this notice. + * + * @return array of Profiles + */ + function getReplyProfiles() + { + $ids = $this->getReplies(); + + $profiles = Profile::multiGet('id', $ids); + + return $profiles->fetchAll(); + } + + /** + * Send e-mail notifications to local @-reply targets. + * + * Replies must already have been saved; this is expected to be run + * from the distrib queue handler. + */ + function sendReplyNotifications() + { + // Don't send reply notifications for repeats + + if (!empty($this->repeat_of)) { + return array(); + } + + $recipientIds = $this->getReplies(); + + foreach ($recipientIds as $recipientId) { + $user = User::staticGet('id', $recipientId); + if (!empty($user)) { + mail_notify_attn($user, $this); + } + } + } + + /** + * Pull list of groups this notice needs to be delivered to, + * as previously recorded by saveGroups() or saveKnownGroups(). + * + * @return array of Group objects + */ + + protected $_groups = -1; + + function getGroups() + { + // Don't save groups for repeats + + if (!empty($this->repeat_of)) { + return array(); + } + + if ($this->_groups != -1) + { + return $this->_groups; + } + + $gis = Memcached_DataObject::listGet('Group_inbox', 'notice_id', array($this->id)); + + $ids = array(); + + foreach ($gis[$this->id] as $gi) + { + $ids[] = $gi->group_id; + } + + $groups = User_group::multiGet('id', $ids); + + $this->_groups = $groups->fetchAll(); + + return $this->_groups; + } + + function _setGroups($groups) + { + $this->_groups = $groups; + } + + /** + * Convert a notice into an activity for export. + * + * @param User $cur Current user + * + * @return Activity activity object representing this Notice. + */ + + function asActivity($cur) + { + $act = self::cacheGet(Cache::codeKey('notice:as-activity:'.$this->id)); + + if (!empty($act)) { + return $act; + } + $act = new Activity(); + + if (Event::handle('StartNoticeAsActivity', array($this, &$act))) { + + $act->id = TagURI::mint("post:".$this->id); + $act->time = strtotime($this->created); + $act->content = common_xml_safe_str($this->rendered); + + $profile = $this->getProfile(); + + $act->actor = ActivityObject::fromProfile($profile); + $act->actor->extra[] = $profile->profileInfo($cur); + + $act->verb = $this->verb; + + if ($this->repeat_of) { + $repeated = Notice::staticGet('id', $this->repeat_of); + if (!empty($repeated)) { + $act->objects[] = $repeated->asActivity($cur); + } + } else { + $act->objects[] = ActivityObject::fromNotice($this); + } + + // XXX: should this be handled by default processing for object entry? + + // Categories + + $tags = $this->getTags(); + + foreach ($tags as $tag) { + $cat = new AtomCategory(); + $cat->term = $tag; + + $act->categories[] = $cat; + } + + // Enclosures + // XXX: use Atom Media and/or File activity objects instead + + $attachments = $this->attachments(); + + foreach ($attachments as $attachment) { + // Save local attachments + if (!empty($attachment->filename)) { + $act->attachments[] = ActivityObject::fromFile($attachment); + } + } + + $ctx = new ActivityContext(); + + if (!empty($this->reply_to)) { + $reply = Notice::staticGet('id', $this->reply_to); + if (!empty($reply)) { + $ctx->replyToID = $reply->uri; + $ctx->replyToUrl = $reply->bestUrl(); + } + } + + $ctx->location = $this->getLocation(); + + $conv = null; + + if (!empty($this->conversation)) { + $conv = Conversation::staticGet('id', $this->conversation); + if (!empty($conv)) { + $ctx->conversation = $conv->uri; + } + } + + $reply_ids = $this->getReplies(); + + foreach ($reply_ids as $id) { + $rprofile = Profile::staticGet('id', $id); + if (!empty($rprofile)) { + $ctx->attention[] = $rprofile->getUri(); + $ctx->attentionType[$rprofile->getUri()] = ActivityObject::PERSON; + } + } + + $groups = $this->getGroups(); + + foreach ($groups as $group) { + $ctx->attention[] = $group->getUri(); + $ctx->attentionType[$group->getUri()] = ActivityObject::GROUP; + } + + switch ($this->scope) { + case Notice::PUBLIC_SCOPE: + $ctx->attention[] = "http://activityschema.org/collection/public"; + $ctx->attentionType["http://activityschema.org/collection/public"] = ActivityObject::COLLECTION; + break; + case Notice::FOLLOWER_SCOPE: + $surl = common_local_url("subscribers", array('nickname' => $profile->nickname)); + $ctx->attention[] = $surl; + $ctx->attentionType[$surl] = ActivityObject::COLLECTION; + break; + } + + // XXX: deprecated; use ActivityVerb::SHARE instead + + $repeat = null; + + if (!empty($this->repeat_of)) { + $repeat = Notice::staticGet('id', $this->repeat_of); + if (!empty($repeat)) { + $ctx->forwardID = $repeat->uri; + $ctx->forwardUrl = $repeat->bestUrl(); + } + } + + $act->context = $ctx; + + $source = $this->getSource(); + + if ($source) { + $act->generator = ActivityObject::fromNoticeSource($source); + } + + // Source + + $atom_feed = $profile->getAtomFeed(); + + if (!empty($atom_feed)) { + + $act->source = new ActivitySource(); + + // XXX: we should store the actual feed ID + + $act->source->id = $atom_feed; + + // XXX: we should store the actual feed title + + $act->source->title = $profile->getBestName(); + + $act->source->links['alternate'] = $profile->profileurl; + $act->source->links['self'] = $atom_feed; + + $act->source->icon = $profile->avatarUrl(AVATAR_PROFILE_SIZE); + + $notice = $profile->getCurrentNotice(); + + if (!empty($notice)) { + $act->source->updated = self::utcDate($notice->created); + } + + $user = User::staticGet('id', $profile->id); + + if (!empty($user)) { + $act->source->links['license'] = common_config('license', 'url'); + } + } + + if ($this->isLocal()) { + $act->selfLink = common_local_url('ApiStatusesShow', array('id' => $this->id, + 'format' => 'atom')); + $act->editLink = $act->selfLink; + } + + Event::handle('EndNoticeAsActivity', array($this, &$act)); + } + + self::cacheSet(Cache::codeKey('notice:as-activity:'.$this->id), $act); + + return $act; + } + + // This has gotten way too long. Needs to be sliced up into functional bits + // or ideally exported to a utility class. + + function asAtomEntry($namespace=false, + $source=false, + $author=true, + $cur=null) + { + $act = $this->asActivity($cur); + $act->extra[] = $this->noticeInfo($cur); + return $act->asString($namespace, $author, $source); + } + + /** + * Extra notice info for atom entries + * + * Clients use some extra notice info in the atom stream. + * This gives it to them. + * + * @param User $cur Current user + * + * @return array representation of element + */ + + function noticeInfo($cur) + { + // local notice ID (useful to clients for ordering) + + $noticeInfoAttr = array('local_id' => $this->id); + + // notice source + + $ns = $this->getSource(); + + if (!empty($ns)) { + $noticeInfoAttr['source'] = $ns->code; + if (!empty($ns->url)) { + $noticeInfoAttr['source_link'] = $ns->url; + if (!empty($ns->name)) { + $noticeInfoAttr['source'] = '' + . htmlspecialchars($ns->name) + . ''; + } + } + } + + // favorite and repeated + + if (!empty($cur)) { + $noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false"; + $cp = $cur->getProfile(); + $noticeInfoAttr['repeated'] = ($cp->hasRepeated($this->id)) ? "true" : "false"; + } + + if (!empty($this->repeat_of)) { + $noticeInfoAttr['repeat_of'] = $this->repeat_of; + } + + return array('statusnet:notice_info', $noticeInfoAttr, null); + } + + /** + * Returns an XML string fragment with a reference to a notice as an + * Activity Streams noun object with the given element type. + * + * Assumes that 'activity' namespace has been previously defined. + * + * @param string $element one of 'subject', 'object', 'target' + * @return string + */ + + function asActivityNoun($element) + { + $noun = ActivityObject::fromNotice($this); + return $noun->asString('activity:' . $element); + } + + function bestUrl() + { + if (!empty($this->url)) { + return $this->url; + } else if (!empty($this->uri) && preg_match('/^https?:/', $this->uri)) { + return $this->uri; + } else { + return common_local_url('shownotice', + array('notice' => $this->id)); + } + } + + + /** + * Determine which notice, if any, a new notice is in reply to. + * + * For conversation tracking, we try to see where this notice fits + * in the tree. Rough algorithm is: + * + * if (reply_to is set and valid) { + * return reply_to; + * } else if ((source not API or Web) and (content starts with "T NAME" or "@name ")) { + * return ID of last notice by initial @name in content; + * } + * + * Note that all @nickname instances will still be used to save "reply" records, + * so the notice shows up in the mentioned users' "replies" tab. + * + * @param integer $reply_to ID passed in by Web or API + * @param integer $profile_id ID of author + * @param string $source Source tag, like 'web' or 'gwibber' + * @param string $content Final notice content + * + * @return integer ID of replied-to notice, or null for not a reply. + */ + + static function getReplyTo($reply_to, $profile_id, $source, $content) + { + static $lb = array('xmpp', 'mail', 'sms', 'omb'); + + // If $reply_to is specified, we check that it exists, and then + // return it if it does + + if (!empty($reply_to)) { + $reply_notice = Notice::staticGet('id', $reply_to); + if (!empty($reply_notice)) { + return $reply_notice; + } + } + + // If it's not a "low bandwidth" source (one where you can't set + // a reply_to argument), we return. This is mostly web and API + // clients. + + if (!in_array($source, $lb)) { + return null; + } + + // Is there an initial @ or T? + + if (preg_match('/^T ([A-Z0-9]{1,64}) /', $content, $match) || + preg_match('/^@([a-z0-9]{1,64})\s+/', $content, $match)) { + $nickname = common_canonical_nickname($match[1]); + } else { + return null; + } + + // Figure out who that is. + + $sender = Profile::staticGet('id', $profile_id); + if (empty($sender)) { + return null; + } + + $recipient = common_relative_profile($sender, $nickname, common_sql_now()); + + if (empty($recipient)) { + return null; + } + + // Get their last notice + + $last = $recipient->getCurrentNotice(); + + if (!empty($last)) { + return $last; + } + + return null; + } + + static function maxContent() + { + $contentlimit = common_config('notice', 'contentlimit'); + // null => use global limit (distinct from 0!) + if (is_null($contentlimit)) { + $contentlimit = common_config('site', 'textlimit'); + } + return $contentlimit; + } + + static function contentTooLong($content) + { + $contentlimit = self::maxContent(); + return ($contentlimit > 0 && !empty($content) && (mb_strlen($content) > $contentlimit)); + } + + function getLocation() + { + $location = null; + + if (!empty($this->location_id) && !empty($this->location_ns)) { + $location = Location::fromId($this->location_id, $this->location_ns); + } + + if (is_null($location)) { // no ID, or Location::fromId() failed + if (!empty($this->lat) && !empty($this->lon)) { + $location = Location::fromLatLon($this->lat, $this->lon); + } + } + + return $location; + } + + /** + * Convenience function for posting a repeat of an existing message. + * + * @param int $repeater_id: profile ID of user doing the repeat + * @param string $source: posting source key, eg 'web', 'api', etc + * @return Notice + * + * @throws Exception on failure or permission problems + */ + function repeat($repeater_id, $source) + { + $author = Profile::staticGet('id', $this->profile_id); + + // TRANS: Message used to repeat a notice. RT is the abbreviation of 'retweet'. + // TRANS: %1$s is the repeated user's name, %2$s is the repeated notice. + $content = sprintf(_('RT @%1$s %2$s'), + $author->nickname, + $this->content); + + $maxlen = common_config('site', 'textlimit'); + if ($maxlen > 0 && mb_strlen($content) > $maxlen) { + // Web interface and current Twitter API clients will + // pull the original notice's text, but some older + // clients and RSS/Atom feeds will see this trimmed text. + // + // Unfortunately this is likely to lose tags or URLs + // at the end of long notices. + $content = mb_substr($content, 0, $maxlen - 4) . ' ...'; + } + + // Scope is same as this one's + + return self::saveNew($repeater_id, + $content, + $source, + array('repeat_of' => $this->id, + 'scope' => $this->scope)); + } + + // These are supposed to be in chron order! + + function repeatStream($limit=100) + { + $cache = Cache::instance(); + + if (empty($cache)) { + $ids = $this->_repeatStreamDirect($limit); + } else { + $idstr = $cache->get(Cache::key('notice:repeats:'.$this->id)); + if ($idstr !== false) { + if (empty($idstr)) { + $ids = array(); + } else { + $ids = explode(',', $idstr); + } + } else { + $ids = $this->_repeatStreamDirect(100); + $cache->set(Cache::key('notice:repeats:'.$this->id), implode(',', $ids)); + } + if ($limit < 100) { + // We do a max of 100, so slice down to limit + $ids = array_slice($ids, 0, $limit); + } + } + + return NoticeStream::getStreamByIds($ids); + } + + function _repeatStreamDirect($limit) + { + $notice = new Notice(); + + $notice->selectAdd(); // clears it + $notice->selectAdd('id'); + + $notice->repeat_of = $this->id; + + $notice->orderBy('created, id'); // NB: asc! + + if (!is_null($limit)) { + $notice->limit(0, $limit); + } + + return $notice->fetchAll('id'); + } + + function locationOptions($lat, $lon, $location_id, $location_ns, $profile = null) + { + $options = array(); + + if (!empty($location_id) && !empty($location_ns)) { + $options['location_id'] = $location_id; + $options['location_ns'] = $location_ns; + + $location = Location::fromId($location_id, $location_ns); + + if (!empty($location)) { + $options['lat'] = $location->lat; + $options['lon'] = $location->lon; + } + + } else if (!empty($lat) && !empty($lon)) { + $options['lat'] = $lat; + $options['lon'] = $lon; + + $location = Location::fromLatLon($lat, $lon); + + if (!empty($location)) { + $options['location_id'] = $location->location_id; + $options['location_ns'] = $location->location_ns; + } + } else if (!empty($profile)) { + if (isset($profile->lat) && isset($profile->lon)) { + $options['lat'] = $profile->lat; + $options['lon'] = $profile->lon; + } + + if (isset($profile->location_id) && isset($profile->location_ns)) { + $options['location_id'] = $profile->location_id; + $options['location_ns'] = $profile->location_ns; + } + } + + return $options; + } + + function clearReplies() + { + $replyNotice = new Notice(); + $replyNotice->reply_to = $this->id; + + //Null any notices that are replies to this notice + + if ($replyNotice->find()) { + while ($replyNotice->fetch()) { + $orig = clone($replyNotice); + $replyNotice->reply_to = null; + $replyNotice->update($orig); + } + } + + // Reply records + + $reply = new Reply(); + $reply->notice_id = $this->id; + + if ($reply->find()) { + while($reply->fetch()) { + self::blow('reply:stream:%d', $reply->profile_id); + $reply->delete(); + } + } + + $reply->free(); + } + + function clearFiles() + { + $f2p = new File_to_post(); + + $f2p->post_id = $this->id; + + if ($f2p->find()) { + while ($f2p->fetch()) { + $f2p->delete(); + } + } + // FIXME: decide whether to delete File objects + // ...and related (actual) files + } + + function clearRepeats() + { + $repeatNotice = new Notice(); + $repeatNotice->repeat_of = $this->id; + + //Null any notices that are repeats of this notice + + if ($repeatNotice->find()) { + while ($repeatNotice->fetch()) { + $orig = clone($repeatNotice); + $repeatNotice->repeat_of = null; + $repeatNotice->update($orig); + } + } + } + + function clearFaves() + { + $fave = new Fave(); + $fave->notice_id = $this->id; + + if ($fave->find()) { + while ($fave->fetch()) { + self::blow('fave:ids_by_user_own:%d', $fave->user_id); + self::blow('fave:ids_by_user_own:%d;last', $fave->user_id); + self::blow('fave:ids_by_user:%d', $fave->user_id); + self::blow('fave:ids_by_user:%d;last', $fave->user_id); + $fave->delete(); + } + } + + $fave->free(); + } + + function clearTags() + { + $tag = new Notice_tag(); + $tag->notice_id = $this->id; + + if ($tag->find()) { + while ($tag->fetch()) { + self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, Cache::keyize($tag->tag)); + self::blow('profile:notice_ids_tagged:%d:%s;last', $this->profile_id, Cache::keyize($tag->tag)); + self::blow('notice_tag:notice_ids:%s', Cache::keyize($tag->tag)); + self::blow('notice_tag:notice_ids:%s;last', Cache::keyize($tag->tag)); + $tag->delete(); + } + } + + $tag->free(); + } + + function clearGroupInboxes() + { + $gi = new Group_inbox(); + + $gi->notice_id = $this->id; + + if ($gi->find()) { + while ($gi->fetch()) { + self::blow('user_group:notice_ids:%d', $gi->group_id); + $gi->delete(); + } + } + + $gi->free(); + } + + function distribute() + { + // We always insert for the author so they don't + // have to wait + Event::handle('StartNoticeDistribute', array($this)); + + $user = User::staticGet('id', $this->profile_id); + if (!empty($user)) { + Inbox::insertNotice($user->id, $this->id); + } + + if (common_config('queue', 'inboxes')) { + // If there's a failure, we want to _force_ + // distribution at this point. + try { + $qm = QueueManager::get(); + $qm->enqueue($this, 'distrib'); + } catch (Exception $e) { + // If the exception isn't transient, this + // may throw more exceptions as DQH does + // its own enqueueing. So, we ignore them! + try { + $handler = new DistribQueueHandler(); + $handler->handle($this); + } catch (Exception $e) { + common_log(LOG_ERR, "emergency redistribution resulted in " . $e->getMessage()); + } + // Re-throw so somebody smarter can handle it. + throw $e; + } + } else { + $handler = new DistribQueueHandler(); + $handler->handle($this); + } + } + + function insert() + { + $result = parent::insert(); + + if ($result) { + // Profile::hasRepeated() abuses pkeyGet(), so we + // have to clear manually + if (!empty($this->repeat_of)) { + $c = self::memcache(); + if (!empty($c)) { + $ck = self::multicacheKey('Notice', + array('profile_id' => $this->profile_id, + 'repeat_of' => $this->repeat_of)); + $c->delete($ck); + } + } + } + + return $result; + } + + /** + * Get the source of the notice + * + * @return Notice_source $ns A notice source object. 'code' is the only attribute + * guaranteed to be populated. + */ + function getSource() + { + $ns = new Notice_source(); + if (!empty($this->source)) { + switch ($this->source) { + case 'web': + case 'xmpp': + case 'mail': + case 'omb': + case 'system': + case 'api': + $ns->code = $this->source; + break; + default: + $ns = Notice_source::staticGet($this->source); + if (!$ns) { + $ns = new Notice_source(); + $ns->code = $this->source; + $app = Oauth_application::staticGet('name', $this->source); + if ($app) { + $ns->name = $app->name; + $ns->url = $app->source_url; + } + } + break; + } + } + return $ns; + } + + /** + * Determine whether the notice was locally created + * + * @return boolean locality + */ + + public function isLocal() + { + return ($this->is_local == Notice::LOCAL_PUBLIC || + $this->is_local == Notice::LOCAL_NONPUBLIC); + } + + /** + * Get the list of hash tags saved with this notice. + * + * @return array of strings + */ + public function getTags() + { + $tags = array(); + + $keypart = sprintf('notice:tags:%d', $this->id); + + $tagstr = self::cacheGet($keypart); + + if ($tagstr !== false) { + $tags = explode(',', $tagstr); + } else { + $tag = new Notice_tag(); + $tag->notice_id = $this->id; + if ($tag->find()) { + while ($tag->fetch()) { + $tags[] = $tag->tag; + } + } + self::cacheSet($keypart, implode(',', $tags)); + } + + return $tags; + } + + static private function utcDate($dt) + { + $dateStr = date('d F Y H:i:s', strtotime($dt)); + $d = new DateTime($dateStr, new DateTimeZone('UTC')); + return $d->format(DATE_W3C); + } + + /** + * Look up the creation timestamp for a given notice ID, even + * if it's been deleted. + * + * @param int $id + * @return mixed string recorded creation timestamp, or false if can't be found + */ + public static function getAsTimestamp($id) + { + if (!$id) { + return false; + } + + $notice = Notice::staticGet('id', $id); + if ($notice) { + return $notice->created; + } + + $deleted = Deleted_notice::staticGet('id', $id); + if ($deleted) { + return $deleted->created; + } + + return false; + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a since_id + * parameter, matching notices posted after the given one (exclusive). + * + * If the referenced notice can't be found, will return false. + * + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function whereSinceId($id, $idField='id', $createdField='created') + { + $since = Notice::getAsTimestamp($id); + if ($since) { + return sprintf("($createdField = '%s' and $idField > %d) or ($createdField > '%s')", $since, $id, $since); + } + return false; + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a since_id + * parameter, matching notices posted after the given one (exclusive), and + * if necessary add it to the data object's query. + * + * @param DB_DataObject $obj + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function addWhereSinceId(DB_DataObject $obj, $id, $idField='id', $createdField='created') + { + $since = self::whereSinceId($id, $idField, $createdField); + if ($since) { + $obj->whereAdd($since); + } + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a max_id + * parameter, matching notices posted before the given one (inclusive). + * + * If the referenced notice can't be found, will return false. + * + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function whereMaxId($id, $idField='id', $createdField='created') + { + $max = Notice::getAsTimestamp($id); + if ($max) { + return sprintf("($createdField < '%s') or ($createdField = '%s' and $idField <= %d)", $max, $max, $id); + } + return false; + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a max_id + * parameter, matching notices posted before the given one (inclusive), and + * if necessary add it to the data object's query. + * + * @param DB_DataObject $obj + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function addWhereMaxId(DB_DataObject $obj, $id, $idField='id', $createdField='created') + { + $max = self::whereMaxId($id, $idField, $createdField); + if ($max) { + $obj->whereAdd($max); + } + } + + function isPublic() + { + if (common_config('public', 'localonly')) { + return ($this->is_local == Notice::LOCAL_PUBLIC); + } else { + return (($this->is_local != Notice::LOCAL_NONPUBLIC) && + ($this->is_local != Notice::GATEWAY)); + } + } + + /** + * Check that the given profile is allowed to read, respond to, or otherwise + * act on this notice. + * + * The $scope member is a bitmask of scopes, representing a logical AND of the + * scope requirement. So, 0x03 (Notice::ADDRESSEE_SCOPE | Notice::SITE_SCOPE) means + * "only visible to people who are mentioned in the notice AND are users on this site." + * Users on the site who are not mentioned in the notice will not be able to see the + * notice. + * + * @param Profile $profile The profile to check; pass null to check for public/unauthenticated users. + * + * @return boolean whether the profile is in the notice's scope + */ + function inScope($profile) + { + if (is_null($profile)) { + $keypart = sprintf('notice:in-scope-for:%d:null', $this->id); + } else { + $keypart = sprintf('notice:in-scope-for:%d:%d', $this->id, $profile->id); + } + + $result = self::cacheGet($keypart); + + if ($result === false) { + $bResult = false; + if (Event::handle('StartNoticeInScope', array($this, $profile, &$bResult))) { + $bResult = $this->_inScope($profile); + Event::handle('EndNoticeInScope', array($this, $profile, &$bResult)); + } + $result = ($bResult) ? 1 : 0; + self::cacheSet($keypart, $result, 0, 300); + } + + return ($result == 1) ? true : false; + } + + protected function _inScope($profile) + { + if (!is_null($this->scope)) { + $scope = $this->scope; + } else { + $scope = self::defaultScope(); + } + + // If there's no scope, anyone (even anon) is in scope. + + if ($scope == 0) { // Not private + + return !$this->isHiddenSpam($profile); + + } else { // Private, somehow + + // If there's scope, anon cannot be in scope + + if (empty($profile)) { + return false; + } + + // Author is always in scope + + if ($this->profile_id == $profile->id) { + return true; + } + + // Only for users on this site + + if ($scope & Notice::SITE_SCOPE) { + $user = $profile->getUser(); + if (empty($user)) { + return false; + } + } + + // Only for users mentioned in the notice + + if ($scope & Notice::ADDRESSEE_SCOPE) { + + $repl = Reply::pkeyGet(array('notice_id' => $this->id, + 'profile_id' => $profile->id)); + + if (empty($repl)) { + return false; + } + } + + // Only for members of the given group + + if ($scope & Notice::GROUP_SCOPE) { + + // XXX: just query for the single membership + + $groups = $this->getGroups(); + + $foundOne = false; + + foreach ($groups as $group) { + if ($profile->isMember($group)) { + $foundOne = true; + break; + } + } + + if (!$foundOne) { + return false; + } + } + + // Only for followers of the author + + $author = null; + + if ($scope & Notice::FOLLOWER_SCOPE) { + + try { + $author = $this->getProfile(); + } catch (Exception $e) { + return false; + } + + if (!Subscription::exists($profile, $author)) { + return false; + } + } + + return !$this->isHiddenSpam($profile); + } + } + + function isHiddenSpam($profile) { + + // Hide posts by silenced users from everyone but moderators. + + if (common_config('notice', 'hidespam')) { + + try { + $author = $this->getProfile(); + } catch(Exception $e) { + // If we can't get an author, keep it hidden. + // XXX: technically not spam, but, whatever. + return true; + } + + if ($author->hasRole(Profile_role::SILENCED)) { + if (empty($profile) || (($profile->id !== $author->id) && (!$profile->hasRight(Right::REVIEWSPAM)))) { + return true; + } + } + } + + return false; + } + + static function groupsFromText($text, $profile) + { + $groups = array(); + + /* extract all !group */ + $count = preg_match_all('/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/', + strtolower($text), + $match); + + if (!$count) { + return $groups; + } + + foreach (array_unique($match[1]) as $nickname) { + $group = User_group::getForNickname($nickname, $profile); + if (!empty($group) && $profile->isMember($group)) { + $groups[] = $group->id; + } + } + + return $groups; + } + + protected $_original = -1; + + function getOriginal() + { + if (is_int($this->_original) && $this->_original == -1) { + if (empty($this->reply_to)) { + $this->_original = null; + } else { + $this->_original = Notice::staticGet('id', $this->reply_to); + } + } + return $this->_original; + } + + /** + * Magic function called at serialize() time. + * + * We use this to drop a couple process-specific references + * from DB_DataObject which can cause trouble in future + * processes. + * + * @return array of variable names to include in serialization. + */ + + function __sleep() + { + $vars = parent::__sleep(); + $skip = array('_original', '_profile', '_groups', '_attachments', '_faves', '_replies', '_repeats'); + return array_diff($vars, $skip); + } + + static function defaultScope() + { + $scope = common_config('notice', 'defaultscope'); + if (is_null($scope)) { + if (common_config('site', 'private')) { + $scope = 1; + } else { + $scope = 0; + } + } + return $scope; + } + + static function fillProfiles($notices) + { + $map = self::getProfiles($notices); + + foreach ($notices as $notice) { + if (array_key_exists($notice->profile_id, $map)) { + $notice->_setProfile($map[$notice->profile_id]); + } + } + + return array_values($map); + } + + static function getProfiles(&$notices) + { + $ids = array(); + foreach ($notices as $notice) { + $ids[] = $notice->profile_id; + } + + $ids = array_unique($ids); + + return Memcached_DataObject::pivotGet('Profile', 'id', $ids); + } + + static function fillGroups(&$notices) + { + $ids = self::_idsOf($notices); + + $gis = Memcached_DataObject::listGet('Group_inbox', 'notice_id', $ids); + + $gids = array(); + + foreach ($gis as $id => $gi) + { + foreach ($gi as $g) + { + $gids[] = $g->group_id; + } + } + + $gids = array_unique($gids); + + $group = Memcached_DataObject::pivotGet('User_group', 'id', $gids); + + foreach ($notices as $notice) + { + $grps = array(); + $gi = $gis[$notice->id]; + foreach ($gi as $g) { + $grps[] = $group[$g->group_id]; + } + $notice->_setGroups($grps); + } + } + + static function _idsOf(&$notices) + { + $ids = array(); + foreach ($notices as $notice) { + $ids[] = $notice->id; + } + $ids = array_unique($ids); + return $ids; + } + + static function fillAttachments(&$notices) + { + $ids = self::_idsOf($notices); + + $f2pMap = Memcached_DataObject::listGet('File_to_post', 'post_id', $ids); + + $fileIds = array(); + + foreach ($f2pMap as $noticeId => $f2ps) { + foreach ($f2ps as $f2p) { + $fileIds[] = $f2p->file_id; + } + } + + $fileIds = array_unique($fileIds); + + $fileMap = Memcached_DataObject::pivotGet('File', 'id', $fileIds); + + foreach ($notices as $notice) + { + $files = array(); + $f2ps = $f2pMap[$notice->id]; + foreach ($f2ps as $f2p) { + $files[] = $fileMap[$f2p->file_id]; + } + $notice->_setAttachments($files); + } + } + + protected $_faves; + + /** + * All faves of this notice + * + * @return array Array of Fave objects + */ + + function getFaves() + { + if (isset($this->_faves) && is_array($this->_faves)) { + return $this->_faves; + } + $faveMap = Memcached_DataObject::listGet('Fave', 'notice_id', array($this->id)); + $this->_faves = $faveMap[$this->id]; + return $this->_faves; + } + + function _setFaves($faves) + { + $this->_faves = $faves; + } + + static function fillFaves(&$notices) + { + $ids = self::_idsOf($notices); + $faveMap = Memcached_DataObject::listGet('Fave', 'notice_id', $ids); + $cnt = 0; + $faved = array(); + foreach ($faveMap as $id => $faves) { + $cnt += count($faves); + if (count($faves) > 0) { + $faved[] = $id; + } + } + foreach ($notices as $notice) { + $faves = $faveMap[$notice->id]; + $notice->_setFaves($faves); + } + } + + static function fillReplies(&$notices) + { + $ids = self::_idsOf($notices); + $replyMap = Memcached_DataObject::listGet('Reply', 'notice_id', $ids); + foreach ($notices as $notice) { + $replies = $replyMap[$notice->id]; + $ids = array(); + foreach ($replies as $reply) { + $ids[] = $reply->profile_id; + } + $notice->_setReplies($ids); + } + } + + protected $_repeats; + + function getRepeats() + { + if (isset($this->_repeats) && is_array($this->_repeats)) { + return $this->_repeats; + } + $repeatMap = Memcached_DataObject::listGet('Notice', 'repeat_of', array($this->id)); + $this->_repeats = $repeatMap[$this->id]; + return $this->_repeats; + } + + function _setRepeats($repeats) + { + $this->_repeats = $repeats; + } + + static function fillRepeats(&$notices) + { + $ids = self::_idsOf($notices); + $repeatMap = Memcached_DataObject::listGet('Notice', 'repeat_of', $ids); + foreach ($notices as $notice) { + $repeats = $repeatMap[$notice->id]; + $notice->_setRepeats($repeats); + } + } +} diff --git a/api-changes-1.1.1/lib/apiaction.php b/api-changes-1.1.1/lib/apiaction.php new file mode 100644 index 0000000..350441b --- /dev/null +++ b/api-changes-1.1.1/lib/apiaction.php @@ -0,0 +1,1684 @@ +. + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author Jeffery To + * @author Toby Inkster + * @author Zach Copley + * @copyright 2009-2010 StatusNet, Inc. + * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +/* External API usage documentation. Please update when you change how the API works. */ + +/*! @mainpage StatusNet REST API + + @section Introduction + + Some explanatory text about the API would be nice. + + @section API Methods + + @subsection timelinesmethods_sec Timeline Methods + + @li @ref publictimeline + @li @ref friendstimeline + + @subsection statusmethods_sec Status Methods + + @li @ref statusesupdate + + @subsection usermethods_sec User Methods + + @subsection directmessagemethods_sec Direct Message Methods + + @subsection friendshipmethods_sec Friendship Methods + + @subsection socialgraphmethods_sec Social Graph Methods + + @subsection accountmethods_sec Account Methods + + @subsection favoritesmethods_sec Favorites Methods + + @subsection blockmethods_sec Block Methods + + @subsection oauthmethods_sec OAuth Methods + + @subsection helpmethods_sec Help Methods + + @subsection groupmethods_sec Group Methods + + @page apiroot API Root + + The URLs for methods referred to in this API documentation are + relative to the StatusNet API root. The API root is determined by the + site's @b server and @b path variables, which are generally specified + in config.php. For example: + + @code + $config['site']['server'] = 'example.org'; + $config['site']['path'] = 'statusnet' + @endcode + + The pattern for a site's API root is: @c protocol://server/path/api E.g: + + @c http://example.org/statusnet/api + + The @b path can be empty. In that case the API root would simply be: + + @c http://example.org/api + +*/ + +if (!defined('STATUSNET')) { + exit(1); +} + +class ApiValidationException extends Exception { } + +/** + * Contains most of the Twitter-compatible API output functions. + * + * @category API + * @package StatusNet + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author Jeffery To + * @author Toby Inkster + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ +class ApiAction extends Action +{ + const READ_ONLY = 1; + const READ_WRITE = 2; + + var $format = null; + var $user = null; + var $auth_user = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $source = null; + var $callback = null; + + var $access = self::READ_ONLY; // read (default) or read-write + + static $reserved_sources = array('web', 'omb', 'ostatus', 'mail', 'xmpp', 'api'); + + /** + * Initialization. + * + * @param array $args Web and URL arguments + * + * @return boolean false if user doesn't exist + */ + function prepare($args) + { + StatusNet::setApi(true); // reduce exception reports to aid in debugging + parent::prepare($args); + + $this->format = $this->arg('format'); + $this->callback = $this->arg('callback'); + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + + if ($this->arg('since')) { + header('X-StatusNet-Warning: since parameter is disabled; use since_id'); + } + + $this->source = $this->trimmed('source'); + + if (empty($this->source) || in_array($this->source, self::$reserved_sources)) { + $this->source = 'api'; + } + + return true; + } + + /** + * Handle a request + * + * @param array $args Arguments from $_REQUEST + * + * @return void + */ + function handle($args) + { + header('Access-Control-Allow-Origin: *'); + parent::handle($args); + } + + /** + * Overrides XMLOutputter::element to write booleans as strings (true|false). + * See that method's documentation for more info. + * + * @param string $tag Element type or tagname + * @param array $attrs Array of element attributes, as + * key-value pairs + * @param string $content string content of the element + * + * @return void + */ + function element($tag, $attrs=null, $content=null) + { + if (is_bool($content)) { + $content = ($content ? 'true' : 'false'); + } + + return parent::element($tag, $attrs, $content); + } + + function twitterUserArray($profile, $get_notice=false) + { + $twitter_user = array(); + + $user = $profile->getUser(); + + $twitter_user['id'] = intval($profile->id); + $twitter_user['name'] = $profile->getBestName(); + $twitter_user['screen_name'] = $profile->nickname; + $twitter_user['location'] = ($profile->location) ? $profile->location : null; + $twitter_user['description'] = ($profile->bio) ? $profile->bio : null; + + $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); + $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_STREAM_SIZE); + $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); + $twitter_user['profile_image_url_profile_size'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_PROFILE_SIZE); + $avatar = $profile->getOriginalAvatar(); + $twitter_user['profile_image_url_original'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_PROFILE_SIZE); + + $groups = $profile->getGroups(); + $groups_count = 0; while($groups->fetch()) $groups_count++; + $twitter_user['groups_count'] = $groups_count; + + $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null; + $twitter_user['protected'] = (!empty($user) && $user->private_stream) ? true : false; + $twitter_user['followers_count'] = $profile->subscriberCount(); + + // Note: some profiles don't have an associated user + + $twitter_user['friends_count'] = $profile->subscriptionCount(); + + $twitter_user['created_at'] = $this->dateTwitter($profile->created); + + $twitter_user['favourites_count'] = $profile->faveCount(); // British spelling! + + $timezone = 'UTC'; + + if (!empty($user) && $user->timezone) { + $timezone = $user->timezone; + } + + $t = new DateTime; + $t->setTimezone(new DateTimeZone($timezone)); + + $twitter_user['utc_offset'] = $t->format('Z'); + $twitter_user['time_zone'] = $timezone; + $twitter_user['statuses_count'] = $profile->noticeCount(); + + // Is the requesting user following this user? + $twitter_user['following'] = false; + $twitter_user['statusnet_blocking'] = false; + $twitter_user['notifications'] = false; + + if (isset($this->auth_user)) { + + $twitter_user['following'] = $this->auth_user->isSubscribed($profile); + $twitter_user['statusnet_blocking'] = $this->auth_user->hasBlocked($profile); + + // Notifications on? + $sub = Subscription::pkeyGet(array('subscriber' => + $this->auth_user->id, + 'subscribed' => $profile->id)); + + if ($sub) { + $twitter_user['notifications'] = ($sub->jabber || $sub->sms); + } + } + + if ($get_notice) { + $notice = $profile->getCurrentNotice(); + if ($notice) { + // don't get user! + $twitter_user['status'] = $this->twitterStatusArray($notice, false); + } + } + + // StatusNet-specific + + $twitter_user['statusnet_profile_url'] = $profile->profileurl; + + return $twitter_user; + } + + function twitterStatusArray($notice, $include_user=true) + { + $base = $this->twitterSimpleStatusArray($notice, $include_user); + + if (!empty($notice->repeat_of)) { + $original = Notice::staticGet('id', $notice->repeat_of); + if (!empty($original)) { + $original_array = $this->twitterSimpleStatusArray($original, $include_user); + $base['retweeted_status'] = $original_array; + } + } + + return $base; + } + + function twitterSimpleStatusArray($notice, $include_user=true) + { + $profile = $notice->getProfile(); + + $twitter_status = array(); + $twitter_status['text'] = $notice->content; + $twitter_status['truncated'] = false; # Not possible on StatusNet + $twitter_status['created_at'] = $this->dateTwitter($notice->created); + $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ? + intval($notice->reply_to) : null; + + $source = null; + + $ns = $notice->getSource(); + if ($ns) { + if (!empty($ns->name) && !empty($ns->url)) { + $source = '' + . htmlspecialchars($ns->name) + . ''; + } else { + $source = $ns->code; + } + } + + $twitter_status['source'] = $source; + $twitter_status['id'] = intval($notice->id); + $twitter_status['uri'] = $notice->uri; + + $replier_profile = null; + + if ($notice->reply_to) { + $reply = Notice::staticGet(intval($notice->reply_to)); + if ($reply) { + $replier_profile = $reply->getProfile(); + } + } + + $twitter_status['in_reply_to_user_id'] = + ($replier_profile) ? intval($replier_profile->id) : null; + $twitter_status['in_reply_to_screen_name'] = + ($replier_profile) ? $replier_profile->nickname : null; + + if (isset($notice->lat) && isset($notice->lon)) { + // This is the format that GeoJSON expects stuff to be in + $twitter_status['geo'] = array('type' => 'Point', + 'coordinates' => array((float) $notice->lat, + (float) $notice->lon)); + } else { + $twitter_status['geo'] = null; + } + + if (isset($this->auth_user)) { + $this_profile = $this->auth_user->getProfile(); + $twitter_status['favorited'] = $this->auth_user->hasFave($notice); + $twitter_status['repeated'] = $this_profile->hasRepeated($notice->id); + } else { + $twitter_status['favorited'] = false; + $twitter_status['repeated'] = false; + } + + // Enclosures + $attachments = $notice->attachments(); + + if (!empty($attachments)) { + + $twitter_status['attachments'] = array(); + + foreach ($attachments as $attachment) { + $enclosure_o=$attachment->getEnclosure(); + if ($enclosure_o) { + $enclosure = array(); + $enclosure['url'] = $enclosure_o->url; + $enclosure['mimetype'] = $enclosure_o->mimetype; + $enclosure['size'] = $enclosure_o->size; + $twitter_status['attachments'][] = $enclosure; + } + } + } + + if ($include_user && $profile) { + // Don't get notice (recursive!) + $twitter_user = $this->twitterUserArray($profile, false); + $twitter_status['user'] = $twitter_user; + } + + // StatusNet-specific + + $twitter_status['statusnet_html'] = $notice->rendered; + $twitter_status['statusnet_conversation_id'] = intval($notice->conversation); + + return $twitter_status; + } + + function twitterGroupArray($group) + { + $twitter_group = array(); + + $twitter_group['id'] = intval($group->id); + $twitter_group['url'] = $group->permalink(); + $twitter_group['nickname'] = $group->nickname; + $twitter_group['fullname'] = $group->fullname; + + if (isset($this->auth_user)) { + $twitter_group['member'] = $this->auth_user->isMember($group); + $twitter_group['blocked'] = Group_block::isBlocked( + $group, + $this->auth_user->getProfile() + ); + } + + $admins = $group->getAdmins(); + $admin_count = 0; while($admins->fetch()) $admin_count++; + $twitter_group['admin_count'] = $admin_count; + $twitter_group['member_count'] = $group->getMemberCount(); + $twitter_group['original_logo'] = $group->original_logo; + $twitter_group['homepage_logo'] = $group->homepage_logo; + $twitter_group['stream_logo'] = $group->stream_logo; + $twitter_group['mini_logo'] = $group->mini_logo; + $twitter_group['homepage'] = $group->homepage; + $twitter_group['description'] = $group->description; + $twitter_group['location'] = $group->location; + $twitter_group['created'] = $this->dateTwitter($group->created); + $twitter_group['modified'] = $this->dateTwitter($group->modified); + + return $twitter_group; + } + + function twitterRssGroupArray($group) + { + $entry = array(); + $entry['content']=$group->description; + $entry['title']=$group->nickname; + $entry['link']=$group->permalink(); + $entry['published']=common_date_iso8601($group->created); + $entry['updated']==common_date_iso8601($group->modified); + $taguribase = common_config('integration', 'groupuri'); + $entry['id'] = "group:$groupuribase:$entry[link]"; + + $entry['description'] = $entry['content']; + $entry['pubDate'] = common_date_rfc2822($group->created); + $entry['guid'] = $entry['link']; + + return $entry; + } + + function twitterListArray($list) + { + $profile = Profile::staticGet('id', $list->tagger); + + $twitter_list = array(); + $twitter_list['id'] = $list->id; + $twitter_list['name'] = $list->tag; + $twitter_list['full_name'] = '@'.$profile->nickname.'/'.$list->tag;; + $twitter_list['slug'] = $list->tag; + $twitter_list['description'] = $list->description; + $twitter_list['subscriber_count'] = $list->subscriberCount(); + $twitter_list['member_count'] = $list->taggedCount(); + $twitter_list['uri'] = $list->getUri(); + + if (isset($this->auth_user)) { + $twitter_list['following'] = $list->hasSubscriber($this->auth_user); + } else { + $twitter_list['following'] = false; + } + + $twitter_list['mode'] = ($list->private) ? 'private' : 'public'; + $twitter_list['user'] = $this->twitterUserArray($profile, false); + + return $twitter_list; + } + + function twitterRssEntryArray($notice) + { + $entry = array(); + + if (Event::handle('StartRssEntryArray', array($notice, &$entry))) { + $profile = $notice->getProfile(); + + // We trim() to avoid extraneous whitespace in the output + + $entry['content'] = common_xml_safe_str(trim($notice->rendered)); + $entry['title'] = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content)); + $entry['link'] = common_local_url('shownotice', array('notice' => $notice->id)); + $entry['published'] = common_date_iso8601($notice->created); + + $taguribase = TagURI::base(); + $entry['id'] = "tag:$taguribase:$entry[link]"; + + $entry['updated'] = $entry['published']; + $entry['author'] = $profile->getBestName(); + + // Enclosures + $attachments = $notice->attachments(); + $enclosures = array(); + + foreach ($attachments as $attachment) { + $enclosure_o=$attachment->getEnclosure(); + if ($enclosure_o) { + $enclosure = array(); + $enclosure['url'] = $enclosure_o->url; + $enclosure['mimetype'] = $enclosure_o->mimetype; + $enclosure['size'] = $enclosure_o->size; + $enclosures[] = $enclosure; + } + } + + if (!empty($enclosures)) { + $entry['enclosures'] = $enclosures; + } + + // Tags/Categories + $tag = new Notice_tag(); + $tag->notice_id = $notice->id; + if ($tag->find()) { + $entry['tags']=array(); + while ($tag->fetch()) { + $entry['tags'][]=$tag->tag; + } + } + $tag->free(); + + // RSS Item specific + $entry['description'] = $entry['content']; + $entry['pubDate'] = common_date_rfc2822($notice->created); + $entry['guid'] = $entry['link']; + + if (isset($notice->lat) && isset($notice->lon)) { + // This is the format that GeoJSON expects stuff to be in. + // showGeoRSS() below uses it for XML output, so we reuse it + $entry['geo'] = array('type' => 'Point', + 'coordinates' => array((float) $notice->lat, + (float) $notice->lon)); + } else { + $entry['geo'] = null; + } + + Event::handle('EndRssEntryArray', array($notice, &$entry)); + } + + return $entry; + } + + function twitterRelationshipArray($source, $target) + { + $relationship = array(); + + $relationship['source'] = + $this->relationshipDetailsArray($source, $target); + $relationship['target'] = + $this->relationshipDetailsArray($target, $source); + + return array('relationship' => $relationship); + } + + function relationshipDetailsArray($source, $target) + { + $details = array(); + + $details['screen_name'] = $source->nickname; + $details['followed_by'] = $target->isSubscribed($source); + $details['following'] = $source->isSubscribed($target); + + $notifications = false; + + if ($source->isSubscribed($target)) { + $sub = Subscription::pkeyGet(array('subscriber' => + $source->id, 'subscribed' => $target->id)); + + if (!empty($sub)) { + $notifications = ($sub->jabber || $sub->sms); + } + } + + $details['notifications_enabled'] = $notifications; + $details['blocking'] = $source->hasBlocked($target); + $details['id'] = intval($source->id); + + return $details; + } + + function showTwitterXmlRelationship($relationship) + { + $this->elementStart('relationship'); + + foreach($relationship as $element => $value) { + if ($element == 'source' || $element == 'target') { + $this->elementStart($element); + $this->showXmlRelationshipDetails($value); + $this->elementEnd($element); + } + } + + $this->elementEnd('relationship'); + } + + function showXmlRelationshipDetails($details) + { + foreach($details as $element => $value) { + $this->element($element, null, $value); + } + } + + function showTwitterXmlStatus($twitter_status, $tag='status', $namespaces=false) + { + $attrs = array(); + if ($namespaces) { + $attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/'; + } + $this->elementStart($tag, $attrs); + foreach($twitter_status as $element => $value) { + switch ($element) { + case 'user': + $this->showTwitterXmlUser($twitter_status['user']); + break; + case 'text': + $this->element($element, null, common_xml_safe_str($value)); + break; + case 'attachments': + $this->showXmlAttachments($twitter_status['attachments']); + break; + case 'geo': + $this->showGeoXML($value); + break; + case 'retweeted_status': + $this->showTwitterXmlStatus($value, 'retweeted_status'); + break; + default: + if (strncmp($element, 'statusnet_', 10) == 0) { + $this->element('statusnet:'.substr($element, 10), null, $value); + } else { + $this->element($element, null, $value); + } + } + } + $this->elementEnd($tag); + } + + function showTwitterXmlGroup($twitter_group) + { + $this->elementStart('group'); + foreach($twitter_group as $element => $value) { + $this->element($element, null, $value); + } + $this->elementEnd('group'); + } + + function showTwitterXmlList($twitter_list) + { + $this->elementStart('list'); + foreach($twitter_list as $element => $value) { + if($element == 'user') { + $this->showTwitterXmlUser($value, 'user'); + } + else { + $this->element($element, null, $value); + } + } + $this->elementEnd('list'); + } + + function showTwitterXmlUser($twitter_user, $role='user', $namespaces=false) + { + $attrs = array(); + if ($namespaces) { + $attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/'; + } + $this->elementStart($role, $attrs); + foreach($twitter_user as $element => $value) { + if ($element == 'status') { + $this->showTwitterXmlStatus($twitter_user['status']); + } else if (strncmp($element, 'statusnet_', 10) == 0) { + $this->element('statusnet:'.substr($element, 10), null, $value); + } else { + $this->element($element, null, $value); + } + } + $this->elementEnd($role); + } + + function showXmlAttachments($attachments) { + if (!empty($attachments)) { + $this->elementStart('attachments', array('type' => 'array')); + foreach ($attachments as $attachment) { + $attrs = array(); + $attrs['url'] = $attachment['url']; + $attrs['mimetype'] = $attachment['mimetype']; + $attrs['size'] = $attachment['size']; + $this->element('enclosure', $attrs, ''); + } + $this->elementEnd('attachments'); + } + } + + function showGeoXML($geo) + { + if (empty($geo)) { + // empty geo element + $this->element('geo'); + } else { + $this->elementStart('geo', array('xmlns:georss' => 'http://www.georss.org/georss')); + $this->element('georss:point', null, $geo['coordinates'][0] . ' ' . $geo['coordinates'][1]); + $this->elementEnd('geo'); + } + } + + function showGeoRSS($geo) + { + if (!empty($geo)) { + $this->element( + 'georss:point', + null, + $geo['coordinates'][0] . ' ' . $geo['coordinates'][1] + ); + } + } + + function showTwitterRssItem($entry) + { + $this->elementStart('item'); + $this->element('title', null, $entry['title']); + $this->element('description', null, $entry['description']); + $this->element('pubDate', null, $entry['pubDate']); + $this->element('guid', null, $entry['guid']); + $this->element('link', null, $entry['link']); + + // RSS only supports 1 enclosure per item + if(array_key_exists('enclosures', $entry) and !empty($entry['enclosures'])){ + $enclosure = $entry['enclosures'][0]; + $this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null); + } + + if(array_key_exists('tags', $entry)){ + foreach($entry['tags'] as $tag){ + $this->element('category', null,$tag); + } + } + + $this->showGeoRSS($entry['geo']); + $this->elementEnd('item'); + } + + function showJsonObjects($objects) + { + print(json_encode($objects)); + } + + function showSingleXmlStatus($notice) + { + $this->initDocument('xml'); + $twitter_status = $this->twitterStatusArray($notice); + $this->showTwitterXmlStatus($twitter_status, 'status', true); + $this->endDocument('xml'); + } + + function showSingleAtomStatus($notice) + { + header('Content-Type: application/atom+xml; charset=utf-8'); + print $notice->asAtomEntry(true, true, true, $this->auth_user); + } + + function show_single_json_status($notice) + { + $this->initDocument('json'); + $status = $this->twitterStatusArray($notice); + $this->showJsonObjects($status); + $this->endDocument('json'); + } + + function showXmlTimeline($notice) + { + $this->initDocument('xml'); + $this->elementStart('statuses', array('type' => 'array', + 'xmlns:statusnet' => 'http://status.net/schema/api/1/')); + + if (is_array($notice)) { + $notice = new ArrayWrapper($notice); + } + + while ($notice->fetch()) { + try { + $twitter_status = $this->twitterStatusArray($notice); + $this->showTwitterXmlStatus($twitter_status); + } catch (Exception $e) { + common_log(LOG_ERR, $e->getMessage()); + continue; + } + } + + $this->elementEnd('statuses'); + $this->endDocument('xml'); + } + + function showRssTimeline($notice, $title, $link, $subtitle, $suplink = null, $logo = null, $self = null) + { + $this->initDocument('rss'); + + $this->element('title', null, $title); + $this->element('link', null, $link); + + if (!is_null($self)) { + $this->element( + 'atom:link', + array( + 'type' => 'application/rss+xml', + 'href' => $self, + 'rel' => 'self' + ) + ); + } + + if (!is_null($suplink)) { + // For FriendFeed's SUP protocol + $this->element('link', array('xmlns' => 'http://www.w3.org/2005/Atom', + 'rel' => 'http://api.friendfeed.com/2008/03#sup', + 'href' => $suplink, + 'type' => 'application/json')); + } + + if (!is_null($logo)) { + $this->elementStart('image'); + $this->element('link', null, $link); + $this->element('title', null, $title); + $this->element('url', null, $logo); + $this->elementEnd('image'); + } + + $this->element('description', null, $subtitle); + $this->element('language', null, 'en-us'); + $this->element('ttl', null, '40'); + + if (is_array($notice)) { + $notice = new ArrayWrapper($notice); + } + + while ($notice->fetch()) { + try { + $entry = $this->twitterRssEntryArray($notice); + $this->showTwitterRssItem($entry); + } catch (Exception $e) { + common_log(LOG_ERR, $e->getMessage()); + // continue on exceptions + } + } + + $this->endTwitterRss(); + } + + function showAtomTimeline($notice, $title, $id, $link, $subtitle=null, $suplink=null, $selfuri=null, $logo=null) + { + $this->initDocument('atom'); + + $this->element('title', null, $title); + $this->element('id', null, $id); + $this->element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), null); + + if (!is_null($logo)) { + $this->element('logo',null,$logo); + } + + if (!is_null($suplink)) { + // For FriendFeed's SUP protocol + $this->element('link', array('rel' => 'http://api.friendfeed.com/2008/03#sup', + 'href' => $suplink, + 'type' => 'application/json')); + } + + if (!is_null($selfuri)) { + $this->element('link', array('href' => $selfuri, + 'rel' => 'self', 'type' => 'application/atom+xml'), null); + } + + $this->element('updated', null, common_date_iso8601('now')); + $this->element('subtitle', null, $subtitle); + + if (is_array($notice)) { + $notice = new ArrayWrapper($notice); + } + + while ($notice->fetch()) { + try { + $this->raw($notice->asAtomEntry()); + } catch (Exception $e) { + common_log(LOG_ERR, $e->getMessage()); + continue; + } + } + + $this->endDocument('atom'); + } + + function showRssGroups($group, $title, $link, $subtitle) + { + $this->initDocument('rss'); + + $this->element('title', null, $title); + $this->element('link', null, $link); + $this->element('description', null, $subtitle); + $this->element('language', null, 'en-us'); + $this->element('ttl', null, '40'); + + if (is_array($group)) { + foreach ($group as $g) { + $twitter_group = $this->twitterRssGroupArray($g); + $this->showTwitterRssItem($twitter_group); + } + } else { + while ($group->fetch()) { + $twitter_group = $this->twitterRssGroupArray($group); + $this->showTwitterRssItem($twitter_group); + } + } + + $this->endTwitterRss(); + } + + function showTwitterAtomEntry($entry) + { + $this->elementStart('entry'); + $this->element('title', null, common_xml_safe_str($entry['title'])); + $this->element( + 'content', + array('type' => 'html'), + common_xml_safe_str($entry['content']) + ); + $this->element('id', null, $entry['id']); + $this->element('published', null, $entry['published']); + $this->element('updated', null, $entry['updated']); + $this->element('link', array('type' => 'text/html', + 'href' => $entry['link'], + 'rel' => 'alternate')); + $this->element('link', array('type' => $entry['avatar-type'], + 'href' => $entry['avatar'], + 'rel' => 'image')); + $this->elementStart('author'); + + $this->element('name', null, $entry['author-name']); + $this->element('uri', null, $entry['author-uri']); + + $this->elementEnd('author'); + $this->elementEnd('entry'); + } + + function showXmlDirectMessage($dm, $namespaces=false) + { + $attrs = array(); + if ($namespaces) { + $attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/'; + } + $this->elementStart('direct_message', $attrs); + foreach($dm as $element => $value) { + switch ($element) { + case 'sender': + case 'recipient': + $this->showTwitterXmlUser($value, $element); + break; + case 'text': + $this->element($element, null, common_xml_safe_str($value)); + break; + default: + $this->element($element, null, $value); + break; + } + } + $this->elementEnd('direct_message'); + } + + function directMessageArray($message) + { + $dmsg = array(); + + $from_profile = $message->getFrom(); + $to_profile = $message->getTo(); + + $dmsg['id'] = intval($message->id); + $dmsg['sender_id'] = intval($from_profile->id); + $dmsg['text'] = trim($message->content); + $dmsg['recipient_id'] = intval($to_profile->id); + $dmsg['created_at'] = $this->dateTwitter($message->created); + $dmsg['sender_screen_name'] = $from_profile->nickname; + $dmsg['recipient_screen_name'] = $to_profile->nickname; + $dmsg['sender'] = $this->twitterUserArray($from_profile, false); + $dmsg['recipient'] = $this->twitterUserArray($to_profile, false); + + return $dmsg; + } + + function rssDirectMessageArray($message) + { + $entry = array(); + + $from = $message->getFrom(); + + $entry['title'] = sprintf('Message from %1$s to %2$s', + $from->nickname, $message->getTo()->nickname); + + $entry['content'] = common_xml_safe_str($message->rendered); + $entry['link'] = common_local_url('showmessage', array('message' => $message->id)); + $entry['published'] = common_date_iso8601($message->created); + + $taguribase = TagURI::base(); + + $entry['id'] = "tag:$taguribase:$entry[link]"; + $entry['updated'] = $entry['published']; + + $entry['author-name'] = $from->getBestName(); + $entry['author-uri'] = $from->homepage; + + $avatar = $from->getAvatar(AVATAR_STREAM_SIZE); + + $entry['avatar'] = (!empty($avatar)) ? $avatar->url : Avatar::defaultImage(AVATAR_STREAM_SIZE); + $entry['avatar-type'] = (!empty($avatar)) ? $avatar->mediatype : 'image/png'; + + // RSS item specific + + $entry['description'] = $entry['content']; + $entry['pubDate'] = common_date_rfc2822($message->created); + $entry['guid'] = $entry['link']; + + return $entry; + } + + function showSingleXmlDirectMessage($message) + { + $this->initDocument('xml'); + $dmsg = $this->directMessageArray($message); + $this->showXmlDirectMessage($dmsg, true); + $this->endDocument('xml'); + } + + function showSingleJsonDirectMessage($message) + { + $this->initDocument('json'); + $dmsg = $this->directMessageArray($message); + $this->showJsonObjects($dmsg); + $this->endDocument('json'); + } + + function showAtomGroups($group, $title, $id, $link, $subtitle=null, $selfuri=null) + { + $this->initDocument('atom'); + + $this->element('title', null, common_xml_safe_str($title)); + $this->element('id', null, $id); + $this->element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), null); + + if (!is_null($selfuri)) { + $this->element('link', array('href' => $selfuri, + 'rel' => 'self', 'type' => 'application/atom+xml'), null); + } + + $this->element('updated', null, common_date_iso8601('now')); + $this->element('subtitle', null, common_xml_safe_str($subtitle)); + + if (is_array($group)) { + foreach ($group as $g) { + $this->raw($g->asAtomEntry()); + } + } else { + while ($group->fetch()) { + $this->raw($group->asAtomEntry()); + } + } + + $this->endDocument('atom'); + + } + + function showJsonTimeline($notice) + { + $this->initDocument('json'); + + $statuses = array(); + + if (is_array($notice)) { + $notice = new ArrayWrapper($notice); + } + + while ($notice->fetch()) { + try { + $twitter_status = $this->twitterStatusArray($notice); + array_push($statuses, $twitter_status); + } catch (Exception $e) { + common_log(LOG_ERR, $e->getMessage()); + continue; + } + } + + $this->showJsonObjects($statuses); + + $this->endDocument('json'); + } + + function showJsonGroups($group) + { + $this->initDocument('json'); + + $groups = array(); + + if (is_array($group)) { + foreach ($group as $g) { + $twitter_group = $this->twitterGroupArray($g); + array_push($groups, $twitter_group); + } + } else { + while ($group->fetch()) { + $twitter_group = $this->twitterGroupArray($group); + array_push($groups, $twitter_group); + } + } + + $this->showJsonObjects($groups); + + $this->endDocument('json'); + } + + function showXmlGroups($group) + { + + $this->initDocument('xml'); + $this->elementStart('groups', array('type' => 'array')); + + if (is_array($group)) { + foreach ($group as $g) { + $twitter_group = $this->twitterGroupArray($g); + $this->showTwitterXmlGroup($twitter_group); + } + } else { + while ($group->fetch()) { + $twitter_group = $this->twitterGroupArray($group); + $this->showTwitterXmlGroup($twitter_group); + } + } + + $this->elementEnd('groups'); + $this->endDocument('xml'); + } + + function showXmlLists($list, $next_cursor=0, $prev_cursor=0) + { + + $this->initDocument('xml'); + $this->elementStart('lists_list'); + $this->elementStart('lists', array('type' => 'array')); + + if (is_array($list)) { + foreach ($list as $l) { + $twitter_list = $this->twitterListArray($l); + $this->showTwitterXmlList($twitter_list); + } + } else { + while ($list->fetch()) { + $twitter_list = $this->twitterListArray($list); + $this->showTwitterXmlList($twitter_list); + } + } + + $this->elementEnd('lists'); + + $this->element('next_cursor', null, $next_cursor); + $this->element('previous_cursor', null, $prev_cursor); + + $this->elementEnd('lists_list'); + $this->endDocument('xml'); + } + + function showJsonLists($list, $next_cursor=0, $prev_cursor=0) + { + $this->initDocument('json'); + + $lists = array(); + + if (is_array($list)) { + foreach ($list as $l) { + $twitter_list = $this->twitterListArray($l); + array_push($lists, $twitter_list); + } + } else { + while ($list->fetch()) { + $twitter_list = $this->twitterListArray($list); + array_push($lists, $twitter_list); + } + } + + $lists_list = array( + 'lists' => $lists, + 'next_cursor' => $next_cursor, + 'next_cursor_str' => strval($next_cursor), + 'previous_cursor' => $prev_cursor, + 'previous_cursor_str' => strval($prev_cursor) + ); + + $this->showJsonObjects($lists_list); + + $this->endDocument('json'); + } + + function showTwitterXmlUsers($user) + { + $this->initDocument('xml'); + $this->elementStart('users', array('type' => 'array', + 'xmlns:statusnet' => 'http://status.net/schema/api/1/')); + + if (is_array($user)) { + foreach ($user as $u) { + $twitter_user = $this->twitterUserArray($u); + $this->showTwitterXmlUser($twitter_user); + } + } else { + while ($user->fetch()) { + $twitter_user = $this->twitterUserArray($user); + $this->showTwitterXmlUser($twitter_user); + } + } + + $this->elementEnd('users'); + $this->endDocument('xml'); + } + + function showJsonUsers($user) + { + $this->initDocument('json'); + + $users = array(); + + if (is_array($user)) { + foreach ($user as $u) { + $twitter_user = $this->twitterUserArray($u); + array_push($users, $twitter_user); + } + } else { + while ($user->fetch()) { + $twitter_user = $this->twitterUserArray($user); + array_push($users, $twitter_user); + } + } + + $this->showJsonObjects($users); + + $this->endDocument('json'); + } + + function showSingleJsonGroup($group) + { + $this->initDocument('json'); + $twitter_group = $this->twitterGroupArray($group); + $this->showJsonObjects($twitter_group); + $this->endDocument('json'); + } + + function showSingleXmlGroup($group) + { + $this->initDocument('xml'); + $twitter_group = $this->twitterGroupArray($group); + $this->showTwitterXmlGroup($twitter_group); + $this->endDocument('xml'); + } + + function showSingleJsonList($list) + { + $this->initDocument('json'); + $twitter_list = $this->twitterListArray($list); + $this->showJsonObjects($twitter_list); + $this->endDocument('json'); + } + + function showSingleXmlList($list) + { + $this->initDocument('xml'); + $twitter_list = $this->twitterListArray($list); + $this->showTwitterXmlList($twitter_list); + $this->endDocument('xml'); + } + + function dateTwitter($dt) + { + $dateStr = date('d F Y H:i:s', strtotime($dt)); + $d = new DateTime($dateStr, new DateTimeZone('UTC')); + $d->setTimezone(new DateTimeZone(common_timezone())); + return $d->format('D M d H:i:s O Y'); + } + + function initDocument($type='xml') + { + switch ($type) { + case 'xml': + header('Content-Type: application/xml; charset=utf-8'); + $this->startXML(); + break; + case 'json': + header('Content-Type: application/json; charset=utf-8'); + + // Check for JSONP callback + if (isset($this->callback)) { + print $this->callback . '('; + } + break; + case 'rss': + header("Content-Type: application/rss+xml; charset=utf-8"); + $this->initTwitterRss(); + break; + case 'atom': + header('Content-Type: application/atom+xml; charset=utf-8'); + $this->initTwitterAtom(); + break; + default: + // TRANS: Client error on an API request with an unsupported data format. + $this->clientError(_('Not a supported data format.')); + break; + } + + return; + } + + function endDocument($type='xml') + { + switch ($type) { + case 'xml': + $this->endXML(); + break; + case 'json': + // Check for JSONP callback + if (isset($this->callback)) { + print ')'; + } + break; + case 'rss': + $this->endTwitterRss(); + break; + case 'atom': + $this->endTwitterRss(); + break; + default: + // TRANS: Client error on an API request with an unsupported data format. + $this->clientError(_('Not a supported data format.')); + break; + } + return; + } + + function clientError($msg, $code = 400, $format = null) + { + $action = $this->trimmed('action'); + if ($format === null) { + $format = $this->format; + } + + common_debug("User error '$code' on '$action': $msg", __FILE__); + + if (!array_key_exists($code, ClientErrorAction::$status)) { + $code = 400; + } + + $status_string = ClientErrorAction::$status[$code]; + + // Do not emit error header for JSONP + if (!isset($this->callback)) { + header('HTTP/1.1 ' . $code . ' ' . $status_string); + } + + switch($format) { + case 'xml': + $this->initDocument('xml'); + $this->elementStart('hash'); + $this->element('error', null, $msg); + $this->element('request', null, $_SERVER['REQUEST_URI']); + $this->elementEnd('hash'); + $this->endDocument('xml'); + break; + case 'json': + $this->initDocument('json'); + $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); + print(json_encode($error_array)); + $this->endDocument('json'); + break; + case 'text': + header('Content-Type: text/plain; charset=utf-8'); + print $msg; + break; + default: + // If user didn't request a useful format, throw a regular client error + throw new ClientException($msg, $code); + } + } + + function serverError($msg, $code = 500, $content_type = null) + { + $action = $this->trimmed('action'); + if ($content_type === null) { + $content_type = $this->format; + } + + common_debug("Server error '$code' on '$action': $msg", __FILE__); + + if (!array_key_exists($code, ServerErrorAction::$status)) { + $code = 400; + } + + $status_string = ServerErrorAction::$status[$code]; + + // Do not emit error header for JSONP + if (!isset($this->callback)) { + header('HTTP/1.1 '.$code.' '.$status_string); + } + + if ($content_type == 'xml') { + $this->initDocument('xml'); + $this->elementStart('hash'); + $this->element('error', null, $msg); + $this->element('request', null, $_SERVER['REQUEST_URI']); + $this->elementEnd('hash'); + $this->endDocument('xml'); + } else { + $this->initDocument('json'); + $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); + print(json_encode($error_array)); + $this->endDocument('json'); + } + } + + function initTwitterRss() + { + $this->startXML(); + $this->elementStart( + 'rss', + array( + 'version' => '2.0', + 'xmlns:atom' => 'http://www.w3.org/2005/Atom', + 'xmlns:georss' => 'http://www.georss.org/georss' + ) + ); + $this->elementStart('channel'); + Event::handle('StartApiRss', array($this)); + } + + function endTwitterRss() + { + $this->elementEnd('channel'); + $this->elementEnd('rss'); + $this->endXML(); + } + + function initTwitterAtom() + { + $this->startXML(); + // FIXME: don't hardcode the language here! + $this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom', + 'xml:lang' => 'en-US', + 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0')); + } + + function endTwitterAtom() + { + $this->elementEnd('feed'); + $this->endXML(); + } + + function showProfile($profile, $content_type='xml', $notice=null, $includeStatuses=true) + { + $profile_array = $this->twitterUserArray($profile, $includeStatuses); + switch ($content_type) { + case 'xml': + $this->showTwitterXmlUser($profile_array); + break; + case 'json': + $this->showJsonObjects($profile_array); + break; + default: + // TRANS: Client error on an API request with an unsupported data format. + $this->clientError(_('Not a supported data format.')); + return; + } + return; + } + + private static function is_decimal($str) + { + return preg_match('/^[0-9]+$/', $str); + } + + function getTargetUser($id) + { + if (empty($id)) { + // Twitter supports these other ways of passing the user ID + if (self::is_decimal($this->arg('id'))) { + return User::staticGet($this->arg('id')); + } else if ($this->arg('id')) { + $nickname = common_canonical_nickname($this->arg('id')); + return User::staticGet('nickname', $nickname); + } else if ($this->arg('user_id')) { + // This is to ensure that a non-numeric user_id still + // overrides screen_name even if it doesn't get used + if (self::is_decimal($this->arg('user_id'))) { + return User::staticGet('id', $this->arg('user_id')); + } + } else if ($this->arg('screen_name')) { + $nickname = common_canonical_nickname($this->arg('screen_name')); + return User::staticGet('nickname', $nickname); + } else { + // Fall back to trying the currently authenticated user + return $this->auth_user; + } + + } else if (self::is_decimal($id)) { + return User::staticGet($id); + } else { + $nickname = common_canonical_nickname($id); + return User::staticGet('nickname', $nickname); + } + } + + function getTargetProfile($id) + { + if (empty($id)) { + + // Twitter supports these other ways of passing the user ID + if (self::is_decimal($this->arg('id'))) { + return Profile::staticGet($this->arg('id')); + } else if ($this->arg('id')) { + // Screen names currently can only uniquely identify a local user. + $nickname = common_canonical_nickname($this->arg('id')); + $user = User::staticGet('nickname', $nickname); + return $user ? $user->getProfile() : null; + } else if ($this->arg('user_id')) { + // This is to ensure that a non-numeric user_id still + // overrides screen_name even if it doesn't get used + if (self::is_decimal($this->arg('user_id'))) { + return Profile::staticGet('id', $this->arg('user_id')); + } + } else if ($this->arg('screen_name')) { + $nickname = common_canonical_nickname($this->arg('screen_name')); + $user = User::staticGet('nickname', $nickname); + return $user ? $user->getProfile() : null; + } + } else if (self::is_decimal($id)) { + return Profile::staticGet($id); + } else { + $nickname = common_canonical_nickname($id); + $user = User::staticGet('nickname', $nickname); + return $user ? $user->getProfile() : null; + } + } + + function getTargetGroup($id) + { + if (empty($id)) { + if (self::is_decimal($this->arg('id'))) { + return User_group::staticGet('id', $this->arg('id')); + } else if ($this->arg('id')) { + return User_group::getForNickname($this->arg('id')); + } else if ($this->arg('group_id')) { + // This is to ensure that a non-numeric group_id still + // overrides group_name even if it doesn't get used + if (self::is_decimal($this->arg('group_id'))) { + return User_group::staticGet('id', $this->arg('group_id')); + } + } else if ($this->arg('group_name')) { + return User_group::getForNickname($this->arg('group_name')); + } + + } else if (self::is_decimal($id)) { + return User_group::staticGet('id', $id); + } else if ($this->arg('uri')) { + return User_group::staticGet('uri', urldecode($this->arg('uri'))); + } else { + return User_group::getForNickname($id); + } + } + + function getTargetList($user=null, $id=null) + { + $tagger = $this->getTargetUser($user); + $list = null; + + if (empty($id)) { + $id = $this->arg('id'); + } + + if($id) { + if (is_numeric($id)) { + $list = Profile_list::staticGet('id', $id); + + // only if the list with the id belongs to the tagger + if(empty($list) || $list->tagger != $tagger->id) { + $list = null; + } + } + if (empty($list)) { + $tag = common_canonical_tag($id); + $list = Profile_list::getByTaggerAndTag($tagger->id, $tag); + } + + if (!empty($list) && $list->private) { + if ($this->auth_user->id == $list->tagger) { + return $list; + } + } else { + return $list; + } + } + return null; + } + + /** + * Returns query argument or default value if not found. Certain + * parameters used throughout the API are lightly scrubbed and + * bounds checked. This overrides Action::arg(). + * + * @param string $key requested argument + * @param string $def default value to return if $key is not provided + * + * @return var $var + */ + function arg($key, $def=null) + { + // XXX: Do even more input validation/scrubbing? + + if (array_key_exists($key, $this->args)) { + switch($key) { + case 'page': + $page = (int)$this->args['page']; + return ($page < 1) ? 1 : $page; + case 'count': + $count = (int)$this->args['count']; + if ($count < 1) { + return 20; + } elseif ($count > 200) { + return 200; + } else { + return $count; + } + case 'since_id': + $since_id = (int)$this->args['since_id']; + return ($since_id < 1) ? 0 : $since_id; + case 'max_id': + $max_id = (int)$this->args['max_id']; + return ($max_id < 1) ? 0 : $max_id; + default: + return parent::arg($key, $def); + } + } else { + return $def; + } + } + + /** + * Calculate the complete URI that called up this action. Used for + * Atom rel="self" links. Warning: this is funky. + * + * @return string URL a URL suitable for rel="self" Atom links + */ + function getSelfUri() + { + $action = mb_substr(get_class($this), 0, -6); // remove 'Action' + + $id = $this->arg('id'); + $aargs = array('format' => $this->format); + if (!empty($id)) { + $aargs['id'] = $id; + } + + $tag = $this->arg('tag'); + if (!empty($tag)) { + $aargs['tag'] = $tag; + } + + parse_str($_SERVER['QUERY_STRING'], $params); + $pstring = ''; + if (!empty($params)) { + unset($params['p']); + $pstring = http_build_query($params); + } + + $uri = common_local_url($action, $aargs); + + if (!empty($pstring)) { + $uri .= '?' . $pstring; + } + + return $uri; + } +} diff --git a/api-changes-1.1.1/lib/router.php b/api-changes-1.1.1/lib/router.php new file mode 100644 index 0000000..cbed72a --- /dev/null +++ b/api-changes-1.1.1/lib/router.php @@ -0,0 +1,1193 @@ +. + * + * @category URL + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * URL Router + * + * Cheap wrapper around Net_URL_Mapper + * + * @category URL + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ +class Router +{ + var $m = null; + static $inst = null; + + const REGEX_TAG = '[^\/]+'; // [\pL\pN_\-\.]{1,64} better if we can do unicode regexes + + static function get() + { + if (!Router::$inst) { + Router::$inst = new Router(); + } + return Router::$inst; + } + + /** + * Clear the global singleton instance for this class. + * Needed to ensure reset when switching site configurations. + */ + static function clear() + { + Router::$inst = null; + } + + function __construct() + { + if (empty($this->m)) { + $this->m = $this->initialize(); + } + } + + /** + * Create a unique hashkey for the router. + * + * The router's url map can change based on the version of the software + * you're running and the plugins that are enabled. To avoid having bad routes + * get stuck in the cache, the key includes a list of plugins and the software + * version. + * + * There can still be problems with a) differences in versions of the plugins and + * b) people running code between official versions, but these tend to be more + * sophisticated users who can grok what's going on and clear their caches. + * + * @return string cache key string that should uniquely identify a router + */ + + static function cacheKey() + { + $parts = array('router'); + + // Many router paths depend on this setting. + if (common_config('singleuser', 'enabled')) { + $parts[] = '1user'; + } else { + $parts[] = 'multi'; + } + + return Cache::codeKey(implode(':', $parts)); + } + + function initialize() + { + $m = new URLMapper(); + + if (Event::handle('StartInitializeRouter', array(&$m))) { + + $m->connect('robots.txt', array('action' => 'robotstxt')); + + $m->connect('opensearch/people', array('action' => 'opensearch', + 'type' => 'people')); + $m->connect('opensearch/notice', array('action' => 'opensearch', + 'type' => 'notice')); + + // docs + + $m->connect('doc/:title', array('action' => 'doc')); + + $m->connect('main/otp/:user_id/:token', + array('action' => 'otp'), + array('user_id' => '[0-9]+', + 'token' => '.+')); + + // these take a code; before the main part + + foreach (array('register', 'confirmaddress', 'recoverpassword') as $c) { + $m->connect('main/'.$c.'/:code', array('action' => $c)); + } + + // Also need a block variant accepting ID on URL for mail links + $m->connect('main/block/:profileid', + array('action' => 'block'), + array('profileid' => '[0-9]+')); + + $m->connect('main/sup/:seconds', array('action' => 'sup'), + array('seconds' => '[0-9]+')); + + // main stuff is repetitive + + $main = array('login', 'logout', 'register', 'subscribe', + 'unsubscribe', 'cancelsubscription', 'approvesub', + 'confirmaddress', 'recoverpassword', + 'invite', 'favor', 'disfavor', 'sup', + 'block', 'unblock', 'subedit', + 'groupblock', 'groupunblock', + 'sandbox', 'unsandbox', + 'silence', 'unsilence', + 'grantrole', 'revokerole', + 'repeat', + 'deleteuser', + 'geocode', + 'version', + 'backupaccount', + 'deleteaccount', + 'restoreaccount', + 'top', + ); + + foreach ($main as $a) { + $m->connect('main/'.$a, array('action' => $a)); + } + + $m->connect('main/tagprofile/:id', array('action' => 'tagprofile'), + array('id' => '[0-9]+')); + + $m->connect('main/tagprofile', array('action' => 'tagprofile')); + + $m->connect('main/oembed', + array('action' => 'oembed')); + + $m->connect('main/xrds', + array('action' => 'publicxrds')); + $m->connect('.well-known/host-meta', + array('action' => 'hostmeta')); + $m->connect('main/xrd', + array('action' => 'userxrd')); + + // settings + + foreach (array('profile', 'avatar', 'password', 'im', 'oauthconnections', + 'oauthapps', 'email', 'sms', 'url') as $s) { + $m->connect('settings/'.$s, array('action' => $s.'settings')); + } + + if (common_config('oldschool', 'enabled')) { + $m->connect('settings/oldschool', array('action' => 'oldschoolsettings')); + } + + $m->connect('settings/oauthapps/show/:id', + array('action' => 'showapplication'), + array('id' => '[0-9]+') + ); + $m->connect('settings/oauthapps/new', + array('action' => 'newapplication') + ); + $m->connect('settings/oauthapps/edit/:id', + array('action' => 'editapplication'), + array('id' => '[0-9]+') + ); + $m->connect('settings/oauthapps/delete/:id', + array('action' => 'deleteapplication'), + array('id' => '[0-9]+') + ); + + // search + + foreach (array('group', 'people', 'notice') as $s) { + $m->connect('search/'.$s.'?q=:q', + array('action' => $s.'search'), + array('q' => '.+')); + $m->connect('search/'.$s, array('action' => $s.'search')); + } + + // The second of these is needed to make the link work correctly + // when inserted into the page. The first is needed to match the + // route on the way in. Seems to be another Net_URL_Mapper bug to me. + $m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'), + array('q' => '.+')); + $m->connect('search/notice/rss', array('action' => 'noticesearchrss')); + + $m->connect('attachment/:attachment', + array('action' => 'attachment'), + array('attachment' => '[0-9]+')); + + $m->connect('attachment/:attachment/ajax', + array('action' => 'attachment_ajax'), + array('attachment' => '[0-9]+')); + + $m->connect('attachment/:attachment/thumbnail', + array('action' => 'attachment_thumbnail'), + array('attachment' => '[0-9]+')); + + $m->connect('notice/new?replyto=:replyto&inreplyto=:inreplyto', + array('action' => 'newnotice'), + array('replyto' => Nickname::DISPLAY_FMT), + array('inreplyto' => '[0-9]+')); + + $m->connect('notice/new?replyto=:replyto', + array('action' => 'newnotice'), + array('replyto' => Nickname::DISPLAY_FMT)); + + $m->connect('notice/new', array('action' => 'newnotice')); + + $m->connect('notice/:notice/file', + array('action' => 'file'), + array('notice' => '[0-9]+')); + + $m->connect('notice/:notice', + array('action' => 'shownotice'), + array('notice' => '[0-9]+')); + + $m->connect('notice/delete/:notice', + array('action' => 'deletenotice'), + array('notice' => '[0-9]+')); + + $m->connect('notice/delete', array('action' => 'deletenotice')); + + $m->connect('bookmarklet/new', array('action' => 'bookmarklet')); + + // conversation + + $m->connect('conversation/:id', + array('action' => 'conversation'), + array('id' => '[0-9]+')); + $m->connect('conversation/:id/replies', + array('action' => 'conversationreplies'), + array('id' => '[0-9]+')); + + $m->connect('message/new', array('action' => 'newmessage')); + $m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => Nickname::DISPLAY_FMT)); + $m->connect('message/:message', + array('action' => 'showmessage'), + array('message' => '[0-9]+')); + + $m->connect('user/:id', + array('action' => 'userbyid'), + array('id' => '[0-9]+')); + + if (!common_config('performance', 'high')) { + $m->connect('tags/', array('action' => 'publictagcloud')); + $m->connect('tag/', array('action' => 'publictagcloud')); + $m->connect('tags', array('action' => 'publictagcloud')); + $m->connect('tag', array('action' => 'publictagcloud')); + } + $m->connect('tag/:tag/rss', + array('action' => 'tagrss'), + array('tag' => self::REGEX_TAG)); + $m->connect('tag/:tag', + array('action' => 'tag'), + array('tag' => self::REGEX_TAG)); + + // groups + + $m->connect('group/new', array('action' => 'newgroup')); + + foreach (array('edit', 'join', 'leave', 'delete', 'cancel', 'approve') as $v) { + $m->connect('group/:nickname/'.$v, + array('action' => $v.'group'), + array('nickname' => Nickname::DISPLAY_FMT)); + $m->connect('group/:id/id/'.$v, + array('action' => $v.'group'), + array('id' => '[0-9]+')); + } + + foreach (array('members', 'logo', 'rss') as $n) { + $m->connect('group/:nickname/'.$n, + array('action' => 'group'.$n), + array('nickname' => Nickname::DISPLAY_FMT)); + } + + $m->connect('group/:nickname/foaf', + array('action' => 'foafgroup'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect('group/:nickname/blocked', + array('action' => 'blockedfromgroup'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect('group/:nickname/makeadmin', + array('action' => 'makeadmin'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect('group/:nickname/members/pending', + array('action' => 'groupqueue'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect('group/:id/id', + array('action' => 'groupbyid'), + array('id' => '[0-9]+')); + + $m->connect('group/:nickname', + array('action' => 'showgroup'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect('group/:nickname/', + array('action' => 'showgroup'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect('group/', array('action' => 'groups')); + $m->connect('group', array('action' => 'groups')); + $m->connect('groups/', array('action' => 'groups')); + $m->connect('groups', array('action' => 'groups')); + + // Twitter-compatible API + + // statuses API + + $m->connect('api', + array('action' => 'Redirect', + 'nextAction' => 'doc', + 'args' => array('title' => 'api'))); + + $m->connect('api/statuses/public_timeline.:format', + array('action' => 'ApiTimelinePublic', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/friends_timeline/:id.:format', + array('action' => 'ApiTimelineFriends', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/friends_timeline.:format', + array('action' => 'ApiTimelineFriends', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/home_timeline/:id.:format', + array('action' => 'ApiTimelineHome', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/home_timeline.:format', + array('action' => 'ApiTimelineHome', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/user_timeline/:id.:format', + array('action' => 'ApiTimelineUser', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/user_timeline.:format', + array('action' => 'ApiTimelineUser', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/mentions/:id.:format', + array('action' => 'ApiTimelineMentions', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/mentions.:format', + array('action' => 'ApiTimelineMentions', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/replies/:id.:format', + array('action' => 'ApiTimelineMentions', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/replies.:format', + array('action' => 'ApiTimelineMentions', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statuses/retweeted_by_me.:format', + array('action' => 'ApiTimelineRetweetedByMe', + 'format' => '(xml|json|atom|as)')); + + $m->connect('api/statuses/retweeted_to_me.:format', + array('action' => 'ApiTimelineRetweetedToMe', + 'format' => '(xml|json|atom|as)')); + + $m->connect('api/statuses/retweets_of_me.:format', + array('action' => 'ApiTimelineRetweetsOfMe', + 'format' => '(xml|json|atom|as)')); + + $m->connect('api/statuses/friends/:id.:format', + array('action' => 'ApiUserFriends', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/statuses/friends.:format', + array('action' => 'ApiUserFriends', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/followers/:id.:format', + array('action' => 'ApiUserFollowers', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/statuses/followers.:format', + array('action' => 'ApiUserFollowers', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/show/:id.:format', + array('action' => 'ApiStatusesShow', + 'id' => '[0-9]+', + 'format' => '(xml|json|atom)')); + + $m->connect('api/statuses/show.:format', + array('action' => 'ApiStatusesShow', + 'format' => '(xml|json|atom)')); + + $m->connect('api/statuses/update.:format', + array('action' => 'ApiStatusesUpdate', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/destroy/:id.:format', + array('action' => 'ApiStatusesDestroy', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/destroy.:format', + array('action' => 'ApiStatusesDestroy', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/retweet/:id.:format', + array('action' => 'ApiStatusesRetweet', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/retweets/:id.:format', + array('action' => 'ApiStatusesRetweets', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/favs/:id.json', + array('action' => 'ApiStatusesFavs', + 'id' => '[0-9]+')); + + $m->connect('api/attachment/:id.json', + array('action' => 'ApiAttachment', + 'id' => '[0-9]+')); + + $m->connect('api/checkhub.json', + array('action' => 'ApiCheckHub')); + + $m->connect('api/externalprofile/show.json', + array('action' => 'ApiExternalProfileShow')); + + // users + + $m->connect('api/users/show/:id.:format', + array('action' => 'ApiUserShow', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/users/show.:format', + array('action' => 'ApiUserShow', + 'format' => '(xml|json)')); + + $m->connect('api/users/profile_image/:screen_name.:format', + array('action' => 'ApiUserProfileImage', + 'screen_name' => Nickname::DISPLAY_FMT, + 'format' => '(xml|json)')); + + // direct messages + + $m->connect('api/direct_messages.:format', + array('action' => 'ApiDirectMessage', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/direct_messages/sent.:format', + array('action' => 'ApiDirectMessage', + 'format' => '(xml|json|rss|atom)', + 'sent' => true)); + + $m->connect('api/direct_messages/new.:format', + array('action' => 'ApiDirectMessageNew', + 'format' => '(xml|json)')); + + // friendships + + $m->connect('api/friendships/show.:format', + array('action' => 'ApiFriendshipsShow', + 'format' => '(xml|json)')); + + $m->connect('api/friendships/exists.:format', + array('action' => 'ApiFriendshipsExists', + 'format' => '(xml|json)')); + + $m->connect('api/friendships/create/:id.:format', + array('action' => 'ApiFriendshipsCreate', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/friendships/create.:format', + array('action' => 'ApiFriendshipsCreate', + 'format' => '(xml|json)')); + + $m->connect('api/friendships/destroy/:id.:format', + array('action' => 'ApiFriendshipsDestroy', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/friendships/destroy.:format', + array('action' => 'ApiFriendshipsDestroy', + 'format' => '(xml|json)')); + + // Social graph + + $m->connect('api/friends/ids/:id.:format', + array('action' => 'ApiUserFriends', + 'ids_only' => true)); + + $m->connect('api/followers/ids/:id.:format', + array('action' => 'ApiUserFollowers', + 'ids_only' => true)); + + $m->connect('api/friends/ids.:format', + array('action' => 'ApiUserFriends', + 'ids_only' => true)); + + $m->connect('api/followers/ids.:format', + array('action' => 'ApiUserFollowers', + 'ids_only' => true)); + + // account + + $m->connect('api/account/verify_credentials.:format', + array('action' => 'ApiAccountVerifyCredentials')); + + $m->connect('api/account/update_profile.:format', + array('action' => 'ApiAccountUpdateProfile')); + + $m->connect('api/account/update_profile_image.:format', + array('action' => 'ApiAccountUpdateProfileImage')); + + $m->connect('api/account/update_delivery_device.:format', + array('action' => 'ApiAccountUpdateDeliveryDevice')); + + // special case where verify_credentials is called w/out a format + + $m->connect('api/account/verify_credentials', + array('action' => 'ApiAccountVerifyCredentials')); + + $m->connect('api/account/rate_limit_status.:format', + array('action' => 'ApiAccountRateLimitStatus')); + + // favorites + + $m->connect('api/favorites/:id.:format', + array('action' => 'ApiTimelineFavorites', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/favorites.:format', + array('action' => 'ApiTimelineFavorites', + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/favorites/create/:id.:format', + array('action' => 'ApiFavoriteCreate', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/favorites/destroy/:id.:format', + array('action' => 'ApiFavoriteDestroy', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); + // blocks + + $m->connect('api/blocks/create/:id.:format', + array('action' => 'ApiBlockCreate', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/blocks/create.:format', + array('action' => 'ApiBlockCreate', + 'format' => '(xml|json)')); + + $m->connect('api/blocks/destroy/:id.:format', + array('action' => 'ApiBlockDestroy', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/blocks/destroy.:format', + array('action' => 'ApiBlockDestroy', + 'format' => '(xml|json)')); + + // help + + $m->connect('api/help/test.:format', + array('action' => 'ApiHelpTest', + 'format' => '(xml|json)')); + + // statusnet + + $m->connect('api/statusnet/version.:format', + array('action' => 'ApiStatusnetVersion', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/config.:format', + array('action' => 'ApiStatusnetConfig', + 'format' => '(xml|json)')); + + // For older methods, we provide "laconica" base action + + $m->connect('api/laconica/version.:format', + array('action' => 'ApiStatusnetVersion', + 'format' => '(xml|json)')); + + $m->connect('api/laconica/config.:format', + array('action' => 'ApiStatusnetConfig', + 'format' => '(xml|json)')); + + // Groups and tags are newer than 0.8.1 so no backward-compatibility + // necessary + + // Groups + //'list' has to be handled differently, as php will not allow a method to be named 'list' + + $m->connect('api/statusnet/groups/timeline/:id.:format', + array('action' => 'ApiTimelineGroup', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + + $m->connect('api/statusnet/groups/show/:id.:format', + array('action' => 'ApiGroupShow', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/show.:format', + array('action' => 'ApiGroupShow', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/join/:id.:format', + array('action' => 'ApiGroupJoin', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/join.:format', + array('action' => 'ApiGroupJoin', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/leave/:id.:format', + array('action' => 'ApiGroupLeave', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/leave.:format', + array('action' => 'ApiGroupLeave', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/is_member.:format', + array('action' => 'ApiGroupIsMember', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/list/:id.:format', + array('action' => 'ApiGroupList', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statusnet/groups/list.:format', + array('action' => 'ApiGroupList', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statusnet/groups/list_all.:format', + array('action' => 'ApiGroupListAll', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statusnet/groups/membership/:id.:format', + array('action' => 'ApiGroupMembership', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/membership.:format', + array('action' => 'ApiGroupMembership', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/create.:format', + array('action' => 'ApiGroupCreate', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/update/:id.:format', + array('action' => 'ApiGroupProfileUpdate', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/conversation/:id.:format', + array('action' => 'apiconversation', + 'id' => '[0-9]+', + 'format' => '(xml|json|rss|atom|as)')); + + // Lists (people tags) + + $m->connect('api/lists/memberships.:format', + array('action' => 'ApiListMemberships', + 'format' => '(xml|json)')); + + $m->connect('api/:user/lists/memberships.:format', + array('action' => 'ApiListMemberships', + 'user' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/lists/subscriptions.:format', + array('action' => 'ApiListSubscriptions', + 'format' => '(xml|json)')); + + $m->connect('api/:user/lists/subscriptions.:format', + array('action' => 'ApiListSubscriptions', + 'user' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/lists.:format', + array('action' => 'ApiLists', + 'format' => '(xml|json)')); + + $m->connect('api/:user/lists/:id.:format', + array('action' => 'ApiList', + 'user' => '[a-zA-Z0-9]+', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/:user/lists.:format', + array('action' => 'ApiLists', + 'user' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/:user/lists/:id/statuses.:format', + array('action' => 'ApiTimelineList', + 'user' => '[a-zA-Z0-9]+', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/:user/:list_id/members/:id.:format', + array('action' => 'ApiListMember', + 'user' => '[a-zA-Z0-9]+', + 'list_id' => '[a-zA-Z0-9]+', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/:user/:list_id/members.:format', + array('action' => 'ApiListMembers', + 'user' => '[a-zA-Z0-9]+', + 'list_id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/:user/:list_id/subscribers/:id.:format', + array('action' => 'ApiListSubscriber', + 'user' => '[a-zA-Z0-9]+', + 'list_id' => '[a-zA-Z0-9]+', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/:user/:list_id/subscribers.:format', + array('action' => 'ApiListSubscribers', + 'user' => '[a-zA-Z0-9]+', + 'list_id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + // Tags + $m->connect('api/statusnet/tags/timeline/:tag.:format', + array('action' => 'ApiTimelineTag', + 'tag' => self::REGEX_TAG, + 'format' => '(xml|json|rss|atom|as)')); + + // media related + $m->connect( + 'api/statusnet/media/upload', + array('action' => 'ApiMediaUpload') + ); + + // search + $m->connect('api/search.atom', array('action' => 'ApiSearchAtom')); + $m->connect('api/search.json', array('action' => 'ApiSearchJSON')); + $m->connect('api/trends.json', array('action' => 'ApiTrends')); + + $m->connect('api/oauth/request_token', + array('action' => 'ApiOauthRequestToken')); + + $m->connect('api/oauth/access_token', + array('action' => 'ApiOauthAccessToken')); + + $m->connect('api/oauth/authorize', + array('action' => 'ApiOauthAuthorize')); + + // Admin + + $m->connect('panel/site', array('action' => 'siteadminpanel')); + $m->connect('panel/user', array('action' => 'useradminpanel')); + $m->connect('panel/access', array('action' => 'accessadminpanel')); + $m->connect('panel/paths', array('action' => 'pathsadminpanel')); + $m->connect('panel/sessions', array('action' => 'sessionsadminpanel')); + $m->connect('panel/sitenotice', array('action' => 'sitenoticeadminpanel')); + $m->connect('panel/snapshot', array('action' => 'snapshotadminpanel')); + $m->connect('panel/license', array('action' => 'licenseadminpanel')); + + $m->connect('panel/plugins', array('action' => 'pluginsadminpanel')); + $m->connect('panel/plugins/enable/:plugin', + array('action' => 'pluginenable'), + array('plugin' => '[A-Za-z0-9_]+')); + $m->connect('panel/plugins/disable/:plugin', + array('action' => 'plugindisable'), + array('plugin' => '[A-Za-z0-9_]+')); + + $m->connect('getfile/:filename', + array('action' => 'getfile'), + array('filename' => '[A-Za-z0-9._-]+')); + + // Common people-tag stuff + + $m->connect('peopletag/:tag', array('action' => 'peopletag', + 'tag' => self::REGEX_TAG)); + + $m->connect('selftag/:tag', array('action' => 'selftag', + 'tag' => self::REGEX_TAG)); + + $m->connect('main/addpeopletag', array('action' => 'addpeopletag')); + + $m->connect('main/removepeopletag', array('action' => 'removepeopletag')); + + $m->connect('main/profilecompletion', array('action' => 'profilecompletion')); + + $m->connect('main/peopletagautocomplete', array('action' => 'peopletagautocomplete')); + + // In the "root" + + if (common_config('singleuser', 'enabled')) { + + $nickname = User::singleUserNickname(); + + foreach (array('subscriptions', 'subscribers', + 'all', 'foaf', 'replies', + 'microsummary') as $a) { + $m->connect($a, + array('action' => $a, + 'nickname' => $nickname)); + } + + foreach (array('subscriptions', 'subscribers') as $a) { + $m->connect($a.'/:tag', + array('action' => $a, + 'nickname' => $nickname), + array('tag' => self::REGEX_TAG)); + } + + $m->connect('subscribers/pending', + array('action' => 'subqueue', + 'nickname' => $nickname)); + + foreach (array('rss', 'groups') as $a) { + $m->connect($a, + array('action' => 'user'.$a, + 'nickname' => $nickname)); + } + + foreach (array('all', 'replies', 'favorites') as $a) { + $m->connect($a.'/rss', + array('action' => $a.'rss', + 'nickname' => $nickname)); + } + + $m->connect('favorites', + array('action' => 'showfavorites', + 'nickname' => $nickname)); + + $m->connect('avatar/:size', + array('action' => 'avatarbynickname', + 'nickname' => $nickname), + array('size' => '(original|96|48|24)')); + + $m->connect('tag/:tag/rss', + array('action' => 'userrss', + 'nickname' => $nickname), + array('tag' => self::REGEX_TAG)); + + $m->connect('tag/:tag', + array('action' => 'showstream', + 'nickname' => $nickname), + array('tag' => self::REGEX_TAG)); + + $m->connect('rsd.xml', + array('action' => 'rsd', + 'nickname' => $nickname)); + + $m->connect('', + array('action' => 'showstream', + 'nickname' => $nickname)); + + // peopletags + + $m->connect('peopletags', + array('action' => 'peopletagsbyuser')); + + $m->connect('peopletags/private', + array('action' => 'peopletagsbyuser', + 'private' => 1)); + + $m->connect('peopletags/public', + array('action' => 'peopletagsbyuser', + 'public' => 1)); + + $m->connect('othertags', + array('action' => 'peopletagsforuser')); + + $m->connect('peopletagsubscriptions', + array('action' => 'peopletagsubscriptions')); + + $m->connect('all/:tag/subscribers', + array('action' => 'peopletagsubscribers', + 'tag' => self::REGEX_TAG)); + + $m->connect('all/:tag/tagged', + array('action' => 'peopletagged', + 'tag' => self::REGEX_TAG)); + + $m->connect('all/:tag/edit', + array('action' => 'editpeopletag', + 'tag' => self::REGEX_TAG)); + + foreach(array('subscribe', 'unsubscribe') as $v) { + $m->connect('peopletag/:id/'.$v, + array('action' => $v.'peopletag', + 'id' => '[0-9]{1,64}')); + } + $m->connect('user/:tagger_id/profiletag/:id/id', + array('action' => 'profiletagbyid', + 'tagger_id' => '[0-9]+', + 'id' => '[0-9]+')); + + $m->connect('all/:tag', + array('action' => 'showprofiletag', + 'tag' => self::REGEX_TAG)); + + foreach (array('subscriptions', 'subscribers') as $a) { + $m->connect($a.'/:tag', + array('action' => $a), + array('tag' => self::REGEX_TAG)); + } + } else { + $m->connect('', array('action' => 'public')); + $m->connect('rss', array('action' => 'publicrss')); + $m->connect('featuredrss', array('action' => 'featuredrss')); + $m->connect('favoritedrss', array('action' => 'favoritedrss')); + $m->connect('featured/', array('action' => 'featured')); + $m->connect('featured', array('action' => 'featured')); + $m->connect('favorited/', array('action' => 'favorited')); + $m->connect('favorited', array('action' => 'favorited')); + $m->connect('rsd.xml', array('action' => 'rsd')); + + foreach (array('subscriptions', 'subscribers', + 'nudge', 'all', 'foaf', 'replies', + 'inbox', 'outbox', 'microsummary') as $a) { + $m->connect(':nickname/'.$a, + array('action' => $a), + array('nickname' => Nickname::DISPLAY_FMT)); + } + $m->connect(':nickname/subscribers/pending', + array('action' => 'subqueue'), + array('nickname' => Nickname::DISPLAY_FMT)); + + // people tags + + $m->connect(':nickname/peopletags', + array('action' => 'peopletagsbyuser', + 'nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':nickname/peopletags/private', + array('action' => 'peopletagsbyuser', + 'nickname' => Nickname::DISPLAY_FMT, + 'private' => 1)); + + $m->connect(':nickname/peopletags/public', + array('action' => 'peopletagsbyuser', + 'nickname' => Nickname::DISPLAY_FMT, + 'public' => 1)); + + $m->connect(':nickname/othertags', + array('action' => 'peopletagsforuser', + 'nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':nickname/peopletagsubscriptions', + array('action' => 'peopletagsubscriptions', + 'nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':tagger/all/:tag/subscribers', + array('action' => 'peopletagsubscribers', + 'tagger' => Nickname::DISPLAY_FMT, + 'tag' => self::REGEX_TAG)); + + $m->connect(':tagger/all/:tag/tagged', + array('action' => 'peopletagged', + 'tagger' => Nickname::DISPLAY_FMT, + 'tag' => self::REGEX_TAG)); + + $m->connect(':tagger/all/:tag/edit', + array('action' => 'editpeopletag', + 'tagger' => Nickname::DISPLAY_FMT, + 'tag' => self::REGEX_TAG)); + + foreach(array('subscribe', 'unsubscribe') as $v) { + $m->connect('peopletag/:id/'.$v, + array('action' => $v.'peopletag', + 'id' => '[0-9]{1,64}')); + } + $m->connect('user/:tagger_id/profiletag/:id/id', + array('action' => 'profiletagbyid', + 'tagger_id' => '[0-9]+', + 'id' => '[0-9]+')); + + $m->connect(':tagger/all/:tag', + array('action' => 'showprofiletag', + 'tagger' => Nickname::DISPLAY_FMT, + 'tag' => self::REGEX_TAG)); + + foreach (array('subscriptions', 'subscribers') as $a) { + $m->connect(':nickname/'.$a.'/:tag', + array('action' => $a), + array('tag' => self::REGEX_TAG, + 'nickname' => Nickname::DISPLAY_FMT)); + } + + foreach (array('rss', 'groups') as $a) { + $m->connect(':nickname/'.$a, + array('action' => 'user'.$a), + array('nickname' => Nickname::DISPLAY_FMT)); + } + + foreach (array('all', 'replies', 'favorites') as $a) { + $m->connect(':nickname/'.$a.'/rss', + array('action' => $a.'rss'), + array('nickname' => Nickname::DISPLAY_FMT)); + } + + $m->connect(':nickname/favorites', + array('action' => 'showfavorites'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':nickname/avatar/:size', + array('action' => 'avatarbynickname'), + array('size' => '(original|96|48|24)', + 'nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':nickname/tag/:tag/rss', + array('action' => 'userrss'), + array('nickname' => Nickname::DISPLAY_FMT), + array('tag' => self::REGEX_TAG)); + + $m->connect(':nickname/tag/:tag', + array('action' => 'showstream'), + array('nickname' => Nickname::DISPLAY_FMT), + array('tag' => self::REGEX_TAG)); + + $m->connect(':nickname/rsd.xml', + array('action' => 'rsd'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':nickname', + array('action' => 'showstream'), + array('nickname' => Nickname::DISPLAY_FMT)); + + $m->connect(':nickname/', + array('action' => 'showstream'), + array('nickname' => Nickname::DISPLAY_FMT)); + } + + // AtomPub API + + $m->connect('api/statusnet/app/service/:id.xml', + array('action' => 'ApiAtomService'), + array('id' => Nickname::DISPLAY_FMT)); + + $m->connect('api/statusnet/app/service.xml', + array('action' => 'ApiAtomService')); + + $m->connect('api/statusnet/app/subscriptions/:subscriber/:subscribed.atom', + array('action' => 'AtomPubShowSubscription'), + array('subscriber' => '[0-9]+', + 'subscribed' => '[0-9]+')); + + $m->connect('api/statusnet/app/subscriptions/:subscriber.atom', + array('action' => 'AtomPubSubscriptionFeed'), + array('subscriber' => '[0-9]+')); + + $m->connect('api/statusnet/app/favorites/:profile/:notice.atom', + array('action' => 'AtomPubShowFavorite'), + array('profile' => '[0-9]+', + 'notice' => '[0-9]+')); + + $m->connect('api/statusnet/app/favorites/:profile.atom', + array('action' => 'AtomPubFavoriteFeed'), + array('profile' => '[0-9]+')); + + $m->connect('api/statusnet/app/memberships/:profile/:group.atom', + array('action' => 'AtomPubShowMembership'), + array('profile' => '[0-9]+', + 'group' => '[0-9]+')); + + $m->connect('api/statusnet/app/memberships/:profile.atom', + array('action' => 'AtomPubMembershipFeed'), + array('profile' => '[0-9]+')); + + // URL shortening + + $m->connect('url/:id', + array('action' => 'redirecturl', + 'id' => '[0-9]+')); + + // user stuff + + Event::handle('RouterInitialized', array($m)); + } + + return $m; + } + + function map($path) + { + try { + $match = $this->m->match($path); + } catch (Exception $e) { + common_log(LOG_ERR, "Problem getting route for $path - " . + $e->getMessage()); + // TRANS: Client error on action trying to visit a non-existing page. + $cac = new ClientErrorAction(_('Page not found.'), 404); + $cac->showPage(); + } + + return $match; + } + + function build($action, $args=null, $params=null, $fragment=null) + { + $action_arg = array('action' => $action); + + if ($args) { + $args = array_merge($action_arg, $args); + } else { + $args = $action_arg; + } + + $url = $this->m->generate($args, $params, $fragment); + // Due to a bug in the Net_URL_Mapper code, the returned URL may + // contain a malformed query of the form ?p1=v1?p2=v2?p3=v3. We + // repair that here rather than modifying the upstream code... + + $qpos = strpos($url, '?'); + if ($qpos !== false) { + $url = substr($url, 0, $qpos+1) . + str_replace('?', '&', substr($url, $qpos+1)); + + // @fixme this is a hacky workaround for http_build_query in the + // lower-level code and bad configs that set the default separator + // to & instead of &. Encoded &s in parameters will not be + // affected. + $url = substr($url, 0, $qpos+1) . + str_replace('&', '&', substr($url, $qpos+1)); + + } + + return $url; + } +} diff --git a/css/1.css b/css/1.css new file mode 100644 index 0000000..912e568 --- /dev/null +++ b/css/1.css @@ -0,0 +1,3088 @@ + /* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · + · · + · · + · Q V I T T E R · + · · + · http://github.com/hannesmannerheim/qvitter · + · · + · · + · \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter 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 three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + +body { + background-color:#fff; + background-size:100% auto; + background-attachment:fixed; + margin:0; + padding:0; + padding-left:50%; + padding-top:39px; + color: #333333; + font-size: 14px; + line-height: 18px; + font-family: "Helvetica Neue",Arial,sans-serif; + } +a, a:visited, a:active { + text-decoration:none; + color:#0084B4; + } +ul, li { + margin:0; + padding:0; + list-style: none outside none; + } + +.nav-session, +.stream-item-footer .with-icn .badge-requeeted, +ul.queet-actions li .icon, +.modal-close .icon, +.dogear, +.chev-right, +.close-right, +button.icon.nav-search { + background-image: url("../img/sprite.png"); + } + +.topbar .global-nav { + background-image: url("../img/sprite_bgs.png"); + } + +#logo { + background-image:url("../img/logo.png"); + } + +.topbar { + box-shadow: 0 2px 3px rgba(0, 0, 0, 0.25); + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 3000; + text-align:center; + } + +#search { + display:none; + height: 26px; + width: 202px; + float: right; + font-size: 12px; + margin: 7px 10px 0 7px; + position: relative; + } +#search-query { + background-color: transparent; + background-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); + color: #444444; + position: absolute; + right: 0; + top: 0; + z-index: 2; + border: 0 none; + border-radius: 13px 13px 13px 13px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; + display: block; + font-size: 12px; + height: 14px; + line-height: 1; + padding: 6px 27px 6px 12px; + transition: all 0.2s ease-in-out 0s; + width: 163px; + margin: 0; + outline: 0 none; + font-family: "Helvetica Neue",Arial,sans-serif; + } +#search-query:focus { + box-shadow:none; + text-shadow:none; + background-color:#fff; + color:#666; + } +#search-query-hint { + background-color: #CCCCCC; + color: #999999; + position: absolute; + right: 0; + z-index: 1; + background-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); + top: 0; + border: 0 none; + border-radius: 13px 13px 13px 13px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; + display: block; + font-size: 12px; + height: 14px; + line-height: 1; + padding: 6px 27px 6px 12px; + transition: all 0.2s ease-in-out 0s; + width: 163px; + margin: 0; + outline: 0 none; + cursor: not-allowed; + } +.search-icon { + font-size: 12px; + cursor: pointer; + display: block; + height: 26px; + position: absolute; + right: 2px; + top: 0; + width: 26px; + z-index: 3; + text-align: left; + } +button.icon.nav-search { + font-family: "Helvetica Neue",Arial,sans-serif; + border: 0 none; + background-repeat: no-repeat; + display: inline-block; + vertical-align: text-top; + height: 14px; + width: 12px; + background-position: -20px -710px; + background-color: transparent; + margin-left: 7px; + margin-top: 3px; + } +button.icon.nav-search span { + font-family: "Helvetica Neue",Arial,sans-serif; + border: 0 none; + clip: rect(0px, 0px, 0px, 0px); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + } + +.global-nav .container { + width:850px; + margin: 0 auto; + } +.language-dropdown { + float: right; + text-align: left; + margin-left: 6px; + margin-right: 0; + position: relative; + display: block; + } +.dropdown { + float: left; + position: relative; + } +.dropdown-toggle { + color: #BBBBBB; + display: block; + font-weight: bold; + height: 12px; + line-height: 1; + padding: 13px 12px 15px; + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.75); + padding-left: 12px; + padding-right: 12px; + font-size: 12px; + position: relative; + text-decoration: none; + font-family: Arial,sans-serif; + cursor:pointer; + } +.dropdown-toggle:hover { + color:#fff; + } +.dropdown-toggle small { + font-weight: normal; + font-size: 12px; + } + +.dropdown-toggle .caret { + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #777777; + display: inline-block; + height: 0; + margin-left: 2px; + margin-top: 5px; + vertical-align: top; + width: 0; + } +.dropdown-toggle .caret b { + font-weight: normal; + } +.dropdown-toggle:hover .caret { + border-top: 4px solid #fff; + } +.dropdown-menu { + right: 0; + width: 125px; + background-clip: padding-box; + background-color: #FFFFFF; + border-color: rgba(0, 0, 0, 0.2); + border-radius: 4px 4px 4px 4px; + border-style: solid; + border-width: 1px; + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + display: none; + float: left; + margin: 2px 0 0; + padding: 4px 0; + position: absolute; + top: 100%; + z-index: 900; + } +.quitter-settings.dropdown-menu { + left:50%; + right:auto; + margin-left:-410px; + } +.quitter-settings.dropdown-menu.dropped { + display:block; + } +.dropdown-caret { + float: left; + height: 7px; + left: 12px; + overflow: hidden; + position: absolute; + top: -7px; + width: 12px; + } +.dropdown-caret .caret-outer { + white-space: nowrap; + display: inline-block; + left: 0; + margin-left: -1px; + position: absolute; + top: 0; + border-bottom: 7px solid rgba(0, 0, 0, 0.2); + border-left: 7px solid transparent; + border-right: 7px solid transparent; + } +.dropdown-caret .caret-inner { + white-space: nowrap; + margin-left: -1px; + position: absolute; + border-bottom: 6px solid #FFFFFF; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + display: inline-block; + left: 1px; + top: 1px; + } +.dropdown-caret.right { + left: auto; + right: 10px; + } +.dropdown.dropped .dropdown-menu { + display:block; + } +.dropdown.dropped .dropdown-toggle, +.dropdown.dropped .dropdown-toggle .current-language { + color:#fff; + text-decoration:underline; + } +.dropdown.dropped .dropdown-toggle .caret { + border-top:4px solid #fff; + } + +.dropdown-menu li:not(.dropdown-caret) { + float: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 125px; + position: relative; + display: block; + } +.dropdown-menu li:not(.dropdown-caret) a { + clear: both; + color: #333333; + cursor: pointer; + display: block; + float: none; + font-size: 12px; + font-weight: normal; + line-height: 18px; + padding: 3px 15px 3px 22px; + position: relative; + text-shadow: none; + white-space: nowrap; + text-decoration: none; + } +.dropdown-menu li:not(.dropdown-caret) a:hover { + background-color: #2271A9; + background: -moz-linear-gradient(top, #2f7eb6 0px, #2271a9 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0px,#2f7eb6), color-stop(100%,#2271a9)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #2f7eb6 0px,#2271a9 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #2f7eb6 0px,#2271a9 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #2f7eb6 0px,#2271a9 100%); /* IE10+ */ + background: linear-gradient(to bottom, #2f7eb6 0px,#2271a9 100%); /* W3C */ + background-repeat: repeat-x; + color: #FFFFFF; + text-decoration: none; + } + +#birds-top { + display:block; + position:fixed; + z-index:1001; + margin-top:-1px; + right:-3px; + } +.topbar .global-nav { + position: relative; + width: 100%; + height: 40px; + background-color: #252525; + background-position: 0 0; + background-repeat: repeat-x; + } + +.queet-text a:hover { + text-decoration:underline; + } +.queet-text a[rel="nofollow external"] { + direction: ltr; + unicode-bidi: bidi-override; + } + +#login-content { + font-family: Arial,​sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + background: #ffffff; /* Old browsers */ + background: -moz-linear-gradient(top, #ffffff 0px, #dddddd 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0px,#ffffff), color-stop(100%,#dddddd)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #ffffff 0px,#dddddd 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #ffffff 0px,#dddddd 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #ffffff 0px,#dddddd 100%); /* IE10+ */ + background: linear-gradient(to bottom, #ffffff 0px,#dddddd 100%); /* W3C */ + background-clip: border-box; + background-origin: padding-box; + background-size: auto auto; + width: 300px; + height: 108px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-right-color: #EEEEEE; + border-bottom-color: #CCCCCC; + border-left-color: #EEEEEE; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 0px 0px; + position:fixed; + opacity:0; + margin-top:1px; + z-index:2000; + } + +#login-content input#username, +#login-content input#password { + font-family: Arial,​sans-serif; + font-size: 13px; + color: #000000; + line-height: 15.4333px; + direction: ltr; + background-color: #FFFFFF; + width: 266px; + height: 20px; + top: 0px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 4px; + padding-right: 4px; + padding-bottom: 4px; + padding-left: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #CCCCCC; + border-right-color: #CCCCCC; + border-bottom-color: #CCCCCC; + border-left-color: #CCCCCC; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + box-shadow: 0 1px 0 #EEEEEE inset, 0 1px 0 #FFFFFF; + outline-color: #000000; + position: absolute; + display: block; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + outline-style: none; + outline-width: 0px; + transition-delay: 0s; + transition-duration: 0.2s; + transition-property: background; + transition-timing-function: cubic-bezier(0, 0, 1, 1); + } +#login-content input#password { + width:100%; + font-size: 13px; + color: #000000; + line-height: 16.3667px; + border-collapse: collapse; + border-spacing:0px 0px; + box-sizing:border-box; + -moz-box-sizing:border-box; + display: block; + height: 30px; + line-height: normal; + width: 100%; + position: absolute; + top: 0; + margin: 0; + outline: 0 none; + padding: 4px; + margin-left:-1px; + } + +table.password-signin { + left: 12px; + position: absolute; + top: 48px; + width: 276px; + border-collapse: collapse; + border-spacing: 0; + } +.flex-table-primary, .flex-table-secondary { + vertical-align: top; + } +.flex-table-primary { + padding-right: 5px; + width: 99%; + } +.flex-table-secondary { + max-width: 1%; + width: 1%; + vertical-align: top; + } +.placeholding-input { + width: 100%; + height: 30px; + font-size: 13px; + overflow: visible; + position: relative; + float: left; + } + +button#submit-login { + font-family: "Helvetica Neue",Arial,​sans-serif; + font-size: 13px; + font-weight: 700; + color: #FFFFFF; + line-height: 18px; + background: -moz-linear-gradient(top, #33bcef 0%, #019ad2 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#33bcef), color-stop(100%,#019ad2)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #33bcef 0%,#019ad2 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #33bcef 0%,#019ad2 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #33bcef 0%,#019ad2 100%); /* IE10+ */ + background: linear-gradient(to bottom, #33bcef 0%,#019ad2 100%); /* W3C */ + background-repeat: repeat-x; + height: 30px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 5px; + padding-right: 10px; + padding-bottom: 5px; + padding-left: 10px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #057ED0; + border-right-color: #057ED0; + border-bottom-color: #057ED0; + border-left-color: #057ED0; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: #FFFFFF 0px 1px 0px 0px; + position: relative; + display: block; + white-space: nowrap; + border-collapse: collapse; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + border-spacing: 0px 0px; + cursor: pointer; + text-shadow: rgba(0, 0, 0, 0.25) 0px -1px 1px; + } +button#submit-login:hover { + background: -moz-linear-gradient(top, #2daddc 0%, #0271bf 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#2daddc), color-stop(100%,#0271bf)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #2daddc 0%,#0271bf 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #2daddc 0%,#0271bf 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #2daddc 0%,#0271bf 100%); /* IE10+ */ + background: linear-gradient(to bottom, #2daddc 0%,#0271bf 100%); /* W3C */ + background-repeat: repeat-x; + border-color:#096eb3; + color:#fff; + } + + + + + +#remember-forgot { + left: 12px; + margin: 0; + position: absolute; + top: 82px; + width: 276px; + color: #999999; + display: inline; + font-size: 11px; + line-height: 13px; + margin: 3px 0 0 0; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); + text-decoration: none; + font-family: Arial,sans-serif; + } +#remember-forgot span#rememberme_label { + cursor:pointer; + } +#remember-forgot a { + color: #999999; + display: inline; + font-size: 11px; + line-height: 13px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); + text-decoration: none; + } +#remember-forgot a:hover { + text-decoration: underline; + } +#remember-forgot input[type="checkbox"] { + height: 13px; + margin: -1px 0 0 0; + vertical-align: text-top; + } +#username-container { + color: #333333; + left: 12px; + position: absolute; + top: 12px; + width: 276px; + height: 30px; + } +#password-container { + left: 12px; + position: absolute; + top: 48px; + } + +#page-container { + width:837px; + padding:14px 14px 0 14px; + background-color:rgba(0,0,0,0.3); + margin-left:-432.5px; + opacity:0; + } + +#footer { + width:100%; + clear:both; + height:100px; + } + +#user-container { + width:300px; + font-size: 12px; + text-shadow: 0 1px 0 #FFFFFF; + line-height: 16px; + position: relative; + float:left; + } +#user-header, +#user-body, +#user-footer { + border: 1px solid rgba(0, 0, 0, 0.1); + opacity:0; + } +#user-header { + border-bottom:0 none; + border-radius: 6px 6px 0 0; + } +#user-body { + border-top:0 none; + border-bottom:0 none; + } +#user-footer { + border-top:0 none; + border-radius: 0 0 6px 6px; + margin-bottom:10px; + } +#user-header:hover #user-name { + color: #0084B4; + text-decoration:underline; + } + +.menu-container { + border: 1px solid rgba(0, 0, 0, 0.1); + text-shadow: 0 1px 0 #FFFFFF; + background-clip: padding-box; + border-radius: 6px 6px 6px 6px; + line-height: 16px; + margin-bottom: 10px; + overflow:hidden; + opacity:0; + } +.menu-container div:first-child { + border-top-left-radius: 6px; + border-top-right-radius: 6px; + } +.menu-container div:last-child { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + } +.menu-container div { + cursor:pointer; + background-color: #FFFFFF; + color: #0084B4; + text-decoration: none; + padding: 8px 12px; + position: relative; + background-color: #F9F9F9; + border-top: 1px solid #E8E8E8; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset; + font-size: 14px; + } +.menu-container div .chev-right { + background-repeat: no-repeat; + display: block; + height: 13px; + width: 9px; + background-position: 0 -140px; + position: absolute; + right: 12px; + top: 9px; + } +.menu-container div .close-right { + background-repeat: no-repeat; + display: none; + height: 9px; + width: 13px; + background-position: -20px -510px; + margin-left:5px; + margin-top:4px; + } +.menu-container div:hover { + background-color:#fff; + } +.menu-container div:hover .chev-right { + background-position: 0 -160px; + } +.menu-container div:hover .close-right { + display:inline-block; + } +.menu-container div .close-right:hover { + background-position: -40px -510px; + } +.menu-container div.current { + background-color:#fff; + font-weight:bold; + color:#333; + } +.menu-container div.current .chev-right { + background-position: 0 -160px; + } +#history-container { + display:none; + } + +#feed { + display:none; + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + width: 522px; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + float: right; + } + +#feed-header { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + background-clip: padding-box; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 0px; + border-left-width: 1px; + border-top-color: rgba(0, 0, 0,0.1); + border-right-color: rgba(0,0,0,0.1); + border-bottom-color: rgba(0, 0, 0, 0.1); + border-left-color: rgba(0, 0, 0, 0.1); + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1: + } +#feed-header-inner { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + background-color: #FFFFFF; + padding-top: 12px; + padding-right: 12px; + padding-bottom: 12px; + padding-left: 12px; + border-bottom-width: 1px; + border-bottom-color: #E8E8E8; + border-bottom-style: solid; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + min-height: 20px; + } + +#feed-header-inner h2 { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 18px; + font-weight: 700; + color: #333333; + line-height: 20px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + text-rendering: optimizelegibility; + } + +.queet-streams { + bottom: 0; + color: #999999; + display:inline-block; + font-size: 12px; + font-weight: normal; + margin: 3px 6px; + } +.queet-streams a { + text-decoration: none; + cursor:pointer; + } +.queet-streams a:hover { + text-decoration: underline; + } + +#new-queets-bar { + background-color: #F5F5F5; + border-top: 1px solid #DDDDDD; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05) inset; + cursor: pointer; + display: block; + font-size: 13px; + font-weight: normal; + padding: 10px 1px; + position: relative; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.6); + top: -1px; + z-index: 2; + color: #0084B4; + } +#new-queets-bar:hover { + background-color: #eee; + } + +.stream-item { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + background-color: #FFFFFF; + background-image: none; + background-repeat: repeat; + background-position: 0% 0%; + background-attachment: scroll; + background-clip: padding-box; + background-origin: padding-box; + background-size: auto auto; + border-right-width: 1px; + border-left-width: 1px; + border-right-color: rgba(0, 0, 0, 0.1); + border-left-color: rgba(0, 0, 0, 0.1); + border-right-style: solid; + border-left-style: solid; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + -webkit-transition: all 0.1s ease; + -moz-transition: all 0.1s ease; + -o-transition: all 0.1s ease; + transition: all 0.1s ease; + } +.stream-item.hidden { + display:none; + } +.stream-item.conversation { + background-color:#F6F6F6; + border:0 none; + opacity:0.5; + } +.stream-item.conversation.visible { + opacity:1; + } +.stream-item.conversation.hidden-conversation { + display:none; + overflow:hidden; + } +.stream-item.conversation .queet:hover { + background-color:#F6F6F6; + } +.show-full-conversation { + float:right; + font-style:italic; + } +.show-full-conversation:hover { + color:#0084B4; + text-decoration:underline; + } +.queet { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + border-bottom-width: 1px; + border-bottom-color: #E8E8E8; + border-bottom-style: solid; + position: relative; + cursor: pointer; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + min-height: 73px; + } +.stream-item.user .queet { + cursor: auto; + } +.queet:hover { + background-color:#f5f5f5; + } +.stream-item.expanded .queet { + border-bottom:1px solid #ddd; + } +.stream-item.expanded .queet:hover { + background-color:#fff; + } +.stream-item.expanded .stream-item:last-child .queet { + border-bottom:0 none; + } +.stream-item.expanded div:last-child { + border-radius:0 0 6px 6px; + } +body.rtl .queet.rtl .expanded-content { + direction:rtl; + } +body.rtl .queet:not(.rtl) .client-and-actions { + direction:rtl; + text-align:left; + } +body.rtl .queet:not(.rtl) .stream-item-header { + direction: rtl; + text-align: left; + } +.stream-item.expanded div:first-child { + border-radius:6px 6px 0 0; + } +.stream-item.expanded .stream-item.conversation .queet:hover { + background-color:#F6F6F6; + } +.queet:hover .stream-item-expand { + color:#0084B4; + } +.queet:hover .stream-item-expand:hover { + text-decoration:underline; + } + +.stream-item.activity .queet { + min-height:21px; + } +.stream-item.activity .queet-content { + margin-left:0; + } +.stream-item.activity .queet-text { + font-size: 0.85em; + font-style: italic; + margin:0; + text-align:center; + width: 470px; + } + +.stream-item.activity .created-at a { + display:none; + } +.stream-item.activity.expanded .created-at a { + font-size: 0.9em; + display:inline; + } +.view-more-container-top { + border-top: 0 none; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + background: none repeat scroll 0 0 #F6F6F6; + cursor:pointer; + border-bottom: 1px solid #DDDDDD; + } +.view-more-container-bottom { + border-bottom: 0 none; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + background: none repeat scroll 0 0 #F6F6F6; + cursor:pointer; + } +body.rtl .view-more-container-top { direction:rtl; } +body.rtl .view-more-container-bottom { direction:rtl; } +.view-more-container-top a, +.view-more-container-bottom a { + display:block; + font-size: 13px; + padding: 14px 12px 14px 72px; + } +.view-more-container-top:hover a, +.view-more-container-bottom:hover a { + text-decoration:underline; + } + +.queet-content { + margin-left: 58px; + cursor:pointer; + padding-top: 9px; + padding-right: 12px; + padding-bottom: 9px; + padding-left: 12px; + + } +.stream-item.user .queet-content { + cursor: auto; + } + +.stream-item-header { + color:#999; + } + +.stream-item-header a.account-group:hover .name { + text-decoration:underline; + color:#0084B4; + } + +.stream-item-header .avatar { + line-height: 18px; + width: 48px; + height: 48px; + margin-top: 3px; + margin-left: -58px; + border-top-width: 0px; + border-right-width: 0px; + border-bottom-width: 0px; + border-left-width: 0px; + border-top-color: #999999; + border-right-color: #999999; + border-bottom-color: #999999; + border-left-color: #999999; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + float: left; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + cursor: pointer; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + } +.stream-item-header .name { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 14px; + font-weight: 700; + color: #333333; + line-height: 18px; + } +.stream-item-header .screen-name { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 12px; + color: #999999; + line-height: 18px; + direction: ltr; + } +.stream-item-header .created-at { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 12px; + color: #BBBBBB; + line-height: 18px; + margin-top: 1px; + position: relative; + float: right; + } +.stream-item-header .created-at a { + font-family:"Helvetica Neue",Arial,sans-serif; + font-size: 12px; + color: #999999; + text-decoration: none; + line-height: 18px; + } +.stream-item-header .created-at a:hover { + text-decoration: underline; + color:#0084B4; + } + +.dogear { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + vertical-align: text-top; + background-repeat: no-repeat; + width: 24px; + height: 24px; + top: 0px; + right: 0px; + position: absolute; + display: none; + cursor: pointer; + list-style-image: none; + list-style-position: outside; + list-style-type: none + } +.stream-item.requeeted > .queet .dogear { + display: block; + background-position: 0 -450px; + } +.stream-item.favorited > .queet .dogear { + display: block; + background-position: -30px -450px; + } +.stream-item.requeeted.favorited > .queet .dogear { + display: block; + background-position: -60px -450px; + } + +.queet-text { + font-family:"Helvetica Neue",Arial,sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + white-space: pre-wrap; + cursor: pointer; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + word-wrap: break-word; + } +.stream-item.user .queet-text { + cursor: auto; + } + +.queet-text img { + width:100%; + } + +.stream-item .queet-text p { + margin:0;padding:0; + } + +.queet-text span.attachment.more { + color:#0084B4; + } +.queet-text span.attachment.more:hover { + text-decoration:underline; + } + +.stream-item.user .queet-content { + margin-right:150px; + } +.stream-item.user .user-actions { + float:right; + padding:9px 12px; + } +body.rtl .stream-item.user .user-actions { + float:left; + } +body.rtl .stream-item.user .queet-content { + margin-left:150px; + margin-right:58px; + } +body.rtl .stream-item.user .queet-text, +body.rtl .stream-item.user .queet-content .stream-item-header { + text-align:right; + } +body.rtl .stream-item.user .queet-content .stream-item-header .avatar { + float:right; + margin-left:auto; + margin-right:-58px; + } + + +ul.queet-actions { + bottom: 0; + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 12px; + color: #333333; + line-height: 18px; + background-color: #FFFFFF; + right: 1px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 0px; + padding-right: 0px; + padding-bottom: 0px; + padding-left: 5px; + position: absolute; + display: none; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + } +.queet.rtl ul.queet-actions { + right:auto; + left:1px; + padding: 0 5px 0 0; + direction: rtl; + } + +.stream-item:hover > .queet ul.queet-actions { + display: block; + } +.stream-item.expanded > .queet ul.queet-actions { + display: block; + } +.stream-item.expanded > .stream-item.expanded .queet ul.queet-actions { + display: block; + background-color: #f6f6f6; + } +.stream-item:hover:not(.expanded) ul.queet-actions { + background-color: #f6f6f6; + } +ul.queet-actions li { + display:inline; + } +ul.queet-actions li .with-icn { + color: #0084B4; + margin-left: 8px; + } +ul.queet-actions li .with-icn b { + display: inline; + color: inherit; + font-weight: normal; + } +ul.queet-actions li .with-icn b:hover { + text-decoration:underline; + } +ul.queet-actions li .icon { + background-color: #0084B4; + background-repeat: no-repeat; + display: inline-block; + vertical-align: text-top; + height: 13px; + } +ul.queet-actions li.action-rt-container .with-icn.done .icon { + background-color: #609928; + } +ul.queet-actions li.action-rt-container .with-icn.done { + color: #609928; + } +ul.queet-actions li.action-fav-container .with-icn.done .icon { + background-color: #FF9B00; + } +ul.queet-actions li.action-fav-container .with-icn.done { + color: #FF9B00; + } + +ul.queet-actions li .icon.sm-reply { + background-position: 0 -190px; + width: 12px; + } +ul.queet-actions li .icon.sm-rt { + background-position: -20px -190px; + width: 12px; + } +ul.queet-actions li .icon.sm-trash { + background-position: -160px -190px; + width: 12px; + } +ul.queet-actions li .icon.sm-fav { + background-position: -40px -190px; + width: 12px; + } +.stream-item:not(.expanded):hover ul.queet-actions li .icon.sm-reply, +.stream-item.expanded > .stream-item.expanded .queet ul.queet-actions li .icon.sm-reply { + background-position: 0 -220px; + } +.stream-item:not(.expanded):hover ul.queet-actions li .icon.sm-rt, +.stream-item.expanded > .stream-item.expanded .queet ul.queet-actions li .icon.sm-rt { + background-position: -20px -220px; + } +.stream-item:not(.expanded):hover ul.queet-actions li .icon.sm-trash, +.stream-item.expanded > .stream-item.expanded .queet ul.queet-actions li .icon.sm-trash { + background-position: -160px -220px; + } +.stream-item:not(.expanded):hover ul.queet-actions li .icon.sm-fav, +.stream-item.expanded > .stream-item.expanded .queet ul.queet-actions li .icon.sm-fav { + background-position: -40px -220px; + } + + + +.queet.rtl .queet-content { + margin-left:0; + margin-right:58px; + } +.queet.rtl .account-group > .avatar { + float:right; + margin-left:0; + margin-right:-58px; + } +.queet.rtl .stream-item-header { + direction: rtl; + text-align:right; + } +.queet.rtl .account-group > .name { + direction: rtl; + text-align:right; + } +.queet.rtl .account-group > .screen-name { + direction: rtl; + text-align:right; + } +.queet.rtl .created-at { + float:left; + } +.queet.rtl .queet-text { + text-align:right; + direction: rtl; + } +.queet.rtl .stream-item-footer { + text-align: right; + } +.queet.rtl .client-and-actions { + text-align: right; + } +.queet.rtl .show-full-conversation { + float:left; + } +.queet.rtl .inline-reply-queetbox { + padding:15px 70px 15px 12px; + } +.queet-box-template a{ + unicode-bidi:bidi-override; + direction:ltr; + } + +.stream-item-footer { + padding-top:1px; + position:relative; + } + +.stream-item-footer .context { + font-size:14px; + } +.stream-item-footer .with-icn { + font-size:12px; + color:#999; + } +.stream-item-footer .with-icn .badge-requeeted { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 12px; + color: #999999; + line-height: 18px; + vertical-align: -1px; + background-color: transparent; + background-repeat: no-repeat; + background-position: -60px -350px; + width: 16px; + height: 12px; + margin-right: 1px; + display: inline-block; + cursor: pointer; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + } +.stream-item-footer .with-icn .requeet-text { + font-size:12px; + color:#999; + } +.stream-item-footer .with-icn .requeet-text a b { + color:#999; + font-weight:400; + } +.stream-item-footer .with-icn .requeet-text a b:hover { + text-decoration:underline; + color:#0084B4; + } + +.stream-item-expand { + font-size: 12px; + font-weight: 400; + color: #999999; + line-height: 18px; + } + +.stream-item.expanded { + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 6px 6px 6px 6px; + margin:8px 0; + overflow:hidden; + -webkit-transition: all 0.1s ease; + -moz-transition: all 0.1s ease; + -o-transition: all 0.1s ease; + transition: all 0.1s ease; + } +.stream-item.expanded > .queet .stream-item-expand { + color: #0084B4; + } +.stream-item.expanded .stream-item-expand:hover { + text-decoration:underline; + } +.stream-item.expanded .stream-item.expanded { + margin:0 0; + border:0 none; + border-radius: 0 0 0 0; + } + +.stream-item .media { + margin-top:10px; + } +.stream-item .media img { + max-width: 435px; + } + +ul.stats { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 14px; + color: #333333; + line-height: 18px; + margin-top: 10px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 0px; + padding-right: 0px; + padding-bottom: 0px; + padding-left: 0px; + border-top: 1px solid #E8E8E8; + border-bottom: 1px solid #E8E8E8; + overflow-x: hidden; + overflow-y: hidden; + cursor: pointer; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + overflow: hidden; + } +.queet.rtl ul.stats { + text-align:right; + } +ul.stats li { + display:inline; + } +.queet.rtl ul.stats li { + float:right; + } +ul.stats a { + width: auto; + border-left: 1px solid #E8E8E8; + color: #999999; + float: left; + font-size: 10px; + line-height: 16px; + padding: 7px 12px; + text-transform: uppercase; + } +.queet.rtl ul.stats a{ + border-right: 1px solid #E8E8E8; + border-left: 0 none; + } +ul.stats li:first-child a { + padding-left: 0; + } +.queet.rtl ul.stats li:first-child a { + padding-right: 0; + padding-left: 12px; + } +ul.stats li:first-child a { + border-left: 0 none; + } +.queet.rtl ul.stats li:first-child a { + border-right: 0 none; + } + + +ul.stats a strong { + color: #333333; + display: block; + font-size: 14px; + } + +ul.stats .avatar-row { + overflow: hidden; + } +ul.stats .avatar-row a { + padding: 11px 0; + border-left: medium none; + } +ul.stats .avatar-row a:first-child { + border-left: 1px solid #E8E8E8; + padding-left: 12px; + } +.queet.rtl ul.stats .avatar-row a { + border-right: 0 none; + padding-right: 0; + border-left: 0 none; + padding-left: 0; + } +.queet.rtl ul.stats .avatar-row a:last-child { + border-right: 1px solid #E8E8E8; + padding-right: 12px; + border-left: 0 none; + padding-left: 0; + } +ul.stats .avatar-row .avatar { + float: left; + margin-right: 5px; + } +.queet.rtl ul.stats .avatar-row .avatar { + float: left; + margin-left: 5px; + margin-right: 0; + } +.avatar.size24 { + border-radius: 3px 3px 3px 3px; + height: 24px; + width: 24px; + } +.avatar.size30 { + border-radius: 3px 3px 3px 3px; + height: 30px; + width: 30px; + margin:0 1px; + } +ul.stats .avatar-row .avatar { + -moz-force-broken-image-icon: 1; + } + +.client-and-actions { + clear: both; + margin-top: 10px; + overflow: hidden; + } + +.client-and-actions .metadata { + line-height: 24px; + overflow: hidden; + color: #999999; + font-size: 12px; + line-height: 24px; + } + +.permalink-link { + color: #999999; + } +.permalink-link:hover { + text-decoration:underline; + color:#0084B4; + } + +.inline-reply-queetbox { + padding: 15px 12px 15px 70px; + position: relative; + background: none repeat scroll 0 0 #F6F6F6; + border-top:1px solid #DDDDDD; + } +.queet-box-template { + font-family: "Helvetica Neue",Arial,​sans-serif; + font-size: 13px; + color: #AAAAAA; + line-height: 20px; + vertical-align: top; + text-overflow: ellipsis; + background-color: #FFFFFF; + width: 420px; + height: 19px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 8px; + padding-right: 8px; + padding-bottom: 8px; + padding-left: 8px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #CCCCCC; + border-right-color: #CCCCCC; + border-bottom-color: #CCCCCC; + border-left-color: #CCCCCC; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 3px !important; + border-top-right-radius: 3px !important; + border-bottom-left-radius: 3px !important; + border-bottom-right-radius: 3px !important; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) inset, 0 1px 0 rgba(255, 255, 255, 0.075); + outline-color: #AAAAAA; + display: block; + overflow-x: hidden; + overflow-y: hidden; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + outline-style: none; + outline-width: 0px; + overflow: hidden; + text-shadow: none; + word-wrap: normal; + cursor:text; + white-space:nowrap; + } +.queet-box-template[contenteditable="false"] { + opacity:0.5; + } + +.queet-box-template:focus { border-color: #56B4EF; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) inset, 0 0 8px rgba(82, 168, 236, 0.6); color: #333333; outline: 0 none; + } +.queet-box-template.active { + height:80px; + color:#333; + margin-bottom:8px; + white-space:normal; + -webkit-transition: all 0.3s ease; + -moz-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; + } + +#user-header { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + background-color: #F9F9F9; + line-height: 16px; + padding: 12px; + cursor: pointer; + font-size: 12px; + text-shadow: 0 1px 0 #FFFFFF; + line-height: 16px; + font-family: "Helvetica Neue",Arial,sans-serif; + color: #333333; + font-size: 14px; + line-height: 18px; + } +#user-name { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + font-weight: 700; + color: #333333; + line-height: 16px; + display: block; + cursor: pointer; + text-shadow: #FFFFFF 0px 1px 0px; + margin-left:42px; + margin-right:20px; + } +#user-screen-name { + display:none; + } + +#user-profile-link a { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 11px; + color: #999999; + line-height: 16px; + text-overflow: ellipsis; + overflow-x: hidden; + overflow-y: hidden; + white-space: nowrap; + cursor: pointer; + overflow: hidden; + text-shadow: #FFFFFF 0px 1px 0px; + margin-left:42px; + margin-right:20px; + } + +#user-avatar { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 12px; + color: #FF00AE; + line-height: 16px; + width: 32px; + height: 32px; + top: 12px; + left: 12px; + border-top-width: 0px; + border-right-width: 0px; + border-bottom-width: 0px; + border-left-width: 0px; + border-top-color: #FF00AE; + border-right-color: #FF00AE; + border-bottom-color: #FF00AE; + border-left-color: #FF00AE; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + position: absolute; + text-shadow: #FFFFFF 0px 1px 0px: + } + +#user-body { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 12px; + color: #333333; + line-height: 16px; + background-color: #F9F9F9; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 0px; + padding-right: 0px; + padding-bottom: 0px; + padding-left: 0px; + border-top-width: 1px; + border-bottom-width: 1px; + border-top-color: #E8E8E8; + border-bottom-color: #E8E8E8; + border-top-style: solid; + border-bottom-style: solid; + overflow-x: hidden; + overflow-y: hidden; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + overflow: hidden; + text-shadow: #FFFFFF 0px 1px 0px; + } + +#user-body #user-queets, +#user-body #user-groups, +#user-body #user-following, +#user-body #user-followers { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 9.5px; + color: #999999; + text-transform: uppercase; + text-decoration: none; + line-height: 16px; + padding-top: 7px; + padding-right: 10px; + padding-bottom: 7px; + padding-left: 12px; + border-left-width: 0px; + border-left-color: #999999; + border-left-style: none; + float: left; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + text-shadow: #FFFFFF 0px 1px 0px; + } +#user-body #user-following, +#user-body #user-groups, +#user-body #user-followers { + border-left-width: 1px; + border-left-color: #E8E8E8; + border-left-style: solid; + } + +#user-body strong { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 14px; + color: #333333; + text-transform: uppercase; + line-height: 16px; + display: block; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + text-shadow: #FFFFFF 0px 1px 0px; + } +#user-body a { + cursor:pointer; + } +ul.stats li:hover a, +ul.stats li:hover a strong, +#user-body a:hover div strong, +#user-body a:hover div div { + color:#0084B4; + } + +#user-footer { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 12px; + color: #333333; + line-height: 12px; + background-color: #F5F5F5; + padding-top: 10px; + padding-right: 12px; + padding-bottom: 10px; + padding-left: 12px; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + text-shadow: #FFFFFF 0px 1px 0px; + } + +.queet-box { + font-family: "Helvetica Neue",​Arial,​sans-serif; + font-size: 13px; + color: #AAAAAA; + line-height: 18px; + vertical-align: top; + background-color: #FFFFFF; + width: 258px; + height: 19px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 6px; + padding-right: 8px; + padding-bottom: 5px; + padding-left: 8px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #CCCCCC; + border-right-color: #CCCCCC; + border-bottom-color: #CCCCCC; + border-left-color: #CCCCCC; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) inset, 0 1px 0 rgba(255, 255, 255, 0.075); + outline-color: #AAAAAA; + display: block; + overflow-x: hidden; + overflow-y: hidden; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + outline-style: none; + outline-width: 0px; + overflow: hidden; + text-shadow: none; + word-wrap: break-word; + } +#queet-box[contenteditable="true"] { + font-family: "Helvetica Neue",Arial,​sans-serif; + font-size: 13px; + color: #333333; + line-height: 18px; + vertical-align: top; + background-color: #FFFFFF; + width: 258px; + height: 80px; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 8px; + margin-left: 0px; + padding-top: 6px; + padding-right: 8px; + padding-bottom: 5px; + padding-left: 8px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #CCCCCC; + border-right-color: #CCCCCC; + border-bottom-color: #CCCCCC; + border-left-color: #CCCCCC; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) inset, 0 1px 0 rgba(255, 255, 255, 0.075); + outline-color: #333333; + display: block; + overflow-x: hidden; + overflow-y: auto; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + outline-style: none; + outline-width: 0px; + text-shadow: none; + word-wrap: break-word; + } +#queet-box[contenteditable="true"]:focus { + box-shadow:0 1px 3px rgba(0, 0, 0, 0.05) inset, 0 0 8px rgba(82, 168, 236, 0.6); + color:##333333; + outline:0 none; + border-color:#56B4EF; + } + +#queet-toolbar, +#queet-toolbar { + position:relative; + display:none; + height:32px; + } + +#queet-box-extras, +.#queet-box-extras { + float: left; + } + +#queet-button, +.queet-button { + float: right; + } +.queet.rtl .queet-button { + float: left; + } +.queet.rtl .queet-button .queet-counter { + float: right; + text-align:left; + margin-left:5px; + margin-right:0; + } + +#queet-counter, +.queet-counter { + background-color: transparent; + border: 0 none; + color: #999999; + display: inline-block; + font-size: 14px; + padding: 0 3px; + position: relative; + text-align: right; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + top: 7px; + vertical-align: top; + width: 35px; + margin-right: 5px; + } + +#queet-toolbar button, +.queet-toolbar button { + font-family: "Helvetica Neue",Arial,sans-serif; + font-size: 13px; + font-weight: 700; + color: #FFFFFF; + line-height: 16px; + background: -moz-linear-gradient(top, #33bcef 0%, #019ad2 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#33bcef), color-stop(100%,#019ad2)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #33bcef 0%,#019ad2 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #33bcef 0%,#019ad2 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #33bcef 0%,#019ad2 100%); /* IE10+ */ + background: linear-gradient(to bottom, #33bcef 0%,#019ad2 100%); /* W3C */ + background-repeat: repeat-x; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 0px; + margin-left: 0px; + padding-top: 5px; + padding-right: 10px; + padding-bottom: 5px; + padding-left: 10px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #057ED0; + border-right-color: #057ED0; + border-bottom-color: #057ED0; + border-left-color: #057ED0; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: rgba(255, 255, 255, 0.1) 0px 1px 0px 0px inset; + position: relative; + display: inline-block; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch; + border-image-slice: 100% 100% 100% 100%; + border-image-source: none; + border-image-width: 1 1 1 1; + cursor: pointer; + text-shadow: rgba(0, 0, 0, 0.25) 0px -1px 1px; + } +#queet-toolbar button.disabled, +.queet-toolbar button.disabled { + background-color: #DDDDDD; + background-image: none; + border-color: #CCCCCC; + color: #777777; + cursor: default; + opacity: 0.65; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + } +#queet-toolbar button.enabled:hover, +.queet-toolbar button.enabled:hover { + background: -moz-linear-gradient(top, #2daddc 0%, #0271bf 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#2daddc), color-stop(100%,#0271bf)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #2daddc 0%,#0271bf 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #2daddc 0%,#0271bf 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #2daddc 0%,#0271bf 100%); /* IE10+ */ + background: linear-gradient(to bottom, #2daddc 0%,#0271bf 100%); /* W3C */ + background-repeat: repeat-x; + border-color:#096eb3; + color:#fff; + } + +#logo { + width:89px; + height:34px; + display:block; + position:fixed; + z-index:1001; + margin-top:3px; + left:50%; + margin-left:-420px; + background-position:0 0; + cursor:pointer; + } +#logolink:hover #logo { + background-position: 0 34px; + } +#logolink:hover i.nav-session { + background-position: -160px -80px; + } +#logolink:hover .caret { + border-top:4px solid #fff; + } + +#logolink .dropdown-toggle { + left: 50%; + margin-left: -340px; + position: fixed; + z-index: 1001; + } +#logolink .caret { + display:block; + position:absolute; + margin-left:25px; + top:13px; + } +.nav-session { + line-height: 1; + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.75); + background-repeat: no-repeat; + vertical-align: text-top; + background-position: -160px -50px; + height: 21px; + width: 20px; + margin: -4px 6px 0 0; + cursor: pointer; + display: block; + } + + +.profile-card { + background-clip: padding-box; + border-radius: 6px 6px 6px 6px; + line-height: 16px; + margin-bottom: 10px; + border: 1px solid rgba(0, 0, 0, 0.1); + text-shadow: 0 1px 0 #FFFFFF; + float: right; + position: relative; + width: 520px; + } +.modal-body .profile-card { + margin-right:-1px; + margin-top:-5px; + margin-bottom:0; + } +.profile-header-inner { + text-shadow: 0 1px 0 #FFFFFF; + line-height: 16px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + background-color: #444444; + background-repeat: no-repeat; + box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.1) inset; + height: 260px; + overflow: hidden; + padding: 0; + text-align: center; + -webkit-background-size: cover; + -moz-background-size: cover; + -o-background-size: cover; + background-size: cover; + } +.profile-header-inner .profile-header-inner-overlay { + background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0.65) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0.65))); + background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0.65) 100%); + background: -o-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0.65) 100%); + background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0.65) 100%); + background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0.65) 100%); + height: 200px; + position: absolute; + top: 60px; + width: 520px; + } +.profile-header-inner .profile-picture { + outline: 0 none; + background-color: #FFFFFF; + border: 4px solid #FFFFFF; + border-radius: 5px 5px 5px 5px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + display: block; + height: 73px; + margin: 20px auto 6px; + position: relative; + width: 73px; + z-index: 5; + } +.profile-header-inner .profile-picture img { + height: 73px; + width: 73px; + border-radius: 3px 3px 3px 3px; + float: none; + } +.profile-header-inner .profile-card-inner { + text-align: center; + line-height: 16px; + float: none; + margin: auto; + position: relative; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); + width: 85%; + } +.profile-header-inner .profile-card-inner h1.fullname { + text-rendering: optimizelegibility; + font-weight: bold; + line-height: 1; + margin-bottom: 2px; + color: #FFFFFF; + font-size: 24px; + white-space: nowrap; + margin-top:0; + } +.profile-header-inner .profile-card-inner h1.fullname span { + font-size: 24px; + white-space: nowrap; + line-height: 1; + } +.profile-header-inner .profile-card-inner h2.username { + margin-top:0; + color: #FFFFFF; + font-size: 18px; + font-weight: normal; + line-height: 24px; + margin-bottom: 1px; + text-rendering: optimizelegibility; + } +.profile-header-inner .profile-card-inner h2.username a { + color:#fff; + } +.profile-header-inner .profile-card-inner .bio-container { + line-height: 18px; + margin-bottom: 4px; + font-size: 14px; + } +.profile-header-inner .profile-card-inner .bio-container p { + color: #FFFFFF; + margin:0; + } +.profile-header-inner .profile-card-inner .location-and-url { + font-size: 14px; + color: #FFFFFF; + line-height: 18px; + margin:0; + } +.profile-header-inner .profile-card-inner .location-and-url span.divider { + padding: 0 2px; + } +.profile-header-inner .profile-card-inner .location-and-url span a { + color:#fff; + } +.profile-header-inner .profile-card-inner .location-and-url span a:hover { + text-decoration:underline; + } +.profile-banner-footer { + padding: 0; + background-color: #FFFFFF; + line-height: 16px; + text-shadow: 0 1px 0 #FFFFFF; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } +.profile-banner-footer ul.stats { + border-bottom: 0 none; + border-top: 0 none; + margin: 0; + float:left; + } +.profile-banner-footer ul.stats li a { + padding: 10px 15px 8px 12px; + } +.profile-banner-footer ul.stats li:first-child a { + padding-left: 12px; + } +.profile-banner-footer ul.stats li a strong { + } + +.profile-card .user-actions { + position:relative; + float: right; + margin: 10px; + } +div.clearfix { + clear:both; + height:0; + } + +.member-button, +.follow-button { + font-family: "Helvetica Neue",Arial,sans-serif; + margin: 0; + position: relative; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + border: 1px solid #CCCCCC; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + color: #333333; + cursor: pointer; + display: inline-block; + font-size: 13px; + font-weight: bold; + line-height: 18px; + background-color: #DDDDDD; + background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(221,221,221,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(221,221,221,1))); + background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background-repeat: repeat-x; + padding: 0; + } +.member-button.disabled, +.follow-button.disabled { + color:#ccc; + } +.member-button.disabled i, +.follow-button.disabled i { + opacity:0.2; + } +.member-button:not(.disabled):not(.member):hover, +.follow-button:not(.disabled):not(.following):hover { + background-color: #D8D8D8; + background: -moz-linear-gradient(top, rgba(248,248,248,1) 0%, rgba(216,216,216,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(248,248,248,1)), color-stop(100%,rgba(216,216,216,1))); + background: -webkit-linear-gradient(top, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + background: -o-linear-gradient(top, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + background: -ms-linear-gradient(top, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + background: linear-gradient(to bottom, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + border-color: #BBBBBB; + text-decoration: none; + } +.member-button:not(.disabled):not(.member):active, +.follow-button:not(.disabled):not(.following):active { + background: none; + background-color: #D8D8D8; + border-color: #BBBBBB; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) inset, 0 1px 0 rgba(255, 255, 255, 0.5); + } +.member-button .button-text, +.follow-button .button-text { + display:none; + font-family: "Helvetica Neue",Arial,sans-serif; + min-width: 70px; + padding: 5px 7px; + text-align: center; + } +.member-button .join-text, +.follow-button .follow-text { + padding: 5px 20px 5px 60px; + text-align:right; + min-width: 0; + } +.member-button .join-text i, +.follow-button .follow-text i { + background-image: url("../img/button_birds.png"); + display: block; + height: 28px; + margin-left: -50px; + margin-top: -5px; + position: absolute; + width: 40px; + } +.member-button.member, +.follow-button.following { + background-color: #019AD2; + background: -moz-linear-gradient(top, rgba(51,188,239,1) 0%, rgba(1,154,210,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(51,188,239,1)), color-stop(100%,rgba(1,154,210,1))); + background: -webkit-linear-gradient(top, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background: -o-linear-gradient(top, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background: -ms-linear-gradient(top, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background: linear-gradient(to bottom, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background-repeat: repeat-x; + border-color: #057ED0; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.1) inset; + color: #FFFFFF; + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + } +.member-button.member:hover, +.follow-button.following:hover { + background-color: #c43c35; + background: -moz-linear-gradient(top, rgba(238,95,91,1) 0%, rgba(196,60,53,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(238,95,91,1)), color-stop(100%,rgba(196,60,53,1))); + background: -webkit-linear-gradient(top, rgba(238,95,91,1) 0%,rgba(196,60,53,1) 100%); + background: -o-linear-gradient(top, rgba(238,95,91,1) 0%,rgba(196,60,53,1) 100%); + background: -ms-linear-gradient(top, rgba(238,95,91,1) 0%,rgba(196,60,53,1) 100%); + background: linear-gradient(to bottom, rgba(238,95,91,1) 0%,rgba(196,60,53,1) 100%); + background-repeat: repeat-x; + border-color: #a93730 #a93730 #952f2a; + } +.member-button .join-text, +.follow-button .follow-text { + display:block; + } +.member-button.member .join-text, +.follow-button.following .follow-text { + display:none; + } +.member-button.member .ismember-text, +.follow-button.following .following-text { + display:block; + } +.member-button.member:hover .ismember-text, +.follow-button.following:hover .following-text { + display:none; + } +.member-button.member:hover .leave-text, +.follow-button.following:hover .unfollow-text { + display:block; + } + + +/* SPINNER */ + +.spinner-wrap { + position: fixed; + top: 29px; + left:50%; + margin-left:-10px; + z-index:10000; +} +.spinner { + height: 20px; width: 20px; + margin: -20px auto 0; + animation: spin 1s steps(12, end) infinite; + -moz-animation: spin 1s steps(12, end) infinite; + -webkit-animation: spin 1s steps(12, end) infinite; +} + +.spinner i { + height: 5px; width: 2px; + margin-left: -1px; + display: block; + + position: absolute; + left: 50%; + + transform-origin: center 10px; + -webkit-transform-origin: center 10px; + -moz-transform-origin: center 10px; + + background: #fff; + border-radius: 2px; +} + +.spinner i:nth-child(1) { opacity: 0.08; } +.spinner i:nth-child(2) { transform: rotate(30deg); transform: rotate(30deg); transform: rotate(30deg); opacity: 0.167; } +.spinner i:nth-child(3) { transform: rotate(60deg); -moz-transform: rotate(60deg); -webkit-transform: rotate(60deg); opacity: 0.25; } +.spinner i:nth-child(4) { transform: rotate(90deg); -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); opacity: 0.33; } +.spinner i:nth-child(5) { transform: rotate(120deg); -moz-transform: rotate(120deg); -webkit-transform: rotate(120deg); opacity: 0.4167; } +.spinner i:nth-child(6) { transform: rotate(150deg); -moz-transform: rotate(150deg); -webkit-transform: rotate(150deg); opacity: 0.5; } +.spinner i:nth-child(7) { transform: rotate(180deg); -moz-transform: rotate(180deg); -webkit-transform: rotate(180deg); opacity: 0.583; } +.spinner i:nth-child(8) { transform: rotate(210deg); -moz-transform: rotate(210deg); -webkit-transform: rotate(210deg); opacity: 0.67; } +.spinner i:nth-child(9) { transform: rotate(240deg); -moz-transform: rotate(240deg); -webkit-transform: rotate(240deg); opacity: 0.75; } +.spinner i:nth-child(10) { transform: rotate(270deg); -moz-transform: rotate(270deg); -webkit-transform: rotate(270deg); opacity: 0.833; } +.spinner i:nth-child(11) { transform: rotate(300deg); -moz-transform: rotate(300deg); -webkit-transform: rotate(300deg); opacity: 0.9167; } +.spinner i:nth-child(12) { transform: rotate(330deg); -moz-transform: rotate(330deg); -webkit-transform: rotate(330deg); opacity: 1; } + +@keyframes spin { + from { transform: rotate(0deg); -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); } + to { transform: rotate(360deg); -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); } +} + +@-webkit-keyframes spin { + from { transform: rotate(0deg); -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); } + to { transform: rotate(360deg); -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); } +} + +@-moz-keyframes spin { + from { transform: rotate(0deg); -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); } + to { transform: rotate(360deg); -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); } +} + + +/* popups +------------*/ + +.modal-container { + bottom: 0; + display: block; + left: 0; + overflow-x: hidden; + overflow-y: auto; + position: fixed; + right: 0; + top: 0; + z-index: 5000; + background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); + } +.modal-draggable { + margin: 0; + padding-bottom: 30px; + position: relative; + top: 30%; + left: 50%; + width: 520px; + z-index: 6000; + } +.modal-content { + background-clip: padding-box; + background-color: #FFFFFF; + border-radius: 6px 6px 6px 6px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(255, 255, 255, 0.5) inset; + position: relative; + } +.modal-close { + margin: 0; + border: 0 none; + cursor: pointer; + padding: 11px 12px; + background-color: transparent; + cursor: pointer; + padding: 11px 12px; + border-left: 1px solid #DDDDDD; + border-radius: 0 6px 0 0; + box-shadow: 1px 0 0 rgba(255, 255, 255, 0.5) inset; + position: absolute; + right: 0; + top: 0; + } +.modal-close:hover { + background-color:#eee; + } +.modal-close .icon { + cursor: pointer; + background-repeat: no-repeat; + display: inline-block; + vertical-align: text-top; + height: 12px; + width: 10px; + background-position: -60px -510px; + float: left; + } +.modal-close:hover .icon { + background-position: -80px -510px; + } +.modal-header { + padding: 15px; + background-color: #ECECEC; + background-image: -moz-linear-gradient(center top , #F5F5F5 0px, #ECECEC 100%); + background-repeat: repeat-x; + border-bottom: 1px solid #DDDDDD; + border-radius: 6px 6px 0 0; + box-shadow: 0 1px 0 #FFFFFF inset; + cursor: move; + padding-bottom: 8px; + padding-top: 8px; + } +.modal-header h3 { + margin: 0; + text-rendering: optimizelegibility; + font-size: 14px; + color: #555555; + font-size: 14px; + font-weight: bold; + line-height: 18px; + margin: 0 auto; + overflow: hidden; + text-align: center; + text-overflow: ellipsis; + text-shadow: 0 1px 0 #FFFFFF; + white-space: nowrap; + width: 75%; + } +.modal-body { + padding: 0; + text-align: left; + overflow:hidden; + } +.modal-footer { + padding: 15px; + text-align: left; + border-top: 1px solid #DDDDDD; + content: " "; + clear: both; + } +.modal-footer .queet { + border-bottom:0 none; + cursor:auto; + } +.modal-footer .queet:hover { + background-color:#fff; + } +.modal-footer .queet-content { + padding:0; + cursor:auto; + } +.modal-footer .queet-text { + cursor:auto; + } +.modal-body .inline-reply-queetbox { + padding-left:12px; + } +body.rtl .modal-body .inline-reply-queetbox { + direction:rtl; + text-align:right; + } +.modal-body .inline-reply-queetbox .queet-box-template { + width:478px; + } +.modal-body .queet { + background-color:#f5f5f5; + } +.modal-footer div.right { + text-align:right; + } +body.rtl .modal-footer div.right { + text-align:left; + direction:rtl; + } +.modal-footer button { + border: 1px solid #CCCCCC; + border-radius: 4px 4px 4px 4px; + color: #333333; + cursor: pointer; + display: inline-block; + font-size: 13px; + font-weight: bold; + line-height: 18px; + padding: 5px 10px; + position: relative; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + background-color: #DDDDDD; + background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(221,221,221,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(221,221,221,1))); + background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(221,221,221,1) 100%); + background-repeat: repeat-x; + font-family: "Helvetica Neue",Arial,sans-serif; + font-weight:700; + margin-left: 10px; + } +.modal-footer button:hover { + background-color: #D8D8D8; + background: -moz-linear-gradient(top, rgba(248,248,248,1) 0%, rgba(216,216,216,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(248,248,248,1)), color-stop(100%,rgba(216,216,216,1))); + background: -webkit-linear-gradient(top, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + background: -o-linear-gradient(top, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + background: -ms-linear-gradient(top, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + background: linear-gradient(to bottom, rgba(248,248,248,1) 0%,rgba(216,216,216,1) 100%); + border-color: #BBBBBB; + text-decoration: none; + } +.modal-footer button.primary { + background-color: #019AD2; + background: -moz-linear-gradient(top, rgba(51,188,239,1) 0%, rgba(1,154,210,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(51,188,239,1)), color-stop(100%,rgba(1,154,210,1))); + background: -webkit-linear-gradient(top, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background: -o-linear-gradient(top, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background: -ms-linear-gradient(top, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background: linear-gradient(to bottom, rgba(51,188,239,1) 0%,rgba(1,154,210,1) 100%); + background-repeat: repeat-x; + border-color: #057ED0; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.1) inset; + color: #FFFFFF; + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + } +.modal-footer button.primary:hover { + background-color: #0271BF; + background: -moz-linear-gradient(top, rgba(45,173,220,1) 0%, rgba(2,113,191,1) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(45,173,220,1)), color-stop(100%,rgba(2,113,191,1))); + background: -webkit-linear-gradient(top, rgba(45,173,220,1) 0%,rgba(2,113,191,1) 100%); + background: -o-linear-gradient(top, rgba(45,173,220,1) 0%,rgba(2,113,191,1) 100%); + background: -ms-linear-gradient(top, rgba(45,173,220,1) 0%,rgba(2,113,191,1) 100%); + background: linear-gradient(to bottom, rgba(45,173,220,1) 0%,rgba(2,113,191,1) 100%); + background-repeat: repeat-x; + border-color: #096EB3; + color: #FFFFFF; + } +body.rtl .modal-footer button { + font-family:Tahoma,Arial,sans-serif; + margin-left: 10px; + } + +.thread-container { + margin:10px 20px 100px 20px; + } +.thread-container .stream-item { + margin:0; + margin-bottom:1px; + border-radius:3px; + } +.thread-container .stream-item .stream-item-footer { + height: 20px; + } + + + +/* RTL +--------- */ + +body.rtl .profile-card .user-actions { + float: left; + } +body.rtl .profile-banner-footer ul.stats { + float: right; + } + +.queet-text .vcard .mention, +.queet-text .vcard .group, +.queet-text .tag a { + direction:ltr; + } +.queet-text .vcard .mention, +.queet-text .vcard .group { + unicode-bidi:bidi-override; + } +.queet.rtl .queet-text .tag a { + direction:rtl; + } +.queet-text .vcard .mention:before { + content:"@"; + } +.queet.rtl .queet-text .vcard .mention:before { + content: ""; + } +.queet.rtl .queet-text .vcard .mention:after { + content: "@"; + } +.queet-text .vcard .group:before { + content:"!"; + } +.queet.rtl .queet-text .vcard .group:before { + content: ""; + } +.queet.rtl .queet-text .vcard .group:after { + content: "!"; + } +.queet-text .tag a:before { + content:"#"; + } + + +body.rtl table.password-signin { + direction:rtl; + } + +body.rtl .flex-table-primary { + padding-left: 5px; + padding-right: 0; + } + +body.rtl #search { + float:left; + } +body.rtl .search-icon { + left:2px; + right:auto; + } +body.rtl #search-query { + padding: 6px 12px 6px 27px; + direction:rtl; + } +body.rtl .profile-card { + float:left; + margin-left:-1px; + margin-right:auto; + } + +body.rtl #user-body { + direction:rtl; + } + +body.rtl #remember-forgot, +body.rtl #login-content input#username, +body.rtl #login-content input#password, +body.rtl .queet-box, +body.rtl #user-header, +body.rtl .queet-box-template, +body.rtl #new-queets-bar, +body.rtl .queet-actions, +body.rtl .longdate { + direction:rtl; + } +body.rtl #queet-box[contenteditable="true"]:focus { + text-align:right; + direction:rtl; + } +body.rtl #queet-button, +body.rtl .queet-button { + direction: rtl; + float:left; + } +body.rtl #queet-counter, +body.rtl .queet-counter { + margin-right:0; + margin-left:5px; + text-align: left; + } +body.rtl #user-body #user-queets, +body.rtl #user-body #user-following, +body.rtl #user-body #user-groups, +body.rtl #user-body #user-followers, +body.rtl .profile-banner-footer ul.stats li { + float:right; + direction: rtl; + } +body.rtl .profile-banner-footer ul.stats li:first-child a, +body.rtl #user-body #user-queets, +body.rtl #user-body #user-following, +body.rtl #user-body #user-followers { + border-left:1px solid #E8E8E8; + } +body.rtl .profile-banner-footer ul.stats li:last-child a { + border-left:0 none; + } +body.rtl #user-body #user-groups { + border:0 none; + } +body.rtl #user-avatar { + left:auto; + right:12px; + } +body.rtl #user-name, +body.rtl #user-profile-link a { + margin-right: 42px; + margin-left: 20px; + } +body.rtl #user-container { + float: right; + } +body.rtl #feed { + float: left; + } +body.rtl #birds-top { + right:auto; + left:-3px; + } +body.rtl .language-dropdown { + float:left; + direction: rtl; + margin-left: 0; + margin-right: 6px; + } +body.rtl .quitter-settings.dropdown-menu { + left:auto; + right:50%; + margin-right:-410px; + margin-left:0; + } + +body.rtl #logo { + left:auto; + right:50%; + margin-right: -420px; + margin-left:auto; + } +body.rtl .dropdown-caret.right { + right: auto; + left: 10px; + } +body.rtl .dropdown-menu { + float: left; + right: auto; + left:0; + } +body.rtl .dropdown-toggle .caret { + margin-right: 2px; + margin-left:0; + } + +body.rtl #logolink .dropdown-toggle { + left: auto; + right:50%; + margin-left:0; + margin-right: -343px; + direction:rtl; + } +body.rtl #logolink .nav-session { + margin-left:6px; + margin-right:0; + } +body.rtl #logolink .caret { + display:block; + position:absolute; + margin-left:0; + margin-right:25px; + top:13px; + } +body.rtl .menu-container div .chev-right { + right:auto; + left:12px; + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + } +body.rtl .menu-container div .close-right { + margin-right:5px; + } +body.rtl .menu-container div { + direction:rtl; + } + +body.rtl #feed-header-inner h2 { + direction: rtl; + } + +body.rtl, +body.rtl label, +body.rtl .label, +body.rtl input, +body.rtl textarea, +body.rtl select, +body.rtl button, +body.rtl span, +body.rtl span.screen-name, +body.rtl strong.name, +body.rtl a, +body.rtl p, +body.rtl div.queet-text, +body.rtl .dropdown-toggle, +body.rtl #remember-forgot, +body.rtl .queet-box, +body.rtl #new-queets-bar, +body.rtl #user-name, +body.rtl #feed-header-inner h2 { + font-family: Tahoma,Arial,sans-serif !important; + } + + +/* =Responsive Structure +----------------------------------------------- */ + +@media (max-width: 1280px) { + body { + background-size:auto auto; + } + } + +@media (max-width: 1050px) { + .language-dropdown { + position:fixed; + right:100px; + } + body.rtl .language-dropdown { + left:100px; + right:auto; + } + } + +@media (max-width: 866px) { + + #page-container { + width: 520px; + margin-left: -275px; + } + #user-container { + width:522px; + } + #feed { + float:left; + width:524px; + } + #logo { + margin-left: -265px; + } + body.rtl #logo { + margin-right:-265px; + } + #logolink .dropdown-toggle { + margin-left: -187px; + } + body.rtl #logolink .dropdown-toggle { + margin-right: -189px; + margin-left:0; + } + .quitter-settings.dropdown-menu { + margin-left:-260px; + } + body.rtl .quitter-settings.dropdown-menu { + margin-left:0; + margin-right:-260px; + } + + #queet-box, + #queet-box[contenteditable="true"] { + width:478px; + } + } +@media (max-width: 566px) { + + body { + overflow-x:hidden; + } + + #logo{ + margin-left: -48.5%; + } + #logolink .dropdown-toggle { + left:0; + padding-left:5px; + margin-left: 95px; + } + .quitter-settings.dropdown-menu { + left:0; + margin-left:20px; + } + body.rtl .quitter-settings.dropdown-menu { + left:auto; + right:0; + margin-left:0; + margin-right:15px; + } + body.rtl #logolink .dropdown-toggle { + left:auto; + right:0; + padding-left:0; + margin-left: 0; + padding-right:5px; + margin-right: 92px; + } + body.rtl #logo{ + margin-right: -48.5%; + margin-left: auto; + } + #page-container { + width: 200%; + margin-left: -100%; + padding:0; + position:relative; + } + #user-container { + width:95%; + margin-left:2.5%; + margin-top:14px; + } + body.rtl #user-container { + margin-right:2.5%; + margin-left:0; + } + #feed { + width:95%; + margin-left:2.5%; + } + #user-footer { + padding-left:2.5%; + } + + .modal-draggable { + width:95%; + } + #queet-box, + #queet-box[contenteditable="true"], + .queet-box-template, + .modal-body .inline-reply-queetbox .queet-box-template { + width:95%; + } + + .stream-item.activity .queet-text { + width:95%; + } + + .stream-item.expanded .media img { + max-width: 100%; + } + + } + +@media (max-width: 466px) { + #logo { + display:none; + } + #logolink .dropdown-toggle { + margin-left:5px; + } + body.rtl #logolink .dropdown-toggle { + margin-right:5px; + } + + .quitter-settings.dropdown-menu { + left:0; + margin-left:20px; + } + .quitter-settings.dropdown-menu .dropdown-caret { + right: auto; + left: 10px; + } + body.rtl .quitter-settings.dropdown-menu { + left:auto; + right:0; + margin-left:0; + margin-right:20px; + } + body.rtl .quitter-settings.dropdown-menu .dropdown-caret { + left: auto; + right: 10px; + } + + body, .topbar .global-nav { + background-image:none !important; + background-color:#222; + } + #birds-top { + width:80px; + } + #user-footer, #feed-header-inner { + border-radius:0 0 0 0; + } + #user-container { + width:100%; + margin-left:0%; + margin-top:-3px; + margin-bottom:-3px; + } + body.rtl #user-container { + margin-right:-1px; + margin-left:0%; + } + #feed { + width:101%; + margin-left:-1px; + } + #feed-header{ + } + + ul.queet-actions li .with-icn b { + display:none; + } + .stream-item-footer .with-icn .requeet-text { + font-size:0; + } + .stream-item-footer .with-icn .requeet-text a { + font-size:12px; + } + } diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..172b7290f3def8404338b1a12568eee0de4c92ec GIT binary patch literal 1150 zcmah}O=uHA6rQ3`Pu(CW9-1ZuY5i%kp;98)CZ*sHu5AJqq=h6)k*0!8wg`G_R%7Ww zNRSHBgGsfN9t-}QH?8-q60dF|L3%RDQAP87Z_){AXmP{anR)Yl-}{-JFxG`Xn~mYy z$>xtUcA7DE4h>!CY5H+s4EH)80AQUa%kn3;$5Z@jS!Zdl(P(rD>%<*28rKGMuMoTRvlgshBg^j(4reY$v3n z^F}Swp>wtO^;NtVPC@N+3^3uA<(^&T8dOJT9>k5R>g!2mq$o*Jz4TFS@koQ#l#4d& z1$F8?2?^3SPc9AQ}t9 z_S!A3XKdXD|HyDLyOvs&-Th_ileklYFGf1Q#gz>21;wPEkgr;+og@tPO4GFGct=u# z(>^*Jj`E;KE~hh@#oYS3O826D|ET#dVC+vfV^5DUrehIhw0zsB;~f83nua)rI3^)x Jk1-Ru{{Zw(paK8@ literal 0 HcmV?d00001 diff --git a/img/birds.png b/img/birds.png new file mode 100644 index 0000000000000000000000000000000000000000..932841dc432ea3301dbed09662a8cffc81205b8b GIT binary patch literal 5996 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 a$NvXHKtyJqxfL=10000) literal 0 HcmV?d00001 diff --git a/img/birds_rtl.png b/img/birds_rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..3b81dcc047fe34d5ca1298ca219d0c9b3ad672c6 GIT binary patch literal 5962 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�Y8Ixbd{l**c*A2BbH)?X-eLcU% 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 z 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�dlEv%+{OddBix3sstxrW^tvOS= zW@cK6p)o)%b3vR5?*~ResZz|!Zw89WPH5>FJFj{a+a>CW=6x03R~m13#bkeEUOFrg zw^BYeD>bzOra~17~}IubH9P)^qn`3+e3>Yy`z=*(fIlQuBrtFUjkrnre!< zPbXt_*s*0V%^Ua9XNQdN0uI8`PcPzPRz%^9Xf3tL&Pz2qv~&2GyQ)@mH`s{C@ni?c zE!W~>jPhd%HAl(yv}ktDE73IeM_;leLq(RjKYc&mdyR0FxKmu+!0pdFkuR4&_GGwD@@vTCYxdDiH)@qa#fB~i~w<|ZJa|;O!LXl zqr4``eZCGFT8s11;4A5Vx_-%?Fsa0G%c_WYOPZvdV)mz8XCnM$WCBu;snSfstesy8!A>bt=p&bV5axWqYQ|)E>Mu;b+i&-R?7G3uJyCNZydvb*Y@hS`hwx_(IN6fS6ahK%L};RPvB<5g@Cu3&g9p&RmpvqJlVW-b597e@Jh*I|vV=<#vsuy@Q$S4o??& zUCXkWOz3~9U-_ocEK{a7Av)~TTOlTR{*J!&m`lA4dz{go$;$}pr9TCp9r_(#j>te^ zMqbWl(tvcmB2Rx*VuRqc#}y<+HM)8VPB5H|7C8U!{|O`i=}O0lqLVgM2Xel16y|lK zS|vB;8pfEVL1J1-wQ7_~ju1NMMn>r<3`cdD�^8DxZBY#7SdoY@XXrdc{rD``{gw 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 z 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�D|Q(}0<&o>P%91RTJrT{My48x+u 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 literal 0 HcmV?d00001 diff --git a/img/logo.png b/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b90e5b360ac529daea5b28f0c94d23ff99e01123 GIT binary patch literal 5661 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 Dk1`AW literal 0 HcmV?d00001 diff --git a/img/sprite.png b/img/sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..b68fdbb94739ce81be24c0599fba181656954530 GIT binary patch literal 9376 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%0DFdimNr~)PI9=9?LD-*z(!pDHKqrt|3(D?{R4f zUOINQ{;dU=jOP{W@~c*}uSYeAzAvzs37b1ym2n!`ts=R{e$*48nxvCdR$W&7ytHTX z1+*={;)_(!3qSdlf_;~XKN1fD5FIEU`TB|dL&@ep?Ui_VDeg`^kNIo2g<;mspJaezsILr?bY?iD zjRgiA^QBOxm{v&AP4wNEt|tiQIppDh-Jmv#R@G!sOA>Jc@oMy8HCq-8A(`Ml$lA%H zwMK6vHD8>caJ{;;@1Rg~vOfa%Y@lg(0VL+7QKYWUl2QauW>^cu==IL1`aBE9Q#t@c#j`C9HO0F~+7!p@g7U4JSl%2|;iv!% zisUk|9G{QD3^bhDYilBq`mm+(VVhecaQUVX#Y1p1dNr!4Jf=#msB02FG^A(qCP zwtdfD&!H^Vu>vIBfXj$#3pFWm#GJ*gNrU^SLc4)hKKu$wAjLs*6jwhAh5mKdZ7SYC zh!6l0^odS-P{pe~jdb6g1}q<$>W|K9N@_3rNLlTstN=^#7D!pu94%-X&5{vEOy!>` zkU5{@EsrflUjiRA@akQ=6x<5j(40S+kk~sGU*21bNwdNVs-I~C6K1<9Yjw*9GCk$z zO3#;8OeQpV0!3%sKHGc2txG`p-g2xlep@afnQ?MrHSVIzfZkGq$7K2hz|%`0B`VmY z68XGA#7u)&V|B|T{i7U#t(&s&`%al1)$%`XKU+4!IL^2-?|aPst6$JB50uwd0*#!i zT-XsS) z8!gVSe>6T|fFjkroQisuZyjOpX+)|cmqL){q9?!RL;*19PeC9OvGYm79~2<}<#WI%AAkM%$G;%T-}#v3|BSbw!7JN8kUqRlfMeQ4fG>}BUDMRN JlC6Qp{~OjT!twwB literal 0 HcmV?d00001 diff --git a/img/sprite_bgs.png b/img/sprite_bgs.png new file mode 100644 index 0000000000000000000000000000000000000000..0fea51da238aba5bd45fdb4685e751380648acac GIT binary patch literal 3913 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 F{sZv@H)sF= literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..8737892 --- /dev/null +++ b/index.php @@ -0,0 +1,176 @@ + + + + <?php print $sitetitle; ?> + + + + + + + + +
+ +
+
+
+

+
+
+ +
+
+ + +
+ + + + + + + + + + \ No newline at end of file diff --git a/js/ajax-functions-1.js b/js/ajax-functions-1.js new file mode 100644 index 0000000..7cf0380 --- /dev/null +++ b/js/ajax-functions-1.js @@ -0,0 +1,397 @@ + + /* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · + · · + · · + · Q V I T T E R · + · · + · http://github.com/hannesmannerheim/qvitter · + · · + · · + · \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter 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 three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + + +/* · + · + · Check login credentials with http basic auth + · + · @param username: users screen name + · @param password: users password + · @param actionOnSuccess: callback function on log in success + · + · · · · · · · · · */ + +function checkLogin(username,password,actionOnSuccess) { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: 'POST', + data: { + getRequest: "account/verify_credentials.json", + username: username, + password: password + }, + dataType: 'json', + success: function(data) { + if(typeof data.error == 'undefined') { + actionOnSuccess(data); + } + else { + alert(data.error); + remove_spinner(); + $('#submit-login').removeAttr('disabled'); + } + } + }); + } + + + +/* · + · + · Generic API GET request + · + · @param stream: any api get-request e.g. 'statuses/favs/111111.json' + · @param actionOnSuccess: callback function + · + · · · · · · · · · · · · · */ + +function getFromAPI(stream, actionOnSuccess) { + + // request without username/password + if(typeof window.loginUsername == 'undefined') { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + getRequest: stream + }, + dataType: 'json', + success: function(data) { + actionOnSuccess(data); + }, + error: function(data) { + actionOnSuccess(false); + console.log(data); + remove_spinner(); + } + }); + } + // with username/password if set + else { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + getRequest: stream, + username: window.loginUsername, + password: window.loginPassword + }, + dataType: 'json', + success: function(data) { + actionOnSuccess(data); + }, + error: function(data) { + actionOnSuccess(false); + console.log(data); + remove_spinner(); + } + }); + } + } + + + +/* · + · + · Post queet + · + · @param queetText_txt: the text to post + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function postQueetToAPI(queetText_txt, actionOnSuccess) { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + postRequest: 'statuses/update.json', + status: queetText_txt, + source: 'Qvitter', + username: window.loginUsername, + password: window.loginPassword + }, + dataType: "json", + error: function(data){ actionOnSuccess(false); console.log(data); }, + success: function(data) { actionOnSuccess(data);} + }); + } + + +/* · + · + · Post follow or unfollow user request + · + · @param followOrUnfollow: either 'follow' or 'unfollow' + · @param user_id: the user id of the user we want to follow + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function APIFollowOrUnfollowUser(followOrUnfollow,user_id,this_element,actionOnSuccess) { + + if(followOrUnfollow == 'follow') { + var postRequest = 'friendships/create.json'; + } + else if (followOrUnfollow == 'unfollow') { + var postRequest = 'friendships/destroy.json'; + } + + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + postRequest: postRequest, + user_id: user_id, + username: window.loginUsername, + password: window.loginPassword + }, + dataType:"json", + error: function(data){ actionOnSuccess(false,this_element); console.log(data); }, + success: function(data) { actionOnSuccess(data,this_element);} + }); + } + + +/* · + · + · Post join or leave group request + · + · @param joinOrLeave: either 'join' or 'leave' + · @param group_id: group's id + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function APIJoinOrLeaveGroup(joinOrLeave,group_id,this_element,actionOnSuccess) { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + postRequest: 'statusnet/groups/' + joinOrLeave + '.json', + id: group_id, + username: window.loginUsername, + password: window.loginPassword + }, + dataType:"json", + error: function(data){ actionOnSuccess(false,this_element); console.log(data); }, + success: function(data) { actionOnSuccess(data,this_element);} + }); + } + + +/* · + · + · Post reply + · + · @param queetText_txt: the text to post + · @param in_reply_to_status_id: the local id for the queet to reply to + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function postReplyToAPI(queetText_txt, in_reply_to_status_id, actionOnSuccess) { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + postRequest: 'statuses/update.json', + status: queetText_txt, + source: 'Qvitter', + username: window.loginUsername, + password: window.loginPassword, + in_reply_to_status_id: in_reply_to_status_id + }, + dataType:"json", + error: function(data){ actionOnSuccess(false); console.log(data); }, + success: function(data) { actionOnSuccess(data);} + }); + } + + + + +/* · + · + · Generic POST-action + · + · @param action: the api action, e.q. 'statuses/retweet/1.json' + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function postActionToAPI(action, actionOnSuccess) { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + postRequest: action, + source: 'Qvitter', + username: window.loginUsername, + password: window.loginPassword + }, + dataType:"json", + error: function(data){ actionOnSuccess(false); console.log(data); }, + success: function(data) { actionOnSuccess(data);} + }); + } + + +/* · + · + · Generic POST-action + · + · @param action: the api action, e.q. 'statuses/retweet/1.json' + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function postActionToAPI(action, actionOnSuccess) { + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + postRequest: action, + source: 'Qvitter', + username: window.loginUsername, + password: window.loginPassword + }, + dataType:"json", + error: function(data){ actionOnSuccess(false); console.log(data); }, + success: function(data) { actionOnSuccess(data);} + }); + } + + +/* · + · + · Delete requeet + · + · @param this_stream_item: jQuery object for stream-item + · @param this_action: JQuery object for the requeet-button + · @param my_rq_id: the id for the requeet + · + · · · · · · · · · */ + +function unRequeet(this_stream_item, this_action, my_rq_id) { + this_action.children('.with-icn').removeClass('done'); + this_action.find('.with-icn b').html(window.sL.requeetVerb); + this_stream_item.removeClass('requeeted'); + + // post unrequeet + postActionToAPI('statuses/destroy/' + my_rq_id + '.json', function(data) { + if(data) { + remove_spinner(); + this_stream_item.removeAttr('data-requeeted-by-me-id'); + } + else { + remove_spinner(); + this_action.children('.with-icn').addClass('done'); + this_action.find('.with-icn b').html(window.sL.requeetedVerb); + this_stream_item.addClass('requeeted'); + } + }); + } + + + +/* · + · + · Gets favs or requeets for a queet from api + · + · @param apiaction: i.e. 'favs' or 'requeets' + · @param qid: the queet id + · @param actionOnSuccess: callback function + · + · · · · · · · · · */ + +function getFavsOrRequeetsForQueet(apiaction,qid,actionOnSuccess) { + if(apiaction=="requeets") { apiaction="retweets"; } // we might mix this up... + $.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php', + type: "POST", + data: { + getRequest: "statuses/" + apiaction + "/" + qid + ".json", + username: window.loginUsername, + password: window.loginPassword + }, + dataType: 'json', + success: function(data) { + if(data.length > 0) { + actionOnSuccess(data); + } + else { + actionOnSuccess(false); + } + }, + error: function(data) { + remove_spinner(); + console.log(data); + } + }); + } + +/* · + · + · Shorten urls in box + · + · @param apiaction: i.e. 'favs' or 'requeets' + · @param qid: the queet id + · @param actionOnSuccess: callback function + · + · params included to pass along to countCharsInQueetBox + · + · · · · · · · · · · · · · */ + +function shortenUrlsInBox(box,cnt,btn) { + // wrap urls +// var allurls = findUrls(box.html().replace(/&/gi,'&').replace(/ /gi,' ')); +// $.each(allurls,function(key,obj){ +// if(obj.substring(0,15) != 'http://qttr.at/' && obj.length > 20) { // don't shorten if link is qttr.at or very short already +// box.html(box.html().replace(/&/gi,'&').replace(obj,'' + obj + '')); +// placeCaretAtEnd(document.getElementById(box.attr('id'))); +// } +// }); +// +// // shorten urls vith qttr.at +// $.each(box.find('a.shortening'),function(key,obj){ +// display_spinner(); +// var urlEncodedUrl = encodeURIComponent($(obj).html().replace(/&/gi,'&')); +// $.ajax({ url: "http://qttr.at/yourls-api.php?format=jsonp&action=shorturl&signature=b6afeec983&url=" + urlEncodedUrl, type: "GET", dataType: "jsonp", success: function(data) { +// if(typeof data.shorturl != 'undefined') { +// $(obj).before(data.shorturl); +// } +// else { +// $(obj).before($(obj).html()); +// } +// $(obj).remove(); +// remove_spinner(); +// placeCaretAtEnd(document.getElementById(box.attr('id'))); +// countCharsInQueetBox(box,cnt,btn); +// }}); +// }); + } + diff --git a/js/dom-functions-1.js b/js/dom-functions-1.js new file mode 100644 index 0000000..4dea14d --- /dev/null +++ b/js/dom-functions-1.js @@ -0,0 +1,1381 @@ + + /* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · + · · + · · + · Q V I T T E R · + · · + · http://github.com/hannesmannerheim/qvitter · + · · + · · + · \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter 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 three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + + +/* · + · + · Main stream item builder function + · + · Not used yet, I was only thinking that the addToFeed()-function + · hidden far down in this file should be restructured into something + · in this direction. + · + · @param streamItemObj: object with all necessary data to build stream + · + · @return the html of the stream item + · + · · · · · · · · · */ + +function buildStreamItem(streamItemObj) { + + // make a jquery base element + var streamItemContainer = $('
+ + + + + + + +
').append('
'); + var streamItem = streamItemContainer.children('.stream-item'); + + // give it an id + streamItem.attr('id',streamItemObj.id); + + // give it classes + $.each(streamItemObj.classes, function(k,o){ + streamItem.addClass(o); + }); + + return streamItemContainer.html(); + } + + + + +/* · + · + · Show favs or requeets in queet element + · + · @param q: queet jQuery object + · @param users: object with users that has faved or requeeted + · @param type: fav or requeet + · + · · · · · · · · · */ + +function showFavsOrRequeetsInQueet(q,users,type) { + + // label maybe plural + if(users.length == 1) { + if(type=='favs') { var label = window.sL.favoriteNoun; } + else if(type=='requeets') { var label = window.sL.requeetNoun; } + } + else if(users.length > 1) { + if(type=='favs') { var label = window.sL.favoritesNoun; } + else if(type=='requeets') { var label = window.sL.requeetsNoun; } + } + + var html = '
  • ' + users.length + ' ' + label + '
  • '; + + // add fav and rq-container if it doesn't exist + if(!q.find('ul.stats').length > 0) { + q.find('.queet-stats-container').prepend('
    '); + } + + // requeets always first + if(type=='favs') { + q.find('li.avatar-row').before(html.replace('x-count','fav-count')); + } + else if(type=='requeets') { + q.find('ul.stats').prepend(html.replace('x-count','rq-count')); + } + + // show max seven avatars + var avatarnum = q.find('.avatar').length; + if(avatarnum < 7) { + $.each(users,function(){ + + // api return little different objects for fav and rq + var userObj = new Object(); + if(type=='favs') { + userObj = this; + } + else if(type=='requeets') { + userObj.fullname = this.user.name; + userObj.user_id = this.user.id; + userObj.profileurl = this.user.statusnet_profile_url; + userObj.avatarurl = this.user.profile_image_url; + } + + // no dupes + if(q.children('.queet').find('#av-' + userObj.user_id).length==0) { + q.find('.avatar-row').append('' + userObj.fullname + ''); + avatarnum++; + } + return (avatarnum < 8); + }); + } + } + + + +/* · + · + · Adds a profile card before feed element, with data from the first object in the included object + · + · @param data: an object with one or more queet objects + · + · · · · · · · · · */ + +function profileCardFromFirstObject(data,screen_name) { + + var first = new Object(); + for (var i in data) { + if (data.hasOwnProperty(i) && typeof(i) !== 'function') { + first = data[i]; + break; + } + } + + if(typeof first.user != 'undefined') { + + // we don't want to print 'null' + first.user.name = first.user.name || ''; + first.user.profile_image_url = first.user.profile_image_url || ''; + first.user.profile_image_url_profile_size = first.user.profile_image_url_profile_size || ''; + first.user.profile_image_url_original = first.user.profile_image_url_original || ''; + first.user.screen_name = first.user.screen_name || ''; + first.user.description = first.user.description || ''; + first.user.location = first.user.location || ''; + first.user.url = first.user.url || ''; + first.user.statusnet_profile_url = first.user.statusnet_profile_url || ''; + first.user.statuses_count = first.user.statuses_count || 0; + first.user.followers_count = first.user.followers_count || 0; + first.user.friends_count = first.user.friends_count || 0; + + // show user actions if logged in + var followingClass = ''; + if(first.user.following) { + followingClass = 'following'; + } + var followButton = ''; + if(typeof window.loginUsername != 'undefined' && window.myUserID != first.user.id) { + var followButton = ''; + } + + $('#feed').before(''); + } + + // if user hasn't queeted or if we're not allowed to read their queets + else { + getFromAPI('users/show/' + screen_name + '.json', function(data){ if(data){ + data.name = data.name || ''; + data.profile_image_url = data.profile_image_url || ''; + data.profile_image_url_profile_size = data.profile_image_url_profile_size || ''; + data.profile_image_url_original = data.profile_image_url_original || ''; + data.screen_name = data.screen_name || ''; + data.description = data.description || ''; + data.location = data.location || ''; + data.url = data.url || ''; + data.statusnet_profile_url = data.statusnet_profile_url || ''; + data.statuses_count = data.statuses_count || 0; + data.followers_count = data.followers_count || 0; + data.groups_count = data.groups_count || 0; + data.friends_count = data.friends_count || 0; + + // show user actions if logged in + var followingClass = ''; + if(data.following) { + followingClass = 'following'; + } + var followButton = ''; + if(typeof window.loginUsername != 'undefined' && window.myUserID != data.id) { + var followButton = ''; + } + + $('#feed').before(''); + }}); + } + } + + + + +/* · + · + · Adds a group profile card before feed element + · + · @param data: an object with one or more queet objects + · + · · · · · · · · · */ + +function groupProfileCard(groupAlias) { + getFromAPI('statusnet/groups/show/' + groupAlias + '.json', function(data){ if(data){ + + data.nickname = data.nickname || ''; + data.fullname = data.fullname || ''; + data.stream_logo = data.stream_logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-stream.png'; + data.homepage_logo = data.homepage_logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-profile.png'; + data.original_logo = data.original_logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-profile.png'; + data.description = data.description || ''; + data.homepage = data.homepage || ''; + data.url = data.url || ''; + data.member_count = data.member_count || 0; + data.admin_count = data.admin_count || 0; + + // show user actions if logged in + var memberClass = ''; + if(data.member) { + memberClass = 'member'; + } + var memberButton = ''; + if(typeof window.loginUsername != 'undefined') { + var memberButton = ''; + } + + // add card to DOM + $('#feed').before(''); + }}); + } + + + +/* · + · + · Change stream + · + · @param stream: part of the url to the api (everything after api base url) + · @param actionOnSuccess: callback function on success + · + · · · · · · · · · */ + +function setNewCurrentStream(stream,actionOnSuccess,setLocation) { + + // don't do anything if this stream is already the current + if(window.currentStream == stream) { + return; + } + + // set location bar from stream + if(setLocation && window.useHistoryPushState) { + setUrlFromStream(stream); + } + + // halt interval that checks for new queets + window.clearInterval(checkForNewQueetsInterval); + + display_spinner(); + $(window).scrollTop(0); + $('#feed-body').removeAttr('data-search-page-number'); // null any searches + + // remember the most recent stream selection in global var + window.currentStream = stream; + + // if this is a @user stream, i.e. user's queets, user's followers, user's following, we set _queets_ as the default stream in the menu + if(stream.substring(0,36) == 'statuses/followers.json?screen_name=' + || stream.substring(0,34) == 'statuses/friends.json?screen_name=' + || stream.substring(0,39) == 'statusnet/groups/list.json?screen_name=' + || stream.substring(0,43) == 'statuses/friends_timeline.json?screen_name=' + || stream.substring(0,27) == 'favorites.json?screen_name=' + || stream.substring(0,35) == 'statuses/mentions.json?screen_name=' + || stream.substring(0,27) == 'statuses/user_timeline.json') { + var defaultStreamName = 'statuses/user_timeline' + stream.substring(stream.indexOf('.json')); + var streamHeader = '@' + stream.substring(stream.indexOf('=')+1); + } + // if this is a my user streams, i.e. my followers, my following + else if(stream == 'statuses/followers.json' + || stream == 'statuses/friends.json' + || stream == 'statusnet/groups/list.json') { + var defaultStreamName = stream; + var streamHeader = '@' + window.loginUsername; + } + // if this is one of the default streams, get header from DOM + else if(stream == 'statuses/friends_timeline.json' + || stream == 'statuses/mentions.json' + || stream == 'favorites.json' + || stream == 'statuses/public_timeline.json') { + var defaultStreamName = stream; + var streamHeader = $('.stream-selection[data-stream-name="' + stream + '"]').attr('data-stream-header'); + } + + // if this is a !group stream + else if(stream.substring(0,26) == 'statusnet/groups/timeline/') { + var defaultStreamName = stream; + var streamHeader = '!' + stream.substring(stream.indexOf('/timeline/')+10,stream.indexOf('.json')); + } + // if this is a #tag stream + else if(stream.substring(0,24) == 'statusnet/tags/timeline/') { + var defaultStreamName = stream; + var streamHeader = '#' + stream.substring(stream.indexOf('/timeline/')+10,stream.indexOf('.json')); + } + // if this is a search stream + else if(stream.substring(0,11) == 'search.json') { + var defaultStreamName = stream; + var streamHeader = window.sL.searchVerb + ': ' + decodeURIComponent(stream.substring(stream.indexOf('?q=')+3)); + } + + // set the h2 header in the feed + if(stream.substring(0,23) == 'statuses/followers.json') { + var h2FeedHeader = window.sL.followers; + } + else if(stream.substring(0,21) == 'statuses/friends.json') { + var h2FeedHeader = window.sL.following; + } + else if(stream.substring(0,40) == 'statuses/user_timeline.json?screen_name=') { + var h2FeedHeader = window.sL.notices + ''; + } + else if(stream.substring(0,35) == 'statuses/mentions.json?screen_name=') { + var h2FeedHeader = '' + window.sL.mentions + ''; + } + else if(stream.substring(0,27) == 'favorites.json?screen_name=') { + var h2FeedHeader = '' + window.sL.favoritesNoun; + } + else if(stream.substring(0,26) == 'statusnet/groups/list.json') { + var h2FeedHeader = window.sL.groups; + } + else if(stream.substring(0,43) == 'statuses/friends_timeline.json?screen_name=') { + var h2FeedHeader = '' + streamHeader + '/all'; // ugly rtl fix, sry, we should have translations for this stream header + } + else { + var h2FeedHeader = streamHeader; + } + + // fade out + $('#feed,.profile-card').animate({opacity:'0'},150,function(){ + // when fade out finishes, remove any profile cards + $('.profile-card').remove(); + $('#feed-header-inner h2').html(h2FeedHeader); + }); + + // add this stream to history menu if it doesn't exist there (but not if this is me or if we're not logged in) + if($('.stream-selection[data-stream-header="' + streamHeader + '"]').length==0 + && streamHeader != '@' + window.loginUsername + && typeof window.loginUsername != 'undefined') { + $('#history-container').append('
    ' + streamHeader + '
    '); + updateHistoryLocalStorage(); + } + + // mark this stream as current in menu + $('.stream-selection').removeClass('current'); + $('.stream-selection[data-stream-header="' + streamHeader + '"]').addClass('current'); + + // if this is user's user feed, i.e. followers etc, we want a profile card, which we need to get from user_timeline since the users/show api action is broken (auth doesn't work) + if(stream.substring(0,23) == 'statuses/followers.json' + || stream.substring(0,21) == 'statuses/friends.json' + || stream.substring(0,26) == 'statusnet/groups/list.json' + || stream.substring(0,35) == 'statuses/mentions.json?screen_name=' + || stream.substring(0,27) == 'favorites.json?screen_name=' + || stream.substring(0,43) == 'statuses/friends_timeline.json?screen_name=') { + getFromAPI(defaultStreamName + '&count=1', function(profile_data){ + if(profile_data) { + getFromAPI(stream, function(user_data){ + if(user_data) { + // while waiting for this data user might have changed stream, so only proceed if current stream still is this one + if(window.currentStream == stream) { + profileCardFromFirstObject(profile_data,window.loginUsername); // show profile card + checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling); // start interval again + remove_spinner(); + $('#feed-body').html(''); // empty feed only now so the scrollers don't flicker on and off + addToFeed(user_data, false,'visible'); // add stream items to feed element + $('#feed').animate({opacity:'1'},150); // fade in + $('body').removeClass('loading-older');$('body').removeClass('loading-newer'); + actionOnSuccess(); // return + } + } + }); + } + }); + } + + // if this is a queet stream + else { + getFromAPI(stream, function(queet_data){ + if(queet_data) { + // while waiting for this data user might have changed stream, so only proceed if current stream still is this one + if(window.currentStream == stream) { + + // show profile card if this is a user's queet stream + if(stream.substring(0,27) == 'statuses/user_timeline.json') { + var thisUsersScreenName = stream.replace('statuses/user_timeline.json','').replace('?screen_name=','').replace('?id=','').replace('?user_id=',''); + profileCardFromFirstObject(queet_data,thisUsersScreenName); + } + // show group profile card if this is a group stream + else if(stream.substring(0,26) == 'statusnet/groups/timeline/') { + var thisGroupAlias = stream.replace('statusnet/groups/timeline/','').replace('.json',''); + groupProfileCard(thisGroupAlias); + } + + checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling); // start interval again + remove_spinner(); + $('#feed-body').html(''); // empty feed only now so the scrollers don't flicker on and off + addToFeed(queet_data, false,'visible'); // add stream items to feed element + $('#feed').animate({opacity:'1'},150); // fade in + $('body').removeClass('loading-older');$('body').removeClass('loading-newer'); + actionOnSuccess(); // return + } + } + }); + } + } + + +/* · + · + · Sets the location bar in the browser to correspond with given stream + · + · @param stream: the stream, e.g. 'public_timeline.json' + · + · · · · · · · · · */ + +function setUrlFromStream(stream) { + + if(stream.substring(0,36) == 'statuses/followers.json?screen_name=') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName + '/subscribers'); + } + else if(stream.substring(0,34) == 'statuses/friends.json?screen_name=') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName + '/subscriptions'); + } + else if(stream.substring(0,35) == 'statuses/mentions.json?screen_name=') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName + '/replies'); + } + else if(stream.substring(0,27) == 'favorites.json?screen_name=') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName + '/favorites'); + } + else if(stream.substring(0,39) == 'statusnet/groups/list.json?screen_name=') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName + '/groups'); + } + else if(stream == 'statuses/followers.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/subscribers'); + } + else if(stream == 'statuses/friends.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/subscriptions'); + } + else if(stream == 'statuses/mentions.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/replies'); + } + else if(stream == 'favorites.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/favorites'); + } + else if(stream == 'statusnet/groups/list.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/groups'); + } + else if (stream.substring(0,27) == 'statuses/user_timeline.json') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName); + } + else if(stream == 'statuses/friends_timeline.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/all'); + } + else if(stream.substring(0,43) == 'statuses/friends_timeline.json?screen_name=') { + var screenName = stream.substring(stream.indexOf('=')+1); + history.pushState({strm:stream},'','/' + screenName + '/all'); + } + else if (stream == 'statuses/mentions.json') { + history.pushState({strm:stream},'','/' + window.loginUsername + '/replies'); + } + else if(stream == 'statuses/public_timeline.json') { + history.pushState({strm:stream},'','/'); + } + else if(stream.substring(0,26) == 'statusnet/groups/timeline/') { + var groupName = stream.substring(stream.indexOf('/timeline/')+10,stream.indexOf('.json')); + history.pushState({strm:stream},'','/group/' + groupName); + } + else if(stream.substring(0,24) == 'statusnet/tags/timeline/') { + var tagName = stream.substring(stream.indexOf('/timeline/')+10,stream.indexOf('.json')); + history.pushState({strm:stream},'','/tag/' + tagName); + } + else if(stream.substring(0,11) == 'search.json') { + var searchTerms = stream.substring(stream.indexOf('?q=')+3); + history.pushState({strm:stream},'','/search/notice?q=' + searchTerms); + } + } + + + +/* · + · + · Get stream from location bar + · + · @param stream: the stream, e.g. 'public_timeline.json' + · + · · · · · · · · · */ + +function getStreamFromUrl() { + var loc = window.location.href.replace('http://','').replace('https://','').replace(window.siteRootDomain,''); + + // default/fallback + var streamToSet = 'statuses/public_timeline.json'; + + // {domain}/{screen_name} + if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','')))) { + var userToStream = loc.replace('/',''); + if(userToStream.length>0) { + streamToSet = 'statuses/user_timeline.json?screen_name=' + userToStream; + } + } + + // {domain}/{screen_name}/all + else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/all','')))) { + var userToStream = loc.replace('/','').replace('/all',''); + if(userToStream.length>0) { + if(window.loginUsername == userToStream) { + streamToSet = 'statuses/friends_timeline.json'; + } + else { + streamToSet = 'statuses/friends_timeline.json?screen_name=' + userToStream; + } + } + } + + // {domain}/{screen_name}/replies + else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/replies','')))) { + var userToStream = loc.replace('/','').replace('/replies',''); + if(userToStream.length>0) { + if(window.loginUsername == userToStream) { + streamToSet = 'statuses/mentions.json'; + } + else { + streamToSet = 'statuses/mentions.json?screen_name=' + userToStream; + } + } + } + + // {domain}/{screen_name}/favorites + else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/favorites','')))) { + var userToStream = loc.replace('/','').replace('/favorites',''); + if(userToStream.length>0) { + if(window.loginUsername == userToStream) { + streamToSet = 'favorites.json'; + } + else { + streamToSet = 'favorites.json?screen_name=' + userToStream; + } + } + } + + // {domain}/{screen_name}/subscribers + else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/subscribers','')))) { + var userToStream = loc.replace('/','').replace('/subscribers',''); + if(userToStream.length>0) { + if(window.loginUsername == userToStream) { + streamToSet = 'statuses/followers.json'; + } + else { + streamToSet = 'statuses/followers.json?screen_name=' + userToStream; + } + } + } + + // {domain}/{screen_name}/subscriptions + else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/subscriptions','')))) { + var userToStream = loc.replace('/','').replace('/subscriptions',''); + if(userToStream.length>0) { + if(window.loginUsername == userToStream) { + streamToSet = 'statuses/friends.json'; + } + else { + streamToSet = 'statuses/friends.json?screen_name=' + userToStream; + } + } + } + + // {domain}/{screen_name}/groups + else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/groups','')))) { + var userToStream = loc.replace('/','').replace('/groups',''); + if(userToStream.length>0) { + if(window.loginUsername == userToStream) { + streamToSet = 'statusnet/groups/list.json'; + } + else { + streamToSet = 'statusnet/groups/list.json?screen_name=' + userToStream; + } + } + } + + // {domain}/tag/{tag} + else if (loc.indexOf('/tag/')>-1) { + var tagToStream = loc.replace('/tag/',''); + if(tagToStream.length>0) { + streamToSet = 'statusnet/tags/timeline/' + tagToStream + '.json'; + } + } + + // {domain}/group/{group} + else if (loc.indexOf('/group/')>-1) { // we assume we don't get any /group/{id}/id-urls, because we shouldn't + var groupToStream = loc.replace('/group/',''); + if(groupToStream.length>0) { + streamToSet = 'statusnet/groups/timeline/' + groupToStream + '.json'; + } + } + + // {domain}/search/notice?q={urlencoded searh terms} + else if (loc.indexOf('/search/notice?q=')>-1) { + var searchToStream = loc.replace('/search/notice?q=',''); + if(userToStream.length>0) { + streamToSet = 'search.json?q=' + searchToStream; + } + } + return streamToSet; + } + + +/* · + · + · Expand/de-expand queet + · + · @param q: the stream item to expand + · + · · · · · · · · · */ + +function expand_queet(q) { + + var qid = q.attr('data-quitter-id'); + + // de-expand if expanded + if(q.hasClass('expanded') && !q.hasClass('collapsing')) { + q.addClass('collapsing'); + q.find('.stream-item-expand').html(window.sL.expand); + if(q.hasClass('conversation')) { + q.removeClass('expanded'); + q.removeClass('collapsing'); + q.find('.expanded-content').remove(); + q.find('.view-more-container-top').remove(); + q.find('.view-more-container-bottom').remove(); + q.find('.stream-item.conversation').remove(); + q.find('.inline-reply-queetbox').remove(); + } + else { + var collapseTime = 200 + q.find('.stream-item.conversation:not(.hidden-conversation)').length*50; + q.find('.expanded-content').slideUp(collapseTime,function(){$(this).remove();}); + q.find('.view-more-container-top').slideUp(collapseTime,function(){$(this).remove();}); + q.find('.view-more-container-bottom').slideUp(collapseTime,function(){$(this).remove();}); + q.find('.stream-item.conversation').slideUp(collapseTime,function(){$(this).remove();}); + q.find('.inline-reply-queetbox').slideUp(collapseTime,function(){$(this).remove();}); + backToMyScrollPos(q,qid,'animate'); + setTimeout(function(){ + q.removeClass('expanded'); + q.removeClass('collapsing'); + },collapseTime+500); + } + } + else { + + rememberMyScrollPos(q,qid,-8); + + q.addClass('expanded'); + + // not for acitivity + if(!q.hasClass('activity')) { + q.find('.stream-item-expand').html(window.sL.collapse); + + // if shortened queet, get full text (not if external) + if(!q.hasClass('external-conversation')) { + if(q.children('.queet').find('span.attachment.more').length>0) { + var attachmentId = q.children('.queet').find('span.attachment.more').attr('data-attachment-id'); + getFromAPI("attachment/" + attachmentId + ".json",function(data){ + if(data) { + q.children('.queet').find('.queet-text').html($.trim(data.replace(/@/gi,'').replace(/!/gi,'').replace(/#/gi,''))); + } + }); + } + } + + // add expanded container + var longdate = parseTwitterLongDate(q.find('.created-at').attr('data-created-at')); + var qurl = q.find('.created-at').find('a').attr('href'); + + var metadata = '' + longdate + ' · ' + window.sL.details + ''; + + // show expanded content + q.find('.stream-item-footer').after('
    '); + + // maybe show images + $.each(q.children('.queet').find('.queet-text').find('a'), function() { + var attachment_title = $(this).attr('title'); + if(typeof attachment_title != 'undefined') { + if(attachment_title.substr(attachment_title.length - 5) == '.jpeg' || + attachment_title.substr(attachment_title.length - 4) == '.png' || + attachment_title.substr(attachment_title.length - 4) == '.gif' || + attachment_title.substr(attachment_title.length - 4) == '.jpg') { + q.children('.queet').find('.expanded-content').prepend('
    '); + } + } + }); + + // get favs and rq:s (not if external) + if(!q.hasClass('external-conversation')) { + + // get and show favs + getFavsOrRequeetsForQueet('favs',qid,function(favs){ + if(favs) { + if(q.hasClass('expanded') && !q.hasClass('collapsing')) { + showFavsOrRequeetsInQueet(q,favs,'favs'); + } + } + }); + + // get and show requeets + getFavsOrRequeetsForQueet('retweets',qid,function(requeets){ + if(requeets) { + if(q.hasClass('expanded') && !q.hasClass('collapsing')) { + showFavsOrRequeetsInQueet(q,requeets,'requeets'); + } + } + }); + } + + // show conversation and reply form (but not if already in conversation) + if(!q.hasClass('conversation')) { + + // show conversation + showConversation(qid); + + // show inline reply form + q.find('#q-' + qid).append(replyFormHtml(q,qid)); + + } + } + } + } + + + + +/* · + · + · Get a reply form + · + · @param q: the stream item to open reply form in + · @param qid: queet id + · @return the html for the reply form + · + · · · · · · · · · */ + +function replyFormHtml(q,qid) { + // get all @:s + var user_screen_name = q.find('.queet').find('.screen-name').html().substring(1); + var user_screen_name_html = '@' + user_screen_name + ''; + var reply_to_screen_name = ''; + var reply_to_screen_name_html = ''; + if(q.attr('data-in-reply-to-screen-name').length>0 // not if not a reply + && q.attr('data-in-reply-to-screen-name') != $('#user-screen-name').html() // not if it's me + && q.attr('data-in-reply-to-screen-name') != user_screen_name // not same screen name twice + ) { + reply_to_screen_name = q.attr('data-in-reply-to-screen-name'); + reply_to_screen_name_html = ' @' + reply_to_screen_name + ''; + } + var more_reply_tos = ''; + $.each(q.find('.queet').find('.queet-text').find('.mention'),function(key,obj){ + if($(obj).html() != user_screen_name && $(obj).html() != reply_to_screen_name && $(obj).html() != $('#user-screen-name').html()) { + more_reply_tos = more_reply_tos + ' @' + $(obj).html() + ''; + } + }); + + return '
    ') + ' data-start-html="' + escape(user_screen_name_html + reply_to_screen_name_html + more_reply_tos) + '">' + window.sL.replyTo + ' ' + user_screen_name_html + reply_to_screen_name_html + more_reply_tos + ' 
    '; + } + + +/* · + · + · Popup for replies, deletes, etc + · + · @param popupId: popups id + · @param heading: popops header + · @param bodyHtml: popups body html + · @param footerHtml: popups footer html + · + · · · · · · · · · · · · · */ + +function popUpAction(popupId, heading, bodyHtml, footerHtml){ + var allFooterHtml = ''; + if(footerHtml) { + allFooterHtml = ''; + } + $('body').prepend(''); + var this_modal_height = $('#' + popupId).children('.modal-draggable').height(); + var this_modal_width = $('#' + popupId).children('.modal-draggable').width(); + var popupPos = $('#' + popupId).children('.modal-draggable').offset().top - $(window).scrollTop(); + if((popupPos-(this_modal_height/2))<5) { + var marginTop = 5-popupPos; + } + else { + var marginTop = 0-this_modal_height/2; + } + $('#' + popupId).children('.modal-draggable').css('margin-top', marginTop + 'px'); + $('#' + popupId).children('.modal-draggable').css('margin-left', '-' + (this_modal_width/2) + 'px'); + $('#' + popupId).children('.modal-draggable').draggable({ handle: ".modal-header" }); + $('#' + popupId).children('.modal-header').disableSelection(); + } + + + +/* · + · + · Expand inline reply form + · + · @param box: jQuery object for the queet box that we want to expand + · + · · · · · · · · · · · · · */ + +function expandInlineQueetBox(box) { + if(!box.hasClass('active')) { + box.addClass('active'); + // remove the "reply/svara/etc" before the mentions + var new_mentions_html = ''; + $.each(box.find('a'),function(key,obj){ + new_mentions_html = new_mentions_html + '' + $(obj).html() + ' '; + }); + box.html(new_mentions_html); + placeCaretAtEnd(document.getElementById(box.attr('id'))); + + // show toolbar/button + box.after('
    '); + + // count chars + countCharsInQueetBox(box,box.parent().find('.queet-toolbar .queet-counter'),box.parent().find('.queet-toolbar button')); + } + } + + + +/* · + · + · Show conversation + · + · This function has grown into a monster, needs fixing + · + · · · · · · · · · · · · · */ + +function showConversation(qid) { + + display_spinner(); + + // get conversation + getFromAPI('statusnet/conversation/' + $('#stream-item-' + qid).attr('data-conversation-id') + '.json?count=100', function(data){ if(data) { + + if(data && !$('#stream-item-' + qid).hasClass('collapsing')){ + // we have local conversation + if(data.length>1) { + var before_or_after = 'after'; + $.each(data, function (key,obj) { + + // switch to append after original queet + if(obj.id == qid) { + before_or_after = 'before'; + } + + // don't add clicked queet to DOM, but all else + // note: first we add the full conversation, but hidden + if(obj.id != qid) { + var queetTime = parseTwitterDate(obj.created_at); + + // we don't want to print 'null', someone might have that username! + var in_reply_to_screen_name = ''; + if(obj.in_reply_to_screen_name != null) { + in_reply_to_screen_name = obj.in_reply_to_screen_name; + } + + // requeet or delete html + var requeetedClass = ''; + if(obj.user.id == window.myUserID) { + var requeetHtml = '
  • ' + window.sL.deleteVerb + '
  • '; + } + else if(obj.repeated) { + var requeetHtml = '
  • ' + window.sL.requeetedVerb + '
  • '; + requeetedClass = 'requeeted'; + } + else { + var requeetHtml = '
  • ' + window.sL.requeetVerb + '
  • '; + } + // favorite html + var favoritedClass = ''; + if(obj.favorited) { + var favoriteHtml = ' ' + window.sL.favoritedVerb + ''; + favoritedClass = 'favorited'; + } + else { + var favoriteHtml = ' ' + window.sL.favoriteVerb + ''; + } + + if(obj.source == 'activity') { + var queetHtml = '
    ' + $.trim(obj.statusnet_html) + '
    '; + } + else { + var queetHtml = '
    ' + $.trim(obj.statusnet_html) + '
    '; + } + + // detect rtl + queetHtml = detectRTL(queetHtml); + + if($('#stream-item-' + qid).hasClass('expanded')) { // add queet to conversation only if still expanded + if(before_or_after == 'before') { + $('#stream-item-' + qid).prepend(queetHtml); + } + else { + $('#q-' + qid).after(queetHtml); + } + + } + } + remove_spinner(); + convertAttachmentMoreHref(); + }); + } + + // try to get conversation from external instance + else if(typeof data[0] != 'undefined') { + if(data[0].source == 'ostatus') { + var external_status_url = data[0].uri.replace('notice','api/statuses/show') + '.json'; + var external_base_url = data[0].uri.substring(0,data[0].uri.indexOf('/notice/')); + $.ajax({ url: external_status_url, type: "GET", dataType: "jsonp", success: function(data) { // try to get conversation id fro notice + var external_id = data.id; + if(typeof data.statusnet_conversation_id == 'undefined') { + console.log(data);remove_spinner(); + } + else { // proceed if we got a conversation_id + $.ajax({ url: external_base_url + '/api/statusnet/conversation/' + data.statusnet_conversation_id + ".json?count=100", type: "GET", dataType: "jsonp", success: function(data) { + var before_or_after = 'after'; + $.each(data, function (key,obj) { + + // switch to append after original queet + if(obj.id == external_id) { + before_or_after = 'before'; + $('#stream-item-' + qid).attr('data-in-reply-to-status-id',obj.in_reply_to_status_id); + } + else { + var queetTime = parseTwitterDate(obj.created_at); + + // we don't want to print 'null', someone might have that username! + var in_reply_to_screen_name = ''; + if(obj.in_reply_to_screen_name != null) { + in_reply_to_screen_name = obj.in_reply_to_screen_name; + } + + + if(obj.source == 'activity') { + var queetHtml = '
    ' + $.trim(obj.statusnet_html) + '
    '; + } + else { + var queetHtml = '
    ' + $.trim(obj.statusnet_html) + '
    '; + } + + // detect rtl + queetHtml = detectRTL(queetHtml); + + if($('#stream-item-' + qid).hasClass('expanded')) { // add queet to conversation only if still expanded + if(before_or_after == 'before') { + $('#stream-item-' + qid).prepend(queetHtml); + } + else { + $('#q-' + qid).after(queetHtml); + } + } + } + remove_spinner(); + convertAttachmentMoreHref(); + }); + findInReplyToStatusAndShow(qid,$('#stream-item-' + qid).attr('data-in-reply-to-status-id'),true,false); + backToMyScrollPos($('#q-' + qid),qid,false); + }, error: function(data) { console.log(data);remove_spinner(); }}); + } + }, error: function(data) { console.log(data);remove_spinner(); }}); + } + // no conversation + else { + remove_spinner(); + } + } + else { + remove_spinner(); + } + + // loop trough this stream items conversation and show the "strict" line of replies + findInReplyToStatusAndShow(qid,$('#stream-item-' + qid).attr('data-in-reply-to-status-id'),true,false); + backToMyScrollPos($('#q-' + qid),qid,false); + } + else { + remove_spinner(); + } + }}); + } + + + +/* · + · + · Recursive walker functions to view onlt reyplies to replies, not full conversation + · + · · · · · · · · · · · · · */ + +function findInReplyToStatusAndShow(qid,reply,only_first,onlyINreplyto) { + var reply_found = $('#stream-item-' + qid).find('.stream-item[data-quitter-id="' + reply + '"]'); + var reply_found_reply_to = $('#stream-item-' + qid).find('.stream-item[data-quitter-id="' + reply_found.attr('data-in-reply-to-status-id') + '"]'); + if(reply_found.length>0) { + reply_found.removeClass('hidden-conversation'); + reply_found.animate({opacity:'1'},500); + if(only_first && reply_found_reply_to.length>0) { + reply_found.before(''); + findReplyToStatusAndShow(qid,qid,true); + } + else { + findInReplyToStatusAndShow(qid,reply_found.attr('data-in-reply-to-status-id'),false,onlyINreplyto); + } + } + else if(!onlyINreplyto) { + findReplyToStatusAndShow(qid,qid,true); + } + else { + checkForHiddenConversationQueets(qid); + } + } +// recursive function to find the replies to a status +function findReplyToStatusAndShow(qid,this_id,only_first) { + var reply_found = $('#stream-item-' + qid).find('.stream-item[data-in-reply-to-status-id="' + this_id + '"]'); + var reply_founds_reply = $('#stream-item-' + qid).find('.stream-item[data-in-reply-to-status-id="' + reply_found.attr('data-quitter-id') + '"]'); + if(reply_found.length>0) { + reply_found.removeClass('hidden-conversation'); + reply_found.animate({opacity:'1'},100,function(){ + if(!only_first) { + findReplyToStatusAndShow(qid,$(this).attr('data-quitter-id'),false); + } + }); + if(only_first && reply_founds_reply.length>0) { + reply_found.last().after(''); + } + } + checkForHiddenConversationQueets(qid); + } + +// helper function for the above recursive functions +function checkForHiddenConversationQueets(qid) { + // here we check if there are any remaining hidden queets in conversation, if there are, we put a "show full conversation"-link + if($('#stream-item-' + qid).find('.hidden-conversation').length>0) { + if($('#stream-item-' + qid).children('.queet').find('.show-full-conversation').length == 0) { + $('#stream-item-' + qid).children('.queet').find('.metadata').append('' + window.sL.expandFullConversation + ''); + } + } + else { + $('#stream-item-' + qid).children('.queet').find('.show-full-conversation').remove(); + } + } + + +/* · + · + · Build stream items and add them to feed + · + · Also a function that has grown out of control... Needs total makeover + · + · · · · · · · · · · · · · */ + +function addToFeed(feed, after, extraClasses) { + + $.each(feed.reverse(), function (key,obj) { + + var extraClassesThisRun = extraClasses; + + // if this is a user feed + if(window.currentStream.substring(0,21) == 'statuses/friends.json' || window.currentStream.substring(0,18) == 'statuses/followers') { + obj.description = obj.description || ''; + + // show user actions + var followingClass = ''; + if(obj.following) { + followingClass = 'following'; + } + var followButton = ''; + if(typeof window.loginUsername != 'undefined' // if logged in + && window.myUserID != obj.id) { // not if this is me + if(!(obj.statusnet_profile_url.indexOf('/twitter.com/')>-1 && obj.following === false)) { // only unfollow twitter users + var followButton = ''; + } + } + + var userHtml = '
    ' + followButton + '
    '; + $('#feed-body').prepend(userHtml); + } + + // if this is a group feed + else if(window.currentStream.substring(0,26) == 'statusnet/groups/list.json') { + + obj.description = obj.description || ''; + obj.stream_logo = obj.stream_logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-stream.png'; + + // show group actions if logged in + var memberClass = ''; + if(obj.member) { + memberClass = 'member'; + } + var memberButton = ''; + if(typeof window.loginUsername != 'undefined') { + var memberButton = ''; + } + + var groupHtml = '
    ' + memberButton + '
    '; + $('#feed-body').prepend(groupHtml); + } + + // if this is a retweet + else if(typeof obj.retweeted_status != 'undefined') { + + // retweeted object already exist in feed + if($('#q-' + obj.retweeted_status.id).length > 0) { + + // only if not already shown and not mine + if($('#requeet-' + obj.id).length == 0 && obj.user.statusnet_profile_url != $('#user-profile-link').children('a').attr('href')) { + + // if not requeeted before + if($('#q-' + obj.retweeted_status.id + ' .stream-item-footer').find('.requeet-text').length > 0) { + // if users rt not already added + if($('#q-' + obj.retweeted_status.id + ' .stream-item-footer').find('.requeet-text').find('a[data-user-id="' + obj.user.id + '"]').length==0) { + $('#q-' + obj.retweeted_status.id + ' .stream-item-footer').find('.requeet-text').append(', ' + obj.user.name + ''); + } + } + else { + $('#q-' + obj.retweeted_status.id + ' .stream-item-footer').prepend('
    ' + window.sL.requeetedBy + ' ' + obj.user.name + '
    '); + } + } + } + // retweeted object don't exist in feed and not mine + else if(obj.user.statusnet_profile_url != $('#user-profile-link').children('a').attr('href')){ + + // we don't want to print 'null', someone might have that username! + var in_reply_to_screen_name = ''; + if(obj.retweeted_status.in_reply_to_screen_name != null) { + in_reply_to_screen_name = obj.retweeted_status.in_reply_to_screen_name; + } + + // requeet html + var requeetedClass = ''; + if(obj.retweeted_status.user.id == window.myUserID) { + var requeetHtml = '
  • ' + window.sL.deleteVerb + '
  • '; + } + else if(obj.retweeted_status.repeated) { + var requeetHtml = '
  • ' + window.sL.requeetedVerb + ''; + requeetedClass = 'requeeted'; + } + else { + var requeetHtml = '
  • ' + window.sL.requeetVerb + ''; + } + // favorite html + var favoritedClass = ''; + if(obj.retweeted_status.favorited) { + var favoriteHtml = ' ' + window.sL.favoritedVerb + ''; + favoritedClass = 'favorited'; + } + else { + var favoriteHtml = ' ' + window.sL.favoriteVerb + ''; + } + + // actions only for logged in users + var queetActions = ''; + var expandHTML = ''; + if(typeof window.loginUsername != 'undefined') { + queetActions = ''; + expandHTML = '' + window.sL.expand + ''; + } + + var queetTime = parseTwitterDate(obj.retweeted_status.created_at); + var queetHtml = '
    ' + $.trim(obj.retweeted_status.statusnet_html) + '
    '; + + // detect rtl + queetHtml = detectRTL(queetHtml); + + if(after) { + $('#' + after).after(queetHtml); + } + else { + $('#feed-body').prepend(queetHtml); + } + + } + + } + + // ordinary tweet + else { + + // only if not already exist + if($('#q-' + obj.id).length == 0) { + + // activity get special design + if(obj.source == 'activity') { + var queetTime = parseTwitterDate(obj.created_at); + var queetHtml = '
    ' + $.trim(obj.statusnet_html) + '
    '; + + // detect rtl + queetHtml = detectRTL(queetHtml); + + if(after) { + $('#' + after).after(queetHtml); + } + else { + $('#feed-body').prepend(queetHtml); + } + + } + else { + + // if this is my queet, remove any temp-queets + if(typeof obj.user != 'undefined') { + if(obj.user.screen_name == $('#user-screen-name').html()) { + if($('.temp-post').length > 0) { + $('.temp-post').each(function (){ + // remove temp duplicate + $(this).css('display','none'); + + // we do this so this queet gets added after correct temp-queet in expanded conversations + if($(this).find('.queet-text').text() == obj.text) { + after = $(this).attr('id'); + } + + // but don't hide my new queet + extraClassesThisRun = 'visible'; + }); + } + } + } + + // we don't want to print 'null' in in_reply_to_screen_name-attribute, someone might have that username! + var in_reply_to_screen_name = ''; + if(obj.in_reply_to_screen_name != null) { + in_reply_to_screen_name = obj.in_reply_to_screen_name; + } + + // requeet html + var requeetedClass = ''; + if(obj.user.id == window.myUserID) { + var requeetHtml = '
  • ' + window.sL.deleteVerb + '
  • '; + } + else if(obj.repeated) { + var requeetHtml = '
  • ' + window.sL.requeetedVerb + '
  • '; + var requeetedClass = 'requeeted'; + } + else { + var requeetHtml = '
  • ' + window.sL.requeetVerb + '
  • '; + } + // favorite html + var favoritedClass = ''; + if(obj.favorited) { + var favoriteHtml = ' ' + window.sL.favoritedVerb + ''; + favoritedClass = 'favorited'; + } + else { + var favoriteHtml = ' ' + window.sL.favoriteVerb + ''; + } + + + // actions only for logged in users + var queetActions = ''; + var expandHTML = ''; + if(typeof window.loginUsername != 'undefined') { + queetActions = ''; + expandHTML = '' + window.sL.expand + ''; + } + + var queetTime = parseTwitterDate(obj.created_at); + var queetHtml = '
    ' + $.trim(obj.statusnet_html) + '
    '; + + // detect rtl + queetHtml = detectRTL(queetHtml); + + if(after) { + if($('#' + after).hasClass('conversation')) { // if this is a reply, give stream item some conversation formatting + if($('#conversation-q-' + obj.id).length == 0) { // only if it's not already there + $('#' + after).after(queetHtml.replace('id="stream-item','id="conversation-stream-item').replace('class="stream-item','class="stream-item conversation').replace('id="q','id="conversation-q')); + $('#' + after).remove(); + } + } + else { + $('#' + after).after(queetHtml); + } + } + else { + $('#feed-body').prepend(queetHtml); + } + + } + } + } + + convertAttachmentMoreHref(); + }); + $('.stream-selection').removeAttr('data-current-user-stream-name'); // don't remeber user feeds + } + + +/* · + · + · View threaded converation + · + · @param id: the stream item id + · + · · · · · · · · · · · · · */ + +$('body').on('click','.longdate',function(){ + threadedConversation($(this).closest('.stream-item:not(.conversation)').attr('data-quitter-id')); + }) +function threadedConversation(id){ + $('body').prepend(''); + var scrollTop = $(window).scrollTop(); + var containerStreamItem = $('#stream-item-' + id); + if(containerStreamItem.children('div:first-child').hasClass('.queet')) { + var firstStreamItemId = id; + } + else { + var firstStreamItemId = containerStreamItem.children('div:first-child').attr('data-quitter-id'); + } + getThreadedReply(id,firstStreamItemId,$('#threaded-' + id + ' .thread-container div')); + } + +function getThreadedReply(containerStreamId,this_id,appendToObj) { + + var $this_item = $('
    ').append($('.stream-item[data-quitter-id="' + this_id + '"]').outerHTML()); + $this_item.children().children().remove('.stream-item.conversation'); + $this_item.children('.stream-item').css('margin-left',parseInt(appendToObj.css('margin-left'),10)+20 + 'px'); + $this_item.children('.stream-item').removeClass('hidden-conversation'); + $this_item.children('.stream-item').removeClass('expanded'); + $this_item.children('.stream-item').removeClass('activity'); + $this_item.children('.stream-item').removeClass('conversation'); + $this_item.children('.stream-item').removeClass('visible'); + $this_item.children('.stream-item').children('div:not(.queet)').remove(); + $this_item.children('.stream-item').find('.inline-reply-queetbox').remove(); + $this_item.children('.stream-item').find('.expanded-content').remove(); + $this_item.children('.stream-item').find('.stream-item-expand').remove(); + $this_item.children('.stream-item').css('opacity','1'); + appendToObj.after($this_item.html()); + + $.each($('.stream-item[data-quitter-id="' + containerStreamId + '"]').children().get().reverse(),function(){ + if($(this).hasClass('queet')) { + var this_reply_to = $(this).parent().attr('data-in-reply-to-status-id'); + var childs_id = $(this).parent().attr('data-quitter-id'); + } + else { + var this_reply_to = $(this).attr('data-in-reply-to-status-id'); + var childs_id = $(this).attr('data-quitter-id'); + } + if(this_id == this_reply_to) { + getThreadedReply(containerStreamId,childs_id,$('#threaded-' + containerStreamId + ' .stream-item[data-quitter-id="' + this_id + '"]')); + } + }); + } diff --git a/js/jquery-2.0.2.min.js b/js/jquery-2.0.2.min.js new file mode 100644 index 0000000..73e5218 --- /dev/null +++ b/js/jquery-2.0.2.min.js @@ -0,0 +1,6 @@ +/*! jQuery v2.0.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-2.0.2.min.map +*/ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.2",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=at(),k=at(),N=at(),E=!1,S=function(){return 0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],H=L.pop,q=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){q.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=vt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+xt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return St(e.replace(z,"$1"),t,r,i)}function st(e){return Q.test(e+"")}function at(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function ut(e){return e[v]=!0,e}function lt(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t,n){e=e.split("|");var r,o=e.length,s=n?null:t;while(o--)(r=i.attrHandle[e[o]])&&r!==t||(i.attrHandle[e[o]]=s)}function pt(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:e[t]===!0?t.toLowerCase():null}function ft(e,t){return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function ht(e){return"input"===e.nodeName.toLowerCase()?e.defaultValue:undefined}function dt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function gt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function mt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function yt(e){return ut(function(t){return t=+t,ut(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.parentWindow;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.frameElement&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=lt(function(e){return e.innerHTML="",ct("type|href|height|width",ft,"#"===e.firstChild.getAttribute("href")),ct(R,pt,null==e.getAttribute("disabled")),e.className="i",!e.getAttribute("className")}),n.input=lt(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")}),ct("value",ht,n.attributes&&n.input),n.getElementsByTagName=lt(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=lt(function(e){return e.innerHTML="
    ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=lt(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=st(t.querySelectorAll))&&(lt(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),lt(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=st(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&<(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=st(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},n.sortDetached=lt(function(e){return 1&e.compareDocumentPosition(t.createElement("div"))}),S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return dt(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?dt(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:ut,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=vt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ut(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ut(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?ut(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ut(function(e){return function(t){return ot(e,t).length>0}}),contains:ut(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ut(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:yt(function(){return[0]}),last:yt(function(e,t){return[t-1]}),eq:yt(function(e,t,n){return[0>n?n+t:n]}),even:yt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:yt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:yt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:yt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=gt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=mt(t);function vt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function xt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function bt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function wt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function Tt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function Ct(e,t,n,r,i,o){return r&&!r[v]&&(r=Ct(r)),i&&!i[v]&&(i=Ct(i,o)),ut(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Et(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:Tt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=Tt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=Tt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function kt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=bt(function(e){return e===t},a,!0),p=bt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[bt(wt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return Ct(l>1&&wt(f),l>1&&xt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&kt(e.slice(l,r)),o>r&&kt(e=e.slice(r)),o>r&&xt(e))}f.push(n)}return wt(f)}function Nt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=H.call(f));y=Tt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?ut(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=vt(e)),n=t.length;while(n--)o=kt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Nt(i,r))}return o};function Et(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function St(e,t,r,o){var s,u,l,c,p,f=vt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&xt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}i.pseudos.nth=i.pseudos.eq;function jt(){}jt.prototype=i.filters=i.pseudos,i.setFilters=new jt,n.sortStable=v.split("").sort(S).join("")===v,c(),[0,0].sort(S),n.detectDuplicates=E,x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!a||n&&!u||(r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,H,q=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){return t===undefined||t&&"string"==typeof t&&n===undefined?this.get(e,t):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,H=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||H.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return H.access(e,t,n)},_removeData:function(e,t){H.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!H.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));H.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:q.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=H.get(e,t),n&&(!r||x.isArray(n)?r=H.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire() +},_queueHooks:function(e,t){var n=t+"queueHooks";return H.get(e,n)||H.access(e,n,{empty:x.Callbacks("once memory").add(function(){H.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=H.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,i="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,s=0,a=x(this),u=t,l=e.match(w)||[];while(o=l[s++])u=i?u:!a.hasClass(o),a[u?"addClass":"removeClass"](o)}else(n===r||"boolean"===n)&&(this.className&&H.set(this,"__className__",this.className),this.className=this.className||e===!1?"":H.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=H.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=H.hasData(e)&&H.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,H.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(H.get(a,"events")||{})[t.type]&&H.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(H.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!H.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.firstChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[H.expando],o&&(t=H.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);H.cache[o]&&delete H.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)H.set(e[r],"globalEval",!t||H.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(H.hasData(e)&&(o=H.access(e),s=H.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function Ht(t){return e.getComputedStyle(t,null)}function qt(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=H.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=H.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&H.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=Ht(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return qt(this,!0)},hide:function(){return qt(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:Lt(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||Ht(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Ht(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("