r77277 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r77276‎ | r77277 | r77278 >
Date:11:31, 25 November 2010
Author:tstarling
Status:ok
Tags:
Comment:
Adding the RSS extension to 1.16wmf4. A patch to make this extension actually work with 1.16 will follow in a subsequent commit.
Modified paths:
  • /branches/wmf/1.16wmf4/extensions/RSS (added) (history)

Diff [purge]

Index: branches/wmf/1.16wmf4/extensions/RSS/RSSHooks.php
@@ -0,0 +1,50 @@
 2+<?php
 3+
 4+class RSSHooks {
 5+ /**
 6+ * Tell the parser how to handle <rss> elements
 7+ * @param Parser Object
 8+ */
 9+ static function parserInit( $parser ) {
 10+ # Install parser hook for <rss> tags
 11+ $parser->setHook( 'rss', array( __CLASS__, 'renderRss' ) );
 12+ return true;
 13+ }
 14+
 15+ /**
 16+ * Static function wrapping RSSParser to handle rendering of RSS elements
 17+ * @param $input String: text inside the tags.
 18+ * @param $args Array: value associative list of the element attributes and
 19+ * their values.
 20+ * @param $frame Frame parser context
 21+ */
 22+ static function renderRss( $input, $args, $parser, $frame ) {
 23+ global $wgRSSCacheAge, $wgRSSCacheCompare;
 24+
 25+ if ( !Http::isValidURI( $input ) ) {
 26+ return wfMsg( 'rss-invalid-url', htmlspecialchars( $input ) );
 27+ }
 28+ if ( $wgRSSCacheCompare ) {
 29+ $timeout = $wgRSSCacheCompare;
 30+ } else {
 31+ $timeout = $wgRSSCacheAge;
 32+ }
 33+
 34+ $parser->getOutput()->updateCacheExpiry( $timeout );
 35+
 36+ $rss = new RSSParser( $input, $args );
 37+
 38+ $status = $rss->fetch();
 39+
 40+ # Check for errors.
 41+ if ( !$status->isGood() ) {
 42+ return wfMsg( 'rss-error', htmlspecialchars( $input ), $status->getWikiText() );
 43+ }
 44+
 45+ if ( !is_object( $rss->rss ) || !is_array( $rss->rss->items ) ) {
 46+ return wfMsg( 'rss-empty', htmlspecialchars( $input ) );
 47+ }
 48+
 49+ return $rss->renderFeed( $parser, $frame );
 50+ }
 51+}
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/RSSHooks.php
___________________________________________________________________
Added: svn:eol-style
152 + native
Added: svn:eol-syle
253 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/INSTALL
@@ -0,0 +1,11 @@
 2+[[RSS 1.7]]
 3+
 4+== Installation ==
 5+
 6+# Save the [[#Source|source]] in your /extensions directory.
 7+# Place the following text in your [[Manual:LocalSettings.php|LocalSettings.php]] file: <tt>require_once("$IP/extensions/RSS/RSS.php");</tt><br />(Make sure there's a semicolon (;) at the end of that line)
 8+# Finally, load your wiki, and have fun with RSS feeds!
 9+
 10+More information can be found at [0].
 11+
 12+[0] http://www.mediawiki.org/wiki/Extension:RSS#Installation
