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 |
1 | 52 | + native |
Added: svn:eol-syle |
2 | 53 | + 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 |
1 | 13 | + 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! —[[User:Alxndr|Alxndr]] <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? —[[User:Alxndr|Alxndr]] <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 |
1 | 26 | + 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 |
1 | 86 | + native |
Added: svn:eol-syle |
2 | 87 | + 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 |
1 | 350 | + 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( '[', '|', ']', ''', 'ISBN ', |
| 301 | + 'RFC ', '://', "\n=", '{{', '}}' ), |
| 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 |
1 | 456 | + native |
Added: svn:eol-syle |
2 | 457 | + 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 |
1 | 381 | + 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 |
1 | 13 | + 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 |
1 | 62 | + native |