\ No newline at end of file
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/INSTALL
___________________________________________________________________
Added: svn:eol-style
113 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/RELEASE-NOTES
@@ -0,0 +1,24 @@
 2+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:RSS
 3+
 4+== Change Log ==
 5+*original by mutante 25.03.2005
 6+*extended by Duesentrieb 30.04.2005
 7+*extended by Rdb78 07.07.2005
 8+*extended by Mafs 10.07.2005, 24.07.2005
 9+*extended by Niffler 28.02.2006
 10+*modified by Dzag 07.2006
 11+*modified by Alxndr 09.2006
 12+*modified by Svanslyck 02.2008, replacing all « and » with "
 13+*<del>This has been updated to work better on newer (1.9) MediaWiki software, with the help of [[User:Duesentrieb]]. --[[User:CryptoQuick|CryptoQuick]] 14:26, 24 January 2007 (UTC)</del>
 14+**This appears not to be true; I have received numerous emails about it not working with 1.9+. I would love to help debug and fix the extension, but my host has not upgraded to PHP 5 and I'm thus stuck at MediaWiki 1.6.8, so that's as far as this is guaranteed to work properly. If anyone develops a fix, please post a link to it here! &#x2014;[[User:Alxndr|Alxndr]]&#x00a0;<sup>([[User talk:Alxndr|t]])</sup> 02:02, 16 June 2007 (UTC)
 15+***I just found [http://nako.us/2007/03/16/mediawiki-19-fix-for-wfstrencode/ this fork] that purports to have a fix for the new loss of wfStrEncode(). I can't test it though so can anyone else verify that it works? &#x2014;[[User:Alxndr|Alxndr]]&#x00a0;<sup>([[User talk:Alxndr|t]])</sup> 02:18, 16 June 2007 (UTC)
 16+*modified by --[[User:Wikinaut|Wikinaut]] 11:17, 7 May 2008 (UTC) : changed method to disable chaching; Extension is now compatible to MediaWiki 1.12
 17+*modified by [[User:Cmreigrut|Cmreigrut]] 19:05, 19 November 2008 (UTC): added date (if specified) to short output
 18+*modified by Peter Newman: 03:15, 7 October 2009 (UTC) Added htmlspecialchars escaping to the displayed strings
 19+*modified by [[User:K001|K001]] 15:15, 26 January 2010 (UTC): version 1.6, added support for date formats
 20+
 21+=== Version 1.7 ===
 22+2010-7-23
 23+
 24+* Cleaned up, included MagpieRSS library and put onto the WMF subversion repository by Jeroen De Dauw - http://www.mediawiki.org/wiki/User:Jeroen_De_Dauw
 25+* i18n file added by TranslateWiki.net people
\ No newline at end of file
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/RELEASE-NOTES
___________________________________________________________________
Added: svn:eol-style
126 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/RSSData.php
@@ -0,0 +1,84 @@
 2+<?php
 3+
 4+class RSSData {
 5+ public $error;
 6+ public $items;
 7+
 8+ /**
 9+ * Constructor, takes a DOMDocument and returns an array of parsed items.
 10+ * @param $xml DOMDocument: the pre-parsed XML Document
 11+ * @return Object RSSData object with a member items that is an array of parsed items,
 12+ */
 13+ function __construct( $xml ) {
 14+ if ( !( $xml instanceof DOMDocument ) ) {
 15+ $this->error = "Not passed DOMDocument object.";
 16+ return;
 17+ }
 18+ $xpath = new DOMXPath( $xml );
 19+ $items = $xpath->query( '/rss/channel/item' );
 20+
 21+ if( $items->length !== 0 ) {
 22+ foreach ( $items as $item ) {
 23+ $bit = array();
 24+ foreach ( $item->childNodes as $n ) {
 25+ $name = $this->rssTokenToName( $n->nodeName );
 26+ if ( $name != null ) {
 27+ /**
 28+ * Because for DOMElements the nodeValue is just
 29+ * the text of the containing element, without any
 30+ * tags, it makes this a safe, if unattractive,
 31+ * value to use. If you want to allow people to
 32+ * mark up their RSS, some more precautions are
 33+ * needed.
 34+ */
 35+ $bit[$name] = $n->nodeValue;
 36+ }
 37+ }
 38+ $this->items[] = $bit;
 39+ }
 40+ } else {
 41+ $this->error = 'No RSS items found.';
 42+ return;
 43+ }
 44+ }
 45+
 46+ /**
 47+ * Return a string that will be used to map RSS elements that
 48+ * contain similar data (e.g. dc:date, date, and pubDate) to the
 49+ * same array key. This works on WordPress feeds as-is, but it
 50+ * probably needs a way to concert dc:date format dates to be the
 51+ * same as pubDate.
 52+ *
 53+ * @param $n String: name of the element we have
 54+ * @return String Name to map it to
 55+ */
 56+ protected function rssTokenToName( $n ) {
 57+ switch( $n ) {
 58+ case 'dc:date':
 59+ return 'date';
 60+ # parse "2010-10-18T18:07:00Z"
 61+ case 'pubDate':
 62+ return 'date';
 63+ # parse RFC date
 64+ case 'dc:creator':
 65+ return 'author';
 66+ case 'title':
 67+ return 'title';
 68+ case 'content:encoded':
 69+ return 'encodedContent';
 70+
 71+ case 'slash:comments':
 72+ case 'slash:department':
 73+ case 'slash:section':
 74+ case 'slash:hit_parade':
 75+ case 'feedburner:origLink':
 76+ case 'wfw:commentRss':
 77+ case 'comments':
 78+ case 'category':
 79+ return null;
 80+
 81+ default:
 82+ return $n;
 83+ }
 84+ }
 85+}
\ No newline at end of file
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/RSSData.php
___________________________________________________________________
Added: svn:eol-style
186 + native
Added: svn:eol-syle
287 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/COPYING
@@ -0,0 +1,348 @@
 2+The license text below "----" applies to all files within this distribution, other
 3+than those that are in a directory which contains files named "LICENSE" or
 4+"COPYING", or a subdirectory thereof. For those files, the license text contained in
 5+said file overrides any license information contained in directories of smaller depth.
 6+Alternative licenses are typically used for software that is provided by external
 7+parties, and merely packaged with the Semantic MediaWiki release for convenience.
 8+----
 9+
 10+ GNU GENERAL PUBLIC LICENSE
 11+ Version 2, June 1991
 12+
 13+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 14+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 15+ Everyone is permitted to copy and distribute verbatim copies
 16+ of this license document, but changing it is not allowed.
 17+
 18+ Preamble
 19+
 20+ The licenses for most software are designed to take away your
 21+freedom to share and change it. By contrast, the GNU General Public
 22+License is intended to guarantee your freedom to share and change free
 23+software--to make sure the software is free for all its users. This
 24+General Public License applies to most of the Free Software
 25+Foundation's software and to any other program whose authors commit to
 26+using it. (Some other Free Software Foundation software is covered by
 27+the GNU Library General Public License instead.) You can apply it to
 28+your programs, too.
 29+
 30+ When we speak of free software, we are referring to freedom, not
 31+price. Our General Public Licenses are designed to make sure that you
 32+have the freedom to distribute copies of free software (and charge for
 33+this service if you wish), that you receive source code or can get it
 34+if you want it, that you can change the software or use pieces of it
 35+in new free programs; and that you know you can do these things.
 36+
 37+ To protect your rights, we need to make restrictions that forbid
 38+anyone to deny you these rights or to ask you to surrender the rights.
 39+These restrictions translate to certain responsibilities for you if you
 40+distribute copies of the software, or if you modify it.
 41+
 42+ For example, if you distribute copies of such a program, whether
 43+gratis or for a fee, you must give the recipients all the rights that
 44+you have. You must make sure that they, too, receive or can get the
 45+source code. And you must show them these terms so they know their
 46+rights.
 47+
 48+ We protect your rights with two steps: (1) copyright the software, and
 49+(2) offer you this license which gives you legal permission to copy,
 50+distribute and/or modify the software.
 51+
 52+ Also, for each author's protection and ours, we want to make certain
 53+that everyone understands that there is no warranty for this free
 54+software. If the software is modified by someone else and passed on, we
 55+want its recipients to know that what they have is not the original, so
 56+that any problems introduced by others will not reflect on the original
 57+authors' reputations.
 58+
 59+ Finally, any free program is threatened constantly by software
 60+patents. We wish to avoid the danger that redistributors of a free
 61+program will individually obtain patent licenses, in effect making the
 62+program proprietary. To prevent this, we have made it clear that any
 63+patent must be licensed for everyone's free use or not licensed at all.
 64+
 65+ The precise terms and conditions for copying, distribution and
 66+modification follow.
 67+
 68+ GNU GENERAL PUBLIC LICENSE
 69+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 70+
 71+ 0. This License applies to any program or other work which contains
 72+a notice placed by the copyright holder saying it may be distributed
 73+under the terms of this General Public License. The "Program", below,
 74+refers to any such program or work, and a "work based on the Program"
 75+means either the Program or any derivative work under copyright law:
 76+that is to say, a work containing the Program or a portion of it,
 77+either verbatim or with modifications and/or translated into another
 78+language. (Hereinafter, translation is included without limitation in
 79+the term "modification".) Each licensee is addressed as "you".
 80+
 81+Activities other than copying, distribution and modification are not
 82+covered by this License; they are outside its scope. The act of
 83+running the Program is not restricted, and the output from the Program
 84+is covered only if its contents constitute a work based on the
 85+Program (independent of having been made by running the Program).
 86+Whether that is true depends on what the Program does.
 87+
 88+ 1. You may copy and distribute verbatim copies of the Program's
 89+source code as you receive it, in any medium, provided that you
 90+conspicuously and appropriately publish on each copy an appropriate
 91+copyright notice and disclaimer of warranty; keep intact all the
 92+notices that refer to this License and to the absence of any warranty;
 93+and give any other recipients of the Program a copy of this License
 94+along with the Program.
 95+
 96+You may charge a fee for the physical act of transferring a copy, and
 97+you may at your option offer warranty protection in exchange for a fee.
 98+
 99+ 2. You may modify your copy or copies of the Program or any portion
 100+of it, thus forming a work based on the Program, and copy and
 101+distribute such modifications or work under the terms of Section 1
 102+above, provided that you also meet all of these conditions:
 103+
 104+ a) You must cause the modified files to carry prominent notices
 105+ stating that you changed the files and the date of any change.
 106+
 107+ b) You must cause any work that you distribute or publish, that in
 108+ whole or in part contains or is derived from the Program or any
 109+ part thereof, to be licensed as a whole at no charge to all third
 110+ parties under the terms of this License.
 111+
 112+ c) If the modified program normally reads commands interactively
 113+ when run, you must cause it, when started running for such
 114+ interactive use in the most ordinary way, to print or display an
 115+ announcement including an appropriate copyright notice and a
 116+ notice that there is no warranty (or else, saying that you provide
 117+ a warranty) and that users may redistribute the program under
 118+ these conditions, and telling the user how to view a copy of this
 119+ License. (Exception: if the Program itself is interactive but
 120+ does not normally print such an announcement, your work based on
 121+ the Program is not required to print an announcement.)
 122+
 123+These requirements apply to the modified work as a whole. If
 124+identifiable sections of that work are not derived from the Program,
 125+and can be reasonably considered independent and separate works in
 126+themselves, then this License, and its terms, do not apply to those
 127+sections when you distribute them as separate works. But when you
 128+distribute the same sections as part of a whole which is a work based
 129+on the Program, the distribution of the whole must be on the terms of
 130+this License, whose permissions for other licensees extend to the
 131+entire whole, and thus to each and every part regardless of who wrote it.
 132+
 133+Thus, it is not the intent of this section to claim rights or contest
 134+your rights to work written entirely by you; rather, the intent is to
 135+exercise the right to control the distribution of derivative or
 136+collective works based on the Program.
 137+
 138+In addition, mere aggregation of another work not based on the Program
 139+with the Program (or with a work based on the Program) on a volume of
 140+a storage or distribution medium does not bring the other work under
 141+the scope of this License.
 142+
 143+ 3. You may copy and distribute the Program (or a work based on it,
 144+under Section 2) in object code or executable form under the terms of
 145+Sections 1 and 2 above provided that you also do one of the following:
 146+
 147+ a) Accompany it with the complete corresponding machine-readable
 148+ source code, which must be distributed under the terms of Sections
 149+ 1 and 2 above on a medium customarily used for software interchange; or,
 150+
 151+ b) Accompany it with a written offer, valid for at least three
 152+ years, to give any third party, for a charge no more than your
 153+ cost of physically performing source distribution, a complete
 154+ machine-readable copy of the corresponding source code, to be
 155+ distributed under the terms of Sections 1 and 2 above on a medium
 156+ customarily used for software interchange; or,
 157+
 158+ c) Accompany it with the information you received as to the offer
 159+ to distribute corresponding source code. (This alternative is
 160+ allowed only for noncommercial distribution and only if you
 161+ received the program in object code or executable form with such
 162+ an offer, in accord with Subsection b above.)
 163+
 164+The source code for a work means the preferred form of the work for
 165+making modifications to it. For an executable work, complete source
 166+code means all the source code for all modules it contains, plus any
 167+associated interface definition files, plus the scripts used to
 168+control compilation and installation of the executable. However, as a
 169+special exception, the source code distributed need not include
 170+anything that is normally distributed (in either source or binary
 171+form) with the major components (compiler, kernel, and so on) of the
 172+operating system on which the executable runs, unless that component
 173+itself accompanies the executable.
 174+
 175+If distribution of executable or object code is made by offering
 176+access to copy from a designated place, then offering equivalent
 177+access to copy the source code from the same place counts as
 178+distribution of the source code, even though third parties are not
 179+compelled to copy the source along with the object code.
 180+
 181+ 4. You may not copy, modify, sublicense, or distribute the Program
 182+except as expressly provided under this License. Any attempt
 183+otherwise to copy, modify, sublicense or distribute the Program is
 184+void, and will automatically terminate your rights under this License.
 185+However, parties who have received copies, or rights, from you under
 186+this License will not have their licenses terminated so long as such
 187+parties remain in full compliance.
 188+
 189+ 5. You are not required to accept this License, since you have not
 190+signed it. However, nothing else grants you permission to modify or
 191+distribute the Program or its derivative works. These actions are
 192+prohibited by law if you do not accept this License. Therefore, by
 193+modifying or distributing the Program (or any work based on the
 194+Program), you indicate your acceptance of this License to do so, and
 195+all its terms and conditions for copying, distributing or modifying
 196+the Program or works based on it.
 197+
 198+ 6. Each time you redistribute the Program (or any work based on the
 199+Program), the recipient automatically receives a license from the
 200+original licensor to copy, distribute or modify the Program subject to
 201+these terms and conditions. You may not impose any further
 202+restrictions on the recipients' exercise of the rights granted herein.
 203+You are not responsible for enforcing compliance by third parties to
 204+this License.
 205+
 206+ 7. If, as a consequence of a court judgment or allegation of patent
 207+infringement or for any other reason (not limited to patent issues),
 208+conditions are imposed on you (whether by court order, agreement or
 209+otherwise) that contradict the conditions of this License, they do not
 210+excuse you from the conditions of this License. If you cannot
 211+distribute so as to satisfy simultaneously your obligations under this
 212+License and any other pertinent obligations, then as a consequence you
 213+may not distribute the Program at all. For example, if a patent
 214+license would not permit royalty-free redistribution of the Program by
 215+all those who receive copies directly or indirectly through you, then
 216+the only way you could satisfy both it and this License would be to
 217+refrain entirely from distribution of the Program.
 218+
 219+If any portion of this section is held invalid or unenforceable under
 220+any particular circumstance, the balance of the section is intended to
 221+apply and the section as a whole is intended to apply in other
 222+circumstances.
 223+
 224+It is not the purpose of this section to induce you to infringe any
 225+patents or other property right claims or to contest validity of any
 226+such claims; this section has the sole purpose of protecting the
 227+integrity of the free software distribution system, which is
 228+implemented by public license practices. Many people have made
 229+generous contributions to the wide range of software distributed
 230+through that system in reliance on consistent application of that
 231+system; it is up to the author/donor to decide if he or she is willing
 232+to distribute software through any other system and a licensee cannot
 233+impose that choice.
 234+
 235+This section is intended to make thoroughly clear what is believed to
 236+be a consequence of the rest of this License.
 237+
 238+ 8. If the distribution and/or use of the Program is restricted in
 239+certain countries either by patents or by copyrighted interfaces, the
 240+original copyright holder who places the Program under this License
 241+may add an explicit geographical distribution limitation excluding
 242+those countries, so that distribution is permitted only in or among
 243+countries not thus excluded. In such case, this License incorporates
 244+the limitation as if written in the body of this License.
 245+
 246+ 9. The Free Software Foundation may publish revised and/or new versions
 247+of the General Public License from time to time. Such new versions will
 248+be similar in spirit to the present version, but may differ in detail to
 249+address new problems or concerns.
 250+
 251+Each version is given a distinguishing version number. If the Program
 252+specifies a version number of this License which applies to it and "any
 253+later version", you have the option of following the terms and conditions
 254+either of that version or of any later version published by the Free
 255+Software Foundation. If the Program does not specify a version number of
 256+this License, you may choose any version ever published by the Free Software
 257+Foundation.
 258+
 259+ 10. If you wish to incorporate parts of the Program into other free
 260+programs whose distribution conditions are different, write to the author
 261+to ask for permission. For software which is copyrighted by the Free
 262+Software Foundation, write to the Free Software Foundation; we sometimes
 263+make exceptions for this. Our decision will be guided by the two goals
 264+of preserving the free status of all derivatives of our free software and
 265+of promoting the sharing and reuse of software generally.
 266+
 267+ NO WARRANTY
 268+
 269+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 270+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
 271+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 272+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 273+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 274+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
 275+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
 276+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 277+REPAIR OR CORRECTION.
 278+
 279+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 280+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 281+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 282+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 283+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 284+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 285+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 286+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 287+POSSIBILITY OF SUCH DAMAGES.
 288+
 289+ END OF TERMS AND CONDITIONS
 290+
 291+ How to Apply These Terms to Your New Programs
 292+
 293+ If you develop a new program, and you want it to be of the greatest
 294+possible use to the public, the best way to achieve this is to make it
 295+free software which everyone can redistribute and change under these terms.
 296+
 297+ To do so, attach the following notices to the program. It is safest
 298+to attach them to the start of each source file to most effectively
 299+convey the exclusion of warranty; and each file should have at least
 300+the "copyright" line and a pointer to where the full notice is found.
 301+
 302+ <one line to give the program's name and a brief idea of what it does.>
 303+ Copyright (C) <year> <name of author>
 304+
 305+ This program is free software; you can redistribute it and/or modify
 306+ it under the terms of the GNU General Public License as published by
 307+ the Free Software Foundation; either version 2 of the License, or
 308+ (at your option) any later version.
 309+
 310+ This program is distributed in the hope that it will be useful,
 311+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 312+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 313+ GNU General Public License for more details.
 314+
 315+ You should have received a copy of the GNU General Public License
 316+ along with this program; if not, write to the Free Software
 317+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 318+
 319+
 320+Also add information on how to contact you by electronic and paper mail.
 321+
 322+If the program is interactive, make it output a short notice like this
 323+when it starts in an interactive mode:
 324+
 325+ Gnomovision version 69, Copyright (C) year name of author
 326+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 327+ This is free software, and you are welcome to redistribute it
 328+ under certain conditions; type `show c' for details.
 329+
 330+The hypothetical commands `show w' and `show c' should show the appropriate
 331+parts of the General Public License. Of course, the commands you use may
 332+be called something other than `show w' and `show c'; they could even be
 333+mouse-clicks or menu items--whatever suits your program.
 334+
 335+You should also get your employer (if you work as a programmer) or your
 336+school, if any, to sign a "copyright disclaimer" for the program, if
 337+necessary. Here is a sample; alter the names:
 338+
 339+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 340+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
 341+
 342+ <signature of Ty Coon>, 1 April 1989
 343+ Ty Coon, President of Vice
 344+
 345+This General Public License does not permit incorporating your program into
 346+proprietary programs. If your program is a subroutine library, you may
 347+consider it more useful to permit linking proprietary applications with the
 348+library. If this is what you want to do, use the GNU Library General
 349+Public License instead of this License.
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/COPYING
___________________________________________________________________
Added: svn:eol-style
1350 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/RSSParser.php
@@ -0,0 +1,454 @@
 2+<?php
 3+
 4+class RSSParser {
 5+ protected $maxheads = 32;
 6+ protected $reversed = false;
 7+ protected $highlight = array();
 8+ protected $filter = array();
 9+ protected $filterOut = array();
 10+ protected $itemTemplate;
 11+ protected $url;
 12+ protected $etag;
 13+ protected $lastModified;
 14+ protected $xml;
 15+ protected $error;
 16+ protected $displayFields = array( 'author', 'title', 'encodedContent', 'description' );
 17+
 18+ public $client;
 19+
 20+ /**
 21+ * Convenience function that takes a space-separated string and returns an array of words
 22+ * @param $str String: list of words
 23+ * @return Array words found
 24+ */
 25+ private static function explodeOnSpaces( $str ) {
 26+ $found = preg_split( '# +#', $str );
 27+ return is_array( $found ) ? $found : array();
 28+ }
 29+
 30+ /**
 31+ * Take a bit of WikiText that looks like
 32+ * <rss max=5>http://example.com/</rss>
 33+ * and return an object that can produce rendered output.
 34+ */
 35+ function __construct( $url, $args ) {
 36+ $this->url = $url;
 37+
 38+ # Get max number of headlines from argument-array
 39+ if ( isset( $args['max'] ) ) {
 40+ $this->maxheads = $args['max'];
 41+ }
 42+
 43+ # Get reverse flag from argument array
 44+ if ( isset( $args['reverse'] ) ) {
 45+ $this->reversed = true;
 46+ }
 47+
 48+ # Get date format from argument array
 49+ # FIXME: not used yet
 50+ if ( isset( $args['date'] ) ) {
 51+ $this->date = $args['date'];
 52+ }
 53+
 54+ # Get highlight terms from argument array
 55+ if ( isset( $args['highlight'] ) ) {
 56+ # mapping to lowercase here so the regex can be case insensitive below.
 57+ $this->highlight = self::explodeOnSpaces( $args['highlight'] );
 58+ }
 59+
 60+ # Get filter terms from argument array
 61+ if ( isset( $args['filter'] ) ) {
 62+ $this->filter = self::explodeOnSpaces( $args['filter'] );
 63+ }
 64+
 65+ if ( isset( $args['filterout'] ) ) {
 66+ $this->filterOut = self::explodeOnSpaces( $args['filterout'] );
 67+ }
 68+
 69+ if ( isset( $args['template'] ) ) {
 70+ $titleObject = Title::newFromText( $args['template'], NS_TEMPLATE );
 71+ $article = new Article( $titleObject, 0 );
 72+ $this->itemTemplate = $article->fetchContent();
 73+ } else {
 74+ $this->itemTemplate = wfMsgNoTrans( 'rss-item' );
 75+ }
 76+ }
 77+
 78+ /**
 79+ * Return RSS object for the given URL, maintaining caching.
 80+ *
 81+ * NOTES ON RETRIEVING REMOTE FILES:
 82+ * No attempt will be made to fetch remote files if there is something in cache.
 83+ *
 84+ * NOTES ON FAILED REQUESTS:
 85+ * If there is an HTTP error while fetching an RSS object, the cached version
 86+ * will be returned, if it exists.
 87+ *
 88+ * @return boolean Status object
 89+ */
 90+ function fetch() {
 91+ if ( !isset( $this->url ) ) {
 92+ return Status::newFatal( 'rss-fetch-nourl' );
 93+ }
 94+
 95+ // Flow
 96+ // 1. check cache
 97+ // 2. if there is a hit, make sure its fresh
 98+ // 3. if cached obj fails freshness check, fetch remote
 99+ // 4. if remote fails, return stale object, or error
 100+ $key = wfMemcKey( 'rss', $this->url );
 101+ $cachedFeed = $this->loadFromCache( $key );
 102+ if ( $cachedFeed !== false ) {
 103+ wfDebugLog( 'RSS', 'Outputting cached feed for ' . $this->url );
 104+ return Status::newGood();
 105+ }
 106+ wfDebugLog( 'RSS', 'Cache Failed, fetching ' . $this->url . ' from remote.' );
 107+
 108+ $status = $this->fetchRemote( $key );
 109+ return $status;
 110+ }
 111+
 112+ /**
 113+ * Retrieve the URL from the cache
 114+ * @param $key String: lookup key to associate with this item
 115+ * @return boolean
 116+ */
 117+ protected function loadFromCache( $key ) {
 118+ global $wgMemc, $wgRSSCacheCompare;
 119+
 120+ $data = $wgMemc->get( $key );
 121+ if ( !is_array( $data ) ) {
 122+ return false;
 123+ }
 124+
 125+ list( $etag, $lastModified, $rss ) =
 126+ $data;
 127+
 128+ if ( !isset( $rss->items ) ) {
 129+ return false;
 130+ }
 131+
 132+ wfDebugLog( 'RSS', "Got '$key' from cache" );
 133+
 134+ # Now that we've verified that we got useful data, keep it around.
 135+ $this->rss = $rss;
 136+ $this->etag = $etag;
 137+ $this->lastModified = $lastModified;
 138+
 139+ // We only care if $wgRSSCacheCompare is > 0
 140+ if ( $wgRSSCacheCompare && time() - $wgRSSCacheCompare > $lastModified ) {
 141+ wfDebugLog( 'RSS', 'Content is old enough that we need to check cached content' );
 142+ return false;
 143+ }
 144+
 145+ return true;
 146+ }
 147+
 148+ /**
 149+ * Store these objects (i.e. etag, lastModified, and RSS) in the cache.
 150+ * @param $key String: lookup key to associate with this item
 151+ * @return boolean
 152+ */
 153+ protected function storeInCache( $key ) {
 154+ global $wgMemc, $wgRSSCacheAge;
 155+
 156+ if ( !isset( $this->rss ) ) {
 157+ return false;
 158+ }
 159+ $r = $wgMemc->set( $key,
 160+ array( $this->etag, $this->lastModified, $this->rss ),
 161+ $wgRSSCacheAge );
 162+
 163+ wfDebugLog( 'RSS', "Stored '$key' as in cache? $r");
 164+ return true;
 165+ }
 166+
 167+ /**
 168+ * Retrieve a feed.
 169+ * @param $key String:
 170+ * @param $headers Array: headers to send along with the request
 171+ * @return Status object
 172+ */
 173+ protected function fetchRemote( $key, array $headers = array()) {
 174+ global $wgRSSFetchTimeout, $wgRSSUserAgent;
 175+
 176+ if ( $this->etag ) {
 177+ wfDebugLog( 'RSS', 'Used etag: ' . $this->etag );
 178+ $headers['If-None-Match'] = $this->etag;
 179+ }
 180+ if ( $this->lastModified ) {
 181+ $lm = gmdate( 'r', $this->lastModified );
 182+ wfDebugLog( 'RSS', "Used last modified: $lm" );
 183+ $headers['If-Modified-Since'] = $lm;
 184+ }
 185+
 186+ $client =
 187+ HttpRequest::factory( $this->url, array( 'timeout' => $wgRSSFetchTimeout ) );
 188+ $client->setUserAgent( $wgRSSUserAgent );
 189+ foreach ( $headers as $header => $value ) {
 190+ $client->setHeader( $header, $value );
 191+ }
 192+
 193+ $fetch = $client->execute();
 194+ $this->client = $client;
 195+
 196+ if ( !$fetch->isGood() ) {
 197+ wfDebug( 'RSS', 'Request Failed: ' . $fetch->getWikiText() );
 198+ return $fetch;
 199+ }
 200+
 201+ $ret = $this->responseToXML( $key );
 202+ return $ret;
 203+ }
 204+
 205+ /**
 206+ * Render the entire feed so that each item is passed to the
 207+ * template which the MediaWiki then displays.
 208+ *
 209+ * @param $parser the parser param to pass to recursiveTagParse()
 210+ * @param $frame the frame param to pass to recursiveTagParse()
 211+ */
 212+ function renderFeed( $parser, $frame ) {
 213+ $output = '';
 214+ if ( isset( $this->itemTemplate ) ) {
 215+ $headcnt = 0;
 216+ if ( $this->reversed ) {
 217+ $this->rss->items = array_reverse( $this->rss->items );
 218+ }
 219+
 220+ foreach ( $this->rss->items as $item ) {
 221+ if ( $this->maxheads > 0 && $headcnt >= $this->maxheads ) {
 222+ continue;
 223+ }
 224+
 225+ if ( $this->canDisplay( $item ) ) {
 226+ $output .= $this->renderItem( $item, $parser, $frame );
 227+ $headcnt++;
 228+ }
 229+ }
 230+ }
 231+ return $output;
 232+ }
 233+
 234+ /**
 235+ * Render each item, filtering it out if necessary, applying any highlighting.
 236+ *
 237+ * @param $item Array: an array produced by RSSData where keys are the
 238+ * names of the RSS elements
 239+ * @param $parser the parser param to pass to recursiveTagParse()
 240+ * @param $frame the frame param to pass to recursiveTagParse()
 241+ */
 242+ protected function renderItem( $item, $parser, $frame ) {
 243+ $output = "";
 244+ if ( isset( $parser ) && isset( $frame ) ) {
 245+ $rendered = $this->itemTemplate;
 246+ // $info will only be an XML element name, so we're safe
 247+ // using it. $item[$info] is handled by the XML parser --
 248+ // and that means bad RSS with stuff like
 249+ // <description><script>alert("hi")</script></description> will find its
 250+ // rogue <script> tags neutered.
 251+ foreach ( array_keys( $item ) as $info ) {
 252+ if ( $info != 'link' ) {
 253+ $txt = $this->highlightTerms( $this->escapeTemplateParameter( $item[ $info ] ) );
 254+ } else {
 255+ $txt = $this->sanitizeUrl( $item[ $info ] );
 256+ }
 257+ $rendered = str_replace( '{{{' . $info . '}}}', $txt, $rendered );
 258+ }
 259+
 260+ $output = $parser->recursiveTagParse( $rendered, $frame );
 261+ }
 262+ return $output;
 263+ }
 264+
 265+ /**
 266+ * Sanitize a URL for inclusion in wikitext. Escapes characters that have
 267+ * a special meaning in wikitext, replacing them with URL escape codes, so
 268+ * that arbitrary input can be included as a free or bracketed external
 269+ * link and both work and be safe.
 270+ */
 271+ protected function sanitizeUrl( $url ) {
 272+ # Remove control characters
 273+ $url = preg_replace( '/[\000-\037\177]/', '', $url );
 274+ # Escape other problematic characters
 275+ $i = 0;
 276+ $out = '';
 277+ for ( $i = 0; $i < strlen( $url ); $i++ ) {
 278+ $boringLength = strcspn( $url, '<>"[|]\ {', $i );
 279+ if ( $boringLength ) {
 280+ $out .= substr( $url, $i, $boringLength );
 281+ $i += $boringLength;
 282+ }
 283+ if ( $i < strlen( $url ) ) {
 284+ $out .= rawurlencode( $url[$i] );
 285+ }
 286+ }
 287+ return $out;
 288+ }
 289+
 290+ /**
 291+ * Sanitize user input for inclusion as a template parameter.
 292+ * Unlike in wfEscapeWikiText() as of r77127, this escapes }} in addition
 293+ * to the other kinds of markup, to avoid user input ending a template
 294+ * invocation.
 295+ */
 296+ protected function escapeTemplateParameter( $text ) {
 297+ $text = str_replace(
 298+ array( '[', '|', ']', '\'', 'ISBN ',
 299+ 'RFC ', '://', "\n=", '{{', '}}' ),
 300+ array( '&#91;', '&#124;', '&#93;', '&#39;', 'ISBN&#32;',
 301+ 'RFC&#32;', '&#58;//', "\n&#61;", '&#123;&#123;', '&#125;&#125;' ),
 302+ htmlspecialchars( $text )
 303+ );
 304+ return $text;
 305+ }
 306+
 307+ /**
 308+ * Parse an HTTP response object into an array of relevant RSS data
 309+ *
 310+ * @param $key String: the key to use to store the parsed response in the cache
 311+ * @return parsed RSS object (see RSSParse) or false
 312+ */
 313+ protected function responseToXML( $key ) {
 314+ wfDebugLog( 'RSS', "Got '" . $this->client->getStatus() . "', updating cache for $key" );
 315+ if ( $this->client->getStatus() === 304 ) {
 316+ # Not modified, update cache
 317+ wfDebugLog( 'RSS', "Got 304, updating cache for $key" );
 318+ $this->storeInCache( $key );
 319+ } else {
 320+ $this->xml = new DOMDocument;
 321+ $raw_xml = $this->client->getContent();
 322+
 323+ if( $raw_xml == '' ) {
 324+ return Status::newFatal( 'rss-parse-error', 'No XML content' );
 325+ }
 326+
 327+ wfSuppressWarnings();
 328+ $this->xml->loadXML( $raw_xml );
 329+ wfRestoreWarnings();
 330+
 331+ $this->rss = new RSSData( $this->xml );
 332+
 333+ // if RSS parsed successfully
 334+ if ( $this->rss && !$this->rss->error ) {
 335+ $this->etag = $this->client->getResponseHeader( 'Etag' );
 336+ $this->lastModified =
 337+ strtotime( $this->client->getResponseHeader( 'Last-Modified' ) );
 338+
 339+ wfDebugLog( 'RSS', 'Stored etag (' . $this->etag . ') and Last-Modified (' .
 340+ $this->client->getResponseHeader( 'Last-Modified' ) . ') and items (' .
 341+ count( $this->rss->items ) . ')!' );
 342+ $this->storeInCache( $key );
 343+ } else {
 344+ return Status::newFatal( 'rss-parse-error', $this->rss->error );
 345+ }
 346+ }
 347+ return Status::newGood();
 348+ }
 349+
 350+ /**
 351+ * Determine if a given item should or should not be displayed
 352+ *
 353+ * @param $item Array: associative array that RSSData produced for an <item>
 354+ * @return boolean
 355+ */
 356+ protected function canDisplay( array $item ) {
 357+ $check = '';
 358+
 359+ /* We're only going to check the displayable fields */
 360+ foreach ( $this->displayFields as $field ) {
 361+ if ( isset( $item[$field] ) ) {
 362+ $check .= $item[$field];
 363+ }
 364+ }
 365+
 366+ if ( $this->filter( $check, 'filterOut' ) ) {
 367+ return false;
 368+ }
 369+ if ( $this->filter( $check, 'filter' ) ) {
 370+ return true;
 371+ }
 372+ return false;
 373+ }
 374+
 375+ /**
 376+ * Filters items in or out if the match a string we're looking for.
 377+ *
 378+ * @param $text String: the text to examine
 379+ * @param $filterType String: "filterOut" to check for matches in the
 380+ * filterOut member list.
 381+ * Otherwise, uses the filter member list.
 382+ * @return Boolean: decision to filter or not.
 383+ */
 384+ protected function filter( $text, $filterType ) {
 385+ if ( $filterType === 'filterOut' ) {
 386+ $filter = $this->filterOut;
 387+ } else {
 388+ $filter = $this->filter;
 389+ }
 390+
 391+ if ( count( $filter ) == 0 ) {
 392+ return $filterType !== 'filterOut';
 393+ }
 394+
 395+ /* Using : for delimiter here since it'll be quoted automatically. */
 396+ $match = preg_match( ':(' . implode( '|', array_map( 'preg_quote', $filter ) ) . '):i', $text ) ;
 397+ if ( $match ) {
 398+ return true;
 399+ }
 400+ return false;
 401+ }
 402+
 403+ /**
 404+ * Highlight the words we're supposed to be looking for
 405+ *
 406+ * @param $text String: the text to look in.
 407+ * @return String with matched text highlighted in a <span> element
 408+ */
 409+ protected function highlightTerms( $text ) {
 410+ if ( count( $this->highlight ) === 0 ) {
 411+ return $text;
 412+ }
 413+
 414+ RSSHighlighter::setTerms( $this->highlight );
 415+ $highlight = ':'. implode( '|', array_map( 'preg_quote', array_values( $this->highlight ) ) ) . ':i';
 416+ return preg_replace_callback( $highlight, 'RSSHighlighter::highlightThis', $text );
 417+ }
 418+}
 419+
 420+
 421+class RSSHighlighter {
 422+ static $terms = array();
 423+
 424+ /**
 425+ * Set the list of terms to match for the next highlighting session
 426+ * @param $terms Array: list of words to match.
 427+ */
 428+ static function setTerms( array $terms ) {
 429+ self::$terms = array_flip( array_map( 'strtolower', $terms ) );
 430+ }
 431+
 432+ /**
 433+ * Actually replace the supplied list of words with HTML code to highlight the words.
 434+ * @param $match Array: list of matched words to highlight.
 435+ * The words are assigned colors based upon the order
 436+ * they were supplied in setTerms()
 437+ * @return String word wrapped in HTML code.
 438+ */
 439+ static function highlightThis( $match ) {
 440+ $styleStart = "<span style='font-weight: bold; background: none repeat scroll 0%% 0%% rgb(%s); color: %s;'>";
 441+ $styleEnd = '</span>';
 442+
 443+ # bg colors cribbed from Google's highlighting of search terms
 444+ $bgcolor = array( '255, 255, 102', '160, 255, 255', '153, 255, 153',
 445+ '255, 153, 153', '255, 102, 255', '136, 0, 0', '0, 170, 0', '136, 104, 0',
 446+ '0, 70, 153', '153, 0, 153' );
 447+ # Spelling out the fg colors instead of using processing time to create this list
 448+ $color = array( 'black', 'black', 'black', 'black', 'black',
 449+ 'white', 'white', 'white', 'white', 'white' );
 450+
 451+ $index = self::$terms[strtolower( $match[0] )] % count( $bgcolor );
 452+
 453+ return sprintf( $styleStart, $bgcolor[$index], $color[$index] ) . $match[0] . $styleEnd;
 454+ }
 455+}
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/RSSParser.php
___________________________________________________________________
Added: svn:eol-style
1456 + native
Added: svn:eol-syle
2457 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/RSS.i18n.php
@@ -0,0 +1,379 @@
 2+<?php
 3+/**
 4+ * Internationalization file for RSS extension.
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Łukasz Garczewski (TOR) <tor@wikia-inc.com>
 14+ */
 15+$messages['en'] = array(
 16+ 'rss-desc' => 'Displays an RSS feed on a wiki page',
 17+ 'rss-error' => 'Failed to load RSS feed from $1: $2',
 18+ 'rss-empty' => 'Failed to load RSS feed from $1!',
 19+ 'rss-fetch-nourl' => 'Fetch called without a URL!',
 20+ 'rss-invalid-url' => 'Not a valid URL: $1',
 21+ 'rss-parse-error' => 'Error parsing XML for RSS',
 22+ 'rss-item' => '{{RSSPost | title = {{{title}}} | link = {{{link}}} | date = {{{date}}} | author = {{{author}}} }}',
 23+);
 24+
 25+$messages['qqq'] = array(
 26+ 'rss-item' => 'Do not translate',
 27+);
 28+
 29+/** Afrikaans (Afrikaans)
 30+ * @author Naudefj
 31+ */
 32+$messages['af'] = array(
 33+ 'rss-desc' => "Bied 'n RSS-voer vir 'n wikibladsy",
 34+ 'rss-error' => 'Kon nie die RSS-voer van $1 laai nie, fout: $2',
 35+ 'rss-empty' => 'Kon nie die RSS-voer van $1 laai nie!',
 36+);
 37+
 38+/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
 39+ * @author EugeneZelenko
 40+ * @author Jim-by
 41+ */
 42+$messages['be-tarask'] = array(
 43+ 'rss-desc' => 'Паказвае RSS-стужкі на вікі-старонках',
 44+ 'rss-error' => 'Памылка загрузкі RSS-стужкі з $1: $2',
 45+ 'rss-empty' => 'Памылка загрузкі RSS-стужкі з $1!',
 46+ 'rss-fetch-nourl' => 'Выбарка выкліканая без URL-адрасу!',
 47+ 'rss-invalid-url' => 'Няслушны URL-адрас: $1',
 48+ 'rss-parse-error' => 'Памылка аналізу XML для RSS',
 49+);
 50+
 51+/** Breton (Brezhoneg)
 52+ * @author Fulup
 53+ * @author Y-M D
 54+ */
 55+$messages['br'] = array(
 56+ 'rss-desc' => 'Diskouez ur gwazh RSS war ur bajenn eus ar wiki',
 57+ 'rss-error' => 'Dibosupl eo kargañ ar gwazh RSS eus $1 : $2',
 58+ 'rss-empty' => 'Dibosupl eo kargañ gwazh RSS eus $1 !',
 59+ 'rss-fetch-nourl' => 'Galvadenn klask hep URL !',
 60+ 'rss-invalid-url' => 'URL direizh : $1',
 61+ 'rss-parse-error' => 'Fazi en dielfennañ XML evit RSS',
 62+);
 63+
 64+/** Bosnian (Bosanski)
 65+ * @author CERminator
 66+ */
 67+$messages['bs'] = array(
 68+ 'rss-desc' => 'Prikazuje RSS fid na wiki stranici',
 69+ 'rss-error' => 'Nije uspjelo učitavanje RSS fida iz $1: $2',
 70+ 'rss-empty' => 'Nije uspjelo učitavanje RSS fida iz $1!',
 71+ 'rss-fetch-nourl' => 'Akcija pozvana bez URL!',
 72+ 'rss-invalid-url' => 'Nije valjan URL: $1',
 73+ 'rss-parse-error' => 'Greška pri parsiranju XML za RSS',
 74+);
 75+
 76+/** German (Deutsch)
 77+ * @author Kghbln
 78+ */
 79+$messages['de'] = array(
 80+ 'rss-desc' => 'Ermöglicht es, einen RSS-Feed auf einer Wikiseite anzuzeigen',
 81+ 'rss-error' => 'Der RSS-Feed konnte nicht von $1 geladen werden: $2',
 82+ 'rss-empty' => 'Der RSS-Feed konnte nicht von $1 geladen werden!',
 83+ 'rss-fetch-nourl' => 'Abruf ohne Angabe einer URL!',
 84+ 'rss-invalid-url' => 'Ungültige URL: $1',
 85+ 'rss-parse-error' => 'Fehler beim Parsen von XML für RSS',
 86+);
 87+
 88+/** Lower Sorbian (Dolnoserbski)
 89+ * @author Michawiki
 90+ */
 91+$messages['dsb'] = array(
 92+ 'rss-desc' => 'Zwobraznjujo RSS-kanal na wikiboku',
 93+ 'rss-error' => 'RSS-kanal njejo dał se z $1 zacytaś: $2',
 94+ 'rss-empty' => 'RSS-kanal njejo dał se z $1 zacytaś!',
 95+ 'rss-fetch-nourl' => 'Wótwołanje bźez URL!',
 96+ 'rss-invalid-url' => 'Njepłaśiwy URL: $1',
 97+ 'rss-parse-error' => 'Zmólka pśi parsowanju XML za RSS',
 98+);
 99+
 100+/** Spanish (Español)
 101+ * @author Locos epraix
 102+ */
 103+$messages['es'] = array(
 104+ 'rss-desc' => 'Muestra un feed RSS en una página wiki',
 105+ 'rss-error' => 'No se pudo cargar el feed RSS desde $1: $2',
 106+ 'rss-empty' => 'No se pudo cargar feed RSS desde $1!',
 107+);
 108+
 109+/** Finnish (Suomi)
 110+ * @author Jack Phoenix <jack@countervandalism.net>
 111+ */
 112+$messages['fi'] = array(
 113+ 'rss-error' => 'RSS-syötteen lataaminen osoitteesta $1 epäonnistui: $2',
 114+ 'rss-empty' => 'RSS-syötteen lataaminen osoitteesta $1 epäonnistui!',
 115+);
 116+
 117+/** French (Français)
 118+ * @author IAlex
 119+ * @author Peter17
 120+ */
 121+$messages['fr'] = array(
 122+ 'rss-desc' => 'Affiche un flux RSS sur une page du wiki',
 123+ 'rss-error' => 'Impossible de charger le flux RSS de $1 : $2',
 124+ 'rss-empty' => 'Impossible de charger le flux RSS de $1 !',
 125+ 'rss-fetch-nourl' => 'Appel passé sans fournir d’URL !',
 126+ 'rss-invalid-url' => 'URL non valide : $1',
 127+ 'rss-parse-error' => 'Erreur lors de l’analyse XML du RSS',
 128+);
 129+
 130+/** Galician (Galego)
 131+ * @author Toliño
 132+ */
 133+$messages['gl'] = array(
 134+ 'rss-desc' => 'Mostra unha fonte de novas RSS nunha páxina wiki',
 135+ 'rss-error' => 'Erro ao cargar a fonte de novas RSS de "$1": $2',
 136+ 'rss-empty' => 'Erro ao cargar a fonte de novas RSS de "$1"!',
 137+ 'rss-fetch-nourl' => 'Non deu ningún enderezo URL!',
 138+ 'rss-invalid-url' => 'O enderezo URL non é válido: $1',
 139+ 'rss-parse-error' => 'Erro analítico de XML para o RSS',
 140+);
 141+
 142+/** Swiss German (Alemannisch)
 143+ * @author Als-Holder
 144+ */
 145+$messages['gsw'] = array(
 146+ 'rss-desc' => 'Zeigt e RSS-Feed uf ere Wikisyte aa',
 147+ 'rss-error' => 'Dr RSS-Feed het nit vu $1 chenne glade wäre: $2',
 148+ 'rss-empty' => 'Dr RSS-Feed het nit vu $1 chenne glade wäre!',
 149+ 'rss-fetch-nourl' => 'Abruef ohni Aagab vun ere URL!',
 150+ 'rss-invalid-url' => 'Uugiltigi URL: $1',
 151+ 'rss-parse-error' => 'Fähler bim Parse vu XML fir RSS',
 152+);
 153+
 154+/** Upper Sorbian (Hornjoserbsce)
 155+ * @author Michawiki
 156+ */
 157+$messages['hsb'] = array(
 158+ 'rss-desc' => 'Zwobraznja RSS-kanal na wikistronje',
 159+ 'rss-error' => 'Začitowanje RSS-kanala z $1 je so njeporadźiło: $2',
 160+ 'rss-empty' => 'Začitowanje RSS-kanala z $1 je so njeporadźiło!',
 161+ 'rss-fetch-nourl' => 'Wotwołanje bjez URL!',
 162+ 'rss-invalid-url' => 'Njepłaćiwy URL: $1',
 163+ 'rss-parse-error' => 'Zmylk při parsowanju XML za RSS',
 164+);
 165+
 166+/** Interlingua (Interlingua)
 167+ * @author McDutchie
 168+ */
 169+$messages['ia'] = array(
 170+ 'rss-desc' => 'Monstra un syndication RSS in un pagina wiki',
 171+ 'rss-error' => 'Falleva de cargar le syndication RSS de $1: $2',
 172+ 'rss-empty' => 'Falleva de cargar le syndication RSS de $1!',
 173+ 'rss-fetch-nourl' => 'Tentativa de obtention sin URL!',
 174+ 'rss-invalid-url' => 'URL non valide: $1',
 175+ 'rss-parse-error' => 'Error de syntaxe in XML de RSS',
 176+);
 177+
 178+/** Indonesian (Bahasa Indonesia)
 179+ * @author Farras
 180+ * @author IvanLanin
 181+ */
 182+$messages['id'] = array(
 183+ 'rss-desc' => 'Menampilkan arus RSS di halaman wiki',
 184+ 'rss-error' => 'Gagal memuat arus RSS dari $1: $2',
 185+ 'rss-empty' => 'Gagal memuat arus RSS dari $1!',
 186+ 'rss-fetch-nourl' => 'Pengambilan dilakukan tanpa URL!',
 187+ 'rss-invalid-url' => 'Bukan URL yang sah: $1',
 188+ 'rss-parse-error' => 'Kesalahan parsing XML untuk RSS',
 189+);
 190+
 191+/** Italian (Italiano)
 192+ * @author Gianfranco
 193+ */
 194+$messages['it'] = array(
 195+ 'rss-desc' => 'Visualizza un feed RSS in una pagina wiki',
 196+ 'rss-error' => 'Non è stato possibile caricare da $1 il feed RSS: $2',
 197+ 'rss-empty' => 'Non è stato possibile possibile caricare feed RSS da $1!',
 198+);
 199+
 200+/** Japanese (日本語)
 201+ * @author Iwai.masaharu
 202+ * @author 青子守歌
 203+ */
 204+$messages['ja'] = array(
 205+ 'rss-desc' => 'ウィキページのRSSフィードを表示',
 206+ 'rss-error' => '$1からのRSSフィードの読み込みに失敗しました:$2',
 207+ 'rss-empty' => '$1からのRSSフィードの読み込みに失敗しました!',
 208+ 'rss-fetch-nourl' => '取得する URL が指定されていません!',
 209+ 'rss-invalid-url' => '無効な URL: $1',
 210+ 'rss-parse-error' => 'RSS の XML 解析エラー',
 211+);
 212+
 213+/** Colognian (Ripoarisch)
 214+ * @author Purodha
 215+ */
 216+$messages['ksh'] = array(
 217+ 'rss-desc' => 'Zeisch ene RSS-Kannaal op en Sigg em Wiki.',
 218+ 'rss-error' => 'Mer kunnte dä RSS-Kannaal vun $1 nit laade: $2',
 219+ 'rss-empty' => 'Mer kunnte dä RSS-Kannaal vun $1 nit laade.',
 220+);
 221+
 222+/** Luxembourgish (Lëtzebuergesch)
 223+ * @author Robby
 224+ */
 225+$messages['lb'] = array(
 226+ 'rss-desc' => 'Weist en RSS-Feed op enger Wiki-Säit',
 227+ 'rss-error' => 'Den RSS-Feed vun $1 konnt net geluede ginn: $2',
 228+ 'rss-empty' => 'Den RSS-Feed vun $1 konnt net geluede ginn!',
 229+);
 230+
 231+/** Macedonian (Македонски)
 232+ * @author Bjankuloski06
 233+ */
 234+$messages['mk'] = array(
 235+ 'rss-desc' => 'Прикажува RSS-канал на викистраница',
 236+ 'rss-error' => 'Не успеав да го вчитам RSS-каналот од $1: $2',
 237+ 'rss-empty' => 'Не успеав да го вчитам RSS-каналот од $1!',
 238+ 'rss-fetch-nourl' => 'Повикувањето за добивање нема URL!',
 239+ 'rss-invalid-url' => 'Не претставува важечка URL: $1',
 240+ 'rss-parse-error' => 'Грешка при парсирање на XML за RSS',
 241+);
 242+
 243+/** Dutch (Nederlands)
 244+ * @author Mitchel Corstjens
 245+ * @author Siebrand
 246+ */
 247+$messages['nl'] = array(
 248+ 'rss-desc' => 'Biedt een RSS-feed voor een wikipagina',
 249+ 'rss-error' => 'Kon RSS feed van $1 niet laden, fout: $2',
 250+ 'rss-empty' => 'Kon RSS feed van $1 niet laden!',
 251+ 'rss-fetch-nourl' => 'Fetch is aangeroepen zonder een URL!',
 252+ 'rss-invalid-url' => 'Geen geldige URL: $1',
 253+ 'rss-parse-error' => 'Fout bij het verwerken van de XML voor RSS',
 254+);
 255+
 256+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 257+ * @author Nghtwlkr
 258+ */
 259+$messages['no'] = array(
 260+ 'rss-desc' => 'Viser en RSS-mating på en wikiside',
 261+ 'rss-error' => 'Kunne ikke laste RSS-mating fra $1: $2',
 262+ 'rss-empty' => 'Kunne ikke laste RSS-mating fra $1.',
 263+);
 264+
 265+/** Polish (Polski)
 266+ * @author Sp5uhe
 267+ */
 268+$messages['pl'] = array(
 269+ 'rss-desc' => 'Wyświetla kanał RSS na stronie wiki',
 270+ 'rss-error' => 'Nie udało się odczytać kanału $1: $2',
 271+ 'rss-empty' => 'Nie udało się odczytać kanału $1!',
 272+ 'rss-fetch-nourl' => 'Wywołano pobieranie bez adresu URL!',
 273+ 'rss-invalid-url' => 'Nieprawidłowy adres URL – $1',
 274+ 'rss-parse-error' => 'Błąd analizowania XML dla RSS',
 275+);
 276+
 277+/** Piedmontese (Piemontèis)
 278+ * @author Borichèt
 279+ * @author Dragonòt
 280+ */
 281+$messages['pms'] = array(
 282+ 'rss-desc' => 'A mostra un fluss RSS su na pàgina dla wiki',
 283+ 'rss-error' => 'Falì a carié ël fluss RSS da $1: $2',
 284+ 'rss-empty' => 'Falì a carié ël fluss RSS da $1!',
 285+ 'rss-fetch-nourl' => "Fetch ciamà sensa n'anliura!",
 286+ 'rss-invalid-url' => "Pa n'anliura bon-a: $1",
 287+ 'rss-parse-error' => 'Eror an parsificand XML për RSS',
 288+);
 289+
 290+/** Portuguese (Português)
 291+ * @author Giro720
 292+ * @author Hamilton Abreu
 293+ */
 294+$messages['pt'] = array(
 295+ 'rss-desc' => 'Mostra um feed RSS numa página wiki',
 296+ 'rss-error' => 'Não foi possível carregar o feed RSS de $1: $2',
 297+ 'rss-empty' => 'Não foi possível carregar o feed RSS de $1!',
 298+ 'rss-fetch-nourl' => 'Chamada fetch sem uma URL!',
 299+ 'rss-invalid-url' => 'A URL não é válida: $1',
 300+ 'rss-parse-error' => 'Erro ao analisar XML para o RSS',
 301+);
 302+
 303+/** Brazilian Portuguese (Português do Brasil)
 304+ * @author Giro720
 305+ */
 306+$messages['pt-br'] = array(
 307+ 'rss-desc' => 'Mostra um feed RSS em uma página wiki',
 308+ 'rss-error' => 'Falha ao carregar feed RSS de $1: $2',
 309+ 'rss-empty' => 'Falha ao carregar feed RSS de $1!',
 310+ 'rss-fetch-nourl' => 'Chamada fetch sem uma URL!',
 311+ 'rss-invalid-url' => 'Não é uma URL válida: $1',
 312+ 'rss-parse-error' => 'Erro ao analisar XML para o RSS',
 313+);
 314+
 315+/** Romanian (Română)
 316+ * @author Minisarm
 317+ */
 318+$messages['ro'] = array(
 319+ 'rss-desc' => 'Afișează un flux RSS pe o pagină wiki',
 320+ 'rss-error' => 'Eroare la încărcarea fluxului RSS de la $1: $2',
 321+ 'rss-empty' => 'Eroare la încărcarea fluxului RSS de la $1!',
 322+);
 323+
 324+/** Tarandíne (Tarandíne)
 325+ * @author Joetaras
 326+ */
 327+$messages['roa-tara'] = array(
 328+ 'rss-desc' => "Fà vedè 'nu feed RSS sus a 'na pàgene de uicchi",
 329+ 'rss-error' => "Carecamende d'u feed RSS fallite da $1: $2",
 330+ 'rss-empty' => "Carecamende d'u feed RSS fallite da $1!",
 331+);
 332+
 333+/** Russian (Русский)
 334+ * @author Александр Сигачёв
 335+ */
 336+$messages['ru'] = array(
 337+ 'rss-desc' => 'Показывает RSS-канал на викистранице',
 338+ 'rss-error' => 'Не удалось загрузить RSS-канал из $1: $2',
 339+ 'rss-empty' => 'Не удалось загрузить RSS-канал из $1!',
 340+ 'rss-fetch-nourl' => 'Выборка вызвана без URL!',
 341+ 'rss-invalid-url' => 'Недопустимый URL: $1',
 342+ 'rss-parse-error' => 'Ошибка разбора XML для RSS',
 343+);
 344+
 345+/** Tagalog (Tagalog)
 346+ * @author AnakngAraw
 347+ */
 348+$messages['tl'] = array(
 349+ 'rss-desc' => 'Nagpapakita ng isang pakaing RSS sa isang pahina ng wiki',
 350+ 'rss-error' => 'Nabigong ikarga ang pakaing RSS mula sa $1: $2',
 351+ 'rss-empty' => 'Nabigong ikarga ang pakaing RSS mula sa $1!',
 352+);
 353+
 354+/** Tatar (Cyrillic) (Татарча/Tatarça (Cyrillic))
 355+ * @author Ильнар
 356+ */
 357+$messages['tt-cyrl'] = array(
 358+ 'rss-desc' => 'RSS-тасманы викибиттә ачу',
 359+ 'rss-error' => '$1: $2 битләреннән RSS-тасманы ачып булмады',
 360+ 'rss-empty' => '$1: битеннән RSS-тасманы ачып булмады',
 361+);
 362+
 363+/** Ukrainian (Українська)
 364+ * @author Arturyatsko
 365+ */
 366+$messages['uk'] = array(
 367+ 'rss-desc' => 'Відображає канал RSS на сторінці вікі',
 368+ 'rss-error' => 'Не вдалося завантажити RSS-канал від $1: $2',
 369+ 'rss-empty' => 'Не вдалося завантажити RSS-канал від $1!',
 370+);
 371+
 372+/** Simplified Chinese (‪中文(简体)‬)
 373+ * @author Chenxiaoqino
 374+ */
 375+$messages['zh-hans'] = array(
 376+ 'rss-desc' => '在维基页面上显示一个RSS源',
 377+ 'rss-error' => '自$1: $2加载RSS失败',
 378+ 'rss-empty' => '自$1加载RSS失败',
 379+);
 380+
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/RSS.i18n.php
___________________________________________________________________
Added: svn:eol-style
1381 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/README
@@ -0,0 +1,11 @@
 2+== About ==
 3+
 4+Displays an RSS feed on a wiki page.
 5+See http://www.mediawiki.org/wiki/Extension:RSS
 6+
 7+== Credits to other projects ==
 8+
 9+* MagpieRSS
 10+This extension includes code from the MagpieRSS library.
 11+MagpieRSS provides an XML-based (expat) RSS parser in PHP,
 12+and is released under the GPL.
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/README
___________________________________________________________________
Added: svn:eol-style
113 + native
Index: branches/wmf/1.16wmf4/extensions/RSS/RSS.php
@@ -0,0 +1,60 @@
 2+<?php
 3+/**
 4+ * RSS-Feed MediaWiki extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ * @version 1.8
 9+ * @author mutante, Daniel Kinzler, Rdb, Mafs, Alxndr, Chris Reigrut, K001
 10+ * @author Kellan Elliott-McCrea <kellan@protest.net> -- author of MagpieRSS
 11+ * @author Jeroen De Dauw
 12+ * @author Jack Phoenix <jack@countervandalism.net>
 13+ * @copyright © Kellan Elliott-McCrea <kellan@protest.net>
 14+ * @copyright © mutante, Daniel Kinzler, Rdb, Mafs, Alxndr, Chris Reigrut, K001
 15+ * @link http://www.mediawiki.org/wiki/Extension:RSS Documentation
 16+ */
 17+
 18+if ( !defined( 'MEDIAWIKI' ) ) {
 19+ die( "This is not a valid entry point.\n" );
 20+}
 21+
 22+// Extension credits that will show up on Special:Version
 23+$wgExtensionCredits['parserhook'][] = array(
 24+ 'name' => 'RSS feed',
 25+ 'author' => array(
 26+ 'Kellan Elliott-McCrea',
 27+ 'mutante',
 28+ 'Daniel Kinzler',
 29+ 'Rdb',
 30+ 'Mafs',
 31+ 'Alxndr',
 32+ 'Wikinaut',
 33+ 'Chris Reigrut',
 34+ 'K001',
 35+ 'Jack Phoenix',
 36+ 'Jeroen De Dauw',
 37+ 'Mark A. Hershberger'
 38+ ),
 39+ 'version' => '1.8',
 40+ 'url' => 'http://www.mediawiki.org/wiki/Extension:RSS',
 41+ 'descriptionmsg' => 'rss-desc',
 42+);
 43+
 44+// Internationalization file and autoloadable classes
 45+$dir = dirname( __FILE__ ) . '/';
 46+$wgExtensionMessagesFiles['RSS'] = $dir . 'RSS.i18n.php';
 47+$wgAutoloadClasses['RSSHooks'] = $dir . 'RSSHooks.php';
 48+$wgAutoloadClasses['RSSParser'] = $dir . 'RSSParser.php';
 49+$wgAutoloadClasses['RSSData'] = $dir . 'RSSData.php';
 50+
 51+$wgHooks['ParserFirstCallInit'][] = 'RSSHooks::parserInit';
 52+
 53+$wgRSSCacheAge = 3600; // one hour
 54+$wgRSSCacheCompare = false; // Check cached content, if available, against remote.
 55+ // $wgRSSCacheCompare should be set to false or a timeout
 56+ // (less than $wgRSSCacheAge) after which a comparison will
 57+ // be made.
 58+$wgRSSFetchTimeout = 5; // 5 second timeout
 59+
 60+// Agent to use for fetching feeds
 61+$wgRSSUserAgent = 'MediaWikiRSS/0.01 (+http://www.mediawiki.org/wiki/Extension:RSS) / MediaWiki RSS extension';
\ No newline at end of file
Property changes on: branches/wmf/1.16wmf4/extensions/RSS/RSS.php
___________________________________________________________________
Added: svn:eol-style
162 + native

Status & tagging log