[qo-modules-dev] [1] initial import |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/qo-modules-dev Archives
]
Revision: 1
Author: ytorres
Date: 2008-11-03 21:45:59 +0100 (Mon, 03 Nov 2008)
Log Message:
-----------
initial import
Added Paths:
-----------
qokregator/
trunk/
trunk/qo-kregator/
trunk/qo-kregator/DewPlayer/
trunk/qo-kregator/DewPlayer/dewplayer.swf
trunk/qo-kregator/DewTube/
trunk/qo-kregator/DewTube/dewtube.swf
trunk/qo-kregator/README.txt
trunk/qo-kregator/img/
trunk/qo-kregator/img/default/
trunk/qo-kregator/img/default/bullet_blue.png
trunk/qo-kregator/img/default/collapse.png
trunk/qo-kregator/img/default/conf.png
trunk/qo-kregator/img/default/date.png
trunk/qo-kregator/img/default/default_fav.png
trunk/qo-kregator/img/default/desktop-icon.png
trunk/qo-kregator/img/default/exclamation.png
trunk/qo-kregator/img/default/expand-collapse.png
trunk/qo-kregator/img/default/expand.png
trunk/qo-kregator/img/default/export.png
trunk/qo-kregator/img/default/feed_add.png
trunk/qo-kregator/img/default/feed_delete.png
trunk/qo-kregator/img/default/feed_modify.png
trunk/qo-kregator/img/default/flag_red.png
trunk/qo-kregator/img/default/folder_add.png
trunk/qo-kregator/img/default/folder_delete.png
trunk/qo-kregator/img/default/folder_go.png
trunk/qo-kregator/img/default/folder_modify.png
trunk/qo-kregator/img/default/folder_open.png
trunk/qo-kregator/img/default/grid3-hrow.gif
trunk/qo-kregator/img/default/icon.png
trunk/qo-kregator/img/default/import.png
trunk/qo-kregator/img/default/information.png
trunk/qo-kregator/img/default/key.png
trunk/qo-kregator/img/default/loading.gif
trunk/qo-kregator/img/default/logo.png
trunk/qo-kregator/img/default/mark_all_as_read.png
trunk/qo-kregator/img/default/mark_as_read.png
trunk/qo-kregator/img/default/mark_as_unread.png
trunk/qo-kregator/img/default/media-flv.png
trunk/qo-kregator/img/default/media-mp3.png
trunk/qo-kregator/img/default/media-pdf.png
trunk/qo-kregator/img/default/media-video.png
trunk/qo-kregator/img/default/media.png
trunk/qo-kregator/img/default/mouse.png
trunk/qo-kregator/img/default/open_in_tab.png
trunk/qo-kregator/img/default/open_site.png
trunk/qo-kregator/img/default/preview-bottom.png
trunk/qo-kregator/img/default/preview-hide.png
trunk/qo-kregator/img/default/preview-right.png
trunk/qo-kregator/img/default/refresh.png
trunk/qo-kregator/img/default/stop.png
trunk/qo-kregator/img/default/summary-p.png
trunk/qo-kregator/img/default/summary.png
trunk/qo-kregator/img/default/tab_delete.png
trunk/qo-kregator/install.sql
trunk/qo-kregator/license_LGPL_v2.txt
trunk/qo-kregator/locale/
trunk/qo-kregator/locale/Desk-Kregator-en.js
trunk/qo-kregator/locale/Desk-Kregator-fr.js
trunk/qo-kregator/locale/Desk-Kregator-pt_br.js
trunk/qo-kregator/locale/Desk-Kregator-vn.js
trunk/qo-kregator/php/
trunk/qo-kregator/php/cache/
trunk/qo-kregator/php/cache/memberID_3/
trunk/qo-kregator/php/cache/memberID_3/b3b45881d4751326bcdd9ce5e1595a4b2e6009dc.spc
trunk/qo-kregator/php/cache/memberID_3/fav_b3b45881d4751326bcdd9ce5e1595a4b2e6009dc_favicon.ico
trunk/qo-kregator/php/cache/memberID_3/img_b3b45881d4751326bcdd9ce5e1595a4b2e6009dc_rss.jpg
trunk/qo-kregator/php/export.php
trunk/qo-kregator/php/lib.php
trunk/qo-kregator/php/qo-kregator.php
trunk/qo-kregator/php/simplepie.inc.php
trunk/qo-kregator/qo-kregator.css
trunk/qo-kregator/qo-kregator.js
trunk/qo-kregator/qo-kregator_old.js
trunk/qo-kregator/uninstall.sql
trunk/qo-kregator/ux/
trunk/qo-kregator/ux/FileUploadField/
trunk/qo-kregator/ux/FileUploadField/FileUploadField.js
trunk/qo-kregator/ux/MultiselectItemSelector/
trunk/qo-kregator/ux/MultiselectItemSelector/DDView.js
trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.css
trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.js
trunk/qo-kregator/ux/MultiselectItemSelector/bottom2.gif
trunk/qo-kregator/ux/MultiselectItemSelector/down2.gif
trunk/qo-kregator/ux/MultiselectItemSelector/left2.gif
trunk/qo-kregator/ux/MultiselectItemSelector/right2.gif
trunk/qo-kregator/ux/MultiselectItemSelector/top2.gif
trunk/qo-kregator/ux/MultiselectItemSelector/up2.gif
trunk/qo-kregator/ux/miframe/
trunk/qo-kregator/ux/miframe/miframe.js
trunk/qo-kregator/ux/miframe/v_03-11-2008
trunk/qo-kregator/ux/spinner/
trunk/qo-kregator/ux/spinner/Spinner.css
trunk/qo-kregator/ux/spinner/Spinner.js
trunk/qo-kregator/ux/spinner/SpinnerStrategy.js
trunk/qo-kregator/ux/spinner/spinner-split.gif
trunk/qo-kregator/ux/spinner/spinner.gif
trunk/qo-kregator/ux/spinner/v_0.35.txt
Added: trunk/qo-kregator/DewPlayer/dewplayer.swf
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/DewPlayer/dewplayer.swf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/DewTube/dewtube.swf
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/DewTube/dewtube.swf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/README.txt
===================================================================
--- trunk/qo-kregator/README.txt (rev 0)
+++ trunk/qo-kregator/README.txt 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,151 @@
+/************************************************************************
+ This file is part of Qo-Kregator.
+ Qo-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+ *************************************************************************/
+
+Author : Yannick Torrès <yannick.torres@xxxxxxxxxxxx>
+Demo Server : http://qo-modules.tuxfamily.org/demo/
+Home Project : http://qo-modules.tuxfamily.org/
+
+Current : version 2.0
+* Change the Name to fit Qo-Modules schema. Desk-Kregator is dead, long life to Qo-Kregator !
+* New great Logo/Icon to fit the name's change. Thanks Franck Carrouget !
+* Configuration : we can now change the size of the text content via a slider
+* Configuration : we can now choose the mode to open Qo-Kregator : window, Maximized, Minimized
+* Configuration : we can now choose the format for all date and date/time
+* Configuration : we can now choose to show or hide the status bar
+* Configuration : we can now build entirely the toolBar for the Feed Panel via Multiselect's ux
+* New menu Button for the Feed ToolBar : same menu as right-click on a feed/folder ; especially for Opera user witch can't view contextMenu
+* New menu Button for the News ToolBar : same menu as right-click on a news ; especially for Opera user witch can't view contextMenu
+* New menu Button for the News ToolBar : we can now filter news by date, using a menu Date Picker.
+* Feed Tree : Add Fx when we remove a Feed/Tree
+* Make use of miframe to manage all iframe
+* Clean up via Jslint
+
+
+10-25-08 : version 1.2
+* Port to qWikiOffice v 0.8.1
+* Move cache/ folder to Desk-Kregator/php/cache/
+* Use native Ext.StatusBar (close bug n°5)
+* More logic into ID
+* Re-organize php's files into just one
+
+09-10-08 : version 1.1
+* First release for qWikiOffice v 0.7.1
+* Some minor change
+
+01-20-08 : version 1.0.1
+* Fix bug in get-user-conf.php
+* Add default value in `deskKregator_conf` Mysql's table
+
+01-16-08 : version 1.0
+* Add option in global objet to modify width of column Unseen & Total
+* Franckxx make some correction on icon set
+* more clean up the source code
+* Add splash & logo with number version
+* correct some minors bugs
+
+01-13-08 : version 1.0RC1
+* CleanUp : big code source cleanUp. Now, all var are in object config. No more dirty var in global scope.
+* FeedTree : each feed can be exclude from refresh Cycle in configuration window
+* AccessKey: CTRL + F : focus search field
+* AccessKey: CTRL + A : Select All items in GridItem
+* AccessKey: F5 : Refresh current feed
+* AccessKey: CTRL + R : Mark all items read for current feed
+* ContextMenu for Tab. Close tab, close other tabs & open in new window.
+
+01-12-08 : version 0.9
+* FeedTreeEditor : don't update name if it doesn't change (patch from Lev_A)
+* GridItem : add confirm box when delete items (idea from Lev_A)
+* GridItem : when item is deleted, next item is show automaticly. If there is no "next" item, then preview pane is blanked (idea from Lev_A)
+* GridItem : prevent multi-load get-items-desc when user dblclick on an item (patch from Lev_A)
+* FeedTree : Disable button when user click "save" btn in AddFolder box (idea from Kent)
+* FeedTree : Real destroy dom element for AddFeed window on close (patch from lucian_mateescu)
+* CSS file : Cleaning and names's homogenization
+* Media Enclosure : Detect pdf in enclosure. Exclude image from enclosure display
+* Translation : Vietnamese language file from Kent
+* Feed Name : remove dev tag from feed name
+
+01-10-08 : version 0.8
+For global application
+* Save in DB all width for all panel & restore it on app startup.
+* Remove in configuration window panel position. Now, when you switch between pane, state is store in DB too.
+* Add posibility to set an icon on desktop for Desk-Kregator in configuration window.
+* Franckxx provide me a new icon set. Make easy to swtich between different icon set & make this new icon set by default. Franckxx, the prince of PhotoShop
+
+For Feed Tree
+* Save in DB display mode for each folder (collapsed or not) & restore it on app startup.
+* Add default icon for feed who don't provide one (thanks to Franckxx who provide me some very nice default icon)
+* Add icon for collapse / expand all
+* Correct encoding for folder / feed text
+* Correct an old bug with FeedEditor
+* When Feeds are refresh, icon "refresh" became "Stop" to stop this operation.
+
+For Items Grid
+* Delete "State" text. Just leave combo who is enought (save space)
+* Modify button "preview pane" with one without text. Just Qtips.
+* Add button who provide a summary directly in Items grid, like in FeedViewer 3. This setting is store in DB & restore on next startup.
+* Remove Modal window. New behavior : when app start, first feed with unread items is loaded, then first items unread is loaded. So we can let's About/Config button in the same place.
+
+01-02-08 : version 0.7
+* Update SimplePie to version 1.0.1.
+* Now support Podcast & rssMedia. All media embed into a RSS Feed is now display at the end of article.
+For mp3 & flv media, you can play it directly with DewPlayer (http://www.alsacreations.fr/dewplayer) & DewTube (http://www.alsacreations.fr/dewtube) into Desk-Kregator ! Other media, like Quicktime, is play with your current webBrowser Plugins.
+* Minor interface improvement
+
+01-01-08 : version 0.6 - Happy new Year release
+* Change FeedTree to a custom TreeUi. No more Qtips for Feed to indicate number of unseen items. Instead, number of unseen & total are display in columns.
+* When a feed is added, we can now choose wathewer we want to read his items (normal or full site).
+* When a feed is successfull added, this feed is selected & items are loaded automatiquely.
+* In general configuration, we can now choose default preview pane position.
+* Improve Import of Opml file. Now works for every Opml version.
+
+If you're upgrade from previous version, just do this on your DB :
+Quote:
+ALTER TABLE `deskKregator_conf` ADD `preview_pane` ENUM( 'bottom', 'right', 'hide' ) NOT NULL DEFAULT 'bottom';
+
+12-27-07 : version 0.5
+* Add Splash Screen
+* Add configuration for global App. Now you can choose the delay before refresh all Feeds & if you want to delete old Items (older than X days, except "Important Items")
+* If you choose to delete old Items, then, all MySql tables needed by Desk-Kregator will be optimize
+* Use of Spinner Extension (http://extjs.com/forum/showthread.php?t=16352) to choose number of Days / refresh feeds
+* Add Import / Export Tools. Now you can export your feeds in Opml v1 file & import an Opml v1 file into Desk-Kregator.
+* Add TwinTriggerField for search items (thanks Lev_A for this idea => http://extjs.com/forum/showthread.php?p=101797#post101797)
+* Re-order Interface button (thanks to Franckxx for this work)
+* Fix this bug => http://extjs.com/forum/showthread.php?p=101259#post101259
+* NB : This version add a new MySql table. You need to add it if you're update your app from v0.4.
+
+12-20-07 : version 0.4
+* correct bug in get-nodes.php witch not display unseen items on startUp
+* Improvement on updateFeed fonction & remove updateFeedAuto function. Now, when we update a feed by right click (cache OFF) & new items are found, then Grid is reload. (spotted by Lev_A here => http://extjs.com/forum/showthread.php?p=100936#post100936)
+* correct bug in del-nodes.php when use FOREIGN KEY in deskKregator_items (spotted by Lev_A here => http://extjs.com/forum/showthread.php?p=100853#post100853)
+* correct name of public var in order to avoid conflict with other app
+
+12-19-07 : version 0.3
+* Warning : this new version work only with StartMenu version >= 12-11-07
+* Add logo from franckxx to About window (& credits)
+* Add pt_br translation provided by sorcerys
+* Fix bug spotted by Lev_A here => http://extjs.com/forum/showthread.php?p=100429#post100429
+* Fix reading pane for locale different to EN (spotted by franckxx here => http://extjs.com/forum/showthread.php?p=99739#post99739)
+
+12-10-07 : version 0.2
+* Remove un-needed item_id field in Database.
+* Add a lot of debug info about mysql error. Please, see response server in Firebug to know what's wrong with your app installation.
+* Intercept click in preview to open in new tab instead of current window
+* Fix bug in delete items & qtips
+* Add first french locale in ZIP file. Need to review it (currently break reading pane fonctionnality)
+* Fix important & unseen items color when use Slate or black theme
+* Add two files for this app. One, Desk-Kregator.js (33Ko), witch is "compact" and one, Desk-Kregator-source.js (55Ko) witch is readable.
+
+12-06-07 : version 0.1
+* First public release, as promised, in LGPL.
+This app work with desktop 2.0 greater than or equal to version 11-30-07
\ No newline at end of file
Added: trunk/qo-kregator/img/default/bullet_blue.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/bullet_blue.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/collapse.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/collapse.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/conf.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/conf.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/date.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/date.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/default_fav.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/default_fav.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/desktop-icon.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/desktop-icon.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/exclamation.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/exclamation.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/expand-collapse.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/expand-collapse.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/expand.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/expand.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/export.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/export.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/feed_add.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/feed_add.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/feed_delete.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/feed_delete.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/feed_modify.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/feed_modify.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/flag_red.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/flag_red.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/folder_add.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/folder_add.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/folder_delete.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/folder_delete.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/folder_go.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/folder_go.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/folder_modify.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/folder_modify.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/folder_open.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/folder_open.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/grid3-hrow.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/grid3-hrow.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/icon.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/icon.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/import.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/import.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/information.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/information.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/key.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/key.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/loading.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/loading.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/logo.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/logo.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/mark_all_as_read.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/mark_all_as_read.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/mark_as_read.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/mark_as_read.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/mark_as_unread.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/mark_as_unread.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/media-flv.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/media-flv.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/media-mp3.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/media-mp3.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/media-pdf.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/media-pdf.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/media-video.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/media-video.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/media.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/media.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/mouse.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/mouse.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/open_in_tab.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/open_in_tab.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/open_site.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/open_site.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/preview-bottom.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/preview-bottom.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/preview-hide.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/preview-hide.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/preview-right.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/preview-right.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/refresh.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/refresh.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/stop.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/stop.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/summary-p.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/summary-p.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/summary.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/summary.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/img/default/tab_delete.png
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/img/default/tab_delete.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/install.sql
===================================================================
--- trunk/qo-kregator/install.sql (rev 0)
+++ trunk/qo-kregator/install.sql 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,155 @@
+-- --------------------------------------------------------
+--
+-- Table `qo-kregator-conf`
+--
+
+CREATE TABLE IF NOT EXISTS `qo-kregator-conf` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `userID` int(10) unsigned NOT NULL,
+ `old_items` tinyint(3) unsigned default NULL,
+ `refresh_feed` tinyint(3) unsigned NOT NULL default '10',
+ `preview_pane` enum('bottom','right','hide') NOT NULL default 'bottom',
+ `showSummary` enum('true','false') NOT NULL default 'true',
+ `tree_panel_width` int(11) NOT NULL default '254',
+ `grid_panel_height` int(11) NOT NULL default '150',
+ `preview_panel_south_height` int(11) NOT NULL default '300',
+ `preview_panel_east_width` int(11) NOT NULL default '400',
+ `content_font_size` tinyint(4) unsigned NOT NULL default '11',
+ `showStatusBar` enum('on','off') NOT NULL default 'on',
+ `tbFeedBtn` varchar(255) NOT NULL default 'AddFeed,AddFolder,ExpandCollapse,RefreshFeed',
+ `openMode` enum('FullScreen','Window','Minimized') NOT NULL default 'Window',
+ `dateTimeFormat` varchar(50) NOT NULL default 'd/m/y, H:i',
+ `dateFormat` varchar(50) NOT NULL default 'd/m/y',
+ KEY `id` (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='User''s Configuration';
+
+-- --------------------------------------------------------
+--
+-- Table `qo-kregator-dir`
+--
+
+CREATE TABLE IF NOT EXISTS `qo-kregator-dir` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `type` enum('file','folder') NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `description` text NOT NULL,
+ `image` varchar(255) NOT NULL,
+ `favicon` varchar(255) NOT NULL,
+ `url` varchar(255) NOT NULL,
+ `url_feed` varchar(255) NOT NULL,
+ `view` enum('normal','site') NOT NULL default 'normal',
+ `refreshCycle` enum('on','off') NOT NULL default 'on',
+ `node` int(11) NOT NULL,
+ `display_order` int(10) unsigned NOT NULL,
+ `expand` tinyint(1) NOT NULL default '1',
+ `userID` int(11) NOT NULL,
+ KEY `id` (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Folder structure';
+
+-- --------------------------------------------------------
+--
+-- Table `qo-kregator-items`
+--
+
+CREATE TABLE IF NOT EXISTS `qo-kregator-items` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `id_feed` int(10) unsigned NOT NULL,
+ `titre` varchar(255) NOT NULL,
+ `date` datetime NOT NULL default '0000-00-00 00:00:00',
+ `auteur` varchar(255) NOT NULL,
+ `summary` varchar(255) NOT NULL,
+ `description` text NOT NULL,
+ `url` varchar(255) NOT NULL,
+ `seen` enum('y','n') NOT NULL default 'n',
+ `important` enum('y','n') NOT NULL default 'n',
+ `userID` int(11) NOT NULL,
+ KEY `id` (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='All items';
+
+-- ----------------------------------------------------------------------------
+-- Add qo-kregator to qo_modules
+-- ----------------------------------------------------------------------------
+INSERT INTO `qo_modules` (
+ `directory`,
+ `author`,
+ `version`,
+ `url`,
+ `description`,
+ `class_name`,
+ `module_type`,
+ `module_id`,
+ `menu_path`,
+ `launcher_icon_cls`,
+ `launcher_shortcut_icon_cls`,
+ `launcher_text`,
+ `launcher_tooltip`,
+ `active`,
+ `preload`
+) VALUES (
+ 'qo-kregator/',
+ 'Yannick Torrès',
+ '2.0',
+ 'http://qo-modules.tuxfamily.org/',
+ 'An Atom/RSS/Podcast viewer',
+ 'QoDesk.QoKregator',
+ 'qo-kregator',
+ 'qo-kregator',
+ 'StartMenu/Internet',
+ 'qo-kregator-icon',
+ 'qo-kregator-win-shortcut',
+ 'Qo-Kregator',
+ '<b>Qo-Kregator</b><br />An Atom/RSS/Podcast viewer',
+ 1,
+ 0
+);
+
+-- ----------------------------------------------------------------------------
+-- Add files to qo_modules_files & qo_modules_stylesheets
+-- ----------------------------------------------------------------------------
+insert into `qo_modules_files` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/', 'qo-kregator.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_stylesheets` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/', 'qo-kregator.css'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+-- ----------------------------------------------------------------------------
+-- Add dependencies to qo_modules_dependencies
+-- ----------------------------------------------------------------------------
+
+insert into `qo_modules_dependencies` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/ux/miframe/', 'miframe.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_dependencies` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/ux/FileUploadField/', 'FileUploadField.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_dependencies` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/ux/MultiselectItemSelector/', 'Multiselect.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_stylesheets` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/ux/MultiselectItemSelector/', 'Multiselect.css'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_dependencies` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/ux/spinner/', 'Spinner.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_dependencies` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/ux/spinner/', 'SpinnerStrategy.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+insert into `qo_modules_dependencies` (`qo_modules_id`, `directory`, `file`)
+select m.id, 'qo-kregator/locale/', 'Desk-Kregator-en.js'
+from (select id from qo_modules where module_id like 'QoKregator') m;
+
+-- ----------------------------------------------------------------------------
+-- Add modules to all group
+-- ----------------------------------------------------------------------------
+insert into `qo_groups_has_modules` (`qo_groups_id`, `qo_modules_id`, `active`)
+select g.id, m.id, 1
+from (select id from qo_groups) g
+ , (select id from qo_modules where module_id like 'QoKregator') m;
\ No newline at end of file
Added: trunk/qo-kregator/license_LGPL_v2.txt
===================================================================
--- trunk/qo-kregator/license_LGPL_v2.txt (rev 0)
+++ trunk/qo-kregator/license_LGPL_v2.txt 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,488 @@
+<pre>
+(c) 2007-2008, Yannick Torrès
+
+This program is distributed under the terms of the LGPL v2.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor
+ Boston, MA 02110-1301, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+</pre>
\ No newline at end of file
Added: trunk/qo-kregator/locale/Desk-Kregator-en.js
===================================================================
--- trunk/qo-kregator/locale/Desk-Kregator-en.js (rev 0)
+++ trunk/qo-kregator/locale/Desk-Kregator-en.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,215 @@
+var QoKregator = {
+
+ "DateDisplay": "Y-m-d, H:i",
+
+ // Launcher
+ "LauncherDescription":"A RSS/Atom/Podcast Viewer",
+
+ // Tab ContextMenu
+ "TabCtxCloseTab":"Close Tab",
+ "TabCtxCloseOtherTabs":"Close Other Tabs",
+
+ // Splash Window
+ "SplashLoadConf" : "Loading configuration...",
+ "SplashInit" : "Initialize...",
+
+ // Conf Window
+ "WinConfToolTip":"Modify configuration",
+ "WinConfTitle":"Configuration",
+
+ "WinConfTab0":"General",
+ "WinConfTab1":"Feed ToolBar",
+ "WinConfTab1Selected": "Selected",
+ "WinConfTab1Available": "Available",
+
+
+ "WinConfFieldSetTitle0":"Refresh feed (in minutes)",
+ "WinConfFieldSetLabel0":"Every ",
+
+ "WinConfFieldSetTitle1":"Delete old Items (in Days)",
+ "WinConfFieldSetLabel1":"Older than ",
+
+ "WinConfFieldSetTitle3":"Font size when reading article",
+
+ "WinConfFieldSetTitle4":"Open Desk-Kregator in...",
+
+ "WinConfFieldSetLabel41":"Full Screen",
+ "WinConfFieldSetLabel42":"Window",
+ "WinConfFieldSetLabel43":"Minimized",
+
+ "WinConfFieldSetTitle5":"Show the statusBar",
+
+ "WinConfSaveBtn":"Save",
+ "WinConfCancelBtn":"Cancel",
+
+ // Import Window
+ "WinImportTitle":"Import some feeds...",
+ "WinImportSaveBtn":"Save",
+ "WinImportCancelBtn":"Cancel",
+ "WinImportLibel1": "Name of Imported Folder ",
+ "WinImportDefaultValue":"Imported Folder",
+ "WinImportLibel2":"File ",
+ "WinImportInfo":"You must choose an Opml File",
+
+ // About window
+
+ "WinAboutTitle":"About",
+ "WinAboutTab0":"About",
+ "WinAboutTab1":"Credits",
+ "WinAboutTab2":"License",
+ "WinAboutClose":"Close",
+ "WinAboutTab1Credits0":"For its logo, its great ideas and assistance during development",
+ "WinAboutTab1Credits1":"For its ideas and its helps on debugging",
+ "WinAboutTab1Credits21":"For the great Spinner extension",
+ "WinAboutTab1Credits3":"For its great Javascript Framework !",
+
+ //FeedTree
+ "TreeColumn1":"Unseen", // Column is not resizable. So, be aware about translation length...
+ "TreeColumn2":"Total", // Column is not resizable. So, be aware about translation length...
+ "TreeRefresh": "Refresh feeds",
+ "TreeAddFeed": "Add feed",
+ "TreeAddNewFeed": "Add new feed",
+ "TreeAddFolder": "Add folder",
+ "TreeAddNewFolder": "Add new folder",
+ "TreeExpandCollapse": "Expand all / Collapse all",
+ "TreeTitle": "My feed",
+ "TreeImport": "Import some feeds...",
+ "TreeExport": "Export your feeds...",
+ "TreeFeedRootTitle": "All feeds",
+ "TreeFeedMarkAsRead": "Mark this feed as read",
+ "TreeFeedLoadFeed": "Refresh",
+ "TreeFeedOpenSite": "Open web site",
+ "TreeFeedMod": "Modify",
+ "TreeFeedDel": "Delete",
+ "TreeFolderMod": "Modify",
+ "TreeFolderDel": "Delete",
+ "TreeQtipNoItemUnseen": "No item unseen",
+ "TreeQtipItemUnseen": "new item unseen",
+ "TreeQtipItemUnseenS": "new items unseen",
+
+ // FeedGrid
+
+ "FeedGridFilterSearch": "Search...",
+ "FeedGridBoxSearchTitle":"Invalid Search",
+ "FeedGridBoxSearchContent":"You must enter a minimum of 2 characters",
+ "FeedGridFilterDateAllDate": "All date",
+ "FeedGridFilterDatePickDate": "Pick a date",
+ "FeedGridFilterAllItems": "All items",
+ "FeedGridFilterUnseenItems": "Unseen",
+ "FeedGridFilterImportantItems": "Important",
+ "FeedGridFilterTitleDisplay": "Items :",
+ "FeedGridItemOpenInTab": "Open in new tab",
+ "FeedGridItemOpenInWin": "Open in new window",
+ "FeedGridItemRemoveMarkImportant": "Remove mark 'Important'",
+ "FeedGridItemMarkAsImportant": "Important",
+ "FeedGridItemMarkAs": "Mark as",
+ "FeedGridItemMarkAsRead": "Seen",
+ "FeedGridItemMarkAsUnRead": "Unseen",
+ "FeedGridItemDel": "Delete",
+ "FeedGridTabTitle": "Articles",
+ "FeedGridHeaderItem": "Item",
+ "FeedGridHeaderFeed": "Feed",
+ "FeedGridHeaderDate": "Date",
+ "FeedGridLoadItems": "Please wait, loading items...",
+ "FeedGridPagingDisplay": "Displaying topics {0} - {1} of {2}",
+ "FeedGridPagingNoDisplay": "No feed to display",
+ "ReadingBtnTitle": "Reading Pane",
+ "ReadingBtnQtip": "Show, move or hide the Reading Pane",
+ "ReadingBtnBottom": "Bottom",
+ "ReadingBtnRight": "Right",
+ "ReadingBtnHide": "Hide",
+ "SummaryBtnTitle": "Summary",
+ "SummaryBtnText": "Show / Hide summary",
+ "ContextMenuBtnTooltipTitle": "ContextMenu",
+ "ContextMenuBtnTooltipText": "Show the same menu as right-click on an element",
+
+ // Preview Panel
+
+ "PreviewAutor": "Autor :",
+ "PreviewTitle": "Preview",
+ "previewLoadInNewPage": "Open in new window",
+
+ // Status Bar
+
+ "StatutDone": "Done.",
+ "StatutReady": "Ready.",
+ "StatutLoadFeed": "Loading feed :",
+ "StatutLoadFeedArticle": "Loading Article :",
+ "StatutLoadFolder": "Loading folder :",
+ "StatutUpdateFeed": "Fetch new items for : ",
+ "StatutUpdateFeedOk": "Refresh feed with success",
+ "StatutUpdateFeedNok": "Error while fetching new items for : ",
+
+ "StatutDelOk": "Delete with success.",
+ "StatutDelNok": "Error when delete.",
+
+ "StatutReorder": "Saving Reorganization...",
+ "StatutReorderOk": "Reorganization with success.",
+ "StatutReorderNok": "Error while Reorganization.",
+ "StatutMod": "Saving modification...",
+ "StatutModOk": "Modification with success.",
+ "StatutModNok": "Error while modification.",
+ "StatutDelFolder": "Delete folder: ",
+ "StatutDelItemNok": "Error while delete this item.",
+ "StatutDelFeed": "Delete feed: ",
+
+ "StatutModFeed": "Saving configuration in progress...",
+ "StatutModFeedOk": "Update configuration with success.",
+ "StatutModFeedNok": "Error while update configuration.",
+
+ "StatutSearchLoad": "Search in progress...",
+ "StatutItemDel": "Delete items...",
+ "StatutItemDelOk": "Delete items : Done.",
+ "StatutItemDelNok": "Error while deleted items !",
+ "StatutAddNewFolder": "Add folder in progress...",
+ "StatutAddNewFolderOk": "Add folder with success.",
+ "StatutAddNewFolderNok": "Error while adding folder.",
+
+ "StatutAddNewFeed": "Initialise new feed...",
+
+ "StatutAddNewFeedWait": "Initialise new feed...",
+ "StatutAddNewFeedWaitInProgress": "Please, wait...",
+
+ "StatutAddNewFeedOk": "New feed added with success.",
+ "StatutAddNewFeedNok": "Error while adding new feed. Server response : ",
+
+ "StatutCleanItemsWait":"Clean old feeds...",
+ "StatutCleanItemsOk":"Old items cleaned. Nb deleted : ",
+ "StatutCleanItemsNok":"Error while cleaning up old items. Server message : ",
+
+ "StatutConfWait" : "Modify configuration...",
+ "StatutConfOk" : "Modify configuration with success.",
+ "StatutConfNok" : "Error while modify configuration.",
+
+ "StatutImportWait" : "Import in progress...",
+ "StatutImportOk" : "Import with success.",
+ "StatutImportNok" : "Error while import. Server response : ",
+
+ // Confirm Dialogue
+
+ "BoxConfirmDelItemTitle": "Delete Item",
+ "BoxConfirmDelItemMessage": "Are you sur to delete this item ?",
+ "BoxConfirmDelItemsTitle": "Delete Items",
+ "BoxConfirmDelItemsMessage": "Are you sur to delete those items ?",
+
+ "BoxConfirmDelFeedTitle": "Delete feed",
+ "BoxConfirmDelFeedMessage": "Do you want to delete feed : ",
+ "BoxConfirmDelFolderTitle": "Delete folder",
+ "BoxConfirmDelFolderMessage": "Do you want to delete folder <b><i>{0}</i></b> and all sub items ?",
+ "BoxModFeedTitle": "Modify feed",
+ "BoxModFeedName": "Name ",
+ "BoxModFeedOption": "Option",
+ "BoxModFeedView": "Load the full site while reading articles",
+ "BoxModFeedSaveBtn": "Save",
+ "BoxModFeedCancelBtn": "Cancel",
+
+ "BoxAddFeedTitle": "Add new feed",
+ "BoxAddFeedUrl": "URL ",
+ "BoxAddFeedSaveBtn": "Save",
+ "BoxAddFeedCancelBtn": "Cancel",
+
+ "BoxAddFolderTitle": "Add Folder",
+ "BoxAddFolderName": "Name ",
+ "BoxAddFolderSaveBtn": "Save",
+ "BoxAddFolderCancelBtn": "Cancel"
+}
Added: trunk/qo-kregator/locale/Desk-Kregator-fr.js
===================================================================
--- trunk/qo-kregator/locale/Desk-Kregator-fr.js (rev 0)
+++ trunk/qo-kregator/locale/Desk-Kregator-fr.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,195 @@
+var DeskKregator = {
+
+ "DateDisplay": "d-m-Y, H:i",
+
+ // Launcher
+ "LauncherDescription":"Un lecteur RSS/Atom/Podcast",
+
+ // Tab ContextMenu
+ "TabCtxCloseTab":"Fermer l'onglet",
+ "TabCtxCloseOtherTabs":"Fermer les autres onglets",
+
+ // Splash Window
+ "SplashLoadConf" : "Chargement de la configuration...",
+ "SplashInit" : "Initialisation...",
+
+ // Conf Window
+
+ "WinConfToolTip":"Modification de la configuration",
+ "WinConfTitle":"Configuration",
+ "WinConfFieldSetTitle0":"Rafra\xEEchir les flux (en minutes)",
+ "WinConfFieldSetLabel0":"Tous les ",
+ "WinConfFieldSetTitle1":"Effacer les articles (en jours)",
+ "WinConfFieldSetLabel1":"Plus vieux que ",
+ "WinConfFieldSetTitle2":"Icone sur le bureau",
+ "WinConfFieldSetLabel2":"Afficher l'icone sur le bureau",
+ "WinConfSaveBtn":"Enregistrer",
+ "WinConfCancelBtn":"Annuler",
+
+ // Import Window
+
+ "WinImportTitle":"Importer des flux...",
+ "WinImportSaveBtn":"Enregistrer",
+ "WinImportCancelBtn":"Annuler",
+ "WinImportLibel1": "Nom du dossier import\xE9 ",
+ "WinImportDefaultValue":"Dossier import\xE9",
+ "WinImportLibel2":"Fichier ",
+ "WinImportInfo":"Vous devez choisir un fichier Opml",
+
+ // About window
+
+ "WinAboutTitle":"A propos",
+ "WinAboutTab0":"A propos",
+ "WinAboutTab1":"Remerciements",
+ "WinAboutTab2":"Licence",
+ "WinAboutClose":"Fermer",
+ "WinAboutTab1Credits0":"Pour son logo, ses superbes id\xE9es et son soutien pendant le d\xE9veloppement.",
+ "WinAboutTab1Credits1":"Pour ses id\xE9es et son aide dans le d\xE9boguage.",
+ "WinAboutTab1Credits21":"Pour sa superbe extension Spinner",
+ "WinAboutTab1Credits3":"Pour ce superbe FrameWork Javascript !",
+
+ //FeedTree
+ "TreeColumn1":"Non-Lu",
+ "TreeColumn2":"Total",
+ "TreeRefresh": "Rafra\xEEchir flux",
+ "TreeAddFeed": "Ajouter un flux",
+ "TreeAddNewFeed": "Ajouter un nouveau flux",
+ "TreeAddFolder": "Ajouter un dossier",
+ "TreeAddNewFolder": "Ajouter un nouveau dossier",
+ "TreeTitle": "Mes flux",
+ "TreeImport": "Importer des flux...",
+ "TreeExport": "Exporter vos flux...",
+ "TreeFeedRootTitle": "Tous les flux",
+ "TreeFeedMarkAsRead": "Marquer comme lu",
+ "TreeFeedLoadFeed": "Rafra\xEEchir ce flux",
+ "TreeFeedOpenSite": "Ouvrir le site",
+ "TreeFeedMod": "Modifier",
+ "TreeFeedDel": "Supprimer",
+ "TreeFolderMod": "Modifier",
+ "TreeFolderDel": "Supprimer",
+ "TreeQtipNoItemUnseen": "Pas d'\xE9l\xE9ment non lu",
+ "TreeQtipItemUnseen": "Nouvel \xE9l\xE9ment non lu",
+ "TreeQtipItemUnseenS": "Nouveaux \xE9l\xE9ments non lus",
+
+ // FeedGrid
+
+ "FeedGridFilterSearch": "Recherche...",
+ "FeedGridBoxSearchTitle":"Recherche invalide",
+ "FeedGridBoxSearchContent":"Vous devez entrer au moins 2 caract\xE8res.",
+ "FeedGridFilterAllItems": "Tous les \xE9l\xE9ments",
+ "FeedGridFilterUnseenItems": "Non lu",
+ "FeedGridFilterImportantItems": "Important",
+ "FeedGridFilterTitleDisplay": "El\xE9ments :",
+ "FeedGridItemOpenInTab": "Ouvrir dans nouvel onglet",
+ "FeedGridItemOpenInWin": "Ouvrir dans nouvelle fen\xEAtre",
+ "FeedGridItemRemoveMarkImportant": "Supprimer le marquage 'Important'",
+ "FeedGridItemMarkAsImportant": "Important",
+ "FeedGridItemMarkAs": "Marquer comme",
+ "FeedGridItemMarkAsRead": "lu",
+ "FeedGridItemMarkAsUnRead": "non lu",
+ "FeedGridItemDel": "Supprimer cet \xE9l\xE9ment",
+ "FeedGridTabTitle": "Articles",
+ "FeedGridHeaderItem": "El\xE9ment",
+ "FeedGridHeaderFeed": "Flux",
+ "FeedGridHeaderDate": "Date",
+ "FeedGridLoadItems": "Veuillez patienter, chargement en cours...",
+ "FeedGridPagingDisplay": "Affichage des sujets {0} - {1} \xE0 {2}",
+ "FeedGridPagingNoDisplay": "Pas de flux \xE0 afficher",
+ "ReadingBtnTitle": "Panneau de pr\xE9visualisation",
+ "ReadingBtnQtip": "Montrer, d\xE9placer ou cacher le panneau de pr\xE9visualisation",
+ "ReadingBtnBottom": "En bas",
+ "ReadingBtnRight": "A droite",
+ "ReadingBtnHide": "Cach\xE9",
+ "SummaryBtnTitle": "R\xE9sum\xE9",
+ "SummaryBtnText": "Afficher/Cacher le r\xE9sum\xE9",
+
+ // Preview Panel
+
+ "PreviewAutor": "Auteur :",
+ "PreviewTitle": "Previsualisation",
+ "previewLoadInNewPage": "Ouvrir dans une nouvelle fen\xEAtre",
+
+ // Status Bar
+
+ "StatutDone": "Fait.",
+ "StatutReady": "Pr\xEAt.",
+ "StatutLoadFeed": "Chargement flux :",
+ "StatutLoadFeedArticle": "Chargement article :",
+ "StatutLoadFolder": "Chargement dossier :",
+ "StatutUpdateFeed": "R\xE9cup\xE9ration des informations pour : ",
+ "StatutUpdateFeedOk": "Flux rafra\xEEchi avec succ\xE8s",
+ "StatutUpdateFeedNok": "Erreur pendant la r\xE9cup\xE9ration des informations : ",
+
+ "StatutDelOk": "Supprim\xE9 avec succ\xE8s.",
+ "StatutDelNok": "Erreur pendant la suppression.",
+
+ "StatutReorder": "Enregistrement de la r\xE9organisation...",
+ "StatutReorderOk": "R\xE9organis\xE9 avec succ\xE8s.",
+ "StatutReorderNok": "Erreur pendant la r\xE9organisation.",
+ "StatutMod": "Enregistrement des modifications...",
+ "StatutModOk": "Modifi\xE9 avec succ\xE8s.",
+ "StatutModNok": "Erreur pendant la modification.",
+ "StatutDelFolder": "Supprimer le dossier : ",
+ "StatutDelItemNok": "Erreur pendant la suppression de l'\xE9l\xE9ment.",
+ "StatutDelFeed": "Supprimer le flux : ",
+
+ "StatutModFeed": "Enregistrement de la configuration en cours...",
+ "StatutModFeedOk": "Mise \xE0 jour de la configuration avec succ\xE8s.",
+ "StatutModFeedNok": "Erreur pendant la mise \xE0 jour.",
+
+ "StatutSearchLoad": "Recherche en cours...",
+ "StatutItemDel": "Suppression des \xE9l\xE9ments...",
+ "StatutItemDelOk": "Suppression des \xE9l\xE9ments : Fait.",
+ "StatutItemDelNok": "Erreur pendant la suppression des \xE9l\xE9ments !",
+ "StatutAddNewFolder": "Ajout du dossier en cours...",
+ "StatutAddNewFolderOk": "Dossier ajout\xE9 avec succ\xE8s.",
+ "StatutAddNewFolderNok": "Erreur pendant l'ajout du dossier.",
+
+ "StatutAddNewFeed": "Initialisation du flux...",
+
+ "StatutAddNewFeedWait": "Initialisation du flux...",
+ "StatutAddNewFeedWaitInProgress": "Veuillez patienter...",
+
+ "StatutAddNewFeedOk": "Nouveau flux ajout\xE9 avec succ\xE8s.",
+ "StatutAddNewFeedNok": "Erreur pendant l'ajout du flux. R\xE9ponse du serveur : ",
+
+ "StatutCleanItemsWait":"Clean old feeds...",
+ "StatutCleanItemsOk":"Old items cleaned. Nb deleted : ",
+ "StatutCleanItemsNok":"Error while cleaning up old items. Server message : ",
+
+ "StatutConfWait" : "Modification de la configuration...",
+ "StatutConfOk" : "Modification de la configuration avec succ\xE8s.",
+ "StatutConfNok" : "Erreur lors de la modification de la configuration.",
+
+ "StatutImportWait" : "Importation en cours...",
+ "StatutImportOk" : "Importation avec succ\xE8s.",
+ "StatutImportNok" : "Erreur lors de l'importation. R\xE9ponse du serveur : ",
+
+ // Confirm Dialogue
+
+ "BoxConfirmDelItemTitle": "Effacer un article",
+ "BoxConfirmDelItemMessage": "\xCAtes-vous s\xFBr de vouloir effacer cet article ?",
+ "BoxConfirmDelItemsTitle": "Effacer des articles",
+ "BoxConfirmDelItemsMessage": "\xCAtes-vous s\xFBr de vouloir effacer ces articles ?",
+
+ "BoxConfirmDelFeedTitle": "Supprimer flux",
+ "BoxConfirmDelFeedMessage": "Voulez-vous supprimer le flux : ",
+ "BoxConfirmDelFolderTitle": "Supprimer dossier",
+ "BoxConfirmDelFolderMessage": "Voulez-vous supprimer le dossier <b><i>{0}</i></b> et les sous-dossiers ?",
+ "BoxModFeedTitle": "Modifier flux",
+ "BoxModFeedName": "Nom ",
+ "BoxModFeedOption": "Option",
+ "BoxModFeedView": "Chargement complet du site dans le panneau de pr\xE9visualisation",
+ "BoxModFeedSaveBtn": "Enregistrer",
+ "BoxModFeedCancelBtn": "Annuler",
+
+ "BoxAddFeedTitle": "Ajouter un nouveau flux",
+ "BoxAddFeedUrl": "URL ",
+ "BoxAddFeedSaveBtn": "Enregistrer",
+ "BoxAddFeedCancelBtn": "Annuler",
+
+ "BoxAddFolderTitle": "Ajouter un nouveau dossier",
+ "BoxAddFolderName": "Nom ",
+ "BoxAddFolderSaveBtn": "Enregistrer",
+ "BoxAddFolderCancelBtn": "Annuler"
+}
Added: trunk/qo-kregator/locale/Desk-Kregator-pt_br.js
===================================================================
--- trunk/qo-kregator/locale/Desk-Kregator-pt_br.js (rev 0)
+++ trunk/qo-kregator/locale/Desk-Kregator-pt_br.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,190 @@
+var DeskKregator = {
+
+ "DateDisplay": "d-m-Y, H:i",
+
+ // Launcher
+ "LauncherDescription":"A RSS/Atom/Podcast Viewer",
+
+ // Tab ContextMenu
+ "TabCtxCloseTab":"Close Tab",
+ "TabCtxCloseOtherTabs":"Close Other Tabs",
+
+ // Splash Window
+ "SplashLoadConf" : "Loading configuration...",
+ "SplashInit" : "Initialize...",
+
+ // Conf Window
+
+ "WinConfToolTip":"Modify configuration",
+ "WinConfTitle":"Configuration",
+ "WinConfFieldSetTitle0":"Refresh feed (in minutes)",
+ "WinConfFieldSetLabel0":"Every ",
+ "WinConfFieldSetTitle1":"Delete old Items (in Days)",
+ "WinConfFieldSetLabel1":"Older than ",
+ "WinConfFieldSetTitle2":"Desktop Icon",
+ "WinConfFieldSetLabel2":"Show icon on Desktop",
+ "WinConfSaveBtn":"Save",
+ "WinConfCancelBtn":"Cancel",
+
+ // Import Window
+
+ "WinImportTitle":"Import some feeds...",
+ "WinImportSaveBtn":"Save",
+ "WinImportCancelBtn":"Cancel",
+ "WinImportLibel1": "Name of Imported Folder ",
+ "WinImportDefaultValue":"Imported Folder",
+ "WinImportLibel2":"File ",
+ "WinImportInfo":"You must choose an Opml File",
+
+ // About window
+
+ "WinAboutTitle":"About",
+ "WinAboutTab0":"About",
+ "WinAboutTab1":"Credits",
+ "WinAboutTab2":"License",
+ "WinAboutClose":"Close",
+ "WinAboutTab1Credits0":"For its logo, its great ideas and assistance during development",
+ "WinAboutTab1Credits1":"For its ideas and its helps on debugging",
+ "WinAboutTab1Credits21":"For the great Spinner extension",
+ "WinAboutTab1Credits3":"For its great Javascript Framework !",
+
+ //FeedTree
+ "TreeColumn1":"Unseen", // Column is not resizable. So, be aware about translation length...
+ "TreeColumn2":"Total", // Column is not resizable. So, be aware about translation length...
+ "TreeRefresh": "Atualizar feeds",
+ "TreeAddFeed": "Novo feed",
+ "TreeAddNewFeed": "Adicionar novo feed",
+ "TreeAddFolder": "Criar pasta",
+ "TreeAddNewFolder": "Criar nova pasta",
+ "TreeTitle": "Meus feed",
+ "TreeImport": "Import some feeds...",
+ "TreeExport": "Export your feeds...",
+ "TreeFeedRootTitle": "Todos feeds",
+ "TreeFeedMarkAsRead": "Marcar como lida",
+ "TreeFeedLoadFeed": "Atualizar este feed",
+ "TreeFeedOpenSite": "Abrir o site",
+ "TreeFeedMod": "Modificar este feed",
+ "TreeFeedDel": "Excluir este feed",
+ "TreeFolderMod": "Modificar esta pasta",
+ "TreeFolderDel": "Excluir esta pasta",
+ "TreeQtipNoItemUnseen": "N\xE3o existem itens n\xE3o lidos",
+ "TreeQtipItemUnseen": "Novo item n\xE3o lido",
+ "TreeQtipItemUnseenS": "Novos itens n\xE3o lidos",
+
+ // FeedGrid
+
+ "FeedGridFilterSearch": "Procurar :",
+ "FeedGridBoxSearchTitle":"Invalid Search",
+ "FeedGridBoxSearchContent":"You must enter a minimum of 2 characters",
+ "FeedGridFilterAllItems": "Todos os itens",
+ "FeedGridFilterUnseenItems": "N\xE3o lidos",
+ "FeedGridFilterImportantItems": "Importante",
+ "FeedGridFilterTitleDisplay": "Items :",
+ "FeedGridItemOpenInTab": "Abrir em nova tab",
+ "FeedGridItemOpenInWin": "Abrir em nova janela",
+ "FeedGridItemRemoveMarkImportant": "Remover sinal de 'Importante'",
+ "FeedGridItemMarkAsImportant": "Importante",
+ "FeedGridItemMarkAs": "Sinalizar como",
+ "FeedGridItemMarkAsRead": "Lida",
+ "FeedGridItemMarkAsUnRead": "N\xE3o lida",
+ "FeedGridItemDel": "Excluir este item",
+ "FeedGridTabTitle": "Artigos",
+ "FeedGridHeaderItem": "Item",
+ "FeedGridHeaderFeed": "Feed",
+ "FeedGridHeaderDate": "Data",
+ "FeedGridLoadItems": "Por favor aguarde,, carregando items...",
+ "FeedGridPagingDisplay": "Mostrando topicos {0} - {1} of {2}",
+ "FeedGridPagingNoDisplay": "Nenhum feed para mostrar",
+ "ReadingBtnTitle": "Painel de leitura",
+ "ReadingBtnQtip": "Mostrar, movee ou ocultar o painel de leitura",
+ "ReadingBtnBottom": "Superior",
+ "ReadingBtnRight": "Direita",
+ "ReadingBtnHide": "Ocultar",
+ "SummaryBtnTitle": "Summary",
+ "SummaryBtnText": "Show / Hide summary",
+
+ // Preview Panel
+
+ "PreviewAutor": "Autor :",
+ "PreviewTitle": "Visualizar",
+ "previewLoadInNewPage": "Abrir em nova janela",
+
+ // Status Bar
+
+ "StatutDone": "Pronto.",
+ "StatutReady": "Preparado.",
+ "StatutLoadFeed": "Carregando feed :",
+ "StatutLoadFeedArticle": "Carregando Artigp :",
+ "StatutLoadFolder": "Carregando pasta :",
+ "StatutUpdateFeed": "Buscar novos itens de : ",
+ "StatutUpdateFeedOk": "feed atualizados com sucesso",
+ "StatutUpdateFeedNok": "Erro ao buscar novos itens de : ",
+
+ "StatutDelOk": "Excluido com successo.",
+ "StatutDelNok": "Erro ao excluir.",
+
+ "StatutReorder": "Salvando reorganiza\xE7\xE3o...",
+ "StatutReorderOk": "Reorganizado com sucesso.",
+ "StatutReorderNok": "Erro ao reorganizar.",
+ "StatutMod": "Salvando modifica\xE7\xF5es...",
+ "StatutModOk": "Modificado com sucesso.",
+ "StatutModNok": "erro no modifica\xE7\xE3o.",
+ "StatutDelFolder": "Excluir pasta: ",
+ "StatutDelItemNok": "Erro ao excluir o item.",
+ "StatutDelFeed": "Feed excluido : ",
+
+ "StatutModFeed": "Salvando configura\xE7\xE3o em progresso...",
+ "StatutModFeedOk": "Configura\xE7\xE3o Atualizada com sucesso.",
+ "StatutModFeedNok": "Erro na atualiza\xE7\xE3o da configura\xE7\xE3o.",
+
+ "StatutSearchLoad": "Pesquisa em andamento...",
+ "StatutItemDel": "Itens excluidos...",
+ "StatutItemDelOk": "Itens excluidos : Pronto.",
+ "StatutItemDelNok": "Erro ao excluir itens !",
+ "StatutAddNewFolder": "Cria\xE7\xE3o da pasta em andamento...",
+ "StatutAddNewFolderOk": "Pasta criada com sucesso.",
+ "StatutAddNewFolderNok": "Erro ao criar a pasta.",
+
+ "StatutAddNewFeed": "Inicializando novo feed...",
+
+ "StatutAddNewFeedWait": "Novo feed inicializado...",
+ "StatutAddNewFeedWaitInProgress": "Por favor, aguarde...",
+
+ "StatutAddNewFeedOk": "Novo feed criado com successo.",
+ "StatutAddNewFeedNok": "Erro ao criar novo feed. Resposta do servidor : ",
+
+ "StatutCleanItemsWait":"Clean old feeds...",
+ "StatutCleanItemsOk":"Old items cleaned. Nb deleted : ",
+ "StatutCleanItemsNok":"Error while cleaning up old items. Server message : ",
+
+ "StatutConfWait" : "Modify configuration...",
+ "StatutConfOk" : "Modify configuration with success.",
+ "StatutConfNok" : "Error while modify configuration.",
+
+ "StatutImportWait" : "Import in progress...",
+ "StatutImportOk" : "Import with success.",
+ "StatutImportNok" : "Error while import. Server response : ",
+
+ // Confirm Dialogue
+
+ "BoxConfirmDelFeedTitle": "Excluir feed",
+ "BoxConfirmDelFeedMessage": "Deseja excluir este feed : ",
+ "BoxConfirmDelFolderTitle": "Excluir pasta",
+ "BoxConfirmDelFolderMessage": "Deseja excluir a pasta <b><i>{0}</i></b> e todos os subitens ?",
+ "BoxModFeedTitle": "Modificar feed",
+ "BoxModFeedName": "Nome ",
+ "BoxModFeedOption": "Op\xE7\xF5es",
+ "BoxModFeedView": "Carregue o site completo ao ler artigos",
+ "BoxModFeedSaveBtn": "Salvar",
+ "BoxModFeedCancelBtn": "Cancelar",
+
+ "BoxAddFeedTitle": "Novo feed",
+ "BoxAddFeedUrl": "URL ",
+ "BoxAddFeedSaveBtn": "Salvar",
+ "BoxAddFeedCancelBtn": "Cancelar",
+
+ "BoxAddFolderTitle": "Nova pasta",
+ "BoxAddFolderName": "Nome ",
+ "BoxAddFolderSaveBtn": "Salvar",
+ "BoxAddFolderCancelBtn": "Cancelar"
+}
Added: trunk/qo-kregator/locale/Desk-Kregator-vn.js
===================================================================
--- trunk/qo-kregator/locale/Desk-Kregator-vn.js (rev 0)
+++ trunk/qo-kregator/locale/Desk-Kregator-vn.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,188 @@
+var DeskKregator = {
+
+ "DateDisplay": "d-m-Y, H:i",
+
+ // Launcher
+ "LauncherDescription":"A RSS/Atom/Podcast Viewer",
+
+ // Splash Window
+ "SplashLoadConf" : "Đang cấu hình...",
+ "SplashInit" : "Đang khởi tạo...",
+
+ // Conf Window
+
+ "WinConfToolTip":"Thay đổi cấu hình",
+ "WinConfTitle":"Cấu hình",
+ "WinConfFieldSetTitle0":"Tải lại nội dung (theo phút)",
+ "WinConfFieldSetLabel0":"Mỗi ",
+ "WinConfFieldSetTitle1":"Xoá tin cũ (theo ngày)",
+ "WinConfFieldSetLabel1":"Cũ hơn ",
+ "WinConfFieldSetTitle2":"Hiển thị",
+ "WinConfFieldSetLabel2":"Hiển thị icon trên màn hình desktop",
+ "WinConfSaveBtn":"Lưu",
+ "WinConfCancelBtn":"Thoát",
+
+ // Import Window
+
+ "WinImportTitle":"Import nguồn tin mới...",
+ "WinImportSaveBtn":"Lưu",
+ "WinImportCancelBtn":"Thoát",
+ "WinImportLibel1": "Tên thư mục import ",
+ "WinImportDefaultValue":"Thư mục được import",
+ "WinImportLibel2":"File ",
+ "WinImportInfo":"Bạn phải chọn file có định dạng Opml",
+
+ // About window
+
+ "WinAboutTitle":"Giới thiệu",
+ "WinAboutTab0":"Giới thiệu",
+ "WinAboutTab1":"Sáng lập",
+ "WinAboutTab2":"Giấy phép sử dụng",
+ "WinAboutClose":"Đóng",
+ "WinAboutTab1Credits0":"Thiết kế logo, cung cấp ý tưởng và trợ giúp trong quá trình phát triển",
+ "WinAboutTab1Credits1":"Hỗ trợ ý tưởng và debug",
+ "WinAboutTab1Credits2":"Cung cấp gói icon",
+ "WinAboutTab1Credits21":"Spinner extension",
+ "WinAboutTab1Credits3":"Javascript Framework",
+
+ //FeedTree
+ "TreeColumn1":"Chưa xem", // Column is not resizable. So, be aware about translation length...
+ "TreeColumn2":"Tổng", // Column is not resizable. So, be aware about translation length...
+ "TreeRefresh": "Tải lại tin",
+ "TreeAddFeed": "Thêm nguồn tin",
+ "TreeAddNewFeed": "Thêm nguồn tin mới",
+ "TreeAddFolder": "Tạo thư mục",
+ "TreeAddNewFolder": "Tạo thư mục mới",
+ "TreeTitle": "Tin của tôi",
+ "TreeImport": "Import nguồn tin...",
+ "TreeExport": "Export nguồn tin của bạn...",
+ "TreeFeedRootTitle": "Tất cả nguồn tin",
+ "TreeFeedMarkAsRead": "Đánh dấu đã đọc",
+ "TreeFeedLoadFeed": "Tải lại",
+ "TreeFeedOpenSite": "Mở website",
+ "TreeFeedMod": "Sửa",
+ "TreeFeedDel": "Xoá",
+ "TreeFolderMod": "Sửa",
+ "TreeFolderDel": "Xoá",
+ "TreeQtipNoItemUnseen": "Không có tin chưa đọc",
+ "TreeQtipItemUnseen": "Tin mới chưa đọc",
+ "TreeQtipItemUnseenS": "Tin mới chưa đọc",
+
+ // FeedGrid
+
+ "FeedGridFilterEtat": "Trạng thái : ",
+ "FeedGridFilterSearch": "Tim kiem...",
+ "FeedGridBoxSearchTitle":"Không thể tìm kiếm",
+ "FeedGridBoxSearchContent":"Bạn phải nhập ít nhất 2 từ",
+ "FeedGridFilterAllItems": "Tat ca cac tin",
+ "FeedGridFilterUnseenItems": "Chưa đọc",
+ "FeedGridFilterImportantItems": "Quan trọng",
+ "FeedGridFilterTitleDisplay": "Tin tức :",
+ "FeedGridItemOpenInTab": "Mở sang một tab mới",
+ "FeedGridItemOpenInWin": "Mở sang một cửa sổ mới",
+ "FeedGridItemRemoveMarkImportant": "Xoá đánh dấu 'Quan trọng'",
+ "FeedGridItemMarkAsImportant": "Quan trọng",
+ "FeedGridItemMarkAs": "Đánh dấu thành",
+ "FeedGridItemMarkAsRead": "Đã đọc",
+ "FeedGridItemMarkAsUnRead": "Chưa đọc",
+ "FeedGridItemDel": "Xoá tin này",
+ "FeedGridTabTitle": "Các bài viết",
+ "FeedGridHeaderItem": "Tin",
+ "FeedGridHeaderFeed": "Feed",
+ "FeedGridHeaderDate": "Ngày",
+ "FeedGridLoadItems": "Xin chờ, đang tải tin...",
+ "FeedGridPagingDisplay": "Hiển chị chủ đề {0} - {1} của tổng số {2}",
+ "FeedGridPagingNoDisplay": "Không có tin để hiển thị",
+ "ReadingBtnTitle": "Thay đổi khung đọc tin",
+ "ReadingBtnQtip": "Hiển thị, di chuyển hoặc dấu vùng đọc tin",
+ "ReadingBtnBottom": "Bên dưới",
+ "ReadingBtnRight": "Bên phải",
+ "ReadingBtnHide": "Dấu",
+ "SummaryBtnTitle": "Summary",
+ "SummaryBtnText": "Show / Hide summary",
+
+ // Preview Panel
+
+ "PreviewAutor": "Người viết :",
+ "PreviewTitle": "Xem trước",
+ "previewLoadInNewPage": "Mở sang một cửa sổ mới",
+
+ // Status Bar
+
+ "StatutDone": "Hoàn tất.",
+ "StatutReady": "Sẵn sàng.",
+ "StatutLoadFeed": "Đang tải tin :",
+ "StatutLoadFeedArticle": "Đang tải bài viết :",
+ "StatutLoadFolder": "Đang tải thư mục :",
+ "StatutUpdateFeed": "Lấy tin mới : ",
+ "StatutUpdateFeedOk": "Tải lại tin",
+ "StatutUpdateFeedNok": "Lỗi khi tải tin mới cho mục : ",
+
+ "StatutDelOk": "Xoá thành công.",
+ "StatutDelNok": "Lỗi trong khi xoá.",
+
+ "StatutReorder": "Đang lưu...",
+ "StatutReorderOk": "Tổ chức lại thành công.",
+ "StatutReorderNok": "Lỗi khi tổ chức lại.",
+ "StatutMod": "Đang lưu thay đổi...",
+ "StatutModOk": "Thay đổi thành công.",
+ "StatutModNok": "Lỗi khi thay đổi.",
+ "StatutDelFolder": "Xoá thư mục: ",
+ "StatutDelItemNok": "Lỗi khi xoá thư mục.",
+ "StatutDelFeed": "Xoá nguồn tin: ",
+
+ "StatutModFeed": "Đang lưu cấu hình...",
+ "StatutModFeedOk": "Cập nhật cấu hình thành công.",
+ "StatutModFeedNok": "Lỗi khi lưu cấu hình.",
+
+ "StatutSearchLoad": "Đang tìm kiếm...",
+ "StatutItemDel": "Xoá tin...",
+ "StatutItemDelOk": "Xoá tin : Hoà tất.",
+ "StatutItemDelNok": "Lỗi khi xoá tin !",
+ "StatutAddNewFolder": "Đang tạo thư mục...",
+ "StatutAddNewFolderOk": "Tạo thư mục thành công.",
+ "StatutAddNewFolderNok": "Lỗi trong khi tạo thư mục.",
+
+ "StatutAddNewFeed": "Đang khởi tạo nguồn tin mới...",
+
+ "StatutAddNewFeedWait": "Đang khởi tạo...",
+ "StatutAddNewFeedWaitInProgress": "Xin chờ...",
+
+ "StatutAddNewFeedOk": "Tạo nguồn tin thành công.",
+ "StatutAddNewFeedNok": "Lỗi khi khởi tạo nguồn tin mới. Máy chủ : ",
+
+ "StatutCleanItemsWait":"Xoá nguồn tin cũ...",
+ "StatutCleanItemsOk":"Nguồn tin cũ đã được xoá : ",
+ "StatutCleanItemsNok":"Lỗi trong khi xoá nguồn tin cũ. Máy chủ : ",
+
+ "StatutConfWait" : "Thay đổi cấu hình...",
+ "StatutConfOk" : "Thay đổi cấu hình thành công.",
+ "StatutConfNok" : "Lỗi khi thay đổi cấu hình.",
+
+ "StatutImportWait" : "Đang import...",
+ "StatutImportOk" : "Import thành công.",
+ "StatutImportNok" : "Lỗi khi import. Máy chủ : ",
+
+ // Confirm Dialogue
+
+ "BoxConfirmDelFeedTitle": "Xoá nguồn tin",
+ "BoxConfirmDelFeedMessage": "Bạn có muốn xoá nguồn tin : ",
+ "BoxConfirmDelFolderTitle": "Xoá thư mục",
+ "BoxConfirmDelFolderMessage": "Bạn có muốn xoá thư mục <b><i>{0}</i></b> và tất cả nguồn tin bên trong nó ?",
+ "BoxModFeedTitle": "Thay đổi nguồn tin",
+ "BoxModFeedName": "Tên ",
+ "BoxModFeedOption": "Lựa chọn",
+ "BoxModFeedView": "Tải toàn bộ trang khi đọc tin",
+ "BoxModFeedSaveBtn": "Lưu",
+ "BoxModFeedCancelBtn": "Thoát",
+
+ "BoxAddFeedTitle": "Tạo nguồn tin mới",
+ "BoxAddFeedUrl": "Địa chỉ ",
+ "BoxAddFeedSaveBtn": "Lưu",
+ "BoxAddFeedCancelBtn": "Thoát",
+
+ "BoxAddFolderTitle": "Tạo thư mục",
+ "BoxAddFolderName": "Tên ",
+ "BoxAddFolderSaveBtn": "Lưu",
+ "BoxAddFolderCancelBtn": "Thoát"
+}
Added: trunk/qo-kregator/php/cache/memberID_3/b3b45881d4751326bcdd9ce5e1595a4b2e6009dc.spc
===================================================================
--- trunk/qo-kregator/php/cache/memberID_3/b3b45881d4751326bcdd9ce5e1595a4b2e6009dc.spc (rev 0)
+++ trunk/qo-kregator/php/cache/memberID_3/b3b45881d4751326bcdd9ce5e1595a4b2e6009dc.spc 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,654 @@
+a:3:{s:5:"child";a:1:{s:0:"";a:1:{s:3:"rss";a:1:{i:0;a:6:{s:4:"data";s:0:"";s:7:"attribs";a:1:{s:0:"";a:1:{s:7:"version";s:3:"2.0";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:1:{s:0:"";a:1:{s:7:"channel";a:1:{i:0;a:6:{s:4:"data";s:71:"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:1:{s:0:"";a:9:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:13:"Ext JS Forums";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:22:"http://extjs.com/forum";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:13:"Ext JS Forums";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"language";a:1:{i:0;a:5:{s:4:"data";s:2:"en";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:13:"lastBuildDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 19:13:27 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:9:"generator";a:1:{i:0;a:5:{s:4:"data";s:9:"vBulletin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:3:"ttl";a:1:{i:0;a:5:{s:4:"data";s:2:"60";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:5:"image";a:1:{i:0;a:6:{s:4:"data";s:15:"
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:1:{s:0:"";a:3:{s:3:"url";a:1:{i:0;a:5:{s:4:"data";s:42:"http://extjs.com/forum/images/misc/rss.jpg";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:13:"Ext JS Forums";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:22:"http://extjs.com/forum";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}}s:4:"item";a:15:{i:0;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:32:"Rails authenticity token problem";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51741&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 18:52:17 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:151:"Hello - 1st post!
+I did a search on this issue and only found this (http://extjs.com/forum/showthread.php?t=40891) post.
+I'm just starting to get my...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51741";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:11634:"<div>Hello - 1st post!<br />
+I did a search on this issue and only found <a href="http://extjs.com/forum/showthread.php?t=40891" target="_blank">this</a> post.<br />
+I'm just starting to get my head around Ext with Rails, with some background with JSON in the past its slowly making sense.<br />
+<br />
+My issue is with an EditorGridPanel, based on the Ext Scaffold output for the normal GridPanel.<br />
+I've been trying to adapt this into a live-editing thing. I think I'm close, apart from the auth token problem. I've tried to copy and adapt from the Delete button code from the generated EditorGrid scaffolding (Ext Scaffold). I'm appending the auth token to the end of the json string. <br />
+<br />
+If anyone has any experience with this would be great to see where I'm going wrong, or if I'm totally on the wrong track! <br />
+<br />
+Thx<br />
+<br />
+My code so far:<br />
+<br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left"> def ext_editor_grid_for(object_name, options = {})<br />
+ element = options[:element]<br />
+ datastore = options[:datastore] || "#{object_name.to_s.demodulize.underscore}_datastore"<br />
+ offset = params[:start] || (controller.send(:previous_pagination_state, object_name))[:offset] || 0<br />
+ page_size = options[:page_size] || 5<br />
+ column_model = options[:column_model] || "#{object_name.to_s.demodulize.underscore}_column_model"<br />
+ collection_path_method = "#{object_name.to_s.tableize.tr('/','_')}_path"<br />
+ collection_path = send collection_path_method<br />
+ new_member_path = send "new_#{object_name.to_s.underscore.tr('/','_')}_path"<br />
+ panel_title = options[:title] || "Listing #{object_name.to_s.demodulize.titleize.pluralize}"<br />
+<br />
+ javascript_tag <<-_JS<br />
+ <br />
+ Ext.onReady(function(){<br />
+ <br />
+ Ext.state.Manager.setProvider(new Ext.state.CookieProvider());<br />
+ Ext.QuickTips.init();<br />
+<br />
+ var ds = #{datastore};<br />
+<br />
+ var cm = #{column_model};<br />
+ cm.defaultSortable = true;<br />
+ <br />
+ var gridForm = new Ext.FormPanel({});<br />
+<br />
+ // create the grid<br />
+ var grid = new Ext.grid.EditorGridPanel({<br />
+ ds: ds,<br />
+ cm: cm,<br />
+ sm: new Ext.grid.CellSelectionModel({singleSelect:true}),<br />
+ renderTo: '#{element}',<br />
+ title: '#{panel_title}',<br />
+ width: #{options[:width] || 540},<br />
+ //height: #{options[:height] || 208},<br />
+ stripeRows: #{options[:stripe_rows] == false ? 'false' : 'true'},<br />
+ viewConfig: {<br />
+ forceFit:#{options[:force_fit] == false ? 'false' : 'true'}<br />
+ },<br />
+<br />
+ clicksToEdit:1, <br />
+ frame:false,<br />
+ autoHeight:true, <br />
+<br />
+ // inline toolbars<br />
+ <br />
+ tbar:[ ], <br />
+ <br />
+ bbar: new Ext.PagingToolbar({<br />
+ pageSize: #{page_size},<br />
+ store: ds,<br />
+ displayInfo: true,<br />
+ displayMsg: 'Record {0} - {1} of {2}',<br />
+ emptyMsg: "No records found"<br />
+ }),<br />
+ plugins:[new Ext.ux.grid.Search({<br />
+ position:'top'<br />
+ })]<br />
+ <br />
+ });<br />
+<br />
+ // show record on double-click<br />
+ <br />
+ grid.on("rowdblclick", function(grid, row, e) {<br />
+ grid.suspendEvents();<br />
+ window.location.href = '#{collection_path}/' + grid.getStore().getAt(row).data.id;<br />
+ });<br />
+ <br />
+ grid.on('afteredit', updateDB);<br />
+<br />
+ <br />
+ function updateDB(oGrid_event){<br />
+ alert("edited"); <br />
+ ds.each(function() { <br />
+ var json_params = Ext.encode(this.data); <br />
+ var auth_token = '#{", \"#{request_forgery_protection_token}\": \"#{form_authenticity_token}\"" if protect_against_forgery?}';<br />
+ var json_final = json_params + auth_token<br />
+ alert( json_final );<br />
+ Ext.Ajax.request({ <br />
+ url: '/#{object_name.to_s.demodulize.pluralize.underscore}/update', <br />
+ //success: function() {console.debug(json_params)},<br />
+ success: function(response, options){ ds.load(); },<br />
+ //failure: function() {console.debug('failure')},<br />
+ failure: function(response, options){ alert('Edit operation failed.'); }, <br />
+ callback: function(o,s,r) {$('#response').html(r.responseText)},<br />
+ params: json_final<br />
+ });<br />
+ <br />
+ });<br />
+<br />
+ <br />
+<br />
+ <br />
+<br />
+ }<br />
+ <br />
+<br />
+ //render form<br />
+<br />
+ //gridForm.render('business-requirement-grid'); <br />
+ <br />
+ <br />
+ ds.load({params: {start: #{offset}, limit:#{page_size}}});<br />
+ });<br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ _JS<br />
+ end</code><hr />
+</div></div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:15:"adam_codegarden";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:1;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:20:"Make homepage button";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51740&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 18:49:03 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:150:"I would like to create a button that when clicked will prompt the user to set the site being viewed to their homepage! I am trying to do it ext but...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51740";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:847:"<div>I would like to create a button that when clicked will prompt the user to set the site being viewed to their homepage! I am trying to do it ext but have a slight gap in my understanding how it would work...<br />
+ <br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left">...<br />
+{<br />
+ text: 'Make homepage',<br />
+ tooltip: 'Make this your homepage',<br />
+ iconCls: 'myicon',<br />
+ handler: makeHomepage<br />
+}<br />
+...<br />
+ <br />
+function makeHomepage()<br />
+{<br />
+ // TODO fix<br />
+ this.setHomePage('http://www.blah.com');<br />
+}</code><hr />
+</div>This doesn't work... Can someone suggest the code for makeHomepage?</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:5:"alexp";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:2;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:20:"Tree Loader Override";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51739&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 18:38:21 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:140:"I am using the following very basic tree code to render a tree :
+
+
+Code:
+---------
+Ext.onReady(function(){
+
+ Ext.BLANK_IMAGE_URL =...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51739";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:3516:"<div>I am using the following very basic tree code to render a tree :<br />
+<br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left">Ext.onReady(function(){<br />
+ <br />
+ Ext.BLANK_IMAGE_URL = "images/s.gif";<br />
+ Ext.QuickTips.init();<br />
+ <br />
+ <br />
+ //Alias for Ext.tree <br />
+ var Tree = Ext.tree;<br />
+ <br />
+ // Children array<br />
+ var myArray = [<br />
+ {id : '1', text : 'Item 1', leaf : true},<br />
+ {id : '2', text : 'Item 2', leaf : true},<br />
+ {<br />
+ id : '3', <br />
+ text : 'Sub Folder', <br />
+ children : [<br />
+ {id : '4', text : 'First', leaf : true},<br />
+ {id : '5', text : 'Second', leaf : true}<br />
+ ]<br />
+ }<br />
+ ];<br />
+ <br />
+ <br />
+ // Root node<br />
+ var rootNode = new Tree.AsyncTreeNode({<br />
+ id : 'isroot',<br />
+ text : 'ROOT',<br />
+ children : myArray<br />
+ });<br />
+<br />
+ // Tree panel <br />
+ var myTree = new Tree.TreePanel({<br />
+ root : rootNode, <br />
+ title : 'Tree Test',<br />
+ rootVisible : true,<br />
+ frame : true,<br />
+ autoScroll:true,<br />
+ animate:true,<br />
+ loader : new Tree.TreeLoader()<br />
+ });<br />
+ <br />
+ myTree.render('tree');<br />
+ myTree.getRootNode().expand();<br />
+ <br />
+});</code><hr />
+</div>I want to use the TreeLoader in a way where I wudn't have to give it a dataUrl but to pass it an object/array to construct some nodes and add them to the parent node. So for example if I do :<br />
+<br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left">myTree.on('click', function(n) {<br />
+ var newNodes = myDataStore.getChildNodes(n.id);<br />
+ updateTree(newNodes);<br />
+}<br />
+<br />
+function updateTree(nodes){<blockquote> for(var i=0; i<nodes.length; i++){<blockquote>nodeID = node[i].id;<br />
+nodeText = node[i].text;<br />
+nodeIsLeaf = node[i].isLeaf;<br />
+</blockquote>}<br />
+</blockquote>}</code><hr />
+</div>How do I use the data I get above to add child nodes to the clicked node and expand it USING THE TreeLoader. I used the appendChild before but it doesn't update the tree quite the way I want to and I am sure the TreeLoader will solve the problem<br />
+<br />
+If anyone could point to a simple example that would be highly appreciated. Thanks</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:6:"sz_146";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:3;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:43:"Checkbox in Grid Column Handler no response";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51738&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 18:32:16 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:149:"Hello All,
+
+I'm trying to implement the checkbox inside a grid column. Everything works correctly, but for some reason my handler is not firing.
+I...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51738";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:1621:"<div>Hello All,<br />
+<br />
+I'm trying to implement the checkbox inside a grid column. Everything works correctly, but for some reason my handler is not firing.<br />
+I get no errors in firefox.<br />
+So far I'm using a very simple implementation with an alert.<br />
+<br />
+Thanks in advance for any help.<br />
+<br />
+Jack<br />
+<br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left">{<br />
+ header: 'Serviced?',<br />
+ width:100,<br />
+ sortable:true,<br />
+ dataIndex:'serviced',<br />
+ align:'center',<br />
+ renderer: function(data) {<br />
+ return "<input type='checkbox' " + (data ? "checked='checked'" : "") + " />"<br />
+ },<br />
+ editor: new Ext.grid.GridEditor(<br />
+ new Ext.form.Checkbox(<br />
+ {<br />
+ handler: function() {<br />
+ alert('Checkbox has been selected');<br />
+ }<br />
+ } <br />
+ )<br />
+ )<br />
+}</code><hr />
+</div></div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:6:"Jack_S";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:4;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:35:"anchor to pin one of several panels";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51737&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 18:18:13 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:147:"I have a window crearted with the layout:'anchor' at config and given a fixed width and height at config but also allowed to resize.
+
+I then add...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:17:"Ext: Premium Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:44:"http://extjs.com/forum/forumdisplay.php?f=11";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51737";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:1782:"<div>I have a window crearted with the layout:'anchor' at config and given a fixed width and height at config but also allowed to resize.<br />
+<br />
+I then add items to the otherwise empty window with the code<br />
+<br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left"> Ext.getCmp('testWindow').add(<br />
+ {html:'<h1>hi there1</h1>',height:25},<br />
+ {html:'<h1>hi there2</h1>',height:55},<br />
+ {html:'<h1>hi there3</h1>',height:25},<br />
+ <br />
+ <br />
+ {anchor:'-50 -50'<br />
+ ,html:'<h1>should use remaining space?</h1>'<br />
+ }<br />
+<br />
+ );</code><hr />
+</div><br />
+If I add ONLY the last item then it appears in the window with theright and bottom edges appearing 50px from the window edges. Resizing the window causes the panel to rezise and retain the 50px<br />
+<br />
+HOWEVER, if I add the first three panels as in the full code above, they all render at the expected size but the final panel now has the correct offset from the right but flows below the bottom of the window.<br />
+<br />
+Can anyone explain what I have got wrong here as it appears the anchor is working at the rights but noty at the bottom?<br />
+<br />
+I have tried this with the same effect in FF and IE.<br />
+<br />
+Thanks<br />
+Graeme</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:11:"GraemeBryce";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:5;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:34:"Best Tool for Editing Theme Images";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51736&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 18:01:57 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:146:"Hi all.
+
+I've looked through the postings here on theme creation and found some references to image editing, but none that really recommend any...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:17:"Ext: Premium Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:44:"http://extjs.com/forum/forumdisplay.php?f=11";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51736";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:721:"<div>Hi all.<br />
+<br />
+I've looked through the postings here on theme creation and found some references to image editing, but none that really recommend any particular tool for modifying the images used in the default and other themes to different color schemes. For example, the default panel title bar image is white-top-bottom.gif; it has a light blue theme. Is there a tool that will allow me<br />
+to keep the same dithering but use a different color without having to re-create a new image? In other words, use the default theme file as a template, but apply a different color?<br />
+Any open source offerings that do the job?<br />
+<br />
+Thanks in advance for anyone's suggestions.<br />
+<br />
+- RJ</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:15:"Robert Jacobsen";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:6;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:40:"Validation for grid items within a form?";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51735&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 17:43:05 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:150:"I've looked through the API and searched the forums for a few days now and I cannot seem to find a way to validate an entry in an editor grid.
+
+The...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51735";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:1028:"<div>I've looked through the API and searched the forums for a few days now and I cannot seem to find a way to validate an entry in an editor grid.<br />
+<br />
+The scenario is this. I've got a form with form data and several editor grids. The data and grid information can be saved periodically. For this save process I turn validation off, per the requirements given to me. However, there is a final save that validation should be turned on for particular items and if validation fails, prompt and halt the final save until corrections are made.<br />
+<br />
+This works very well for the form elements that need proper validation. However, there is no ".isValid()" method, or anything of the like, for the records within the store. <br />
+<br />
+Anyone have any idea how I might be able to test for validation without walking through the store array "cell" by "cell"?<br />
+<br />
+<br />
+Using Ext version 2.1<br />
+<br />
+<br />
+Thanks in advance!<br />
+<br />
+Heath</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:6:"HeathT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:7;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:34:"bug with clicksToEdit:1 in ext 2.2";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51734&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 17:42:09 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:99:"Hi everybody
+
+The clicksToEdit:1 is still not working as well I hope :
+
+if you take this example...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Bugs";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:44:"http://extjs.com/forum/forumdisplay.php?f=20";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51734";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:1031:"<div>Hi everybody<br />
+<br />
+The clicksToEdit:1 is still not working as well I hope :<br />
+<br />
+if you take this example :<br />
+<br />
+<a href="http://extjs.com/deploy/dev/examples/grid/edit-grid.html" target="_blank">http://extjs.com/deploy/dev/examples...edit-grid.html</a><br />
+<br />
+Here is my problem<br />
+<br />
+1) click on "blue gentian" - don't change the cell<br />
+2) then click on "sun or shade", the right cell of "blue gentian" - >you are in edit mode<br />
+<br />
+1) click on "blue gentian" - <b>change </b>the cell<br />
+2) then click on "sun or shade", the right cell of "blue gentian" - >you are in <b>NOT </b>edit mode<br />
+<br />
+1) click on "blue gentian" - <b>change </b>the cell<br />
+ 2) then click on "Anenome", (first col 2nd row) - >you are in edit mode<br />
+<br />
+So the problem is only when you click on the next right cell, you have edit before :(<br />
+<br />
+Thanks to look at this problem</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:9:"gegene421";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:8;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:26:"ComboBox store config bug?";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51733&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 17:35:26 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:151:"This looks like a bug, but maybe I'm not understanding the intended behavior:
+
+It is possible to supply a storeId of a previously created/registered...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:17:"Ext: Premium Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:44:"http://extjs.com/forum/forumdisplay.php?f=11";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51733";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:988:"<div>This looks like a bug, but maybe I'm not understanding the intended behavior:<br />
+<br />
+It is possible to supply a storeId of a previously created/registered data store as the store config property of a ComboBox (the code specifically supports it and it works fine). But when lazyInit=true, the store doesn't gets looked up until the Combo is initialized. So if a ComboBox is rendered on a form but never used, when that form is destroyed (like closing/destroying a window containing the form), the bindStore function does not take this possibility into account, resulting in a runtime error when it tries to 'un' the listeners (from the string storeId, which of course, doesn't have any listeners).<br />
+<br />
+If this sounds like a bug, the only fix I could come up with is to override the bindStore function and specifically check the type of the store property before uninitializing it.<br />
+<br />
+Any other thoughts/ideas on this?<br />
+<br />
+Thanks,<br />
+Eric</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:6:"Eric24";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:9;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:18:"Grid CRUD example.";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51732&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 17:28:21 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:149:"Hi!
+
+ Is there some simple CRUD example. Just basic features.
+ Initially empty EditableGrid with one plain text column "data". three buttons on...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:17:"Gxt: Premium Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:44:"http://extjs.com/forum/forumdisplay.php?f=25";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51732";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:813:"<div>Hi!<br />
+<br />
+ Is there some simple CRUD example. Just basic features. <br />
+ Initially empty EditableGrid with one plain text column "data". three buttons on toolbar<br />
+1. Refresh/load (let's assume server via GWT RPC will give us ready to use List<BasicModel>)<br />
+2. Delete record. <br />
+<br />
+ BaseModel item = grid.getSelectionModel().getSelectedItem();<br />
+ if (item != null)<br />
+ {<br />
+ store.remove(item);<br />
+ }<br />
+make's changes in store, but they are not visible, for some reason.<br />
+3. And just add "new line" line to grid. <br />
+<br />
+ BaseModel item = makeItem();<br />
+ store.add(item);<br />
+<br />
+also add's item to store but it is not visible.</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:14:"SpiralUniverse";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:10;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:24:"Grow height of TreePanel";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51731&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 17:07:20 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:149:"Hi, I'd like to allow the height of a treepanel to expand and contract as nodes are opened or closed, rather than using a staticly sized container...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51731";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:223:"<div>Hi, I'd like to allow the height of a treepanel to expand and contract as nodes are opened or closed, rather than using a staticly sized container with a scrollbar. <br />
+<br />
+Is there a way to do this?</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:8:"jfb_1973";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:11;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:20:"Getting totalRecords";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51730&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 17:02:56 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:147:"i've been trying to get the totalRecords into the store to no avail. below is the xml returned by the server. how do i get at the totalRecords...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51730";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:1729:"<div>i've been trying to get the totalRecords into the store to no avail. below is the xml returned by the server. how do i get at the totalRecords property?<br />
+<br />
+<br />
+<div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">PHP Code:</div>
+ <div class="alt2">
+ <hr />
+ <code style="white-space:nowrap">
+ <div dir="ltr" style="text-align:left;">
+ <!-- php buffer start --><code><span style="color: #000000">
+<br /><span style="color: #0000BB"><?xml version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0" </span><span style="color: #0000BB">encoding</span><span style="color: #007700">=</span><span style="color: #DD0000">"UTF-8"</span><span style="color: #0000BB">?><br /></span><NewDataSet><br /><br /> <Table><br /> <CustomerID>1000000</CustomerID><br /> <CountryID>188</CountryID><br /> <FirstName>Counter</FirstName><br /> <LastName>Walk-in</LastName><br /> <PassportNum>a</PassportNum><br /> <email>a</email><br /> <Cell>a</Cell><br /> <Addr1>addr1</Addr1><br /> <Addr2>addr2</Addr2><br /> </Table><br /><br /> <Table1><br /> <totalCount>3</totalCount><br /> </Table1><br /><br /></NewDataSet></span>
+</code><!-- php buffer end -->
+ </div>
+ </code>
+ <hr />
+ </div>
+</div></div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:12:"d0uble_hel1x";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:12;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:27:"Grid Filter plugin API docs";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51729&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 16:54:14 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:127:"Now that Ambience's Grid Filter plugin is included in the SDK package, would it be possible to include API documentation for...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:21:"Ext: Feature Requests";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=4";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51729";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:396:"<div>Now that Ambience's Grid Filter plugin is included in the SDK package, would it be possible to include API documentation for it?<br />
+<br />
+<a href="http://extjs.com/forum/showthread.php?t=14503" target="_blank">http://extjs.com/forum/showthread.php?t=14503</a><br />
+<br />
+From what I have seen, it looks like it is one of the most popular plugins....<br />
+<br />
+Thanks</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:8:"vmorale4";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:13;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:37:"How to the selectedIndex of combobox?";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51728&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 16:42:57 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:151:"Hi,
+I m trying to set the selectedIndex on a combobox, I've read this topic : http://extjs.com/forum/showthread.php?t=51631&highlight=ComboBox
+
+But...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51728";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:972:"<div>Hi,<br />
+I m trying to set the selectedIndex on a combobox, I've read this topic : <a href="http://extjs.com/forum/showthread.php?t=51631&highlight=ComboBox" target="_blank">http://extjs.com/forum/showthread.ph...light=ComboBox</a><br />
+ <br />
+But the solution doesn't work for me.<br />
+ <br />
+I have : <br />
+ <br />
+{<br />
+ id : 'pays',<br />
+ xtype : 'combo',<br />
+ //frame: 'true',<br />
+ style : 'color : black;text-align: left;',<br />
+ itemCls : 'x-combo-list-item2',<br />
+ displayField:'fr_nom',<br />
+ valueField:'id',<br />
+ triggerAction: 'all',<br />
+ store: ds7,<br />
+ mode:'local',<br />
+ editable : false,<br />
+ fieldLabel: 'Pays',<br />
+ allowBlank: false,<br />
+ name: 'pays'<br />
+}<br />
+ <br />
+As you notice, the displayField is different from the valuefield, and i'd like to autoSelect an items in the list.<br />
+How should i do?<br />
+Thanks,<br />
+Nico.</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:8:"Nico5779";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:14;a:6:{s:4:"data";s:35:"
+
+
+
+
+
+
+
+
+ ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:3:{s:0:"";a:6:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:55:"types[config.xtype || defaultType] is not a constructor";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://extjs.com/forum/showthread.php?t=51727&goto=newpost";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:29:"Mon, 03 Nov 2008 16:33:38 GMT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:140:"I have a page that works fine in IE, but has intermittent errors in FireFox 3. Sometimes I load the page and get:
+
+types[config.xtype ||...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Ext: Help";s:7:"attribs";a:1:{s:0:"";a:1:{s:6:"domain";s:43:"http://extjs.com/forum/forumdisplay.php?f=9";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:45:"http://extjs.com/forum/showthread.php?t=51727";s:7:"attribs";a:1:{s:0:"";a:1:{s:11:"isPermaLink";s:4:"true";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://purl.org/rss/1.0/modules/content/";a:1:{s:7:"encoded";a:1:{i:0;a:5:{s:4:"data";s:3493:"<div>I have a page that works fine in IE, but has intermittent errors in FireFox 3. Sometimes I load the page and get:<br />
+<br />
+types[config.xtype || defaultType] is not a constructor<br />
+<br />
+I can reload the same page and get:<br />
+<br />
+Ext.ux.TabbedPortal is not a constructor<br />
+<br />
+And sometimes I can load this page and it loads with no errors and works as expected. <br />
+<br />
+Without making any code changes, I can just reload the page over and over and get any one of these responses. I am not posting code right now because the app is fairly large. I just wanted to see if anyone else has experience this type of intermittent error in FireFox. Since the page does load and run 100% correctly sometimes, I'm not sure how it could be a coding error. It seems like a timing error.<br />
+<br />
+Also, in another, possibly related error, I have a pre-configured TabPanel which has a context menu which is nearly a copy/paste of the context menu in the Advanced Tabs sample application. I am loading it as a plugin:<br />
+<br />
+ <div style="margin:20px; margin-top:5px">
+ <div class="smallfont" style="margin-bottom:2px">Code:</div>
+ <hr /><code style="margin:0px" dir="ltr" style="text-align:left">initComponent: function()<br />
+ {<br />
+ Ext.apply(this,<br />
+ {<br />
+ layout: 'border',<br />
+ items:<br />
+ [<br />
+ //configure the tab panel which will hold the portal components<br />
+ {<br />
+ xtype: 'tabpanel',<br />
+ resizeTabs: true, <br />
+ minTabWidth: 115,<br />
+ tabWidth: 135,<br />
+ enableTabScroll: true,<br />
+ defaults: { autoScroll: true },<br />
+ region: 'center',<br />
+ activeTab: 0,<br />
+ plugins: new Ext.ux.PortalTabContextMenu()<br />
+<br />
+ },</code><hr />
+</div>I also get an "Ext.ux.PortalTabContextMenu is not a constructor" error when that line is in place with FireFox3 (but works fine in IE). <br />
+<br />
+Using Firebug, I pull up the script of the file that contains that object and the file is shown as empty. So, it appears that FireFox has either not loaded the file completly when the error occurs or thinks it has loaded the file, but has not. It is really odd. <br />
+<br />
+I have never been able to get this to work in FireFox but it works fine in IE. This also seems like a timing issue. The only major difference between this situation and the one in the Advanced Tabs Sample application is that I am using a pre-configured TabPanel and the sample app instantiates the TabPanel in the onReady event handler.</div>
+
+";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:6:"bwoody";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}}}}}}}}}}}}s:7:"headers";a:14:{s:4:"date";s:29:"Mon, 03 Nov 2008 20:03:14 GMT";s:6:"server";s:22:"Apache/2.2.3 (Red Hat)";s:12:"x-powered-by";s:9:"PHP/5.2.5";s:10:"set-cookie";s:134:"bblastvisit=1225742594; expires=Tue, 03-Nov-2009 20:03:14 GMT; path=/, bblastactivity=0; expires=Tue, 03-Nov-2009 20:03:14 GMT; path=/";s:13:"cache-control";s:18:"max-age=1225743207";s:6:"pragma";s:7:"private";s:7:"expires";s:29:"Mon, 03 Nov 2008 20:13:27 GMT";s:13:"last-modified";s:29:"Mon, 03 Nov 2008 19:13:27 GMT";s:4:"etag";s:32:"8ee50b17c7bad1a22198c70b271ef24d";s:4:"vary";s:15:"Accept-Encoding";s:16:"content-encoding";s:4:"gzip";s:14:"content-length";s:4:"8991";s:10:"connection";s:5:"close";s:12:"content-type";s:28:"text/xml; charset=ISO-8859-1";}s:5:"build";d:20080315205903;}
\ No newline at end of file
Added: trunk/qo-kregator/php/cache/memberID_3/fav_b3b45881d4751326bcdd9ce5e1595a4b2e6009dc_favicon.ico
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/php/cache/memberID_3/fav_b3b45881d4751326bcdd9ce5e1595a4b2e6009dc_favicon.ico
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/php/cache/memberID_3/img_b3b45881d4751326bcdd9ce5e1595a4b2e6009dc_rss.jpg
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/php/cache/memberID_3/img_b3b45881d4751326bcdd9ce5e1595a4b2e6009dc_rss.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/php/export.php
===================================================================
--- trunk/qo-kregator/php/export.php (rev 0)
+++ trunk/qo-kregator/php/export.php 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,56 @@
+<?php
+
+/************************************************************************
+ This file is part of Qo-Kregator.
+
+ Qo-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+*************************************************************************/
+
+require_once("./system/modules/qo-kregator/php/lib.php");
+
+$myFeed = '<?xml version="1.0" encoding="UTF-8"?>
+<opml version="1.0" >
+ <head>
+ <text></text>
+ </head>
+ <body>
+';
+
+// Get feed URL
+$s = 'SELECT * FROM `qo-kregator-dir` WHERE type=\'file\' AND userID=\''.$member_id.'\' ORDER BY name ASC';
+$r = mysql_query($s);
+
+$search = array("&", "\"", "<", ">", "\r", "\n");
+$replace = array("&", """, "<", ">", "
", "
");
+
+while( $a = mysql_fetch_object($r) ) {
+
+$a->url = str_replace($search, $replace, $a->url);
+$a->url_feed = str_replace($search, $replace, $a->url_feed);
+$a->name = str_replace($search, $replace, $a->name);
+$a->description = str_replace($search, $replace, $a->description);
+
+$myFeed .= ' <outline htmlUrl="'.$a->url.'" title="'.$a->name.'" version="RSS" type="rss" xmlUrl="'.$a->url_feed.'" text="'.$a->name.'" description="'.$a->description.'" />
+';
+
+} // Fin du while
+
+$myFeed .= ' </body>
+</opml>';
+
+header('Content-type: text/xml');
+header('Content-Disposition: attachment; filename="myfeed.opml"');
+echo $myFeed;
+
+?>
\ No newline at end of file
Added: trunk/qo-kregator/php/lib.php
===================================================================
--- trunk/qo-kregator/php/lib.php (rev 0)
+++ trunk/qo-kregator/php/lib.php 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,142 @@
+<?php
+
+/************************************************************************
+ This file is part of Qo-Kregator.
+
+ Qo-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+*************************************************************************/
+
+// Unset all error reporting
+error_reporting(0);
+
+// Emulate mysql_set_charset function if it don't exist (exist until Php >= 5.2.3 & MySql >= 5.0.7 ).
+// This function must be Ok with MySql >= 4 & Php >= 4.
+
+if (function_exists('mysql_set_charset') === false) {
+ function mysql_set_charset($charset) {
+ return mysql_query('SET CHARACTER SET "'.$charset.'"');
+ }
+}
+
+// Set MySql charset to UTF8
+mysql_set_charset('utf8');
+
+
+function summary($string, $length) {
+
+ $suffix = '...';
+ $short_desc = trim(str_replace(array("\r","\n", "\t"), ' ', strip_tags($string)));
+ $desc = trim(substr($short_desc, 0, $length));
+ $lastchar = substr($desc, -1, 1);
+
+ if ($lastchar == '.' || $lastchar == '!' || $lastchar == '?') $suffix='';
+
+ $desc .= $suffix;
+
+ return trim($desc);
+} // summary
+
+function get_total($id_feed, $member_id) {
+
+$s = 'SELECT id FROM `qo-kregator-items` WHERE id_feed=\''.$id_feed.'\' AND userID=\''.$member_id.'\'';
+$r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+return mysql_num_rows($r);
+
+} // End of get_total()
+
+function get_unseen($id_feed, $member_id) {
+
+$s = 'SELECT id FROM `qo-kregator-items` WHERE id_feed=\''.$id_feed.'\' AND seen=\'n\' AND userID=\''.$member_id.'\'';
+$r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+return mysql_num_rows($r);
+
+} // End of get_unseen()
+
+
+function get_enclosure($choice, $link, $height, $width, $title, $type='' ) {
+
+$return = '';
+
+if( $choice == 'mp3' ) {
+
+$return = '
+<tr class="qo-kregator-enclosure">
+ <td class="qo-kregator-enclosure-img"><img src="system/modules/qo-kregator/img/default/media-mp3.png" alt="" /></td>
+ <td class="qo-kregator-enclosure-content">
+ <div>
+ <object type="application/x-shockwave-flash" data="system/modules/qo-kregator/DewPlayer/dewplayer.swf?mp3='.$link.'" width="200" height="20">
+ <param name="movie" value="/system/modules/qo-kregator/DewPlayer/dewplayer.swf?mp3='.$link.'" />
+ </object>
+ </div>
+ <div>'.$title.'</div>
+ </td>
+</tr>
+';
+
+return $return;
+
+} elseif( $choice == 'flv' ) {
+
+$return = '
+<tr class="qo-kregator-enclosure">
+ <td class="qo-kregator-enclosure-img"><img src="system/modules/qo-kregator/img/default/media-flv.png" alt="" /></td>
+ <td class="qo-kregator-enclosure-content">
+ <div>
+ <object type="application/x-shockwave-flash" data="system/modules/qo-kregator/DewTube/dewtube.swf?movie='.$link.'" width="'.$width.'" height="'.$height.'">
+ <param name="movie" value="dewtube.swf?movie='.$link.'" />
+ </object>
+ </div>
+ <div>'.$title.'</div>
+ </td>
+</tr>
+';
+
+return $return;
+
+} elseif( $choice == 'pdf' ) {
+
+$return = '
+<tr class="qo-kregator-enclosure">
+ <td class="qo-kregator-enclosure-img"><img src="system/modules/qo-kregator/img/default/media-pdf.png" alt="" /></td>
+ <td class="qo-kregator-enclosure-content">
+ <div><embed src="'.$link.'" width="200" height="100" type="'.$type.'" autoplay="false" /></div>
+ <div>'.$title.'</div>
+ </td>
+</tr>
+';
+
+return $return;
+
+} elseif( $choice == 'other' ) {
+
+$return = '
+<tr class="qo-kregator-enclosure">
+ <td class="qo-kregator-enclosure-img"><img src="system/modules/qo-kregator/img/default/media-video.png" alt="" /></td>
+ <td class="qo-kregator-enclosure-content">
+ <div><embed src="'.$link.'" width="'.$width.'" height="'.$height.'" type="'.$type.'" autoplay="false" /></div>
+ <div>'.$title.'</div>
+ </td>
+</tr>
+';
+
+return $return;
+
+}
+
+
+} // End of get_enclosure()
+
+?>
\ No newline at end of file
Added: trunk/qo-kregator/php/qo-kregator.php
===================================================================
--- trunk/qo-kregator/php/qo-kregator.php (rev 0)
+++ trunk/qo-kregator/php/qo-kregator.php 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,1190 @@
+<?php
+
+/************************************************************************
+ This file is part of Qo-Kregator.
+
+ Qo-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+*************************************************************************/
+
+$o = new stdClass;
+$o->success = false; // By default
+
+$what = (isset($_GET["what"])) ? $_GET["what"] : $_POST["what"];
+
+
+switch($what) {
+
+ case "add_folder":
+
+ $new_folder = $_POST['newFolder'];
+ $nodeID = $_POST['nodeID'];
+
+ $s = '
+ INSERT INTO
+ `qo-kregator-dir`
+
+ (node, display_order, name, type, userID) VALUES
+
+ (\''.$nodeID.'\', \'999\', \''.mysql_real_escape_string($new_folder).'\', \'folder\', \''.$member_id.'\')
+ ';
+
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $id_folder = mysql_insert_id();
+
+ $o->success = true;
+ $o->id = $id_folder;
+ $o->name = stripslashes($new_folder);
+ $o->nodeID = stripslashes($nodeID);
+
+ echo json_encode($o);
+ break;
+
+ case "clean_feed":
+
+ $day = $_POST['day'];
+ $nb = 0;
+
+ $s = 'DELETE FROM `qo-kregator-items` WHERE DATEDIFF(now(), `date`) > '.$day.' AND userID='.$member_id.' AND important=\'n\'';
+
+ mysql_query($s) or die('{"success": false,"msg":"'.mysql_error().'"}');
+
+ $nb = mysql_affected_rows();
+
+ $o->success= true;
+ $o->del_items= $nb;
+
+ // We are taking the opportunity to optimize all tables
+ $s = 'OPTIMIZE TABLE `qo-kregator-items`, `qo-kregator-conf`, `qo-kregator-dir`';
+ mysql_query($s) or die('{"success": false,"msg":"'.mysql_error().'"}');
+
+ echo json_encode($o);
+ break;
+
+ case "del_items":
+
+ require_once("./system/modules/qo-kregator/php/lib.php");
+ $id_item = $_POST['id_item'];
+
+ $item = explode(',', $id_item);
+
+ $o = new stdClass;
+ $o->success = true;
+
+ // Delete lignes
+ for( $i=0; $i < count($item); $i++ ) {
+ if( trim($item[$i]) != '' ) {
+
+ $s = 'SELECT id_feed FROM `qo-kregator-items` WHERE id=\''.$item[$i].'\' AND userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+ $a = mysql_fetch_object($r);
+ $id_feed = $a->id_feed;
+
+ $s = 'DELETE FROM `qo-kregator-items` WHERE id=\''.$item[$i].'\' AND userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $o->message->Node[$id_feed]->unseen = get_unseen($id_feed, $member_id);
+ $o->message->Node[$id_feed]->total = get_total($id_feed, $member_id);
+ }
+ }
+
+ echo json_encode($o);
+ break;
+
+ case "del_nodes":
+
+ require_once("./system/modules/qo-kregator/php/lib.php");
+
+ $id_node = $_POST['id_node'];
+
+ $s = 'SELECT id, type, url_feed, favicon, image FROM `qo-kregator-dir` WHERE (node=\''.$id_node.'\' OR id=\''.$id_node.'\') AND userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ while ( $a = mysql_fetch_object($r) ) {
+
+ // If it's feed, we delete cache
+ if( $a->type == 'file' ) {
+
+ @unlink('./system/modules/qo-kregator/php/cache/memberID_'.$member_id.'/'.sha1($a->url_feed).'.spc');
+
+ if( substr($a->image, 0, 7) != 'http://' ) @unlink('.'.$a->image);
+ if( substr($a->favicon, 0, 7) != 'http://' ) @unlink('.'.$a->favicon);
+
+ }
+
+ $s1 = 'DELETE FROM `qo-kregator-items` WHERE id_feed=\''.$a->id.'\' AND userID=\''.$member_id.'\'';
+ mysql_query($s1) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $s1 = 'DELETE FROM `qo-kregator-dir` WHERE id=\''.$a->id.'\' AND userID=\''.$member_id.'\'';
+ mysql_query($s1) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ }
+
+ $o = new stdClass;
+ $o->success = true;
+ echo json_encode($o);
+ break;
+
+ case "get_items_desc":
+
+ $id_item = $_POST['id_item'];
+
+ $s = 'SELECT
+ `qo-kregator-items`.titre as t,
+ `qo-kregator-items`.date as d,
+ `qo-kregator-items`.auteur as a,
+ `qo-kregator-items`.description as des,
+ `qo-kregator-items`.url as u,
+ `qo-kregator-dir`.name as f
+
+ FROM
+ `qo-kregator-items`,
+ `qo-kregator-dir`
+
+ WHERE
+ `qo-kregator-items`.id_feed = `qo-kregator-dir`.id AND
+ `qo-kregator-items`.id=\''.$id_item.'\' AND
+ `qo-kregator-items`.userID=\''.$member_id.'\'';
+
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Error while retrieve description description (id:".$id_item."). Sql error : ".mysql_error()." }");
+ $nb_items = mysql_num_rows($r);
+ $a = mysql_fetch_object($r);
+
+ $Items[0]['t'] = utf8_encode($a->t);
+ $Items[0]['d'] = $a->d;
+ $Items[0]['a'] = $a->a;
+ $Items[0]['des'] = utf8_encode($a->des);
+ $Items[0]['u'] = $a->u;
+ $Items[0]['f'] = utf8_encode($a->f);
+
+
+ echo json_encode($Items);
+ break;
+
+ case "get_items":
+
+ $id_feed = $_POST['id_feed'];
+ $id_node = $_POST['id_node'];
+
+ $start = $_POST['start'];
+ $limit = $_POST['limit'];
+
+ if( isset($_POST['searchText']) ) {
+ $searchText = $_POST['searchText'];
+ $sqlTxt = 'AND `qo-kregator-items`.titre LIKE \'%'.$searchText.'%\'';
+ }
+ else {
+ $sqlTxt = '';
+ }
+
+ if( isset($_POST['searchEtat']) ) {
+ $searchEtat = $_POST['searchEtat'];
+ if( $searchEtat == 'all' ) {
+ $sqlEtat = '';
+ } else if( $searchEtat == 'nonlu' ) {
+ $sqlEtat = 'AND `qo-kregator-items`.seen=\'n\'';
+ } else if( $searchEtat == 'important' ) {
+ $sqlEtat = 'AND `qo-kregator-items`.important=\'y\'';
+ }
+ }
+ else {
+ $sqlEtat = '';
+ }
+
+ if( $id_feed == '*' ) {
+
+ if( $id_node == 0 ) {
+ $sql_feed = '';
+ } else {
+ $sql_feed = '`qo-kregator-dir`.node=\''.$id_node.'\' AND';
+ }
+
+ } else {
+ $sql_feed = '`qo-kregator-items`.id_feed=\''.$id_feed.'\' AND';
+ }
+
+ if( isset($_POST['searchDate']) ) {
+ $searchDate = $_POST['searchDate'];
+ if( $searchDate == '*') {
+ $sql_date = '';
+ } else {
+ $sql_date = 'DATE(`qo-kregator-items`.date)=\''.$searchDate.'\' AND';
+ }
+ } else {
+ $sql_date = '';
+ }
+
+ $Items = array();
+
+ $s_count = '
+ SELECT
+ `qo-kregator-items`.id,
+ `qo-kregator-items`.titre as t,
+ `qo-kregator-items`.summary as sum,
+ `qo-kregator-items`.date as d,
+ `qo-kregator-items`.url as u,
+ `qo-kregator-items`.seen as s,
+ `qo-kregator-items`.important as i,
+ `qo-kregator-dir`.id as id_f,
+ `qo-kregator-dir`.name as f
+
+ FROM
+ `qo-kregator-items`,
+ `qo-kregator-dir`
+
+ WHERE
+ `qo-kregator-items`.id_feed = `qo-kregator-dir`.id AND
+ '.$sql_feed.'
+ '.$sql_date.'
+ `qo-kregator-items`.userID=\''.$member_id.'\'
+ '.$sqlTxt.'
+ '.$sqlEtat.'
+ ';
+
+ $s = $s_count. '
+ ORDER BY d DESC
+ LIMIT '.$start.', '.$limit;
+
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Error while retrive items for feed id ".$id_feed.". Sql error : ".mysql_error()."'}");
+ $r_count = mysql_query($s_count);
+
+ $nb_items = mysql_num_rows($r_count);
+
+ $i=0;
+
+ while($a = mysql_fetch_object($r)) {
+
+ $Items[$i]['id'] = $a->id;
+ $Items[$i]['t'] = utf8_encode($a->t);
+ $Items[$i]['sum'] = utf8_encode($a->sum);
+ $Items[$i]['d'] = $a->d;
+ $Items[$i]['u'] = $a->u;
+ $Items[$i]['s'] = $a->s;
+ $Items[$i]['i'] = $a->i;
+ $Items[$i]['id_f'] = utf8_encode($a->id_f);
+ $Items[$i]['f'] = $a->f;
+
+ $i++;
+
+ }
+
+ echo '{"nbItems":'.$nb_items.', "Items":'.json_encode($Items).'}';
+
+ break;
+
+ case "get_nodes":
+
+ require_once("system/modules/qo-kregator/php/lib.php");
+
+ function isChild($id) {
+ global $member_id;
+
+ $nb = 0;
+
+ $s = 'SELECT id FROM `qo-kregator-dir` WHERE node=\''.$id.'\' AND userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success': false, 'msg':'3 - Sql error : ".mysql_error()."'}");
+
+ $nb = mysql_num_rows($r);
+
+ if( $nb == 0 ) return false;
+ else return true;
+
+ } //isChild
+
+ function getNode($deph) {
+ global $member_id;
+
+ $s = 'SELECT * FROM `qo-kregator-dir` WHERE node=\''.$deph.'\' AND userID=\''.$member_id.'\' ORDER BY display_order ASC';
+ $r = mysql_query($s) or die("{'success': false, 'msg':'4 - Sql error : ".mysql_error()."}");
+
+ $retour = '[';
+
+ while ( $a = mysql_fetch_object($r) ) {
+
+ // Add default Favicon if this feed dosen't have one.
+ if( $a->type == 'file' && $a->favicon == '' ) $a->favicon = 'system/modules/qo-kregator/img/default/default_fav.png';
+
+ // Handle expand state
+ if( $a->type == 'folder' ) {
+ if( $a->expand == 0 ) $expand = 'false';
+ elseif( $a->expand == 1 ) $expand = 'true';
+ }
+
+ if( $a->type == 'folder' ) {
+
+ if( isChild($a->id) ) {
+
+ $retour.= "{
+ id:".$a->id.",
+ type: '".$a->type."',
+ text:'".utf8_decode(addslashes($a->name))."',
+ unseen:'',
+ total:'',
+ uiProvider:'col',
+ leaf:false,
+ iconCls:'qo-kregator-feed-folder',
+ nodeID: '".$deph."',
+ expanded:".$expand.",
+ children: ".getNode($a->id)."
+ },";
+
+ } else {
+
+ $retour.= "{
+ id:".$a->id.",
+ type: '".$a->type."',
+ text:'".utf8_decode(addslashes($a->name))."',
+ unseen:'',
+ total:'',
+ uiProvider:'col',
+ leaf:false,
+ iconCls:'qo-kregator-feed-folder',
+ children:[],
+ expanded:".$expand.",
+ nodeID: '".$deph."'
+ },";
+
+ }
+
+ } else {
+
+ $retour.= "{
+ id:".$a->id.",
+ text:'".addslashes($a->name)."',
+ url: '".$a->url."',
+ url_feed: '".$a->url_feed."',
+ type: '".$a->type."',
+ desc: '".addslashes($a->description)."',
+ image: '".$a->image."',
+ view: '".$a->view."',
+ nodeID: '".$deph."',
+ unseen:'".get_unseen($a->id, $member_id)."',
+ total:'".get_total($a->id, $member_id)."',
+ uiProvider:'col',
+ leaf:true,
+ icon:'".$a->favicon."',
+ iconCls:'',
+ refreshCycle:'".$a->refreshCycle."'
+ },";
+
+ }
+
+ } // while
+
+ $retour = substr($retour, 0, strlen($retour)-1);
+
+ $retour .= "]";
+
+ return $retour;
+ } // getNode
+
+ echo getNode(0);
+ break;
+
+ case "get_user_conf" :
+
+ // Is this user as conf ?
+ $nb = 0;
+ $s = 'SELECT id FROM `qo-kregator-conf` WHERE userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success': false,'msg':'1 - Sql error'}");
+
+ $nb = mysql_num_rows($r);
+
+ if( $nb == 0 ) {
+ $s = 'INSERT INTO `qo-kregator-conf` (userID) VALUES (\''.$member_id.'\')';
+ mysql_query($s) or die("{'success': false,'msg':'Sql error'}");
+ }
+
+ $nb = 0;
+
+ $s = 'SELECT * FROM `qo-kregator-conf` WHERE userID=\''.$member_id.'\'';
+
+ $r = mysql_query($s) or die("{'success': false,'msg':'1 - Sql error'}");
+ $a = mysql_fetch_object($r);
+
+ $o->success= true;
+ $o->refresh_feed= $a->refresh_feed;
+ $o->preview_pane = $a->preview_pane;
+ $o->content_font_size = $a->content_font_size;
+ $o->openMode = $a->openMode;
+ $o->showStatusBar = $a->showStatusBar;
+
+ $o->dateTimeFormat = $a->dateTimeFormat;
+ $o->dateFormat = $a->dateFormat;
+
+ $o->tbFeedBtn = explode(',', $a->tbFeedBtn);
+
+ $o->tree_panel_width = ( $a->tree_panel_width == 0 )? '254' : $a->tree_panel_width;
+ $o->grid_panel_height = ( $a->grid_panel_height == 0 )? '150' : $a->grid_panel_height;
+ $o->preview_panel_south_height = ( $a->preview_panel_south_height == 0 )? '300' : $a->preview_panel_south_height;
+ $o->preview_panel_east_width = ( $a->preview_panel_east_width == 0 )? '400' : $a->preview_panel_east_width;
+
+ if( $a->showSummary == 'false' ) { $o->showSummary = false; }
+ else { $o->showSummary = true; }
+
+ if( $a->old_items ) {
+ $o->old_items = true; // delete old items
+ $o->old_items_day = $a->old_items;
+ } else {
+ $o->old_items = false; // no delete
+ $o->old_items_day = 30;
+ }
+
+ echo json_encode($o);
+ break;
+
+ case "add_feed" :
+
+ // Cache must be writable
+ if( !is_writable('./system/modules/qo-kregator/php/cache/') ) {
+
+ $o->success = false;
+ $o->message = 'cache directory is not writable (./system/modules/qo-kregator/php/cache/)';
+ echo json_encode($o);
+ exit;
+
+ }
+
+ require_once("system/modules/qo-kregator/php/lib.php");
+ require_once("system/modules/qo-kregator/php/simplepie.inc.php");
+
+ $o = new stdClass;
+
+ if( isset($_POST['view']) && $_POST['view'] == 'on' ) {
+ $view = 'site';
+ } else {
+ $view = 'normal';
+ }
+
+ if( !isset($_POST['newFeed']) || trim($_POST['newFeed']) == '' ) {
+
+ $o->success = false;
+ $o->message = 'No Feed';
+ echo json_encode($o);
+ exit;
+
+ }
+
+ // Verify if cache dir exist for this user
+ if( !is_dir('./system/modules/qo-kregator/php/memberID_'.$member_id) ) {
+ mkdir('./system/modules/qo-kregator/php/cache/memberID_'.$member_id);
+ }
+
+ $new_feed = trim($_POST['newFeed']);
+ $nodeID = trim($_POST['nodeID']);
+
+ $feed = new SimplePie();
+
+ if (get_magic_quotes_gpc()) {
+ $new_feed = stripslashes($new_feed);
+ }
+ $feed->set_cache_location('./system/modules/qo-kregator/php/cache/memberID_'.$member_id);
+
+ $feed->set_feed_url($new_feed);
+
+ $feed->enable_order_by_date(false);
+ $feed->init();
+
+ $feed->handle_content_type();
+
+ if( $feed->error() ) {
+ $o->success = false;
+ $o->message = 'Bad url.';
+ echo json_encode($o);
+ exit;
+ }
+
+ // Add / at the end of url if needed
+ $url_site = $feed->get_link();
+ if( substr($url_site, -1, 1) != '/' ) { $url_site = $url_site.'/'; }
+
+ /* Put in cache favicon & img of this site */
+
+ // Favicon
+ $tmp_fav = $feed->get_favicon();
+
+ if( $tmp_fav != '' ) {
+
+ if( substr($feed->get_favicon(), 0, 7) != 'http://' ) $tmp_fav = $url_site.$feed->get_favicon();
+
+ $part = explode('/',$tmp_fav);
+ $fav_name = 'fav_'.sha1($new_feed).'_'.$part[count($part)-1];
+
+ if( !@copy($tmp_fav, './system/modules/qo-kregator/php/cache/memberID_'.$member_id.'/'.$fav_name) ) {
+ $favicon = $tmp_fav;
+ } else {
+ $favicon = './system/modules/qo-kregator/php/cache/memberID_'.$member_id.'/'.$fav_name;
+ }
+
+ } else $favicon = '';
+
+ // Image descriptive
+ $tmp_image = $feed->get_image_url();
+
+ if( $tmp_image != '' ) {
+
+ $part = explode('/',$tmp_image);
+ $img_name = 'img_'.sha1($new_feed).'_'.$part[count($part)-1];
+
+ if( !@copy($tmp_image, './system/modules/qo-kregator/php/cache/memberID_'.$member_id.'/'.$img_name) ) {
+ $img_desc = $tmp_image;
+ } else {
+ $img_desc = './system/modules/qo-kregator/php/cache/memberID_'.$member_id.'/'.$img_name;
+ }
+ } else $img_desc = '';
+
+ // Insert feed
+ $s = '
+ INSERT INTO
+ `qo-kregator-dir`
+
+ (type, name, description, url, url_feed, image, favicon, node, display_order, view, userID)
+ VALUES (
+ \'file\',
+ \''.mysql_real_escape_string($feed->get_title()).'\',
+ \''.mysql_real_escape_string($feed->get_description()).'\',
+ \''.$url_site.'\',
+ \''.$new_feed.'\',
+ \''.$img_desc.'\',
+ \''.$favicon.'\',
+ \''.$nodeID.'\',
+ \'0\',
+ \''.$view.'\',
+ \''.$member_id.'\'
+ )';
+
+ if( !mysql_query($s) ) {
+ $o->success = false;
+ $o->message = 'Error while adding new feed. Sql error : '.mysql_error();
+ echo json_encode($o);
+ exit;
+ }
+
+ $id_feed = mysql_insert_id();
+
+ // Insert elements
+
+ if ($feed->data):
+ $items = $feed->get_items();
+ foreach($items as $item):
+
+ $auteur_1 = $item->get_author();
+
+ if( !isset( $auteur_1 ) ) $auteur = '-';
+ else $auteur = $auteur_1->get_name();
+
+ // images relatives
+ $contenu = $item->get_content();
+ $contenu = str_replace('src="/', 'src="'.$feed->get_link(), $contenu);
+
+ // Enclosure management
+ $enclosures = $item->get_enclosures();
+ $nb_enclosures = count($enclosures);
+ $nb_real_enclosures = 0;
+ $enclosure_contenu = '';
+ if( $nb_enclosures > 0 ) {
+
+ $enclosure_contenu .= '<h1 class="qo-kregator-enclosure">Media</h1><table>';
+
+ foreach($enclosures as $enclosure) {
+
+ $extension = strtolower(substr($enclosure->link, -3));
+
+ if( $enclosure->handler == 'mp3' && $extension == 'mp3' ) {
+
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('mp3', $enclosure->link, 0, 0, $enclosure->title);
+
+ } else if( $enclosure->handler == 'fmedia' && $extension == 'flv' ) {
+
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('flv', $enclosure->link, $enclosure->height, $enclosure->width, $enclosure->title);
+
+ } else if ( $enclosure->type == 'application/pdf' ) {
+
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('pdf', $enclosure->link, 0, 0, $enclosure->title, $enclosure->type);
+
+ } else if ( $enclosure->type != 'application/postscript'
+ && $enclosure->type != 'image/gif'
+ && $enclosure->type != 'image/png'
+ && $enclosure->type != 'image/jpeg'
+ && $enclosure->type != 'image/bmp' ) {
+
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('other', $enclosure->link, $enclosure->height, $enclosure->width, $enclosure->title, $enclosure->type);
+
+ }
+ } // End foreach
+
+ $enclosure_contenu .= '</table>';
+
+ } // There is an enclosure
+
+ // Add enclosure
+ if( $nb_real_enclosures != 0 ) {
+ $contenu = $contenu.$enclosure_contenu;
+ }
+
+ $s = '
+ INSERT INTO
+ `qo-kregator-items`
+
+ (id_feed, titre, date, auteur, summary, description, url, userID)
+ VALUES (
+ \''.$id_feed.'\',
+ \''.mysql_real_escape_string($item->get_title()).'\',
+ \''.$item->get_date('Y-m-d H:i:s').'\',
+ \''.mysql_real_escape_string($auteur).'\',
+ \''.summary(mysql_real_escape_string($contenu), '100').'\',
+ \''.mysql_real_escape_string($contenu).'\',
+ \''.$item->get_permalink().'\',
+ \''.$member_id.'\'
+ )';
+
+ if( !mysql_query($s)) {
+
+ $o->success = false;
+ $o->message = 'Error while inserting articles. Sql error : '.mysql_error();
+ echo json_encode($o);
+ exit;
+
+ }
+
+ endforeach;
+ endif;
+
+ $unseen = get_unseen($id_feed, $member_id);
+
+ if( $unseen != 0 ) {
+ $cls = 'file qo-kregator-feed-Unseen';
+ } else {
+ $cls = 'file';
+ }
+
+ $o->success = true;
+
+ $o->text = $feed->get_title();
+ $o->id = $id_feed;
+ $o->url = $url_site;
+ $o->url_feed = $new_feed;
+ $o->cls = $cls;
+ $o->unseen = $unseen;
+ $o->total = get_total($id_feed, $member_id);
+ $o->type = 'file';
+ $o->desc = $feed->get_description();
+ $o->image = $img_desc;
+ $o->icon = $favicon;
+ $o->view = $view;
+ $o->nodeID = $nodeID;
+ echo json_encode($o);
+
+ break;
+
+ case "import" :
+
+ require_once("./system/modules/qo-kregator/php/lib.php");
+
+ if( isset($_FILES['importFile']) && $_FILES['importFile']['tmp_name'] != '' ) {
+ $fichier = $_FILES['importFile'];
+ } else {
+ $fichier = '';
+ }
+
+ if( $_FILES['importFile']['error'] != 0 ) {
+
+ if( $_FILES['importFile']['error'] == 1 ) { echo '{"success":false, "msg":"file too big."}'; exit;}
+ if( $_FILES['importFile']['error'] == 2 ) { echo '{"success":false, "msg":"Exceed MAX FILE SIZE."}'; exit;}
+ if( $_FILES['importFile']['error'] == 3 ) { echo '{"success":false, "msg":"File partialy uploaded."}'; exit;}
+ if( $_FILES['importFile']['error'] == 4 ) { echo '{"success":false, "msg":"No file uploaded."}'; exit;}
+ if( $_FILES['importFile']['error'] == 6 ) { echo '{"success":false, "msg":"No tmp dir configured."}'; exit;}
+ if( $_FILES['importFile']['error'] == 7 ) { echo '{"success":false, "msg":"Not allowed to write file to disk."}'; exit;}
+ if( $_FILES['importFile']['error'] == 8 ) { echo '{"success":false, "msg":"File upload stopped by extension."}'; exit;}
+
+ echo '{"success":false, "msg":"Unknow errror.'.$_FILES['importFile']['error'].'"}'; exit;
+
+ } else {
+
+ // Upload Ok
+ $flux = file_get_contents($_FILES['importFile']['tmp_name']);
+ $importFolder = utf8_encode($_POST['importFolder']);
+
+ // Extract all xmlUrl attributs for this file
+ preg_match_all("/xmlUrl=\"(.*?)\"/e", $flux, $matches, PREG_SET_ORDER);
+
+ $count = count($matches);
+
+ $result = array();
+
+ for($i=0; $i < $count; $i++) {
+
+ $result[] = $matches[$i][1];
+
+ } // for
+
+ $new_feed = implode('|', $result);
+
+ // Add new folder
+ $s = '
+ INSERT INTO
+ `qo-kregator-dir`
+
+ (node, display_order, name, type, userID) VALUES
+
+ (\'0\', \'999\', \''.mysql_real_escape_string($importFolder).'\', \'folder\', \''.$member_id.'\')
+ ';
+
+ mysql_query($s) or die(mysql_error());
+
+ $id_folder = mysql_insert_id();
+
+ $o = new stdClass;
+ $o->success = true;
+ $o->nb = $count;
+ $o->message = 'Done';
+ $o->folderText = stripslashes($importFolder);
+ $o->folderId = $id_folder;
+ $o->new_feed = $new_feed;
+
+ echo json_encode($o);
+ exit;
+
+ } // Upload Ok
+
+ break;
+
+ case "mod_feed" :
+
+ if( !isset($_POST['id_feed']) || trim($_POST['id_feed']) == '' ) {
+ $o->success = false;
+ $o->message = 'NO_FEED';
+ echo json_encode($o);
+ exit;
+ }
+
+ $id_feed = trim($_POST['id_feed']);
+
+ $nom = $_POST['modFeed'];
+
+ if( isset($_POST['view']) && $_POST['view'] == 'on' ) $view = 'site';
+ else $view = 'normal';
+
+ if( isset($_POST['refreshCycle']) && $_POST['refreshCycle'] == 'on' ) $refreshCycle = 'off';
+ else $refreshCycle = 'on';
+
+ // Insert feed
+ $s = 'UPDATE `qo-kregator-dir` SET name=\''.stripslashes(mysql_real_escape_string($nom)).'\', view=\''.$view.'\', refreshCycle=\''.$refreshCycle.'\' WHERE id=\''.$id_feed.'\' AND userID=\''.$member_id.'\'';
+
+ if( !mysql_query($s) ) {
+ $o->success = false;
+ $o->message = 'Error while modify the feed. Sql error : '.mysql_error();
+ echo json_encode($o);
+ exit;
+ }
+
+ $o->success = true;
+ $o->view = $view;
+ $o->nom = stripslashes($nom);
+ $o->refreshCycle = $refreshCycle;
+ echo json_encode($o);
+
+ break;
+
+ case "mod_feed_text" :
+
+ $id = $_POST['id'];
+ $value = $_POST['value'];
+
+ $s = 'UPDATE `qo-kregator-dir` SET name=\''.stripslashes(mysql_real_escape_string($value)).'\' WHERE id=\''.$id.'\' AND userID=\''.$member_id.'\'';
+
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $o->success = true;
+ echo json_encode($o);
+
+ break;
+
+ case "mod_user_conf" :
+
+ $refresh_feed = $_POST['refresh_feed'];
+ $tbFeedBtn = $_POST['tbFeedBtn'];
+ $ContentFontSize = $_POST['ContentFontSize'];
+ $openMode = $_POST['openMode'];
+
+ $dateTimeFormat = $_POST['dateTimeFormat'];
+ $dateFormat = $_POST['dateFormat'];
+
+ if( isset($_POST['showStatusBar']) && $_POST['showStatusBar'] == 'on' ) {
+ $showStatusBar = 'on';
+ } else {
+ $showStatusBar = 'off';
+ }
+
+ if( isset($_POST['old_items']) && $_POST['old_items'] == 'on' ) {
+ $old_items = $_POST['old_items'];
+ } else {
+ $old_items = 'off';
+ }
+
+ $old_items_day = $_POST['old_items_day'];
+
+ if( $old_items == 'on' ) {
+ $old_items_DB = '\''.$old_items_day.'\'';
+ $old_items_RETURN = true;
+ } else {
+ $old_items_DB = 'NULL';
+ $old_items_RETURN = false;
+ }
+
+ // Update user conf
+
+ $s = 'UPDATE `qo-kregator-conf`
+ SET
+ refresh_feed=\''.$refresh_feed.'\',
+ old_items='.$old_items_DB.',
+ showStatusBar=\''.$showStatusBar.'\',
+ tbFeedBtn=\''.$tbFeedBtn.'\',
+ content_font_size=\''.$ContentFontSize.'\',
+ openMode=\''.$openMode.'\',
+ dateTimeFormat=\''.$dateTimeFormat.'\',
+ dateFormat=\''.$dateFormat.'\'
+
+ WHERE userID=\''.$member_id.'\'';
+
+ mysql_query($s) or die("{'success': false,'msg':'Sql error'}");
+
+ $o->success= true;
+ $o->refresh_feed= $refresh_feed;
+ $o->old_items = $old_items_RETURN;
+ $o->old_items_day = $old_items_day;
+ $o->showStatusBar = $showStatusBar;
+ $o->tbFeedBtn = explode(',', $tbFeedBtn);
+ $o->ContentFontSize = $ContentFontSize;
+ $o->openMode = $openMode;
+ $o->dateTimeFormat = $dateTimeFormat;
+ $o->dateFormat = $dateFormat;
+
+ echo json_encode($o);
+
+ break;
+
+ case "save_important" :
+
+ $id_item = $_POST['id_item'];
+ $typeMark = $_POST['typeMark'];
+
+ $s = 'UPDATE `qo-kregator-items` SET important=\''.$typeMark.'\' WHERE id=\''.$id_item.'\' AND userID=\''.$member_id.'\'';
+
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $o->success = true;
+ echo json_encode($o);
+
+ break;
+
+ case "save_nodes" :
+
+ function update_nodes($nodes, $parent_id=0, $display_order=0) {
+ global $member_id;
+ foreach ($nodes as $id => $children) {
+ $s = 'UPDATE `qo-kregator-dir` SET node=\''.$parent_id.'\', display_order=\''.$display_order.'\' WHERE id=\''.$id.'\' AND userID=\''.$member_id.'\'';
+
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $display_order ++;
+ update_nodes($children, $id, $display_order);
+
+ }
+ }
+
+ update_nodes(json_decode(stripslashes($_POST['nodes'])));
+
+ $o->success = true;
+ echo json_encode($o);
+
+ break;
+
+ case "save_seenDB" :
+
+ require_once("./system/modules/qo-kregator/php/lib.php");
+
+ $id_feed = $_POST['id_feed'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-items` SET seen=\'y\' WHERE id_feed=\''.$id_feed.'\' AND userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ $o = new stdClass;
+ $o->success = true;
+ $o->nodeID = $id_feed;
+ $o->unSeen = 0;
+ $o->total = get_total($id_feed, $member_id);
+ echo json_encode($o);
+
+ break;
+
+ case "save_seenUnseen" :
+
+ require_once("./system/modules/qo-kregator/php/lib.php");
+
+ $id_item = $_POST['id_item'];
+ $typeMark = $_POST['typeMark'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-items` SET seen=\''.$typeMark.'\' WHERE id=\''.$id_item.'\' AND userID=\''.$member_id.'\'';
+
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ // Get info
+ $s = 'SELECT id_feed FROM `qo-kregator-items` WHERE id=\''.$id_item.'\' AND userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+ $a = mysql_fetch_object($r);
+
+ $o->success = true;
+ $o->nodeID = $a->id_feed;
+ $o->unSeen = get_unseen($a->id_feed, $member_id);
+ $o->total = get_total($a->id_feed, $member_id);
+
+ echo json_encode($o);
+
+ break;
+
+ case "set_folder_state" :
+
+ $nodeID = $_POST['nodeID'];
+ $expand = $_POST['expand'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-dir` SET expand=\''.$expand.'\' WHERE id=\''.$nodeID.'\' AND userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ echo "{'success':true}";
+
+ break;
+
+
+ case "set_panelsize_state" :
+
+ $panel = $_POST['panel'];
+ $panelsize = $_POST['panelsize'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-conf` SET '.$panel.'=\''.$panelsize.'\' WHERE userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error().$s."'}");
+
+ echo "{'success':true}";
+
+ break;
+
+ case "set_previewpaneposition_state" :
+
+ $preview_pane = $_POST['preview_pane'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-conf` SET preview_pane=\''.$preview_pane.'\' WHERE userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ echo "{'success':true}";
+
+ break;
+
+ case "set_summary_state" :
+
+ $showSummary = $_POST['showSummary'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-conf` SET showSummary=\''.$showSummary.'\' WHERE userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ echo "{'success':true}";
+
+ break;
+
+ case "set_content_font_size" :
+
+ $content_font_size = $_POST['content_font_size'];
+
+ // Update
+ $s = 'UPDATE `qo-kregator-conf` SET content_font_size=\''.$content_font_size.'\' WHERE userID=\''.$member_id.'\'';
+ mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+
+ echo "{'success':true}";
+
+ break;
+
+ case "update_feed" :
+
+ require_once("./system/modules/qo-kregator/php/lib.php");
+ require_once("./system/modules/qo-kregator/php/simplepie.inc.php");
+
+ if( !isset($_POST['idFeed']) || trim($_POST['idFeed']) == '' ) {
+ $o->success = false;
+ $o->message = 'No feed';
+ echo json_encode($o);
+ exit;
+ }
+
+ $id_feed = trim($_POST['idFeed']);
+ $cache = trim($_POST['cache']);
+
+ $old_nb_items = get_total($id_feed, $member_id);
+
+ // Get URL of the feed
+ $s = 'SELECT url_feed FROM `qo-kregator-dir` WHERE id=\''.$id_feed.'\' AND userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+ $a = mysql_fetch_object($r);
+
+ $url_feed = $a->url_feed;
+
+ $feed = new SimplePie();
+
+ if (get_magic_quotes_gpc()) {
+ $url_feed = stripslashes($url_feed);
+ }
+
+ $feed->set_feed_url($url_feed);
+ $feed->enable_order_by_date(false);
+
+ $feed->set_cache_location('./system/modules/qo-kregator/php/cache/memberID_'.$member_id);
+
+ // Cache
+ if( $cache == 'off' ) {
+ $feed->enable_cache(false);
+ } else {
+ $feed->enable_cache();
+ }
+
+ $feed->init();
+ $feed->handle_content_type();
+
+ if( $feed->error() ) {
+ $o->success = false;
+ $o->message = 'Error when analyze feed. ' . $feed->error();
+ echo json_encode($o);
+ exit;
+ }
+
+ function item_present($url, $titre) {
+ global $id_feed;
+ global $member_id;
+
+ $s = 'SELECT id FROM `qo-kregator-items` WHERE url=\''.mysql_real_escape_string($url).'\' AND titre=\''.mysql_real_escape_string($titre).'\' AND id_feed=\''.$id_feed.'\' AND userID=\''.$member_id.'\'';
+ $r = mysql_query($s) or die("{'success':false, 'msg':'Sql error :".mysql_error()."'}");
+ $nb = mysql_num_rows($r);
+
+ if( $nb == 0 ) { return false; }
+ else { return true; }
+
+ } // item_present
+
+ // Insert new article
+
+ if ($feed->data):
+ $items = $feed->get_items();
+ foreach($items as $item):
+
+ $auteur_1 = $item->get_author();
+
+ if( !isset( $auteur_1 ) ) $auteur = '-';
+ else $auteur = $auteur_1->get_name();
+
+ if( !item_present($item->get_permalink(), $item->get_title()) ) {
+
+ // images relatives
+ $contenu = $item->get_content();
+ $contenu = str_replace('src="/', 'src="'.$feed->get_link(), $contenu);
+
+ // Enclosure management
+
+ $enclosures = $item->get_enclosures();
+ $nb_enclosures = count($enclosures);
+ $nb_real_enclosures = 0;
+ $enclosure_contenu = '';
+
+ if( $nb_enclosures > 0 ) {
+
+ $enclosure_contenu .= '<h1 class="qo-kregator-enclosure">Media</h1><table>';
+
+ foreach($enclosures as $enclosure) {
+
+ $extension = strtolower(substr($enclosure->link, -3));
+
+ if( $enclosure->handler == 'mp3' && $extension == 'mp3' ) {
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('mp3', $enclosure->link, 0, 0, $enclosure->title);
+ } else if( $enclosure->handler == 'fmedia' && $extension == 'flv' ) {
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('flv', $enclosure->link, $enclosure->height, $enclosure->width, $enclosure->title);
+ } else if ( $enclosure->type == 'application/pdf' ) {
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('pdf', $enclosure->link, 0, 0, $enclosure->title, $enclosure->type);
+ } else if ( $enclosure->type != 'application/postscript'
+ && $enclosure->type != 'image/gif'
+ && $enclosure->type != 'image/png'
+ && $enclosure->type != 'image/jpeg'
+ && $enclosure->type != 'image/bmp' ) {
+ $nb_real_enclosures++;
+ $enclosure_contenu .= get_enclosure('other', $enclosure->link, $enclosure->height, $enclosure->width, $enclosure->title, $enclosure->type);
+ }
+ } // End foreach
+
+ $enclosure_contenu .= '</table>';
+
+ } // There is an enclosure
+
+ // Add enclosure
+ if( $nb_real_enclosures != 0 ) {
+ $contenu = $contenu.$enclosure_contenu;
+ }
+
+ $s = '
+ INSERT INTO
+ `qo-kregator-items`
+
+ (id_feed, titre, date, auteur, summary, description, url, userID)
+ VALUES (
+ \''.$id_feed.'\',
+ \''.mysql_real_escape_string($item->get_title()).'\',
+ \''.$item->get_date('Y-m-d H:i:s').'\',
+ \''.mysql_real_escape_string($auteur).'\',
+ \''.summary(mysql_real_escape_string($contenu), '100').'\',
+ \''.mysql_real_escape_string($contenu).'\',
+ \''.$item->get_permalink().'\',
+ \''.$member_id.'\'
+ )';
+
+ if( !mysql_query($s)) {
+ $o->success = false;
+ $o->message = 'Error while inserting an article. Sql error : '.mysql_error();
+ echo json_encode($o);
+ exit;
+ }
+ }
+ endforeach;
+ endif;
+
+ $new_nb_items = get_total($id_feed, $member_id);
+
+ $o->success = true;
+ $o->unseen = get_unseen($id_feed, $member_id);
+ $o->old_nb_item = $old_nb_items;
+ $o->new_nb_item = $new_nb_items;
+
+ echo json_encode($o);
+
+ break;
+
+}
+
+?>
\ No newline at end of file
Added: trunk/qo-kregator/php/simplepie.inc.php
===================================================================
--- trunk/qo-kregator/php/simplepie.inc.php (rev 0)
+++ trunk/qo-kregator/php/simplepie.inc.php 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,13316 @@
+<?php
+/**
+ * SimplePie
+ *
+ * A PHP-Based RSS and Atom Feed Framework.
+ * Takes the hard work out of managing a complete RSS/Atom solution.
+ *
+ * Copyright (c) 2004-2008, Ryan Parman and Geoffrey Sneddon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * * Neither the name of the SimplePie Team nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package SimplePie
+ * @version 1.1.1
+ * @copyright 2004-2008 Ryan Parman, Geoffrey Sneddon
+ * @author Ryan Parman
+ * @author Geoffrey Sneddon
+ * @link http://simplepie.org/ SimplePie
+ * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @todo phpDoc comments
+ */
+
+/**
+ * SimplePie Name
+ */
+define('SIMPLEPIE_NAME', 'SimplePie');
+
+/**
+ * SimplePie Version
+ */
+define('SIMPLEPIE_VERSION', '1.1.1');
+
+/**
+ * SimplePie Build
+ * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
+ */
+define('SIMPLEPIE_BUILD', 20080315205903);
+//define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date: 2008-03-15 15:28:23 -0700 (Sat, 15 Mar 2008) $', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date: 2008-03-15 15:28:23 -0700 (Sat, 15 Mar 2008) $', 7, 25)) : filemtime(__FILE__)));
+
+/**
+ * SimplePie Website URL
+ */
+define('SIMPLEPIE_URL', 'http://simplepie.org');
+
+/**
+ * SimplePie Useragent
+ * @see SimplePie::set_useragent()
+ */
+define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
+
+/**
+ * SimplePie Linkback
+ */
+define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
+
+/**
+ * No Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_NONE', 0);
+
+/**
+ * Feed Link Element Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
+
+/**
+ * Local Feed Extension Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
+
+/**
+ * Local Feed Body Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
+
+/**
+ * Remote Feed Extension Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
+
+/**
+ * Remote Feed Body Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
+
+/**
+ * All Feed Autodiscovery
+ * @see SimplePie::set_autodiscovery_level()
+ */
+define('SIMPLEPIE_LOCATOR_ALL', 31);
+
+/**
+ * No known feed type
+ */
+define('SIMPLEPIE_TYPE_NONE', 0);
+
+/**
+ * RSS 0.90
+ */
+define('SIMPLEPIE_TYPE_RSS_090', 1);
+
+/**
+ * RSS 0.91 (Netscape)
+ */
+define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
+
+/**
+ * RSS 0.91 (Userland)
+ */
+define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
+
+/**
+ * RSS 0.91 (both Netscape and Userland)
+ */
+define('SIMPLEPIE_TYPE_RSS_091', 6);
+
+/**
+ * RSS 0.92
+ */
+define('SIMPLEPIE_TYPE_RSS_092', 8);
+
+/**
+ * RSS 0.93
+ */
+define('SIMPLEPIE_TYPE_RSS_093', 16);
+
+/**
+ * RSS 0.94
+ */
+define('SIMPLEPIE_TYPE_RSS_094', 32);
+
+/**
+ * RSS 1.0
+ */
+define('SIMPLEPIE_TYPE_RSS_10', 64);
+
+/**
+ * RSS 2.0
+ */
+define('SIMPLEPIE_TYPE_RSS_20', 128);
+
+/**
+ * RDF-based RSS
+ */
+define('SIMPLEPIE_TYPE_RSS_RDF', 65);
+
+/**
+ * Non-RDF-based RSS (truly intended as syndication format)
+ */
+define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
+
+/**
+ * All RSS
+ */
+define('SIMPLEPIE_TYPE_RSS_ALL', 255);
+
+/**
+ * Atom 0.3
+ */
+define('SIMPLEPIE_TYPE_ATOM_03', 256);
+
+/**
+ * Atom 1.0
+ */
+define('SIMPLEPIE_TYPE_ATOM_10', 512);
+
+/**
+ * All Atom
+ */
+define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
+
+/**
+ * All feed types
+ */
+define('SIMPLEPIE_TYPE_ALL', 1023);
+
+/**
+ * No construct
+ */
+define('SIMPLEPIE_CONSTRUCT_NONE', 0);
+
+/**
+ * Text construct
+ */
+define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
+
+/**
+ * HTML construct
+ */
+define('SIMPLEPIE_CONSTRUCT_HTML', 2);
+
+/**
+ * XHTML construct
+ */
+define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
+
+/**
+ * base64-encoded construct
+ */
+define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
+
+/**
+ * IRI construct
+ */
+define('SIMPLEPIE_CONSTRUCT_IRI', 16);
+
+/**
+ * A construct that might be HTML
+ */
+define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
+
+/**
+ * All constructs
+ */
+define('SIMPLEPIE_CONSTRUCT_ALL', 63);
+
+/**
+ * PCRE for HTML attributes
+ */
+define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
+
+/**
+ * PCRE for XML attributes
+ */
+define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
+
+/**
+ * XML Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
+
+/**
+ * Atom 1.0 Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
+
+/**
+ * Atom 0.3 Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
+
+/**
+ * RDF Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
+
+/**
+ * RSS 0.90 Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
+
+/**
+ * RSS 1.0 Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
+
+/**
+ * RSS 1.0 Content Module Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
+
+/**
+ * DC 1.0 Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
+
+/**
+ * DC 1.1 Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
+
+/**
+ * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
+
+/**
+ * GeoRSS Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
+
+/**
+ * Media RSS Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
+
+/**
+ * Wrong Media RSS Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
+
+/**
+ * iTunes RSS Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
+
+/**
+ * XHTML Namespace
+ */
+define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
+
+/**
+ * IANA Link Relations Registry
+ */
+define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
+
+/**
+ * Whether we're running on PHP5
+ */
+define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
+
+/**
+ * No file source
+ */
+define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
+
+/**
+ * Remote file source
+ */
+define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
+
+/**
+ * Local file source
+ */
+define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
+
+/**
+ * fsockopen() file source
+ */
+define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
+
+/**
+ * cURL file source
+ */
+define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
+
+/**
+ * file_get_contents() file source
+ */
+define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
+
+/**
+ * SimplePie
+ *
+ * @package SimplePie
+ * @version "Razzleberry"
+ * @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
+ * @author Ryan Parman
+ * @author Geoffrey Sneddon
+ * @todo Option for type of fetching (cache, not modified header, fetch, etc.)
+ */
+class SimplePie
+{
+ /**
+ * @var array Raw data
+ * @access private
+ */
+ var $data = array();
+
+ /**
+ * @var mixed Error string
+ * @access private
+ */
+ var $error;
+
+ /**
+ * @var object Instance of SimplePie_Sanitize (or other class)
+ * @see SimplePie::set_sanitize_class()
+ * @access private
+ */
+ var $sanitize;
+
+ /**
+ * @var string SimplePie Useragent
+ * @see SimplePie::set_useragent()
+ * @access private
+ */
+ var $useragent = SIMPLEPIE_USERAGENT;
+
+ /**
+ * @var string Feed URL
+ * @see SimplePie::set_feed_url()
+ * @access private
+ */
+ var $feed_url;
+
+ /**
+ * @var object Instance of SimplePie_File to use as a feed
+ * @see SimplePie::set_file()
+ * @access private
+ */
+ var $file;
+
+ /**
+ * @var string Raw feed data
+ * @see SimplePie::set_raw_data()
+ * @access private
+ */
+ var $raw_data;
+
+ /**
+ * @var int Timeout for fetching remote files
+ * @see SimplePie::set_timeout()
+ * @access private
+ */
+ var $timeout = 10;
+
+ /**
+ * @var bool Forces fsockopen() to be used for remote files instead
+ * of cURL, even if a new enough version is installed
+ * @see SimplePie::force_fsockopen()
+ * @access private
+ */
+ var $force_fsockopen = false;
+
+ /**
+ * @var bool Force the given data/URL to be treated as a feed no matter what
+ * it appears like
+ * @see SimplePie::force_feed()
+ * @access private
+ */
+ var $force_feed = false;
+
+ /**
+ * @var bool Enable/Disable XML dump
+ * @see SimplePie::enable_xml_dump()
+ * @access private
+ */
+ var $xml_dump = false;
+
+ /**
+ * @var bool Enable/Disable Caching
+ * @see SimplePie::enable_cache()
+ * @access private
+ */
+ var $cache = true;
+
+ /**
+ * @var int Cache duration (in seconds)
+ * @see SimplePie::set_cache_duration()
+ * @access private
+ */
+ var $cache_duration = 3600;
+
+ /**
+ * @var int Auto-discovery cache duration (in seconds)
+ * @see SimplePie::set_autodiscovery_cache_duration()
+ * @access private
+ */
+ var $autodiscovery_cache_duration = 604800; // 7 Days.
+
+ /**
+ * @var string Cache location (relative to executing script)
+ * @see SimplePie::set_cache_location()
+ * @access private
+ */
+ var $cache_location = './cache';
+
+ /**
+ * @var string Function that creates the cache filename
+ * @see SimplePie::set_cache_name_function()
+ * @access private
+ */
+ var $cache_name_function = 'sha1';
+
+ /**
+ * @var bool Reorder feed by date descending
+ * @see SimplePie::enable_order_by_date()
+ * @access private
+ */
+ var $order_by_date = true;
+
+ /**
+ * @var mixed Force input encoding to be set to the follow value
+ * (false, or anything type-cast to false, disables this feature)
+ * @see SimplePie::set_input_encoding()
+ * @access private
+ */
+ var $input_encoding = false;
+
+ /**
+ * @var int Feed Autodiscovery Level
+ * @see SimplePie::set_autodiscovery_level()
+ * @access private
+ */
+ var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
+
+ /**
+ * @var string Class used for caching feeds
+ * @see SimplePie::set_cache_class()
+ * @access private
+ */
+ var $cache_class = 'SimplePie_Cache';
+
+ /**
+ * @var string Class used for locating feeds
+ * @see SimplePie::set_locator_class()
+ * @access private
+ */
+ var $locator_class = 'SimplePie_Locator';
+
+ /**
+ * @var string Class used for parsing feeds
+ * @see SimplePie::set_parser_class()
+ * @access private
+ */
+ var $parser_class = 'SimplePie_Parser';
+
+ /**
+ * @var string Class used for fetching feeds
+ * @see SimplePie::set_file_class()
+ * @access private
+ */
+ var $file_class = 'SimplePie_File';
+
+ /**
+ * @var string Class used for items
+ * @see SimplePie::set_item_class()
+ * @access private
+ */
+ var $item_class = 'SimplePie_Item';
+
+ /**
+ * @var string Class used for authors
+ * @see SimplePie::set_author_class()
+ * @access private
+ */
+ var $author_class = 'SimplePie_Author';
+
+ /**
+ * @var string Class used for categories
+ * @see SimplePie::set_category_class()
+ * @access private
+ */
+ var $category_class = 'SimplePie_Category';
+
+ /**
+ * @var string Class used for enclosures
+ * @see SimplePie::set_enclosures_class()
+ * @access private
+ */
+ var $enclosure_class = 'SimplePie_Enclosure';
+
+ /**
+ * @var string Class used for Media RSS <media:text> captions
+ * @see SimplePie::set_caption_class()
+ * @access private
+ */
+ var $caption_class = 'SimplePie_Caption';
+
+ /**
+ * @var string Class used for Media RSS <media:copyright>
+ * @see SimplePie::set_copyright_class()
+ * @access private
+ */
+ var $copyright_class = 'SimplePie_Copyright';
+
+ /**
+ * @var string Class used for Media RSS <media:credit>
+ * @see SimplePie::set_credit_class()
+ * @access private
+ */
+ var $credit_class = 'SimplePie_Credit';
+
+ /**
+ * @var string Class used for Media RSS <media:rating>
+ * @see SimplePie::set_rating_class()
+ * @access private
+ */
+ var $rating_class = 'SimplePie_Rating';
+
+ /**
+ * @var string Class used for Media RSS <media:restriction>
+ * @see SimplePie::set_restriction_class()
+ * @access private
+ */
+ var $restriction_class = 'SimplePie_Restriction';
+
+ /**
+ * @var string Class used for content-type sniffing
+ * @see SimplePie::set_content_type_sniffer_class()
+ * @access private
+ */
+ var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
+
+ /**
+ * @var string Class used for item sources.
+ * @see SimplePie::set_source_class()
+ * @access private
+ */
+ var $source_class = 'SimplePie_Source';
+
+ /**
+ * @var mixed Set javascript query string parameter (false, or
+ * anything type-cast to false, disables this feature)
+ * @see SimplePie::set_javascript()
+ * @access private
+ */
+ var $javascript = 'js';
+
+ /**
+ * @var int Maximum number of feeds to check with autodiscovery
+ * @see SimplePie::set_max_checked_feeds()
+ * @access private
+ */
+ var $max_checked_feeds = 10;
+
+ /**
+ * @var string Web-accessible path to the handler_favicon.php file.
+ * @see SimplePie::set_favicon_handler()
+ * @access private
+ */
+ var $favicon_handler = '';
+
+ /**
+ * @var string Web-accessible path to the handler_image.php file.
+ * @see SimplePie::set_image_handler()
+ * @access private
+ */
+ var $image_handler = '';
+
+ /**
+ * @var array Stores the URLs when multiple feeds are being initialized.
+ * @see SimplePie::set_feed_url()
+ * @access private
+ */
+ var $multifeed_url = array();
+
+ /**
+ * @var array Stores SimplePie objects when multiple feeds initialized.
+ * @access private
+ */
+ var $multifeed_objects = array();
+
+ /**
+ * @var array Stores the get_object_vars() array for use with multifeeds.
+ * @see SimplePie::set_feed_url()
+ * @access private
+ */
+ var $config_settings = null;
+
+ /**
+ * @var integer Stores the number of items to return per-feed with multifeeds.
+ * @see SimplePie::set_item_limit()
+ * @access private
+ */
+ var $item_limit = 0;
+
+ /**
+ * @var array Stores the default attributes to be stripped by strip_attributes().
+ * @see SimplePie::strip_attributes()
+ * @access private
+ */
+ var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
+
+ /**
+ * @var array Stores the default tags to be stripped by strip_htmltags().
+ * @see SimplePie::strip_htmltags()
+ * @access private
+ */
+ var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
+
+ /**
+ * The SimplePie class contains feed level data and options
+ *
+ * There are two ways that you can create a new SimplePie object. The first
+ * is by passing a feed URL as a parameter to the SimplePie constructor
+ * (as well as optionally setting the cache location and cache expiry). This
+ * will initialise the whole feed with all of the default settings, and you
+ * can begin accessing methods and properties immediately.
+ *
+ * The second way is to create the SimplePie object with no parameters
+ * at all. This will enable you to set configuration options. After setting
+ * them, you must initialise the feed using $feed->init(). At that point the
+ * object's methods and properties will be available to you. This format is
+ * what is used throughout this documentation.
+ *
+ * @access public
+ * @since 1.0 Preview Release
+ * @param string $feed_url This is the URL you want to parse.
+ * @param string $cache_location This is where you want the cache to be stored.
+ * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
+ */
+ function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
+ {
+ // Other objects, instances created here so we can set options on them
+ $this->sanitize =& new SimplePie_Sanitize;
+
+ // Set options if they're passed to the constructor
+ if ($cache_location !== null)
+ {
+ $this->set_cache_location($cache_location);
+ }
+
+ if ($cache_duration !== null)
+ {
+ $this->set_cache_duration($cache_duration);
+ }
+
+ // Only init the script if we're passed a feed URL
+ if ($feed_url !== null)
+ {
+ $this->set_feed_url($feed_url);
+ $this->init();
+ }
+ }
+
+ /**
+ * Used for converting object to a string
+ */
+ function __toString()
+ {
+ return md5(serialize($this->data));
+ }
+
+ /**
+ * Remove items that link back to this before destroying this object
+ */
+ function __destruct()
+ {
+ if (!empty($this->data['items']))
+ {
+ foreach ($this->data['items'] as $item)
+ {
+ $item->__destruct();
+ }
+ unset($this->data['items']);
+ }
+ if (!empty($this->data['ordered_items']))
+ {
+ foreach ($this->data['ordered_items'] as $item)
+ {
+ $item->__destruct();
+ }
+ unset($this->data['ordered_items']);
+ }
+ }
+
+ /**
+ * Force the given data/URL to be treated as a feed no matter what it
+ * appears like
+ *
+ * @access public
+ * @since 1.1
+ * @param bool $enable Force the given data/URL to be treated as a feed
+ */
+ function force_feed($enable = false)
+ {
+ $this->force_feed = (bool) $enable;
+ }
+
+ /**
+ * This is the URL of the feed you want to parse.
+ *
+ * This allows you to enter the URL of the feed you want to parse, or the
+ * website you want to try to use auto-discovery on. This takes priority
+ * over any set raw data.
+ *
+ * You can set multiple feeds to mash together by passing an array instead
+ * of a string for the $url. Remember that with each additional feed comes
+ * additional processing and resources.
+ *
+ * @access public
+ * @since 1.0 Preview Release
+ * @param mixed $url This is the URL (or array of URLs) that you want to parse.
+ * @see SimplePie::set_raw_data()
+ */
+ function set_feed_url($url)
+ {
+ if (is_array($url))
+ {
+ $this->multifeed_url = array();
+ foreach ($url as $value)
+ {
+ $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
+ }
+ }
+ else
+ {
+ $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
+ }
+ }
+
+ /**
+ * Provides an instance of SimplePie_File to use as a feed
+ *
+ * @access public
+ * @param object &$file Instance of SimplePie_File (or subclass)
+ * @return bool True on success, false on failure
+ */
+ function set_file(&$file)
+ {
+ if (is_a($file, 'SimplePie_File'))
+ {
+ $this->feed_url = $file->url;
+ $this->file =& $file;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to use a string of RSS/Atom data instead of a remote feed.
+ *
+ * If you have a feed available as a string in PHP, you can tell SimplePie
+ * to parse that data string instead of a remote feed. Any set feed URL
+ * takes precedence.
+ *
+ * @access public
+ * @since 1.0 Beta 3
+ * @param string $data RSS or Atom data as a string.
+ * @see SimplePie::set_feed_url()
+ */
+ function set_raw_data($data)
+ {
+ $this->raw_data = $data;
+ }
+
+ /**
+ * Allows you to override the default timeout for fetching remote feeds.
+ *
+ * This allows you to change the maximum time the feed's server to respond
+ * and send the feed back.
+ *
+ * @access public
+ * @since 1.0 Beta 3
+ * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
+ */
+ function set_timeout($timeout = 10)
+ {
+ $this->timeout = (int) $timeout;
+ }
+
+ /**
+ * Forces SimplePie to use fsockopen() instead of the preferred cURL
+ * functions.
+ *
+ * @access public
+ * @since 1.0 Beta 3
+ * @param bool $enable Force fsockopen() to be used
+ */
+ function force_fsockopen($enable = false)
+ {
+ $this->force_fsockopen = (bool) $enable;
+ }
+
+ /**
+ * Outputs the raw XML content of the feed, after it has gone through
+ * SimplePie's filters.
+ *
+ * Used only for debugging, this function will output the XML content as
+ * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
+ * before trying to parse it. Many parts of the feed are re-written in
+ * memory, and in the end, you have a parsable feed. XML dump shows you the
+ * actual XML that SimplePie tries to parse, which may or may not be very
+ * different from the original feed.
+ *
+ * @access public
+ * @since 1.0 Preview Release
+ * @param bool $enable Enable XML dump
+ */
+ function enable_xml_dump($enable = false)
+ {
+ $this->xml_dump = (bool) $enable;
+ }
+
+ /**
+ * Enables/disables caching in SimplePie.
+ *
+ * This option allows you to disable caching all-together in SimplePie.
+ * However, disabling the cache can lead to longer load times.
+ *
+ * @access public
+ * @since 1.0 Preview Release
+ * @param bool $enable Enable caching
+ */
+ function enable_cache($enable = true)
+ {
+ $this->cache = (bool) $enable;
+ }
+
+ /**
+ * Set the length of time (in seconds) that the contents of a feed
+ * will be cached.
+ *
+ * @access public
+ * @param int $seconds The feed content cache duration.
+ */
+ function set_cache_duration($seconds = 3600)
+ {
+ $this->cache_duration = (int) $seconds;
+ }
+
+ /**
+ * Set the length of time (in seconds) that the autodiscovered feed
+ * URL will be cached.
+ *
+ * @access public
+ * @param int $seconds The autodiscovered feed URL cache duration.
+ */
+ function set_autodiscovery_cache_duration($seconds = 604800)
+ {
+ $this->autodiscovery_cache_duration = (int) $seconds;
+ }
+
+ /**
+ * Set the file system location where the cached files should be stored.
+ *
+ * @access public
+ * @param string $location The file system location.
+ */
+ function set_cache_location($location = './cache')
+ {
+ $this->cache_location = (string) $location;
+ }
+
+ /**
+ * Determines whether feed items should be sorted into reverse chronological order.
+ *
+ * @access public
+ * @param bool $enable Sort as reverse chronological order.
+ */
+ function enable_order_by_date($enable = true)
+ {
+ $this->order_by_date = (bool) $enable;
+ }
+
+ /**
+ * Allows you to override the character encoding reported by the feed.
+ *
+ * @access public
+ * @param string $encoding Character encoding.
+ */
+ function set_input_encoding($encoding = false)
+ {
+ if ($encoding)
+ {
+ $this->input_encoding = (string) $encoding;
+ }
+ else
+ {
+ $this->input_encoding = false;
+ }
+ }
+
+ /**
+ * Set how much feed autodiscovery to do
+ *
+ * @access public
+ * @see SIMPLEPIE_LOCATOR_NONE
+ * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
+ * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
+ * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
+ * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
+ * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
+ * @see SIMPLEPIE_LOCATOR_ALL
+ * @param int $level Feed Autodiscovery Level (level can be a
+ * combination of the above constants, see bitwise OR operator)
+ */
+ function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
+ {
+ $this->autodiscovery = (int) $level;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for caching.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_cache_class($class = 'SimplePie_Cache')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
+ {
+ $this->cache_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for auto-discovery.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_locator_class($class = 'SimplePie_Locator')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
+ {
+ $this->locator_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for XML parsing.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_parser_class($class = 'SimplePie_Parser')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
+ {
+ $this->parser_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for remote file fetching.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_file_class($class = 'SimplePie_File')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
+ {
+ $this->file_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for data sanitization.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_sanitize_class($class = 'SimplePie_Sanitize')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
+ {
+ $this->sanitize =& new $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for handling feed items.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_item_class($class = 'SimplePie_Item')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
+ {
+ $this->item_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for handling author data.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_author_class($class = 'SimplePie_Author')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
+ {
+ $this->author_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for handling category data.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_category_class($class = 'SimplePie_Category')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
+ {
+ $this->category_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for feed enclosures.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_enclosure_class($class = 'SimplePie_Enclosure')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
+ {
+ $this->enclosure_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for <media:text> captions
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_caption_class($class = 'SimplePie_Caption')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
+ {
+ $this->caption_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for <media:copyright>
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_copyright_class($class = 'SimplePie_Copyright')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
+ {
+ $this->copyright_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for <media:credit>
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_credit_class($class = 'SimplePie_Credit')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
+ {
+ $this->credit_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for <media:rating>
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_rating_class($class = 'SimplePie_Rating')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
+ {
+ $this->rating_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for <media:restriction>
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_restriction_class($class = 'SimplePie_Restriction')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
+ {
+ $this->restriction_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses for content-type sniffing.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
+ {
+ $this->content_type_sniffer_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to change which class SimplePie uses item sources.
+ * Useful when you are overloading or extending SimplePie's default classes.
+ *
+ * @access public
+ * @param string $class Name of custom class.
+ * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+ */
+ function set_source_class($class = 'SimplePie_Source')
+ {
+ if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
+ {
+ $this->source_class = $class;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allows you to override the default user agent string.
+ *
+ * @access public
+ * @param string $ua New user agent string.
+ */
+ function set_useragent($ua = SIMPLEPIE_USERAGENT)
+ {
+ $this->useragent = (string) $ua;
+ }
+
+ /**
+ * Set callback function to create cache filename with
+ *
+ * @access public
+ * @param mixed $function Callback function
+ */
+ function set_cache_name_function($function = 'md5')
+ {
+ if (is_callable($function))
+ {
+ $this->cache_name_function = $function;
+ }
+ }
+
+ /**
+ * Set javascript query string parameter
+ *
+ * @access public
+ * @param mixed $get Javascript query string parameter
+ */
+ function set_javascript($get = 'js')
+ {
+ if ($get)
+ {
+ $this->javascript = (string) $get;
+ }
+ else
+ {
+ $this->javascript = false;
+ }
+ }
+
+ /**
+ * Set options to make SP as fast as possible. Forgoes a
+ * substantial amount of data sanitization in favor of speed.
+ *
+ * @access public
+ * @param bool $set Whether to set them or not
+ */
+ function set_stupidly_fast($set = false)
+ {
+ if ($set)
+ {
+ $this->enable_order_by_date(false);
+ $this->remove_div(false);
+ $this->strip_comments(false);
+ $this->strip_htmltags(false);
+ $this->strip_attributes(false);
+ $this->set_image_handler(false);
+ }
+ }
+
+ /**
+ * Set maximum number of feeds to check with autodiscovery
+ *
+ * @access public
+ * @param int $max Maximum number of feeds to check
+ */
+ function set_max_checked_feeds($max = 10)
+ {
+ $this->max_checked_feeds = (int) $max;
+ }
+
+ function remove_div($enable = true)
+ {
+ $this->sanitize->remove_div($enable);
+ }
+
+ function strip_htmltags($tags = '', $encode = null)
+ {
+ if ($tags === '')
+ {
+ $tags = $this->strip_htmltags;
+ }
+ $this->sanitize->strip_htmltags($tags);
+ if ($encode !== null)
+ {
+ $this->sanitize->encode_instead_of_strip($tags);
+ }
+ }
+
+ function encode_instead_of_strip($enable = true)
+ {
+ $this->sanitize->encode_instead_of_strip($enable);
+ }
+
+ function strip_attributes($attribs = '')
+ {
+ if ($attribs === '')
+ {
+ $attribs = $this->strip_attributes;
+ }
+ $this->sanitize->strip_attributes($attribs);
+ }
+
+ function set_output_encoding($encoding = 'UTF-8')
+ {
+ $this->sanitize->set_output_encoding($encoding);
+ }
+
+ function strip_comments($strip = false)
+ {
+ $this->sanitize->strip_comments($strip);
+ }
+
+ /**
+ * Set element/attribute key/value pairs of HTML attributes
+ * containing URLs that need to be resolved relative to the feed
+ *
+ * @access public
+ * @since 1.0
+ * @param array $element_attribute Element/attribute key/value pairs
+ */
+ function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
+ {
+ $this->sanitize->set_url_replacements($element_attribute);
+ }
+
+ /**
+ * Set the handler to enable the display of cached favicons.
+ *
+ * @access public
+ * @param str $page Web-accessible path to the handler_favicon.php file.
+ * @param str $qs The query string that the value should be passed to.
+ */
+ function set_favicon_handler($page = false, $qs = 'i')
+ {
+ if ($page != false)
+ {
+ $this->favicon_handler = $page . '?' . $qs . '=';
+ }
+ else
+ {
+ $this->favicon_handler = '';
+ }
+ }
+
+ /**
+ * Set the handler to enable the display of cached images.
+ *
+ * @access public
+ * @param str $page Web-accessible path to the handler_image.php file.
+ * @param str $qs The query string that the value should be passed to.
+ */
+ function set_image_handler($page = false, $qs = 'i')
+ {
+ if ($page != false)
+ {
+ $this->sanitize->set_image_handler($page . '?' . $qs . '=');
+ }
+ else
+ {
+ $this->image_handler = '';
+ }
+ }
+
+ /**
+ * Set the limit for items returned per-feed with multifeeds.
+ *
+ * @access public
+ * @param integer $limit The maximum number of items to return.
+ */
+ function set_item_limit($limit = 0)
+ {
+ $this->item_limit = (int) $limit;
+ }
+
+ function init()
+ {
+ if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
+ {
+ return false;
+ }
+ if (isset($_GET[$this->javascript]))
+ {
+ if (function_exists('ob_gzhandler'))
+ {
+ ob_start('ob_gzhandler');
+ }
+ header('Content-type: text/javascript; charset: UTF-8');
+ header('Cache-Control: must-revalidate');
+ header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
+ ?>
+function embed_odeo(link) {
+ document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
+}
+
+function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
+ if (placeholder != '') {
+ document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
+ }
+ else {
+ document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
+ }
+}
+
+function embed_flash(bgcolor, width, height, link, loop, type) {
+ document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
+}
+
+function embed_flv(width, height, link, placeholder, loop, player) {
+ document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
+}
+
+function embed_wmedia(width, height, link) {
+ document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
+}
+ <?php
+ exit;
+ }
+
+ // Pass whatever was set with config options over to the sanitizer.
+ $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
+ $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
+
+ if ($this->feed_url !== null || $this->raw_data !== null)
+ {
+ $this->data = array();
+ $this->multifeed_objects = array();
+ $cache = false;
+
+ if ($this->feed_url !== null)
+ {
+ $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
+ // Decide whether to enable caching
+ if ($this->cache && $parsed_feed_url['scheme'] !== '')
+ {
+ $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
+ }
+ // If it's enabled and we don't want an XML dump, use the cache
+ if ($cache && !$this->xml_dump)
+ {
+ // Load the Cache
+ $this->data = $cache->load();
+ if (!empty($this->data))
+ {
+ // If the cache is for an outdated build of SimplePie
+ if (!isset($this->data['build']) || $this->data['build'] != SIMPLEPIE_BUILD)
+ {
+ $cache->unlink();
+ $this->data = array();
+ }
+ // If we've hit a collision just rerun it with caching disabled
+ elseif (isset($this->data['url']) && $this->data['url'] != $this->feed_url)
+ {
+ $cache = false;
+ $this->data = array();
+ }
+ // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
+ elseif (isset($this->data['feed_url']))
+ {
+ // If the autodiscovery cache is still valid use it.
+ if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
+ {
+ // Do not need to do feed autodiscovery yet.
+ if ($this->data['feed_url'] == $this->data['url'])
+ {
+ $cache->unlink();
+ $this->data = array();
+ }
+ else
+ {
+ $this->set_feed_url($this->data['feed_url']);
+ return $this->init();
+ }
+ }
+ }
+ // Check if the cache has been updated
+ elseif ($cache->mtime() + $this->cache_duration < time())
+ {
+ // If we have last-modified and/or etag set
+ if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
+ {
+ $headers = array();
+ if (isset($this->data['headers']['last-modified']))
+ {
+ $headers['if-modified-since'] = $this->data['headers']['last-modified'];
+ }
+ if (isset($this->data['headers']['etag']))
+ {
+ $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
+ }
+ $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
+ if ($file->success)
+ {
+ if ($file->status_code == 304)
+ {
+ $cache->touch();
+ return true;
+ }
+ else
+ {
+ $headers = $file->headers;
+ }
+ }
+ else
+ {
+ unset($file);
+ }
+ }
+ }
+ // If the cache is still valid, just return true
+ else
+ {
+ return true;
+ }
+ }
+ // If the cache is empty, delete it
+ else
+ {
+ $cache->unlink();
+ $this->data = array();
+ }
+ }
+ // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
+ if (!isset($file))
+ {
+ if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->feed_url)
+ {
+ $file =& $this->file;
+ }
+ else
+ {
+ $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
+ }
+ }
+ // If the file connection has an error, set SimplePie::error to that and quit
+ if (!$file->success)
+ {
+ $this->error = $file->error;
+ if (!empty($this->data))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!$this->force_feed)
+ {
+ // Check if the supplied URL is a feed, if it isn't, look for it.
+ $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
+ if (!$locate->is_feed($file))
+ {
+ // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
+ unset($file);
+ if ($file = $locate->find($this->autodiscovery))
+ {
+ if ($cache)
+ {
+ $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
+ if (!$cache->save($this))
+ {
+ trigger_error("$cache->name is not writeable", E_USER_WARNING);
+ }
+ $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
+ }
+ $this->feed_url = $file->url;
+ }
+ else
+ {
+ $this->error = "A feed could not be found at $this->feed_url";
+ SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
+ return false;
+ }
+ }
+ $locate = null;
+ }
+
+ $headers = $file->headers;
+ $data = $file->body;
+ $sniffer = new $this->content_type_sniffer_class($file);
+ $sniffed = $sniffer->get_type();
+ }
+ else
+ {
+ $data = $this->raw_data;
+ }
+
+ // Set up array of possible encodings
+ $encodings = array();
+
+ // First check to see if input has been overridden.
+ if ($this->input_encoding !== false)
+ {
+ $encodings[] = $this->input_encoding;
+ }
+
+ $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
+ $text_types = array('text/xml', 'text/xml-external-parsed-entity');
+
+ // RFC 3023 (only applies to sniffed content)
+ if (isset($sniffed))
+ {
+ if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
+ {
+ if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
+ {
+ $encodings[] = strtoupper($charset[1]);
+ }
+ $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
+ $encodings[] = 'UTF-8';
+ }
+ elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
+ {
+ if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
+ {
+ $encodings[] = $charset[1];
+ }
+ $encodings[] = 'US-ASCII';
+ }
+ // Text MIME-type default
+ elseif (substr($sniffed, 0, 5) === 'text/')
+ {
+ $encodings[] = 'US-ASCII';
+ }
+ }
+
+ // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
+ $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
+ $encodings[] = 'UTF-8';
+ $encodings[] = 'ISO-8859-1';
+
+ // There's no point in trying an encoding twice
+ $encodings = array_unique($encodings);
+
+ // If we want the XML, just output that with the most likely encoding and quit
+ if ($this->xml_dump)
+ {
+ header('Content-type: text/xml; charset=' . $encodings[0]);
+ echo $data;
+ exit;
+ }
+
+ // Loop through each possible encoding, till we return something, or run out of possibilities
+ foreach ($encodings as $encoding)
+ {
+ // Change the encoding to UTF-8 (as we always use UTF-8 internally)
+ $utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8');
+
+ // Create new parser
+ $parser =& new $this->parser_class();
+
+ // If it's parsed fine
+ if ($parser->parse($utf8_data, 'UTF-8'))
+ {
+ $this->data = $parser->get_data();
+ if (isset($this->data['child']))
+ {
+ if (isset($headers))
+ {
+ $this->data['headers'] = $headers;
+ }
+ $this->data['build'] = SIMPLEPIE_BUILD;
+
+ // Cache the file if caching is enabled
+ if ($cache && !$cache->save($this))
+ {
+ trigger_error("$cache->name is not writeable", E_USER_WARNING);
+ }
+ return true;
+ }
+ else
+ {
+ $this->error = "A feed could not be found at $this->feed_url";
+ SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
+ return false;
+ }
+ }
+ }
+ // We have an error, just set SimplePie::error to it and quit
+ $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
+ SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
+ return false;
+ }
+ elseif (!empty($this->multifeed_url))
+ {
+ $i = 0;
+ $success = 0;
+ $this->multifeed_objects = array();
+ foreach ($this->multifeed_url as $url)
+ {
+ if (SIMPLEPIE_PHP5)
+ {
+ // This keyword needs to defy coding standards for PHP4 compatibility
+ $this->multifeed_objects[$i] = clone($this);
+ }
+ else
+ {
+ $this->multifeed_objects[$i] = $this;
+ }
+ $this->multifeed_objects[$i]->set_feed_url($url);
+ $success |= $this->multifeed_objects[$i]->init();
+ $i++;
+ }
+ return (bool) $success;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Return the error message for the occured error
+ *
+ * @access public
+ * @return string Error message
+ */
+ function error()
+ {
+ return $this->error;
+ }
+
+ function get_encoding()
+ {
+ return $this->sanitize->output_encoding;
+ }
+
+ function handle_content_type($mime = 'text/html')
+ {
+ if (!headers_sent())
+ {
+ $header = "Content-type: $mime;";
+ if ($this->get_encoding())
+ {
+ $header .= ' charset=' . $this->get_encoding();
+ }
+ else
+ {
+ $header .= ' charset=UTF-8';
+ }
+ header($header);
+ }
+ }
+
+ function get_type()
+ {
+ if (!isset($this->data['type']))
+ {
+ $this->data['type'] = SIMPLEPIE_TYPE_ALL;
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
+ {
+ $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
+ }
+ elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
+ {
+ $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
+ }
+ elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
+ {
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
+ || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
+ || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
+ || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
+ {
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
+ }
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
+ || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
+ || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
+ || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
+ {
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
+ }
+ }
+ elseif (isset($this->data['child']['']['rss']))
+ {
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
+ if (isset($this->data['child']['']['rss'][0]['attribs']['']['version']))
+ {
+ switch (trim($this->data['child']['']['rss'][0]['attribs']['']['version']))
+ {
+ case '0.91':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
+ if (isset($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
+ {
+ switch (trim($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
+ {
+ case '0':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
+ break;
+
+ case '24':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
+ break;
+ }
+ }
+ break;
+
+ case '0.92':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
+ break;
+
+ case '0.93':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
+ break;
+
+ case '0.94':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
+ break;
+
+ case '2.0':
+ $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
+ break;
+ }
+ }
+ }
+ else
+ {
+ $this->data['type'] = SIMPLEPIE_TYPE_NONE;
+ }
+ }
+ return $this->data['type'];
+ }
+
+ /**
+ * Returns the URL for the favicon of the feed's website.
+ *
+ * @todo Cache atom:icon
+ * @access public
+ * @since 1.0
+ */
+ function get_favicon()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
+ {
+ $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
+
+ if ($this->cache && $this->favicon_handler)
+ {
+ $favicon_filename = call_user_func($this->cache_name_function, $favicon);
+ $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
+
+ if ($cache->load())
+ {
+ return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
+
+ if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
+ {
+ $sniffer = new $this->content_type_sniffer_class($file);
+ if (substr($sniffer->get_type(), 0, 6) === 'image/')
+ {
+ if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
+ {
+ return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ trigger_error("$cache->name is not writeable", E_USER_WARNING);
+ return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @todo If we have a perm redirect we should return the new URL
+ * @todo When we make the above change, let's support <itunes:new-feed-url> as well
+ * @todo Also, |atom:link|@rel=self
+ */
+ function subscribe_url()
+ {
+ if ($this->feed_url !== null)
+ {
+ return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function subscribe_feed()
+ {
+ if ($this->feed_url !== null)
+ {
+ return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function subscribe_outlook()
+ {
+ if ($this->feed_url !== null)
+ {
+ return 'outlook' . $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function subscribe_podcast()
+ {
+ if ($this->feed_url !== null)
+ {
+ return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function subscribe_itunes()
+ {
+ if ($this->feed_url !== null)
+ {
+ return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Creates the subscribe_* methods' return data
+ *
+ * @access private
+ * @param string $feed_url String to prefix to the feed URL
+ * @param string $site_url String to prefix to the site URL (and
+ * suffix to the feed URL)
+ * @return mixed URL if feed exists, false otherwise
+ */
+ function subscribe_service($feed_url, $site_url = null)
+ {
+ if ($this->subscribe_url())
+ {
+ $return = $this->sanitize($feed_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->feed_url);
+ if ($site_url !== null && $this->get_link() !== null)
+ {
+ $return .= $this->sanitize($site_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_link());
+ }
+ return $return;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function subscribe_aol()
+ {
+ return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
+ }
+
+ function subscribe_bloglines()
+ {
+ return urldecode($this->subscribe_service('http://www.bloglines.com/sub/'));
+ }
+
+ function subscribe_eskobo()
+ {
+ return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
+ }
+
+ function subscribe_feedfeeds()
+ {
+ return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
+ }
+
+ function subscribe_feedster()
+ {
+ return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
+ }
+
+ function subscribe_google()
+ {
+ return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
+ }
+
+ function subscribe_gritwire()
+ {
+ return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
+ }
+
+ function subscribe_msn()
+ {
+ return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
+ }
+
+ function subscribe_netvibes()
+ {
+ return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
+ }
+
+ function subscribe_newsburst()
+ {
+ return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
+ }
+
+ function subscribe_newsgator()
+ {
+ return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
+ }
+
+ function subscribe_odeo()
+ {
+ return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
+ }
+
+ function subscribe_podnova()
+ {
+ return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
+ }
+
+ function subscribe_rojo()
+ {
+ return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
+ }
+
+ function subscribe_yahoo()
+ {
+ return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
+ }
+
+ function get_feed_tags($namespace, $tag)
+ {
+ $type = $this->get_type();
+ if ($type & SIMPLEPIE_TYPE_ATOM_10)
+ {
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
+ {
+ return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_ATOM_03)
+ {
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
+ {
+ return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_RDF)
+ {
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
+ {
+ return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
+ {
+ if (isset($this->data['child']['']['rss'][0]['child'][$namespace][$tag]))
+ {
+ return $this->data['child']['']['rss'][0]['child'][$namespace][$tag];
+ }
+ }
+ return null;
+ }
+
+ function get_channel_tags($namespace, $tag)
+ {
+ $type = $this->get_type();
+ if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
+ {
+ if ($return = $this->get_feed_tags($namespace, $tag))
+ {
+ return $return;
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_10)
+ {
+ if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
+ {
+ if (isset($channel[0]['child'][$namespace][$tag]))
+ {
+ return $channel[0]['child'][$namespace][$tag];
+ }
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_090)
+ {
+ if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
+ {
+ if (isset($channel[0]['child'][$namespace][$tag]))
+ {
+ return $channel[0]['child'][$namespace][$tag];
+ }
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
+ {
+ if ($channel = $this->get_feed_tags('', 'channel'))
+ {
+ if (isset($channel[0]['child'][$namespace][$tag]))
+ {
+ return $channel[0]['child'][$namespace][$tag];
+ }
+ }
+ }
+ return null;
+ }
+
+ function get_image_tags($namespace, $tag)
+ {
+ $type = $this->get_type();
+ if ($type & SIMPLEPIE_TYPE_RSS_10)
+ {
+ if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
+ {
+ if (isset($image[0]['child'][$namespace][$tag]))
+ {
+ return $image[0]['child'][$namespace][$tag];
+ }
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_090)
+ {
+ if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
+ {
+ if (isset($image[0]['child'][$namespace][$tag]))
+ {
+ return $image[0]['child'][$namespace][$tag];
+ }
+ }
+ }
+ if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
+ {
+ if ($image = $this->get_channel_tags('', 'image'))
+ {
+ if (isset($image[0]['child'][$namespace][$tag]))
+ {
+ return $image[0]['child'][$namespace][$tag];
+ }
+ }
+ }
+ return null;
+ }
+
+ function get_base($element = array())
+ {
+ if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
+ {
+ return $element['xml_base'];
+ }
+ elseif ($this->get_link() !== null)
+ {
+ return $this->get_link();
+ }
+ else
+ {
+ return $this->subscribe_url();
+ }
+ }
+
+ function sanitize($data, $type, $base = '')
+ {
+ return $this->sanitize->sanitize($data, $type, $base);
+ }
+
+ function get_title()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags('', 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_category($key = 0)
+ {
+ $categories = $this->get_categories();
+ if (isset($categories[$key]))
+ {
+ return $categories[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_categories()
+ {
+ $categories = array();
+
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['attribs']['']['term']))
+ {
+ $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories[] =& new $this->category_class($term, $scheme, $label);
+ }
+ foreach ((array) $this->get_channel_tags('', 'category') as $category)
+ {
+ $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
+ {
+ $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
+ {
+ $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+
+ if (!empty($categories))
+ {
+ return SimplePie_Misc::array_unique($categories);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_author($key = 0)
+ {
+ $authors = $this->get_authors();
+ if (isset($authors[$key]))
+ {
+ return $authors[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_authors()
+ {
+ $authors = array();
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
+ {
+ $name = null;
+ $uri = null;
+ $email = null;
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
+ {
+ $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
+ {
+ $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
+ }
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
+ {
+ $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $uri !== null)
+ {
+ $authors[] =& new $this->author_class($name, $uri, $email);
+ }
+ }
+ if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
+ {
+ $name = null;
+ $url = null;
+ $email = null;
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
+ {
+ $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
+ {
+ $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
+ }
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
+ {
+ $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $url !== null)
+ {
+ $authors[] =& new $this->author_class($name, $url, $email);
+ }
+ }
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
+ {
+ $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
+ {
+ $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
+ {
+ $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+
+ if (!empty($authors))
+ {
+ return SimplePie_Misc::array_unique($authors);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_contributor($key = 0)
+ {
+ $contributors = $this->get_contributors();
+ if (isset($contributors[$key]))
+ {
+ return $contributors[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_contributors()
+ {
+ $contributors = array();
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
+ {
+ $name = null;
+ $uri = null;
+ $email = null;
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
+ {
+ $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
+ {
+ $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
+ {
+ $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $uri !== null)
+ {
+ $contributors[] =& new $this->author_class($name, $uri, $email);
+ }
+ }
+ foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
+ {
+ $name = null;
+ $url = null;
+ $email = null;
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
+ {
+ $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
+ {
+ $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
+ {
+ $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $url !== null)
+ {
+ $contributors[] =& new $this->author_class($name, $url, $email);
+ }
+ }
+
+ if (!empty($contributors))
+ {
+ return SimplePie_Misc::array_unique($contributors);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_link($key = 0, $rel = 'alternate')
+ {
+ $links = $this->get_links($rel);
+ if (isset($links[$key]))
+ {
+ return $links[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Added for parity between the parent-level and the item/entry-level.
+ */
+ function get_permalink()
+ {
+ return $this->get_link(0);
+ }
+
+ function get_links($rel = 'alternate')
+ {
+ if (!isset($this->data['links']))
+ {
+ $this->data['links'] = array();
+ if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
+ {
+ foreach ($links as $link)
+ {
+ if (isset($link['attribs']['']['href']))
+ {
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+ }
+ }
+ }
+ if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
+ {
+ foreach ($links as $link)
+ {
+ if (isset($link['attribs']['']['href']))
+ {
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+
+ }
+ }
+ }
+ if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_channel_tags('', 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+
+ $keys = array_keys($this->data['links']);
+ foreach ($keys as $key)
+ {
+ if (SimplePie_Misc::is_isegment_nz_nc($key))
+ {
+ if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
+ {
+ $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
+ $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
+ }
+ else
+ {
+ $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
+ }
+ }
+ elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
+ {
+ $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
+ }
+ $this->data['links'][$key] = array_unique($this->data['links'][$key]);
+ }
+ }
+
+ if (isset($this->data['links'][$rel]))
+ {
+ return $this->data['links'][$rel];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_description()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags('', 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_copyright()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags('', 'copyright'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_language()
+ {
+ if ($return = $this->get_channel_tags('', 'language'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
+ {
+ return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
+ {
+ return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
+ {
+ return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($this->data['headers']['content-language']))
+ {
+ return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_latitude()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
+ {
+ return (float) $match[1];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_longitude()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
+ {
+ return (float) $match[2];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_image_title()
+ {
+ if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_image_tags('', 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_image_url()
+ {
+ if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
+ {
+ return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_image_tags('', 'url'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_image_link()
+ {
+ if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_image_tags('', 'link'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_image_width()
+ {
+ if ($return = $this->get_image_tags('', 'width'))
+ {
+ return round($return[0]['data']);
+ }
+ elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
+ {
+ return 88.0;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_image_height()
+ {
+ if ($return = $this->get_image_tags('', 'height'))
+ {
+ return round($return[0]['data']);
+ }
+ elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
+ {
+ return 31.0;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_item_quantity($max = 0)
+ {
+ $qty = count($this->get_items());
+ if ($max == 0)
+ {
+ return $qty;
+ }
+ else
+ {
+ return ($qty > $max) ? $max : $qty;
+ }
+ }
+
+ function get_item($key = 0)
+ {
+ $items = $this->get_items();
+ if (isset($items[$key]))
+ {
+ return $items[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_items($start = 0, $end = 0)
+ {
+ if (!empty($this->multifeed_objects))
+ {
+ return SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
+ }
+ elseif (!isset($this->data['items']))
+ {
+ if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
+ {
+ $keys = array_keys($items);
+ foreach ($keys as $key)
+ {
+ $this->data['items'][] =& new $this->item_class($this, $items[$key]);
+ }
+ }
+ if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
+ {
+ $keys = array_keys($items);
+ foreach ($keys as $key)
+ {
+ $this->data['items'][] =& new $this->item_class($this, $items[$key]);
+ }
+ }
+ if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
+ {
+ $keys = array_keys($items);
+ foreach ($keys as $key)
+ {
+ $this->data['items'][] =& new $this->item_class($this, $items[$key]);
+ }
+ }
+ if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
+ {
+ $keys = array_keys($items);
+ foreach ($keys as $key)
+ {
+ $this->data['items'][] =& new $this->item_class($this, $items[$key]);
+ }
+ }
+ if ($items = $this->get_channel_tags('', 'item'))
+ {
+ $keys = array_keys($items);
+ foreach ($keys as $key)
+ {
+ $this->data['items'][] =& new $this->item_class($this, $items[$key]);
+ }
+ }
+ }
+
+ if (!empty($this->data['items']))
+ {
+ // If we want to order it by date, check if all items have a date, and then sort it
+ if ($this->order_by_date)
+ {
+ if (!isset($this->data['ordered_items']))
+ {
+ $do_sort = true;
+ foreach ($this->data['items'] as $item)
+ {
+ if (!$item->get_date('U'))
+ {
+ $do_sort = false;
+ break;
+ }
+ }
+ $item = null;
+ $this->data['ordered_items'] = $this->data['items'];
+ if ($do_sort)
+ {
+ usort($this->data['ordered_items'], array(&$this, 'sort_items'));
+ }
+ }
+ $items = $this->data['ordered_items'];
+ }
+ else
+ {
+ $items = $this->data['items'];
+ }
+
+ // Slice the data as desired
+ if ($end == 0)
+ {
+ return array_slice($items, $start);
+ }
+ else
+ {
+ return array_slice($items, $start, $end);
+ }
+ }
+ else
+ {
+ return array();
+ }
+ }
+
+ function sort_items($a, $b)
+ {
+ return $a->get_date('U') <= $b->get_date('U');
+ }
+
+ function merge_items($urls, $start = 0, $end = 0, $limit = 0)
+ {
+ if (is_array($urls) && sizeof($urls) > 0)
+ {
+ $items = array();
+ foreach ($urls as $arg)
+ {
+ if (is_a($arg, 'SimplePie'))
+ {
+ $items = array_merge($items, $arg->get_items(0, $limit));
+ }
+ else
+ {
+ trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
+ }
+ }
+
+ $do_sort = true;
+ foreach ($items as $item)
+ {
+ if (!$item->get_date('U'))
+ {
+ $do_sort = false;
+ break;
+ }
+ }
+ $item = null;
+ if ($do_sort)
+ {
+ usort($items, array('SimplePie', 'sort_items'));
+ }
+
+ if ($end == 0)
+ {
+ return array_slice($items, $start);
+ }
+ else
+ {
+ return array_slice($items, $start, $end);
+ }
+ }
+ else
+ {
+ trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
+ return array();
+ }
+ }
+}
+
+class SimplePie_Item
+{
+ var $feed;
+ var $data = array();
+
+ function SimplePie_Item($feed, $data)
+ {
+ $this->feed = $feed;
+ $this->data = $data;
+ }
+
+ function __toString()
+ {
+ return md5(serialize($this->data));
+ }
+
+ /**
+ * Remove items that link back to this before destroying this object
+ */
+ function __destruct()
+ {
+ unset($this->feed);
+ }
+
+ function get_item_tags($namespace, $tag)
+ {
+ if (isset($this->data['child'][$namespace][$tag]))
+ {
+ return $this->data['child'][$namespace][$tag];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_base($element = array())
+ {
+ return $this->feed->get_base($element);
+ }
+
+ function sanitize($data, $type, $base = '')
+ {
+ return $this->feed->sanitize($data, $type, $base);
+ }
+
+ function get_feed()
+ {
+ return $this->feed;
+ }
+
+ function get_id($hash = false)
+ {
+ if (!$hash)
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags('', 'guid'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (($return = $this->get_permalink()) !== null)
+ {
+ return $return;
+ }
+ elseif (($return = $this->get_title()) !== null)
+ {
+ return $return;
+ }
+ }
+ if ($this->get_permalink() !== null || $this->get_title() !== null)
+ {
+ return md5($this->get_permalink() . $this->get_title());
+ }
+ else
+ {
+ return md5(serialize($this->data));
+ }
+ }
+
+ function get_title()
+ {
+ if (!isset($this->data['title']))
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags('', 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
+ {
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $this->data['title'] = null;
+ }
+ }
+ return $this->data['title'];
+ }
+
+ function get_description($description_only = false)
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags('', 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (!$description_only)
+ {
+ return $this->get_content(true);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_content($content_only = false)
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ elseif (!$content_only)
+ {
+ return $this->get_description(true);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_category($key = 0)
+ {
+ $categories = $this->get_categories();
+ if (isset($categories[$key]))
+ {
+ return $categories[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_categories()
+ {
+ $categories = array();
+
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['attribs']['']['term']))
+ {
+ $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ foreach ((array) $this->get_item_tags('', 'category') as $category)
+ {
+ $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
+ {
+ $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
+ {
+ $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+
+ if (!empty($categories))
+ {
+ return SimplePie_Misc::array_unique($categories);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_author($key = 0)
+ {
+ $authors = $this->get_authors();
+ if (isset($authors[$key]))
+ {
+ return $authors[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_contributor($key = 0)
+ {
+ $contributors = $this->get_contributors();
+ if (isset($contributors[$key]))
+ {
+ return $contributors[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_contributors()
+ {
+ $contributors = array();
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
+ {
+ $name = null;
+ $uri = null;
+ $email = null;
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
+ {
+ $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
+ {
+ $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
+ {
+ $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $uri !== null)
+ {
+ $contributors[] =& new $this->feed->author_class($name, $uri, $email);
+ }
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
+ {
+ $name = null;
+ $url = null;
+ $email = null;
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
+ {
+ $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
+ {
+ $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
+ {
+ $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $url !== null)
+ {
+ $contributors[] =& new $this->feed->author_class($name, $url, $email);
+ }
+ }
+
+ if (!empty($contributors))
+ {
+ return SimplePie_Misc::array_unique($contributors);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @todo Atom inheritance (item author, source author, feed author)
+ */
+ function get_authors()
+ {
+ $authors = array();
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
+ {
+ $name = null;
+ $uri = null;
+ $email = null;
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
+ {
+ $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
+ {
+ $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
+ }
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
+ {
+ $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $uri !== null)
+ {
+ $authors[] =& new $this->feed->author_class($name, $uri, $email);
+ }
+ }
+ if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
+ {
+ $name = null;
+ $url = null;
+ $email = null;
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
+ {
+ $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
+ {
+ $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
+ }
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
+ {
+ $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $url !== null)
+ {
+ $authors[] =& new $this->feed->author_class($name, $url, $email);
+ }
+ }
+ if ($author = $this->get_item_tags('', 'author'))
+ {
+ $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
+ {
+ $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
+ {
+ $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
+ {
+ $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+
+ if (!empty($authors))
+ {
+ return SimplePie_Misc::array_unique($authors);
+ }
+ elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
+ {
+ return $authors;
+ }
+ elseif ($authors = $this->feed->get_authors())
+ {
+ return $authors;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_copyright()
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_date($date_format = 'j F Y, g:i a')
+ {
+ if (!isset($this->data['date']))
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags('', 'pubDate'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
+ {
+ $this->data['date']['raw'] = $return[0]['data'];
+ }
+
+ if (!empty($this->data['date']['raw']))
+ {
+ $parser = SimplePie_Parse_Date::get();
+ $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
+ }
+ else
+ {
+ $this->data['date'] = null;
+ }
+ }
+ if ($this->data['date'])
+ {
+ $date_format = (string) $date_format;
+ switch ($date_format)
+ {
+ case '':
+ return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
+
+ case 'U':
+ return $this->data['date']['parsed'];
+
+ default:
+ return date($date_format, $this->data['date']['parsed']);
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_local_date($date_format = '%c')
+ {
+ if (!$date_format)
+ {
+ return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (($date = $this->get_date('U')) !== null)
+ {
+ return strftime($date_format, $date);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_permalink()
+ {
+ $link = $this->get_link();
+ $enclosure = $this->get_enclosure(0);
+ if ($link !== null)
+ {
+ return $link;
+ }
+ elseif ($enclosure !== null)
+ {
+ return $enclosure->get_link();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_link($key = 0, $rel = 'alternate')
+ {
+ $links = $this->get_links($rel);
+ if ($links[$key] !== null)
+ {
+ return $links[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_links($rel = 'alternate')
+ {
+ if (!isset($this->data['links']))
+ {
+ $this->data['links'] = array();
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
+ {
+ if (isset($link['attribs']['']['href']))
+ {
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+
+ }
+ }
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
+ {
+ if (isset($link['attribs']['']['href']))
+ {
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+ }
+ }
+ if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_item_tags('', 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_item_tags('', 'guid'))
+ {
+ if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) == 'true')
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ }
+
+ $keys = array_keys($this->data['links']);
+ foreach ($keys as $key)
+ {
+ if (SimplePie_Misc::is_isegment_nz_nc($key))
+ {
+ if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
+ {
+ $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
+ $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
+ }
+ else
+ {
+ $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
+ }
+ }
+ elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
+ {
+ $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
+ }
+ $this->data['links'][$key] = array_unique($this->data['links'][$key]);
+ }
+ }
+ if (isset($this->data['links'][$rel]))
+ {
+ return $this->data['links'][$rel];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @todo Add ability to prefer one type of content over another (in a media group).
+ */
+ function get_enclosure($key = 0, $prefer = null)
+ {
+ $enclosures = $this->get_enclosures();
+ if (isset($enclosures[$key]))
+ {
+ return $enclosures[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Grabs all available enclosures (podcasts, etc.)
+ *
+ * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
+ *
+ * At this point, we're pretty much assuming that all enclosures for an item are the same content. Anything else is too complicated to properly support.
+ *
+ * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
+ * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
+ */
+ function get_enclosures()
+ {
+ if (!isset($this->data['enclosures']))
+ {
+ $this->data['enclosures'] = array();
+
+ // Elements
+ $captions_parent = null;
+ $categories_parent = null;
+ $copyrights_parent = null;
+ $credits_parent = null;
+ $description_parent = null;
+ $duration_parent = null;
+ $hashes_parent = null;
+ $keywords_parent = null;
+ $player_parent = null;
+ $ratings_parent = null;
+ $restrictions_parent = null;
+ $thumbnails_parent = null;
+ $title_parent = null;
+
+ // Let's do the channel and item-level ones first, and just re-use them if we need to.
+ $parent = $this->get_feed();
+
+ // CAPTIONS
+ if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
+ {
+ foreach ($captions as $caption)
+ {
+ $caption_type = null;
+ $caption_lang = null;
+ $caption_startTime = null;
+ $caption_endTime = null;
+ $caption_text = null;
+ if (isset($caption['attribs']['']['type']))
+ {
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['lang']))
+ {
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['start']))
+ {
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['end']))
+ {
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['data']))
+ {
+ $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
+ }
+ }
+ elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
+ {
+ foreach ($captions as $caption)
+ {
+ $caption_type = null;
+ $caption_lang = null;
+ $caption_startTime = null;
+ $caption_endTime = null;
+ $caption_text = null;
+ if (isset($caption['attribs']['']['type']))
+ {
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['lang']))
+ {
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['start']))
+ {
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['end']))
+ {
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['data']))
+ {
+ $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
+ }
+ }
+ if (is_array($captions_parent))
+ {
+ $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
+ }
+
+ // CATEGORIES
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['data']))
+ {
+ $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['data']))
+ {
+ $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
+ {
+ $term = null;
+ $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
+ $label = null;
+ if (isset($category['attribs']['']['text']))
+ {
+ $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
+
+ if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
+ {
+ foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
+ {
+ if (isset($subcategory['attribs']['']['text']))
+ {
+ $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ }
+ }
+ if (is_array($categories_parent))
+ {
+ $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
+ }
+
+ // COPYRIGHT
+ if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
+ {
+ $copyright_url = null;
+ $copyright_label = null;
+ if (isset($copyright[0]['attribs']['']['url']))
+ {
+ $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($copyright[0]['data']))
+ {
+ $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
+ }
+ elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
+ {
+ $copyright_url = null;
+ $copyright_label = null;
+ if (isset($copyright[0]['attribs']['']['url']))
+ {
+ $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($copyright[0]['data']))
+ {
+ $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
+ }
+
+ // CREDITS
+ if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
+ {
+ foreach ($credits as $credit)
+ {
+ $credit_role = null;
+ $credit_scheme = null;
+ $credit_name = null;
+ if (isset($credit['attribs']['']['role']))
+ {
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($credit['attribs']['']['scheme']))
+ {
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $credit_scheme = 'urn:ebu';
+ }
+ if (isset($credit['data']))
+ {
+ $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
+ }
+ }
+ elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
+ {
+ foreach ($credits as $credit)
+ {
+ $credit_role = null;
+ $credit_scheme = null;
+ $credit_name = null;
+ if (isset($credit['attribs']['']['role']))
+ {
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($credit['attribs']['']['scheme']))
+ {
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $credit_scheme = 'urn:ebu';
+ }
+ if (isset($credit['data']))
+ {
+ $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
+ }
+ }
+ if (is_array($credits_parent))
+ {
+ $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
+ }
+
+ // DESCRIPTION
+ if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
+ {
+ if (isset($description_parent[0]['data']))
+ {
+ $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ }
+ elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
+ {
+ if (isset($description_parent[0]['data']))
+ {
+ $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ }
+
+ // DURATION
+ if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
+ {
+ $seconds = null;
+ $minutes = null;
+ $hours = null;
+ if (isset($duration_parent[0]['data']))
+ {
+ $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ if (sizeof($temp) > 0)
+ {
+ (int) $seconds = array_pop($temp);
+ }
+ if (sizeof($temp) > 0)
+ {
+ (int) $minutes = array_pop($temp);
+ $seconds += $minutes * 60;
+ }
+ if (sizeof($temp) > 0)
+ {
+ (int) $hours = array_pop($temp);
+ $seconds += $hours * 3600;
+ }
+ unset($temp);
+ $duration_parent = $seconds;
+ }
+ }
+
+ // HASHES
+ if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
+ {
+ foreach ($hashes_iterator as $hash)
+ {
+ $value = null;
+ $algo = null;
+ if (isset($hash['data']))
+ {
+ $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($hash['attribs']['']['algo']))
+ {
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $algo = 'md5';
+ }
+ $hashes_parent[] = $algo.':'.$value;
+ }
+ }
+ elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
+ {
+ foreach ($hashes_iterator as $hash)
+ {
+ $value = null;
+ $algo = null;
+ if (isset($hash['data']))
+ {
+ $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($hash['attribs']['']['algo']))
+ {
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $algo = 'md5';
+ }
+ $hashes_parent[] = $algo.':'.$value;
+ }
+ }
+ if (is_array($hashes_parent))
+ {
+ $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
+ }
+
+ // KEYWORDS
+ if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
+ {
+ if (isset($keywords[0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords_parent[] = trim($word);
+ }
+ }
+ unset($temp);
+ }
+ elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
+ {
+ if (isset($keywords[0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords_parent[] = trim($word);
+ }
+ }
+ unset($temp);
+ }
+ elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
+ {
+ if (isset($keywords[0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords_parent[] = trim($word);
+ }
+ }
+ unset($temp);
+ }
+ elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
+ {
+ if (isset($keywords[0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords_parent[] = trim($word);
+ }
+ }
+ unset($temp);
+ }
+ if (is_array($keywords_parent))
+ {
+ $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
+ }
+
+ // PLAYER
+ if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
+ {
+ if (isset($player_parent[0]['attribs']['']['url']))
+ {
+ $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ }
+ elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
+ {
+ if (isset($player_parent[0]['attribs']['']['url']))
+ {
+ $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ }
+
+ // RATINGS
+ if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
+ {
+ foreach ($ratings as $rating)
+ {
+ $rating_scheme = null;
+ $rating_value = null;
+ if (isset($rating['attribs']['']['scheme']))
+ {
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $rating_scheme = 'urn:simple';
+ }
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ }
+ elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
+ {
+ foreach ($ratings as $rating)
+ {
+ $rating_scheme = 'urn:itunes';
+ $rating_value = null;
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ }
+ elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
+ {
+ foreach ($ratings as $rating)
+ {
+ $rating_scheme = null;
+ $rating_value = null;
+ if (isset($rating['attribs']['']['scheme']))
+ {
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $rating_scheme = 'urn:simple';
+ }
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ }
+ elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
+ {
+ foreach ($ratings as $rating)
+ {
+ $rating_scheme = 'urn:itunes';
+ $rating_value = null;
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ }
+ if (is_array($ratings_parent))
+ {
+ $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
+ }
+
+ // RESTRICTIONS
+ if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
+ {
+ foreach ($restrictions as $restriction)
+ {
+ $restriction_relationship = null;
+ $restriction_type = null;
+ $restriction_value = null;
+ if (isset($restriction['attribs']['']['relationship']))
+ {
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['attribs']['']['type']))
+ {
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['data']))
+ {
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ }
+ elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
+ {
+ foreach ($restrictions as $restriction)
+ {
+ $restriction_relationship = 'allow';
+ $restriction_type = null;
+ $restriction_value = 'itunes';
+ if (isset($restriction['data']) && strtolower($restriction['data']) == 'yes')
+ {
+ $restriction_relationship = 'deny';
+ }
+ $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ }
+ elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
+ {
+ foreach ($restrictions as $restriction)
+ {
+ $restriction_relationship = null;
+ $restriction_type = null;
+ $restriction_value = null;
+ if (isset($restriction['attribs']['']['relationship']))
+ {
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['attribs']['']['type']))
+ {
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['data']))
+ {
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ }
+ elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
+ {
+ foreach ($restrictions as $restriction)
+ {
+ $restriction_relationship = 'allow';
+ $restriction_type = null;
+ $restriction_value = 'itunes';
+ if (isset($restriction['data']) && strtolower($restriction['data']) == 'yes')
+ {
+ $restriction_relationship = 'deny';
+ }
+ $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ }
+ if (is_array($restrictions_parent))
+ {
+ $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
+ }
+
+ // THUMBNAILS
+ if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
+ {
+ foreach ($thumbnails as $thumbnail)
+ {
+ if (isset($thumbnail['attribs']['']['url']))
+ {
+ $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ }
+ }
+ elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
+ {
+ foreach ($thumbnails as $thumbnail)
+ {
+ if (isset($thumbnail['attribs']['']['url']))
+ {
+ $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ }
+ }
+
+ // TITLES
+ if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
+ {
+ if (isset($title_parent[0]['data']))
+ {
+ $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ }
+ elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
+ {
+ if (isset($title_parent[0]['data']))
+ {
+ $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ }
+
+ // Clear the memory
+ unset($parent);
+
+ // Attributes
+ $bitrate = null;
+ $channels = null;
+ $duration = null;
+ $expression = null;
+ $framerate = null;
+ $height = null;
+ $javascript = null;
+ $lang = null;
+ $length = null;
+ $medium = null;
+ $samplingrate = null;
+ $type = null;
+ $url = null;
+ $width = null;
+
+ // Elements
+ $captions = null;
+ $categories = null;
+ $copyrights = null;
+ $credits = null;
+ $description = null;
+ $hashes = null;
+ $keywords = null;
+ $player = null;
+ $ratings = null;
+ $restrictions = null;
+ $thumbnails = null;
+ $title = null;
+
+ // If we have media:group tags, loop through them.
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
+ {
+ // If we have media:content tags, loop through them.
+ foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
+ {
+ if (isset($content['attribs']['']['url']))
+ {
+ // Attributes
+ $bitrate = null;
+ $channels = null;
+ $duration = null;
+ $expression = null;
+ $framerate = null;
+ $height = null;
+ $javascript = null;
+ $lang = null;
+ $length = null;
+ $medium = null;
+ $samplingrate = null;
+ $type = null;
+ $url = null;
+ $width = null;
+
+ // Elements
+ $captions = null;
+ $categories = null;
+ $copyrights = null;
+ $credits = null;
+ $description = null;
+ $hashes = null;
+ $keywords = null;
+ $player = null;
+ $ratings = null;
+ $restrictions = null;
+ $thumbnails = null;
+ $title = null;
+
+ // Start checking the attributes of media:content
+ if (isset($content['attribs']['']['bitrate']))
+ {
+ $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['channels']))
+ {
+ $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['duration']))
+ {
+ $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $duration = $duration_parent;
+ }
+ if (isset($content['attribs']['']['expression']))
+ {
+ $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['framerate']))
+ {
+ $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['height']))
+ {
+ $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['lang']))
+ {
+ $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['fileSize']))
+ {
+ $length = ceil($content['attribs']['']['fileSize']);
+ }
+ if (isset($content['attribs']['']['medium']))
+ {
+ $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['samplingrate']))
+ {
+ $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['type']))
+ {
+ $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['width']))
+ {
+ $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+
+ // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
+
+ // CAPTIONS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
+ {
+ $caption_type = null;
+ $caption_lang = null;
+ $caption_startTime = null;
+ $caption_endTime = null;
+ $caption_text = null;
+ if (isset($caption['attribs']['']['type']))
+ {
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['lang']))
+ {
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['start']))
+ {
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['end']))
+ {
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['data']))
+ {
+ $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
+ }
+ if (is_array($captions))
+ {
+ $captions = array_values(SimplePie_Misc::array_unique($captions));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
+ {
+ foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
+ {
+ $caption_type = null;
+ $caption_lang = null;
+ $caption_startTime = null;
+ $caption_endTime = null;
+ $caption_text = null;
+ if (isset($caption['attribs']['']['type']))
+ {
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['lang']))
+ {
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['start']))
+ {
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['end']))
+ {
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['data']))
+ {
+ $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
+ }
+ if (is_array($captions))
+ {
+ $captions = array_values(SimplePie_Misc::array_unique($captions));
+ }
+ }
+ else
+ {
+ $captions = $captions_parent;
+ }
+
+ // CATEGORIES
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
+ {
+ foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['data']))
+ {
+ $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ }
+ if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
+ {
+ foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['data']))
+ {
+ $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ }
+ if (is_array($categories) && is_array($categories_parent))
+ {
+ $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
+ }
+ elseif (is_array($categories))
+ {
+ $categories = array_values(SimplePie_Misc::array_unique($categories));
+ }
+ elseif (is_array($categories_parent))
+ {
+ $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
+ }
+
+ // COPYRIGHTS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
+ {
+ $copyright_url = null;
+ $copyright_label = null;
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
+ {
+ $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
+ {
+ $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
+ {
+ $copyright_url = null;
+ $copyright_label = null;
+ if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
+ {
+ $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
+ {
+ $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
+ }
+ else
+ {
+ $copyrights = $copyrights_parent;
+ }
+
+ // CREDITS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
+ {
+ $credit_role = null;
+ $credit_scheme = null;
+ $credit_name = null;
+ if (isset($credit['attribs']['']['role']))
+ {
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($credit['attribs']['']['scheme']))
+ {
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $credit_scheme = 'urn:ebu';
+ }
+ if (isset($credit['data']))
+ {
+ $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
+ }
+ if (is_array($credits))
+ {
+ $credits = array_values(SimplePie_Misc::array_unique($credits));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
+ {
+ foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
+ {
+ $credit_role = null;
+ $credit_scheme = null;
+ $credit_name = null;
+ if (isset($credit['attribs']['']['role']))
+ {
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($credit['attribs']['']['scheme']))
+ {
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $credit_scheme = 'urn:ebu';
+ }
+ if (isset($credit['data']))
+ {
+ $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
+ }
+ if (is_array($credits))
+ {
+ $credits = array_values(SimplePie_Misc::array_unique($credits));
+ }
+ }
+ else
+ {
+ $credits = $credits_parent;
+ }
+
+ // DESCRIPTION
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
+ {
+ $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
+ {
+ $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $description = $description_parent;
+ }
+
+ // HASHES
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
+ {
+ $value = null;
+ $algo = null;
+ if (isset($hash['data']))
+ {
+ $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($hash['attribs']['']['algo']))
+ {
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $algo = 'md5';
+ }
+ $hashes[] = $algo.':'.$value;
+ }
+ if (is_array($hashes))
+ {
+ $hashes = array_values(SimplePie_Misc::array_unique($hashes));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
+ {
+ foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
+ {
+ $value = null;
+ $algo = null;
+ if (isset($hash['data']))
+ {
+ $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($hash['attribs']['']['algo']))
+ {
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $algo = 'md5';
+ }
+ $hashes[] = $algo.':'.$value;
+ }
+ if (is_array($hashes))
+ {
+ $hashes = array_values(SimplePie_Misc::array_unique($hashes));
+ }
+ }
+ else
+ {
+ $hashes = $hashes_parent;
+ }
+
+ // KEYWORDS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
+ {
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords[] = trim($word);
+ }
+ unset($temp);
+ }
+ if (is_array($keywords))
+ {
+ $keywords = array_values(SimplePie_Misc::array_unique($keywords));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
+ {
+ if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords[] = trim($word);
+ }
+ unset($temp);
+ }
+ if (is_array($keywords))
+ {
+ $keywords = array_values(SimplePie_Misc::array_unique($keywords));
+ }
+ }
+ else
+ {
+ $keywords = $keywords_parent;
+ }
+
+ // PLAYER
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
+ {
+ $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
+ {
+ $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ $player = $player_parent;
+ }
+
+ // RATINGS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
+ {
+ $rating_scheme = null;
+ $rating_value = null;
+ if (isset($rating['attribs']['']['scheme']))
+ {
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $rating_scheme = 'urn:simple';
+ }
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ if (is_array($ratings))
+ {
+ $ratings = array_values(SimplePie_Misc::array_unique($ratings));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
+ {
+ foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
+ {
+ $rating_scheme = null;
+ $rating_value = null;
+ if (isset($rating['attribs']['']['scheme']))
+ {
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $rating_scheme = 'urn:simple';
+ }
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ if (is_array($ratings))
+ {
+ $ratings = array_values(SimplePie_Misc::array_unique($ratings));
+ }
+ }
+ else
+ {
+ $ratings = $ratings_parent;
+ }
+
+ // RESTRICTIONS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
+ {
+ $restriction_relationship = null;
+ $restriction_type = null;
+ $restriction_value = null;
+ if (isset($restriction['attribs']['']['relationship']))
+ {
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['attribs']['']['type']))
+ {
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['data']))
+ {
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ if (is_array($restrictions))
+ {
+ $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
+ {
+ foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
+ {
+ $restriction_relationship = null;
+ $restriction_type = null;
+ $restriction_value = null;
+ if (isset($restriction['attribs']['']['relationship']))
+ {
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['attribs']['']['type']))
+ {
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['data']))
+ {
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ if (is_array($restrictions))
+ {
+ $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
+ }
+ }
+ else
+ {
+ $restrictions = $restrictions_parent;
+ }
+
+ // THUMBNAILS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
+ {
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ if (is_array($thumbnails))
+ {
+ $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
+ }
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
+ {
+ foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
+ {
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ if (is_array($thumbnails))
+ {
+ $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
+ }
+ }
+ else
+ {
+ $thumbnails = $thumbnails_parent;
+ }
+
+ // TITLES
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
+ {
+ $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
+ {
+ $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $title = $title_parent;
+ }
+
+ $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
+ }
+ }
+ }
+
+ // If we have standalone media:content tags, loop through them.
+ if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
+ {
+ foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
+ {
+ if (isset($content['attribs']['']['url']))
+ {
+ // Attributes
+ $bitrate = null;
+ $channels = null;
+ $duration = null;
+ $expression = null;
+ $framerate = null;
+ $height = null;
+ $javascript = null;
+ $lang = null;
+ $length = null;
+ $medium = null;
+ $samplingrate = null;
+ $type = null;
+ $url = null;
+ $width = null;
+
+ // Elements
+ $captions = null;
+ $categories = null;
+ $copyrights = null;
+ $credits = null;
+ $description = null;
+ $hashes = null;
+ $keywords = null;
+ $player = null;
+ $ratings = null;
+ $restrictions = null;
+ $thumbnails = null;
+ $title = null;
+
+ // Start checking the attributes of media:content
+ if (isset($content['attribs']['']['bitrate']))
+ {
+ $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['channels']))
+ {
+ $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['duration']))
+ {
+ $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $duration = $duration_parent;
+ }
+ if (isset($content['attribs']['']['expression']))
+ {
+ $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['framerate']))
+ {
+ $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['height']))
+ {
+ $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['lang']))
+ {
+ $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['fileSize']))
+ {
+ $length = ceil($content['attribs']['']['fileSize']);
+ }
+ if (isset($content['attribs']['']['medium']))
+ {
+ $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['samplingrate']))
+ {
+ $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['type']))
+ {
+ $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['attribs']['']['width']))
+ {
+ $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+
+ // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
+
+ // CAPTIONS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
+ {
+ $caption_type = null;
+ $caption_lang = null;
+ $caption_startTime = null;
+ $caption_endTime = null;
+ $caption_text = null;
+ if (isset($caption['attribs']['']['type']))
+ {
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['lang']))
+ {
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['start']))
+ {
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['attribs']['']['end']))
+ {
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($caption['data']))
+ {
+ $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
+ }
+ if (is_array($captions))
+ {
+ $captions = array_values(SimplePie_Misc::array_unique($captions));
+ }
+ }
+ else
+ {
+ $captions = $captions_parent;
+ }
+
+ // CATEGORIES
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
+ {
+ foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['data']))
+ {
+ $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories[] =& new $this->feed->category_class($term, $scheme, $label);
+ }
+ }
+ if (is_array($categories) && is_array($categories_parent))
+ {
+ $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
+ }
+ elseif (is_array($categories))
+ {
+ $categories = array_values(SimplePie_Misc::array_unique($categories));
+ }
+ elseif (is_array($categories_parent))
+ {
+ $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
+ }
+ else
+ {
+ $categories = null;
+ }
+
+ // COPYRIGHTS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
+ {
+ $copyright_url = null;
+ $copyright_label = null;
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
+ {
+ $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
+ {
+ $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
+ }
+ else
+ {
+ $copyrights = $copyrights_parent;
+ }
+
+ // CREDITS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
+ {
+ $credit_role = null;
+ $credit_scheme = null;
+ $credit_name = null;
+ if (isset($credit['attribs']['']['role']))
+ {
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($credit['attribs']['']['scheme']))
+ {
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $credit_scheme = 'urn:ebu';
+ }
+ if (isset($credit['data']))
+ {
+ $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
+ }
+ if (is_array($credits))
+ {
+ $credits = array_values(SimplePie_Misc::array_unique($credits));
+ }
+ }
+ else
+ {
+ $credits = $credits_parent;
+ }
+
+ // DESCRIPTION
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
+ {
+ $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $description = $description_parent;
+ }
+
+ // HASHES
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
+ {
+ $value = null;
+ $algo = null;
+ if (isset($hash['data']))
+ {
+ $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($hash['attribs']['']['algo']))
+ {
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $algo = 'md5';
+ }
+ $hashes[] = $algo.':'.$value;
+ }
+ if (is_array($hashes))
+ {
+ $hashes = array_values(SimplePie_Misc::array_unique($hashes));
+ }
+ }
+ else
+ {
+ $hashes = $hashes_parent;
+ }
+
+ // KEYWORDS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
+ {
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
+ {
+ $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
+ foreach ($temp as $word)
+ {
+ $keywords[] = trim($word);
+ }
+ unset($temp);
+ }
+ if (is_array($keywords))
+ {
+ $keywords = array_values(SimplePie_Misc::array_unique($keywords));
+ }
+ }
+ else
+ {
+ $keywords = $keywords_parent;
+ }
+
+ // PLAYER
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
+ {
+ $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ else
+ {
+ $player = $player_parent;
+ }
+
+ // RATINGS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
+ {
+ $rating_scheme = null;
+ $rating_value = null;
+ if (isset($rating['attribs']['']['scheme']))
+ {
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $rating_scheme = 'urn:simple';
+ }
+ if (isset($rating['data']))
+ {
+ $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
+ }
+ if (is_array($ratings))
+ {
+ $ratings = array_values(SimplePie_Misc::array_unique($ratings));
+ }
+ }
+ else
+ {
+ $ratings = $ratings_parent;
+ }
+
+ // RESTRICTIONS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
+ {
+ $restriction_relationship = null;
+ $restriction_type = null;
+ $restriction_value = null;
+ if (isset($restriction['attribs']['']['relationship']))
+ {
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['attribs']['']['type']))
+ {
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($restriction['data']))
+ {
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
+ }
+ if (is_array($restrictions))
+ {
+ $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
+ }
+ }
+ else
+ {
+ $restrictions = $restrictions_parent;
+ }
+
+ // THUMBNAILS
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
+ {
+ foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
+ {
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ if (is_array($thumbnails))
+ {
+ $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
+ }
+ }
+ else
+ {
+ $thumbnails = $thumbnails_parent;
+ }
+
+ // TITLES
+ if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
+ {
+ $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ $title = $title_parent;
+ }
+
+ $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
+ }
+ }
+ }
+
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
+ {
+ if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
+ {
+ // Attributes
+ $bitrate = null;
+ $channels = null;
+ $duration = null;
+ $expression = null;
+ $framerate = null;
+ $height = null;
+ $javascript = null;
+ $lang = null;
+ $length = null;
+ $medium = null;
+ $samplingrate = null;
+ $type = null;
+ $url = null;
+ $width = null;
+
+ $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+ if (isset($link['attribs']['']['type']))
+ {
+ $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($link['attribs']['']['length']))
+ {
+ $length = ceil($link['attribs']['']['length']);
+ }
+
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
+ $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
+ }
+ }
+
+ foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
+ {
+ if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
+ {
+ // Attributes
+ $bitrate = null;
+ $channels = null;
+ $duration = null;
+ $expression = null;
+ $framerate = null;
+ $height = null;
+ $javascript = null;
+ $lang = null;
+ $length = null;
+ $medium = null;
+ $samplingrate = null;
+ $type = null;
+ $url = null;
+ $width = null;
+
+ $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+ if (isset($link['attribs']['']['type']))
+ {
+ $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($link['attribs']['']['length']))
+ {
+ $length = ceil($link['attribs']['']['length']);
+ }
+
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
+ $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
+ }
+ }
+
+ if ($enclosure = $this->get_item_tags('', 'enclosure'))
+ {
+ if (isset($enclosure[0]['attribs']['']['url']))
+ {
+ // Attributes
+ $bitrate = null;
+ $channels = null;
+ $duration = null;
+ $expression = null;
+ $framerate = null;
+ $height = null;
+ $javascript = null;
+ $lang = null;
+ $length = null;
+ $medium = null;
+ $samplingrate = null;
+ $type = null;
+ $url = null;
+ $width = null;
+
+ $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
+ if (isset($enclosure[0]['attribs']['']['type']))
+ {
+ $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($enclosure[0]['attribs']['']['length']))
+ {
+ $length = ceil($enclosure[0]['attribs']['']['length']);
+ }
+
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
+ $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
+ }
+ }
+
+ if (sizeof($this->data['enclosures']) == 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
+ {
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
+ $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
+ }
+
+ $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
+ }
+ if (!empty($this->data['enclosures']))
+ {
+ return $this->data['enclosures'];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_latitude()
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
+ {
+ return (float) $match[1];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_longitude()
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
+ {
+ return (float) $match[2];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_source()
+ {
+ if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
+ {
+ return new $this->feed->source_class($this, $return[0]);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Creates the add_to_* methods' return data
+ *
+ * @access private
+ * @param string $item_url String to prefix to the item permalink
+ * @param string $title_url String to prefix to the item title
+ * (and suffix to the item permalink)
+ * @return mixed URL if feed exists, false otherwise
+ */
+ function add_to_service($item_url, $title_url = null, $summary_url = null)
+ {
+ if ($this->get_permalink() !== null)
+ {
+ $return = $this->sanitize($item_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_permalink());
+ if ($title_url !== null && $this->get_title() !== null)
+ {
+ $return .= $this->sanitize($title_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_title());
+ }
+ if ($summary_url !== null && $this->get_description() !== null)
+ {
+ $return .= $this->sanitize($summary_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_description());
+ }
+ return $return;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function add_to_blinklist()
+ {
+ return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
+ }
+
+ function add_to_blogmarks()
+ {
+ return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
+ }
+
+ function add_to_delicious()
+ {
+ return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
+ }
+
+ function add_to_digg()
+ {
+ return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
+ }
+
+ function add_to_furl()
+ {
+ return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
+ }
+
+ function add_to_magnolia()
+ {
+ return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
+ }
+
+ function add_to_myweb20()
+ {
+ return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
+ }
+
+ function add_to_newsvine()
+ {
+ return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
+ }
+
+ function add_to_reddit()
+ {
+ return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
+ }
+
+ function add_to_segnalo()
+ {
+ return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
+ }
+
+ function add_to_simpy()
+ {
+ return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
+ }
+
+ function add_to_spurl()
+ {
+ return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
+ }
+
+ function add_to_wists()
+ {
+ return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
+ }
+
+ function search_technorati()
+ {
+ return $this->add_to_service('http://www.technorati.com/search/');
+ }
+}
+
+class SimplePie_Source
+{
+ var $item;
+ var $data = array();
+
+ function SimplePie_Source($item, $data)
+ {
+ $this->item = $item;
+ $this->data = $data;
+ }
+
+ function __toString()
+ {
+ return md5(serialize($this->data));
+ }
+
+ /**
+ * Remove items that link back to this before destroying this object
+ */
+ function __destruct()
+ {
+ unset($this->item);
+ }
+
+ function get_source_tags($namespace, $tag)
+ {
+ if (isset($this->data['child'][$namespace][$tag]))
+ {
+ return $this->data['child'][$namespace][$tag];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_base($element = array())
+ {
+ return $this->item->get_base($element);
+ }
+
+ function sanitize($data, $type, $base = '')
+ {
+ return $this->item->sanitize($data, $type, $base);
+ }
+
+ function get_item()
+ {
+ return $this->item;
+ }
+
+ function get_title()
+ {
+ if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags('', 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_category($key = 0)
+ {
+ $categories = $this->get_categories();
+ if (isset($categories[$key]))
+ {
+ return $categories[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_categories()
+ {
+ $categories = array();
+
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
+ {
+ $term = null;
+ $scheme = null;
+ $label = null;
+ if (isset($category['attribs']['']['term']))
+ {
+ $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['scheme']))
+ {
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($category['attribs']['']['label']))
+ {
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
+ }
+ foreach ((array) $this->get_source_tags('', 'category') as $category)
+ {
+ $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
+ {
+ $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
+ {
+ $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+
+ if (!empty($categories))
+ {
+ return SimplePie_Misc::array_unique($categories);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_author($key = 0)
+ {
+ $authors = $this->get_authors();
+ if (isset($authors[$key]))
+ {
+ return $authors[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_authors()
+ {
+ $authors = array();
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
+ {
+ $name = null;
+ $uri = null;
+ $email = null;
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
+ {
+ $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
+ {
+ $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
+ }
+ if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
+ {
+ $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $uri !== null)
+ {
+ $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
+ }
+ }
+ if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
+ {
+ $name = null;
+ $url = null;
+ $email = null;
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
+ {
+ $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
+ {
+ $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
+ }
+ if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
+ {
+ $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $url !== null)
+ {
+ $authors[] =& new $this->item->feed->author_class($name, $url, $email);
+ }
+ }
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
+ {
+ $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
+ {
+ $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
+ {
+ $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+ }
+
+ if (!empty($authors))
+ {
+ return SimplePie_Misc::array_unique($authors);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_contributor($key = 0)
+ {
+ $contributors = $this->get_contributors();
+ if (isset($contributors[$key]))
+ {
+ return $contributors[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_contributors()
+ {
+ $contributors = array();
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
+ {
+ $name = null;
+ $uri = null;
+ $email = null;
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
+ {
+ $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
+ {
+ $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
+ {
+ $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $uri !== null)
+ {
+ $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
+ }
+ }
+ foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
+ {
+ $name = null;
+ $url = null;
+ $email = null;
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
+ {
+ $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
+ {
+ $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
+ }
+ if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
+ {
+ $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ if ($name !== null || $email !== null || $url !== null)
+ {
+ $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
+ }
+ }
+
+ if (!empty($contributors))
+ {
+ return SimplePie_Misc::array_unique($contributors);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_link($key = 0, $rel = 'alternate')
+ {
+ $links = $this->get_links($rel);
+ if (isset($links[$key]))
+ {
+ return $links[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Added for parity between the parent-level and the item/entry-level.
+ */
+ function get_permalink()
+ {
+ return $this->get_link(0);
+ }
+
+ function get_links($rel = 'alternate')
+ {
+ if (!isset($this->data['links']))
+ {
+ $this->data['links'] = array();
+ if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
+ {
+ foreach ($links as $link)
+ {
+ if (isset($link['attribs']['']['href']))
+ {
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+ }
+ }
+ }
+ if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
+ {
+ foreach ($links as $link)
+ {
+ if (isset($link['attribs']['']['href']))
+ {
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
+
+ }
+ }
+ }
+ if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+ if ($links = $this->get_source_tags('', 'link'))
+ {
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
+ }
+
+ $keys = array_keys($this->data['links']);
+ foreach ($keys as $key)
+ {
+ if (SimplePie_Misc::is_isegment_nz_nc($key))
+ {
+ if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
+ {
+ $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
+ $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
+ }
+ else
+ {
+ $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
+ }
+ }
+ elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
+ {
+ $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
+ }
+ $this->data['links'][$key] = array_unique($this->data['links'][$key]);
+ }
+ }
+
+ if (isset($this->data['links'][$rel]))
+ {
+ return $this->data['links'][$rel];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_description()
+ {
+ if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags('', 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_copyright()
+ {
+ if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
+ {
+ return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags('', 'copyright'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_language()
+ {
+ if ($return = $this->get_source_tags('', 'language'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ elseif (isset($this->data['xml_lang']))
+ {
+ return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_latitude()
+ {
+ if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
+ {
+ return (float) $match[1];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_longitude()
+ {
+ if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
+ {
+ return (float) $return[0]['data'];
+ }
+ elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
+ {
+ return (float) $match[2];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_image_url()
+ {
+ if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
+ {
+ return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
+ {
+ return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+class SimplePie_Author
+{
+ var $name;
+ var $link;
+ var $email;
+
+ // Constructor, used to input the data
+ function SimplePie_Author($name = null, $link = null, $email = null)
+ {
+ $this->name = $name;
+ $this->link = $link;
+ $this->email = $email;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_name()
+ {
+ if ($this->name !== null)
+ {
+ return $this->name;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_link()
+ {
+ if ($this->link !== null)
+ {
+ return $this->link;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_email()
+ {
+ if ($this->email !== null)
+ {
+ return $this->email;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+class SimplePie_Category
+{
+ var $term;
+ var $scheme;
+ var $label;
+
+ // Constructor, used to input the data
+ function SimplePie_Category($term = null, $scheme = null, $label = null)
+ {
+ $this->term = $term;
+ $this->scheme = $scheme;
+ $this->label = $label;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_term()
+ {
+ if ($this->term !== null)
+ {
+ return $this->term;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_scheme()
+ {
+ if ($this->scheme !== null)
+ {
+ return $this->scheme;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_label()
+ {
+ if ($this->label !== null)
+ {
+ return $this->label;
+ }
+ else
+ {
+ return $this->get_term();
+ }
+ }
+}
+
+class SimplePie_Enclosure
+{
+ var $bitrate;
+ var $captions;
+ var $categories;
+ var $channels;
+ var $copyright;
+ var $credits;
+ var $description;
+ var $duration;
+ var $expression;
+ var $framerate;
+ var $handler;
+ var $hashes;
+ var $height;
+ var $javascript;
+ var $keywords;
+ var $lang;
+ var $length;
+ var $link;
+ var $medium;
+ var $player;
+ var $ratings;
+ var $restrictions;
+ var $samplingrate;
+ var $thumbnails;
+ var $title;
+ var $type;
+ var $width;
+
+ // Constructor, used to input the data
+ function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
+ {
+ $this->bitrate = $bitrate;
+ $this->captions = $captions;
+ $this->categories = $categories;
+ $this->channels = $channels;
+ $this->copyright = $copyright;
+ $this->credits = $credits;
+ $this->description = $description;
+ $this->duration = $duration;
+ $this->expression = $expression;
+ $this->framerate = $framerate;
+ $this->hashes = $hashes;
+ $this->height = $height;
+ $this->javascript = $javascript;
+ $this->keywords = $keywords;
+ $this->lang = $lang;
+ $this->length = $length;
+ $this->link = $link;
+ $this->medium = $medium;
+ $this->player = $player;
+ $this->ratings = $ratings;
+ $this->restrictions = $restrictions;
+ $this->samplingrate = $samplingrate;
+ $this->thumbnails = $thumbnails;
+ $this->title = $title;
+ $this->type = $type;
+ $this->width = $width;
+ if (class_exists('idna_convert'))
+ {
+ $idn =& new idna_convert;
+ $parsed = SimplePie_Misc::parse_url($link);
+ $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
+ }
+ $this->handler = $this->get_handler(); // Needs to load last
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_bitrate()
+ {
+ if ($this->bitrate !== null)
+ {
+ return $this->bitrate;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_caption($key = 0)
+ {
+ $captions = $this->get_captions();
+ if (isset($captions[$key]))
+ {
+ return $captions[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_captions()
+ {
+ if ($this->captions !== null)
+ {
+ return $this->captions;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_category($key = 0)
+ {
+ $categories = $this->get_categories();
+ if (isset($categories[$key]))
+ {
+ return $categories[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_categories()
+ {
+ if ($this->categories !== null)
+ {
+ return $this->categories;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_channels()
+ {
+ if ($this->channels !== null)
+ {
+ return $this->channels;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_copyright()
+ {
+ if ($this->copyright !== null)
+ {
+ return $this->copyright;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_credit($key = 0)
+ {
+ $credits = $this->get_credits();
+ if (isset($credits[$key]))
+ {
+ return $credits[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_credits()
+ {
+ if ($this->credits !== null)
+ {
+ return $this->credits;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_description()
+ {
+ if ($this->description !== null)
+ {
+ return $this->description;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_duration($convert = false)
+ {
+ if ($this->duration !== null)
+ {
+ if ($convert)
+ {
+ $time = SimplePie_Misc::time_hms($this->duration);
+ return $time;
+ }
+ else
+ {
+ return $this->duration;
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_expression()
+ {
+ if ($this->expression !== null)
+ {
+ return $this->expression;
+ }
+ else
+ {
+ return 'full';
+ }
+ }
+
+ function get_extension()
+ {
+ if ($this->link !== null)
+ {
+ $url = SimplePie_Misc::parse_url($this->link);
+ if ($url['path'] !== '')
+ {
+ return pathinfo($url['path'], PATHINFO_EXTENSION);
+ }
+ }
+ return null;
+ }
+
+ function get_framerate()
+ {
+ if ($this->framerate !== null)
+ {
+ return $this->framerate;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_handler()
+ {
+ return $this->get_real_type(true);
+ }
+
+ function get_hash($key = 0)
+ {
+ $hashes = $this->get_hashes();
+ if (isset($hashes[$key]))
+ {
+ return $hashes[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_hashes()
+ {
+ if ($this->hashes !== null)
+ {
+ return $this->hashes;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_height()
+ {
+ if ($this->height !== null)
+ {
+ return $this->height;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_language()
+ {
+ if ($this->lang !== null)
+ {
+ return $this->lang;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_keyword($key = 0)
+ {
+ $keywords = $this->get_keywords();
+ if (isset($keywords[$key]))
+ {
+ return $keywords[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_keywords()
+ {
+ if ($this->keywords !== null)
+ {
+ return $this->keywords;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_length()
+ {
+ if ($this->length !== null)
+ {
+ return $this->length;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_link()
+ {
+ if ($this->link !== null)
+ {
+ return urldecode($this->link);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_medium()
+ {
+ if ($this->medium !== null)
+ {
+ return $this->medium;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_player()
+ {
+ if ($this->player !== null)
+ {
+ return $this->player;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_rating($key = 0)
+ {
+ $ratings = $this->get_ratings();
+ if (isset($ratings[$key]))
+ {
+ return $ratings[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_ratings()
+ {
+ if ($this->ratings !== null)
+ {
+ return $this->ratings;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_restriction($key = 0)
+ {
+ $restrictions = $this->get_restrictions();
+ if (isset($restrictions[$key]))
+ {
+ return $restrictions[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_restrictions()
+ {
+ if ($this->restrictions !== null)
+ {
+ return $this->restrictions;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_sampling_rate()
+ {
+ if ($this->samplingrate !== null)
+ {
+ return $this->samplingrate;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_size()
+ {
+ $length = $this->get_length();
+ if ($length !== null)
+ {
+ return round($length/1048576, 2);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_thumbnail($key = 0)
+ {
+ $thumbnails = $this->get_thumbnails();
+ if (isset($thumbnails[$key]))
+ {
+ return $thumbnails[$key];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_thumbnails()
+ {
+ if ($this->thumbnails !== null)
+ {
+ return $this->thumbnails;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_title()
+ {
+ if ($this->title !== null)
+ {
+ return $this->title;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_type()
+ {
+ if ($this->type !== null)
+ {
+ return $this->type;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_width()
+ {
+ if ($this->width !== null)
+ {
+ return $this->width;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function native_embed($options='')
+ {
+ return $this->embed($options, true);
+ }
+
+ /**
+ * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
+ */
+ function embed($options = '', $native = false)
+ {
+ // Set up defaults
+ $audio = '';
+ $video = '';
+ $alt = '';
+ $altclass = '';
+ $loop = 'false';
+ $width = 'auto';
+ $height = 'auto';
+ $bgcolor = '#ffffff';
+ $mediaplayer = '';
+ $widescreen = false;
+ $handler = $this->get_handler();
+ $type = $this->get_real_type();
+
+ // Process options and reassign values as necessary
+ if (is_array($options))
+ {
+ extract($options);
+ }
+ else
+ {
+ $options = explode(',', $options);
+ foreach($options as $option)
+ {
+ $opt = explode(':', $option, 2);
+ if (isset($opt[0], $opt[1]))
+ {
+ $opt[0] = trim($opt[0]);
+ $opt[1] = trim($opt[1]);
+ switch ($opt[0])
+ {
+ case 'audio':
+ $audio = $opt[1];
+ break;
+
+ case 'video':
+ $video = $opt[1];
+ break;
+
+ case 'alt':
+ $alt = $opt[1];
+ break;
+
+ case 'altclass':
+ $altclass = $opt[1];
+ break;
+
+ case 'loop':
+ $loop = $opt[1];
+ break;
+
+ case 'width':
+ $width = $opt[1];
+ break;
+
+ case 'height':
+ $height = $opt[1];
+ break;
+
+ case 'bgcolor':
+ $bgcolor = $opt[1];
+ break;
+
+ case 'mediaplayer':
+ $mediaplayer = $opt[1];
+ break;
+
+ case 'widescreen':
+ $widescreen = $opt[1];
+ break;
+ }
+ }
+ }
+ }
+
+ $mime = explode('/', $type, 2);
+ $mime = $mime[0];
+
+ // Process values for 'auto'
+ if ($width == 'auto')
+ {
+ if ($mime == 'video')
+ {
+ if ($height == 'auto')
+ {
+ $width = 480;
+ }
+ elseif ($widescreen)
+ {
+ $width = round((intval($height)/9)*16);
+ }
+ else
+ {
+ $width = round((intval($height)/3)*4);
+ }
+ }
+ else
+ {
+ $width = '100%';
+ }
+ }
+
+ if ($height == 'auto')
+ {
+ if ($mime == 'audio')
+ {
+ $height = 0;
+ }
+ elseif ($mime == 'video')
+ {
+ if ($width == 'auto')
+ {
+ if ($widescreen)
+ {
+ $height = 270;
+ }
+ else
+ {
+ $height = 360;
+ }
+ }
+ elseif ($widescreen)
+ {
+ $height = round((intval($width)/16)*9);
+ }
+ else
+ {
+ $height = round((intval($width)/4)*3);
+ }
+ }
+ else
+ {
+ $height = 376;
+ }
+ }
+ elseif ($mime == 'audio')
+ {
+ $height = 0;
+ }
+
+ // Set proper placeholder value
+ if ($mime == 'audio')
+ {
+ $placeholder = $audio;
+ }
+ elseif ($mime == 'video')
+ {
+ $placeholder = $video;
+ }
+
+ $embed = '';
+
+ // Make sure the JS library is included
+ if (!$native)
+ {
+ static $javascript_outputted = null;
+ if (!$javascript_outputted && $this->javascript)
+ {
+ $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
+ $javascript_outputted = true;
+ }
+ }
+
+ // Odeo Feed MP3's
+ if ($handler == 'odeo')
+ {
+ if ($native)
+ {
+ $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
+ }
+ else
+ {
+ $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
+ }
+ }
+
+ // Flash
+ elseif ($handler == 'flash')
+ {
+ if ($native)
+ {
+ $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
+ }
+ else
+ {
+ $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
+ }
+ }
+
+ // Flash Media Player file types.
+ // Preferred handler for MP3 file types.
+ elseif ($handler == 'fmedia' || ($handler == 'mp3' && $mediaplayer != ''))
+ {
+ $height += 20;
+ if ($native)
+ {
+ $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
+ }
+ else
+ {
+ $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
+ }
+ }
+
+ // QuickTime 7 file types. Need to test with QuickTime 6.
+ // Only handle MP3's if the Flash Media Player is not present.
+ elseif ($handler == 'quicktime' || ($handler == 'mp3' && $mediaplayer == ''))
+ {
+ $height += 16;
+ if ($native)
+ {
+ if ($placeholder != ""){
+ $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
+ }
+ else {
+ $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
+ }
+ }
+ else
+ {
+ $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
+ }
+ }
+
+ // Windows Media
+ elseif ($handler == 'wmedia')
+ {
+ $height += 45;
+ if ($native)
+ {
+ $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
+ }
+ else
+ {
+ $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
+ }
+ }
+
+ // Everything else
+ else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
+
+ return $embed;
+ }
+
+ function get_real_type($find_handler = false)
+ {
+ // If it's Odeo, let's get it out of the way.
+ if (substr(strtolower($this->get_link()), 0, 15) == 'http://odeo.com')
+ {
+ return 'odeo';
+ }
+
+ // Mime-types by handler.
+ $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
+ $types_fmedia = array('video/flv', 'video/x-flv'); // Flash Media Player
+ $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
+ $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
+ $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
+
+ if ($this->get_type() !== null)
+ {
+ $type = strtolower($this->type);
+ }
+ else
+ {
+ $type = null;
+ }
+
+ // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
+ if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
+ {
+ switch (strtolower($this->get_extension()))
+ {
+ // Audio mime-types
+ case 'aac':
+ case 'adts':
+ $type = 'audio/acc';
+ break;
+
+ case 'aif':
+ case 'aifc':
+ case 'aiff':
+ case 'cdda':
+ $type = 'audio/aiff';
+ break;
+
+ case 'bwf':
+ $type = 'audio/wav';
+ break;
+
+ case 'kar':
+ case 'mid':
+ case 'midi':
+ case 'smf':
+ $type = 'audio/midi';
+ break;
+
+ case 'm4a':
+ $type = 'audio/x-m4a';
+ break;
+
+ case 'mp3':
+ case 'swa':
+ $type = 'audio/mp3';
+ break;
+
+ case 'wav':
+ $type = 'audio/wav';
+ break;
+
+ case 'wax':
+ $type = 'audio/x-ms-wax';
+ break;
+
+ case 'wma':
+ $type = 'audio/x-ms-wma';
+ break;
+
+ // Video mime-types
+ case '3gp':
+ case '3gpp':
+ $type = 'video/3gpp';
+ break;
+
+ case '3g2':
+ case '3gp2':
+ $type = 'video/3gpp2';
+ break;
+
+ case 'asf':
+ $type = 'video/x-ms-asf';
+ break;
+
+ case 'flv':
+ $type = 'video/x-flv';
+ break;
+
+ case 'm1a':
+ case 'm1s':
+ case 'm1v':
+ case 'm15':
+ case 'm75':
+ case 'mp2':
+ case 'mpa':
+ case 'mpeg':
+ case 'mpg':
+ case 'mpm':
+ case 'mpv':
+ $type = 'video/mpeg';
+ break;
+
+ case 'm4v':
+ $type = 'video/x-m4v';
+ break;
+
+ case 'mov':
+ case 'qt':
+ $type = 'video/quicktime';
+ break;
+
+ case 'mp4':
+ case 'mpg4':
+ $type = 'video/mp4';
+ break;
+
+ case 'sdv':
+ $type = 'video/sd-video';
+ break;
+
+ case 'wm':
+ $type = 'video/x-ms-wm';
+ break;
+
+ case 'wmv':
+ $type = 'video/x-ms-wmv';
+ break;
+
+ case 'wvx':
+ $type = 'video/x-ms-wvx';
+ break;
+
+ // Flash mime-types
+ case 'spl':
+ $type = 'application/futuresplash';
+ break;
+
+ case 'swf':
+ $type = 'application/x-shockwave-flash';
+ break;
+ }
+ }
+
+ if ($find_handler)
+ {
+ if (in_array($type, $types_flash))
+ {
+ return 'flash';
+ }
+ elseif (in_array($type, $types_fmedia))
+ {
+ return 'fmedia';
+ }
+ elseif (in_array($type, $types_quicktime))
+ {
+ return 'quicktime';
+ }
+ elseif (in_array($type, $types_wmedia))
+ {
+ return 'wmedia';
+ }
+ elseif (in_array($type, $types_mp3))
+ {
+ return 'mp3';
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ return $type;
+ }
+ }
+}
+
+class SimplePie_Caption
+{
+ var $type;
+ var $lang;
+ var $startTime;
+ var $endTime;
+ var $text;
+
+ // Constructor, used to input the data
+ function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
+ {
+ $this->type = $type;
+ $this->lang = $lang;
+ $this->startTime = $startTime;
+ $this->endTime = $endTime;
+ $this->text = $text;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_endtime()
+ {
+ if ($this->endTime !== null)
+ {
+ return $this->endTime;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_language()
+ {
+ if ($this->lang !== null)
+ {
+ return $this->lang;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_starttime()
+ {
+ if ($this->startTime !== null)
+ {
+ return $this->startTime;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_text()
+ {
+ if ($this->text !== null)
+ {
+ return $this->text;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_type()
+ {
+ if ($this->type !== null)
+ {
+ return $this->type;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+class SimplePie_Credit
+{
+ var $role;
+ var $scheme;
+ var $name;
+
+ // Constructor, used to input the data
+ function SimplePie_Credit($role = null, $scheme = null, $name = null)
+ {
+ $this->role = $role;
+ $this->scheme = $scheme;
+ $this->name = $name;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_role()
+ {
+ if ($this->role !== null)
+ {
+ return $this->role;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_scheme()
+ {
+ if ($this->scheme !== null)
+ {
+ return $this->scheme;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_name()
+ {
+ if ($this->name !== null)
+ {
+ return $this->name;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+class SimplePie_Copyright
+{
+ var $url;
+ var $label;
+
+ // Constructor, used to input the data
+ function SimplePie_Copyright($url = null, $label = null)
+ {
+ $this->url = $url;
+ $this->label = $label;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_url()
+ {
+ if ($this->url !== null)
+ {
+ return $this->url;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_attribution()
+ {
+ if ($this->label !== null)
+ {
+ return $this->label;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+class SimplePie_Rating
+{
+ var $scheme;
+ var $value;
+
+ // Constructor, used to input the data
+ function SimplePie_Rating($scheme = null, $value = null)
+ {
+ $this->scheme = $scheme;
+ $this->value = $value;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_scheme()
+ {
+ if ($this->scheme !== null)
+ {
+ return $this->scheme;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_value()
+ {
+ if ($this->value !== null)
+ {
+ return $this->value;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+class SimplePie_Restriction
+{
+ var $relationship;
+ var $type;
+ var $value;
+
+ // Constructor, used to input the data
+ function SimplePie_Restriction($relationship = null, $type = null, $value = null)
+ {
+ $this->relationship = $relationship;
+ $this->type = $type;
+ $this->value = $value;
+ }
+
+ function __toString()
+ {
+ // There is no $this->data here
+ return md5(serialize($this));
+ }
+
+ function get_relationship()
+ {
+ if ($this->relationship !== null)
+ {
+ return $this->relationship;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_type()
+ {
+ if ($this->type !== null)
+ {
+ return $this->type;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ function get_value()
+ {
+ if ($this->value !== null)
+ {
+ return $this->value;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+/**
+ * @todo Move to properly supporting RFC2616 (HTTP/1.1)
+ */
+class SimplePie_File
+{
+ var $url;
+ var $useragent;
+ var $success = true;
+ var $headers = array();
+ var $body;
+ var $status_code;
+ var $redirects = 0;
+ var $error;
+ var $method = SIMPLEPIE_FILE_SOURCE_NONE;
+
+ function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
+ {
+ if (class_exists('idna_convert'))
+ {
+ $idn =& new idna_convert;
+ $parsed = SimplePie_Misc::parse_url($url);
+ $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
+ }
+ $this->url = $url;
+ $this->useragent = $useragent;
+ if (preg_match('/^http(s)?:\/\//i', $url))
+ {
+ if ($useragent === null)
+ {
+ $useragent = ini_get('user_agent');
+ $this->useragent = $useragent;
+ }
+ if (!is_array($headers))
+ {
+ $headers = array();
+ }
+ if (!$force_fsockopen && function_exists('curl_exec'))
+ {
+ $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
+ $fp = curl_init();
+ $headers2 = array();
+ foreach ($headers as $key => $value)
+ {
+ $headers2[] = "$key: $value";
+ }
+ if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
+ {
+ curl_setopt($fp, CURLOPT_ENCODING, '');
+ }
+ curl_setopt($fp, CURLOPT_URL, $url);
+ curl_setopt($fp, CURLOPT_HEADER, 1);
+ curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
+ curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
+ curl_setopt($fp, CURLOPT_REFERER, $url);
+ curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
+ curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
+ if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
+ {
+ curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
+ }
+
+ $this->headers = curl_exec($fp);
+ if (curl_errno($fp) == 23 || curl_errno($fp) == 61)
+ {
+ curl_setopt($fp, CURLOPT_ENCODING, 'none');
+ $this->headers = curl_exec($fp);
+ }
+ if (curl_errno($fp))
+ {
+ $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
+ $this->success = false;
+ }
+ else
+ {
+ $info = curl_getinfo($fp);
+ curl_close($fp);
+ $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
+ $this->headers = array_pop($this->headers);
+ $parser =& new SimplePie_HTTP_Parser($this->headers);
+ if ($parser->parse())
+ {
+ $this->headers = $parser->headers;
+ $this->body = $parser->body;
+ $this->status_code = $parser->status_code;
+ if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303 || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
+ {
+ $this->redirects++;
+ $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
+ return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
+ }
+ }
+ }
+ }
+ else
+ {
+ $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
+ $url_parts = parse_url($url);
+ if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) == 'https')
+ {
+ $url_parts['host'] = "ssl://$url_parts[host]";
+ $url_parts['port'] = 443;
+ }
+ if (!isset($url_parts['port']))
+ {
+ $url_parts['port'] = 80;
+ }
+ $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
+ if (!$fp)
+ {
+ $this->error = 'fsockopen error: ' . $errstr;
+ $this->success = false;
+ }
+ else
+ {
+ stream_set_timeout($fp, $timeout);
+ if (isset($url_parts['path']))
+ {
+ if (isset($url_parts['query']))
+ {
+ $get = "$url_parts[path]?$url_parts[query]";
+ }
+ else
+ {
+ $get = $url_parts['path'];
+ }
+ }
+ else
+ {
+ $get = '/';
+ }
+ $out = "GET $get HTTP/1.0\r\n";
+ $out .= "Host: $url_parts[host]\r\n";
+ $out .= "User-Agent: $useragent\r\n";
+ if (function_exists('gzinflate'))
+ {
+ $out .= "Accept-Encoding: gzip,deflate\r\n";
+ }
+
+ if (isset($url_parts['user']) && isset($url_parts['pass']))
+ {
+ $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
+ }
+ foreach ($headers as $key => $value)
+ {
+ $out .= "$key: $value\r\n";
+ }
+ $out .= "Connection: Close\r\n\r\n";
+ fwrite($fp, $out);
+
+ $info = stream_get_meta_data($fp);
+
+ $this->headers = '';
+ while (!$info['eof'] && !$info['timed_out'])
+ {
+ $this->headers .= fread($fp, 1160);
+ $info = stream_get_meta_data($fp);
+ }
+ if (!$info['timed_out'])
+ {
+ $parser =& new SimplePie_HTTP_Parser($this->headers);
+ if ($parser->parse())
+ {
+ $this->headers = $parser->headers;
+ $this->body = $parser->body;
+ $this->status_code = $parser->status_code;
+ if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303 || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
+ {
+ $this->redirects++;
+ $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
+ return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
+ }
+ if (isset($this->headers['content-encoding']) && ($this->headers['content-encoding'] == 'gzip' || $this->headers['content-encoding'] == 'deflate'))
+ {
+ if (substr($this->body, 0, 8) == "\x1f\x8b\x08\x00\x00\x00\x00\x00")
+ {
+ $this->body = substr($this->body, 10);
+ }
+ $this->body = gzinflate($this->body);
+ }
+ }
+ }
+ else
+ {
+ $this->error = 'fsocket timed out';
+ $this->success = false;
+ }
+ fclose($fp);
+ }
+ }
+ }
+ else
+ {
+ $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
+ if (!$this->body = file_get_contents($url))
+ {
+ $this->error = 'file_get_contents could not read the file';
+ $this->success = false;
+ }
+ }
+ }
+}
+
+/**
+ * HTTP Response Parser
+ *
+ * @package SimplePie
+ */
+class SimplePie_HTTP_Parser
+{
+ /**
+ * HTTP Version
+ *
+ * @access public
+ * @var float
+ */
+ var $http_version = 0.0;
+
+ /**
+ * Status code
+ *
+ * @access public
+ * @var int
+ */
+ var $status_code = 0;
+
+ /**
+ * Reason phrase
+ *
+ * @access public
+ * @var string
+ */
+ var $reason = '';
+
+ /**
+ * Key/value pairs of the headers
+ *
+ * @access public
+ * @var array
+ */
+ var $headers = array();
+
+ /**
+ * Body of the response
+ *
+ * @access public
+ * @var string
+ */
+ var $body = '';
+
+ /**
+ * Current state of the state machine
+ *
+ * @access private
+ * @var string
+ */
+ var $state = 'http_version';
+
+ /**
+ * Input data
+ *
+ * @access private
+ * @var string
+ */
+ var $data = '';
+
+ /**
+ * Input data length (to avoid calling strlen() everytime this is needed)
+ *
+ * @access private
+ * @var int
+ */
+ var $data_length = 0;
+
+ /**
+ * Current position of the pointer
+ *
+ * @var int
+ * @access private
+ */
+ var $position = 0;
+
+ /**
+ * Name of the hedaer currently being parsed
+ *
+ * @access private
+ * @var string
+ */
+ var $name = '';
+
+ /**
+ * Value of the hedaer currently being parsed
+ *
+ * @access private
+ * @var string
+ */
+ var $value = '';
+
+ /**
+ * Create an instance of the class with the input data
+ *
+ * @access public
+ * @param string $data Input data
+ */
+ function SimplePie_HTTP_Parser($data)
+ {
+ $this->data = $data;
+ $this->data_length = strlen($this->data);
+ }
+
+ /**
+ * Parse the input data
+ *
+ * @access public
+ * @return bool true on success, false on failure
+ */
+ function parse()
+ {
+ while ($this->state && $this->state !== 'emit' && $this->has_data())
+ {
+ $state = $this->state;
+ $this->$state();
+ }
+ $this->data = '';
+ if ($this->state === 'emit' || $this->state === 'body')
+ {
+ return true;
+ }
+ else
+ {
+ $this->http_version = '';
+ $this->status_code = '';
+ $this->reason = '';
+ $this->headers = array();
+ $this->body = '';
+ return false;
+ }
+ }
+
+ /**
+ * Check whether there is data beyond the pointer
+ *
+ * @access private
+ * @return bool true if there is further data, false if not
+ */
+ function has_data()
+ {
+ return (bool) ($this->position < $this->data_length);
+ }
+
+ /**
+ * See if the next character is LWS
+ *
+ * @access private
+ * @return bool true if the next character is LWS, false if not
+ */
+ function is_linear_whitespace()
+ {
+ return (bool) ($this->data[$this->position] === "\x09"
+ || $this->data[$this->position] === "\x20"
+ || ($this->data[$this->position] === "\x0A"
+ && isset($this->data[$this->position + 1])
+ && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
+ }
+
+ /**
+ * Parse the HTTP version
+ *
+ * @access private
+ */
+ function http_version()
+ {
+ if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
+ {
+ $len = strspn($this->data, '0123456789.', 5);
+ $this->http_version = substr($this->data, 5, $len);
+ $this->position += 5 + $len;
+ if (substr_count($this->http_version, '.') <= 1)
+ {
+ $this->http_version = (float) $this->http_version;
+ $this->position += strspn($this->data, "\x09\x20", $this->position);
+ $this->state = 'status';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ /**
+ * Parse the status code
+ *
+ * @access private
+ */
+ function status()
+ {
+ if ($len = strspn($this->data, '0123456789', $this->position))
+ {
+ $this->status_code = (int) substr($this->data, $this->position, $len);
+ $this->position += $len;
+ $this->state = 'reason';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ /**
+ * Parse the reason phrase
+ *
+ * @access private
+ */
+ function reason()
+ {
+ $len = strcspn($this->data, "\x0A", $this->position);
+ $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
+ $this->position += $len + 1;
+ $this->state = 'new_line';
+ }
+
+ /**
+ * Deal with a new line, shifting data around as needed
+ *
+ * @access private
+ */
+ function new_line()
+ {
+ $this->value = trim($this->value, "\x0D\x20");
+ if ($this->name !== '' && $this->value !== '')
+ {
+ $this->name = strtolower($this->name);
+ if (isset($this->headers[$this->name]))
+ {
+ $this->headers[$this->name] .= ', ' . $this->value;
+ }
+ else
+ {
+ $this->headers[$this->name] = $this->value;
+ }
+ }
+ $this->name = '';
+ $this->value = '';
+ if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
+ {
+ $this->position += 2;
+ $this->state = 'body';
+ }
+ elseif ($this->data[$this->position] === "\x0A")
+ {
+ $this->position++;
+ $this->state = 'body';
+ }
+ else
+ {
+ $this->state = 'name';
+ }
+ }
+
+ /**
+ * Parse a header name
+ *
+ * @access private
+ */
+ function name()
+ {
+ $len = strcspn($this->data, "\x0A:", $this->position);
+ if (isset($this->data[$this->position + $len]))
+ {
+ if ($this->data[$this->position + $len] === "\x0A")
+ {
+ $this->position += $len;
+ $this->state = 'new_line';
+ }
+ else
+ {
+ $this->name = substr($this->data, $this->position, $len);
+ $this->position += $len + 1;
+ $this->state = 'value';
+ }
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ /**
+ * Parse LWS, replacing consecutive LWS characters with a single space
+ *
+ * @access private
+ */
+ function linear_whitespace()
+ {
+ do
+ {
+ if (substr($this->data, $this->position, 2) === "\x0D\x0A")
+ {
+ $this->position += 2;
+ }
+ elseif ($this->data[$this->position] === "\x0A")
+ {
+ $this->position++;
+ }
+ $this->position += strspn($this->data, "\x09\x20", $this->position);
+ } while ($this->has_data() && $this->is_linear_whitespace());
+ $this->value .= "\x20";
+ }
+
+ /**
+ * See what state to move to while within non-quoted header values
+ *
+ * @access private
+ */
+ function value()
+ {
+ if ($this->is_linear_whitespace())
+ {
+ $this->linear_whitespace();
+ }
+ else
+ {
+ switch ($this->data[$this->position])
+ {
+ case '"':
+ $this->position++;
+ $this->state = 'quote';
+ break;
+
+ case "\x0A":
+ $this->position++;
+ $this->state = 'new_line';
+ break;
+
+ default:
+ $this->state = 'value_char';
+ break;
+ }
+ }
+ }
+
+ /**
+ * Parse a header value while outside quotes
+ *
+ * @access private
+ */
+ function value_char()
+ {
+ $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
+ $this->value .= substr($this->data, $this->position, $len);
+ $this->position += $len;
+ $this->state = 'value';
+ }
+
+ /**
+ * See what state to move to while within quoted header values
+ *
+ * @access private
+ */
+ function quote()
+ {
+ if ($this->is_linear_whitespace())
+ {
+ $this->linear_whitespace();
+ }
+ else
+ {
+ switch ($this->data[$this->position])
+ {
+ case '"':
+ $this->position++;
+ $this->state = 'value';
+ break;
+
+ case "\x0A":
+ $this->position++;
+ $this->state = 'new_line';
+ break;
+
+ case '\\':
+ $this->position++;
+ $this->state = 'quote_escaped';
+ break;
+
+ default:
+ $this->state = 'quote_char';
+ break;
+ }
+ }
+ }
+
+ /**
+ * Parse a header value while within quotes
+ *
+ * @access private
+ */
+ function quote_char()
+ {
+ $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
+ $this->value .= substr($this->data, $this->position, $len);
+ $this->position += $len;
+ $this->state = 'value';
+ }
+
+ /**
+ * Parse an escaped character within quotes
+ *
+ * @access private
+ */
+ function quote_escaped()
+ {
+ $this->value .= $this->data[$this->position];
+ $this->position++;
+ $this->state = 'quote';
+ }
+
+ /**
+ * Parse the body
+ *
+ * @access private
+ */
+ function body()
+ {
+ $this->body = substr($this->data, $this->position);
+ $this->state = 'emit';
+ }
+}
+
+class SimplePie_Cache
+{
+ /**
+ * Don't call the constructor. Please.
+ *
+ * @access private
+ */
+ function SimplePie_Cache()
+ {
+ trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
+ }
+
+ /**
+ * Create a new SimplePie_Cache object
+ *
+ * @static
+ * @access public
+ */
+ function create($location, $filename, $extension)
+ {
+ return new SimplePie_Cache_File($location, $filename, $extension);
+ }
+}
+
+class SimplePie_Cache_File
+{
+ var $location;
+ var $filename;
+ var $extension;
+ var $name;
+
+ function SimplePie_Cache_File($location, $filename, $extension)
+ {
+ $this->location = $location;
+ $this->filename = rawurlencode($filename);
+ $this->extension = rawurlencode($extension);
+ $this->name = "$location/$this->filename.$this->extension";
+ }
+
+ function save($data)
+ {
+ if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
+ {
+ if (is_a($data, 'SimplePie'))
+ {
+ $data = $data->data;
+ }
+
+ $data = serialize($data);
+
+ if (function_exists('file_put_contents'))
+ {
+ return (bool) file_put_contents($this->name, $data);
+ }
+ else
+ {
+ $fp = fopen($this->name, 'wb');
+ if ($fp)
+ {
+ fwrite($fp, $data);
+ fclose($fp);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function load()
+ {
+ if (file_exists($this->name) && is_readable($this->name))
+ {
+ return unserialize(file_get_contents($this->name));
+ }
+ return false;
+ }
+
+ function mtime()
+ {
+ if (file_exists($this->name))
+ {
+ return filemtime($this->name);
+ }
+ return false;
+ }
+
+ function touch()
+ {
+ if (file_exists($this->name))
+ {
+ return touch($this->name);
+ }
+ return false;
+ }
+
+ function unlink()
+ {
+ if (file_exists($this->name))
+ {
+ return unlink($this->name);
+ }
+ return false;
+ }
+}
+
+class SimplePie_Misc
+{
+ function time_hms($seconds)
+ {
+ $time = '';
+
+ $hours = floor($seconds / 3600);
+ $remainder = $seconds % 3600;
+ if ($hours > 0)
+ {
+ $time .= $hours.':';
+ }
+
+ $minutes = floor($remainder / 60);
+ $seconds = $remainder % 60;
+ if ($minutes < 10 && $hours > 0)
+ {
+ $minutes = '0' . $minutes;
+ }
+ if ($seconds < 10)
+ {
+ $seconds = '0' . $seconds;
+ }
+
+ $time .= $minutes.':';
+ $time .= $seconds;
+
+ return $time;
+ }
+
+ function absolutize_url($relative, $base)
+ {
+ if ($relative !== '')
+ {
+ $relative = SimplePie_Misc::parse_url($relative);
+ if ($relative['scheme'] !== '')
+ {
+ $target = $relative;
+ }
+ elseif ($base !== '')
+ {
+ $base = SimplePie_Misc::parse_url($base);
+ $target = SimplePie_Misc::parse_url('');
+ if ($relative['authority'] !== '')
+ {
+ $target = $relative;
+ $target['scheme'] = $base['scheme'];
+ }
+ else
+ {
+ $target['scheme'] = $base['scheme'];
+ $target['authority'] = $base['authority'];
+ if ($relative['path'] !== '')
+ {
+ if (strpos($relative['path'], '/') === 0)
+ {
+ $target['path'] = $relative['path'];
+ }
+ elseif ($base['authority'] !== '' && $base['path'] === '')
+ {
+ $target['path'] = '/' . $relative['path'];
+ }
+ elseif (($last_segment = strrpos($base['path'], '/')) !== false)
+ {
+ $target['path'] = substr($base['path'], 0, $last_segment + 1) . $relative['path'];
+ }
+ else
+ {
+ $target['path'] = $relative['path'];
+ }
+ $target['query'] = $relative['query'];
+ }
+ else
+ {
+ $target['path'] = $base['path'];
+ if ($relative['query'] !== '')
+ {
+ $target['query'] = $relative['query'];
+ }
+ elseif ($base['query'] !== '')
+ {
+ $target['query'] = $base['query'];
+ }
+ }
+ }
+ $target['fragment'] = $relative['fragment'];
+ }
+ else
+ {
+ // No base URL, just return the relative URL
+ $target = $relative;
+ }
+ $return = SimplePie_Misc::compress_parse_url($target['scheme'], $target['authority'], $target['path'], $target['query'], $target['fragment']);
+ }
+ else
+ {
+ $return = $base;
+ }
+ $return = SimplePie_Misc::normalize_url($return);
+ return $return;
+ }
+
+ function remove_dot_segments($input)
+ {
+ $output = '';
+ while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input == '.' || $input == '..')
+ {
+ // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
+ if (strpos($input, '../') === 0)
+ {
+ $input = substr($input, 3);
+ }
+ elseif (strpos($input, './') === 0)
+ {
+ $input = substr($input, 2);
+ }
+ // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
+ elseif (strpos($input, '/./') === 0)
+ {
+ $input = substr_replace($input, '/', 0, 3);
+ }
+ elseif ($input == '/.')
+ {
+ $input = '/';
+ }
+ // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
+ elseif (strpos($input, '/../') === 0)
+ {
+ $input = substr_replace($input, '/', 0, 4);
+ $output = substr_replace($output, '', strrpos($output, '/'));
+ }
+ elseif ($input == '/..')
+ {
+ $input = '/';
+ $output = substr_replace($output, '', strrpos($output, '/'));
+ }
+ // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
+ elseif ($input == '.' || $input == '..')
+ {
+ $input = '';
+ }
+ // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
+ elseif (($pos = strpos($input, '/', 1)) !== false)
+ {
+ $output .= substr($input, 0, $pos);
+ $input = substr_replace($input, '', 0, $pos);
+ }
+ else
+ {
+ $output .= $input;
+ $input = '';
+ }
+ }
+ return $output . $input;
+ }
+
+ function get_element($realname, $string)
+ {
+ $return = array();
+ $name = preg_quote($realname, '/');
+ if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
+ {
+ for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
+ {
+ $return[$i]['tag'] = $realname;
+ $return[$i]['full'] = $matches[$i][0][0];
+ $return[$i]['offset'] = $matches[$i][0][1];
+ if (strlen($matches[$i][3][0]) <= 2)
+ {
+ $return[$i]['self_closing'] = true;
+ }
+ else
+ {
+ $return[$i]['self_closing'] = false;
+ $return[$i]['content'] = $matches[$i][4][0];
+ }
+ $return[$i]['attribs'] = array();
+ if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
+ {
+ for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
+ {
+ if (count($attribs[$j]) == 2)
+ {
+ $attribs[$j][2] = $attribs[$j][1];
+ }
+ $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
+ }
+ }
+ }
+ }
+ return $return;
+ }
+
+ function element_implode($element)
+ {
+ $full = "<$element[tag]";
+ foreach ($element['attribs'] as $key => $value)
+ {
+ $key = strtolower($key);
+ $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
+ }
+ if ($element['self_closing'])
+ {
+ $full .= ' />';
+ }
+ else
+ {
+ $full .= ">$element[content]</$element[tag]>";
+ }
+ return $full;
+ }
+
+ function error($message, $level, $file, $line)
+ {
+ switch ($level)
+ {
+ case E_USER_ERROR:
+ $note = 'PHP Error';
+ break;
+ case E_USER_WARNING:
+ $note = 'PHP Warning';
+ break;
+ case E_USER_NOTICE:
+ $note = 'PHP Notice';
+ break;
+ default:
+ $note = 'Unknown Error';
+ break;
+ }
+ error_log("$note: $message in $file on line $line", 0);
+ return $message;
+ }
+
+ /**
+ * If a file has been cached, retrieve and display it.
+ *
+ * This is most useful for caching images (get_favicon(), etc.),
+ * however it works for all cached files. This WILL NOT display ANY
+ * file/image/page/whatever, but rather only display what has already
+ * been cached by SimplePie.
+ *
+ * @access public
+ * @see SimplePie::get_favicon()
+ * @param str $identifier_url URL that is used to identify the content.
+ * This may or may not be the actual URL of the live content.
+ * @param str $cache_location Location of SimplePie's cache. Defaults
+ * to './cache'.
+ * @param str $cache_extension The file extension that the file was
+ * cached with. Defaults to 'spc'.
+ * @param str $cache_class Name of the cache-handling class being used
+ * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
+ * as-is unless you've overloaded the class.
+ * @param str $cache_name_function Obsolete. Exists for backwards
+ * compatibility reasons only.
+ */
+ function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
+ {
+ $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
+
+ if ($file = $cache->load())
+ {
+ if (isset($file['headers']['content-type']))
+ {
+ header('Content-type:' . $file['headers']['content-type']);
+ }
+ else
+ {
+ header('Content-type: application/octet-stream');
+ }
+ header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
+ echo $file['body'];
+ exit;
+ }
+
+ die('Cached file for ' . $identifier_url . ' cannot be found.');
+ }
+
+ function fix_protocol($url, $http = 1)
+ {
+ $url = SimplePie_Misc::normalize_url($url);
+ $parsed = SimplePie_Misc::parse_url($url);
+ if ($parsed['scheme'] !== '' && $parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')
+ {
+ return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
+ }
+
+ if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
+ {
+ return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
+ }
+
+ if ($http == 2 && $parsed['scheme'] !== '')
+ {
+ return "feed:$url";
+ }
+ elseif ($http == 3 && strtolower($parsed['scheme']) == 'http')
+ {
+ return substr_replace($url, 'podcast', 0, 4);
+ }
+ elseif ($http == 4 && strtolower($parsed['scheme']) == 'http')
+ {
+ return substr_replace($url, 'itpc', 0, 4);
+ }
+ else
+ {
+ return $url;
+ }
+ }
+
+ function parse_url($url)
+ {
+ static $cache = array();
+ if (isset($cache[$url]))
+ {
+ return $cache[$url];
+ }
+ elseif (preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $url, $match))
+ {
+ for ($i = count($match); $i <= 9; $i++)
+ {
+ $match[$i] = '';
+ }
+ return $cache[$url] = array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
+ }
+ else
+ {
+ return $cache[$url] = array('scheme' => '', 'authority' => '', 'path' => '', 'query' => '', 'fragment' => '');
+ }
+ }
+
+ function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
+ {
+ $return = '';
+ if ($scheme !== '')
+ {
+ $return .= "$scheme:";
+ }
+ if ($authority !== '')
+ {
+ $return .= "//$authority";
+ }
+ if ($path !== '')
+ {
+ $return .= $path;
+ }
+ if ($query !== '')
+ {
+ $return .= "?$query";
+ }
+ if ($fragment !== '')
+ {
+ $return .= "#$fragment";
+ }
+ return $return;
+ }
+
+ function normalize_url($url)
+ {
+ $url = preg_replace_callback('/%([0-9A-Fa-f]{2})/', array('SimplePie_Misc', 'percent_encoding_normalization'), $url);
+ $url = SimplePie_Misc::parse_url($url);
+ $url['scheme'] = strtolower($url['scheme']);
+ if ($url['authority'] !== '')
+ {
+ $url['authority'] = strtolower($url['authority']);
+ $url['path'] = SimplePie_Misc::remove_dot_segments($url['path']);
+ }
+ return SimplePie_Misc::compress_parse_url($url['scheme'], $url['authority'], $url['path'], $url['query'], $url['fragment']);
+ }
+
+ function percent_encoding_normalization($match)
+ {
+ $integer = hexdec($match[1]);
+ if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer == 0x2D || $integer == 0x2E || $integer == 0x5F || $integer == 0x7E)
+ {
+ return chr($integer);
+ }
+ else
+ {
+ return strtoupper($match[0]);
+ }
+ }
+
+ /**
+ * Remove bad UTF-8 bytes
+ *
+ * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
+ * FAQ: Multilingual Forms (modified to include full ASCII range)
+ *
+ * @author Geoffrey Sneddon
+ * @see http://www.w3.org/International/questions/qa-forms-utf-8
+ * @param string $str String to remove bad UTF-8 bytes from
+ * @return string UTF-8 string
+ */
+ function utf8_bad_replace($str)
+ {
+ if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
+ {
+ return $return;
+ }
+ elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
+ {
+ return $return;
+ }
+ elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
+ {
+ return implode("\xEF\xBF\xBD", $matches[0]);
+ }
+ elseif ($str !== '')
+ {
+ return "\xEF\xBF\xBD";
+ }
+ else
+ {
+ return '';
+ }
+ }
+
+ /**
+ * Converts a Windows-1252 encoded string to a UTF-8 encoded string
+ *
+ * @static
+ * @access public
+ * @param string $string Windows-1252 encoded string
+ * @return string UTF-8 encoded string
+ */
+ function windows_1252_to_utf8($string)
+ {
+ static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
+
+ return strtr($string, $convert_table);
+ }
+
+ function change_encoding($data, $input, $output)
+ {
+ $input = SimplePie_Misc::encoding($input);
+ $output = SimplePie_Misc::encoding($output);
+
+ // We fail to fail on non US-ASCII bytes
+ if ($input === 'US-ASCII')
+ {
+ static $non_ascii_octects = '';
+ if (!$non_ascii_octects)
+ {
+ for ($i = 0x80; $i <= 0xFF; $i++)
+ {
+ $non_ascii_octects .= chr($i);
+ }
+ }
+ $data = substr($data, 0, strcspn($data, $non_ascii_octects));
+ }
+
+ if (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
+ {
+ return $return;
+ }
+ elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($data, $output, $input)))
+ {
+ return $return;
+ }
+ elseif ($input == 'windows-1252' && $output == 'UTF-8')
+ {
+ return SimplePie_Misc::windows_1252_to_utf8($data);
+ }
+ elseif ($input == 'UTF-8' && $output == 'windows-1252')
+ {
+ return utf8_decode($data);
+ }
+ return $data;
+ }
+
+ function encoding($encoding)
+ {
+ // Character sets are case-insensitive (though we'll return them in the form given in their registration)
+ switch (strtoupper($encoding))
+ {
+ case 'ANSI_X3.110-1983':
+ case 'CSA_T500-1983':
+ case 'CSISO99NAPLPS':
+ case 'ISO-IR-99':
+ case 'NAPLPS':
+ return 'ANSI_X3.110-1983';
+
+ case 'ARABIC7':
+ case 'ASMO_449':
+ case 'CSISO89ASMO449':
+ case 'ISO-IR-89':
+ case 'ISO_9036':
+ return 'ASMO_449';
+
+ case 'ADOBE-STANDARD-ENCODING':
+ case 'CSADOBESTANDARDENCODING':
+ return 'Adobe-Standard-Encoding';
+
+ case 'ADOBE-SYMBOL-ENCODING':
+ case 'CSHPPSMATH':
+ return 'Adobe-Symbol-Encoding';
+
+ case 'AMI-1251':
+ case 'AMI1251':
+ case 'AMIGA-1251':
+ case 'AMIGA1251':
+ return 'Amiga-1251';
+
+ case 'BOCU-1':
+ case 'CSBOCU-1':
+ return 'BOCU-1';
+
+ case 'BRF':
+ case 'CSBRF':
+ return 'BRF';
+
+ case 'BS_4730':
+ case 'CSISO4UNITEDKINGDOM':
+ case 'GB':
+ case 'ISO-IR-4':
+ case 'ISO646-GB':
+ case 'UK':
+ return 'BS_4730';
+
+ case 'BS_VIEWDATA':
+ case 'CSISO47BSVIEWDATA':
+ case 'ISO-IR-47':
+ return 'BS_viewdata';
+
+ case 'BIG5':
+ case 'CSBIG5':
+ return 'Big5';
+
+ case 'BIG5-HKSCS':
+ return 'Big5-HKSCS';
+
+ case 'CESU-8':
+ case 'CSCESU-8':
+ return 'CESU-8';
+
+ case 'CA':
+ case 'CSA7-1':
+ case 'CSA_Z243.4-1985-1':
+ case 'CSISO121CANADIAN1':
+ case 'ISO-IR-121':
+ case 'ISO646-CA':
+ return 'CSA_Z243.4-1985-1';
+
+ case 'CSA7-2':
+ case 'CSA_Z243.4-1985-2':
+ case 'CSISO122CANADIAN2':
+ case 'ISO-IR-122':
+ case 'ISO646-CA2':
+ return 'CSA_Z243.4-1985-2';
+
+ case 'CSA_Z243.4-1985-GR':
+ case 'CSISO123CSAZ24341985GR':
+ case 'ISO-IR-123':
+ return 'CSA_Z243.4-1985-gr';
+
+ case 'CSISO139CSN369103':
+ case 'CSN_369103':
+ case 'ISO-IR-139':
+ return 'CSN_369103';
+
+ case 'CSDECMCS':
+ case 'DEC':
+ case 'DEC-MCS':
+ return 'DEC-MCS';
+
+ case 'CSISO21GERMAN':
+ case 'DE':
+ case 'DIN_66003':
+ case 'ISO-IR-21':
+ case 'ISO646-DE':
+ return 'DIN_66003';
+
+ case 'CSISO646DANISH':
+ case 'DK':
+ case 'DS2089':
+ case 'DS_2089':
+ case 'ISO646-DK':
+ return 'DS_2089';
+
+ case 'CSIBMEBCDICATDE':
+ case 'EBCDIC-AT-DE':
+ return 'EBCDIC-AT-DE';
+
+ case 'CSEBCDICATDEA':
+ case 'EBCDIC-AT-DE-A':
+ return 'EBCDIC-AT-DE-A';
+
+ case 'CSEBCDICCAFR':
+ case 'EBCDIC-CA-FR':
+ return 'EBCDIC-CA-FR';
+
+ case 'CSEBCDICDKNO':
+ case 'EBCDIC-DK-NO':
+ return 'EBCDIC-DK-NO';
+
+ case 'CSEBCDICDKNOA':
+ case 'EBCDIC-DK-NO-A':
+ return 'EBCDIC-DK-NO-A';
+
+ case 'CSEBCDICES':
+ case 'EBCDIC-ES':
+ return 'EBCDIC-ES';
+
+ case 'CSEBCDICESA':
+ case 'EBCDIC-ES-A':
+ return 'EBCDIC-ES-A';
+
+ case 'CSEBCDICESS':
+ case 'EBCDIC-ES-S':
+ return 'EBCDIC-ES-S';
+
+ case 'CSEBCDICFISE':
+ case 'EBCDIC-FI-SE':
+ return 'EBCDIC-FI-SE';
+
+ case 'CSEBCDICFISEA':
+ case 'EBCDIC-FI-SE-A':
+ return 'EBCDIC-FI-SE-A';
+
+ case 'CSEBCDICFR':
+ case 'EBCDIC-FR':
+ return 'EBCDIC-FR';
+
+ case 'CSEBCDICIT':
+ case 'EBCDIC-IT':
+ return 'EBCDIC-IT';
+
+ case 'CSEBCDICPT':
+ case 'EBCDIC-PT':
+ return 'EBCDIC-PT';
+
+ case 'CSEBCDICUK':
+ case 'EBCDIC-UK':
+ return 'EBCDIC-UK';
+
+ case 'CSEBCDICUS':
+ case 'EBCDIC-US':
+ return 'EBCDIC-US';
+
+ case 'CSISO111ECMACYRILLIC':
+ case 'ECMA-CYRILLIC':
+ case 'ISO-IR-111':
+ case 'KOI8-E':
+ return 'ECMA-cyrillic';
+
+ case 'CSISO17SPANISH':
+ case 'ES':
+ case 'ISO-IR-17':
+ case 'ISO646-ES':
+ return 'ES';
+
+ case 'CSISO85SPANISH2':
+ case 'ES2':
+ case 'ISO-IR-85':
+ case 'ISO646-ES2':
+ return 'ES2';
+
+ case 'CSEUCPKDFMTJAPANESE':
+ case 'EUC-JP':
+ case 'EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE':
+ return 'EUC-JP';
+
+ case 'CSEUCKR':
+ case 'EUC-KR':
+ return 'EUC-KR';
+
+ case 'CSEUCFIXWIDJAPANESE':
+ case 'EXTENDED_UNIX_CODE_FIXED_WIDTH_FOR_JAPANESE':
+ return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
+
+ case 'GB18030':
+ return 'GB18030';
+
+ case 'CSGB2312':
+ case 'GB2312':
+ return 'GB2312';
+
+ case 'CP936':
+ case 'GBK':
+ case 'MS936':
+ case 'WINDOWS-936':
+ return 'GBK';
+
+ case 'CN':
+ case 'CSISO57GB1988':
+ case 'GB_1988-80':
+ case 'ISO-IR-57':
+ case 'ISO646-CN':
+ return 'GB_1988-80';
+
+ case 'CHINESE':
+ case 'CSISO58GB231280':
+ case 'GB_2312-80':
+ case 'ISO-IR-58':
+ return 'GB_2312-80';
+
+ case 'CSISO153GOST1976874':
+ case 'GOST_19768-74':
+ case 'ISO-IR-153':
+ case 'ST_SEV_358-88':
+ return 'GOST_19768-74';
+
+ case 'CSHPDESKTOP':
+ case 'HP-DESKTOP':
+ return 'HP-DeskTop';
+
+ case 'CSHPLEGAL':
+ case 'HP-LEGAL':
+ return 'HP-Legal';
+
+ case 'CSHPMATH8':
+ case 'HP-MATH8':
+ return 'HP-Math8';
+
+ case 'CSHPPIFONT':
+ case 'HP-PI-FONT':
+ return 'HP-Pi-font';
+
+ case 'HZ-GB-2312':
+ return 'HZ-GB-2312';
+
+ case 'CSIBMSYMBOLS':
+ case 'IBM-SYMBOLS':
+ return 'IBM-Symbols';
+
+ case 'CSIBMTHAI':
+ case 'IBM-THAI':
+ return 'IBM-Thai';
+
+ case 'CCSID00858':
+ case 'CP00858':
+ case 'IBM00858':
+ case 'PC-MULTILINGUAL-850+EURO':
+ return 'IBM00858';
+
+ case 'CCSID00924':
+ case 'CP00924':
+ case 'EBCDIC-LATIN9--EURO':
+ case 'IBM00924':
+ return 'IBM00924';
+
+ case 'CCSID01140':
+ case 'CP01140':
+ case 'EBCDIC-US-37+EURO':
+ case 'IBM01140':
+ return 'IBM01140';
+
+ case 'CCSID01141':
+ case 'CP01141':
+ case 'EBCDIC-DE-273+EURO':
+ case 'IBM01141':
+ return 'IBM01141';
+
+ case 'CCSID01142':
+ case 'CP01142':
+ case 'EBCDIC-DK-277+EURO':
+ case 'EBCDIC-NO-277+EURO':
+ case 'IBM01142':
+ return 'IBM01142';
+
+ case 'CCSID01143':
+ case 'CP01143':
+ case 'EBCDIC-FI-278+EURO':
+ case 'EBCDIC-SE-278+EURO':
+ case 'IBM01143':
+ return 'IBM01143';
+
+ case 'CCSID01144':
+ case 'CP01144':
+ case 'EBCDIC-IT-280+EURO':
+ case 'IBM01144':
+ return 'IBM01144';
+
+ case 'CCSID01145':
+ case 'CP01145':
+ case 'EBCDIC-ES-284+EURO':
+ case 'IBM01145':
+ return 'IBM01145';
+
+ case 'CCSID01146':
+ case 'CP01146':
+ case 'EBCDIC-GB-285+EURO':
+ case 'IBM01146':
+ return 'IBM01146';
+
+ case 'CCSID01147':
+ case 'CP01147':
+ case 'EBCDIC-FR-297+EURO':
+ case 'IBM01147':
+ return 'IBM01147';
+
+ case 'CCSID01148':
+ case 'CP01148':
+ case 'EBCDIC-INTERNATIONAL-500+EURO':
+ case 'IBM01148':
+ return 'IBM01148';
+
+ case 'CCSID01149':
+ case 'CP01149':
+ case 'EBCDIC-IS-871+EURO':
+ case 'IBM01149':
+ return 'IBM01149';
+
+ case 'CP037':
+ case 'CSIBM037':
+ case 'EBCDIC-CP-CA':
+ case 'EBCDIC-CP-NL':
+ case 'EBCDIC-CP-US':
+ case 'EBCDIC-CP-WT':
+ case 'IBM037':
+ return 'IBM037';
+
+ case 'CP038':
+ case 'CSIBM038':
+ case 'EBCDIC-INT':
+ case 'IBM038':
+ return 'IBM038';
+
+ case 'CP1026':
+ case 'CSIBM1026':
+ case 'IBM1026':
+ return 'IBM1026';
+
+ case 'IBM-1047':
+ case 'IBM1047':
+ return 'IBM1047';
+
+ case 'CP273':
+ case 'CSIBM273':
+ case 'IBM273':
+ return 'IBM273';
+
+ case 'CP274':
+ case 'CSIBM274':
+ case 'EBCDIC-BE':
+ case 'IBM274':
+ return 'IBM274';
+
+ case 'CP275':
+ case 'CSIBM275':
+ case 'EBCDIC-BR':
+ case 'IBM275':
+ return 'IBM275';
+
+ case 'CSIBM277':
+ case 'EBCDIC-CP-DK':
+ case 'EBCDIC-CP-NO':
+ case 'IBM277':
+ return 'IBM277';
+
+ case 'CP278':
+ case 'CSIBM278':
+ case 'EBCDIC-CP-FI':
+ case 'EBCDIC-CP-SE':
+ case 'IBM278':
+ return 'IBM278';
+
+ case 'CP280':
+ case 'CSIBM280':
+ case 'EBCDIC-CP-IT':
+ case 'IBM280':
+ return 'IBM280';
+
+ case 'CP281':
+ case 'CSIBM281':
+ case 'EBCDIC-JP-E':
+ case 'IBM281':
+ return 'IBM281';
+
+ case 'CP284':
+ case 'CSIBM284':
+ case 'EBCDIC-CP-ES':
+ case 'IBM284':
+ return 'IBM284';
+
+ case 'CP285':
+ case 'CSIBM285':
+ case 'EBCDIC-CP-GB':
+ case 'IBM285':
+ return 'IBM285';
+
+ case 'CP290':
+ case 'CSIBM290':
+ case 'EBCDIC-JP-KANA':
+ case 'IBM290':
+ return 'IBM290';
+
+ case 'CP297':
+ case 'CSIBM297':
+ case 'EBCDIC-CP-FR':
+ case 'IBM297':
+ return 'IBM297';
+
+ case 'CP420':
+ case 'CSIBM420':
+ case 'EBCDIC-CP-AR1':
+ case 'IBM420':
+ return 'IBM420';
+
+ case 'CP423':
+ case 'CSIBM423':
+ case 'EBCDIC-CP-GR':
+ case 'IBM423':
+ return 'IBM423';
+
+ case 'CP424':
+ case 'CSIBM424':
+ case 'EBCDIC-CP-HE':
+ case 'IBM424':
+ return 'IBM424';
+
+ case '437':
+ case 'CP437':
+ case 'CSPC8CODEPAGE437':
+ case 'IBM437':
+ return 'IBM437';
+
+ case 'CP500':
+ case 'CSIBM500':
+ case 'EBCDIC-CP-BE':
+ case 'EBCDIC-CP-CH':
+ case 'IBM500':
+ return 'IBM500';
+
+ case 'CP775':
+ case 'CSPC775BALTIC':
+ case 'IBM775':
+ return 'IBM775';
+
+ case '850':
+ case 'CP850':
+ case 'CSPC850MULTILINGUAL':
+ case 'IBM850':
+ return 'IBM850';
+
+ case '851':
+ case 'CP851':
+ case 'CSIBM851':
+ case 'IBM851':
+ return 'IBM851';
+
+ case '852':
+ case 'CP852':
+ case 'CSPCP852':
+ case 'IBM852':
+ return 'IBM852';
+
+ case '855':
+ case 'CP855':
+ case 'CSIBM855':
+ case 'IBM855':
+ return 'IBM855';
+
+ case '857':
+ case 'CP857':
+ case 'CSIBM857':
+ case 'IBM857':
+ return 'IBM857';
+
+ case '860':
+ case 'CP860':
+ case 'CSIBM860':
+ case 'IBM860':
+ return 'IBM860';
+
+ case '861':
+ case 'CP-IS':
+ case 'CP861':
+ case 'CSIBM861':
+ case 'IBM861':
+ return 'IBM861';
+
+ case '862':
+ case 'CP862':
+ case 'CSPC862LATINHEBREW':
+ case 'IBM862':
+ return 'IBM862';
+
+ case '863':
+ case 'CP863':
+ case 'CSIBM863':
+ case 'IBM863':
+ return 'IBM863';
+
+ case 'CP864':
+ case 'CSIBM864':
+ case 'IBM864':
+ return 'IBM864';
+
+ case '865':
+ case 'CP865':
+ case 'CSIBM865':
+ case 'IBM865':
+ return 'IBM865';
+
+ case '866':
+ case 'CP866':
+ case 'CSIBM866':
+ case 'IBM866':
+ return 'IBM866';
+
+ case 'CP-AR':
+ case 'CP868':
+ case 'CSIBM868':
+ case 'IBM868':
+ return 'IBM868';
+
+ case '869':
+ case 'CP-GR':
+ case 'CP869':
+ case 'CSIBM869':
+ case 'IBM869':
+ return 'IBM869';
+
+ case 'CP870':
+ case 'CSIBM870':
+ case 'EBCDIC-CP-ROECE':
+ case 'EBCDIC-CP-YU':
+ case 'IBM870':
+ return 'IBM870';
+
+ case 'CP871':
+ case 'CSIBM871':
+ case 'EBCDIC-CP-IS':
+ case 'IBM871':
+ return 'IBM871';
+
+ case 'CP880':
+ case 'CSIBM880':
+ case 'EBCDIC-CYRILLIC':
+ case 'IBM880':
+ return 'IBM880';
+
+ case 'CP891':
+ case 'CSIBM891':
+ case 'IBM891':
+ return 'IBM891';
+
+ case 'CP903':
+ case 'CSIBM903':
+ case 'IBM903':
+ return 'IBM903';
+
+ case '904':
+ case 'CP904':
+ case 'CSIBBM904':
+ case 'IBM904':
+ return 'IBM904';
+
+ case 'CP905':
+ case 'CSIBM905':
+ case 'EBCDIC-CP-TR':
+ case 'IBM905':
+ return 'IBM905';
+
+ case 'CP918':
+ case 'CSIBM918':
+ case 'EBCDIC-CP-AR2':
+ case 'IBM918':
+ return 'IBM918';
+
+ case 'CSISO143IECP271':
+ case 'IEC_P27-1':
+ case 'ISO-IR-143':
+ return 'IEC_P27-1';
+
+ case 'CSISO49INIS':
+ case 'INIS':
+ case 'ISO-IR-49':
+ return 'INIS';
+
+ case 'CSISO50INIS8':
+ case 'INIS-8':
+ case 'ISO-IR-50':
+ return 'INIS-8';
+
+ case 'CSISO51INISCYRILLIC':
+ case 'INIS-CYRILLIC':
+ case 'ISO-IR-51':
+ return 'INIS-cyrillic';
+
+ case 'CSINVARIANT':
+ case 'INVARIANT':
+ return 'INVARIANT';
+
+ case 'ISO-10646-J-1':
+ return 'ISO-10646-J-1';
+
+ case 'CSUNICODE':
+ case 'ISO-10646-UCS-2':
+ return 'ISO-10646-UCS-2';
+
+ case 'CSUCS4':
+ case 'ISO-10646-UCS-4':
+ return 'ISO-10646-UCS-4';
+
+ case 'CSUNICODEASCII':
+ case 'ISO-10646-UCS-BASIC':
+ return 'ISO-10646-UCS-Basic';
+
+ case 'CSISO10646UTF1':
+ case 'ISO-10646-UTF-1':
+ return 'ISO-10646-UTF-1';
+
+ case 'CSUNICODELATIN1':
+ case 'ISO-10646':
+ case 'ISO-10646-UNICODE-LATIN1':
+ return 'ISO-10646-Unicode-Latin1';
+
+ case 'CSISO115481':
+ case 'ISO-11548-1':
+ case 'ISO_11548-1':
+ case 'ISO_TR_11548-1':
+ return 'ISO-11548-1';
+
+ case 'ISO-2022-CN':
+ return 'ISO-2022-CN';
+
+ case 'ISO-2022-CN-EXT':
+ return 'ISO-2022-CN-EXT';
+
+ case 'CSISO2022JP':
+ case 'ISO-2022-JP':
+ return 'ISO-2022-JP';
+
+ case 'CSISO2022JP2':
+ case 'ISO-2022-JP-2':
+ return 'ISO-2022-JP-2';
+
+ case 'CSISO2022KR':
+ case 'ISO-2022-KR':
+ return 'ISO-2022-KR';
+
+ case 'CSWINDOWS30LATIN1':
+ case 'ISO-8859-1-WINDOWS-3.0-LATIN-1':
+ return 'ISO-8859-1-Windows-3.0-Latin-1';
+
+ case 'CSWINDOWS31LATIN1':
+ case 'ISO-8859-1-WINDOWS-3.1-LATIN-1':
+ return 'ISO-8859-1-Windows-3.1-Latin-1';
+
+ case 'CSISOLATIN6':
+ case 'ISO-8859-10':
+ case 'ISO-IR-157':
+ case 'ISO_8859-10:1992':
+ case 'L6':
+ case 'LATIN6':
+ return 'ISO-8859-10';
+
+ case 'ISO-8859-13':
+ return 'ISO-8859-13';
+
+ case 'ISO-8859-14':
+ case 'ISO-CELTIC':
+ case 'ISO-IR-199':
+ case 'ISO_8859-14':
+ case 'ISO_8859-14:1998':
+ case 'L8':
+ case 'LATIN8':
+ return 'ISO-8859-14';
+
+ case 'ISO-8859-15':
+ case 'ISO_8859-15':
+ case 'LATIN-9':
+ return 'ISO-8859-15';
+
+ case 'ISO-8859-16':
+ case 'ISO-IR-226':
+ case 'ISO_8859-16':
+ case 'ISO_8859-16:2001':
+ case 'L10':
+ case 'LATIN10':
+ return 'ISO-8859-16';
+
+ case 'CSISOLATIN2':
+ case 'ISO-8859-2':
+ case 'ISO-IR-101':
+ case 'ISO_8859-2':
+ case 'ISO_8859-2:1987':
+ case 'L2':
+ case 'LATIN2':
+ return 'ISO-8859-2';
+
+ case 'CSWINDOWS31LATIN2':
+ case 'ISO-8859-2-WINDOWS-LATIN-2':
+ return 'ISO-8859-2-Windows-Latin-2';
+
+ case 'CSISOLATIN3':
+ case 'ISO-8859-3':
+ case 'ISO-IR-109':
+ case 'ISO_8859-3':
+ case 'ISO_8859-3:1988':
+ case 'L3':
+ case 'LATIN3':
+ return 'ISO-8859-3';
+
+ case 'CSISOLATIN4':
+ case 'ISO-8859-4':
+ case 'ISO-IR-110':
+ case 'ISO_8859-4':
+ case 'ISO_8859-4:1988':
+ case 'L4':
+ case 'LATIN4':
+ return 'ISO-8859-4';
+
+ case 'CSISOLATINCYRILLIC':
+ case 'CYRILLIC':
+ case 'ISO-8859-5':
+ case 'ISO-IR-144':
+ case 'ISO_8859-5':
+ case 'ISO_8859-5:1988':
+ return 'ISO-8859-5';
+
+ case 'ARABIC':
+ case 'ASMO-708':
+ case 'CSISOLATINARABIC':
+ case 'ECMA-114':
+ case 'ISO-8859-6':
+ case 'ISO-IR-127':
+ case 'ISO_8859-6':
+ case 'ISO_8859-6:1987':
+ return 'ISO-8859-6';
+
+ case 'CSISO88596E':
+ case 'ISO-8859-6-E':
+ case 'ISO_8859-6-E':
+ return 'ISO-8859-6-E';
+
+ case 'CSISO88596I':
+ case 'ISO-8859-6-I':
+ case 'ISO_8859-6-I':
+ return 'ISO-8859-6-I';
+
+ case 'CSISOLATINGREEK':
+ case 'ECMA-118':
+ case 'ELOT_928':
+ case 'GREEK':
+ case 'GREEK8':
+ case 'ISO-8859-7':
+ case 'ISO-IR-126':
+ case 'ISO_8859-7':
+ case 'ISO_8859-7:1987':
+ return 'ISO-8859-7';
+
+ case 'CSISOLATINHEBREW':
+ case 'HEBREW':
+ case 'ISO-8859-8':
+ case 'ISO-IR-138':
+ case 'ISO_8859-8':
+ case 'ISO_8859-8:1988':
+ return 'ISO-8859-8';
+
+ case 'CSISO88598E':
+ case 'ISO-8859-8-E':
+ case 'ISO_8859-8-E':
+ return 'ISO-8859-8-E';
+
+ case 'CSISO88598I':
+ case 'ISO-8859-8-I':
+ case 'ISO_8859-8-I':
+ return 'ISO-8859-8-I';
+
+ case 'CSISOLATIN5':
+ case 'ISO-8859-9':
+ case 'ISO-IR-148':
+ case 'ISO_8859-9':
+ case 'ISO_8859-9:1989':
+ case 'L5':
+ case 'LATIN5':
+ return 'ISO-8859-9';
+
+ case 'CSWINDOWS31LATIN5':
+ case 'ISO-8859-9-WINDOWS-LATIN-5':
+ return 'ISO-8859-9-Windows-Latin-5';
+
+ case 'CSUNICODEIBM1261':
+ case 'ISO-UNICODE-IBM-1261':
+ return 'ISO-Unicode-IBM-1261';
+
+ case 'CSUNICODEIBM1264':
+ case 'ISO-UNICODE-IBM-1264':
+ return 'ISO-Unicode-IBM-1264';
+
+ case 'CSUNICODEIBM1265':
+ case 'ISO-UNICODE-IBM-1265':
+ return 'ISO-Unicode-IBM-1265';
+
+ case 'CSUNICODEIBM1268':
+ case 'ISO-UNICODE-IBM-1268':
+ return 'ISO-Unicode-IBM-1268';
+
+ case 'CSUNICODEIBM1276':
+ case 'ISO-UNICODE-IBM-1276':
+ return 'ISO-Unicode-IBM-1276';
+
+ case 'CSISO10367BOX':
+ case 'ISO-IR-155':
+ case 'ISO_10367-BOX':
+ return 'ISO_10367-box';
+
+ case 'CSISO2033':
+ case 'E13B':
+ case 'ISO-IR-98':
+ case 'ISO_2033-1983':
+ return 'ISO_2033-1983';
+
+ case 'CSISO5427CYRILLIC':
+ case 'ISO-IR-37':
+ case 'ISO_5427':
+ return 'ISO_5427';
+
+ case 'ISO-IR-54':
+ case 'ISO5427CYRILLIC1981':
+ case 'ISO_5427:1981':
+ return 'ISO_5427:1981';
+
+ case 'CSISO5428GREEK':
+ case 'ISO-IR-55':
+ case 'ISO_5428:1980':
+ return 'ISO_5428:1980';
+
+ case 'CSISO646BASIC1983':
+ case 'ISO_646.BASIC:1983':
+ case 'REF':
+ return 'ISO_646.basic:1983';
+
+ case 'CSISO2INTLREFVERSION':
+ case 'IRV':
+ case 'ISO-IR-2':
+ case 'ISO_646.IRV:1983':
+ return 'ISO_646.irv:1983';
+
+ case 'CSISO6937ADD':
+ case 'ISO-IR-152':
+ case 'ISO_6937-2-25':
+ return 'ISO_6937-2-25';
+
+ case 'CSISOTEXTCOMM':
+ case 'ISO-IR-142':
+ case 'ISO_6937-2-ADD':
+ return 'ISO_6937-2-add';
+
+ case 'CSISO8859SUPP':
+ case 'ISO-IR-154':
+ case 'ISO_8859-SUPP':
+ case 'LATIN1-2-5':
+ return 'ISO_8859-supp';
+
+ case 'CSISO15ITALIAN':
+ case 'ISO-IR-15':
+ case 'ISO646-IT':
+ case 'IT':
+ return 'IT';
+
+ case 'CSISO13JISC6220JP':
+ case 'ISO-IR-13':
+ case 'JIS_C6220-1969':
+ case 'JIS_C6220-1969-JP':
+ case 'KATAKANA':
+ case 'X0201-7':
+ return 'JIS_C6220-1969-jp';
+
+ case 'CSISO14JISC6220RO':
+ case 'ISO-IR-14':
+ case 'ISO646-JP':
+ case 'JIS_C6220-1969-RO':
+ case 'JP':
+ return 'JIS_C6220-1969-ro';
+
+ case 'CSISO42JISC62261978':
+ case 'ISO-IR-42':
+ case 'JIS_C6226-1978':
+ return 'JIS_C6226-1978';
+
+ case 'CSISO87JISX0208':
+ case 'ISO-IR-87':
+ case 'JIS_C6226-1983':
+ case 'JIS_X0208-1983':
+ case 'X0208':
+ return 'JIS_C6226-1983';
+
+ case 'CSISO91JISC62291984A':
+ case 'ISO-IR-91':
+ case 'JIS_C6229-1984-A':
+ case 'JP-OCR-A':
+ return 'JIS_C6229-1984-a';
+
+ case 'CSISO92JISC62991984B':
+ case 'ISO-IR-92':
+ case 'ISO646-JP-OCR-B':
+ case 'JIS_C6229-1984-B':
+ case 'JP-OCR-B':
+ return 'JIS_C6229-1984-b';
+
+ case 'CSISO93JIS62291984BADD':
+ case 'ISO-IR-93':
+ case 'JIS_C6229-1984-B-ADD':
+ case 'JP-OCR-B-ADD':
+ return 'JIS_C6229-1984-b-add';
+
+ case 'CSISO94JIS62291984HAND':
+ case 'ISO-IR-94':
+ case 'JIS_C6229-1984-HAND':
+ case 'JP-OCR-HAND':
+ return 'JIS_C6229-1984-hand';
+
+ case 'CSISO95JIS62291984HANDADD':
+ case 'ISO-IR-95':
+ case 'JIS_C6229-1984-HAND-ADD':
+ case 'JP-OCR-HAND-ADD':
+ return 'JIS_C6229-1984-hand-add';
+
+ case 'CSISO96JISC62291984KANA':
+ case 'ISO-IR-96':
+ case 'JIS_C6229-1984-KANA':
+ return 'JIS_C6229-1984-kana';
+
+ case 'CSJISENCODING':
+ case 'JIS_ENCODING':
+ return 'JIS_Encoding';
+
+ case 'CSHALFWIDTHKATAKANA':
+ case 'JIS_X0201':
+ case 'X0201':
+ return 'JIS_X0201';
+
+ case 'CSISO159JISX02121990':
+ case 'ISO-IR-159':
+ case 'JIS_X0212-1990':
+ case 'X0212':
+ return 'JIS_X0212-1990';
+
+ case 'CSISO141JUSIB1002':
+ case 'ISO-IR-141':
+ case 'ISO646-YU':
+ case 'JS':
+ case 'JUS_I.B1.002':
+ case 'YU':
+ return 'JUS_I.B1.002';
+
+ case 'CSISO147MACEDONIAN':
+ case 'ISO-IR-147':
+ case 'JUS_I.B1.003-MAC':
+ case 'MACEDONIAN':
+ return 'JUS_I.B1.003-mac';
+
+ case 'CSISO146SERBIAN':
+ case 'ISO-IR-146':
+ case 'JUS_I.B1.003-SERB':
+ case 'SERBIAN':
+ return 'JUS_I.B1.003-serb';
+
+ case 'KOI7-SWITCHED':
+ return 'KOI7-switched';
+
+ case 'CSKOI8R':
+ case 'KOI8-R':
+ return 'KOI8-R';
+
+ case 'KOI8-U':
+ return 'KOI8-U';
+
+ case 'CSKSC5636':
+ case 'ISO646-KR':
+ case 'KSC5636':
+ return 'KSC5636';
+
+ case 'CSKSC56011987':
+ case 'ISO-IR-149':
+ case 'KOREAN':
+ case 'KSC_5601':
+ case 'KS_C_5601-1987':
+ case 'KS_C_5601-1989':
+ return 'KS_C_5601-1987';
+
+ case 'CSKZ1048':
+ case 'KZ-1048':
+ case 'RK1048':
+ case 'STRK1048-2002':
+ return 'KZ-1048';
+
+ case 'CSISO27LATINGREEK1':
+ case 'ISO-IR-27':
+ case 'LATIN-GREEK-1':
+ return 'Latin-greek-1';
+
+ case 'CSMNEM':
+ case 'MNEM':
+ return 'MNEM';
+
+ case 'CSMNEMONIC':
+ case 'MNEMONIC':
+ return 'MNEMONIC';
+
+ case 'CSISO86HUNGARIAN':
+ case 'HU':
+ case 'ISO-IR-86':
+ case 'ISO646-HU':
+ case 'MSZ_7795.3':
+ return 'MSZ_7795.3';
+
+ case 'CSMICROSOFTPUBLISHING':
+ case 'MICROSOFT-PUBLISHING':
+ return 'Microsoft-Publishing';
+
+ case 'CSNATSDANO':
+ case 'ISO-IR-9-1':
+ case 'NATS-DANO':
+ return 'NATS-DANO';
+
+ case 'CSNATSDANOADD':
+ case 'ISO-IR-9-2':
+ case 'NATS-DANO-ADD':
+ return 'NATS-DANO-ADD';
+
+ case 'CSNATSSEFI':
+ case 'ISO-IR-8-1':
+ case 'NATS-SEFI':
+ return 'NATS-SEFI';
+
+ case 'CSNATSSEFIADD':
+ case 'ISO-IR-8-2':
+ case 'NATS-SEFI-ADD':
+ return 'NATS-SEFI-ADD';
+
+ case 'CSISO151CUBA':
+ case 'CUBA':
+ case 'ISO-IR-151':
+ case 'ISO646-CU':
+ case 'NC_NC00-10:81':
+ return 'NC_NC00-10:81';
+
+ case 'CSISO69FRENCH':
+ case 'FR':
+ case 'ISO-IR-69':
+ case 'ISO646-FR':
+ case 'NF_Z_62-010':
+ return 'NF_Z_62-010';
+
+ case 'CSISO25FRENCH':
+ case 'ISO-IR-25':
+ case 'ISO646-FR1':
+ case 'NF_Z_62-010_(1973)':
+ return 'NF_Z_62-010_(1973)';
+
+ case 'CSISO60DANISHNORWEGIAN':
+ case 'CSISO60NORWEGIAN1':
+ case 'ISO-IR-60':
+ case 'ISO646-NO':
+ case 'NO':
+ case 'NS_4551-1':
+ return 'NS_4551-1';
+
+ case 'CSISO61NORWEGIAN2':
+ case 'ISO-IR-61':
+ case 'ISO646-NO2':
+ case 'NO2':
+ case 'NS_4551-2':
+ return 'NS_4551-2';
+
+ case 'OSD_EBCDIC_DF03_IRV':
+ return 'OSD_EBCDIC_DF03_IRV';
+
+ case 'OSD_EBCDIC_DF04_1':
+ return 'OSD_EBCDIC_DF04_1';
+
+ case 'OSD_EBCDIC_DF04_15':
+ return 'OSD_EBCDIC_DF04_15';
+
+ case 'CSPC8DANISHNORWEGIAN':
+ case 'PC8-DANISH-NORWEGIAN':
+ return 'PC8-Danish-Norwegian';
+
+ case 'CSPC8TURKISH':
+ case 'PC8-TURKISH':
+ return 'PC8-Turkish';
+
+ case 'CSISO16PORTUGUESE':
+ case 'ISO-IR-16':
+ case 'ISO646-PT':
+ case 'PT':
+ return 'PT';
+
+ case 'CSISO84PORTUGUESE2':
+ case 'ISO-IR-84':
+ case 'ISO646-PT2':
+ case 'PT2':
+ return 'PT2';
+
+ case 'CP154':
+ case 'CSPTCP154':
+ case 'CYRILLIC-ASIAN':
+ case 'PT154':
+ case 'PTCP154':
+ return 'PTCP154';
+
+ case 'SCSU':
+ return 'SCSU';
+
+ case 'CSISO10SWEDISH':
+ case 'FI':
+ case 'ISO-IR-10':
+ case 'ISO646-FI':
+ case 'ISO646-SE':
+ case 'SE':
+ case 'SEN_850200_B':
+ return 'SEN_850200_B';
+
+ case 'CSISO11SWEDISHFORNAMES':
+ case 'ISO-IR-11':
+ case 'ISO646-SE2':
+ case 'SE2':
+ case 'SEN_850200_C':
+ return 'SEN_850200_C';
+
+ case 'CSSHIFTJIS':
+ case 'MS_KANJI':
+ case 'SHIFT_JIS':
+ return 'Shift_JIS';
+
+ case 'CSISO128T101G2':
+ case 'ISO-IR-128':
+ case 'T.101-G2':
+ return 'T.101-G2';
+
+ case 'CSISO102T617BIT':
+ case 'ISO-IR-102':
+ case 'T.61-7BIT':
+ return 'T.61-7bit';
+
+ case 'CSISO103T618BIT':
+ case 'ISO-IR-103':
+ case 'T.61':
+ case 'T.61-8BIT':
+ return 'T.61-8bit';
+
+ case 'CSTSCII':
+ case 'TSCII':
+ return 'TSCII';
+
+ case 'CSUNICODE11':
+ case 'UNICODE-1-1':
+ return 'UNICODE-1-1';
+
+ case 'CSUNICODE11UTF7':
+ case 'UNICODE-1-1-UTF-7':
+ return 'UNICODE-1-1-UTF-7';
+
+ case 'CSUNKNOWN8BIT':
+ case 'UNKNOWN-8BIT':
+ return 'UNKNOWN-8BIT';
+
+ case 'ANSI':
+ case 'ANSI_X3.4-1968':
+ case 'ANSI_X3.4-1986':
+ case 'ASCII':
+ case 'CP367':
+ case 'CSASCII':
+ case 'IBM367':
+ case 'ISO-IR-6':
+ case 'ISO646-US':
+ case 'ISO_646.IRV:1991':
+ case 'US':
+ case 'US-ASCII':
+ return 'US-ASCII';
+
+ case 'UTF-16':
+ return 'UTF-16';
+
+ case 'UTF-16BE':
+ return 'UTF-16BE';
+
+ case 'UTF-16LE':
+ return 'UTF-16LE';
+
+ case 'UTF-32':
+ return 'UTF-32';
+
+ case 'UTF-32BE':
+ return 'UTF-32BE';
+
+ case 'UTF-32LE':
+ return 'UTF-32LE';
+
+ case 'UTF-7':
+ return 'UTF-7';
+
+ case 'UTF-8':
+ return 'UTF-8';
+
+ case 'CSVIQR':
+ case 'VIQR':
+ return 'VIQR';
+
+ case 'CSVISCII':
+ case 'VISCII':
+ return 'VISCII';
+
+ case 'CSVENTURAINTERNATIONAL':
+ case 'VENTURA-INTERNATIONAL':
+ return 'Ventura-International';
+
+ case 'CSVENTURAMATH':
+ case 'VENTURA-MATH':
+ return 'Ventura-Math';
+
+ case 'CSVENTURAUS':
+ case 'VENTURA-US':
+ return 'Ventura-US';
+
+ case 'CSWINDOWS31J':
+ case 'WINDOWS-31J':
+ return 'Windows-31J';
+
+ case 'CSDKUS':
+ case 'DK-US':
+ return 'dk-us';
+
+ case 'CSISO150':
+ case 'CSISO150GREEKCCITT':
+ case 'GREEK-CCITT':
+ case 'ISO-IR-150':
+ return 'greek-ccitt';
+
+ case 'CSISO88GREEK7':
+ case 'GREEK7':
+ case 'ISO-IR-88':
+ return 'greek7';
+
+ case 'CSISO18GREEK7OLD':
+ case 'GREEK7-OLD':
+ case 'ISO-IR-18':
+ return 'greek7-old';
+
+ case 'CSHPROMAN8':
+ case 'HP-ROMAN8':
+ case 'R8':
+ case 'ROMAN8':
+ return 'hp-roman8';
+
+ case 'CSISO90':
+ case 'ISO-IR-90':
+ return 'iso-ir-90';
+
+ case 'CSISO19LATINGREEK':
+ case 'ISO-IR-19':
+ case 'LATIN-GREEK':
+ return 'latin-greek';
+
+ case 'CSISO158LAP':
+ case 'ISO-IR-158':
+ case 'LAP':
+ case 'LATIN-LAP':
+ return 'latin-lap';
+
+ case 'CSMACINTOSH':
+ case 'MAC':
+ case 'MACINTOSH':
+ return 'macintosh';
+
+ case 'CSUSDK':
+ case 'US-DK':
+ return 'us-dk';
+
+ case 'CSISO70VIDEOTEXSUPP1':
+ case 'ISO-IR-70':
+ case 'VIDEOTEX-SUPPL':
+ return 'videotex-suppl';
+
+ case 'WINDOWS-1250':
+ return 'windows-1250';
+
+ case 'WINDOWS-1251':
+ return 'windows-1251';
+
+ case 'CP819':
+ case 'CSISOLATIN1':
+ case 'IBM819':
+ case 'ISO-8859-1':
+ case 'ISO-IR-100':
+ case 'ISO_8859-1':
+ case 'ISO_8859-1:1987':
+ case 'L1':
+ case 'LATIN1':
+ case 'WINDOWS-1252':
+ return 'windows-1252';
+
+ case 'WINDOWS-1253':
+ return 'windows-1253';
+
+ case 'WINDOWS-1254':
+ return 'windows-1254';
+
+ case 'WINDOWS-1255':
+ return 'windows-1255';
+
+ case 'WINDOWS-1256':
+ return 'windows-1256';
+
+ case 'WINDOWS-1257':
+ return 'windows-1257';
+
+ case 'WINDOWS-1258':
+ return 'windows-1258';
+
+ default:
+ return $encoding;
+ }
+ }
+
+ function get_curl_version()
+ {
+ if (is_array($curl = curl_version()))
+ {
+ $curl = $curl['version'];
+ }
+ elseif (substr($curl, 0, 5) == 'curl/')
+ {
+ $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
+ }
+ elseif (substr($curl, 0, 8) == 'libcurl/')
+ {
+ $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
+ }
+ else
+ {
+ $curl = 0;
+ }
+ return $curl;
+ }
+
+ function is_subclass_of($class1, $class2)
+ {
+ if (func_num_args() != 2)
+ {
+ trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
+ }
+ elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
+ {
+ return is_subclass_of($class1, $class2);
+ }
+ elseif (is_string($class1) && is_string($class2))
+ {
+ if (class_exists($class1))
+ {
+ if (class_exists($class2))
+ {
+ $class2 = strtolower($class2);
+ while ($class1 = strtolower(get_parent_class($class1)))
+ {
+ if ($class1 == $class2)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ else
+ {
+ trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Strip HTML comments
+ *
+ * @access public
+ * @param string $data Data to strip comments from
+ * @return string Comment stripped string
+ */
+ function strip_comments($data)
+ {
+ $output = '';
+ while (($start = strpos($data, '<!--')) !== false)
+ {
+ $output .= substr($data, 0, $start);
+ if (($end = strpos($data, '-->', $start)) !== false)
+ {
+ $data = substr_replace($data, '', 0, $end + 3);
+ }
+ else
+ {
+ $data = '';
+ }
+ }
+ return $output . $data;
+ }
+
+ function parse_date($dt)
+ {
+ $parser = SimplePie_Parse_Date::get();
+ return $parser->parse($dt);
+ }
+
+ /**
+ * Decode HTML entities
+ *
+ * @static
+ * @access public
+ * @param string $data Input data
+ * @return string Output data
+ */
+ function entities_decode($data)
+ {
+ $decoder = new SimplePie_Decode_HTML_Entities($data);
+ return $decoder->parse();
+ }
+
+ /**
+ * Remove RFC822 comments
+ *
+ * @access public
+ * @param string $data Data to strip comments from
+ * @return string Comment stripped string
+ */
+ function uncomment_rfc822($string)
+ {
+ $string = (string) $string;
+ $position = 0;
+ $length = strlen($string);
+ $depth = 0;
+
+ $output = '';
+
+ while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
+ {
+ $output .= substr($string, $position, $pos - $position);
+ $position = $pos + 1;
+ if ($string[$pos - 1] !== '\\')
+ {
+ $depth++;
+ while ($depth && $position < $length)
+ {
+ $position += strcspn($string, '()', $position);
+ if ($string[$position - 1] === '\\')
+ {
+ $position++;
+ continue;
+ }
+ elseif (isset($string[$position]))
+ {
+ switch ($string[$position])
+ {
+ case '(':
+ $depth++;
+ break;
+
+ case ')':
+ $depth--;
+ break;
+ }
+ $position++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ $output .= '(';
+ }
+ }
+ $output .= substr($string, $position);
+
+ return $output;
+ }
+
+ function parse_mime($mime)
+ {
+ if (($pos = strpos($mime, ';')) === false)
+ {
+ return trim($mime);
+ }
+ else
+ {
+ return trim(substr($mime, 0, $pos));
+ }
+ }
+
+ function htmlspecialchars_decode($string, $quote_style)
+ {
+ if (function_exists('htmlspecialchars_decode'))
+ {
+ return htmlspecialchars_decode($string, $quote_style);
+ }
+ else
+ {
+ return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
+ }
+ }
+
+ function atom_03_construct_type($attribs)
+ {
+ if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) == 'base64'))
+ {
+ $mode = SIMPLEPIE_CONSTRUCT_BASE64;
+ }
+ else
+ {
+ $mode = SIMPLEPIE_CONSTRUCT_NONE;
+ }
+ if (isset($attribs['']['type']))
+ {
+ switch (strtolower(trim($attribs['']['type'])))
+ {
+ case 'text':
+ case 'text/plain':
+ return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
+
+ case 'html':
+ case 'text/html':
+ return SIMPLEPIE_CONSTRUCT_HTML | $mode;
+
+ case 'xhtml':
+ case 'application/xhtml+xml':
+ return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
+
+ default:
+ return SIMPLEPIE_CONSTRUCT_NONE | $mode;
+ }
+ }
+ else
+ {
+ return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
+ }
+ }
+
+ function atom_10_construct_type($attribs)
+ {
+ if (isset($attribs['']['type']))
+ {
+ switch (strtolower(trim($attribs['']['type'])))
+ {
+ case 'text':
+ return SIMPLEPIE_CONSTRUCT_TEXT;
+
+ case 'html':
+ return SIMPLEPIE_CONSTRUCT_HTML;
+
+ case 'xhtml':
+ return SIMPLEPIE_CONSTRUCT_XHTML;
+
+ default:
+ return SIMPLEPIE_CONSTRUCT_NONE;
+ }
+ }
+ return SIMPLEPIE_CONSTRUCT_TEXT;
+ }
+
+ function atom_10_content_construct_type($attribs)
+ {
+ if (isset($attribs['']['type']))
+ {
+ $type = strtolower(trim($attribs['']['type']));
+ switch ($type)
+ {
+ case 'text':
+ return SIMPLEPIE_CONSTRUCT_TEXT;
+
+ case 'html':
+ return SIMPLEPIE_CONSTRUCT_HTML;
+
+ case 'xhtml':
+ return SIMPLEPIE_CONSTRUCT_XHTML;
+ }
+ if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) == 'text/')
+ {
+ return SIMPLEPIE_CONSTRUCT_NONE;
+ }
+ else
+ {
+ return SIMPLEPIE_CONSTRUCT_BASE64;
+ }
+ }
+ else
+ {
+ return SIMPLEPIE_CONSTRUCT_TEXT;
+ }
+ }
+
+ function is_isegment_nz_nc($string)
+ {
+ return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
+ }
+
+ function space_seperated_tokens($string)
+ {
+ $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
+ $string_length = strlen($string);
+
+ $position = strspn($string, $space_characters);
+ $tokens = array();
+
+ while ($position < $string_length)
+ {
+ $len = strcspn($string, $space_characters, $position);
+ $tokens[] = substr($string, $position, $len);
+ $position += $len;
+ $position += strspn($string, $space_characters, $position);
+ }
+
+ return $tokens;
+ }
+
+ function array_unique($array)
+ {
+ if (version_compare(PHP_VERSION, '5.2', '>='))
+ {
+ return array_unique($array);
+ }
+ else
+ {
+ $array = (array) $array;
+ $new_array = array();
+ $new_array_strings = array();
+ foreach ($array as $key => $value)
+ {
+ if (is_object($value))
+ {
+ if (method_exists($value, '__toString'))
+ {
+ $cmp = $value->__toString();
+ }
+ else
+ {
+ trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
+ }
+ }
+ elseif (is_array($value))
+ {
+ $cmp = (string) reset($value);
+ }
+ else
+ {
+ $cmp = (string) $value;
+ }
+ if (!in_array($cmp, $new_array_strings))
+ {
+ $new_array[$key] = $value;
+ $new_array_strings[] = $cmp;
+ }
+ }
+ return $new_array;
+ }
+ }
+
+ /**
+ * Converts a unicode codepoint to a UTF-8 character
+ *
+ * @static
+ * @access public
+ * @param int $codepoint Unicode codepoint
+ * @return string UTF-8 character
+ */
+ function codepoint_to_utf8($codepoint)
+ {
+ static $cache = array();
+ $codepoint = (int) $codepoint;
+ if (isset($cache[$codepoint]))
+ {
+ return $cache[$codepoint];
+ }
+ elseif ($codepoint < 0)
+ {
+ return $cache[$codepoint] = false;
+ }
+ else if ($codepoint <= 0x7f)
+ {
+ return $cache[$codepoint] = chr($codepoint);
+ }
+ else if ($codepoint <= 0x7ff)
+ {
+ return $cache[$codepoint] = chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
+ }
+ else if ($codepoint <= 0xffff)
+ {
+ return $cache[$codepoint] = chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
+ }
+ else if ($codepoint <= 0x10ffff)
+ {
+ return $cache[$codepoint] = chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
+ }
+ else
+ {
+ // U+FFFD REPLACEMENT CHARACTER
+ return $cache[$codepoint] = "\xEF\xBF\xBD";
+ }
+ }
+
+ /**
+ * Re-implementation of PHP 5's stripos()
+ *
+ * Returns the numeric position of the first occurrence of needle in the
+ * haystack string.
+ *
+ * @static
+ * @access string
+ * @param object $haystack
+ * @param string $needle Note that the needle may be a string of one or more
+ * characters. If needle is not a string, it is converted to an integer
+ * and applied as the ordinal value of a character.
+ * @param int $offset The optional offset parameter allows you to specify which
+ * character in haystack to start searching. The position returned is still
+ * relative to the beginning of haystack.
+ * @return bool If needle is not found, stripos() will return boolean false.
+ */
+ function stripos($haystack, $needle, $offset = 0)
+ {
+ if (function_exists('stripos'))
+ {
+ return stripos($haystack, $needle, $offset);
+ }
+ else
+ {
+ if (is_string($needle))
+ {
+ $needle = strtolower($needle);
+ }
+ elseif (is_int($needle) || is_bool($needle) || is_double($needle))
+ {
+ $needle = strtolower(chr($needle));
+ }
+ else
+ {
+ trigger_error('needle is not a string or an integer', E_USER_WARNING);
+ return false;
+ }
+
+ return strpos(strtolower($haystack), $needle, $offset);
+ }
+ }
+
+ /**
+ * Similar to parse_str()
+ *
+ * Returns an associative array of name/value pairs, where the value is an
+ * array of values that have used the same name
+ *
+ * @static
+ * @access string
+ * @param string $str The input string.
+ * @return array
+ */
+ function parse_str($str)
+ {
+ $return = array();
+ $str = explode('&', $str);
+
+ foreach ($str as $section)
+ {
+ if (strpos($section, '=') !== false)
+ {
+ list($name, $value) = explode('=', $section, 2);
+ $return[urldecode($name)][] = urldecode($value);
+ }
+ else
+ {
+ $return[urldecode($section)][] = null;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Detect XML encoding, as per XML 1.0 Appendix F.1
+ *
+ * @todo Add support for EBCDIC
+ * @param string $data XML data
+ * @return array Possible encodings
+ */
+ function xml_encoding($data)
+ {
+ // UTF-32 Big Endian BOM
+ if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
+ {
+ $encoding[] = 'UTF-32BE';
+ }
+ // UTF-32 Little Endian BOM
+ elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
+ {
+ $encoding[] = 'UTF-32LE';
+ }
+ // UTF-16 Big Endian BOM
+ elseif (substr($data, 0, 2) === "\xFE\xFF")
+ {
+ $encoding[] = 'UTF-16BE';
+ }
+ // UTF-16 Little Endian BOM
+ elseif (substr($data, 0, 2) === "\xFF\xFE")
+ {
+ $encoding[] = 'UTF-16LE';
+ }
+ // UTF-8 BOM
+ elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
+ {
+ $encoding[] = 'UTF-8';
+ }
+ // UTF-32 Big Endian Without BOM
+ elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
+ {
+ if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
+ {
+ $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
+ if ($parser->parse())
+ {
+ $encoding[] = $parser->encoding;
+ }
+ }
+ $encoding[] = 'UTF-32BE';
+ }
+ // UTF-32 Little Endian Without BOM
+ elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
+ {
+ if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
+ {
+ $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
+ if ($parser->parse())
+ {
+ $encoding[] = $parser->encoding;
+ }
+ }
+ $encoding[] = 'UTF-32LE';
+ }
+ // UTF-16 Big Endian Without BOM
+ elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
+ {
+ if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
+ {
+ $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
+ if ($parser->parse())
+ {
+ $encoding[] = $parser->encoding;
+ }
+ }
+ $encoding[] = 'UTF-16BE';
+ }
+ // UTF-16 Little Endian Without BOM
+ elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
+ {
+ if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
+ {
+ $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
+ if ($parser->parse())
+ {
+ $encoding[] = $parser->encoding;
+ }
+ }
+ $encoding[] = 'UTF-16LE';
+ }
+ // US-ASCII (or superset)
+ elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
+ {
+ if ($pos = strpos($data, "\x3F\x3E"))
+ {
+ $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
+ if ($parser->parse())
+ {
+ $encoding[] = $parser->encoding;
+ }
+ }
+ $encoding[] = 'UTF-8';
+ }
+ // Fallback to UTF-8
+ else
+ {
+ $encoding[] = 'UTF-8';
+ }
+ return $encoding;
+ }
+}
+
+/**
+ * Decode HTML Entities
+ *
+ * This implements HTML5 as of revision 967 (2007-06-28)
+ *
+ * @package SimplePie
+ */
+class SimplePie_Decode_HTML_Entities
+{
+ /**
+ * Data to be parsed
+ *
+ * @access private
+ * @var string
+ */
+ var $data = '';
+
+ /**
+ * Currently consumed bytes
+ *
+ * @access private
+ * @var string
+ */
+ var $consumed = '';
+
+ /**
+ * Position of the current byte being parsed
+ *
+ * @access private
+ * @var int
+ */
+ var $position = 0;
+
+ /**
+ * Create an instance of the class with the input data
+ *
+ * @access public
+ * @param string $data Input data
+ */
+ function SimplePie_Decode_HTML_Entities($data)
+ {
+ $this->data = $data;
+ }
+
+ /**
+ * Parse the input data
+ *
+ * @access public
+ * @return string Output data
+ */
+ function parse()
+ {
+ while (($this->position = strpos($this->data, '&', $this->position)) !== false)
+ {
+ $this->consume();
+ $this->entity();
+ $this->consumed = '';
+ }
+ return $this->data;
+ }
+
+ /**
+ * Consume the next byte
+ *
+ * @access private
+ * @return mixed The next byte, or false, if there is no more data
+ */
+ function consume()
+ {
+ if (isset($this->data[$this->position]))
+ {
+ $this->consumed .= $this->data[$this->position];
+ return $this->data[$this->position++];
+ }
+ else
+ {
+ $this->consumed = false;
+ return false;
+ }
+ }
+
+ /**
+ * Consume a range of characters
+ *
+ * @access private
+ * @param string $chars Characters to consume
+ * @return mixed A series of characters that match the range, or false
+ */
+ function consume_range($chars)
+ {
+ if ($len = strspn($this->data, $chars, $this->position))
+ {
+ $data = substr($this->data, $this->position, $len);
+ $this->consumed .= $data;
+ $this->position += $len;
+ return $data;
+ }
+ else
+ {
+ $this->consumed = false;
+ return false;
+ }
+ }
+
+ /**
+ * Unconsume one byte
+ *
+ * @access private
+ */
+ function unconsume()
+ {
+ $this->consumed = substr($this->consumed, 0, -1);
+ $this->position--;
+ }
+
+ /**
+ * Decode an entity
+ *
+ * @access private
+ */
+ function entity()
+ {
+ switch ($this->consume())
+ {
+ case "\x09":
+ case "\x0A":
+ case "\x0B":
+ case "\x0B":
+ case "\x0C":
+ case "\x20":
+ case "\x3C":
+ case "\x26":
+ case false:
+ break;
+
+ case "\x23":
+ switch ($this->consume())
+ {
+ case "\x78":
+ case "\x58":
+ $range = '0123456789ABCDEFabcdef';
+ $hex = true;
+ break;
+
+ default:
+ $range = '0123456789';
+ $hex = false;
+ $this->unconsume();
+ break;
+ }
+
+ if ($codepoint = $this->consume_range($range))
+ {
+ static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
+
+ if ($hex)
+ {
+ $codepoint = hexdec($codepoint);
+ }
+ else
+ {
+ $codepoint = intval($codepoint);
+ }
+
+ if (isset($windows_1252_specials[$codepoint]))
+ {
+ $replacement = $windows_1252_specials[$codepoint];
+ }
+ else
+ {
+ $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
+ }
+
+ if ($this->consume() != ';')
+ {
+ $this->unconsume();
+ }
+
+ $consumed_length = strlen($this->consumed);
+ $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
+ $this->position += strlen($replacement) - $consumed_length;
+ }
+ break;
+
+ default:
+ static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
+
+ for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
+ {
+ $consumed = substr($this->consumed, 1);
+ if (isset($entities[$consumed]))
+ {
+ $match = $consumed;
+ }
+ }
+
+ if ($match !== null)
+ {
+ $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
+ $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Date Parser
+ *
+ * @package SimplePie
+ */
+class SimplePie_Parse_Date
+{
+ /**
+ * Input data
+ *
+ * @access protected
+ * @var string
+ */
+ var $date;
+
+ /**
+ * List of days, calendar day name => ordinal day number in the week
+ *
+ * @access protected
+ * @var array
+ */
+ var $day = array(
+ // English
+ 'mon' => 1,
+ 'monday' => 1,
+ 'tue' => 2,
+ 'tuesday' => 2,
+ 'wed' => 3,
+ 'wednesday' => 3,
+ 'thu' => 4,
+ 'thursday' => 4,
+ 'fri' => 5,
+ 'friday' => 5,
+ 'sat' => 6,
+ 'saturday' => 6,
+ 'sun' => 7,
+ 'sunday' => 7,
+ // Dutch
+ 'maandag' => 1,
+ 'dinsdag' => 2,
+ 'woensdag' => 3,
+ 'donderdag' => 4,
+ 'vrijdag' => 5,
+ 'zaterdag' => 6,
+ 'zondag' => 7,
+ // French
+ 'lundi' => 1,
+ 'mardi' => 2,
+ 'mercredi' => 3,
+ 'jeudi' => 4,
+ 'vendredi' => 5,
+ 'samedi' => 6,
+ 'dimanche' => 7,
+ // German
+ 'montag' => 1,
+ 'dienstag' => 2,
+ 'mittwoch' => 3,
+ 'donnerstag' => 4,
+ 'freitag' => 5,
+ 'samstag' => 6,
+ 'sonnabend' => 6,
+ 'sonntag' => 7,
+ // Italian
+ 'lunedì' => 1,
+ 'martedì' => 2,
+ 'mercoledì' => 3,
+ 'giovedì' => 4,
+ 'venerdì' => 5,
+ 'sabato' => 6,
+ 'domenica' => 7,
+ // Spanish
+ 'lunes' => 1,
+ 'martes' => 2,
+ 'miércoles' => 3,
+ 'jueves' => 4,
+ 'viernes' => 5,
+ 'sábado' => 6,
+ 'domingo' => 7,
+ // Finnish
+ 'maanantai' => 1,
+ 'tiistai' => 2,
+ 'keskiviikko' => 3,
+ 'torstai' => 4,
+ 'perjantai' => 5,
+ 'lauantai' => 6,
+ 'sunnuntai' => 7,
+ // Hungarian
+ 'hétfő' => 1,
+ 'kedd' => 2,
+ 'szerda' => 3,
+ 'csütörtok' => 4,
+ 'péntek' => 5,
+ 'szombat' => 6,
+ 'vasárnap' => 7,
+ // Greek
+ 'Δευ' => 1,
+ 'Τρι' => 2,
+ 'Τετ' => 3,
+ 'Πεμ' => 4,
+ 'Παρ' => 5,
+ 'Σαβ' => 6,
+ 'Κυρ' => 7,
+ );
+
+ /**
+ * List of months, calendar month name => calendar month number
+ *
+ * @access protected
+ * @var array
+ */
+ var $month = array(
+ // English
+ 'jan' => 1,
+ 'january' => 1,
+ 'feb' => 2,
+ 'february' => 2,
+ 'mar' => 3,
+ 'march' => 3,
+ 'apr' => 4,
+ 'april' => 4,
+ 'may' => 5,
+ // No long form of May
+ 'jun' => 6,
+ 'june' => 6,
+ 'jul' => 7,
+ 'july' => 7,
+ 'aug' => 8,
+ 'august' => 8,
+ 'sep' => 9,
+ 'september' => 8,
+ 'oct' => 10,
+ 'october' => 10,
+ 'nov' => 11,
+ 'november' => 11,
+ 'dec' => 12,
+ 'december' => 12,
+ // Dutch
+ 'januari' => 1,
+ 'februari' => 2,
+ 'maart' => 3,
+ 'april' => 4,
+ 'mei' => 5,
+ 'juni' => 6,
+ 'juli' => 7,
+ 'augustus' => 8,
+ 'september' => 9,
+ 'oktober' => 10,
+ 'november' => 11,
+ 'december' => 12,
+ // French
+ 'janvier' => 1,
+ 'février' => 2,
+ 'mars' => 3,
+ 'avril' => 4,
+ 'mai' => 5,
+ 'juin' => 6,
+ 'juillet' => 7,
+ 'août' => 8,
+ 'septembre' => 9,
+ 'octobre' => 10,
+ 'novembre' => 11,
+ 'décembre' => 12,
+ // German
+ 'januar' => 1,
+ 'februar' => 2,
+ 'märz' => 3,
+ 'april' => 4,
+ 'mai' => 5,
+ 'juni' => 6,
+ 'juli' => 7,
+ 'august' => 8,
+ 'september' => 9,
+ 'oktober' => 10,
+ 'november' => 11,
+ 'dezember' => 12,
+ // Italian
+ 'gennaio' => 1,
+ 'febbraio' => 2,
+ 'marzo' => 3,
+ 'aprile' => 4,
+ 'maggio' => 5,
+ 'giugno' => 6,
+ 'luglio' => 7,
+ 'agosto' => 8,
+ 'settembre' => 9,
+ 'ottobre' => 10,
+ 'novembre' => 11,
+ 'dicembre' => 12,
+ // Spanish
+ 'enero' => 1,
+ 'febrero' => 2,
+ 'marzo' => 3,
+ 'abril' => 4,
+ 'mayo' => 5,
+ 'junio' => 6,
+ 'julio' => 7,
+ 'agosto' => 8,
+ 'septiembre' => 9,
+ 'setiembre' => 9,
+ 'octubre' => 10,
+ 'noviembre' => 11,
+ 'diciembre' => 12,
+ // Finnish
+ 'tammikuu' => 1,
+ 'helmikuu' => 2,
+ 'maaliskuu' => 3,
+ 'huhtikuu' => 4,
+ 'toukokuu' => 5,
+ 'kesäkuu' => 6,
+ 'heinäkuu' => 7,
+ 'elokuu' => 8,
+ 'suuskuu' => 9,
+ 'lokakuu' => 10,
+ 'marras' => 11,
+ 'joulukuu' => 12,
+ // Hungarian
+ 'január' => 1,
+ 'február' => 2,
+ 'március' => 3,
+ 'április' => 4,
+ 'május' => 5,
+ 'június' => 6,
+ 'július' => 7,
+ 'augusztus' => 8,
+ 'szeptember' => 9,
+ 'október' => 10,
+ 'november' => 11,
+ 'december' => 12,
+ // Greek
+ 'Ιαν' => 1,
+ 'Φεβ' => 2,
+ 'Μάώ' => 3,
+ 'Μαώ' => 3,
+ 'Απρ' => 4,
+ 'Μάι' => 5,
+ 'Μαϊ' => 5,
+ 'Μαι' => 5,
+ 'Ιούν' => 6,
+ 'Ιον' => 6,
+ 'Ιούλ' => 7,
+ 'Ιολ' => 7,
+ 'Αύγ' => 8,
+ 'Αυγ' => 8,
+ 'Σεπ' => 9,
+ 'Οκτ' => 10,
+ 'Νοέ' => 11,
+ 'Δεκ' => 12,
+ );
+
+ /**
+ * List of timezones, abbreviation => offset from UTC
+ *
+ * @access protected
+ * @var array
+ */
+ var $timezone = array(
+ 'ACDT' => 37800,
+ 'ACIT' => 28800,
+ 'ACST' => 34200,
+ 'ACT' => -18000,
+ 'ACWDT' => 35100,
+ 'ACWST' => 31500,
+ 'AEDT' => 39600,
+ 'AEST' => 36000,
+ 'AFT' => 16200,
+ 'AKDT' => -28800,
+ 'AKST' => -32400,
+ 'AMDT' => 18000,
+ 'AMT' => -14400,
+ 'ANAST' => 46800,
+ 'ANAT' => 43200,
+ 'ART' => -10800,
+ 'AZOST' => -3600,
+ 'AZST' => 18000,
+ 'AZT' => 14400,
+ 'BIOT' => 21600,
+ 'BIT' => -43200,
+ 'BOT' => -14400,
+ 'BRST' => -7200,
+ 'BRT' => -10800,
+ 'BST' => 3600,
+ 'BTT' => 21600,
+ 'CAST' => 18000,
+ 'CAT' => 7200,
+ 'CCT' => 23400,
+ 'CDT' => -18000,
+ 'CEDT' => 7200,
+ 'CET' => 3600,
+ 'CGST' => -7200,
+ 'CGT' => -10800,
+ 'CHADT' => 49500,
+ 'CHAST' => 45900,
+ 'CIST' => -28800,
+ 'CKT' => -36000,
+ 'CLDT' => -10800,
+ 'CLST' => -14400,
+ 'COT' => -18000,
+ 'CST' => -21600,
+ 'CVT' => -3600,
+ 'CXT' => 25200,
+ 'DAVT' => 25200,
+ 'DTAT' => 36000,
+ 'EADT' => -18000,
+ 'EAST' => -21600,
+ 'EAT' => 10800,
+ 'ECT' => -18000,
+ 'EDT' => -14400,
+ 'EEST' => 10800,
+ 'EET' => 7200,
+ 'EGT' => -3600,
+ 'EKST' => 21600,
+ 'EST' => -18000,
+ 'FJT' => 43200,
+ 'FKDT' => -10800,
+ 'FKST' => -14400,
+ 'FNT' => -7200,
+ 'GALT' => -21600,
+ 'GEDT' => 14400,
+ 'GEST' => 10800,
+ 'GFT' => -10800,
+ 'GILT' => 43200,
+ 'GIT' => -32400,
+ 'GST' => 14400,
+ 'GST' => -7200,
+ 'GYT' => -14400,
+ 'HAA' => -10800,
+ 'HAC' => -18000,
+ 'HADT' => -32400,
+ 'HAE' => -14400,
+ 'HAP' => -25200,
+ 'HAR' => -21600,
+ 'HAST' => -36000,
+ 'HAT' => -9000,
+ 'HAY' => -28800,
+ 'HKST' => 28800,
+ 'HMT' => 18000,
+ 'HNA' => -14400,
+ 'HNC' => -21600,
+ 'HNE' => -18000,
+ 'HNP' => -28800,
+ 'HNR' => -25200,
+ 'HNT' => -12600,
+ 'HNY' => -32400,
+ 'IRDT' => 16200,
+ 'IRKST' => 32400,
+ 'IRKT' => 28800,
+ 'IRST' => 12600,
+ 'JFDT' => -10800,
+ 'JFST' => -14400,
+ 'JST' => 32400,
+ 'KGST' => 21600,
+ 'KGT' => 18000,
+ 'KOST' => 39600,
+ 'KOVST' => 28800,
+ 'KOVT' => 25200,
+ 'KRAST' => 28800,
+ 'KRAT' => 25200,
+ 'KST' => 32400,
+ 'LHDT' => 39600,
+ 'LHST' => 37800,
+ 'LINT' => 50400,
+ 'LKT' => 21600,
+ 'MAGST' => 43200,
+ 'MAGT' => 39600,
+ 'MAWT' => 21600,
+ 'MDT' => -21600,
+ 'MESZ' => 7200,
+ 'MEZ' => 3600,
+ 'MHT' => 43200,
+ 'MIT' => -34200,
+ 'MNST' => 32400,
+ 'MSDT' => 14400,
+ 'MSST' => 10800,
+ 'MST' => -25200,
+ 'MUT' => 14400,
+ 'MVT' => 18000,
+ 'MYT' => 28800,
+ 'NCT' => 39600,
+ 'NDT' => -9000,
+ 'NFT' => 41400,
+ 'NMIT' => 36000,
+ 'NOVST' => 25200,
+ 'NOVT' => 21600,
+ 'NPT' => 20700,
+ 'NRT' => 43200,
+ 'NST' => -12600,
+ 'NUT' => -39600,
+ 'NZDT' => 46800,
+ 'NZST' => 43200,
+ 'OMSST' => 25200,
+ 'OMST' => 21600,
+ 'PDT' => -25200,
+ 'PET' => -18000,
+ 'PETST' => 46800,
+ 'PETT' => 43200,
+ 'PGT' => 36000,
+ 'PHOT' => 46800,
+ 'PHT' => 28800,
+ 'PKT' => 18000,
+ 'PMDT' => -7200,
+ 'PMST' => -10800,
+ 'PONT' => 39600,
+ 'PST' => -28800,
+ 'PWT' => 32400,
+ 'PYST' => -10800,
+ 'PYT' => -14400,
+ 'RET' => 14400,
+ 'ROTT' => -10800,
+ 'SAMST' => 18000,
+ 'SAMT' => 14400,
+ 'SAST' => 7200,
+ 'SBT' => 39600,
+ 'SCDT' => 46800,
+ 'SCST' => 43200,
+ 'SCT' => 14400,
+ 'SEST' => 3600,
+ 'SGT' => 28800,
+ 'SIT' => 28800,
+ 'SRT' => -10800,
+ 'SST' => -39600,
+ 'SYST' => 10800,
+ 'SYT' => 7200,
+ 'TFT' => 18000,
+ 'THAT' => -36000,
+ 'TJT' => 18000,
+ 'TKT' => -36000,
+ 'TMT' => 18000,
+ 'TOT' => 46800,
+ 'TPT' => 32400,
+ 'TRUT' => 36000,
+ 'TVT' => 43200,
+ 'TWT' => 28800,
+ 'UYST' => -7200,
+ 'UYT' => -10800,
+ 'UZT' => 18000,
+ 'VET' => -14400,
+ 'VLAST' => 39600,
+ 'VLAT' => 36000,
+ 'VOST' => 21600,
+ 'VUT' => 39600,
+ 'WAST' => 7200,
+ 'WAT' => 3600,
+ 'WDT' => 32400,
+ 'WEST' => 3600,
+ 'WFT' => 43200,
+ 'WIB' => 25200,
+ 'WIT' => 32400,
+ 'WITA' => 28800,
+ 'WKST' => 18000,
+ 'WST' => 28800,
+ 'YAKST' => 36000,
+ 'YAKT' => 32400,
+ 'YAPT' => 36000,
+ 'YEKST' => 21600,
+ 'YEKT' => 18000,
+ );
+
+ /**
+ * Cached PCRE for SimplePie_Parse_Date::$day
+ *
+ * @access protected
+ * @var string
+ */
+ var $day_pcre;
+
+ /**
+ * Cached PCRE for SimplePie_Parse_Date::$month
+ *
+ * @access protected
+ * @var string
+ */
+ var $month_pcre;
+
+ /**
+ * Array of user-added callback methods
+ *
+ * @access private
+ * @var array
+ */
+ var $built_in = array();
+
+ /**
+ * Array of user-added callback methods
+ *
+ * @access private
+ * @var array
+ */
+ var $user = array();
+
+ /**
+ * Create new SimplePie_Parse_Date object, and set self::day_pcre,
+ * self::month_pcre, and self::built_in
+ *
+ * @access private
+ */
+ function SimplePie_Parse_Date()
+ {
+ $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
+ $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
+
+ static $cache;
+ if (!isset($cache[get_class($this)]))
+ {
+ if (extension_loaded('Reflection'))
+ {
+ $class = new ReflectionClass(get_class($this));
+ $methods = $class->getMethods();
+ $all_methods = array();
+ foreach ($methods as $method)
+ {
+ $all_methods[] = $method->getName();
+ }
+ }
+ else
+ {
+ $all_methods = get_class_methods($this);
+ }
+
+ foreach ($all_methods as $method)
+ {
+ if (strtolower(substr($method, 0, 5)) === 'date_')
+ {
+ $cache[get_class($this)][] = $method;
+ }
+ }
+ }
+
+ foreach ($cache[get_class($this)] as $method)
+ {
+ $this->built_in[] = $method;
+ }
+ }
+
+ /**
+ * Get the object
+ *
+ * @access public
+ */
+ function get()
+ {
+ static $object;
+ if (!$object)
+ {
+ $object = new SimplePie_Parse_Date;
+ }
+ return $object;
+ }
+
+ /**
+ * Parse a date
+ *
+ * @final
+ * @access public
+ * @param string $date Date to parse
+ * @return int Timestamp corresponding to date string, or false on failure
+ */
+ function parse($date)
+ {
+ foreach ($this->user as $method)
+ {
+ if (($returned = call_user_func($method, $date)) !== false)
+ {
+ return $returned;
+ }
+ }
+
+ foreach ($this->built_in as $method)
+ {
+ if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
+ {
+ return $returned;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Add a callback method to parse a date
+ *
+ * @final
+ * @access public
+ * @param callback $callback
+ */
+ function add_callback($callback)
+ {
+ if (is_callable($callback))
+ {
+ $this->user[] = $callback;
+ }
+ else
+ {
+ trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
+ }
+ }
+
+ /**
+ * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
+ * well as allowing any of upper or lower case "T", horizontal tabs, or
+ * spaces to be used as the time seperator (including more than one))
+ *
+ * @access protected
+ * @return int Timestamp
+ */
+ function date_w3cdtf($date)
+ {
+ static $pcre;
+ if (!$pcre)
+ {
+ $year = '([0-9]{4})';
+ $month = $day = $hour = $minute = $second = '([0-9]{2})';
+ $decimal = '([0-9]*)';
+ $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
+ $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
+ }
+ if (preg_match($pcre, $date, $match))
+ {
+ /*
+ Capturing subpatterns:
+ 1: Year
+ 2: Month
+ 3: Day
+ 4: Hour
+ 5: Minute
+ 6: Second
+ 7: Decimal fraction of a second
+ 8: Zulu
+ 9: Timezone ±
+ 10: Timezone hours
+ 11: Timezone minutes
+ */
+
+ // Fill in empty matches
+ for ($i = count($match); $i <= 3; $i++)
+ {
+ $match[$i] = '1';
+ }
+
+ for ($i = count($match); $i <= 7; $i++)
+ {
+ $match[$i] = '0';
+ }
+
+ // Numeric timezone
+ if (isset($match[9]) && $match[9] !== '')
+ {
+ $timezone = $match[10] * 3600;
+ $timezone += $match[11] * 60;
+ if ($match[9] === '-')
+ {
+ $timezone = 0 - $timezone;
+ }
+ }
+ else
+ {
+ $timezone = 0;
+ }
+
+ // Convert the number of seconds to an integer, taking decimals into account
+ $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
+
+ return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Remove RFC822 comments
+ *
+ * @access protected
+ * @param string $data Data to strip comments from
+ * @return string Comment stripped string
+ */
+ function remove_rfc2822_comments($string)
+ {
+ $string = (string) $string;
+ $position = 0;
+ $length = strlen($string);
+ $depth = 0;
+
+ $output = '';
+
+ while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
+ {
+ $output .= substr($string, $position, $pos - $position);
+ $position = $pos + 1;
+ if ($string[$pos - 1] !== '\\')
+ {
+ $depth++;
+ while ($depth && $position < $length)
+ {
+ $position += strcspn($string, '()', $position);
+ if ($string[$position - 1] === '\\')
+ {
+ $position++;
+ continue;
+ }
+ elseif (isset($string[$position]))
+ {
+ switch ($string[$position])
+ {
+ case '(':
+ $depth++;
+ break;
+
+ case ')':
+ $depth--;
+ break;
+ }
+ $position++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ $output .= '(';
+ }
+ }
+ $output .= substr($string, $position);
+
+ return $output;
+ }
+
+ /**
+ * Parse RFC2822's date format
+ *
+ * @access protected
+ * @return int Timestamp
+ */
+ function date_rfc2822($date)
+ {
+ static $pcre;
+ if (!$pcre)
+ {
+ $wsp = '[\x09\x20]';
+ $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
+ $optional_fws = $fws . '?';
+ $day_name = $this->day_pcre;
+ $month = $this->month_pcre;
+ $day = '([0-9]{1,2})';
+ $hour = $minute = $second = '([0-9]{2})';
+ $year = '([0-9]{2,4})';
+ $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
+ $character_zone = '([A-Z]{1,5})';
+ $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
+ $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
+ }
+ if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
+ {
+ /*
+ Capturing subpatterns:
+ 1: Day name
+ 2: Day
+ 3: Month
+ 4: Year
+ 5: Hour
+ 6: Minute
+ 7: Second
+ 8: Timezone ±
+ 9: Timezone hours
+ 10: Timezone minutes
+ 11: Alphabetic timezone
+ */
+
+ // Find the month number
+ $month = $this->month[strtolower($match[3])];
+
+ // Numeric timezone
+ if ($match[8] !== '')
+ {
+ $timezone = $match[9] * 3600;
+ $timezone += $match[10] * 60;
+ if ($match[8] === '-')
+ {
+ $timezone = 0 - $timezone;
+ }
+ }
+ // Character timezone
+ elseif (isset($this->timezone[strtoupper($match[11])]))
+ {
+ $timezone = $this->timezone[strtoupper($match[11])];
+ }
+ // Assume everything else to be -0000
+ else
+ {
+ $timezone = 0;
+ }
+
+ // Deal with 2/3 digit years
+ if ($match[4] < 50)
+ {
+ $match[4] += 2000;
+ }
+ elseif ($match[4] < 1000)
+ {
+ $match[4] += 1900;
+ }
+
+ // Second is optional, if it is empty set it to zero
+ if ($match[7] !== '')
+ {
+ $second = $match[7];
+ }
+ else
+ {
+ $second = 0;
+ }
+
+ return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Parse RFC850's date format
+ *
+ * @access protected
+ * @return int Timestamp
+ */
+ function date_rfc850($date)
+ {
+ static $pcre;
+ if (!$pcre)
+ {
+ $space = '[\x09\x20]+';
+ $day_name = $this->day_pcre;
+ $month = $this->month_pcre;
+ $day = '([0-9]{1,2})';
+ $year = $hour = $minute = $second = '([0-9]{2})';
+ $zone = '([A-Z]{1,5})';
+ $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
+ }
+ if (preg_match($pcre, $date, $match))
+ {
+ /*
+ Capturing subpatterns:
+ 1: Day name
+ 2: Day
+ 3: Month
+ 4: Year
+ 5: Hour
+ 6: Minute
+ 7: Second
+ 8: Timezone
+ */
+
+ // Month
+ $month = $this->month[strtolower($match[3])];
+
+ // Character timezone
+ if (isset($this->timezone[strtoupper($match[8])]))
+ {
+ $timezone = $this->timezone[strtoupper($match[8])];
+ }
+ // Assume everything else to be -0000
+ else
+ {
+ $timezone = 0;
+ }
+
+ // Deal with 2 digit year
+ if ($match[4] < 50)
+ {
+ $match[4] += 2000;
+ }
+ else
+ {
+ $match[4] += 1900;
+ }
+
+ return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Parse C99's asctime()'s date format
+ *
+ * @access protected
+ * @return int Timestamp
+ */
+ function date_asctime($date)
+ {
+ static $pcre;
+ if (!$pcre)
+ {
+ $space = '[\x09\x20]+';
+ $wday_name = $this->day_pcre;
+ $mon_name = $this->month_pcre;
+ $day = '([0-9]{1,2})';
+ $hour = $sec = $min = '([0-9]{2})';
+ $year = '([0-9]{4})';
+ $terminator = '\x0A?\x00?';
+ $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
+ }
+ if (preg_match($pcre, $date, $match))
+ {
+ /*
+ Capturing subpatterns:
+ 1: Day name
+ 2: Month
+ 3: Day
+ 4: Hour
+ 5: Minute
+ 6: Second
+ 7: Year
+ */
+
+ $month = $this->month[strtolower($match[2])];
+ return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Parse dates using strtotime()
+ *
+ * @access protected
+ * @return int Timestamp
+ */
+ function date_strtotime($date)
+ {
+ $strtotime = strtotime($date);
+ if ($strtotime === -1 || $strtotime === false)
+ {
+ return false;
+ }
+ else
+ {
+ return $strtotime;
+ }
+ }
+}
+
+/**
+ * Content-type sniffing
+ *
+ * @package SimplePie
+ */
+class SimplePie_Content_Type_Sniffer
+{
+ /**
+ * File object
+ *
+ * @var SimplePie_File
+ * @access private
+ */
+ var $file;
+
+ /**
+ * Create an instance of the class with the input file
+ *
+ * @access public
+ * @param SimplePie_Content_Type_Sniffer $file Input file
+ */
+ function SimplePie_Content_Type_Sniffer($file)
+ {
+ $this->file = $file;
+ }
+
+ /**
+ * Get the Content-Type of the specified file
+ *
+ * @access public
+ * @return string Actual Content-Type
+ */
+ function get_type()
+ {
+ if (isset($this->file->headers['content-type']))
+ {
+ if (!isset($this->file->headers['content-encoding'])
+ && ($this->file->headers['content-type'] === 'text/plain'
+ || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
+ || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
+ {
+ return $this->text_or_binary();
+ }
+
+ if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
+ {
+ $official = substr($this->file->headers['content-type'], 0, $pos);
+ }
+ else
+ {
+ $official = $this->file->headers['content-type'];
+ }
+ $official = strtolower($official);
+
+ if ($official === 'unknown/unknown'
+ || $official === 'application/unknown')
+ {
+ return $this->unknown();
+ }
+ elseif (substr($official, -4) === '+xml'
+ || $official === 'text/xml'
+ || $official === 'application/xml')
+ {
+ return $official;
+ }
+ elseif (substr($official, 0, 6) === 'image/')
+ {
+ if ($return = $this->image())
+ {
+ return $return;
+ }
+ else
+ {
+ return $official;
+ }
+ }
+ elseif ($official === 'text/html')
+ {
+ return $this->feed_or_html();
+ }
+ else
+ {
+ return $official;
+ }
+ }
+ else
+ {
+ return $this->unknown();
+ }
+ }
+
+ /**
+ * Sniff text or binary
+ *
+ * @access private
+ * @return string Actual Content-Type
+ */
+ function text_or_binary()
+ {
+ if (substr($this->file->body, 0, 2) === "\xFE\xFF"
+ || substr($this->file->body, 0, 2) === "\xFF\xFE"
+ || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
+ || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
+ {
+ return 'text/plain';
+ }
+ elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
+ {
+ return 'application/octect-stream';
+ }
+ else
+ {
+ return 'text/plain';
+ }
+ }
+
+ /**
+ * Sniff unknown
+ *
+ * @access private
+ * @return string Actual Content-Type
+ */
+ function unknown()
+ {
+ $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
+ if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
+ || strtolower(substr($this->file->body, $ws, 5)) === '<html'
+ || strtolower(substr($this->file->body, $ws, 7)) === '<script')
+ {
+ return 'text/html';
+ }
+ elseif (substr($this->file->body, 0, 5) === '%PDF-')
+ {
+ return 'application/pdf';
+ }
+ elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
+ {
+ return 'application/postscript';
+ }
+ elseif (substr($this->file->body, 0, 6) === 'GIF87a'
+ || substr($this->file->body, 0, 6) === 'GIF89a')
+ {
+ return 'image/gif';
+ }
+ elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
+ {
+ return 'image/png';
+ }
+ elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
+ {
+ return 'image/jpeg';
+ }
+ elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
+ {
+ return 'image/bmp';
+ }
+ else
+ {
+ return $this->text_or_binary();
+ }
+ }
+
+ /**
+ * Sniff images
+ *
+ * @access private
+ * @return string Actual Content-Type
+ */
+ function image()
+ {
+ if (substr($this->file->body, 0, 6) === 'GIF87a'
+ || substr($this->file->body, 0, 6) === 'GIF89a')
+ {
+ return 'image/gif';
+ }
+ elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
+ {
+ return 'image/png';
+ }
+ elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
+ {
+ return 'image/jpeg';
+ }
+ elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
+ {
+ return 'image/bmp';
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Sniff HTML
+ *
+ * @access private
+ * @return string Actual Content-Type
+ */
+ function feed_or_html()
+ {
+ $len = strlen($this->file->body);
+ $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
+
+ while ($pos < $len)
+ {
+ switch ($this->file->body[$pos])
+ {
+ case "\x09":
+ case "\x0A":
+ case "\x0D":
+ case "\x20":
+ $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
+ continue 2;
+
+ case '<':
+ $pos++;
+ break;
+
+ default:
+ return 'text/html';
+ }
+
+ if (substr($this->file->body, $pos, 3) === '!--')
+ {
+ $pos += 3;
+ if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
+ {
+ $pos += 3;
+ }
+ else
+ {
+ return 'text/html';
+ }
+ }
+ elseif (substr($this->file->body, $pos, 1) === '!')
+ {
+ if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
+ {
+ $pos++;
+ }
+ else
+ {
+ return 'text/html';
+ }
+ }
+ elseif (substr($this->file->body, $pos, 1) === '?')
+ {
+ if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
+ {
+ $pos += 2;
+ }
+ else
+ {
+ return 'text/html';
+ }
+ }
+ elseif (substr($this->file->body, $pos, 3) === 'rss'
+ || substr($this->file->body, $pos, 7) === 'rdf:RDF')
+ {
+ return 'application/rss+xml';
+ }
+ elseif (substr($this->file->body, $pos, 4) === 'feed')
+ {
+ return 'application/atom+xml';
+ }
+ else
+ {
+ return 'text/html';
+ }
+ }
+
+ return 'text/html';
+ }
+}
+
+/**
+ * Parses the XML Declaration
+ *
+ * @package SimplePie
+ */
+class SimplePie_XML_Declaration_Parser
+{
+ /**
+ * XML Version
+ *
+ * @access public
+ * @var string
+ */
+ var $version = '1.0';
+
+ /**
+ * Encoding
+ *
+ * @access public
+ * @var string
+ */
+ var $encoding = 'UTF-8';
+
+ /**
+ * Standalone
+ *
+ * @access public
+ * @var bool
+ */
+ var $standalone = false;
+
+ /**
+ * Current state of the state machine
+ *
+ * @access private
+ * @var string
+ */
+ var $state = 'before_version_name';
+
+ /**
+ * Input data
+ *
+ * @access private
+ * @var string
+ */
+ var $data = '';
+
+ /**
+ * Input data length (to avoid calling strlen() everytime this is needed)
+ *
+ * @access private
+ * @var int
+ */
+ var $data_length = 0;
+
+ /**
+ * Current position of the pointer
+ *
+ * @var int
+ * @access private
+ */
+ var $position = 0;
+
+ /**
+ * Create an instance of the class with the input data
+ *
+ * @access public
+ * @param string $data Input data
+ */
+ function SimplePie_XML_Declaration_Parser($data)
+ {
+ $this->data = $data;
+ $this->data_length = strlen($this->data);
+ }
+
+ /**
+ * Parse the input data
+ *
+ * @access public
+ * @return bool true on success, false on failure
+ */
+ function parse()
+ {
+ while ($this->state && $this->state !== 'emit' && $this->has_data())
+ {
+ $state = $this->state;
+ $this->$state();
+ }
+ $this->data = '';
+ if ($this->state === 'emit')
+ {
+ return true;
+ }
+ else
+ {
+ $this->version = '';
+ $this->encoding = '';
+ $this->standalone = '';
+ return false;
+ }
+ }
+
+ /**
+ * Check whether there is data beyond the pointer
+ *
+ * @access private
+ * @return bool true if there is further data, false if not
+ */
+ function has_data()
+ {
+ return (bool) ($this->position < $this->data_length);
+ }
+
+ /**
+ * Advance past any whitespace
+ *
+ * @return int Number of whitespace characters passed
+ */
+ function skip_whitespace()
+ {
+ $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
+ $this->position += $whitespace;
+ return $whitespace;
+ }
+
+ /**
+ * Read value
+ */
+ function get_value()
+ {
+ $quote = substr($this->data, $this->position, 1);
+ if ($quote === '"' || $quote === "'")
+ {
+ $this->position++;
+ $len = strcspn($this->data, $quote, $this->position);
+ if ($this->has_data())
+ {
+ $value = substr($this->data, $this->position, $len);
+ $this->position += $len + 1;
+ return $value;
+ }
+ }
+ return false;
+ }
+
+ function before_version_name()
+ {
+ if ($this->skip_whitespace())
+ {
+ $this->state = 'version_name';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function version_name()
+ {
+ if (substr($this->data, $this->position, 7) === 'version')
+ {
+ $this->position += 7;
+ $this->skip_whitespace();
+ $this->state = 'version_equals';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function version_equals()
+ {
+ if (substr($this->data, $this->position, 1) === '=')
+ {
+ $this->position++;
+ $this->skip_whitespace();
+ $this->state = 'version_value';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function version_value()
+ {
+ if ($this->version = $this->get_value())
+ {
+ $this->skip_whitespace();
+ if ($this->has_data())
+ {
+ $this->state = 'encoding_name';
+ }
+ else
+ {
+ $this->state = 'emit';
+ }
+ }
+ else
+ {
+ $this->state = 'standalone_name';
+ }
+ }
+
+ function encoding_name()
+ {
+ if (substr($this->data, $this->position, 8) === 'encoding')
+ {
+ $this->position += 8;
+ $this->skip_whitespace();
+ $this->state = 'encoding_equals';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function encoding_equals()
+ {
+ if (substr($this->data, $this->position, 1) === '=')
+ {
+ $this->position++;
+ $this->skip_whitespace();
+ $this->state = 'encoding_value';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function encoding_value()
+ {
+ if ($this->encoding = $this->get_value())
+ {
+ $this->skip_whitespace();
+ if ($this->has_data())
+ {
+ $this->state = 'standalone_name';
+ }
+ else
+ {
+ $this->state = 'emit';
+ }
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function standalone_name()
+ {
+ if (substr($this->data, $this->position, 10) === 'standalone')
+ {
+ $this->position += 10;
+ $this->skip_whitespace();
+ $this->state = 'standalone_equals';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function standalone_equals()
+ {
+ if (substr($this->data, $this->position, 1) === '=')
+ {
+ $this->position++;
+ $this->skip_whitespace();
+ $this->state = 'standalone_value';
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+
+ function standalone_value()
+ {
+ if ($standalone = $this->get_value())
+ {
+ switch ($standalone)
+ {
+ case 'yes':
+ $this->standalone = true;
+ break;
+
+ case 'no':
+ $this->standalone = false;
+ break;
+
+ default:
+ $this->state = false;
+ return;
+ }
+
+ $this->skip_whitespace();
+ if ($this->has_data())
+ {
+ $this->state = false;
+ }
+ else
+ {
+ $this->state = 'emit';
+ }
+ }
+ else
+ {
+ $this->state = false;
+ }
+ }
+}
+
+class SimplePie_Locator
+{
+ var $useragent;
+ var $timeout;
+ var $file;
+ var $local = array();
+ var $elsewhere = array();
+ var $file_class = 'SimplePie_File';
+ var $cached_entities = array();
+ var $http_base;
+ var $base;
+ var $base_location = 0;
+ var $checked_feeds = 0;
+ var $max_checked_feeds = 10;
+ var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
+
+ function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
+ {
+ $this->file =& $file;
+ $this->file_class = $file_class;
+ $this->useragent = $useragent;
+ $this->timeout = $timeout;
+ $this->max_checked_feeds = $max_checked_feeds;
+ $this->content_type_sniffer_class = $content_type_sniffer_class;
+ }
+
+ function find($type = SIMPLEPIE_LOCATOR_ALL)
+ {
+ if ($this->is_feed($this->file))
+ {
+ return $this->file;
+ }
+
+ if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
+ {
+ $sniffer = new $this->content_type_sniffer_class($this->file);
+ if ($sniffer->get_type() !== 'text/html')
+ {
+ return null;
+ }
+ }
+
+ if ($type & ~SIMPLEPIE_LOCATOR_NONE)
+ {
+ $this->get_base();
+ }
+
+ if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
+ {
+ return $working;
+ }
+
+ if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
+ {
+ if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
+ {
+ return $working;
+ }
+
+ if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
+ {
+ return $working;
+ }
+
+ if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
+ {
+ return $working;
+ }
+
+ if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
+ {
+ return $working;
+ }
+ }
+ return null;
+ }
+
+ function is_feed(&$file)
+ {
+ if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
+ {
+ $sniffer = new $this->content_type_sniffer_class($file);
+ $sniffed = $sniffer->get_type();
+ if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'application/atom+xml', 'text/xml', 'application/xml', 'text/plain')))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ function get_base()
+ {
+ $this->http_base = $this->file->url;
+ $this->base = $this->http_base;
+ $elements = SimplePie_Misc::get_element('base', $this->file->body);
+ foreach ($elements as $element)
+ {
+ if ($element['attribs']['href']['data'] !== '')
+ {
+ $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
+ $this->base_location = $element['offset'];
+ break;
+ }
+ }
+ }
+
+ function autodiscovery()
+ {
+ $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
+ $done = array();
+ foreach ($links as $link)
+ {
+ if ($this->checked_feeds == $this->max_checked_feeds)
+ {
+ break;
+ }
+ if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
+ {
+ $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
+
+ if ($this->base_location < $link['offset'])
+ {
+ $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
+ }
+ else
+ {
+ $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
+ }
+
+ if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))))
+ {
+ $this->checked_feeds++;
+ $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
+ if ($this->is_feed($feed))
+ {
+ return $feed;
+ }
+ }
+ $done[] = $href;
+ }
+ }
+ return null;
+ }
+
+ function get_links()
+ {
+ $links = SimplePie_Misc::get_element('a', $this->file->body);
+ foreach ($links as $link)
+ {
+ if (isset($link['attribs']['href']['data']))
+ {
+ $href = trim($link['attribs']['href']['data']);
+ $parsed = SimplePie_Misc::parse_url($href);
+ if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
+ {
+ if ($this->base_location < $link['offset'])
+ {
+ $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
+ }
+ else
+ {
+ $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
+ }
+
+ $current = SimplePie_Misc::parse_url($this->file->url);
+
+ if ($parsed['authority'] === '' || $parsed['authority'] == $current['authority'])
+ {
+ $this->local[] = $href;
+ }
+ else
+ {
+ $this->elsewhere[] = $href;
+ }
+ }
+ }
+ }
+ $this->local = array_unique($this->local);
+ $this->elsewhere = array_unique($this->elsewhere);
+ if (!empty($this->local) || !empty($this->elsewhere))
+ {
+ return true;
+ }
+ return null;
+ }
+
+ function extension(&$array)
+ {
+ foreach ($array as $key => $value)
+ {
+ if ($this->checked_feeds == $this->max_checked_feeds)
+ {
+ break;
+ }
+ if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
+ {
+ $this->checked_feeds++;
+ $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
+ if ($this->is_feed($feed))
+ {
+ return $feed;
+ }
+ else
+ {
+ unset($array[$key]);
+ }
+ }
+ }
+ return null;
+ }
+
+ function body(&$array)
+ {
+ foreach ($array as $key => $value)
+ {
+ if ($this->checked_feeds == $this->max_checked_feeds)
+ {
+ break;
+ }
+ if (preg_match('/(rss|rdf|atom|xml)/i', $value))
+ {
+ $this->checked_feeds++;
+ $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
+ if ($this->is_feed($feed))
+ {
+ return $feed;
+ }
+ else
+ {
+ unset($array[$key]);
+ }
+ }
+ }
+ return null;
+ }
+}
+
+class SimplePie_Parser
+{
+ var $error_code;
+ var $error_string;
+ var $current_line;
+ var $current_column;
+ var $current_byte;
+ var $separator = ' ';
+ var $feed = false;
+ var $namespace = array('');
+ var $element = array('');
+ var $xml_base = array('');
+ var $xml_base_explicit = array(false);
+ var $xml_lang = array('');
+ var $data = array();
+ var $datas = array(array());
+ var $current_xhtml_construct = -1;
+ var $encoding;
+
+ function parse(&$data, $encoding)
+ {
+ // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
+ if (strtoupper($encoding) == 'US-ASCII')
+ {
+ $this->encoding = 'UTF-8';
+ }
+ else
+ {
+ $this->encoding = $encoding;
+ }
+
+ // Strip BOM:
+ // UTF-32 Big Endian BOM
+ if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
+ {
+ $data = substr($data, 4);
+ }
+ // UTF-32 Little Endian BOM
+ elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
+ {
+ $data = substr($data, 4);
+ }
+ // UTF-16 Big Endian BOM
+ elseif (substr($data, 0, 2) === "\xFE\xFF")
+ {
+ $data = substr($data, 2);
+ }
+ // UTF-16 Little Endian BOM
+ elseif (substr($data, 0, 2) === "\xFF\xFE")
+ {
+ $data = substr($data, 2);
+ }
+ // UTF-8 BOM
+ elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
+ {
+ $data = substr($data, 3);
+ }
+
+ if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
+ {
+ $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
+ if ($declaration->parse())
+ {
+ $data = substr($data, $pos + 2);
+ $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
+ }
+ else
+ {
+ $this->error_string = 'SimplePie bug! Please report this!';
+ return false;
+ }
+ }
+
+ $return = true;
+
+ // Create the parser
+ $xml = xml_parser_create_ns($this->encoding, $this->separator);
+ xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
+ xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
+ xml_set_object($xml, $this);
+ xml_set_character_data_handler($xml, 'cdata');
+ xml_set_element_handler($xml, 'tag_open', 'tag_close');
+
+ // Parse!
+ if (!xml_parse($xml, $data, true))
+ {
+ $this->error_code = xml_get_error_code($xml);
+ $this->error_string = xml_error_string($this->error_code);
+ $return = false;
+ }
+ $this->current_line = xml_get_current_line_number($xml);
+ $this->current_column = xml_get_current_column_number($xml);
+ $this->current_byte = xml_get_current_byte_index($xml);
+ xml_parser_free($xml);
+ return $return;
+ }
+
+ function get_error_code()
+ {
+ return $this->error_code;
+ }
+
+ function get_error_string()
+ {
+ return $this->error_string;
+ }
+
+ function get_current_line()
+ {
+ return $this->current_line;
+ }
+
+ function get_current_column()
+ {
+ return $this->current_column;
+ }
+
+ function get_current_byte()
+ {
+ return $this->current_byte;
+ }
+
+ function get_data()
+ {
+ return $this->data;
+ }
+
+ function tag_open($parser, $tag, $attributes)
+ {
+ if ($this->feed === 0)
+ {
+ return;
+ }
+ elseif ($this->feed == false)
+ {
+ if (in_array($tag, array(
+ SIMPLEPIE_NAMESPACE_ATOM_10 . $this->separator . 'feed',
+ SIMPLEPIE_NAMESPACE_ATOM_03 . $this->separator . 'feed',
+ 'rss',
+ SIMPLEPIE_NAMESPACE_RDF . $this->separator . 'RDF'
+ )))
+ {
+ $this->feed = 1;
+ }
+ }
+ else
+ {
+ $this->feed++;
+ }
+
+ list($this->namespace[], $this->element[]) = $this->split_ns($tag);
+
+ $attribs = array();
+ foreach ($attributes as $name => $value)
+ {
+ list($attrib_namespace, $attribute) = $this->split_ns($name);
+ $attribs[$attrib_namespace][$attribute] = $value;
+ }
+
+ if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
+ {
+ $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
+ $this->xml_base_explicit[] = true;
+ }
+ else
+ {
+ $this->xml_base[] = end($this->xml_base);
+ $this->xml_base_explicit[] = end($this->xml_base_explicit);
+ }
+
+ if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
+ {
+ $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
+ }
+ else
+ {
+ $this->xml_lang[] = end($this->xml_lang);
+ }
+
+ if ($this->current_xhtml_construct >= 0)
+ {
+ $this->current_xhtml_construct++;
+ if (end($this->namespace) == SIMPLEPIE_NAMESPACE_XHTML)
+ {
+ $this->data['data'] .= '<' . end($this->element);
+ if (isset($attribs['']))
+ {
+ foreach ($attribs[''] as $name => $value)
+ {
+ $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
+ }
+ }
+ $this->data['data'] .= '>';
+ }
+ }
+ else
+ {
+ $this->datas[] =& $this->data;
+ $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
+ $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
+ if ((end($this->namespace) == SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] == 'xml')
+ || (end($this->namespace) == SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] == 'xhtml'))
+ {
+ $this->current_xhtml_construct = 0;
+ }
+ }
+ }
+
+ function cdata($parser, $cdata)
+ {
+ if ($this->current_xhtml_construct >= 0)
+ {
+ $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
+ }
+ elseif ($this->feed > 1)
+ {
+ $this->data['data'] .= $cdata;
+ }
+ }
+
+ function tag_close($parser, $tag)
+ {
+ if (!$this->feed)
+ {
+ return;
+ }
+
+ if ($this->current_xhtml_construct >= 0)
+ {
+ $this->current_xhtml_construct--;
+ if (end($this->namespace) == SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
+ {
+ $this->data['data'] .= '</' . end($this->element) . '>';
+ }
+ }
+ if ($this->current_xhtml_construct == -1)
+ {
+ $this->data =& $this->datas[$this->feed];
+ array_pop($this->datas);
+ }
+
+ array_pop($this->element);
+ array_pop($this->namespace);
+ array_pop($this->xml_base);
+ array_pop($this->xml_base_explicit);
+ array_pop($this->xml_lang);
+ $this->feed--;
+ }
+
+ function split_ns($string)
+ {
+ static $cache = array();
+ if (!isset($cache[$string]))
+ {
+ if ($pos = strpos($string, $this->separator))
+ {
+ static $separator_length;
+ if (!$separator_length)
+ {
+ $separator_length = strlen($this->separator);
+ }
+ $namespace = substr($string, 0, $pos);
+ $local_name = substr($string, $pos + $separator_length);
+ if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
+ {
+ $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
+ }
+
+ // Normalize the Media RSS namespaces
+ if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
+ {
+ $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
+ }
+ $cache[$string] = array($namespace, $local_name);
+ }
+ else
+ {
+ $cache[$string] = array('', $string);
+ }
+ }
+ return $cache[$string];
+ }
+}
+
+/**
+ * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
+ */
+class SimplePie_Sanitize
+{
+ // Private vars
+ var $base;
+
+ // Options
+ var $remove_div = true;
+ var $image_handler = '';
+ var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
+ var $encode_instead_of_strip = false;
+ var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
+ var $strip_comments = false;
+ var $output_encoding = 'UTF-8';
+ var $enable_cache = true;
+ var $cache_location = './cache';
+ var $cache_name_function = 'md5';
+ var $cache_class = 'SimplePie_Cache';
+ var $file_class = 'SimplePie_File';
+ var $timeout = 10;
+ var $useragent = '';
+ var $force_fsockopen = false;
+
+ var $replace_url_attributes = array(
+ 'a' => 'href',
+ 'area' => 'href',
+ 'blockquote' => 'cite',
+ 'del' => 'cite',
+ 'form' => 'action',
+ 'img' => array('longdesc', 'src'),
+ 'input' => 'src',
+ 'ins' => 'cite',
+ 'q' => 'cite'
+ );
+
+ function remove_div($enable = true)
+ {
+ $this->remove_div = (bool) $enable;
+ }
+
+ function set_image_handler($page = false)
+ {
+ if ($page)
+ {
+ $this->image_handler = (string) $page;
+ }
+ else
+ {
+ $this->image_handler = false;
+ }
+ }
+
+ function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
+ {
+ if (isset($enable_cache))
+ {
+ $this->enable_cache = (bool) $enable_cache;
+ }
+
+ if ($cache_location)
+ {
+ $this->cache_location = (string) $cache_location;
+ }
+
+ if ($cache_name_function)
+ {
+ $this->cache_name_function = (string) $cache_name_function;
+ }
+
+ if ($cache_class)
+ {
+ $this->cache_class = (string) $cache_class;
+ }
+ }
+
+ function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
+ {
+ if ($file_class)
+ {
+ $this->file_class = (string) $file_class;
+ }
+
+ if ($timeout)
+ {
+ $this->timeout = (string) $timeout;
+ }
+
+ if ($useragent)
+ {
+ $this->useragent = (string) $useragent;
+ }
+
+ if ($force_fsockopen)
+ {
+ $this->force_fsockopen = (string) $force_fsockopen;
+ }
+ }
+
+ function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
+ {
+ if ($tags)
+ {
+ if (is_array($tags))
+ {
+ $this->strip_htmltags = $tags;
+ }
+ else
+ {
+ $this->strip_htmltags = explode(',', $tags);
+ }
+ }
+ else
+ {
+ $this->strip_htmltags = false;
+ }
+ }
+
+ function encode_instead_of_strip($encode = false)
+ {
+ $this->encode_instead_of_strip = (bool) $encode;
+ }
+
+ function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
+ {
+ if ($attribs)
+ {
+ if (is_array($attribs))
+ {
+ $this->strip_attributes = $attribs;
+ }
+ else
+ {
+ $this->strip_attributes = explode(',', $attribs);
+ }
+ }
+ else
+ {
+ $this->strip_attributes = false;
+ }
+ }
+
+ function strip_comments($strip = false)
+ {
+ $this->strip_comments = (bool) $strip;
+ }
+
+ function set_output_encoding($encoding = 'UTF-8')
+ {
+ $this->output_encoding = (string) $encoding;
+ }
+
+ /**
+ * Set element/attribute key/value pairs of HTML attributes
+ * containing URLs that need to be resolved relative to the feed
+ *
+ * @access public
+ * @since 1.0
+ * @param array $element_attribute Element/attribute key/value pairs
+ */
+ function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
+ {
+ $this->replace_url_attributes = (array) $element_attribute;
+ }
+
+ function sanitize($data, $type, $base = '')
+ {
+ $data = trim($data);
+ if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
+ {
+ if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
+ {
+ if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
+ {
+ $type |= SIMPLEPIE_CONSTRUCT_HTML;
+ }
+ else
+ {
+ $type |= SIMPLEPIE_CONSTRUCT_TEXT;
+ }
+ }
+
+ if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
+ {
+ $data = base64_decode($data);
+ }
+
+ if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
+ {
+ if ($this->remove_div)
+ {
+ $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
+ $data = preg_replace('/<\/div>$/', '', $data);
+ }
+ else
+ {
+ $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
+ }
+ }
+
+ if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
+ {
+ // Strip comments
+ if ($this->strip_comments)
+ {
+ $data = SimplePie_Misc::strip_comments($data);
+ }
+
+ // Strip out HTML tags and attributes that might cause various security problems.
+ // Based on recommendations by Mark Pilgrim at:
+ // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
+ if ($this->strip_htmltags)
+ {
+ foreach ($this->strip_htmltags as $tag)
+ {
+ $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
+ while (preg_match($pcre, $data))
+ {
+ $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
+ }
+ }
+ }
+
+ if ($this->strip_attributes)
+ {
+ foreach ($this->strip_attributes as $attrib)
+ {
+ $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
+ }
+ }
+
+ // Replace relative URLs
+ $this->base = $base;
+ foreach ($this->replace_url_attributes as $element => $attributes)
+ {
+ $data = $this->replace_urls($data, $element, $attributes);
+ }
+
+ // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
+ if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
+ {
+ $images = SimplePie_Misc::get_element('img', $data);
+ foreach ($images as $img)
+ {
+ if (isset($img['attribs']['src']['data']))
+ {
+ $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
+ $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
+
+ if ($cache->load())
+ {
+ $img['attribs']['src']['data'] = $this->image_handler . $image_url;
+ $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
+ }
+ else
+ {
+ $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
+ $headers = $file->headers;
+
+ if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)))
+ {
+ if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
+ {
+ $img['attribs']['src']['data'] = $this->image_handler . $image_url;
+ $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
+ }
+ else
+ {
+ trigger_error("$cache->name is not writeable", E_USER_WARNING);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
+ $data = trim($data);
+ }
+
+ if ($type & SIMPLEPIE_CONSTRUCT_IRI)
+ {
+ $data = SimplePie_Misc::absolutize_url($data, $base);
+ }
+
+ if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
+ {
+ $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
+ }
+
+ if ($this->output_encoding != 'UTF-8')
+ {
+ $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
+ }
+ }
+ return $data;
+ }
+
+ function replace_urls($data, $tag, $attributes)
+ {
+ if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
+ {
+ $elements = SimplePie_Misc::get_element($tag, $data);
+ foreach ($elements as $element)
+ {
+ if (is_array($attributes))
+ {
+ foreach ($attributes as $attribute)
+ {
+ if (isset($element['attribs'][$attribute]['data']))
+ {
+ $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
+ $new_element = SimplePie_Misc::element_implode($element);
+ $data = str_replace($element['full'], $new_element, $data);
+ $element['full'] = $new_element;
+ }
+ }
+ }
+ elseif (isset($element['attribs'][$attributes]['data']))
+ {
+ $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
+ $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
+ }
+ }
+ }
+ return $data;
+ }
+
+ function do_strip_htmltags($match)
+ {
+ if ($this->encode_instead_of_strip)
+ {
+ if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
+ {
+ $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
+ $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
+ return "<$match[1]$match[2]>$match[3]</$match[1]>";
+ }
+ else
+ {
+ return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
+ }
+ }
+ elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
+ {
+ return $match[4];
+ }
+ else
+ {
+ return '';
+ }
+ }
+}
+
+?>
\ No newline at end of file
Added: trunk/qo-kregator/qo-kregator.css
===================================================================
--- trunk/qo-kregator/qo-kregator.css (rev 0)
+++ trunk/qo-kregator/qo-kregator.css 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,129 @@
+/************************************************************************
+ This file is part of Qo-Kregator.
+
+ Desk-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+*************************************************************************/
+
+.x-form-file-wrap {position: relative;height: 22px;}
+.x-form-file-wrap .x-form-file {position: absolute;right: 0;-moz-opacity: 0;filter:alpha(opacity: 0);opacity: 0;z-index: 2;height: 22px;}
+.x-form-file-wrap .x-form-file-btn {position: absolute;right: 0;z-index: 1;}
+.x-form-file-wrap .x-form-file-text {position: absolute;left: 0;z-index: 3;color: #777;}
+
+.upload-icon {background: url('img/default/folder_open.png') no-repeat 0 0 !important;}
+
+
+/* TreePanel */
+.qo-kregator-x-column-tree .x-tree-node {zoom:1;}
+.qo-kregator-x-column-tree .x-tree-node-el {zoom:1;}
+.qo-kregator-x-column-tree .x-tree-selected {background: #d9e8fb;}
+.qo-kregator-x-column-tree .x-tree-node a {line-height:18px;vertical-align:middle;}
+.qo-kregator-x-column-tree .x-tree-node .x-tree-selected a span {background:transparent;color:#000;}
+.qo-kregator-x-tree-col {float:left;overflow:hidden;padding:0 1px;zoom:1;}
+.qo-kregator-x-tree-col-text, .qo-kregator-x-tree-hd-text, .qo-kregator-x-tree-hd-text-feed {overflow:hidden;-o-text-overflow: ellipsis;text-overflow: ellipsis;padding:3px 3px 3px 5px;white-space: nowrap;font:normal 11px arial, tahoma, helvetica, sans-serif;}
+.qo-kregator-x-tree-col-text {text-align: right;}
+.qo-kregator-x-tree-hd-text {text-align: right;}
+.qo-kregator-x-tree-hd-text-feed {text-align: left;}
+.qo-kregator-x-tree-headers {background: #f9f9f9 url('img/default/grid3-hrow.gif') repeat-x 0 bottom;cursor:default;zoom:1;}
+.qo-kregator-x-tree-hd {float:left;overflow:hidden;border-left:1px solid #eee;border-right:1px solid #d0d0d0;}
+
+/* Media Enclosure */
+h1.qo-kregator-enclosure {margin: 10px 0px 10px 0px;padding-left: 20px;color: #54667a;border-bottom: 1px solid #54667a;background: url(img/default/media.png) no-repeat 0 top;line-height: 18px;}
+tr.qo-kregator-enclosure:hover {background-color: #dfe8f6;}
+td.qo-kregator-enclosure-img, td.qo-kregator-enclosure-content {text-align:center;}
+
+/* Splash screen */
+#qo-kregator-splash {position:absolute;left:30%;top:20%;padding:2px;z-index:20001;height:auto;border:1px solid #425063;background-color: #425063;color: #fff;}
+#qo-kregator-splash-msg {background: url('img/default/loading.gif') no-repeat 0px 1px;padding-left:20px;padding-top:2px;}
+
+/* About / Credit */
+#qo-kregator-credit ul {margin: 5px;}
+#qo-kregator-credit li {margin: 10px;list-style-image: url(img/default/bullet_blue.png) !important;padding:0;}
+.qo-kregator-credit-info {color: #3B433B;}
+#qo-kregator-about, #qo-kregator-about-info {text-align: center;color: #000;}
+
+/* Grid Panel */
+.qo-kregator-summary {margin: 0 0 0 10px !important;padding-left: 18px !important;background: transparent url('img/default/summary-p.png') no-repeat 0 50%;}
+.qo-kregator-feed-info {background: #F1F2F4 none repeat scroll 0%;border-bottom: 1px solid #DADADB;padding: 5px;}
+.qo-kregator-feed-image {float: right;}
+.qo-kregator-feed-read.x-grid3-row td {font-weight: normal!important;}
+.qo-kregator-feed-unread.x-grid3-row td {font-weight: bold!important;}
+.qo-kregator-feed-important {color: #ff0000 !important;}
+.qo-kregator-feed-Unseen {font-weight: bold;}
+.qo-kregator-item-date {float: right;margin: 0;font-size: 10px;font-weight:normal;}
+.qo-kregator-item-title {font:bold 12px "sans serif", verdana;color:#444444;}
+.qo-kregator-item-author {font:normal 9px "sans serif", verdana;}
+.qo-kregator-feed-content {padding: 10px;background-color: #fff; font-size: 11px;}
+.qo-kregator-feed-image {float: right;}
+/*.qo-kregator-preview-content {overflow:hidden;width: 100%;height:100%;} */
+
+/* Desktop Icon */
+.qo-kregator-win-shortcut img {background-image: url('img/default/desktop-icon.png');filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='system/modules/Desk-Kregator/img/default/desktop-icon.png', sizingMethod='scale');}
+
+/* App Icon */
+.qo-kregator-summary-btn { background-image:url('img/default/summary.png') !important;}
+.qo-kregator-preview-bottom { background-image:url('img/default/preview-bottom.png') !important;}
+.qo-kregator-preview-right { background-image:url('img/default/preview-right.png') !important;}
+.qo-kregator-preview-hide { background-image:url('img/default/preview-hide.png') !important;}
+
+.qo-kregator-icon-datefilter { background-image:url('img/default/date.png') !important;}
+
+.qo-kregator-refresh-btn { background-image:url('img/default/refresh.png') !important;}
+.qo-kregator-refresh-btn-conf { background:url('img/default/refresh.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-refresh-stop-btn { background-image:url('img/default/stop.png') !important;}
+.qo-kregator-open-site-btn { background-image:url('img/default/open_site.png') !important;}
+.qo-kregator-open-inTab-btn { background-image:url('img/default/open_in_tab.png') !important;}
+.qo-kregator-close-Tab-btn { background-image:url('img/default/tab_delete.png') !important;}
+.qo-kregator-icon, .qo-kregator-icon-about { background-image:url('img/default/icon.png') !important;}
+
+.qo-kregator-icon-import { background-image:url('img/default/import.png') !important;}
+.qo-kregator-icon-import-conf { background:url('img/default/import.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-export { background-image:url('img/default/export.png') !important;}
+.qo-kregator-icon-export-conf { background:url('img/default/export.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-expand { background-image:url('img/default/expand.png') !important;}
+.qo-kregator-icon-expand-conf { background:url('img/default/expand.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-collapse { background-image:url('img/default/collapse.png') !important;}
+.qo-kregator-icon-collapse-conf { background:url('img/default/collapse.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-conf { background-image:url('img/default/conf.png') !important;}
+
+
+.qo-kregator-icon-contextmenu { background-image:url('img/default/mouse.png') !important;}
+.qo-kregator-icon-contextmenu-conf { background:url('img/default/mouse.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-add-feed { background-image:url('img/default/feed_add.png') !important;}
+.qo-kregator-icon-add-feed-conf { background:url('img/default/feed_add.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-add-folder { background-image:url('img/default/folder_add.png') !important;}
+.qo-kregator-icon-add-folder-conf { background:url('img/default/folder_add.png') no-repeat 0 0; padding-left: 18px;}
+
+.qo-kregator-icon-mod-folder { background-image:url('img/default/folder_modify.png') !important;}
+.qo-kregator-icon-mod-feed { background-image:url('img/default/feed_modify.png') !important;}
+.qo-kregator-icon-del-folder { background-image:url('img/default/folder_delete.png') !important;}
+.qo-kregator-icon-del-feed { background-image:url('img/default/feed_delete.png') !important;}
+.qo-kregator-icon-mark-all-as-read { background-image:url('img/default/mark_all_as_read.png') !important;}
+.qo-kregator-icon-mark-as-read { background-image:url('img/default/mark_as_read.png') !important;}
+.qo-kregator-icon-mark-as-unread { background-image:url('img/default/mark_as_unread.png') !important;}
+.qo-kregator-icon-mark-as-important { background-image:url('img/default/flag_red.png') !important;}
+.qo-kregator-icon-unmark-as-important { background-image:url('img/default/flag_red.png') !important;}
+.qo-kregator-feed-folder { background-image:url('img/default/folder_go.png') !important;}
+
+/* Status Bar */
+#qo-kregator-statusBar .x-status-text {font:normal 8pt verdana;padding-left: 20px;padding-top: 2px;}
+.qo-kregator-inProgress {background: url('img/default/loading.gif') no-repeat 0px 1px;padding-top:2px;}
+.qo-kregator-done {background: url('img/default/information.png') no-repeat 0px 1px; padding-top:2px;}
+.qo-kregator-error {color: #ff0000 !important;font-weight: bold !important;background: url('img/default/exclamation.png') no-repeat 0px 1px;padding-top:2px;}
\ No newline at end of file
Added: trunk/qo-kregator/qo-kregator.js
===================================================================
--- trunk/qo-kregator/qo-kregator.js (rev 0)
+++ trunk/qo-kregator/qo-kregator.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,3456 @@
+/************************************************************************
+ This file is part of Qo-Kregator.
+ Qo-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+ *************************************************************************/
+
+// Allow to add a Menu after the Button is rendered
+Ext.override(Ext.Button,
+{
+ initComponent: function() {
+ Ext.Button.superclass.initComponent.call(this);
+ this.addEvents('click','toggle','mouseover','mouseout','menushow','menuhide','menutriggerover','menutriggerout');
+
+ if (this.menu) {
+ var m = this.menu;
+ delete this.menu;
+ this.setMenu(m);
+ }
+
+ if (typeof this.toggleGroup === 'string') {
+ this.enableToggle = true;
+ }
+ },
+
+ setMenu: function(menu) {
+ var hasMenu = (this.menu !== null);
+ this.menu = Ext.menu.MenuMgr.get(menu);
+
+ if (this.rendered && !hasMenu) {
+ this.el.child(this.menuClassTarget).addClass('x-btn-with-menu');
+ this.menu.on("show", this.onMenuShow, this);
+ this.menu.on("hide", this.onMenuHide, this);
+ }
+ },
+
+ clearMenu: function(destroy) {
+ if (this.rendered) {
+ this.el.child(this.menuClassTarget).removeClass('x-btn-with-menu');
+ this.menu.un('show', this.onMenuShow, this);
+ this.menu.un('hide', this.onMenuHide, this);
+ }
+ if (destroy) {
+ Ext.destroy(this.menu);
+ }
+ this.menu = null;
+ }
+}
+);
+
+QoDesk.QoKregator = Ext.extend(Ext.app.Module, {
+
+ moduleType : 'internet',
+ moduleId : 'qo-kregator',
+ menuPath: 'StartMenu/Internet',
+
+ appVer : '2.0',
+
+ // Conf var
+ ConfExpandCollapse : false,
+ ConfGoRefresh: true,
+ ConfShowSummary: true,
+ ConfTreePanelWidth:'254',
+ ConfGridPanelHeight:'150',
+ ConfPreviewPanelSouthHeight:'300',
+ ConfPreviewPanelEastWidth:'400',
+ ConfPreviewPane:'bottom',
+ ConfRefreshFeed:'10',
+ ConfOldItems:false,
+ ConfOldItemsDay:'30',
+ ConfContentFontSize: 11,
+ ConfshowStatusBar: 'on',
+ ConfOpenMode: 'Window',
+ ConfDateTimeFormat: 'd/m/y, H:i',
+ ConfDateFormat: 'd/m/y',
+
+ // Panel
+ PanelFeedTree:'',
+ PanelFeedTreeEditor:'',
+ PanelGridItem:'',
+ PanelPreview:'',
+ PanelCenter:'',
+
+ //ToolBars
+ tbFeedBtnAvailable: ['AddFeed', 'AddFolder', 'Import', 'Export', 'ExpandCollapse', 'RefreshFeed', 'ContextMenu'],
+ tbFeedBtnCurrent: [],
+
+ // DataStore
+ dsItems:'',
+ dsItemDesc:'',
+
+ // Window
+ winAbout:false,
+
+ // Task
+ TaskSearchFeed:false,
+ TaskCleanFeed:false,
+
+ // others vars
+ FeedNeedUpdate:false,
+ LastClick:0,
+ curNodeId:'',
+ curFeedId:'',
+ columnUnseenWidth:50, // change this value to modify Unseen column width
+ columnTotalWidth:50, // change this value to modify Total column width
+ linkDefaultTab:'',
+
+ init: function(){
+ this.launcher = {
+ text: 'Qo-Kregator',
+ tooltip: '<b>Qo-Kregator</b><br />' + QoKregator.LauncherDescription,
+ iconCls: 'qo-kregator-icon',
+ shortcutIconCls: 'qo-kregator-win-shortcut',
+ handler: this.createWindow,
+ scope: this
+ };
+ },
+
+ createWindow: function() {
+ var desktop = this.app.getDesktop();
+ var win = desktop.getWindow('qo-kregator');
+
+ if (!win) {
+
+
+ // Plugins for right click on tab
+ Ext.ux.KregaTabCloseMenu = function(env){
+ var tabs, menu, ctxItem;
+ this.scope = env;
+ this.init = function(tp){
+ tabs = tp;
+ tabs.on('contextmenu', onContextMenu, this);
+ };
+
+ function onContextMenu(ts, item, e){
+
+ e.preventDefault();
+ e.stopEvent();
+
+ if( item.id == 'qo-kregator-main' ) { item.linkTab = this.scope.linkDefaultTab;}
+
+ if(!menu){ // create context menu on first right click
+ menu = new Ext.menu.Menu([{
+ id: 'qo-kregator-' + tabs.id + '-close',
+ text: QoKregator.TabCtxCloseTab,
+ iconCls: 'DeskKregator-close-Tab-btn',
+ handler : function() {
+ tabs.remove(ctxItem);
+ }
+ },{
+ id: 'qo-kregator-' + tabs.id + '-close-others',
+ text: QoKregator.TabCtxCloseOtherTabs,
+ handler : function() {
+ tabs.items.each(function(item){
+ if(item.closable && item != ctxItem){
+ tabs.remove(item);
+ }
+ });
+ }
+ },'-',{
+ id:'qo-kregator-' + tabs.id + '-open-tab-site',
+ text:QoKregator.FeedGridItemOpenInWin,
+ iconCls:'qo-kregator-open-site-btn',
+ handler: function() {
+ window.open(ctxItem.linkTab, 'win');
+ }
+ }]);
+ }
+ ctxItem = item;
+ var items = menu.items;
+ items.get('qo-kregator-' + tabs.id + '-close').setDisabled(!item.closable);
+ var disableOthers = true;
+ tabs.items.each(function(){
+ if(this != item && this.closable){
+ disableOthers = false;
+ return false;
+ }
+ });
+ items.get('qo-kregator-' + tabs.id + '-close-others').setDisabled(disableOthers);
+ if( !item.linkTab ) {
+ items.get('qo-kregator-' + tabs.id + '-open-tab-site').setDisabled(true);
+ } else {
+ items.get('qo-kregator-' + tabs.id + '-open-tab-site').setDisabled(false);
+ }
+ menu.showAt(e.getPoint());
+ }
+ };
+
+ // Create Splash
+ Ext.DomHelper.append(document.body, {
+ tag: 'div',
+ id: 'qo-kregator-splash',
+ children: [{
+ tag: 'div',
+ cls: 'qo-kregator-splash-indicator',
+ html: '<img src="system/modules/qo-kregator/img/default/logo.png" alt="" /><div id="qo-kregator-splash-msg">' + QoKregator.SplashInit + '</div>'
+ }]
+ });
+
+ // We load user conf before show app
+ Ext.get('qo-kregator-splash-msg').dom.innerHTML = QoKregator.SplashLoadConf;
+
+
+ Ext.Ajax.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ what: 'get_user_conf'
+ },
+ success: function(response, options) {
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.ConfRefreshFeed = o.refresh_feed;
+ this.ConfOldItems = o.old_items;
+ this.ConfOldItemsDay = o.old_items_day;
+ this.ConfPreviewPane = o.preview_pane;
+ this.ConfShowSummary = o.showSummary;
+ this.ConfContentFontSize = o.content_font_size;
+ this.ConfshowStatusBar = o.showStatusBar;
+ this.tbFeedBtnCurrent = o.tbFeedBtn;
+
+ this.ConfOpenMode = o.openMode;
+
+ this.ConfDateTimeFormat = o.dateTimeFormat;
+ this.ConfDateFormat = o.dateFormat;
+
+ this.ConfTreePanelWidth = o.tree_panel_width;
+ this.ConfGridPanelHeight = o.grid_panel_height;
+ this.ConfPreviewPanelSouthHeight = o.preview_panel_south_height;
+ this.ConfPreviewPanelEastWidth = o.preview_panel_east_width;
+
+ } else {
+
+ this.ConfRefreshFeed = 10;
+ this.ConfOldItems = false;
+ this.ConfOldItemsDay = 30;
+ this.ConfPreviewPane = 'bottom';
+ this.ConfShowSummary = true;
+ this.ConfContentFontSize = 11;
+ this.ConfshowStatusBar = 'on';
+ this.ConfOpenMode = 'Window';
+
+ this.ConfDateTimeFormat = 'd/m/y, H:i';
+ this.ConfDateFormat = 'd/m/y';
+
+ this.ConfTreePanelWidth = '254';
+ this.ConfGridPanelHeight = '150';
+ this.ConfPreviewPanelSouthHeight = '300';
+ this.ConfPreviewPanelEastWidth = '400';
+ this.tbFeedBtnCurrent = ['AddFeed', 'AddFolder', 'Import', 'Export', 'ExpandCollapse', 'RefreshFeed'];
+
+ }
+
+ // Custom ColumnTree
+ Ext.tree.KregaColumnTree = Ext.extend(Ext.tree.TreePanel, {
+ lines:false,
+ borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
+ cls:'qo-kregator-x-column-tree',
+ onRender : function(){
+ Ext.tree.KregaColumnTree.superclass.onRender.apply(this, arguments);
+ this.headers = this.body.createChild(
+ {id:'qo-kregator-x-tree-headers-id', cls:'qo-kregator-x-tree-headers'},this.innerCt.dom);
+ var cols = this.columns, c;
+ var totalWidth = 0;
+ for(var i = 0, len = cols.length; i < len; i++) {
+ var clsHere;
+ if( i === 0 ) { clsHere = 'qo-kregator-x-tree-hd-text-feed';}
+ else { clsHere = 'qo-kregator-x-tree-hd-text';}
+
+ c = cols[i];
+ totalWidth += c.width;
+ this.headers.createChild({
+ id: 'qo-kregator-feed-hd-'+i,
+ cls:'qo-kregator-x-tree-hd ' + (c.cls?c.cls+'-hd':''),
+ cn: {
+ cls: clsHere,
+ html: c.header
+ },
+ style:'width:'+(c.width-this.borderWidth)+'px;'
+ });
+ }
+ this.headers.createChild({cls:'x-clear'});
+ // prevent floats from wrapping when clipped
+ this.headers.setWidth(totalWidth);
+ this.innerCt.setWidth(totalWidth);
+ }
+ });
+
+ Ext.tree.KregaColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+ focus: Ext.emptyFn, // prevent odd scrolling behavior
+
+ renderElements : function(n, a, targetNode, bulkRender){
+ this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
+
+ var t = n.getOwnerTree();
+ var cols = t.columns;
+ var bw = t.borderWidth;
+ var c = cols[0];
+ var colID;
+
+ var buf = [
+ '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'">',
+ '<div class="qo-kregator-x-tree-col" style="width:',c.width-bw,'px;">',
+ '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
+ '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
+ '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
+ '<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
+ a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
+ '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
+ "</div>"];
+ for(var i = 1, len = cols.length; i < len; i++) {
+ c = cols[i];
+
+ if( i == 1 ) { colID = 'qo-kregator-unSeen-'+n.id; }
+ else { colID = 'qo-kregator-Total-'+n.id; }
+
+ buf.push('<div class="qo-kregator-x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
+ '<div class="qo-kregator-x-tree-col-text" id="'+colID+'">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
+ "</div>");
+ }
+ buf.push(
+ '<div class="x-clear"></div></div>',
+ '<ul class="x-tree-node-ct" style="display:none;"></ul>',
+ "</li>");
+
+ if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
+ this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
+ n.nextSibling.ui.getEl(), buf.join(""));
+ }else{
+ this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
+ }
+
+ this.elNode = this.wrap.childNodes[0];
+ this.ctNode = this.wrap.childNodes[1];
+ var cs = this.elNode.firstChild.childNodes;
+ this.indentNode = cs[0];
+ this.ecNode = cs[1];
+ this.iconNode = cs[2];
+ this.anchor = cs[3];
+ this.textNode = cs[3].firstChild;
+ }
+ });
+
+ this.dsItems = new Ext.data.Store({
+ proxy: new Ext.data.HttpProxy({
+ url: this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/qo-kregator.php&what=get_items'
+ }),
+ reader: new Ext.data.JsonReader({
+ root: 'Items',
+ totalProperty: 'nbItems',
+ id: 'id'
+ }, [{
+ name: 'id',
+ mapping: 'id'
+ }, {
+ name: 't',
+ mapping: 't'
+ }, {
+ name: 'd',
+ mapping: 'd'
+ }, {
+ name: 'u',
+ mapping: 'u'
+ }, {
+ name: 's',
+ mapping: 's'
+ }, {
+ name: 'i',
+ mapping: 'i'
+ }, {
+ name: 'f',
+ mapping: 'f'
+ }, {
+ name: 'id_f',
+ mapping: 'id_f'
+ }, {
+ name: 'sum',
+ mapping: 'sum'
+ }])
+ });
+
+ // Sort by default : date, DESC
+ this.dsItems.setDefaultSort('d', 'desc');
+
+ this.dsItems.on('load', function(){
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutDone);
+ this.selectFirstUnreadItems();
+
+ }, this);
+
+ this.dsItemDesc = new Ext.data.Store({
+ proxy: new Ext.data.HttpProxy({
+ url: this.app.connection
+ }),
+ baseParams: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ what: 'get_items_desc'
+ },
+ reader: new Ext.data.JsonReader({}, [{
+ name: 't'
+ }, {
+ name: 'd'
+ }, {
+ name: 'a'
+ }, {
+ name: 'des'
+ }, {
+ name: 'u'
+ }, {
+ name: 'f'
+ }])
+ });
+
+ this.dsItemDesc.on('load', function(){
+
+ var nodeItem = this.dsItemDesc.getAt(0);
+
+ if( nodeItem ) {
+
+ var title = nodeItem.data.t;
+ var link = nodeItem.data.u;
+ var date = this.renderDate(nodeItem.data.d, this.ConfDateTimeFormat);
+ var auteur = nodeItem.data.a;
+ var feedName = nodeItem.data.f;
+ var desc = nodeItem.data.des;
+
+ if (this.PanelFeedTree.selModel.selNode.attributes.view == 'site') {
+
+ this.PanelPreview.setTitle(this.PanelFeedTree.selModel.selNode.attributes.text);
+
+ // Remove content
+ this.PanelPreview.body.dom.innerHTML = '';
+
+ // Add iframe via miframe
+ this.PanelPreview.add({
+ xtype : 'iframepanel',
+ id : 'qo-kregator-preview-iframe',
+ loadMask : true,
+ defaultSrc : link
+ });
+
+ this.PanelPreview.doLayout();
+
+ } else {
+
+ this.PanelPreview.setTitle(feedName);
+
+ var content = '<div class="qo-kregator-feed-info">' +
+ '<div class="qo-kregator-item-date">' +
+ date +
+ '</div>' +
+ '<div class="qo-kregator-item-title">' +
+ title +
+ '</div>' +
+ '<div class="qo-kregator-item-author">' +
+ QoKregator.PreviewAutor +
+ auteur +
+ '</div>' +
+ '</div>' +
+ '<div class="qo-kregator-feed-content">' +
+ desc +
+ '</div>';
+
+ this.PanelPreview.body.dom.innerHTML = content;
+ this.setContentFontSize('=');
+ this.PanelPreview.el.on('click', function(e, target, options) {
+
+ e.preventDefault();
+ e.stopEvent();
+
+ var delai = new Date();
+ var curClick = delai.getTime();
+
+ if (this.LastClick === 0) { this.LastClick = curClick - 51; }
+
+ var diff = (curClick - this.LastClick);
+ if (target.href) {
+ if (diff > 50) {
+ this.LastClick = curClick;
+ var uniq = Ext.id();
+ this.openInTab(uniq, target.href, target.href);
+ }
+ }
+ }, this);
+ }
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutDone);
+
+ }
+
+ }, this);
+
+ this.PanelFeedTree = new Ext.tree.KregaColumnTree({
+ width:252,
+ id: 'qo-kregator-id-tree-column',
+ border: false,
+ enableDD: true,
+ autoHeight:true,
+ rootVisible:false,
+ autoScroll:true,
+ containerScroll: true,
+ listeners: {
+ scope: this,
+ contextmenu: this.onContextMenuFeed,
+ click: this.onClickFeed
+ },
+
+ columns:[{
+ id:'qo-kregator-feedTree-colum',
+ header:QoKregator.TreeTitle,
+ width:150,
+ dataIndex:'text'
+ },{
+ header: QoKregator.TreeColumn1,
+ width:this.columnUnseenWidth,
+ dataIndex:'unseen'
+ },{
+ header: QoKregator.TreeColumn2,
+ width:this.columnTotalWidth,
+ dataIndex:'total'
+ }],
+
+ loader: new Ext.tree.TreeLoader({
+ dataUrl:this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/qo-kregator.php&what=get_nodes',
+ uiProviders:{
+ 'col': Ext.tree.KregaColumnNodeUI
+ }
+ }),
+
+ root: new Ext.tree.AsyncTreeNode({
+ text:'RootFeed'
+ })
+ });
+
+ // Editor
+ this.PanelFeedTreeEditor = new Ext.tree.TreeEditor(this.PanelFeedTree, {
+ allowBlank: false
+ });
+
+ // Edit node
+ this.PanelFeedTreeEditor.on('complete', function(editor, fieldValue, beforeValue){
+
+ // If there is no change, go back
+ if(fieldValue == beforeValue) { return; }
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutMod);
+
+ // Update nodeText
+ var saveFeedText = new Ext.data.Connection();
+ saveFeedText.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id: editor.editNode.id,
+ value: fieldValue,
+ what: 'mod_feed_text'
+ },
+
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutModOk);
+
+ // Update tab title & preview Title
+ Ext.getCmp('qo-kregator-main').setTitle(Ext.util.Format.ellipsis(fieldValue,20));
+ this.PanelPreview.setTitle(fieldValue);
+
+ }
+ else {
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutModNok);
+ }
+ }
+ });
+
+ }, this);
+
+ // Drag & Drop Tree Elements
+ this.PanelFeedTree.on('enddrag', function(tree){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutReorder);
+
+ function simplifyNodes(node){
+ var resultNode = {};
+ var kids = node.childNodes;
+ var len = kids.length;
+ for (var i = 0; i < len; i++) {
+ resultNode[kids[i].id] = simplifyNodes(kids[i]);
+ }
+ return resultNode;
+ }
+
+ // JSON-encode our tree
+ var encNodes = Ext.encode(simplifyNodes(this.PanelFeedTree.root));
+
+ // send it to the backend to save
+ var saveOrder = new Ext.data.Connection();
+ saveOrder.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodes: encNodes,
+ what: 'save_nodes'
+ },
+
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutReorderOk);
+ }
+ else {
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutReorderNok);
+ }
+ }
+ });
+ }, this);
+
+ // New SearchField
+ Ext.app.SearchField = Ext.extend(Ext.form.TwinTriggerField, {
+
+ initComponent: function(){
+
+ if (!this.store.baseParams) {
+ this.store.baseParams = {};
+ }
+
+ Ext.app.SearchField.superclass.initComponent.call(this);
+
+ this.on('specialkey', function(f, e){
+ if (e.getKey() == e.ENTER) {
+ this.onTrigger2Click();
+ }
+ }, this);
+ },
+
+ validationEvent: false,
+ validateOnBlur: false,
+ trigger1Class: 'x-form-clear-trigger',
+ trigger2Class: 'x-form-search-trigger',
+ hideTrigger1: true,
+ width: 100,
+ hasSearch: false,
+ emptyText: QoKregator.FeedGridFilterSearch,
+
+ onTrigger1Click: function(){
+ if (this.hasSearch) {
+
+ this.store.baseParams = {
+ 'id_feed': this.env.curFeedId,
+ 'id_node': this.env.curNodeId
+ };
+
+ Ext.getCmp('qo-kregator-etat').setValue('all', true);
+
+ var o = {
+ start: 0,
+ limit: 25
+ };
+ this.store.reload({
+ params: o
+ });
+
+ this.el.dom.value = '';
+ this.triggers[0].hide();
+ this.hasSearch = false;
+ }
+ this.reset();
+ },
+
+ onTrigger2Click: function(){
+
+ var v = this.getRawValue();
+
+ if (v.length < 2 && v !== '') {
+ Ext.Msg.alert(QoKregator.FeedGridBoxSearchTitle, QoKregator.FeedGridBoxSearchContent);
+ return;
+ }
+
+ this.env.setStatusBar('qo-kregator-inProgress', QoKregator.StatutSearchLoad);
+
+ this.store.baseParams = {
+ 'id_feed': this.env.curFeedId,
+ 'id_node': this.env.curNodeId,
+ 'searchText': v,
+ 'searchEtat': Ext.getCmp('qo-kregator-etat').getValue(),
+ 'searchDate' : Ext.getCmp('qo-kregator-datefilter-btn').curDate
+ };
+
+ var o = {
+ start: 0,
+ limit: 25
+ };
+ this.store.reload({
+ params: o
+ });
+ this.hasSearch = true;
+ this.triggers[0].show();
+ }
+ });
+ Ext.reg('searchfield', Ext.app.SearchField);
+ // End new searchField
+
+ this.PanelGridItem = new Ext.grid.GridPanel({
+ scope: this,
+ id:'qo-kregator-id-gridFeed-panel',
+ store: this.dsItems,
+ lastRowClick: {
+ time: new Date().getTime(),
+ row: -1
+ },
+ columns: [{
+ id: 'article',
+ header: QoKregator.FeedGridHeaderItem,
+ sortable: true,
+ dataIndex: 't'
+ }, {
+ id: 'feed',
+ header: QoKregator.FeedGridHeaderFeed,
+ sortable: true,
+ width: 120,
+ dataIndex: 'f'
+ }, {
+ id: 'date',
+ header: QoKregator.FeedGridHeaderDate,
+ width: 120,
+ sortable: true,
+ dataIndex: 'd',
+ scope: this,
+ renderer: this.renderDate.createDelegate(this, [this.ConfDateTimeFormat], 1)
+ }],
+ autoExpandColumn: 'article',
+ loadMask: true,
+ viewConfig: {
+ scope: this,
+ forceFit: true,
+ showSummary: this.ConfShowSummary,
+ enableRowBody: true,
+ getRowClass: function(record, rowIndex, p, ds) {
+
+ var retour = '';
+
+ if (record.data.s == 'y') {
+ retour += 'qo-kregator-feed-read';
+ } else {
+ retour += 'qo-kregator-feed-unread';
+ }
+
+ if (record.data.i == 'y') {
+ retour += ' qo-kregator-feed-important';
+ }
+
+ if( this.showSummary ) {
+ p.body = '<p class="qo-kregator-summary">' + record.data.sum + '</p>';
+ retour += ' x-grid3-row-expanded';
+ }
+
+ return retour;
+
+ }
+ },
+ enableColumnMove: true,
+ tbar: [{
+ xtype:'searchfield',
+ id: 'qo-kregator-search',
+ width: 130,
+ store: this.dsItems,
+ env: this,
+ listeners: {
+ scope: this
+ }
+ },'-',{
+ xtype: 'combo',
+ store: new Ext.data.SimpleStore({
+ fields: ['etat', 'Libel'],
+ data: [['all', QoKregator.FeedGridFilterAllItems], ['nonlu', QoKregator.FeedGridFilterUnseenItems], ['important', QoKregator.FeedGridFilterImportantItems]]
+ }),
+ displayField: 'Libel',
+ valueField: 'etat',
+ typeAhead: true,
+ width: 120,
+ mode: 'local',
+ triggerAction: 'all',
+ selectOnFocus: false,
+ editable: false,
+ allowBlank: false,
+ value: 'all',
+ id: 'qo-kregator-etat',
+ listeners: {
+ scope: this,
+ select: function(){
+ Ext.getCmp('qo-kregator-search').onTrigger2Click();
+ }
+ }
+ },'-',{
+ xtype: 'tbsplit',
+ scope:this,
+ text: QoKregator.FeedGridFilterDateAllDate,
+ id: 'qo-kregator-datefilter-btn',
+ iconCls: 'qo-kregator-icon-datefilter',
+ tooltip: QoKregator.FeedGridFilterDatePickDate,
+ curDate: '*',
+ enableToggle: true,
+ handler: function(btn) {
+ if( btn.pressed ) {
+ btn.setText(QoKregator.FeedGridFilterDatePickDate);
+ btn.showMenu();
+ btn.curDate = '*';
+ } else {
+ btn.setText(QoKregator.FeedGridFilterDateAllDate);
+ btn.hideMenu();
+ btn.curDate = '*';
+ Ext.getCmp('qo-kregator-search').onTrigger2Click();
+ }
+ },
+ menu: new Ext.menu.DateMenu({
+ scope: this,
+ handler : function(dp, date){
+ Ext.getCmp('qo-kregator-datefilter-btn').setText(date.format(this.ConfDateFormat));
+ Ext.getCmp('qo-kregator-datefilter-btn').curDate = date.format('Y:m:d');
+ Ext.getCmp('qo-kregator-search').onTrigger2Click();
+ }
+ })
+ }, '-', {
+ scope: this,
+ tooltip: {
+ title: QoKregator.ReadingBtnTitle,
+ text: QoKregator.ReadingBtnQtip
+ },
+ iconCls: 'qo-kregator-preview-bottom',
+ handler: this.movePreview
+ },'-',{
+ scope: this,
+ tooltip: {
+ title: QoKregator.SummaryBtnTitle,
+ text: QoKregator.SummaryBtnText
+ },
+ enableToggle: true,
+ id:'qo-kregator-summary-btn-id',
+ iconCls: 'qo-kregator-summary-btn',
+ toggleHandler: function(btn, pressed){
+ this.toggleSummary(pressed);
+ }
+ },'-', {
+ xtype: 'button',
+ scope:this,
+ id: 'qo-kregator-contextmenu-news-btn',
+ iconCls: 'qo-kregator-icon-contextmenu',
+ tooltip: {
+ title: QoKregator.ContextMenuBtnTooltipTitle,
+ text: QoKregator.ContextMenuBtnTooltipText
+ },
+ menu: []
+ }
+ ],
+
+ bbar: new Ext.PagingToolbar({
+ pageSize: 25,
+ store: this.dsItems,
+ displayInfo: true,
+ displayMsg: QoKregator.FeedGridPagingDisplay,
+ emptyMsg: QoKregator.FeedGridPagingNoDisplay
+ }),
+ listeners: {
+ scope: this,
+ rowdblclick: function(grid, rowIndex, e) {
+
+ var _node = this.dsItems.getAt(rowIndex);
+ var _id = _node.data.id;
+ var _link = _node.data.u;
+ var _title = _node.data.t;
+ this.openInTab('items-' + _id, _title, _link);
+
+ var timeNow = new Date().getTime();
+
+ if(grid.lastRowClick.row != rowIndex){
+ grid.lastRowClick.row = rowIndex;
+ grid.lastRowClick.time = timeNow;
+ }
+ else if(timeNow - grid.lastRowClick.time >= 500){
+ return;
+ }
+ else{
+ grid.lastRowClick.time = timeNow;
+ }
+
+ },
+
+ rowclick: function(grid, rowIndex, e) {
+
+ var timeNow = new Date().getTime();
+ if(grid.lastRowClick.row != rowIndex){
+ grid.lastRowClick.row = rowIndex;
+ grid.lastRowClick.time = timeNow;
+ }
+ else if(timeNow - grid.lastRowClick.time < 500){
+ return;
+ }
+ else{
+ grid.lastRowClick.time = timeNow;
+ }
+
+ },
+
+ rowcontextmenu: function(grid, rowIndex, e){
+ this.onContextItemFeed(grid, rowIndex, e);
+ }
+ }
+ });
+
+ // SelectionModel for GridPanel
+ var smPanelGridItem = this.PanelGridItem.getSelectionModel();
+ smPanelGridItem.on('rowselect', function(sM, rowIndex, r) {
+
+ //Build the sub-menu for the contextMenu-btn
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu(this.createContextItemFeed());
+
+ this.loadItem(rowIndex);
+
+ }, this);
+
+ this.PanelCenter = new Ext.TabPanel({
+ region: 'center',
+ margins: '0 0 0 0',
+ activeTab: 0,
+ border: false,
+ bodyStyle: 'background-color:#fff',
+ enableTabScroll: true,
+ plugins: new Ext.ux.KregaTabCloseMenu(this),
+ defaults: {
+ autoScroll: true
+ },
+ items: [{
+ title: QoKregator.FeedGridTabTitle,
+ id: 'qo-kregator-main',
+ border: false,
+ margins: '0 0 0 0',
+ layout: 'fit',
+ items: [{
+ region: 'center',
+ border: false,
+ layout: 'border',
+ margins: '0 0 0 0',
+ items: [{
+ region: 'center',
+ layout: 'fit',
+ border: false,
+ minHeight: 150,
+ height: 150,
+ split: true,
+ items: this.PanelGridItem
+ }, {
+ layout: 'fit',
+ region: 'south',
+ split: true,
+ height: 300,
+ bodyStyle: 'background-color:#fff',
+ id: 'qo-kregator-previewPanelSouth',
+ title: QoKregator.PreviewTitle
+ }, {
+ layout: 'fit',
+ region: 'east',
+ split: true,
+ hidden: true,
+ width: 400,
+ bodyStyle: 'background-color:#fff',
+ id: 'qo-kregator-previewPanelEast',
+ title: QoKregator.PreviewTitle
+ }]
+ }]
+ }]
+ });
+
+ this.PanelPreview = Ext.getCmp('qo-kregator-previewPanelSouth');
+
+ var winWidth = desktop.getWinWidth() / 1.1;
+ var winHeight = desktop.getWinHeight() / 1.1;
+
+ // Feed ToolBar
+ this.tbFeedBtnAvailable.AddFeed = {
+ xtype: 'button',
+ id: 'qo-kregator-add-feed-btn',
+ iconCls:'qo-kregator-icon-add-feed',
+ cls: 'x-btn-icon',
+ scope: this,
+ handler: function(){
+ this.showAddFeed(0);
+ },
+ tooltip: QoKregator.TreeAddFeed
+ };
+
+ this.tbFeedBtnAvailable.AddFolder = {
+ xtype: 'button',
+ iconCls:'qo-kregator-icon-add-folder',
+ scope: this,
+ handler: function(){
+ this.showAddFolder(0);
+ },
+ tooltip: QoKregator.TreeAddFolder
+ };
+
+ this.tbFeedBtnAvailable.Import = {
+ xtype: 'button',
+ iconCls:'qo-kregator-icon-import',
+ scope: this,
+ handler: this.showImport,
+ tooltip: QoKregator.TreeImport
+ };
+
+ this.tbFeedBtnAvailable.Export = {
+ xtype: 'button',
+ scope: this,
+ iconCls:'qo-kregator-icon-export',
+ handler: function(){
+ window.location = this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/export.php';
+ },
+ tooltip: QoKregator.TreeExport
+ };
+
+
+ this.tbFeedBtnAvailable.ExpandCollapse = {
+ xtype: 'button',
+ scope: this,
+ id: 'qo-kregator-expand-collapse-btn',
+ iconCls:'qo-kregator-icon-expand',
+ handler: function(){
+ if( !this.ConfExpandCollapse ) {
+
+ this.ConfExpandCollapse='collapse';
+ this.PanelFeedTree.expandAll();
+ Ext.getCmp('qo-kregator-expand-collapse-btn').setIconClass('qo-kregator-icon-collapse');
+
+ } else if( this.ConfExpandCollapse == 'expand' ) {
+
+ this.ConfExpandCollapse='collapse';
+ this.PanelFeedTree.expandAll();
+ Ext.getCmp('qo-kregator-expand-collapse-btn').setIconClass('qo-kregator-icon-collapse');
+
+ } else if( this.ConfExpandCollapse == 'collapse' ) {
+
+ this.ConfExpandCollapse='expand';
+ this.PanelFeedTree.collapseAll();
+ Ext.getCmp('qo-kregator-expand-collapse-btn').setIconClass('qo-kregator-icon-expand');
+
+ }
+ },
+ tooltip: QoKregator.TreeExpandCollapse
+ };
+
+ this.tbFeedBtnAvailable.RefreshFeed = {
+ xtype: 'button',
+ scope:this,
+ id: 'qo-kregator-add-refresh-feed-btn',
+ iconCls: 'qo-kregator-refresh-btn',
+ handler: function(){
+ this.TaskSearchFeed.delay(1000);
+ },
+ tooltip: QoKregator.TreeRefresh
+ };
+
+ this.tbFeedBtnAvailable.ContextMenu = {
+ xtype: 'button',
+ scope:this,
+ id: 'qo-kregator-contextmenu-btn',
+ iconCls: 'qo-kregator-icon-contextmenu',
+ tooltip: {
+ title: QoKregator.ContextMenuBtnTooltipTitle,
+ text: QoKregator.ContextMenuBtnTooltipText
+ },
+ menu: []
+ };
+
+
+ win = desktop.createWindow({
+ id: 'qo-kregator',
+ title: 'Qo-Kregator',
+ width: winWidth,
+ height: winHeight,
+ x: desktop.getWinX(winWidth),
+ y: desktop.getWinY(winHeight),
+ iconCls: 'qo-kregator-icon',
+ shim: false,
+ animCollapse: false,
+ constrainHeader: true,
+ minimizable: true,
+ maximizable: true,
+ layout: 'border',
+ tools : [{
+ scope: this,
+ id:'gear',
+ qtip:QoKregator.WinConfToolTip,
+ handler:this.showConf
+
+ }, {
+ scope: this,
+ id:'help',
+ qtip: QoKregator.WinAboutTitle,
+ handler:this.showAbout
+
+ }],
+ bbar: new Ext.StatusBar({
+ id: 'qo-kregator-statusBar',
+ text: QoKregator.StatutReady,
+ iconCls: 'qo-kregator-done'
+
+ }),
+ items: [{
+ region: 'west',
+ layout:'fit',
+ id: 'qo-kregator-id-Feed-Tree',
+ autoScroll: true,
+ collapsible: true,
+ collapseMode: 'mini',
+ cmargins: '0 0 0 0',
+ margins: '0 0 0 0',
+ split: true,
+ bodyStyle: 'background-color:#fff',
+ width: 254,
+ items: this.PanelFeedTree,
+ scope: this,
+ tbar: []
+ }, this.PanelCenter]
+ });
+
+ //Build Tb Feed
+ this.buildTbFeed();
+
+ this.PanelFeedTree.on('collapsenode', function(node){ this.saveFolderState(node.id, 0); }, this);
+ this.PanelFeedTree.on('expandnode', function(node){ this.saveFolderState(node.id, 1); }, this);
+
+ // Set preview pane position
+ this.setPreviewPanePosition(this.ConfPreviewPane);
+
+ // Set summary configuration
+ this.setSummary(this.ConfShowSummary);
+
+ // Show / Hide the statusBar
+ this.showHideStatusBar();
+
+ // Set Pane Size
+ this.setPanelSize('tree_panel_width', this.ConfTreePanelWidth);
+ this.setPanelSize('grid_panel_height', this.ConfGridPanelHeight);
+ this.setPanelSize('panel_south_height',this.ConfPreviewPanelSouthHeight);
+ this.setPanelSize('panel_east_width', this.ConfPreviewPanelEastWidth);
+
+ if (this.ConfOldItems) {
+
+ // Register task for delete old items
+ this.TaskCleanFeed = new Ext.util.DelayedTask(this.cleanFeed, this);
+ this.TaskCleanFeed.delay(2000); // start after 2 secondes.
+ } else {
+
+ // Register task for AutoRefresh Feed
+ this.TaskSearchFeed = new Ext.util.DelayedTask(this.searchFeed, this);
+ this.TaskSearchFeed.delay(2000); // start after 2 secondes.
+ }
+
+ // Unregister
+ win.on('close', function() { this.TaskSearchFeed.cancel(); }, this);
+
+ var Krega_taskSelectFirstFeed = new Ext.util.DelayedTask(this.selectFirstUnseenFeed, this);
+ Krega_taskSelectFirstFeed.delay(1000); // start after 1 seconde.
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutReady);
+
+ // 'On' resize TreePanel
+ Ext.getCmp('qo-kregator-id-Feed-Tree').on('resize', function(panel, Pwidth, Pheight) {
+
+ var treeWidth;
+
+ if( panel.body.isScrollable() ) { treeWidth = Pwidth-19; }
+ else { treeWidth = Pwidth; }
+
+ this.setFeedPanelWidth(treeWidth);
+ this.savePanelSizeState('tree_panel_width', treeWidth);
+
+ }, this);
+
+ // 'On' resize GridPanel
+ Ext.getCmp('qo-kregator-id-gridFeed-panel').on('resize', function(panel, Pwidth, Pheight) {
+ this.savePanelSizeState('grid_panel_height', Pheight);
+ }, this);
+
+ // 'On' resize PreviewPanel Bottom
+ Ext.getCmp('qo-kregator-previewPanelSouth').on('resize', function(panel, Pwidth, Pheight) {
+ this.savePanelSizeState('preview_panel_south_height', Pheight);
+ }, this);
+
+ // 'On' resize PreviewPanel Right
+ Ext.getCmp('qo-kregator-previewPanelEast').on('resize', function(panel, Pwidth, Pheight) {
+ this.savePanelSizeState('preview_panel_east_width', Pwidth);
+ }, this);
+
+ // Remove the splash screen
+ Ext.get('qo-kregator-splash').fadeOut({
+ remove: true
+ });
+
+ // Handle How we must open Qo-Kregator
+ if( this.ConfOpenMode == 'Window' ) {
+ win.show();
+ } else if( this.ConfOpenMode == 'FullScreen' ) {
+ win.show();
+ new Ext.util.DelayedTask().delay(2000, function() { win.maximize(); }, this);
+ } else if( this.ConfOpenMode == 'Minimized' ) {
+ win.show();
+ new Ext.util.DelayedTask().delay(2000, function() { win.minimize(); }, this);
+ }
+
+
+
+ } // End successfully load user's configuration
+
+ });
+
+
+ } else { win.show(); }
+
+ }, //createWindow
+
+ buildTbFeed: function() {
+
+ // We remove all button currently in this toolBar
+ var nbButton = Ext.getCmp('qo-kregator-id-Feed-Tree').getTopToolbar().items.items.length;
+
+ for( var i=0; i < nbButton; i++ ) {
+ var item = Ext.getCmp('qo-kregator-id-Feed-Tree').getTopToolbar().items.itemAt(i);
+ item.destroy();
+ }
+
+ // And now, we create the New ToolBar
+ var curTb = [];
+
+ Ext.each(this.tbFeedBtnCurrent, function(item) {
+
+ curTb.push(this.tbFeedBtnAvailable[item]);
+
+ }, this);
+
+ Ext.getCmp('qo-kregator-id-Feed-Tree').getTopToolbar().add(curTb);
+
+ // Build the sub Menu for contextMenu button if exist
+ if( Ext.getCmp('qo-kregator-contextmenu-btn') ) {
+
+ var node = this.PanelFeedTree.getSelectionModel().getSelectedNode();
+
+ if( node && node.attributes.type == 'folder' ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFolder());
+ }
+ if( node && node.attributes.type == 'file' ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFeed());
+ }
+ }
+ }, //buildTbFeed
+
+ selectFirstUnreadItems: function() {
+
+ var firstItem = false;
+ var firstItemUnread = false;
+ var rowIndex = 0;
+
+ // If there is no items in the dsItems, we reset the contextMenu-btn
+ if( this.dsItems.data.length === 0 ) {
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu('');
+ }
+
+ // We loop over items
+ for( var i = 0 ; i < this.dsItems.data.length ; i++ ) {
+
+ // State first items
+ if( i === 0 ) { firstItem = this.dsItems.data.items[i].data.id; }
+
+ // State first items unread
+ if( this.dsItems.data.items[i].data.s == 'n' ) {
+ firstItemUnread = this.dsItems.data.items[i].data.id;
+ rowIndex = i;
+ break;
+ }
+ }
+
+ if( firstItemUnread ) {
+
+ // Load first unread
+ this.PanelGridItem.getSelectionModel().selectRow(rowIndex);
+
+ this.loadItem(rowIndex);
+ } else if( firstItem ) {
+
+ // or load first item
+ this.PanelGridItem.getSelectionModel().selectRow(rowIndex);
+ this.loadItem(rowIndex);
+ }
+
+ }, // selectFirstUnreadItems
+
+ selectFirstUnseenFeed: function() {
+
+ var firstFeed = false;
+ var firstFolder = false;
+ var firstFeedUnread = false;
+
+ function _searchFeed(node){
+ var kids = node.childNodes;
+ var len = kids.length;
+ for (var i = 0; i < len; i++) {
+
+ if (kids[i].attributes.type == 'folder') {
+ if( !firstFolder ) { firstFolder = kids[i].id; }
+ }
+
+ if (kids[i].attributes.type == 'file') {
+
+ if( !firstFeed ) { firstFeed = kids[i].id; }
+
+ if( kids[i].attributes.unseen != '-' && kids[i].attributes.unseen > 0 ) {
+
+ if( !firstFeedUnread ) {
+ firstFeedUnread = kids[i].id;
+ break;
+ }
+ }
+
+ }
+ if( !firstFeedUnread ) { _searchFeed(kids[i]); }
+ }
+ }
+
+ _searchFeed(this.PanelFeedTree.getRootNode());
+
+ // Select Best Feed
+ if( firstFeedUnread ) {
+ this.PanelFeedTree.getNodeById(firstFeedUnread).select();
+ this.onClickFeed(this.PanelFeedTree.getNodeById(firstFeedUnread));
+ } else if( firstFeed ) {
+ this.PanelFeedTree.getNodeById(firstFeed).select();
+ this.onClickFeed(this.PanelFeedTree.getNodeById(firstFeed));
+ } else if( firstFolder ) {
+ this.PanelFeedTree.getNodeById(firstFolder).select();
+ this.onClickFeed(this.PanelFeedTree.getNodeById(firstFolder));
+ }
+ },
+
+ loadItem : function(rowIndex) {
+
+ var curArticle = this.dsItems.getAt(rowIndex).data.id;
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutLoadFeedArticle + this.dsItems.getAt(rowIndex).data.t);
+
+ this.markAsSeenUnseen('y', curArticle, this);
+ var r = Ext.get(this.PanelGridItem.getView().getRow(rowIndex));
+ r.replaceClass("qo-kregator-feed-unread", "qo-kregator-feed-read");
+
+ this.dsItemDesc.load({
+ params: {
+ 'id_item': curArticle
+ }
+ });
+
+ }, // loadItem
+
+ setPanelSize : function(Panel, Psize) {
+
+ switch (Panel) {
+ case 'tree_panel_width':
+ Ext.getCmp('qo-kregator-id-Feed-Tree').setWidth(Psize);
+ this.setFeedPanelWidth(Psize);
+ break;
+ case 'grid_panel_height':
+ Ext.getCmp('qo-kregator-id-gridFeed-panel').setHeight(Psize);
+ break;
+ case 'panel_south_height':
+ Ext.getCmp('qo-kregator-previewPanelSouth').setHeight(Psize);
+ break;
+ case 'panel_east_width':
+ Ext.getCmp('qo-kregator-previewPanelEast').setWidth(Psize);
+ break;
+ }
+
+ }, // setPanelSize
+
+ savePanelSizeState : function(Panel, Psize) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ panel: Panel,
+ panelsize: Psize,
+ what: 'set_panelsize_state'
+ }
+ });
+
+ }, //savePanelWidthState
+
+ setFeedPanelWidth : function(treeWidth) {
+
+ var bw = Ext.isBorderBox ? 0 : 2;
+ var widths = [(treeWidth-(this.columnUnseenWidth+this.columnTotalWidth+4)), this.columnUnseenWidth, this.columnTotalWidth];
+ var totalWidth = 0;
+ for (var i = 0; i < widths.length; i++) {
+ totalWidth += widths[i];
+ Ext.select("div.qo-kregator-x-tree-hd:nth-child(" + (i+1) + ")", false, "*TreeID*").setWidth(widths[i] - bw);
+ Ext.select("div.qo-kregator-x-tree-col:nth-child(" + (i+1) + ")", false, "*TreeID*").setWidth(widths[i] - bw);
+ this.PanelFeedTree.columns[i].width = widths[i];
+ }
+ this.PanelFeedTree.headers.setWidth(totalWidth);
+ this.PanelFeedTree.innerCt.setWidth(totalWidth);
+
+ }, //setFeedPanelWidth
+
+ setSummary : function(pressed) {
+
+ this.toggleSummary(pressed);
+ Ext.getCmp('qo-kregator-summary-btn-id').toggle(pressed);
+
+ }, // setSummary
+
+ toggleSummary : function(pressed) {
+
+ this.PanelGridItem.view.showSummary = pressed;
+ this.PanelGridItem.view.refresh();
+
+ // Save in DB
+ this.saveSummaryState(pressed);
+
+ }, // toggleSummary
+
+ saveSummaryState:function(state) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ showSummary: state,
+ what: 'set_summary_state'
+ }
+ });
+
+ }, // saveSummaryState
+
+ saveFolderState:function(_nodeID, expand) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodeID: _nodeID,
+ expand: expand,
+ what: 'set_folder_state'
+ },
+ success: function(response, options){},
+ failure: function(response, options){}
+ });
+
+ }, // saveFolderState
+
+ movePreview: function() {
+
+ if( this.ConfPreviewPane == 'bottom' ) {
+ // Set to right
+ this.ConfPreviewPane = 'right';
+ this.setPreviewPanePosition('right');
+
+ } else if( this.ConfPreviewPane == 'right' ) {
+ //set to hide
+ this.ConfPreviewPane = 'hide';
+ this.setPreviewPanePosition('hide');
+
+ } else if( this.ConfPreviewPane == 'hide' ) {
+ // set to bottom
+ this.ConfPreviewPane = 'bottom';
+ this.setPreviewPanePosition('bottom');
+
+ }
+
+ }, // movePreview
+
+ setPreviewPanePosition : function(position) {
+
+ var _title = this.PanelPreview.title;
+ var _content = this.PanelPreview.body.dom.innerHTML;
+
+ var right = Ext.getCmp('qo-kregator-previewPanelEast');
+ var bot = Ext.getCmp('qo-kregator-previewPanelSouth');
+ var btn = this.PanelGridItem.getTopToolbar().items.get(6);
+
+ switch (position) {
+ case 'bottom':
+ this.PanelPreview = bot;
+ this.PanelPreview.setTitle(_title);
+ this.PanelPreview.el.on('click',this.clickInterceptor, this);
+ right.hide();
+ bot.show();
+ bot.ownerCt.doLayout();
+ btn.setIconClass('qo-kregator-preview-bottom');
+ this.dsItemDesc.fireEvent('load', this);
+
+ break;
+
+ case 'right':
+ this.PanelPreview = right;
+ this.PanelPreview.setTitle(_title);
+ this.PanelPreview.el.on('click',this.clickInterceptor, this);
+ bot.hide();
+ right.show();
+ right.ownerCt.doLayout();
+ btn.setIconClass('qo-kregator-preview-right');
+ this.dsItemDesc.fireEvent('load', this);
+ break;
+
+ case 'hide':
+ this.PanelPreview.hide();
+ this.PanelPreview.ownerCt.doLayout();
+ btn.setIconClass('qo-kregator-preview-hide');
+ break;
+ }
+
+ this.savePreviewPanePosition(position);
+
+ }, // setPreviewPanePosition
+
+ savePreviewPanePosition:function(state) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ preview_pane: state,
+ what: 'set_previewpaneposition_state'
+ }
+ });
+
+ }, // savePreviewPanePosition
+
+ updateFeedInfo : function(id_feed, nb_unseen, nb_total) {
+
+ if( nb_total === 0 ) { nb_total = '-'; }
+
+
+ if( nb_unseen === 0 ) {
+ // Remove class bold
+ nb_unseen = '-';
+ this.PanelFeedTree.getNodeById(id_feed).ui.removeClass("qo-kregator-feed-Unseen");
+ Ext.get('qo-kregator-unSeen-'+id_feed).removeClass("qo-kregator-feed-Unseen");
+ } else {
+ // Add class bold
+ this.PanelFeedTree.getNodeById(id_feed).ui.addClass("qo-kregator-feed-Unseen");
+ Ext.get('qo-kregator-unSeen-'+id_feed).addClass("qo-kregator-feed-Unseen");
+ }
+
+ Ext.get('qo-kregator-unSeen-'+id_feed).dom.innerHTML = nb_unseen;
+ Ext.get('qo-kregator-Total-'+id_feed).dom.innerHTML = nb_total;
+
+ }, //updateFeedInfo
+
+ cleanFeed: function(){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutCleanItemsWait);
+
+ Ext.Ajax.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ day: this.ConfOldItemsDay,
+ what: 'clean_feed'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutCleanItemsOk + o.del_items);
+
+
+ }
+ else {
+
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutCleanItemsNok + o.msg);
+
+ }
+
+ // Register task for AutoRefresh Feed after cleanFeed
+ this.TaskSearchFeed = new Ext.util.DelayedTask(this.searchFeed, this);
+ this.TaskSearchFeed.delay(2000); // start after 2 secondes.
+ }
+ });
+
+ }, // cleanFeed
+
+ clickInterceptor : function(e, target, options){
+
+ e.preventDefault();
+ e.stopEvent();
+
+ var delai = new Date();
+ var curClick = delai.getTime();
+
+ if (this.LastClick === 0) {
+ this.LastClick = curClick - 51;
+ }
+
+ var diff = (curClick - this.LastClick);
+
+ if (target.href) {
+ if (diff > 50) {
+ this.LastClick = curClick;
+ var uniq = Ext.id();
+ this.openInTab(uniq, target.href, target.href);
+ }
+ }
+
+ }, // clickInterceptor
+
+ /********
+ *
+ * ContextMenu
+ *
+ ********/
+
+ createContextMenuTreeFeed: function() {
+
+ var node = this.PanelFeedTree.getNodeById(this.curNodeId);
+
+ var menu = new Ext.menu.Menu({
+ items: [{
+ text: QoKregator.TreeFeedMarkAsRead,
+ iconCls: 'qo-kregator-icon-mark-all-as-read',
+ scope: this,
+ handler: function(el, ev){
+ this.markAllAsRead(node, this);
+ }
+ }, new Ext.menu.Separator(), {
+ scope: this,
+ text: QoKregator.TreeFeedLoadFeed,
+ iconCls:'qo-kregator-refresh-btn',
+ handler: function(n, ev){
+ this.updateFeed(node.attributes.text, node.attributes.id, node.id, 'off', -1);
+ }
+ }, new Ext.menu.Separator(), {
+ scope: this,
+ text: QoKregator.TreeFeedOpenSite,
+ iconCls: 'qo-kregator-open-site-btn',
+ handler: function(n, ev){
+ this.openInTab(node.attributes.id, node.attributes.text, node.attributes.url);
+ }
+ }, new Ext.menu.Separator(), {
+ scope: this,
+ text: QoKregator.TreeFeedMod,
+ iconCls: 'qo-kregator-icon-mod-feed',
+ handler: function(n, ev){
+ this.showModFeed(node);
+ }
+ }, {
+ scope: this,
+ text: QoKregator.TreeFeedDel,
+ iconCls: 'qo-kregator-icon-del-feed',
+ handler: function(n, ev){
+ this.showDelItemArbre(node);
+ }
+ }]
+ });
+ return menu;
+ }, //createContextMenuTreeFeed
+
+ createContextMenuTreeFolder: function() {
+
+ var node = this.PanelFeedTree.getNodeById(this.curNodeId);
+
+ var menu = new Ext.menu.Menu({
+ items: [{
+ scope: this,
+ text: QoKregator.TreeAddNewFeed,
+ iconCls:'qo-kregator-icon-add-feed',
+ handler: function(n, ev){
+ this.showAddFeed(node.id);
+ }
+ }, {
+ scope: this,
+ text: QoKregator.TreeAddNewFolder,
+ iconCls: 'qo-kregator-icon-add-folder',
+ handler: function(n, ev){
+ this.showAddFolder(node.id);
+ }
+ }, '-', {
+ scope: this,
+ text: QoKregator.TreeFolderMod,
+ iconCls: 'qo-kregator-icon-mod-folder',
+ handler: function(n, ev){
+ // Start Edit
+ this.PanelFeedTreeEditor.editNode = node;
+ this.PanelFeedTreeEditor.startEdit(node.ui.getAnchor(), node.text);
+ }
+ }, {
+ scope: this,
+ text: QoKregator.TreeFolderDel,
+ iconCls: 'qo-kregator-icon-del-folder',
+ handler: function(n, ev){
+ this.showDelItemArbre(node);
+ }
+ }]
+ });
+ return menu;
+
+ }, //createContextMenuTreeFolder
+
+ onContextMenuFeed: function(node, ev) {
+
+ ev.preventDefault();
+ ev.stopEvent();
+
+ var actuNode = this.PanelFeedTree.getSelectionModel().getSelectedNode();
+
+ if (node != actuNode) {
+ node.select();
+ this.onClickFeed(node, ev);
+ }
+
+ this.curNodeId = node.id;
+ var nodeType = node.attributes.type;
+
+ if (this.curNodeId !== 0) {
+ if (nodeType == 'file') {
+ menu = this.createContextMenuTreeFeed();
+ menu.showAt(ev.getXY());
+ }
+
+ if (nodeType == 'folder') {
+ menu = this.createContextMenuTreeFolder();
+ menu.showAt(ev.getXY());
+ }
+ }
+ }, // onContextMenuFeed
+
+ createContextItemFeed : function() {
+
+ var rowSelected = this.PanelGridItem.getSelections(); // All row selected
+ var RowToDel = ''; // construct the string containing all row to delete
+
+ var isImportant = false; //Is a row is important into all rows selected ?
+ var isUnseen = false; //Is a row is unseen into all rows selected ?
+
+ var menu = new Ext.menu.Menu();
+
+ for (var j = 0; j < rowSelected.length; j++) {
+
+ RowToDel += rowSelected[j].id + ',';
+ if (rowSelected[j].data.i == 'y') {
+ isImportant = true;
+ }
+ if (rowSelected[j].data.s == 'n') {
+ isUnseen = true;
+ }
+
+ }
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemOpenInTab,
+ iconCls: 'qo-kregator-open-inTab-btn',
+ handler: function(){
+ for (var i = 0; i < rowSelected.length; i++) {
+
+ var _node = this.dsItems.getById(rowSelected[i].id);
+ var _link = _node.data.u;
+ var _title = _node.data.t;
+
+ this.openInTab('items-' + rowSelected[i].id, _title, _link);
+ }
+ }
+ });
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemOpenInWin,
+ iconCls: 'qo-kregator-open-site-btn',
+ handler: function(){
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.openInWindow(rowSelected[i].id);
+ }
+ }
+ });
+
+ menu.addSeparator();
+
+ var varMenuImportant;
+
+ if (isImportant) {
+
+ varMenuImportant = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemRemoveMarkImportant,
+ iconCls: 'qo-kregator-icon-unmark-as-important',
+ handler: function(){
+
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsImportant('n', rowSelected[i].id);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.removeClass("qo-kregator-feed-important");
+ }
+
+ }
+ });
+ }
+ else {
+
+ varMenuImportant = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAsImportant,
+ iconCls: 'qo-kregator-icon-mark-as-important',
+ handler: function(){
+
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsImportant('y', rowSelected[i].id);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.addClass("qo-kregator-feed-important");
+
+ }
+ }
+ });
+ }
+
+ var varMenuUnseen;
+
+ if( isUnseen ) {
+
+ varMenuUnseen = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAsRead,
+ iconCls: 'qo-kregator-icon-mark-as-read',
+ handler: function(){
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsSeenUnseen('y', rowSelected[i].id, this);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.addClass("qo-kregator-feed-read");
+ p.removeClass("qo-kregator-feed-unread");
+
+ }
+ }
+ });
+
+ } else {
+
+ varMenuUnseen = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAsUnRead,
+ iconCls: 'qo-kregator-icon-mark-as-unread',
+ handler: function(){
+
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsSeenUnseen('n', rowSelected[i].id, this);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.removeClass("qo-kregator-feed-read");
+ p.addClass("qo-kregator-feed-unread");
+ }
+ }
+ });
+
+ }
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAs,
+ menu: {
+ items: [varMenuImportant, new Ext.menu.Separator(),varMenuUnseen]
+ }
+ });
+
+ menu.addSeparator();
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemDel,
+ iconCls: 'qo-kregator-icon-del-feed',
+ handler: function(grid, rowIndex, ev){
+
+ var boxTitle='', boxMessage='';
+
+ // How many rows to delete ?
+ if( rowSelected.length == 1 ) {
+ boxTitle = QoKregator.BoxConfirmDelItemTitle;
+ boxMessage = QoKregator.BoxConfirmDelItemMessage;
+ } else {
+ boxTitle = QoKregator.BoxConfirmDelItemsTitle;
+ boxMessage = QoKregator.BoxConfirmDelItemsMessage;
+ }
+
+
+ // Show confirm box
+ Ext.Msg.show({
+ scope: this,
+ title:boxTitle,
+ msg: boxMessage,
+ buttons: Ext.Msg.YESNOCANCEL,
+ fn: function(btn) {
+
+ if( btn == 'yes' ) {
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutItemDel);
+
+ // Update DB
+ var delItem = new Ext.data.Connection();
+ delItem.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_item: RowToDel,
+ what: 'del_items'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutItemDelOk);
+
+ // Delete ligne(s)
+ for (var i = 0; i < rowSelected.length; i++) {
+
+ var _nodeID = this.dsItems.getById(rowSelected[i].id).data.id_f;
+ var unSeen = o.message.Node[_nodeID].unseen;
+ var total = o.message.Node[_nodeID].total;
+ this.dsItems.remove(this.dsItems.getById(rowSelected[i].id));
+ this.updateFeedInfo(_nodeID, unSeen, total);
+
+ }
+
+ // Focus & Display next items
+ if( this.dsItems.data.items.length > 0 ) {
+ this.loadItem(0);
+ this.PanelGridItem.getSelectionModel().selectRow(0);
+ } else {
+ // Clear Preview Panel
+ this.PanelPreview.setTitle(QoKregator.PreviewTitle);
+ this.PanelPreview.body.dom.innerHTML = '';
+ }
+
+ },
+ failure: function(form, action){
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutItemDelNok);
+ }
+ });
+ }
+ },
+ icon: Ext.MessageBox.QUESTION
+ });
+ }
+ });
+ return menu;
+ }, // CreateContextItemFeed
+
+ onContextItemFeed: function(grid, rowIndex, ev){
+
+ ev.stopEvent();
+
+ // Get all rows selected, if any
+ var rowSelected = this.PanelGridItem.getSelections();
+
+ // Get the single row selected
+ var contextRowID = this.dsItems.getAt(rowIndex).id;
+
+ // If right-click without a rows selected, we auto-select the rows over the right-click
+ var asSelect = false;
+ for (var i = 0; i < rowSelected.length; i++) {
+ if (contextRowID == rowSelected[i].id) {
+ asSelect = true;
+ }
+ }
+
+ if (!asSelect) {
+ var v = this.PanelGridItem.getSelectionModel();
+ v.selectRow(rowIndex);
+ rowSelected = this.PanelGridItem.getSelections();
+ }
+
+ var menu;
+ menu = this.createContextItemFeed();
+ menu.showAt(ev.getXY());
+
+ }, // onContextItemFeed
+
+ markAsImportant: function(typeMark, rowId){
+
+ var importantStatut = this.dsItems.getById(rowId).data.i;
+
+ var _typeMark = typeMark;
+ var _rowId = rowId;
+
+ if ((importantStatut == 'y' && _typeMark == 'n') || (importantStatut == 'n' && _typeMark == 'y')) {
+
+ var saveImportant = new Ext.data.Connection();
+ saveImportant.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_item: _rowId,
+ typeMark: _typeMark,
+ what: 'save_important'
+ },
+ success: function(){
+
+ if (_typeMark == 'y') {
+ this.dsItems.getById(_rowId).data.i = 'y';
+ } else if (_typeMark == 'n') {
+ this.dsItems.getById(_rowId).data.i = 'n';
+ }
+
+ // ReBuilt the contextMenu-btn
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu(this.createContextItemFeed());
+
+ }
+ });
+ }
+ }, //markAsImportant
+
+ markAsSeenUnseen: function(typeMark, rowId, scope){
+
+ this.scope = scope;
+
+ var seenStatut = this.dsItems.getById(rowId).data.s;
+ var _typeMark = typeMark;
+ var _rowId = rowId;
+
+ // Modify if necessary
+ if ((seenStatut == 'y' && _typeMark == 'n') || (seenStatut == 'n' && _typeMark == 'y')) {
+
+ var saveSeenUnseen = new Ext.data.Connection();
+ saveSeenUnseen.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_item: _rowId,
+ typeMark: _typeMark,
+ what: 'save_seenUnseen'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ var node = this.PanelFeedTree.getNodeById(o.nodeID);
+ node.attributes.unseen = o.unSeen;
+ node.attributes.total = o.total;
+
+ // Update client data
+ if (_typeMark == 'y') {
+ this.dsItems.getById(_rowId).data.s = 'y';
+ } else if (_typeMark == 'n') {
+ this.dsItems.getById(_rowId).data.s = 'n';
+ }
+
+ this.updateFeedInfo(node.id, o.unSeen, o.total);
+
+ // ReBuilt the contextMenu-btn
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu(this.createContextItemFeed());
+
+ }
+ }
+ });
+ }
+ }, //markAsSeenUnseen
+
+ markAllAsRead: function(node, scope) {
+
+ var nb = scope.dsItems.data.length;
+
+ for (var i = 0; i < nb; i++) {
+ var r = Ext.get(scope.PanelGridItem.getView().getRow(i));
+ r.replaceClass("qo-kregator-feed-unread", "qo-kregator-feed-read");
+ }
+ scope.markAsSeenDB(node.id, scope);
+ node.ui.removeClass("qo-kregator-feed-Unseen");
+
+ },
+
+ markAsSeenDB: function(_nodeID, scope){
+
+ this.scope = scope;
+
+ var saveSeenUnseen = new Ext.data.Connection();
+ saveSeenUnseen.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_feed: _nodeID,
+ what: 'save_seenDB'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ var node = this.PanelFeedTree.getNodeById(o.nodeID);
+ node.attributes.unseen = o.unSeen;
+ node.attributes.total = o.total;
+ this.updateFeedInfo(node.id, o.unSeen, o.total);
+
+ }
+ }
+ });
+
+ }, //markAsSeenDB
+
+ openInWindow: function(rowId){
+ var node = this.dsItems.getById(rowId);
+ var link = node.data.u;
+ window.open(link, 'win' + rowId);
+ }, //openInWindow
+
+ openInTab: function(feedID, title, link){
+
+ var TabExist = this.PanelCenter.findById('qo-kregator-tab-' + feedID);
+
+ if (TabExist) {
+ this.PanelCenter.activate('qo-kregator-tab-' + feedID);
+ }
+ else {
+
+ this.PanelCenter.add({
+ id: 'qo-kregator-tab-' + feedID,
+ linkTab: link,
+ closable: true,
+ title: Ext.util.Format.ellipsis(title, 20),
+ layout: 'fit',
+ border: true,
+ items: [{
+ xtype : 'iframepanel',
+ loadMask : true,
+ defaultSrc : link
+ }]
+
+ });
+
+ this.PanelCenter.activate('qo-kregator-tab-' + feedID);
+
+ }
+
+ }, //openInTab
+
+ onClickFeed: function(node, ev){
+
+ this.curNodeId = node.id;
+
+ var nodeType = node.attributes.type;
+
+ this.PanelCenter.activate('qo-kregator-main');
+
+ this.gridClearFilter();
+
+ // Delete data
+ this.dsItems.removeAll();
+
+ if (nodeType == 'folder') {
+
+ this.PanelPreview.body.dom.innerHTML = '';
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutLoadFolder + " " + node.attributes.text);
+
+ var ColIndex = this.PanelGridItem.getColumnModel().getIndexById('feed');
+ this.PanelGridItem.getColumnModel().setHidden(ColIndex, false);
+
+ // Set tab title
+ Ext.getCmp('qo-kregator-main').setTitle(Ext.util.Format.ellipsis(node.attributes.text, 20));
+ this.linkDefaultTab = '';
+ this.curFeedId = '*';
+
+ } else {
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutLoadFeed + " " + node.attributes.text);
+
+ var _ColIndex = this.PanelGridItem.getColumnModel().getIndexById('feed');
+ this.PanelGridItem.getColumnModel().setHidden(_ColIndex, true);
+
+ Ext.getCmp('qo-kregator-main').setTitle(Ext.util.Format.ellipsis(node.attributes.text, 20));
+ this.linkDefaultTab = node.attributes.url;
+ this.curFeedId = node.id;
+
+ var image;
+
+ if ( node.attributes.image ) {
+ image = "<img src=\"" + node.attributes.image + "\" alt=\"\" />";
+ } else {
+ image = '';
+ }
+
+ var content = '<div class="qo-kregator-feed-info">' +
+ '<div class="qo-kregator-item-date"></div>' +
+ '<div class="qo-kregator-item-title">' +
+ node.attributes.desc +
+ '</div>' +
+ '<div class="qo-kregator-item-author"><a href="' +
+ node.attributes.url +
+ '" Ext:qtip="' +
+ QoKregator.previewLoadInNewPage +
+ '" target="_blank">' +
+ node.attributes.url +
+ '</a></div>' +
+ '</div>' +
+ '<div class="qo-kregator-feed-content">' +
+ '<div class="qo-kregator-feed-image">' +
+ image +
+ '</div>' +
+ '</div>';
+
+ this.PanelPreview.body.dom.innerHTML = content;
+
+ }
+
+ this.PanelPreview.setTitle(node.attributes.text);
+
+ this.dsItems.baseParams = {
+ 'id_feed': this.curFeedId,
+ 'id_node': this.curNodeId
+ };
+
+ this.dsItems.load({
+ params: {
+ start: 0,
+ limit: 25
+ }
+ });
+
+ if (nodeType == 'folder') {
+
+ //Handle ContextMenu
+ if( Ext.getCmp('qo-kregator-contextmenu-btn') ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFolder());
+ }
+
+ } else {
+
+ //Handle ContextMenu
+ if( Ext.getCmp('qo-kregator-contextmenu-btn') ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFeed());
+ }
+
+ }
+
+ }, //onClickFeed
+
+ showDelItemArbre: function(node){
+
+ var titre, message, typeObj;
+
+ if (node.attributes.type == 'file') {
+ titre = QoKregator.BoxConfirmDelFeedTitle;
+ message = QoKregator.BoxConfirmDelFeedMessage + node.attributes.text + ' ?';
+ }
+
+ if (node.attributes.type == 'folder') {
+ titre = QoKregator.BoxConfirmDelFolderTitle;
+ message = String.format(QoKregator.BoxConfirmDelFolderMessage, node.attributes.text);
+ }
+
+ Ext.Msg.show({
+ scope: this,
+ icon: Ext.MessageBox.QUESTION,
+ title: titre,
+ msg: message,
+ buttons: Ext.MessageBox.YESNO,
+ fn: function(btn){
+ if (btn == 'yes') {
+ if (node.attributes.type == 'file') {
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutDelFeed + node.attributes.text + '...');
+ }
+ else {
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutDelFolder + node.attributes.text + '...');
+ }
+
+ // Update
+ var delNode = new Ext.data.Connection();
+ delNode.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_node: node.id,
+ what: 'del_nodes'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutDone);
+
+ //Del node
+ var curNode = this.PanelFeedTree.selModel.selNode;
+
+ //Animation
+ Ext.fly(curNode.ui.elNode).switchOff({
+ easing: 'easeIn',
+ duration: .3,
+ remove: false,
+ useDisplay: false,
+ scope: this,
+ callback: function() { curNode.parentNode.removeChild(curNode) ; }
+ });
+
+ // Return to initial state
+ Ext.getCmp('qo-kregator-main').setTitle(QoKregator.FeedGridTabTitle);
+ this.linkDefaultTab = '';
+ this.dsItems.removeAll();
+
+ this.PanelPreview.setTitle(QoKregator.PreviewTitle);
+ this.PanelPreview.body.dom.innerHTML = '';
+
+ }
+ else {
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutDelItemNok);
+ }
+
+ }
+ });
+
+ }
+ }
+ });
+
+ }, // showDelItemArbre
+
+ showAddFeed: function(_nodeID){
+
+ function validForm(scope) {
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutAddNewFeed);
+
+ var waitAddFeed = Ext.MessageBox.show({
+ msg: QoKregator.StatutAddNewFeedWait,
+ progressText: QoKregator.StatutAddNewFeedWaitInProgress,
+ width: 300,
+ wait: true,
+ waitConfig: {
+ interval: 200
+ }
+ });
+
+ FormAddFeed.form.submit({
+ scope: scope,
+ url: scope.app.connection,
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodeID: _nodeID,
+ what: 'add_feed'
+ },
+ success: function(form, action){
+
+ // Add this new node to tree
+ var o = action.result;
+
+ var nodeToAppend = new Ext.tree.TreeNode({
+ id:o.id,
+ text:o.text,
+ url: o.url,
+ url_feed: o.url_feed,
+ type: o.type,
+ desc: o.desc,
+ image: o.image,
+ view: o.view,
+ nodeID: o.nodeID,
+ unseen:o.unseen,
+ total:o.total,
+ uiProvider:Ext.tree.KregaColumnNodeUI,
+ leaf:true,
+ icon:o.icon,
+ iconCls:'',
+ refreshCycle:'on'
+ });
+
+ if( o.nodeID === "0" ) { scope.PanelFeedTree.getRootNode().appendChild(nodeToAppend); }
+ else { scope.PanelFeedTree.getNodeById(o.nodeID).appendChild(nodeToAppend); }
+
+ scope.PanelFeedTree.expandAll();
+
+ var newNode = scope.PanelFeedTree.getNodeById(o.id);
+ newNode.select();
+ scope.onClickFeed(newNode);
+
+ scope.updateFeedInfo(o.id, o.unseen, o.total);
+
+ FormAddFeed.form.reset();
+ waitAddFeed.hide();
+ winAddFeed.close();
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFeedOk);
+ },
+
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-error', QoKregator.StatutAddNewFeedNok + action.result.message);
+
+ waitAddFeed.hide();
+ Ext.get('newFeed').focus();
+
+ }
+ });
+
+ } //addFeed
+
+ var FormAddFeed = new Ext.FormPanel({
+ labelWidth: 40,
+ frame: true,
+ bodyStyle: 'padding:5px',
+ width: 350,
+ items: [{
+ xtype:'textfield',
+ fieldLabel: QoKregator.BoxAddFeedUrl,
+ name: 'newFeed',
+ id: 'newFeed',
+ width: 300,
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(this);
+ }
+ }
+ }
+ },{
+ xtype: 'checkbox',
+ hideLabel: true,
+ boxLabel: QoKregator.BoxModFeedView,
+ name: 'view',
+ checked: false
+ }]
+ });
+
+ var winAddFeed = new Ext.Window({
+ animateEl: 'qo-kregator-add-feed-btn',
+ title: QoKregator.BoxAddFeedTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-add-feed',
+ width: 430,
+ height: 160,
+ closeAction: 'close',
+ bodyStyle: 'padding:5px',
+ plain: true,
+ items: FormAddFeed,
+
+ buttons: [{
+ text: QoKregator.BoxAddFeedSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(this);
+ }
+ }, {
+ text: QoKregator.BoxAddFeedCancelBtn,
+ handler: function(){
+ winAddFeed.close();
+ }
+ }]
+ });
+
+ winAddFeed.show(this);
+
+ var tmp = new Ext.util.DelayedTask(function() { Ext.getCmp('newFeed').focus(); }, this);
+ tmp.delay(200);
+
+ }, //showAddFeed
+
+ showConf: function() {
+
+ function in_array(array, it) {
+
+ for( var i=0; i < array.length; i++ ) {
+
+ if( array[i] == it ) { return 1; }
+
+ }
+ return 0;
+
+ } // array_diff
+
+ var _tbFeedCurrent=[], _tbFeedDisponible=[];
+
+ //Actual tbFeed
+ Ext.each(this.tbFeedBtnCurrent, function(item) {
+
+ _tbFeedCurrent.push([item, '<div class="'+this.tbFeedBtnAvailable[item].iconCls+'-conf">'+((typeof this.tbFeedBtnAvailable[item].tooltip == 'object' ) ? this.tbFeedBtnAvailable[item].tooltip.title : this.tbFeedBtnAvailable[item].tooltip) +'</div>']);
+
+ }, this);
+
+ //Disponible tbFeed
+ Ext.each(this.tbFeedBtnAvailable, function(item) {
+
+ if( in_array(this.tbFeedBtnCurrent,item) === 0 ) {
+
+ _tbFeedDisponible.push([item, '<div class="'+this.tbFeedBtnAvailable[item].iconCls+'-conf">'+((typeof this.tbFeedBtnAvailable[item].tooltip == 'object' ) ? this.tbFeedBtnAvailable[item].tooltip.title : this.tbFeedBtnAvailable[item].tooltip) +'</div>']);
+
+ }
+
+ }, this);
+
+ var FormConf = new Ext.FormPanel({
+ labelWidth: 75,
+ border:false,
+ autoWidth: true,
+ items: [{
+ xtype:'tabpanel',
+ deferredRender:false,
+ activeTab: 0,
+ defaults:{autoHeight:true, bodyStyle:'padding:10px'},
+ items:[{
+ title:QoKregator.WinConfTab0,
+ layout:'form',
+ items: [{
+ layout:'column',
+ border: false,
+ items:[{
+ columnWidth:0.5,
+ layout: 'form',
+ border: false,
+ items: [{
+ //1
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle0,
+ height: 60,
+ labelWidth: 100,
+ items: [
+ new Ext.ux.form.Spinner({
+ strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue: '1', maxValue: '100'}),
+ fieldLabel: QoKregator.WinConfFieldSetLabel0,
+ name: 'refresh_feed',
+ editable: false,
+ width: 50,
+ value: this.ConfRefreshFeed
+ })
+ ]
+ },{
+ //2
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle1,
+ height: 60,
+ checkboxToggle: true,
+ checkboxName: 'old_items',
+ collapsed: !this.ConfOldItems,
+ labelWidth: 100,
+ items: [
+ new Ext.ux.form.Spinner({
+ strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue: '1', maxValue: '100'}),
+ fieldLabel: QoKregator.WinConfFieldSetLabel1,
+ name: 'old_items_day',
+ editable: false,
+ width: 50,
+ value: this.ConfOldItemsDay
+ })
+ ]
+ },{
+ xtype:'checkbox',
+ checked: (this.ConfshowStatusBar == 'on') ? true : false,
+ hideLabel: true,
+ boxLabel: QoKregator.WinConfFieldSetTitle5,
+ name: 'showStatusBar'
+ }]
+ },{
+ columnWidth:0.5,
+ layout: 'form',
+ border: false,
+ items: [{
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle3,
+ height: 60,
+ labelWidth: 100,
+ layout:'absolute',
+ items: [{
+ xtype: 'slider',
+ width: 150,
+ value: this.ConfContentFontSize,
+ increment: 1,
+ minValue: 8,
+ maxValue: 20,
+ listeners: {
+ change: function(s, NewValue) {
+ Ext.getCmp('showSlider').setValue(NewValue);
+ }
+ }
+ },{
+ xtype: 'textfield',
+ readOnly: true,
+ id:'showSlider',
+ name: 'ContentFontSize',
+ width: 24,
+ value: this.ConfContentFontSize,
+ x: 154,
+ y: 0
+ }]
+ },{
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle4,
+ height: 60,
+ labelWidth: 100,
+ items: [{
+ xtype: 'combo',
+ hideLabel: true,
+ store: [['FullScreen', QoKregator.WinConfFieldSetLabel41],['Window', QoKregator.WinConfFieldSetLabel42], ['Minimized', QoKregator.WinConfFieldSetLabel43]],
+ forceSelection: true,
+ triggerAction: 'all',
+ hiddenName: 'openMode',
+ mode: 'local',
+ value: this.ConfOpenMode,
+ editable:false,
+ width: 100
+
+ }]
+ },{
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: 'Date/Time format',
+ height: 90,
+ labelWidth: 70,
+ items: [{
+ xtype: 'combo',
+ fieldLabel: 'Date ',
+ store: [
+ ['d/m/y', '31/12/99'],
+ ['d/m/Y', '31/12/1999'],
+ ['y-m-d', '99-12-31'],
+ ['Y-m-d', '1999-12-31']
+ ],
+ forceSelection: true,
+ triggerAction: 'all',
+ hiddenName: 'dateFormat',
+ mode: 'local',
+ value: this.ConfDateFormat,
+ editable:false,
+ width: 120
+
+ },{
+ xtype: 'combo',
+ fieldLabel: 'Date/Time ',
+ store: [
+ ['d/m/y, H:i', '31/12/99, 14:15'],
+ ['d/m/Y, H:i', '31/12/1999, 14:15'],
+ ['y-m-d, H:i', '99-12-31, 14:15'],
+ ['Y-m-d, H:i', '1999-12-31, 14:15']
+ ],
+ forceSelection: true,
+ triggerAction: 'all',
+ hiddenName: 'dateTimeFormat',
+ mode: 'local',
+ value: this.ConfDateTimeFormat,
+ editable:false,
+ width: 120
+
+ }]
+ }]
+ }]
+ }]
+ },{
+ title : QoKregator.WinConfTab1,
+ layout:'form',
+ defaults: {width: 420},
+ items: [{
+ xtype:"itemselector",
+ id: "qo-kregator-conf-tb-feed",
+ name:"tbFeedBtn",
+ hideLabel: true,
+ dataFields:["code", "desc"],
+ fromData: _tbFeedDisponible,
+ toData:_tbFeedCurrent,
+ msWidth:200,
+ msHeight:110,
+ valueField:"code",
+ displayField:"desc",
+ imagePath:"system/modules/qo-kregator/ux/MultiselectItemSelector/",
+ toLegend: QoKregator.WinConfTab1Selected,
+ fromLegend: QoKregator.WinConfTab1Available
+ }]
+ }]
+ }],
+ buttons: [{
+ text: QoKregator.WinConfSaveBtn,
+ scope: this,
+ handler: function(){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutConfWait);
+
+ FormConf.form.submit({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ what: 'mod_user_conf'
+ },
+ success: function(form, action){
+
+ var o = action.result;
+
+ this.ConfRefreshFeed = o.refresh_feed;
+ this.ConfOldItems = o.old_items;
+ this.ConfOldItemsDay = o.old_items_day;
+ this.ConfshowStatusBar = o.showStatusBar;
+ this.tbFeedBtnCurrent = o.tbFeedBtn;
+ this.ConfContentFontSize = o.ContentFontSize;
+ this.ConfOpenMode = o.openMode;
+
+ this.ConfDateTimeFormat = o.dateTimeFormat;
+ this.ConfDateFormat = o.dateFormat;
+
+ // Update ContentFontSize for the current preview
+ this.setContentFontSize();
+
+ // Update conf for the statusBar
+ this.showHideStatusBar();
+
+ // Update tbFeedBtn
+ this.buildTbFeed();
+
+ // Redraw the grid to handle dateFormat Change
+ this.PanelGridItem.getColumnModel().getColumnById('date').renderer = this.renderDate.createDelegate(this, [this.ConfDateTimeFormat], 1);
+ this.PanelGridItem.getView().refresh();
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutConfOk);
+
+ winConf.close();
+ },
+ failure: function(form, action){
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutConfNok);
+ }
+ });
+
+ }
+ },{
+ text: QoKregator.WinConfCancelBtn,
+ handler: function(){
+ winConf.close();
+ }
+ }]
+
+ });
+
+ var winConf = new Ext.Window({
+ scope: this,
+ title: QoKregator.WinConfTitle,
+ layout: 'fit',
+ modal: true,
+ closeAction: 'close',
+ iconCls: 'qo-kregator-icon-conf',
+ width: 500,
+ height: 350,
+ plain: true,
+ items: FormConf
+ });
+
+ winConf.show();
+ },
+
+ showModFeed: function(node){
+
+ function validForm(node, scope) {
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutModFeed);
+
+ FormModFeed.form.submit({
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_feed: node.attributes.id,
+ what: 'mod_feed'
+ },
+ scope: scope,
+ url: scope.app.connection,
+ success: function(form, action){
+
+ var o = action.result;
+
+ // Update tree
+ node.setText(o.nom);
+ node.attributes.view = o.view;
+ node.attributes.refreshCycle = o.refreshCycle;
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutModFeedOk);
+ scope.winModFeed.hide();
+ },
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-error', QoKregator.StatutModFeedNok);
+ }
+ });
+
+ } // validForm
+
+ var viewValue = false;
+ if (node.attributes.view == 'site') {
+ viewValue = true;
+ }
+
+ var refreshCycleValue = false;
+ if (node.attributes.refreshCycle == 'off') {
+ refreshCycleValue = true;
+ }
+
+ var FormModFeed = new Ext.FormPanel({
+ labelWidth: 40,
+ frame: true,
+ bodyStyle: 'padding:5px',
+ items: [{
+ xtype: 'fieldset',
+ title: node.text,
+ autoHeight: true,
+ defaultType: 'textfield',
+ items: [{
+ fieldLabel: QoKregator.BoxModFeedName,
+ name: 'modFeed',
+ value: node.text,
+ width: 300,
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(node, this);
+ }
+ }
+ }
+ }, {
+ fieldLabel: 'Url ',
+ name: 'url',
+ readOnly: true,
+ value: node.attributes.url_feed,
+ width: 300,
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(node, this);
+ }
+ }
+ }
+ }]
+ }, {
+ xtype: 'fieldset',
+ title: QoKregator.BoxModFeedOption,
+ autoHeight: true,
+ defaultType: 'checkbox',
+ items: [{
+ hideLabel: true,
+ boxLabel: QoKregator.BoxModFeedView,
+ name: 'view',
+ checked: viewValue
+ },{
+ hideLabel: true,
+ boxLabel: 'Exclude from refresh cycle',
+ name: 'refreshCycle',
+ checked: refreshCycleValue
+ }]
+ }]
+ });
+
+ this.winModFeed = new Ext.Window({
+ scope: this,
+ title: QoKregator.BoxModFeedTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-mod-feed',
+ width: 450,
+ height: 280,
+ closeAction: 'hide',
+ bodyStyle: 'padding:5px',
+ plain: true,
+ items: FormModFeed,
+
+ buttons: [{
+ text: QoKregator.BoxModFeedSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(node, this);
+ }
+ }, {
+ scope:this,
+ text: QoKregator.BoxModFeedCancelBtn,
+ handler: function(){
+ this.winModFeed.hide();
+ }
+ }]
+ });
+ this.winModFeed.show(this);
+ }, //showModFeed
+
+ showAddFolder: function(_nodeID){
+
+ function validForm(scope) {
+
+ // Disable btn
+ Ext.getCmp('qo-kregator-btnOK-id-add-folder').disable();
+ Ext.getCmp('qo-kregator-btnCANCEL-id-add-folder').disable();
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutAddNewFolder);
+
+ FormAddFolder.form.submit({
+ scope: scope,
+ url: scope.app.connection,
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodeID: _nodeID,
+ what: 'add_folder'
+ },
+ success: function(form, action){
+
+ var o = action.result, node;
+
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFolderOk);
+
+ // Add this new node to tree
+
+ if( o.nodeID !== "0" ) {
+
+ scope.PanelFeedTree.getNodeById(o.nodeID).appendChild(new Ext.tree.TreeNode({
+ text: o.name,
+ id: o.id,
+ leaf: false,
+ iconCls: 'qo-kregator-feed-folder',
+ type: 'folder',
+ children:[],
+ nodeID: o.nodeID
+ }));
+
+ } else {
+
+ scope.PanelFeedTree.getRootNode().appendChild(new Ext.tree.TreeNode({
+ text: o.name,
+ id: o.id,
+ leaf: false,
+ iconCls: 'qo-kregator-feed-folder',
+ type: 'folder',
+ children:[],
+ nodeID: o.nodeID
+ }));
+
+ }
+
+ var newNode = scope.PanelFeedTree.getNodeById(o.id);
+ newNode.select();
+
+ FormAddFolder.form.reset();
+ Ext.getCmp('qo-kregator-btnOK-id-add-folder').enable();
+ Ext.getCmp('qo-kregator-btnCANCEL-id-add-folder').enable();
+ winAddFolder.close();
+ },
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFolderNok);
+ }
+ });
+
+ } //validForm
+
+ var FormAddFolder = new Ext.FormPanel({
+ labelWidth: 45,
+ id: 'form-add-folder',
+ frame: true,
+ bodyStyle: 'padding:5px 5px 0',
+ width: 350,
+ defaults: {width: 280},
+ items: [{
+ xtype: 'textfield',
+ fieldLabel: QoKregator.BoxAddFolderName,
+ name: 'newFolder',
+ id: 'newFolder',
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(this);
+ }
+ }
+ }
+ }]
+ });
+
+ var winAddFolder = new Ext.Window({
+ scope: this,
+ animateEl: 'qo-kregator-add-feed-btn',
+ title: QoKregator.BoxAddFolderTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-add-folder',
+ width: 400,
+ height: 130,
+ closeAction: 'close',
+ plain: true,
+ items: FormAddFolder,
+ buttons: [{
+ id:'qo-kregator-btnOK-id-add-folder',
+ text: QoKregator.BoxAddFolderSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(this);
+ }
+ }, {
+ scope:this,
+ text: QoKregator.BoxAddFolderCancelBtn,
+ id:'qo-kregator-btnCANCEL-id-add-folder',
+ handler: function(){
+ winAddFolder.close();
+ }
+ }]
+ });
+
+ winAddFolder.show(this);
+
+ var tmp = new Ext.util.DelayedTask(function() { Ext.getCmp('newFolder').focus(); }, this);
+ tmp.delay(200);
+
+ }, //showAddFolder
+
+ showImport: function(_nodeID){
+
+ function validForm(scope) {
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutImportWait);
+
+ FormImport.form.submit({
+ scope: scope,
+ success: function(form, action){
+
+ var o = action.result;
+
+ if (o.success) {
+
+ // Add folder
+ scope.PanelFeedTree.getRootNode().appendChild(new Ext.tree.TreeNode({
+ text: o.folderText,
+ id: o.folderId,
+ leaf: false,
+ iconCls: 'qo-kregator-feed-folder',
+ type: 'folder',
+ children:[],
+ nodeID: 0
+ }));
+
+ scope.PanelFeedTree.getNodeById(o.folderId).expand();
+
+ var new_feed = [];
+ var reg = new RegExp("[|]+", "g");
+
+ var tmp_feed = o.new_feed;
+ new_feed = tmp_feed.split(reg);
+
+ // On ajoute les flux
+ for (var i = 0; i < new_feed.length; i++) {
+
+ if ( !new_feed[i]) { continue; }
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutAddNewFeed);
+
+ var saveFeed = new Ext.data.Connection();
+ saveFeed.request({
+ scope: scope,
+ url: scope.app.connection,
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ newFeed: new_feed[i],
+ nodeID: o.folderId,
+ what: 'add_feed'
+ },
+
+ success: function(response, options){
+
+ var o2 = Ext.util.JSON.decode(response.responseText);
+
+ if (o2.success) {
+
+ // Add the new node
+ scope.PanelFeedTree.getNodeById(o.folderId).appendChild(new Ext.tree.TreeNode({
+ id:o2.id,
+ text:o2.text,
+ url: o2.url,
+ url_feed: o2.url_feed,
+ type: o2.type,
+ desc: o2.desc,
+ image: o2.image,
+ view: o2.view,
+ nodeID: o2.nodeID,
+ unseen:o2.unseen,
+ total:o2.total,
+ uiProvider:Ext.tree.KregaColumnNodeUI,
+ leaf:true,
+ icon:o2.icon,
+ iconCls:'',
+ refreshCycle:'on'
+ }));
+
+ scope.updateFeedInfo(o2.id, o2.unseen, o2.total);
+
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFeedOk);
+
+ } else {
+ scope.setStatusBar('qo-kregator-error', QoKregator.StatutAddNewFeedNok + o2.message);
+ }
+ }
+ });
+
+ }
+
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutImportOk);
+
+ } else {
+
+ Ext.MessageBox.show({
+ title: 'erreur',
+ msg: 'erreur' + o.msg,
+ buttons: Ext.MessageBox.OK,
+ animEl: 'mb9',
+ icon: Ext.MessageBox.ERROR
+ });
+
+ }
+
+ FormImport.form.reset();
+ winImport.close();
+ },
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutImportNok + action.result.msg);
+ }
+ });
+
+ } // validForm
+
+
+ var FormImport = new Ext.FormPanel({
+ labelWidth: 45,
+ labelAlign: 'top',
+ id: 'form-import',
+ fileUpload: true,
+ url: this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/qo-kregator.php&what=import',
+ frame: true,
+ bodyStyle: 'padding: 10px 10px 0 10px;',
+ autoHeight: true,
+ labelWidth: 50,
+ defaults: {
+ anchor: '95%',
+ allowBlank: false,
+ msgTarget: 'side'
+ },
+
+ items: [{
+ fieldLabel: QoKregator.WinImportLibel1,
+ xtype: 'textfield',
+ name: 'importFolder',
+ value: QoKregator.WinImportDefaultValue
+ }, {
+ xtype: 'fileuploadfield',
+ fieldLabel: QoKregator.WinImportLibel2,
+ name: 'importFile',
+ id: 'importFile',
+ emptyText: QoKregator.WinImportInfo,
+ buttonCfg: {
+ text: '',
+ iconCls: 'upload-icon'
+ }
+
+ }]
+
+ });
+
+ var winImport = new Ext.Window({
+ animateEl: 'qo-kregator-add-feed-btn',
+ title: QoKregator.WinImportTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-import',
+ width: 400,
+ height: 210,
+ plain: true,
+ bodyStyle: 'padding:5px',
+ items: FormImport,
+
+ buttons: [{
+ text: QoKregator.WinImportSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(this);
+ }
+ }, {
+ text: QoKregator.WinImportCancelBtn,
+ handler: function(){
+ winImport.close();
+ }
+ }]
+ });
+
+ winImport.show(this);
+
+ }, //showImport
+
+ showAbout: function(){
+
+ if (!this.winAbout) {
+
+ this.winAbout = new Ext.Window({
+ layout: 'fit',
+ width: 560,
+ height: 520,
+ iconCls: 'qo-kregator-icon-about',
+ modal: true,
+ title: QoKregator.WinAboutTitle,
+ closeAction: 'hide',
+ plain: true,
+ bodyStyle: 'color:#000',
+ items: new Ext.TabPanel({
+ autoTabs: true,
+ activeTab: 0,
+ border: false,
+ defaults: {
+ autoScroll: true
+ },
+ items: [{
+ title: QoKregator.WinAboutTab0,
+ html: '<div id="qo-kregator-about"><img src="system/modules/qo-kregator/img/default/logo.png" alt="" /></div><div id="qo-kregator-about-info">ver '+this.appVer+' - (c) 2007 - 2008, Yannick Torrès - <a href="mailto:yannick.torres@xxxxxxxxxxxx">yannick.torres@xxxxxxxxxxxx</a></div>'
+ }, {
+ title: QoKregator.WinAboutTab1,
+ bodyStyle: 'padding:5px',
+ html: '<div id="qo-kregator-credit"><ul><li><a href="http://extjs.com/forum/member.php?u=12208">Franck Carrouget</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits0 + '</span></li><li><a href="http://extjs.com/forum/member.php?u=6915">Andriy Levytskyy</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits1 + '</span></li><li><a href="http://extjs.com/forum/member.php?u=1485">K0bo</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits21 + '</span></li><li><a href="http://www.alsacreations.fr">AlsaCréations</a><br><span class="qo-kregator-credit-info"><a href="http://www.alsacreations.fr/dewplayer">DewPlayer</a> & <a href="http://www.alsacreations.fr/dewtube">DewTube</a></span></li><li><a href="http://extjs.com">ExtJs Team</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits3 + '</span></li></ul></div>'
+ }, {
+ title: QoKregator.WinAboutTab2,
+ autoLoad: {
+ url: 'system/modules/qo-kregator/license_LGPL_v2.txt'
+ }
+ }]
+ }),
+
+ buttons: [{
+ scope:this,
+ text: QoKregator.WinAboutClose,
+ handler: function(){
+ this.winAbout.hide();
+ }
+ }]
+ });
+ }
+ this.winAbout.show(this);
+
+ }, //showAbout
+
+ gridClearFilter: function(){
+
+ // Date searchField
+ Ext.getCmp('qo-kregator-datefilter-btn').curDate = '*';
+ Ext.getCmp('qo-kregator-datefilter-btn').setText(QoKregator.FeedGridFilterDateAllDate);
+ Ext.getCmp('qo-kregator-datefilter-btn').toggle(false);
+
+ // Text searchField
+ Ext.getCmp('qo-kregator-search').setValue('');
+
+ // State searchField
+ Ext.getCmp('qo-kregator-etat').setValue('all', true);
+
+ // Reset the trigger
+ Ext.getCmp('qo-kregator-search').triggers[0].hide();
+
+ }, // gridClearFilter
+
+ showHideStatusBar: function() {
+
+ if( this.ConfshowStatusBar == 'on' ) {
+ Ext.getCmp('qo-kregator').getBottomToolbar().show();
+ } else {
+ Ext.getCmp('qo-kregator').getBottomToolbar().hide();
+ }
+
+ }, //showHideStatusBar
+
+ setStatusBar: function(style, message){
+
+ var statusBar = Ext.getCmp('qo-kregator-statusBar');
+
+ statusBar.setStatus({
+ text: message,
+ iconCls: style
+ });
+
+ }, // setStatusBar
+
+ searchFeed: function() {
+
+ var count = 0;
+
+ this.FeedNeedUpdate = [];
+ this.ConfGoRefresh = true;
+
+ // We change "refresh" to "stop" icon
+ if( Ext.getCmp('qo-kregator-add-refresh-feed-btn') ) {
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setHandler(function() {this.ConfGoRefresh = false;}, this);
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setIconClass('qo-kregator-refresh-stop-btn');
+ }
+
+ function _searchFeed(node, scope){
+
+ var kids = node.childNodes;
+ var len = kids.length;
+ for (var i = 0; i < len; i++) {
+
+ if (kids[i].attributes.type == 'file') {
+
+ // Exclude feed where refreshCycle == off
+ if( kids[i].attributes.refreshCycle == 'on' ) {
+
+ scope.FeedNeedUpdate[count] = [];
+
+ scope.FeedNeedUpdate[count].nodeID = kids[i].id;
+ scope.FeedNeedUpdate[count].id = kids[i].attributes.id;
+ scope.FeedNeedUpdate[count].texte = kids[i].text;
+ ++count;
+
+ }
+
+ }
+ _searchFeed(kids[i], scope);
+ }
+ }
+
+ _searchFeed(this.PanelFeedTree.getRootNode(), this);
+
+ this.goUpdateAllFeed(0);
+
+ this.TaskSearchFeed.delay(this.ConfRefreshFeed * 60 * 1000);
+
+ }, //searchFeed
+
+ goUpdateAllFeed: function(FeedIndex){
+
+ if (this.FeedNeedUpdate[FeedIndex] && this.ConfGoRefresh ) {
+ this.updateFeed(this.FeedNeedUpdate[FeedIndex].texte, this.FeedNeedUpdate[FeedIndex].id, this.FeedNeedUpdate[FeedIndex].nodeID, 'on', FeedIndex + 1);
+ } else {
+
+ // Return to default button refresh
+ if( Ext.getCmp('qo-kregator-add-refresh-feed-btn') ) {
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setHandler(function() {this.TaskSearchFeed.delay(1000);}, this);
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setIconClass('qo-kregator-refresh-btn');
+ }
+ }
+
+
+ }, // goUpdateAllFeed
+
+ updateFeed: function(id_texte, id_Feed, _nodeID, cache, NextFeedIndex){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutUpdateFeed + id_texte + '...');
+
+ this.PanelFeedTree.getNodeById(_nodeID).ui.removeClass("qo-kregator-feed-Unseen");
+ this.PanelFeedTree.getNodeById(_nodeID).ui.addClass("x-tree-node-disabled");
+
+ var UpdateFeed = new Ext.data.Connection();
+
+ UpdateFeed.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ idFeed: id_Feed,
+ cache: cache,
+ what: 'update_feed'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.setStatusBar('qo-kregator-done', id_texte + ' : ' + QoKregator.StatutDone);
+ this.PanelFeedTree.getNodeById(_nodeID).ui.removeClass("x-tree-node-disabled");
+ this.updateFeedInfo(_nodeID, o.unseen, o.new_nb_item);
+
+ // if there is new items & items for this feed are displayed, we update the grid
+ if (o.new_nb_item > o.old_nb_item && this.curFeedId == id_Feed) {
+ this.dsItems.reload();
+ }
+
+ } else {
+
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutUpdateFeedNok + id_texte);
+
+ this.PanelFeedTree.getNodeById(_nodeID).ui.removeClass("x-tree-node-disabled");
+ this.PanelFeedTree.getNodeById(_nodeID).ui.addClass("x-tree-node-error");
+ }
+
+ if (NextFeedIndex >= 0) {
+ this.goUpdateAllFeed(NextFeedIndex);
+ }
+
+ }
+ });
+ }, //updateFeed
+
+ renderDate: function(TmpDate, GoFormat) {
+
+ if (TmpDate == '0000-00-00 00:00:00') { return '-'; }
+
+ var dt = new Date();
+ dt = Date.parseDate(TmpDate, "Y-m-d h:i:s");
+
+ return dt.format(GoFormat);
+
+ }, //renderDate
+
+ setContentFontSize: function(choice) {
+
+ if( Ext.select('.qo-kregator-feed-content') ) {
+ Ext.select('.qo-kregator-feed-content').setStyle('font-size', this.ConfContentFontSize+'px');
+ }
+ } // setContentFontSize
+
+});
Added: trunk/qo-kregator/qo-kregator_old.js
===================================================================
--- trunk/qo-kregator/qo-kregator_old.js (rev 0)
+++ trunk/qo-kregator/qo-kregator_old.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,3434 @@
+/************************************************************************
+ This file is part of Qo-Kregator.
+ Qo-Kregator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Qo-Kregator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Qo-Kregator. If not, see <http://www.gnu.org/licenses/>.
+ *************************************************************************/
+
+// Allow to add a Menu after the Button is rendered
+Ext.override(Ext.Button,
+{
+ initComponent: function() {
+ Ext.Button.superclass.initComponent.call(this);
+ this.addEvents('click','toggle','mouseover','mouseout','menushow','menuhide','menutriggerover','menutriggerout');
+
+ if (this.menu) {
+ var m = this.menu;
+ delete this.menu;
+ this.setMenu(m);
+ }
+
+ if (typeof this.toggleGroup === 'string') {
+ this.enableToggle = true;
+ }
+ },
+
+ setMenu: function(menu) {
+ var hasMenu = (this.menu !== null);
+ this.menu = Ext.menu.MenuMgr.get(menu);
+
+ if (this.rendered && !hasMenu) {
+ this.el.child(this.menuClassTarget).addClass('x-btn-with-menu');
+ this.menu.on("show", this.onMenuShow, this);
+ this.menu.on("hide", this.onMenuHide, this);
+ }
+ },
+
+ clearMenu: function(destroy) {
+ if (this.rendered) {
+ this.el.child(this.menuClassTarget).removeClass('x-btn-with-menu');
+ this.menu.un('show', this.onMenuShow, this);
+ this.menu.un('hide', this.onMenuHide, this);
+ }
+ if (destroy) {
+ Ext.destroy(this.menu);
+ }
+ this.menu = null;
+ }
+}
+);
+
+QoDesk.QoKregator = Ext.extend(Ext.app.Module, {
+
+ moduleType : 'internet',
+ moduleId : 'qo-kregator',
+ menuPath: 'StartMenu/Internet',
+
+ appVer : '2.0',
+
+ // Conf var
+ ConfExpandCollapse : false,
+ ConfGoRefresh: true,
+ ConfShowSummary: true,
+ ConfTreePanelWidth:'254',
+ ConfGridPanelHeight:'150',
+ ConfPreviewPanelSouthHeight:'300',
+ ConfPreviewPanelEastWidth:'400',
+ ConfPreviewPane:'bottom',
+ ConfRefreshFeed:'10',
+ ConfOldItems:false,
+ ConfOldItemsDay:'30',
+ ConfContentFontSize: 11,
+ ConfshowStatusBar: 'on',
+ ConfOpenMode: 'Window',
+ ConfDateTimeFormat: 'd/m/y, H:i',
+ ConfDateFormat: 'd/m/y',
+
+ // Panel
+ PanelFeedTree:'',
+ PanelFeedTreeEditor:'',
+ PanelGridItem:'',
+ PanelPreview:'',
+ PanelCenter:'',
+
+ //ToolBars
+ tbFeedBtnAvailable: ['AddFeed', 'AddFolder', 'Import', 'Export', 'ExpandCollapse', 'RefreshFeed', 'ContextMenu'],
+ tbFeedBtnCurrent: [],
+
+ // DataStore
+ dsItems:'',
+ dsItemDesc:'',
+
+ // Window
+ winAbout:false,
+
+ // Task
+ TaskSearchFeed:false,
+ TaskCleanFeed:false,
+
+ // others vars
+ FeedNeedUpdate:false,
+ LastClick:0,
+ curNodeId:'',
+ curFeedId:'',
+ columnUnseenWidth:50, // change this value to modify Unseen column width
+ columnTotalWidth:50, // change this value to modify Total column width
+ linkDefaultTab:'',
+
+ init: function(){
+ this.launcher = {
+ text: 'Qo-Kregator',
+ tooltip: '<b>Qo-Kregator</b><br />' + QoKregator.LauncherDescription,
+ iconCls: 'qo-kregator-icon',
+ shortcutIconCls: 'qo-kregator-win-shortcut',
+ handler: this.createWindow,
+ scope: this
+ };
+ },
+
+ createWindow: function() {
+ var desktop = this.app.getDesktop();
+ var win = desktop.getWindow('qo-kregator');
+
+ if (!win) {
+
+
+ // Plugins for right click on tab
+ Ext.ux.KregaTabCloseMenu = function(env){
+ var tabs, menu, ctxItem;
+ this.scope = env;
+ this.init = function(tp){
+ tabs = tp;
+ tabs.on('contextmenu', onContextMenu, this);
+ };
+
+ function onContextMenu(ts, item, e){
+
+ e.preventDefault();
+ e.stopEvent();
+
+ if( item.id == 'qo-kregator-main' ) { item.linkTab = this.scope.linkDefaultTab;}
+
+ if(!menu){ // create context menu on first right click
+ menu = new Ext.menu.Menu([{
+ id: 'qo-kregator-' + tabs.id + '-close',
+ text: QoKregator.TabCtxCloseTab,
+ iconCls: 'DeskKregator-close-Tab-btn',
+ handler : function() {
+ tabs.remove(ctxItem);
+ }
+ },{
+ id: 'qo-kregator-' + tabs.id + '-close-others',
+ text: QoKregator.TabCtxCloseOtherTabs,
+ handler : function() {
+ tabs.items.each(function(item){
+ if(item.closable && item != ctxItem){
+ tabs.remove(item);
+ }
+ });
+ }
+ },'-',{
+ id:'qo-kregator-' + tabs.id + '-open-tab-site',
+ text:QoKregator.FeedGridItemOpenInWin,
+ iconCls:'qo-kregator-open-site-btn',
+ handler: function() {
+ window.open(ctxItem.linkTab, 'win');
+ }
+ }]);
+ }
+ ctxItem = item;
+ var items = menu.items;
+ items.get('qo-kregator-' + tabs.id + '-close').setDisabled(!item.closable);
+ var disableOthers = true;
+ tabs.items.each(function(){
+ if(this != item && this.closable){
+ disableOthers = false;
+ return false;
+ }
+ });
+ items.get('qo-kregator-' + tabs.id + '-close-others').setDisabled(disableOthers);
+ if( !item.linkTab ) {
+ items.get('qo-kregator-' + tabs.id + '-open-tab-site').setDisabled(true);
+ } else {
+ items.get('qo-kregator-' + tabs.id + '-open-tab-site').setDisabled(false);
+ }
+ menu.showAt(e.getPoint());
+ }
+ };
+
+ // Create Splash
+ Ext.DomHelper.append(document.body, {
+ tag: 'div',
+ id: 'qo-kregator-splash',
+ children: [{
+ tag: 'div',
+ cls: 'qo-kregator-splash-indicator',
+ html: '<img src="system/modules/qo-kregator/img/default/logo.png" alt="" /><div id="qo-kregator-splash-msg">' + QoKregator.SplashInit + '</div>'
+ }]
+ });
+
+ // We load user conf before show app
+ Ext.get('qo-kregator-splash-msg').dom.innerHTML = QoKregator.SplashLoadConf;
+
+
+ Ext.Ajax.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ what: 'get_user_conf'
+ },
+ success: function(response, options) {
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.ConfRefreshFeed = o.refresh_feed;
+ this.ConfOldItems = o.old_items;
+ this.ConfOldItemsDay = o.old_items_day;
+ this.ConfPreviewPane = o.preview_pane;
+ this.ConfShowSummary = o.showSummary;
+ this.ConfContentFontSize = o.content_font_size;
+ this.ConfshowStatusBar = o.showStatusBar;
+ this.tbFeedBtnCurrent = o.tbFeedBtn;
+
+ this.ConfOpenMode = o.openMode;
+
+ this.ConfDateTimeFormat = o.dateTimeFormat;
+ this.ConfDateFormat = o.dateFormat;
+
+ this.ConfTreePanelWidth = o.tree_panel_width;
+ this.ConfGridPanelHeight = o.grid_panel_height;
+ this.ConfPreviewPanelSouthHeight = o.preview_panel_south_height;
+ this.ConfPreviewPanelEastWidth = o.preview_panel_east_width;
+
+ } else {
+
+ this.ConfRefreshFeed = 10;
+ this.ConfOldItems = false;
+ this.ConfOldItemsDay = 30;
+ this.ConfPreviewPane = 'bottom';
+ this.ConfShowSummary = true;
+ this.ConfContentFontSize = 11;
+ this.ConfshowStatusBar = 'on';
+ this.ConfOpenMode = 'Window';
+
+ this.ConfDateTimeFormat = 'd/m/y, H:i';
+ this.ConfDateFormat = 'd/m/y';
+
+ this.ConfTreePanelWidth = '254';
+ this.ConfGridPanelHeight = '150';
+ this.ConfPreviewPanelSouthHeight = '300';
+ this.ConfPreviewPanelEastWidth = '400';
+ this.tbFeedBtnCurrent = ['AddFeed', 'AddFolder', 'Import', 'Export', 'ExpandCollapse', 'RefreshFeed'];
+
+ }
+
+ // Custom ColumnTree
+ Ext.tree.KregaColumnTree = Ext.extend(Ext.tree.TreePanel, {
+ lines:false,
+ borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
+ cls:'qo-kregator-x-column-tree',
+ onRender : function(){
+ Ext.tree.KregaColumnTree.superclass.onRender.apply(this, arguments);
+ this.headers = this.body.createChild(
+ {id:'qo-kregator-x-tree-headers-id', cls:'qo-kregator-x-tree-headers'},this.innerCt.dom);
+ var cols = this.columns, c;
+ var totalWidth = 0;
+ for(var i = 0, len = cols.length; i < len; i++) {
+ var clsHere;
+ if( i === 0 ) { clsHere = 'qo-kregator-x-tree-hd-text-feed';}
+ else { clsHere = 'qo-kregator-x-tree-hd-text';}
+
+ c = cols[i];
+ totalWidth += c.width;
+ this.headers.createChild({
+ id: 'qo-kregator-feed-hd-'+i,
+ cls:'qo-kregator-x-tree-hd ' + (c.cls?c.cls+'-hd':''),
+ cn: {
+ cls: clsHere,
+ html: c.header
+ },
+ style:'width:'+(c.width-this.borderWidth)+'px;'
+ });
+ }
+ this.headers.createChild({cls:'x-clear'});
+ // prevent floats from wrapping when clipped
+ this.headers.setWidth(totalWidth);
+ this.innerCt.setWidth(totalWidth);
+ }
+ });
+
+ Ext.tree.KregaColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+ focus: Ext.emptyFn, // prevent odd scrolling behavior
+
+ renderElements : function(n, a, targetNode, bulkRender){
+ this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
+
+ var t = n.getOwnerTree();
+ var cols = t.columns;
+ var bw = t.borderWidth;
+ var c = cols[0];
+ var colID;
+
+ var buf = [
+ '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'">',
+ '<div class="qo-kregator-x-tree-col" style="width:',c.width-bw,'px;">',
+ '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
+ '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
+ '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
+ '<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
+ a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
+ '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
+ "</div>"];
+ for(var i = 1, len = cols.length; i < len; i++) {
+ c = cols[i];
+
+ if( i == 1 ) { colID = 'qo-kregator-unSeen-'+n.id; }
+ else { colID = 'qo-kregator-Total-'+n.id; }
+
+ buf.push('<div class="qo-kregator-x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
+ '<div class="qo-kregator-x-tree-col-text" id="'+colID+'">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
+ "</div>");
+ }
+ buf.push(
+ '<div class="x-clear"></div></div>',
+ '<ul class="x-tree-node-ct" style="display:none;"></ul>',
+ "</li>");
+
+ if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
+ this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
+ n.nextSibling.ui.getEl(), buf.join(""));
+ }else{
+ this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
+ }
+
+ this.elNode = this.wrap.childNodes[0];
+ this.ctNode = this.wrap.childNodes[1];
+ var cs = this.elNode.firstChild.childNodes;
+ this.indentNode = cs[0];
+ this.ecNode = cs[1];
+ this.iconNode = cs[2];
+ this.anchor = cs[3];
+ this.textNode = cs[3].firstChild;
+ }
+ });
+
+ this.dsItems = new Ext.data.Store({
+ proxy: new Ext.data.HttpProxy({
+ url: this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/qo-kregator.php&what=get_items'
+ }),
+ reader: new Ext.data.JsonReader({
+ root: 'Items',
+ totalProperty: 'nbItems',
+ id: 'id'
+ }, [{
+ name: 'id',
+ mapping: 'id'
+ }, {
+ name: 't',
+ mapping: 't'
+ }, {
+ name: 'd',
+ mapping: 'd'
+ }, {
+ name: 'u',
+ mapping: 'u'
+ }, {
+ name: 's',
+ mapping: 's'
+ }, {
+ name: 'i',
+ mapping: 'i'
+ }, {
+ name: 'f',
+ mapping: 'f'
+ }, {
+ name: 'id_f',
+ mapping: 'id_f'
+ }, {
+ name: 'sum',
+ mapping: 'sum'
+ }])
+ });
+
+ // Sort by default : date, DESC
+ this.dsItems.setDefaultSort('d', 'desc');
+
+ this.dsItems.on('load', function(){
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutDone);
+ this.selectFirstUnreadItems();
+
+ }, this);
+
+ this.dsItemDesc = new Ext.data.Store({
+ proxy: new Ext.data.HttpProxy({
+ url: this.app.connection
+ }),
+ baseParams: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ what: 'get_items_desc'
+ },
+ reader: new Ext.data.JsonReader({}, [{
+ name: 't'
+ }, {
+ name: 'd'
+ }, {
+ name: 'a'
+ }, {
+ name: 'des'
+ }, {
+ name: 'u'
+ }, {
+ name: 'f'
+ }])
+ });
+
+ this.dsItemDesc.on('load', function(){
+
+ var nodeItem = this.dsItemDesc.getAt(0);
+ var title = nodeItem.data.t;
+ var link = nodeItem.data.u;
+ var date = this.renderDate(nodeItem.data.d, this.ConfDateTimeFormat);
+ var auteur = nodeItem.data.a;
+ var feedName = nodeItem.data.f;
+ var desc = nodeItem.data.des;
+
+ if (this.PanelFeedTree.selModel.selNode.attributes.view == 'site') {
+
+ this.PanelPreview.setTitle(this.PanelFeedTree.selModel.selNode.attributes.text);
+ this.PanelPreview.body.dom.innerHTML = '<div class="qo-kregator-preview-content"><iframe width="100%" height="100%" frameborder="0" src="' + link + '" /></div>';
+
+ } else {
+
+ this.PanelPreview.setTitle(feedName);
+
+ var content = '<div class="qo-kregator-feed-info">' +
+ '<div class="qo-kregator-item-date">' +
+ date +
+ '</div>' +
+ '<div class="qo-kregator-item-title">' +
+ title +
+ '</div>' +
+ '<div class="qo-kregator-item-author">' +
+ QoKregator.PreviewAutor +
+ auteur +
+ '</div>' +
+ '</div>' +
+ '<div class="qo-kregator-feed-content">' +
+ desc +
+ '</div>';
+
+ this.PanelPreview.body.dom.innerHTML = content;
+ this.setContentFontSize('=');
+ this.PanelPreview.el.on('click', function(e, target, options) {
+
+ e.preventDefault();
+ e.stopEvent();
+
+ var delai = new Date();
+ var curClick = delai.getTime();
+
+ if (this.LastClick === 0) { this.LastClick = curClick - 51; }
+
+ var diff = (curClick - this.LastClick);
+ if (target.href) {
+ if (diff > 50) {
+ this.LastClick = curClick;
+ var uniq = Ext.id();
+ this.openInTab(uniq, target.href, target.href);
+ }
+ }
+ }, this);
+ }
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutDone);
+
+ }, this);
+
+ this.PanelFeedTree = new Ext.tree.KregaColumnTree({
+ width:252,
+ id: 'qo-kregator-id-tree-column',
+ border: false,
+ enableDD: true,
+ autoHeight:true,
+ rootVisible:false,
+ autoScroll:true,
+ containerScroll: true,
+ listeners: {
+ scope: this,
+ contextmenu: this.onContextMenuFeed,
+ click: this.onClickFeed
+ },
+
+ columns:[{
+ id:'qo-kregator-feedTree-colum',
+ header:QoKregator.TreeTitle,
+ width:150,
+ dataIndex:'text'
+ },{
+ header: QoKregator.TreeColumn1,
+ width:this.columnUnseenWidth,
+ dataIndex:'unseen'
+ },{
+ header: QoKregator.TreeColumn2,
+ width:this.columnTotalWidth,
+ dataIndex:'total'
+ }],
+
+ loader: new Ext.tree.TreeLoader({
+ dataUrl:this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/qo-kregator.php&what=get_nodes',
+ uiProviders:{
+ 'col': Ext.tree.KregaColumnNodeUI
+ }
+ }),
+
+ root: new Ext.tree.AsyncTreeNode({
+ text:'RootFeed'
+ })
+ });
+
+ // Editor
+ this.PanelFeedTreeEditor = new Ext.tree.TreeEditor(this.PanelFeedTree, {
+ allowBlank: false
+ });
+
+ // Edit node
+ this.PanelFeedTreeEditor.on('complete', function(editor, fieldValue, beforeValue){
+
+ // If there is no change, go back
+ if(fieldValue == beforeValue) { return; }
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutMod);
+
+ // Update nodeText
+ var saveFeedText = new Ext.data.Connection();
+ saveFeedText.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id: editor.editNode.id,
+ value: fieldValue,
+ what: 'mod_feed_text'
+ },
+
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutModOk);
+
+ // Update tab title & preview Title
+ Ext.getCmp('qo-kregator-main').setTitle(Ext.util.Format.ellipsis(fieldValue,20));
+ this.PanelPreview.setTitle(fieldValue);
+
+ }
+ else {
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutModNok);
+ }
+ }
+ });
+
+ }, this);
+
+ // Drag & Drop Tree Elements
+ this.PanelFeedTree.on('enddrag', function(tree){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutReorder);
+
+ function simplifyNodes(node){
+ var resultNode = {};
+ var kids = node.childNodes;
+ var len = kids.length;
+ for (var i = 0; i < len; i++) {
+ resultNode[kids[i].id] = simplifyNodes(kids[i]);
+ }
+ return resultNode;
+ }
+
+ // JSON-encode our tree
+ var encNodes = Ext.encode(simplifyNodes(this.PanelFeedTree.root));
+
+ // send it to the backend to save
+ var saveOrder = new Ext.data.Connection();
+ saveOrder.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodes: encNodes,
+ what: 'save_nodes'
+ },
+
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutReorderOk);
+ }
+ else {
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutReorderNok);
+ }
+ }
+ });
+ }, this);
+
+ // New SearchField
+ Ext.app.SearchField = Ext.extend(Ext.form.TwinTriggerField, {
+
+ initComponent: function(){
+
+ if (!this.store.baseParams) {
+ this.store.baseParams = {};
+ }
+
+ Ext.app.SearchField.superclass.initComponent.call(this);
+
+ this.on('specialkey', function(f, e){
+ if (e.getKey() == e.ENTER) {
+ this.onTrigger2Click();
+ }
+ }, this);
+ },
+
+ validationEvent: false,
+ validateOnBlur: false,
+ trigger1Class: 'x-form-clear-trigger',
+ trigger2Class: 'x-form-search-trigger',
+ hideTrigger1: true,
+ width: 100,
+ hasSearch: false,
+ emptyText: QoKregator.FeedGridFilterSearch,
+
+ onTrigger1Click: function(){
+ if (this.hasSearch) {
+
+ this.store.baseParams = {
+ 'id_feed': this.env.curFeedId,
+ 'id_node': this.env.curNodeId
+ };
+
+ Ext.getCmp('qo-kregator-etat').setValue('all', true);
+
+ var o = {
+ start: 0,
+ limit: 25
+ };
+ this.store.reload({
+ params: o
+ });
+
+ this.el.dom.value = '';
+ this.triggers[0].hide();
+ this.hasSearch = false;
+ }
+ this.reset();
+ },
+
+ onTrigger2Click: function(){
+
+ var v = this.getRawValue();
+
+ if (v.length < 2 && v !== '') {
+ Ext.Msg.alert(QoKregator.FeedGridBoxSearchTitle, QoKregator.FeedGridBoxSearchContent);
+ return;
+ }
+
+ this.env.setStatusBar('qo-kregator-inProgress', QoKregator.StatutSearchLoad);
+
+ this.store.baseParams = {
+ 'id_feed': this.env.curFeedId,
+ 'id_node': this.env.curNodeId,
+ 'searchText': v,
+ 'searchEtat': Ext.getCmp('qo-kregator-etat').getValue(),
+ 'searchDate' : Ext.getCmp('qo-kregator-datefilter-btn').curDate
+ };
+
+ var o = {
+ start: 0,
+ limit: 25
+ };
+ this.store.reload({
+ params: o
+ });
+ this.hasSearch = true;
+ this.triggers[0].show();
+ }
+ });
+ Ext.reg('searchfield', Ext.app.SearchField);
+ // End new searchField
+
+ this.PanelGridItem = new Ext.grid.GridPanel({
+ scope: this,
+ id:'qo-kregator-id-gridFeed-panel',
+ store: this.dsItems,
+ lastRowClick: {
+ time: new Date().getTime(),
+ row: -1
+ },
+ columns: [{
+ id: 'article',
+ header: QoKregator.FeedGridHeaderItem,
+ sortable: true,
+ dataIndex: 't'
+ }, {
+ id: 'feed',
+ header: QoKregator.FeedGridHeaderFeed,
+ sortable: true,
+ width: 120,
+ dataIndex: 'f'
+ }, {
+ id: 'date',
+ header: QoKregator.FeedGridHeaderDate,
+ width: 120,
+ sortable: true,
+ dataIndex: 'd',
+ scope: this,
+ renderer: this.renderDate.createDelegate(this, [this.ConfDateTimeFormat], 1)
+ }],
+ autoExpandColumn: 'article',
+ loadMask: true,
+ viewConfig: {
+ scope: this,
+ forceFit: true,
+ showSummary: this.ConfShowSummary,
+ enableRowBody: true,
+ getRowClass: function(record, rowIndex, p, ds) {
+
+ var retour = '';
+
+ if (record.data.s == 'y') {
+ retour += 'qo-kregator-feed-read';
+ } else {
+ retour += 'qo-kregator-feed-unread';
+ }
+
+ if (record.data.i == 'y') {
+ retour += ' qo-kregator-feed-important';
+ }
+
+ if( this.showSummary ) {
+ p.body = '<p class="qo-kregator-summary">' + record.data.sum + '</p>';
+ retour += ' x-grid3-row-expanded';
+ }
+
+ return retour;
+
+ }
+ },
+ enableColumnMove: true,
+ tbar: [{
+ xtype:'searchfield',
+ id: 'qo-kregator-search',
+ width: 130,
+ store: this.dsItems,
+ env: this,
+ listeners: {
+ scope: this
+ }
+ },'-',{
+ xtype: 'combo',
+ store: new Ext.data.SimpleStore({
+ fields: ['etat', 'Libel'],
+ data: [['all', QoKregator.FeedGridFilterAllItems], ['nonlu', QoKregator.FeedGridFilterUnseenItems], ['important', QoKregator.FeedGridFilterImportantItems]]
+ }),
+ displayField: 'Libel',
+ valueField: 'etat',
+ typeAhead: true,
+ width: 120,
+ mode: 'local',
+ triggerAction: 'all',
+ selectOnFocus: false,
+ editable: false,
+ allowBlank: false,
+ value: 'all',
+ id: 'qo-kregator-etat',
+ listeners: {
+ scope: this,
+ select: function(){
+ Ext.getCmp('qo-kregator-search').onTrigger2Click();
+ }
+ }
+ },'-',{
+ xtype: 'tbsplit',
+ scope:this,
+ text: QoKregator.FeedGridFilterDateAllDate,
+ id: 'qo-kregator-datefilter-btn',
+ iconCls: 'qo-kregator-icon-datefilter',
+ tooltip: QoKregator.FeedGridFilterDatePickDate,
+ curDate: '*',
+ enableToggle: true,
+ handler: function(btn) {
+ if( btn.pressed ) {
+ btn.setText(QoKregator.FeedGridFilterDatePickDate);
+ btn.showMenu();
+ btn.curDate = '*';
+ } else {
+ btn.setText(QoKregator.FeedGridFilterDateAllDate);
+ btn.hideMenu();
+ btn.curDate = '*';
+ Ext.getCmp('qo-kregator-search').onTrigger2Click();
+ }
+ },
+ menu: new Ext.menu.DateMenu({
+ scope: this,
+ handler : function(dp, date){
+ Ext.getCmp('qo-kregator-datefilter-btn').setText(date.format(this.ConfDateFormat));
+ Ext.getCmp('qo-kregator-datefilter-btn').curDate = date.format('Y:m:d');
+ Ext.getCmp('qo-kregator-search').onTrigger2Click();
+ }
+ })
+ }, '-', {
+ scope: this,
+ tooltip: {
+ title: QoKregator.ReadingBtnTitle,
+ text: QoKregator.ReadingBtnQtip
+ },
+ iconCls: 'qo-kregator-preview-bottom',
+ handler: this.movePreview
+ },'-',{
+ scope: this,
+ tooltip: {
+ title: QoKregator.SummaryBtnTitle,
+ text: QoKregator.SummaryBtnText
+ },
+ enableToggle: true,
+ id:'qo-kregator-summary-btn-id',
+ iconCls: 'qo-kregator-summary-btn',
+ toggleHandler: function(btn, pressed){
+ this.toggleSummary(pressed);
+ }
+ },'-', {
+ xtype: 'button',
+ scope:this,
+ id: 'qo-kregator-contextmenu-news-btn',
+ iconCls: 'qo-kregator-icon-contextmenu',
+ tooltip: {
+ title: QoKregator.ContextMenuBtnTooltipTitle,
+ text: QoKregator.ContextMenuBtnTooltipText
+ },
+ menu: []
+ }
+ ],
+
+ bbar: new Ext.PagingToolbar({
+ pageSize: 25,
+ store: this.dsItems,
+ displayInfo: true,
+ displayMsg: QoKregator.FeedGridPagingDisplay,
+ emptyMsg: QoKregator.FeedGridPagingNoDisplay
+ }),
+ listeners: {
+ scope: this,
+ rowdblclick: function(grid, rowIndex, e) {
+
+ var _node = this.dsItems.getAt(rowIndex);
+ var _id = _node.data.id;
+ var _link = _node.data.u;
+ var _title = _node.data.t;
+ this.openInTab('items-' + _id, _title, _link);
+
+ var timeNow = new Date().getTime();
+
+ if(grid.lastRowClick.row != rowIndex){
+ grid.lastRowClick.row = rowIndex;
+ grid.lastRowClick.time = timeNow;
+ }
+ else if(timeNow - grid.lastRowClick.time >= 500){
+ return;
+ }
+ else{
+ grid.lastRowClick.time = timeNow;
+ }
+
+ },
+
+ rowclick: function(grid, rowIndex, e) {
+
+ var timeNow = new Date().getTime();
+ if(grid.lastRowClick.row != rowIndex){
+ grid.lastRowClick.row = rowIndex;
+ grid.lastRowClick.time = timeNow;
+ }
+ else if(timeNow - grid.lastRowClick.time < 500){
+ return;
+ }
+ else{
+ grid.lastRowClick.time = timeNow;
+ }
+
+ },
+
+ rowcontextmenu: function(grid, rowIndex, e){
+ this.onContextItemFeed(grid, rowIndex, e);
+ }
+ }
+ });
+
+ // SelectionModel for GridPanel
+ var smPanelGridItem = this.PanelGridItem.getSelectionModel();
+ smPanelGridItem.on('rowselect', function(sM, rowIndex, r) {
+
+ //Build the sub-menu for the contextMenu-btn
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu(this.createContextItemFeed());
+
+ this.loadItem(rowIndex);
+
+ }, this);
+
+ this.PanelCenter = new Ext.TabPanel({
+ region: 'center',
+ margins: '0 0 0 0',
+ activeTab: 0,
+ border: false,
+ bodyStyle: 'background-color:#fff',
+ enableTabScroll: true,
+ plugins: new Ext.ux.KregaTabCloseMenu(this),
+ defaults: {
+ autoScroll: true
+ },
+ items: [{
+ title: QoKregator.FeedGridTabTitle,
+ id: 'qo-kregator-main',
+ border: false,
+ margins: '0 0 0 0',
+ layout: 'fit',
+ items: [{
+ region: 'center',
+ border: false,
+ layout: 'border',
+ margins: '0 0 0 0',
+ items: [{
+ region: 'center',
+ layout: 'fit',
+ border: false,
+ minHeight: 150,
+ height: 150,
+ split: true,
+ items: this.PanelGridItem
+ }, {
+ autoScroll: true,
+ layout: 'fit',
+ region: 'south',
+ split: true,
+ height: 300,
+ bodyStyle: 'background-color:#fff',
+ id: 'qo-kregator-previewPanelSouth',
+ title: QoKregator.PreviewTitle
+ }, {
+ autoScroll: true,
+ layout: 'fit',
+ region: 'east',
+ split: true,
+ hidden: true,
+ width: 400,
+ bodyStyle: 'background-color:#fff',
+ id: 'qo-kregator-previewPanelEast',
+ title: QoKregator.PreviewTitle
+ }]
+ }]
+ }]
+ });
+
+ this.PanelPreview = Ext.getCmp('qo-kregator-previewPanelSouth');
+
+ var winWidth = desktop.getWinWidth() / 1.1;
+ var winHeight = desktop.getWinHeight() / 1.1;
+
+ // Feed ToolBar
+ this.tbFeedBtnAvailable.AddFeed = {
+ xtype: 'button',
+ id: 'qo-kregator-add-feed-btn',
+ iconCls:'qo-kregator-icon-add-feed',
+ cls: 'x-btn-icon',
+ scope: this,
+ handler: function(){
+ this.showAddFeed(0);
+ },
+ tooltip: QoKregator.TreeAddFeed
+ };
+
+ this.tbFeedBtnAvailable.AddFolder = {
+ xtype: 'button',
+ iconCls:'qo-kregator-icon-add-folder',
+ scope: this,
+ handler: function(){
+ this.showAddFolder(0);
+ },
+ tooltip: QoKregator.TreeAddFolder
+ };
+
+ this.tbFeedBtnAvailable.Import = {
+ xtype: 'button',
+ iconCls:'qo-kregator-icon-import',
+ scope: this,
+ handler: this.showImport,
+ tooltip: QoKregator.TreeImport
+ };
+
+ this.tbFeedBtnAvailable.Export = {
+ xtype: 'button',
+ scope: this,
+ iconCls:'qo-kregator-icon-export',
+ handler: function(){
+ window.location = this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/export.php';
+ },
+ tooltip: QoKregator.TreeExport
+ };
+
+
+ this.tbFeedBtnAvailable.ExpandCollapse = {
+ xtype: 'button',
+ scope: this,
+ id: 'qo-kregator-expand-collapse-btn',
+ iconCls:'qo-kregator-icon-expand',
+ handler: function(){
+ if( !this.ConfExpandCollapse ) {
+
+ this.ConfExpandCollapse='collapse';
+ this.PanelFeedTree.expandAll();
+ Ext.getCmp('qo-kregator-expand-collapse-btn').setIconClass('qo-kregator-icon-collapse');
+
+ } else if( this.ConfExpandCollapse == 'expand' ) {
+
+ this.ConfExpandCollapse='collapse';
+ this.PanelFeedTree.expandAll();
+ Ext.getCmp('qo-kregator-expand-collapse-btn').setIconClass('qo-kregator-icon-collapse');
+
+ } else if( this.ConfExpandCollapse == 'collapse' ) {
+
+ this.ConfExpandCollapse='expand';
+ this.PanelFeedTree.collapseAll();
+ Ext.getCmp('qo-kregator-expand-collapse-btn').setIconClass('qo-kregator-icon-expand');
+
+ }
+ },
+ tooltip: QoKregator.TreeExpandCollapse
+ };
+
+ this.tbFeedBtnAvailable.RefreshFeed = {
+ xtype: 'button',
+ scope:this,
+ id: 'qo-kregator-add-refresh-feed-btn',
+ iconCls: 'qo-kregator-refresh-btn',
+ handler: function(){
+ this.TaskSearchFeed.delay(1000);
+ },
+ tooltip: QoKregator.TreeRefresh
+ };
+
+ this.tbFeedBtnAvailable.ContextMenu = {
+ xtype: 'button',
+ scope:this,
+ id: 'qo-kregator-contextmenu-btn',
+ iconCls: 'qo-kregator-icon-contextmenu',
+ tooltip: {
+ title: QoKregator.ContextMenuBtnTooltipTitle,
+ text: QoKregator.ContextMenuBtnTooltipText
+ },
+ menu: []
+ };
+
+
+ win = desktop.createWindow({
+ id: 'qo-kregator',
+ title: 'Qo-Kregator',
+ width: winWidth,
+ height: winHeight,
+ x: desktop.getWinX(winWidth),
+ y: desktop.getWinY(winHeight),
+ iconCls: 'qo-kregator-icon',
+ shim: false,
+ animCollapse: false,
+ constrainHeader: true,
+ minimizable: true,
+ maximizable: true,
+ layout: 'border',
+ tools : [{
+ scope: this,
+ id:'gear',
+ qtip:QoKregator.WinConfToolTip,
+ handler:this.showConf
+
+ }, {
+ scope: this,
+ id:'help',
+ qtip: QoKregator.WinAboutTitle,
+ handler:this.showAbout
+
+ }],
+ bbar: new Ext.StatusBar({
+ id: 'qo-kregator-statusBar',
+ text: QoKregator.StatutReady,
+ iconCls: 'qo-kregator-done'
+
+ }),
+ items: [{
+ region: 'west',
+ layout:'fit',
+ id: 'qo-kregator-id-Feed-Tree',
+ autoScroll: true,
+ collapsible: true,
+ collapseMode: 'mini',
+ cmargins: '0 0 0 0',
+ margins: '0 0 0 0',
+ split: true,
+ bodyStyle: 'background-color:#fff',
+ width: 254,
+ items: this.PanelFeedTree,
+ scope: this,
+ tbar: []
+ }, this.PanelCenter]
+ });
+
+ //Build Tb Feed
+ this.buildTbFeed();
+
+ this.PanelFeedTree.on('collapsenode', function(node){ this.saveFolderState(node.id, 0); }, this);
+ this.PanelFeedTree.on('expandnode', function(node){ this.saveFolderState(node.id, 1); }, this);
+
+ // Set preview pane position
+ this.setPreviewPanePosition(this.ConfPreviewPane);
+
+ // Set summary configuration
+ this.setSummary(this.ConfShowSummary);
+
+ // Show / Hide the statusBar
+ this.showHideStatusBar();
+
+ // Set Pane Size
+ this.setPanelSize('tree_panel_width', this.ConfTreePanelWidth);
+ this.setPanelSize('grid_panel_height', this.ConfGridPanelHeight);
+ this.setPanelSize('panel_south_height',this.ConfPreviewPanelSouthHeight);
+ this.setPanelSize('panel_east_width', this.ConfPreviewPanelEastWidth);
+
+ if (this.ConfOldItems) {
+
+ // Register task for delete old items
+ this.TaskCleanFeed = new Ext.util.DelayedTask(this.cleanFeed, this);
+ this.TaskCleanFeed.delay(2000); // start after 2 secondes.
+ } else {
+
+ // Register task for AutoRefresh Feed
+ this.TaskSearchFeed = new Ext.util.DelayedTask(this.searchFeed, this);
+ this.TaskSearchFeed.delay(2000); // start after 2 secondes.
+ }
+
+ // Unregister
+ win.on('close', function() { this.TaskSearchFeed.cancel(); }, this);
+
+ var Krega_taskSelectFirstFeed = new Ext.util.DelayedTask(this.selectFirstUnseenFeed, this);
+ Krega_taskSelectFirstFeed.delay(1000); // start after 1 seconde.
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutReady);
+
+ // 'On' resize TreePanel
+ Ext.getCmp('qo-kregator-id-Feed-Tree').on('resize', function(panel, Pwidth, Pheight) {
+
+ var treeWidth;
+
+ if( panel.body.isScrollable() ) { treeWidth = Pwidth-19; }
+ else { treeWidth = Pwidth; }
+
+ this.setFeedPanelWidth(treeWidth);
+ this.savePanelSizeState('tree_panel_width', treeWidth);
+
+ }, this);
+
+ // 'On' resize GridPanel
+ Ext.getCmp('qo-kregator-id-gridFeed-panel').on('resize', function(panel, Pwidth, Pheight) {
+ this.savePanelSizeState('grid_panel_height', Pheight);
+ }, this);
+
+ // 'On' resize PreviewPanel Bottom
+ Ext.getCmp('qo-kregator-previewPanelSouth').on('resize', function(panel, Pwidth, Pheight) {
+ this.savePanelSizeState('preview_panel_south_height', Pheight);
+ }, this);
+
+ // 'On' resize PreviewPanel Right
+ Ext.getCmp('qo-kregator-previewPanelEast').on('resize', function(panel, Pwidth, Pheight) {
+ this.savePanelSizeState('preview_panel_east_width', Pwidth);
+ }, this);
+
+ // Remove the splash screen
+ Ext.get('qo-kregator-splash').fadeOut({
+ remove: true
+ });
+
+ // Handle How we must open Qo-Kregator
+ if( this.ConfOpenMode == 'Window' ) {
+ win.show();
+ } else if( this.ConfOpenMode == 'FullScreen' ) {
+ win.show();
+ win.maximize();
+ } else if( this.ConfOpenMode == 'Minimized' ) {}
+
+
+
+ } // End successfully load user's configuration
+
+ });
+
+
+ } else { win.show(); }
+
+ }, //createWindow
+
+ buildTbFeed: function() {
+
+ // We remove all button currently in this toolBar
+ var nbButton = Ext.getCmp('qo-kregator-id-Feed-Tree').getTopToolbar().items.items.length;
+
+ for( var i=0; i < nbButton; i++ ) {
+ var item = Ext.getCmp('qo-kregator-id-Feed-Tree').getTopToolbar().items.itemAt(i);
+ item.destroy();
+ }
+
+ // And now, we create the New ToolBar
+ var curTb = [];
+
+ Ext.each(this.tbFeedBtnCurrent, function(item) {
+
+ curTb.push(this.tbFeedBtnAvailable[item]);
+
+ }, this);
+
+ Ext.getCmp('qo-kregator-id-Feed-Tree').getTopToolbar().add(curTb);
+
+ // Build the sub Menu for contextMenu button if exist
+ if( Ext.getCmp('qo-kregator-contextmenu-btn') ) {
+
+ var node = this.PanelFeedTree.getSelectionModel().getSelectedNode();
+
+ if( node && node.attributes.type == 'folder' ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFolder());
+ }
+ if( node && node.attributes.type == 'file' ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFeed());
+ }
+ }
+ }, //buildTbFeed
+
+ selectFirstUnreadItems: function() {
+
+ var firstItem = false;
+ var firstItemUnread = false;
+ var rowIndex = 0;
+
+ // If there is no items in the dsItems, we reset the contextMenu-btn
+ if( this.dsItems.data.length === 0 ) {
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu('');
+ }
+
+ // We loop over items
+ for( var i = 0 ; i < this.dsItems.data.length ; i++ ) {
+
+ // State first items
+ if( i === 0 ) { firstItem = this.dsItems.data.items[i].data.id; }
+
+ // State first items unread
+ if( this.dsItems.data.items[i].data.s == 'n' ) {
+ firstItemUnread = this.dsItems.data.items[i].data.id;
+ rowIndex = i;
+ break;
+ }
+ }
+
+ if( firstItemUnread ) {
+
+ // Load first unread
+ this.PanelGridItem.getSelectionModel().selectRow(rowIndex);
+
+ this.loadItem(rowIndex);
+ } else if( firstItem ) {
+
+ // or load first item
+ this.PanelGridItem.getSelectionModel().selectRow(rowIndex);
+ this.loadItem(rowIndex);
+ }
+
+ }, // selectFirstUnreadItems
+
+ selectFirstUnseenFeed: function() {
+
+ var firstFeed = false;
+ var firstFolder = false;
+ var firstFeedUnread = false;
+
+ function _searchFeed(node){
+ var kids = node.childNodes;
+ var len = kids.length;
+ for (var i = 0; i < len; i++) {
+
+ if (kids[i].attributes.type == 'folder') {
+ if( !firstFolder ) { firstFolder = kids[i].id; }
+ }
+
+ if (kids[i].attributes.type == 'file') {
+
+ if( !firstFeed ) { firstFeed = kids[i].id; }
+
+ if( kids[i].attributes.unseen != '-' && kids[i].attributes.unseen > 0 ) {
+
+ if( !firstFeedUnread ) {
+ firstFeedUnread = kids[i].id;
+ break;
+ }
+ }
+
+ }
+ if( !firstFeedUnread ) { _searchFeed(kids[i]); }
+ }
+ }
+
+ _searchFeed(this.PanelFeedTree.getRootNode());
+
+ // Select Best Feed
+ if( firstFeedUnread ) {
+ this.PanelFeedTree.getNodeById(firstFeedUnread).select();
+ this.onClickFeed(this.PanelFeedTree.getNodeById(firstFeedUnread));
+ } else if( firstFeed ) {
+ this.PanelFeedTree.getNodeById(firstFeed).select();
+ this.onClickFeed(this.PanelFeedTree.getNodeById(firstFeed));
+ } else if( firstFolder ) {
+ this.PanelFeedTree.getNodeById(firstFolder).select();
+ this.onClickFeed(this.PanelFeedTree.getNodeById(firstFolder));
+ }
+ },
+
+ loadItem : function(rowIndex) {
+
+ var curArticle = this.dsItems.getAt(rowIndex).data.id;
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutLoadFeedArticle + this.dsItems.getAt(rowIndex).data.t);
+
+ this.markAsSeenUnseen('y', curArticle, this);
+ var r = Ext.get(this.PanelGridItem.getView().getRow(rowIndex));
+ r.replaceClass("qo-kregator-feed-unread", "qo-kregator-feed-read");
+
+ this.dsItemDesc.load({
+ params: {
+ 'id_item': curArticle
+ }
+ });
+
+ }, // loadItem
+
+ setPanelSize : function(Panel, Psize) {
+
+ switch (Panel) {
+ case 'tree_panel_width':
+ Ext.getCmp('qo-kregator-id-Feed-Tree').setWidth(Psize);
+ this.setFeedPanelWidth(Psize);
+ break;
+ case 'grid_panel_height':
+ Ext.getCmp('qo-kregator-id-gridFeed-panel').setHeight(Psize);
+ break;
+ case 'panel_south_height':
+ Ext.getCmp('qo-kregator-previewPanelSouth').setHeight(Psize);
+ break;
+ case 'panel_east_width':
+ Ext.getCmp('qo-kregator-previewPanelEast').setWidth(Psize);
+ break;
+ }
+
+ }, // setPanelSize
+
+ savePanelSizeState : function(Panel, Psize) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ panel: Panel,
+ panelsize: Psize,
+ what: 'set_panelsize_state'
+ }
+ });
+
+ }, //savePanelWidthState
+
+ setFeedPanelWidth : function(treeWidth) {
+
+ var bw = Ext.isBorderBox ? 0 : 2;
+ var widths = [(treeWidth-(this.columnUnseenWidth+this.columnTotalWidth+4)), this.columnUnseenWidth, this.columnTotalWidth];
+ var totalWidth = 0;
+ for (var i = 0; i < widths.length; i++) {
+ totalWidth += widths[i];
+ Ext.select("div.qo-kregator-x-tree-hd:nth-child(" + (i+1) + ")", false, "*TreeID*").setWidth(widths[i] - bw);
+ Ext.select("div.qo-kregator-x-tree-col:nth-child(" + (i+1) + ")", false, "*TreeID*").setWidth(widths[i] - bw);
+ this.PanelFeedTree.columns[i].width = widths[i];
+ }
+ this.PanelFeedTree.headers.setWidth(totalWidth);
+ this.PanelFeedTree.innerCt.setWidth(totalWidth);
+
+ }, //setFeedPanelWidth
+
+ setSummary : function(pressed) {
+
+ this.toggleSummary(pressed);
+ Ext.getCmp('qo-kregator-summary-btn-id').toggle(pressed);
+
+ }, // setSummary
+
+ toggleSummary : function(pressed) {
+
+ this.PanelGridItem.view.showSummary = pressed;
+ this.PanelGridItem.view.refresh();
+
+ // Save in DB
+ this.saveSummaryState(pressed);
+
+ }, // toggleSummary
+
+ saveSummaryState:function(state) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ showSummary: state,
+ what: 'set_summary_state'
+ }
+ });
+
+ }, // saveSummaryState
+
+ saveFolderState:function(_nodeID, expand) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodeID: _nodeID,
+ expand: expand,
+ what: 'set_folder_state'
+ },
+ success: function(response, options){},
+ failure: function(response, options){}
+ });
+
+ }, // saveFolderState
+
+ movePreview: function() {
+
+ if( this.ConfPreviewPane == 'bottom' ) {
+ // Set to right
+ this.ConfPreviewPane = 'right';
+ this.setPreviewPanePosition('right');
+
+ } else if( this.ConfPreviewPane == 'right' ) {
+ //set to hide
+ this.ConfPreviewPane = 'hide';
+ this.setPreviewPanePosition('hide');
+
+ } else if( this.ConfPreviewPane == 'hide' ) {
+ // set to bottom
+ this.ConfPreviewPane = 'bottom';
+ this.setPreviewPanePosition('bottom');
+
+ }
+
+ }, // movePreview
+
+ setPreviewPanePosition : function(position) {
+
+ var _title = this.PanelPreview.title;
+ var _content = this.PanelPreview.body.dom.innerHTML;
+
+ var right = Ext.getCmp('qo-kregator-previewPanelEast');
+ var bot = Ext.getCmp('qo-kregator-previewPanelSouth');
+ var btn = this.PanelGridItem.getTopToolbar().items.get(6);
+
+ switch (position) {
+ case 'bottom':
+ this.PanelPreview = bot;
+ this.PanelPreview.setTitle(_title);
+ this.PanelPreview.body.dom.innerHTML = _content;
+ this.PanelPreview.el.on('click',this.clickInterceptor, this);
+ right.hide();
+ bot.show();
+ bot.ownerCt.doLayout();
+ btn.setIconClass('qo-kregator-preview-bottom');
+ break;
+ case 'right':
+ this.PanelPreview = right;
+ this.PanelPreview.setTitle(_title);
+ this.PanelPreview.body.dom.innerHTML = _content;
+
+ this.PanelPreview.el.on('click',this.clickInterceptor, this);
+
+ bot.hide();
+ right.show();
+ right.ownerCt.doLayout();
+ btn.setIconClass('qo-kregator-preview-right');
+ break;
+ case 'hide':
+ this.PanelPreview.hide();
+ this.PanelPreview.ownerCt.doLayout();
+ btn.setIconClass('qo-kregator-preview-hide');
+ break;
+ }
+
+ this.savePreviewPanePosition(position);
+
+ }, // setPreviewPanePosition
+
+ savePreviewPanePosition:function(state) {
+
+ Ext.Ajax.request({
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ preview_pane: state,
+ what: 'set_previewpaneposition_state'
+ }
+ });
+
+ }, // savePreviewPanePosition
+
+ updateFeedInfo : function(id_feed, nb_unseen, nb_total) {
+
+ if( nb_total === 0 ) { nb_total = '-'; }
+
+
+ if( nb_unseen === 0 ) {
+ // Remove class bold
+ nb_unseen = '-';
+ this.PanelFeedTree.getNodeById(id_feed).ui.removeClass("qo-kregator-feed-Unseen");
+ Ext.get('qo-kregator-unSeen-'+id_feed).removeClass("qo-kregator-feed-Unseen");
+ } else {
+ // Add class bold
+ this.PanelFeedTree.getNodeById(id_feed).ui.addClass("qo-kregator-feed-Unseen");
+ Ext.get('qo-kregator-unSeen-'+id_feed).addClass("qo-kregator-feed-Unseen");
+ }
+
+ Ext.get('qo-kregator-unSeen-'+id_feed).dom.innerHTML = nb_unseen;
+ Ext.get('qo-kregator-Total-'+id_feed).dom.innerHTML = nb_total;
+
+ }, //updateFeedInfo
+
+ cleanFeed: function(){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutCleanItemsWait);
+
+ Ext.Ajax.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ day: this.ConfOldItemsDay,
+ what: 'clean_feed'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutCleanItemsOk + o.del_items);
+
+
+ }
+ else {
+
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutCleanItemsNok + o.msg);
+
+ }
+
+ // Register task for AutoRefresh Feed after cleanFeed
+ this.TaskSearchFeed = new Ext.util.DelayedTask(this.searchFeed, this);
+ this.TaskSearchFeed.delay(2000); // start after 2 secondes.
+ }
+ });
+
+ }, // cleanFeed
+
+ clickInterceptor : function(e, target, options){
+
+ e.preventDefault();
+ e.stopEvent();
+
+ var delai = new Date();
+ var curClick = delai.getTime();
+
+ if (this.LastClick === 0) {
+ this.LastClick = curClick - 51;
+ }
+
+ var diff = (curClick - this.LastClick);
+
+ if (target.href) {
+ if (diff > 50) {
+ this.LastClick = curClick;
+ var uniq = Ext.id();
+ this.openInTab(uniq, target.href, target.href);
+ }
+ }
+
+ }, // clickInterceptor
+
+ /********
+ *
+ * ContextMenu
+ *
+ ********/
+
+ createContextMenuTreeFeed: function() {
+
+ var node = this.PanelFeedTree.getNodeById(this.curNodeId);
+
+ var menu = new Ext.menu.Menu({
+ items: [{
+ text: QoKregator.TreeFeedMarkAsRead,
+ iconCls: 'qo-kregator-icon-mark-all-as-read',
+ scope: this,
+ handler: function(el, ev){
+ this.markAllAsRead(node, this);
+ }
+ }, new Ext.menu.Separator(), {
+ scope: this,
+ text: QoKregator.TreeFeedLoadFeed,
+ iconCls:'qo-kregator-refresh-btn',
+ handler: function(n, ev){
+ this.updateFeed(node.attributes.text, node.attributes.id, node.id, 'off', -1);
+ }
+ }, new Ext.menu.Separator(), {
+ scope: this,
+ text: QoKregator.TreeFeedOpenSite,
+ iconCls: 'qo-kregator-open-site-btn',
+ handler: function(n, ev){
+ this.openInTab(node.attributes.id, node.attributes.text, node.attributes.url);
+ }
+ }, new Ext.menu.Separator(), {
+ scope: this,
+ text: QoKregator.TreeFeedMod,
+ iconCls: 'qo-kregator-icon-mod-feed',
+ handler: function(n, ev){
+ this.showModFeed(node);
+ }
+ }, {
+ scope: this,
+ text: QoKregator.TreeFeedDel,
+ iconCls: 'qo-kregator-icon-del-feed',
+ handler: function(n, ev){
+ this.showDelItemArbre(node);
+ }
+ }]
+ });
+ return menu;
+ }, //createContextMenuTreeFeed
+
+ createContextMenuTreeFolder: function() {
+
+ var node = this.PanelFeedTree.getNodeById(this.curNodeId);
+
+ var menu = new Ext.menu.Menu({
+ items: [{
+ scope: this,
+ text: QoKregator.TreeAddNewFeed,
+ iconCls:'qo-kregator-icon-add-feed',
+ handler: function(n, ev){
+ this.showAddFeed(node.id);
+ }
+ }, {
+ scope: this,
+ text: QoKregator.TreeAddNewFolder,
+ iconCls: 'qo-kregator-icon-add-folder',
+ handler: function(n, ev){
+ this.showAddFolder(node.id);
+ }
+ }, '-', {
+ scope: this,
+ text: QoKregator.TreeFolderMod,
+ iconCls: 'qo-kregator-icon-mod-folder',
+ handler: function(n, ev){
+ // Start Edit
+ this.PanelFeedTreeEditor.editNode = node;
+ this.PanelFeedTreeEditor.startEdit(node.ui.getAnchor(), node.text);
+ }
+ }, {
+ scope: this,
+ text: QoKregator.TreeFolderDel,
+ iconCls: 'qo-kregator-icon-del-folder',
+ handler: function(n, ev){
+ this.showDelItemArbre(node);
+ }
+ }]
+ });
+ return menu;
+
+ }, //createContextMenuTreeFolder
+
+ onContextMenuFeed: function(node, ev) {
+
+ ev.preventDefault();
+ ev.stopEvent();
+
+ var actuNode = this.PanelFeedTree.getSelectionModel().getSelectedNode();
+
+ if (node != actuNode) {
+ node.select();
+ this.onClickFeed(node, ev);
+ }
+
+ this.curNodeId = node.id;
+ var nodeType = node.attributes.type;
+
+ if (this.curNodeId !== 0) {
+ if (nodeType == 'file') {
+ menu = this.createContextMenuTreeFeed();
+ menu.showAt(ev.getXY());
+ }
+
+ if (nodeType == 'folder') {
+ menu = this.createContextMenuTreeFolder();
+ menu.showAt(ev.getXY());
+ }
+ }
+ }, // onContextMenuFeed
+
+ createContextItemFeed : function() {
+
+ var rowSelected = this.PanelGridItem.getSelections(); // All row selected
+ var RowToDel = ''; // construct the string containing all row to delete
+
+ var isImportant = false; //Is a row is important into all rows selected ?
+ var isUnseen = false; //Is a row is unseen into all rows selected ?
+
+ var menu = new Ext.menu.Menu();
+
+ for (var j = 0; j < rowSelected.length; j++) {
+
+ RowToDel += rowSelected[j].id + ',';
+ if (rowSelected[j].data.i == 'y') {
+ isImportant = true;
+ }
+ if (rowSelected[j].data.s == 'n') {
+ isUnseen = true;
+ }
+
+ }
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemOpenInTab,
+ iconCls: 'qo-kregator-open-inTab-btn',
+ handler: function(){
+ for (var i = 0; i < rowSelected.length; i++) {
+
+ var _node = this.dsItems.getById(rowSelected[i].id);
+ var _link = _node.data.u;
+ var _title = _node.data.t;
+
+ this.openInTab('items-' + rowSelected[i].id, _title, _link);
+ }
+ }
+ });
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemOpenInWin,
+ iconCls: 'qo-kregator-open-site-btn',
+ handler: function(){
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.openInWindow(rowSelected[i].id);
+ }
+ }
+ });
+
+ menu.addSeparator();
+
+ var varMenuImportant;
+
+ if (isImportant) {
+
+ varMenuImportant = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemRemoveMarkImportant,
+ iconCls: 'qo-kregator-icon-unmark-as-important',
+ handler: function(){
+
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsImportant('n', rowSelected[i].id);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.removeClass("qo-kregator-feed-important");
+ }
+
+ }
+ });
+ }
+ else {
+
+ varMenuImportant = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAsImportant,
+ iconCls: 'qo-kregator-icon-mark-as-important',
+ handler: function(){
+
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsImportant('y', rowSelected[i].id);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.addClass("qo-kregator-feed-important");
+
+ }
+ }
+ });
+ }
+
+ var varMenuUnseen;
+
+ if( isUnseen ) {
+
+ varMenuUnseen = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAsRead,
+ iconCls: 'qo-kregator-icon-mark-as-read',
+ handler: function(){
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsSeenUnseen('y', rowSelected[i].id, this);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.addClass("qo-kregator-feed-read");
+ p.removeClass("qo-kregator-feed-unread");
+
+ }
+ }
+ });
+
+ } else {
+
+ varMenuUnseen = new Ext.menu.Item({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAsUnRead,
+ iconCls: 'qo-kregator-icon-mark-as-unread',
+ handler: function(){
+
+ for (var i = 0; i < rowSelected.length; i++) {
+ this.markAsSeenUnseen('n', rowSelected[i].id, this);
+
+ var rowId = rowSelected[i].id;
+ var p = Ext.get(this.PanelGridItem.getView().getRow(this.dsItems.indexOfId(rowId)));
+ p.removeClass("qo-kregator-feed-read");
+ p.addClass("qo-kregator-feed-unread");
+ }
+ }
+ });
+
+ }
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemMarkAs,
+ menu: {
+ items: [varMenuImportant, new Ext.menu.Separator(),varMenuUnseen]
+ }
+ });
+
+ menu.addSeparator();
+
+ menu.add({
+ scope: this,
+ text: QoKregator.FeedGridItemDel,
+ iconCls: 'qo-kregator-icon-del-feed',
+ handler: function(grid, rowIndex, ev){
+
+ var boxTitle='', boxMessage='';
+
+ // How many rows to delete ?
+ if( rowSelected.length == 1 ) {
+ boxTitle = QoKregator.BoxConfirmDelItemTitle;
+ boxMessage = QoKregator.BoxConfirmDelItemMessage;
+ } else {
+ boxTitle = QoKregator.BoxConfirmDelItemsTitle;
+ boxMessage = QoKregator.BoxConfirmDelItemsMessage;
+ }
+
+
+ // Show confirm box
+ Ext.Msg.show({
+ scope: this,
+ title:boxTitle,
+ msg: boxMessage,
+ buttons: Ext.Msg.YESNOCANCEL,
+ fn: function(btn) {
+
+ if( btn == 'yes' ) {
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutItemDel);
+
+ // Update DB
+ var delItem = new Ext.data.Connection();
+ delItem.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_item: RowToDel,
+ what: 'del_items'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutItemDelOk);
+
+ // Delete ligne(s)
+ for (var i = 0; i < rowSelected.length; i++) {
+
+ var _nodeID = this.dsItems.getById(rowSelected[i].id).data.id_f;
+ var unSeen = o.message.Node[_nodeID].unseen;
+ var total = o.message.Node[_nodeID].total;
+ this.dsItems.remove(this.dsItems.getById(rowSelected[i].id));
+ this.updateFeedInfo(_nodeID, unSeen, total);
+
+ }
+
+ // Focus & Display next items
+ if( this.dsItems.data.items.length > 0 ) {
+ this.loadItem(0);
+ this.PanelGridItem.getSelectionModel().selectRow(0);
+ } else {
+ // Clear Preview Panel
+ this.PanelPreview.setTitle(QoKregator.PreviewTitle);
+ this.PanelPreview.body.dom.innerHTML = '';
+ }
+
+ },
+ failure: function(form, action){
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutItemDelNok);
+ }
+ });
+ }
+ },
+ icon: Ext.MessageBox.QUESTION
+ });
+ }
+ });
+ return menu;
+ }, // CreateContextItemFeed
+
+ onContextItemFeed: function(grid, rowIndex, ev){
+
+ ev.stopEvent();
+
+ // Get all rows selected, if any
+ var rowSelected = this.PanelGridItem.getSelections();
+
+ // Get the single row selected
+ var contextRowID = this.dsItems.getAt(rowIndex).id;
+
+ // If right-click without a rows selected, we auto-select the rows over the right-click
+ var asSelect = false;
+ for (var i = 0; i < rowSelected.length; i++) {
+ if (contextRowID == rowSelected[i].id) {
+ asSelect = true;
+ }
+ }
+
+ if (!asSelect) {
+ var v = this.PanelGridItem.getSelectionModel();
+ v.selectRow(rowIndex);
+ rowSelected = this.PanelGridItem.getSelections();
+ }
+
+ var menu;
+ menu = this.createContextItemFeed();
+ menu.showAt(ev.getXY());
+
+ }, // onContextItemFeed
+
+ markAsImportant: function(typeMark, rowId){
+
+ var importantStatut = this.dsItems.getById(rowId).data.i;
+
+ var _typeMark = typeMark;
+ var _rowId = rowId;
+
+ if ((importantStatut == 'y' && _typeMark == 'n') || (importantStatut == 'n' && _typeMark == 'y')) {
+
+ var saveImportant = new Ext.data.Connection();
+ saveImportant.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_item: _rowId,
+ typeMark: _typeMark,
+ what: 'save_important'
+ },
+ success: function(){
+
+ if (_typeMark == 'y') {
+ this.dsItems.getById(_rowId).data.i = 'y';
+ } else if (_typeMark == 'n') {
+ this.dsItems.getById(_rowId).data.i = 'n';
+ }
+
+ // ReBuilt the contextMenu-btn
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu(this.createContextItemFeed());
+
+ }
+ });
+ }
+ }, //markAsImportant
+
+ markAsSeenUnseen: function(typeMark, rowId, scope){
+
+ this.scope = scope;
+
+ var seenStatut = this.dsItems.getById(rowId).data.s;
+ var _typeMark = typeMark;
+ var _rowId = rowId;
+
+ // Modify if necessary
+ if ((seenStatut == 'y' && _typeMark == 'n') || (seenStatut == 'n' && _typeMark == 'y')) {
+
+ var saveSeenUnseen = new Ext.data.Connection();
+ saveSeenUnseen.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_item: _rowId,
+ typeMark: _typeMark,
+ what: 'save_seenUnseen'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ var node = this.PanelFeedTree.getNodeById(o.nodeID);
+ node.attributes.unseen = o.unSeen;
+ node.attributes.total = o.total;
+
+ // Update client data
+ if (_typeMark == 'y') {
+ this.dsItems.getById(_rowId).data.s = 'y';
+ } else if (_typeMark == 'n') {
+ this.dsItems.getById(_rowId).data.s = 'n';
+ }
+
+ this.updateFeedInfo(node.id, o.unSeen, o.total);
+
+ // ReBuilt the contextMenu-btn
+ Ext.getCmp('qo-kregator-contextmenu-news-btn').setMenu(this.createContextItemFeed());
+
+ }
+ }
+ });
+ }
+ }, //markAsSeenUnseen
+
+ markAllAsRead: function(node, scope) {
+
+ var nb = scope.dsItems.data.length;
+
+ for (var i = 0; i < nb; i++) {
+ var r = Ext.get(scope.PanelGridItem.getView().getRow(i));
+ r.replaceClass("qo-kregator-feed-unread", "qo-kregator-feed-read");
+ }
+ scope.markAsSeenDB(node.id, scope);
+ node.ui.removeClass("qo-kregator-feed-Unseen");
+
+ },
+
+ markAsSeenDB: function(_nodeID, scope){
+
+ this.scope = scope;
+
+ var saveSeenUnseen = new Ext.data.Connection();
+ saveSeenUnseen.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_feed: _nodeID,
+ what: 'save_seenDB'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ var node = this.PanelFeedTree.getNodeById(o.nodeID);
+ node.attributes.unseen = o.unSeen;
+ node.attributes.total = o.total;
+ this.updateFeedInfo(node.id, o.unSeen, o.total);
+
+ }
+ }
+ });
+
+ }, //markAsSeenDB
+
+ openInWindow: function(rowId){
+ var node = this.dsItems.getById(rowId);
+ var link = node.data.u;
+ window.open(link, 'win' + rowId);
+ }, //openInWindow
+
+ openInTab: function(feedID, title, link){
+
+ var TabExist = this.PanelCenter.findById('qo-kregator-tab-' + feedID);
+
+ if (TabExist) {
+ this.PanelCenter.activate('qo-kregator-tab-' + feedID);
+ }
+ else {
+
+ this.PanelCenter.add({
+ id: 'qo-kregator-tab-' + feedID,
+ linkTab: link,
+ closable: true,
+ title: Ext.util.Format.ellipsis(title, 20),
+ layout: 'fit',
+ border: true,
+ html: '<div class="qo-kregator-preview-content"><iframe width="100%" height="100%" frameborder="0" src="' + link + '" /></div>'
+
+ });
+
+ this.PanelCenter.activate('qo-kregator-tab-' + feedID);
+
+ }
+
+ }, //openInTab
+
+ onClickFeed: function(node, ev){
+
+ this.curNodeId = node.id;
+
+ var nodeType = node.attributes.type;
+
+ this.PanelCenter.activate('qo-kregator-main');
+
+ this.gridClearFilter();
+
+ // Delete data
+ this.dsItems.removeAll();
+
+ if (nodeType == 'folder') {
+
+ this.PanelPreview.body.dom.innerHTML = '';
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutLoadFolder + " " + node.attributes.text);
+
+ var ColIndex = this.PanelGridItem.getColumnModel().getIndexById('feed');
+ this.PanelGridItem.getColumnModel().setHidden(ColIndex, false);
+
+ // Set tab title
+ Ext.getCmp('qo-kregator-main').setTitle(Ext.util.Format.ellipsis(node.attributes.text, 20));
+ this.linkDefaultTab = '';
+ this.curFeedId = '*';
+
+ } else {
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutLoadFeed + " " + node.attributes.text);
+
+ var _ColIndex = this.PanelGridItem.getColumnModel().getIndexById('feed');
+ this.PanelGridItem.getColumnModel().setHidden(_ColIndex, true);
+
+ Ext.getCmp('qo-kregator-main').setTitle(Ext.util.Format.ellipsis(node.attributes.text, 20));
+ this.linkDefaultTab = node.attributes.url;
+ this.curFeedId = node.id;
+
+ var image;
+
+ if ( node.attributes.image ) {
+ image = "<img src=\"" + node.attributes.image + "\" alt=\"\" />";
+ } else {
+ image = '';
+ }
+
+ var content = '<div class="qo-kregator-feed-info">' +
+ '<div class="qo-kregator-item-date"></div>' +
+ '<div class="qo-kregator-item-title">' +
+ node.attributes.desc +
+ '</div>' +
+ '<div class="qo-kregator-item-author"><a href="' +
+ node.attributes.url +
+ '" Ext:qtip="' +
+ QoKregator.previewLoadInNewPage +
+ '" target="_blank">' +
+ node.attributes.url +
+ '</a></div>' +
+ '</div>' +
+ '<div class="qo-kregator-feed-content">' +
+ '<div class="qo-kregator-feed-image">' +
+ image +
+ '</div>' +
+ '</div>';
+
+ this.PanelPreview.body.dom.innerHTML = content;
+
+ }
+
+ this.PanelPreview.setTitle(node.attributes.text);
+
+ this.dsItems.baseParams = {
+ 'id_feed': this.curFeedId,
+ 'id_node': this.curNodeId
+ };
+
+ this.dsItems.load({
+ params: {
+ start: 0,
+ limit: 25
+ }
+ });
+
+
+ if (nodeType == 'folder') {
+
+ //Handle ContextMenu
+ if( Ext.getCmp('qo-kregator-contextmenu-btn') ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFolder());
+ }
+
+ } else {
+
+ //Handle ContextMenu
+ if( Ext.getCmp('qo-kregator-contextmenu-btn') ) {
+ Ext.getCmp('qo-kregator-contextmenu-btn').setMenu(this.createContextMenuTreeFeed());
+ }
+
+ }
+
+ }, //onClickFeed
+
+ showDelItemArbre: function(node){
+
+ var titre, message, typeObj;
+
+ if (node.attributes.type == 'file') {
+ titre = QoKregator.BoxConfirmDelFeedTitle;
+ message = QoKregator.BoxConfirmDelFeedMessage + node.attributes.text + ' ?';
+ }
+
+ if (node.attributes.type == 'folder') {
+ titre = QoKregator.BoxConfirmDelFolderTitle;
+ message = String.format(QoKregator.BoxConfirmDelFolderMessage, node.attributes.text);
+ }
+
+ Ext.Msg.show({
+ scope: this,
+ icon: Ext.MessageBox.QUESTION,
+ title: titre,
+ msg: message,
+ buttons: Ext.MessageBox.YESNO,
+ fn: function(btn){
+ if (btn == 'yes') {
+ if (node.attributes.type == 'file') {
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutDelFeed + node.attributes.text + '...');
+ }
+ else {
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutDelFolder + node.attributes.text + '...');
+ }
+
+ // Update
+ var delNode = new Ext.data.Connection();
+ delNode.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_node: node.id,
+ what: 'del_nodes'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutDone);
+
+ //Del node
+ var curNode = this.PanelFeedTree.selModel.selNode;
+
+ //Animation
+ Ext.fly(curNode.ui.elNode).switchOff({
+ easing: 'easeIn',
+ duration: .3,
+ remove: false,
+ useDisplay: false,
+ scope: this,
+ callback: function() { curNode.parentNode.removeChild(curNode) ; }
+ });
+
+ // Return to initial state
+ Ext.getCmp('qo-kregator-main').setTitle(QoKregator.FeedGridTabTitle);
+ this.linkDefaultTab = '';
+ this.dsItems.removeAll();
+
+ this.PanelPreview.setTitle(QoKregator.PreviewTitle);
+ this.PanelPreview.body.dom.innerHTML = '';
+
+ }
+ else {
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutDelItemNok);
+ }
+
+ }
+ });
+
+ }
+ }
+ });
+
+ }, // showDelItemArbre
+
+ showAddFeed: function(_nodeID){
+
+ function validForm(scope) {
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutAddNewFeed);
+
+ var waitAddFeed = Ext.MessageBox.show({
+ msg: QoKregator.StatutAddNewFeedWait,
+ progressText: QoKregator.StatutAddNewFeedWaitInProgress,
+ width: 300,
+ wait: true,
+ waitConfig: {
+ interval: 200
+ }
+ });
+
+ FormAddFeed.form.submit({
+ scope: scope,
+ url: scope.app.connection,
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodeID: _nodeID,
+ what: 'add_feed'
+ },
+ success: function(form, action){
+
+ // Add this new node to tree
+ var o = action.result;
+
+ var nodeToAppend = new Ext.tree.TreeNode({
+ id:o.id,
+ text:o.text,
+ url: o.url,
+ url_feed: o.url_feed,
+ type: o.type,
+ desc: o.desc,
+ image: o.image,
+ view: o.view,
+ nodeID: o.nodeID,
+ unseen:o.unseen,
+ total:o.total,
+ uiProvider:Ext.tree.KregaColumnNodeUI,
+ leaf:true,
+ icon:o.icon,
+ iconCls:'',
+ refreshCycle:'on'
+ });
+
+ if( o.nodeID === "0" ) { scope.PanelFeedTree.getRootNode().appendChild(nodeToAppend); }
+ else { scope.PanelFeedTree.getNodeById(o.nodeID).appendChild(nodeToAppend); }
+
+ scope.PanelFeedTree.expandAll();
+
+ var newNode = scope.PanelFeedTree.getNodeById(o.id);
+ newNode.select();
+ scope.onClickFeed(newNode);
+
+ scope.updateFeedInfo(o.id, o.unseen, o.total);
+
+ FormAddFeed.form.reset();
+ waitAddFeed.hide();
+ winAddFeed.close();
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFeedOk);
+ },
+
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-error', QoKregator.StatutAddNewFeedNok + action.result.message);
+
+ waitAddFeed.hide();
+ Ext.get('newFeed').focus();
+
+ }
+ });
+
+ } //addFeed
+
+ var FormAddFeed = new Ext.FormPanel({
+ labelWidth: 40,
+ frame: true,
+ bodyStyle: 'padding:5px',
+ width: 350,
+ items: [{
+ xtype:'textfield',
+ fieldLabel: QoKregator.BoxAddFeedUrl,
+ name: 'newFeed',
+ id: 'newFeed',
+ width: 300,
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(this);
+ }
+ }
+ }
+ },{
+ xtype: 'checkbox',
+ hideLabel: true,
+ boxLabel: QoKregator.BoxModFeedView,
+ name: 'view',
+ checked: false
+ }]
+ });
+
+ var winAddFeed = new Ext.Window({
+ animateEl: 'qo-kregator-add-feed-btn',
+ title: QoKregator.BoxAddFeedTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-add-feed',
+ width: 430,
+ height: 160,
+ closeAction: 'close',
+ bodyStyle: 'padding:5px',
+ plain: true,
+ items: FormAddFeed,
+
+ buttons: [{
+ text: QoKregator.BoxAddFeedSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(this);
+ }
+ }, {
+ text: QoKregator.BoxAddFeedCancelBtn,
+ handler: function(){
+ winAddFeed.close();
+ }
+ }]
+ });
+
+ winAddFeed.show(this);
+
+ var tmp = new Ext.util.DelayedTask(function() { Ext.getCmp('newFeed').focus(); }, this);
+ tmp.delay(200);
+
+ }, //showAddFeed
+
+ showConf: function() {
+
+ function in_array(array, it) {
+
+ for( var i=0; i < array.length; i++ ) {
+
+ if( array[i] == it ) { return 1; }
+
+ }
+ return 0;
+
+ } // array_diff
+
+ var _tbFeedCurrent=[], _tbFeedDisponible=[];
+
+ //Actual tbFeed
+ Ext.each(this.tbFeedBtnCurrent, function(item) {
+
+ _tbFeedCurrent.push([item, '<div class="'+this.tbFeedBtnAvailable[item].iconCls+'-conf">'+((typeof this.tbFeedBtnAvailable[item].tooltip == 'object' ) ? this.tbFeedBtnAvailable[item].tooltip.title : this.tbFeedBtnAvailable[item].tooltip) +'</div>']);
+
+ }, this);
+
+ //Disponible tbFeed
+ Ext.each(this.tbFeedBtnAvailable, function(item) {
+
+ if( in_array(this.tbFeedBtnCurrent,item) === 0 ) {
+
+ _tbFeedDisponible.push([item, '<div class="'+this.tbFeedBtnAvailable[item].iconCls+'-conf">'+((typeof this.tbFeedBtnAvailable[item].tooltip == 'object' ) ? this.tbFeedBtnAvailable[item].tooltip.title : this.tbFeedBtnAvailable[item].tooltip) +'</div>']);
+
+ }
+
+ }, this);
+
+ var FormConf = new Ext.FormPanel({
+ labelWidth: 75,
+ border:false,
+ autoWidth: true,
+ items: [{
+ xtype:'tabpanel',
+ deferredRender:false,
+ activeTab: 0,
+ defaults:{autoHeight:true, bodyStyle:'padding:10px'},
+ items:[{
+ title:QoKregator.WinConfTab0,
+ layout:'form',
+ items: [{
+ layout:'column',
+ border: false,
+ items:[{
+ columnWidth:0.5,
+ layout: 'form',
+ border: false,
+ items: [{
+ //1
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle0,
+ height: 60,
+ labelWidth: 100,
+ items: [
+ new Ext.ux.form.Spinner({
+ strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue: '1', maxValue: '100'}),
+ fieldLabel: QoKregator.WinConfFieldSetLabel0,
+ name: 'refresh_feed',
+ editable: false,
+ width: 50,
+ value: this.ConfRefreshFeed
+ })
+ ]
+ },{
+ //2
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle1,
+ height: 60,
+ checkboxToggle: true,
+ checkboxName: 'old_items',
+ collapsed: !this.ConfOldItems,
+ labelWidth: 100,
+ items: [
+ new Ext.ux.form.Spinner({
+ strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue: '1', maxValue: '100'}),
+ fieldLabel: QoKregator.WinConfFieldSetLabel1,
+ name: 'old_items_day',
+ editable: false,
+ width: 50,
+ value: this.ConfOldItemsDay
+ })
+ ]
+ },{
+ xtype:'checkbox',
+ checked: (this.ConfshowStatusBar == 'on') ? true : false,
+ hideLabel: true,
+ boxLabel: QoKregator.WinConfFieldSetTitle5,
+ name: 'showStatusBar'
+ }]
+ },{
+ columnWidth:0.5,
+ layout: 'form',
+ border: false,
+ items: [{
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle3,
+ height: 60,
+ labelWidth: 100,
+ layout:'absolute',
+ items: [{
+ xtype: 'slider',
+ width: 150,
+ value: this.ConfContentFontSize,
+ increment: 1,
+ minValue: 8,
+ maxValue: 20,
+ listeners: {
+ change: function(s, NewValue) {
+ Ext.getCmp('showSlider').setValue(NewValue);
+ }
+ }
+ },{
+ xtype: 'textfield',
+ readOnly: true,
+ id:'showSlider',
+ name: 'ContentFontSize',
+ width: 24,
+ value: this.ConfContentFontSize,
+ x: 154,
+ y: 0
+ }]
+ },{
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: QoKregator.WinConfFieldSetTitle4,
+ height: 60,
+ labelWidth: 100,
+ items: [{
+ xtype: 'combo',
+ hideLabel: true,
+ store: [['FullScreen', QoKregator.WinConfFieldSetLabel41],['Window', QoKregator.WinConfFieldSetLabel42], ['Minimized', QoKregator.WinConfFieldSetLabel43]],
+ forceSelection: true,
+ triggerAction: 'all',
+ hiddenName: 'openMode',
+ mode: 'local',
+ value: this.ConfOpenMode,
+ editable:false,
+ width: 100
+
+ }]
+ },{
+ xtype: 'fieldset',
+ anchor:'95%',
+ title: 'Date/Time format',
+ height: 90,
+ labelWidth: 70,
+ items: [{
+ xtype: 'combo',
+ fieldLabel: 'Date ',
+ store: [
+ ['d/m/y', '31/12/99'],
+ ['d/m/Y', '31/12/1999'],
+ ['y-m-d', '99-12-31'],
+ ['Y-m-d', '1999-12-31']
+ ],
+ forceSelection: true,
+ triggerAction: 'all',
+ hiddenName: 'dateFormat',
+ mode: 'local',
+ value: this.ConfDateFormat,
+ editable:false,
+ width: 120
+
+ },{
+ xtype: 'combo',
+ fieldLabel: 'Date/Time ',
+ store: [
+ ['d/m/y, H:i', '31/12/99, 14:15'],
+ ['d/m/Y, H:i', '31/12/1999, 14:15'],
+ ['y-m-d, H:i', '99-12-31, 14:15'],
+ ['Y-m-d, H:i', '1999-12-31, 14:15']
+ ],
+ forceSelection: true,
+ triggerAction: 'all',
+ hiddenName: 'dateTimeFormat',
+ mode: 'local',
+ value: this.ConfDateTimeFormat,
+ editable:false,
+ width: 120
+
+ }]
+ }]
+ }]
+ }]
+ },{
+ title : QoKregator.WinConfTab1,
+ layout:'form',
+ defaults: {width: 420},
+ items: [{
+ xtype:"itemselector",
+ id: "qo-kregator-conf-tb-feed",
+ name:"tbFeedBtn",
+ hideLabel: true,
+ dataFields:["code", "desc"],
+ fromData: _tbFeedDisponible,
+ toData:_tbFeedCurrent,
+ msWidth:200,
+ msHeight:110,
+ valueField:"code",
+ displayField:"desc",
+ imagePath:"system/modules/qo-kregator/ux/MultiselectItemSelector/",
+ toLegend: QoKregator.WinConfTab1Selected,
+ fromLegend: QoKregator.WinConfTab1Available
+ }]
+ }]
+ }],
+ buttons: [{
+ text: QoKregator.WinConfSaveBtn,
+ scope: this,
+ handler: function(){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutConfWait);
+
+ FormConf.form.submit({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ what: 'mod_user_conf'
+ },
+ success: function(form, action){
+
+ var o = action.result;
+
+ this.ConfRefreshFeed = o.refresh_feed;
+ this.ConfOldItems = o.old_items;
+ this.ConfOldItemsDay = o.old_items_day;
+ this.ConfshowStatusBar = o.showStatusBar;
+ this.tbFeedBtnCurrent = o.tbFeedBtn;
+ this.ConfContentFontSize = o.ContentFontSize;
+ this.ConfOpenMode = o.openMode;
+
+ this.ConfDateTimeFormat = o.dateTimeFormat;
+ this.ConfDateFormat = o.dateFormat;
+
+ // Update ContentFontSize for the current preview
+ this.setContentFontSize();
+
+ // Update conf for the statusBar
+ this.showHideStatusBar();
+
+ // Update tbFeedBtn
+ this.buildTbFeed();
+
+ // Redraw the grid to handle dateFormat Change
+ this.PanelGridItem.getColumnModel().getColumnById('date').renderer = this.renderDate.createDelegate(this, [this.ConfDateTimeFormat], 1);
+ this.PanelGridItem.getView().refresh();
+
+ this.setStatusBar('qo-kregator-done', QoKregator.StatutConfOk);
+
+ winConf.close();
+ },
+ failure: function(form, action){
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutConfNok);
+ }
+ });
+
+ }
+ },{
+ text: QoKregator.WinConfCancelBtn,
+ handler: function(){
+ winConf.close();
+ }
+ }]
+
+ });
+
+ var winConf = new Ext.Window({
+ scope: this,
+ title: QoKregator.WinConfTitle,
+ layout: 'fit',
+ modal: true,
+ closeAction: 'close',
+ iconCls: 'qo-kregator-icon-conf',
+ width: 500,
+ height: 350,
+ plain: true,
+ items: FormConf
+ });
+
+ winConf.show();
+ },
+
+ showModFeed: function(node){
+
+ function validForm(node, scope) {
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutModFeed);
+
+ FormModFeed.form.submit({
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ id_feed: node.attributes.id,
+ what: 'mod_feed'
+ },
+ scope: scope,
+ url: scope.app.connection,
+ success: function(form, action){
+
+ var o = action.result;
+
+ // Update tree
+ node.setText(o.nom);
+ node.attributes.view = o.view;
+ node.attributes.refreshCycle = o.refreshCycle;
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutModFeedOk);
+ scope.winModFeed.hide();
+ },
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-error', QoKregator.StatutModFeedNok);
+ }
+ });
+
+ } // validForm
+
+ var viewValue = false;
+ if (node.attributes.view == 'site') {
+ viewValue = true;
+ }
+
+ var refreshCycleValue = false;
+ if (node.attributes.refreshCycle == 'off') {
+ refreshCycleValue = true;
+ }
+
+ var FormModFeed = new Ext.FormPanel({
+ labelWidth: 40,
+ frame: true,
+ bodyStyle: 'padding:5px',
+ items: [{
+ xtype: 'fieldset',
+ title: node.text,
+ autoHeight: true,
+ defaultType: 'textfield',
+ items: [{
+ fieldLabel: QoKregator.BoxModFeedName,
+ name: 'modFeed',
+ value: node.text,
+ width: 300,
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(node, this);
+ }
+ }
+ }
+ }, {
+ fieldLabel: 'Url ',
+ name: 'url',
+ readOnly: true,
+ value: node.attributes.url_feed,
+ width: 300,
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(node, this);
+ }
+ }
+ }
+ }]
+ }, {
+ xtype: 'fieldset',
+ title: QoKregator.BoxModFeedOption,
+ autoHeight: true,
+ defaultType: 'checkbox',
+ items: [{
+ hideLabel: true,
+ boxLabel: QoKregator.BoxModFeedView,
+ name: 'view',
+ checked: viewValue
+ },{
+ hideLabel: true,
+ boxLabel: 'Exclude from refresh cycle',
+ name: 'refreshCycle',
+ checked: refreshCycleValue
+ }]
+ }]
+ });
+
+ this.winModFeed = new Ext.Window({
+ scope: this,
+ title: QoKregator.BoxModFeedTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-mod-feed',
+ width: 450,
+ height: 280,
+ closeAction: 'hide',
+ bodyStyle: 'padding:5px',
+ plain: true,
+ items: FormModFeed,
+
+ buttons: [{
+ text: QoKregator.BoxModFeedSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(node, this);
+ }
+ }, {
+ scope:this,
+ text: QoKregator.BoxModFeedCancelBtn,
+ handler: function(){
+ this.winModFeed.hide();
+ }
+ }]
+ });
+ this.winModFeed.show(this);
+ }, //showModFeed
+
+ showAddFolder: function(_nodeID){
+
+ function validForm(scope) {
+
+ // Disable btn
+ Ext.getCmp('qo-kregator-btnOK-id-add-folder').disable();
+ Ext.getCmp('qo-kregator-btnCANCEL-id-add-folder').disable();
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutAddNewFolder);
+
+ FormAddFolder.form.submit({
+ scope: scope,
+ url: scope.app.connection,
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ nodeID: _nodeID,
+ what: 'add_folder'
+ },
+ success: function(form, action){
+
+ var o = action.result, node;
+
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFolderOk);
+
+ // Add this new node to tree
+
+ if( o.nodeID !== "0" ) {
+
+ scope.PanelFeedTree.getNodeById(o.nodeID).appendChild(new Ext.tree.TreeNode({
+ text: o.name,
+ id: o.id,
+ leaf: false,
+ iconCls: 'qo-kregator-feed-folder',
+ type: 'folder',
+ children:[],
+ nodeID: o.nodeID
+ }));
+
+ } else {
+
+ scope.PanelFeedTree.getRootNode().appendChild(new Ext.tree.TreeNode({
+ text: o.name,
+ id: o.id,
+ leaf: false,
+ iconCls: 'qo-kregator-feed-folder',
+ type: 'folder',
+ children:[],
+ nodeID: o.nodeID
+ }));
+
+ }
+
+ var newNode = scope.PanelFeedTree.getNodeById(o.id);
+ newNode.select();
+
+ FormAddFolder.form.reset();
+ Ext.getCmp('qo-kregator-btnOK-id-add-folder').enable();
+ Ext.getCmp('qo-kregator-btnCANCEL-id-add-folder').enable();
+ winAddFolder.close();
+ },
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFolderNok);
+ }
+ });
+
+ } //validForm
+
+ var FormAddFolder = new Ext.FormPanel({
+ labelWidth: 45,
+ id: 'form-add-folder',
+ frame: true,
+ bodyStyle: 'padding:5px 5px 0',
+ width: 350,
+ defaults: {width: 280},
+ items: [{
+ xtype: 'textfield',
+ fieldLabel: QoKregator.BoxAddFolderName,
+ name: 'newFolder',
+ id: 'newFolder',
+ enableKeyEvents: true,
+ listeners: {
+ scope: this,
+ keyup: function(field, e) {
+ if( e.getCharCode() == e.ENTER ) {
+ validForm(this);
+ }
+ }
+ }
+ }]
+ });
+
+ var winAddFolder = new Ext.Window({
+ scope: this,
+ animateEl: 'qo-kregator-add-feed-btn',
+ title: QoKregator.BoxAddFolderTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-add-folder',
+ width: 400,
+ height: 130,
+ closeAction: 'close',
+ plain: true,
+ items: FormAddFolder,
+ buttons: [{
+ id:'qo-kregator-btnOK-id-add-folder',
+ text: QoKregator.BoxAddFolderSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(this);
+ }
+ }, {
+ scope:this,
+ text: QoKregator.BoxAddFolderCancelBtn,
+ id:'qo-kregator-btnCANCEL-id-add-folder',
+ handler: function(){
+ winAddFolder.close();
+ }
+ }]
+ });
+
+ winAddFolder.show(this);
+
+ var tmp = new Ext.util.DelayedTask(function() { Ext.getCmp('newFolder').focus(); }, this);
+ tmp.delay(200);
+
+ }, //showAddFolder
+
+ showImport: function(_nodeID){
+
+ function validForm(scope) {
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutImportWait);
+
+ FormImport.form.submit({
+ scope: scope,
+ success: function(form, action){
+
+ var o = action.result;
+
+ if (o.success) {
+
+ // Add folder
+ scope.PanelFeedTree.getRootNode().appendChild(new Ext.tree.TreeNode({
+ text: o.folderText,
+ id: o.folderId,
+ leaf: false,
+ iconCls: 'qo-kregator-feed-folder',
+ type: 'folder',
+ children:[],
+ nodeID: 0
+ }));
+
+ scope.PanelFeedTree.getNodeById(o.folderId).expand();
+
+ var new_feed = [];
+ var reg = new RegExp("[|]+", "g");
+
+ var tmp_feed = o.new_feed;
+ new_feed = tmp_feed.split(reg);
+
+ // On ajoute les flux
+ for (var i = 0; i < new_feed.length; i++) {
+
+ if ( !new_feed[i]) { continue; }
+
+ scope.setStatusBar('qo-kregator-inProgress', QoKregator.StatutAddNewFeed);
+
+ var saveFeed = new Ext.data.Connection();
+ saveFeed.request({
+ scope: scope,
+ url: scope.app.connection,
+ params: {
+ moduleId: scope.moduleId,
+ fileName: 'php/qo-kregator.php',
+ newFeed: new_feed[i],
+ nodeID: o.folderId,
+ what: 'add_feed'
+ },
+
+ success: function(response, options){
+
+ var o2 = Ext.util.JSON.decode(response.responseText);
+
+ if (o2.success) {
+
+ // Add the new node
+ scope.PanelFeedTree.getNodeById(o.folderId).appendChild(new Ext.tree.TreeNode({
+ id:o2.id,
+ text:o2.text,
+ url: o2.url,
+ url_feed: o2.url_feed,
+ type: o2.type,
+ desc: o2.desc,
+ image: o2.image,
+ view: o2.view,
+ nodeID: o2.nodeID,
+ unseen:o2.unseen,
+ total:o2.total,
+ uiProvider:Ext.tree.KregaColumnNodeUI,
+ leaf:true,
+ icon:o2.icon,
+ iconCls:'',
+ refreshCycle:'on'
+ }));
+
+ scope.updateFeedInfo(o2.id, o2.unseen, o2.total);
+
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutAddNewFeedOk);
+
+ } else {
+ scope.setStatusBar('qo-kregator-error', QoKregator.StatutAddNewFeedNok + o2.message);
+ }
+ }
+ });
+
+ }
+
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutImportOk);
+
+ } else {
+
+ Ext.MessageBox.show({
+ title: 'erreur',
+ msg: 'erreur' + o.msg,
+ buttons: Ext.MessageBox.OK,
+ animEl: 'mb9',
+ icon: Ext.MessageBox.ERROR
+ });
+
+ }
+
+ FormImport.form.reset();
+ winImport.close();
+ },
+ failure: function(form, action){
+ scope.setStatusBar('qo-kregator-done', QoKregator.StatutImportNok + action.result.msg);
+ }
+ });
+
+ } // validForm
+
+
+ var FormImport = new Ext.FormPanel({
+ labelWidth: 45,
+ labelAlign: 'top',
+ id: 'form-import',
+ fileUpload: true,
+ url: this.app.connection+'?moduleId='+this.moduleId+'&fileName=php/qo-kregator.php&what=import',
+ frame: true,
+ bodyStyle: 'padding: 10px 10px 0 10px;',
+ autoHeight: true,
+ labelWidth: 50,
+ defaults: {
+ anchor: '95%',
+ allowBlank: false,
+ msgTarget: 'side'
+ },
+
+ items: [{
+ fieldLabel: QoKregator.WinImportLibel1,
+ xtype: 'textfield',
+ name: 'importFolder',
+ value: QoKregator.WinImportDefaultValue
+ }, {
+ xtype: 'fileuploadfield',
+ fieldLabel: QoKregator.WinImportLibel2,
+ name: 'importFile',
+ id: 'importFile',
+ emptyText: QoKregator.WinImportInfo,
+ buttonCfg: {
+ text: '',
+ iconCls: 'upload-icon'
+ }
+
+ }]
+
+ });
+
+ var winImport = new Ext.Window({
+ animateEl: 'qo-kregator-add-feed-btn',
+ title: QoKregator.WinImportTitle,
+ layout: 'fit',
+ modal: true,
+ iconCls: 'qo-kregator-icon-import',
+ width: 400,
+ height: 210,
+ plain: true,
+ bodyStyle: 'padding:5px',
+ items: FormImport,
+
+ buttons: [{
+ text: QoKregator.WinImportSaveBtn,
+ scope: this,
+ handler: function(){
+ validForm(this);
+ }
+ }, {
+ text: QoKregator.WinImportCancelBtn,
+ handler: function(){
+ winImport.close();
+ }
+ }]
+ });
+
+ winImport.show(this);
+
+ }, //showImport
+
+ showAbout: function(){
+
+ if (!this.winAbout) {
+
+ this.winAbout = new Ext.Window({
+ layout: 'fit',
+ width: 560,
+ height: 520,
+ iconCls: 'qo-kregator-icon-about',
+ modal: true,
+ title: QoKregator.WinAboutTitle,
+ closeAction: 'hide',
+ plain: true,
+ bodyStyle: 'color:#000',
+ items: new Ext.TabPanel({
+ autoTabs: true,
+ activeTab: 0,
+ border: false,
+ defaults: {
+ autoScroll: true
+ },
+ items: [{
+ title: QoKregator.WinAboutTab0,
+ html: '<div id="qo-kregator-about"><img src="system/modules/qo-kregator/img/default/logo.png" alt="" /></div><div id="qo-kregator-about-info">ver '+this.appVer+' - (c) 2007 - 2008, Yannick Torrès - <a href="mailto:yannick.torres@xxxxxxxxxxxx">yannick.torres@xxxxxxxxxxxx</a></div>'
+ }, {
+ title: QoKregator.WinAboutTab1,
+ bodyStyle: 'padding:5px',
+ html: '<div id="qo-kregator-credit"><ul><li><a href="http://extjs.com/forum/member.php?u=12208">Franck Carrouget</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits0 + '</span></li><li><a href="http://extjs.com/forum/member.php?u=6915">Andriy Levytskyy</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits1 + '</span></li><li><a href="http://extjs.com/forum/member.php?u=1485">K0bo</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits21 + '</span></li><li><a href="http://www.alsacreations.fr">AlsaCréations</a><br><span class="qo-kregator-credit-info"><a href="http://www.alsacreations.fr/dewplayer">DewPlayer</a> & <a href="http://www.alsacreations.fr/dewtube">DewTube</a></span></li><li><a href="http://extjs.com">ExtJs Team</a><br><span class="qo-kregator-credit-info">' + QoKregator.WinAboutTab1Credits3 + '</span></li></ul></div>'
+ }, {
+ title: QoKregator.WinAboutTab2,
+ autoLoad: {
+ url: 'system/modules/qo-kregator/license_LGPL_v2.txt'
+ }
+ }]
+ }),
+
+ buttons: [{
+ scope:this,
+ text: QoKregator.WinAboutClose,
+ handler: function(){
+ this.winAbout.hide();
+ }
+ }]
+ });
+ }
+ this.winAbout.show(this);
+
+ }, //showAbout
+
+ gridClearFilter: function(){
+
+ // Date searchField
+ Ext.getCmp('qo-kregator-datefilter-btn').curDate = '*';
+ Ext.getCmp('qo-kregator-datefilter-btn').setText(QoKregator.FeedGridFilterDateAllDate);
+ Ext.getCmp('qo-kregator-datefilter-btn').toggle(false);
+
+ // Text searchField
+ Ext.getCmp('qo-kregator-search').setValue('');
+
+ // State searchField
+ Ext.getCmp('qo-kregator-etat').setValue('all', true);
+
+ // Reset the trigger
+ Ext.getCmp('qo-kregator-search').triggers[0].hide();
+
+ }, // gridClearFilter
+
+ showHideStatusBar: function() {
+
+ if( this.ConfshowStatusBar == 'on' ) {
+ Ext.getCmp('qo-kregator').getBottomToolbar().show();
+ } else {
+ Ext.getCmp('qo-kregator').getBottomToolbar().hide();
+ }
+
+ }, //showHideStatusBar
+
+ setStatusBar: function(style, message){
+
+ var statusBar = Ext.getCmp('qo-kregator-statusBar');
+
+ statusBar.setStatus({
+ text: message,
+ iconCls: style
+ });
+
+ }, // setStatusBar
+
+ searchFeed: function() {
+
+ var count = 0;
+
+ this.FeedNeedUpdate = [];
+ this.ConfGoRefresh = true;
+
+ // We change "refresh" to "stop" icon
+ if( Ext.getCmp('qo-kregator-add-refresh-feed-btn') ) {
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setHandler(function() {this.ConfGoRefresh = false;}, this);
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setIconClass('qo-kregator-refresh-stop-btn');
+ }
+
+ function _searchFeed(node, scope){
+
+ var kids = node.childNodes;
+ var len = kids.length;
+ for (var i = 0; i < len; i++) {
+
+ if (kids[i].attributes.type == 'file') {
+
+ // Exclude feed where refreshCycle == off
+ if( kids[i].attributes.refreshCycle == 'on' ) {
+
+ scope.FeedNeedUpdate[count] = [];
+
+ scope.FeedNeedUpdate[count].nodeID = kids[i].id;
+ scope.FeedNeedUpdate[count].id = kids[i].attributes.id;
+ scope.FeedNeedUpdate[count].texte = kids[i].text;
+ ++count;
+
+ }
+
+ }
+ _searchFeed(kids[i], scope);
+ }
+ }
+
+ _searchFeed(this.PanelFeedTree.getRootNode(), this);
+
+ this.goUpdateAllFeed(0);
+
+ this.TaskSearchFeed.delay(this.ConfRefreshFeed * 60 * 1000);
+
+ }, //searchFeed
+
+ goUpdateAllFeed: function(FeedIndex){
+
+ if (this.FeedNeedUpdate[FeedIndex] && this.ConfGoRefresh ) {
+ this.updateFeed(this.FeedNeedUpdate[FeedIndex].texte, this.FeedNeedUpdate[FeedIndex].id, this.FeedNeedUpdate[FeedIndex].nodeID, 'on', FeedIndex + 1);
+ } else {
+
+ // Return to default button refresh
+ if( Ext.getCmp('qo-kregator-add-refresh-feed-btn') ) {
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setHandler(function() {this.TaskSearchFeed.delay(1000);}, this);
+ Ext.getCmp('qo-kregator-add-refresh-feed-btn').setIconClass('qo-kregator-refresh-btn');
+ }
+ }
+
+
+ }, // goUpdateAllFeed
+
+ updateFeed: function(id_texte, id_Feed, _nodeID, cache, NextFeedIndex){
+
+ this.setStatusBar('qo-kregator-inProgress', QoKregator.StatutUpdateFeed + id_texte + '...');
+
+ this.PanelFeedTree.getNodeById(_nodeID).ui.removeClass("qo-kregator-feed-Unseen");
+ this.PanelFeedTree.getNodeById(_nodeID).ui.addClass("x-tree-node-disabled");
+
+ var UpdateFeed = new Ext.data.Connection();
+
+ UpdateFeed.request({
+ scope: this,
+ url: this.app.connection,
+ params: {
+ moduleId: this.moduleId,
+ fileName: 'php/qo-kregator.php',
+ idFeed: id_Feed,
+ cache: cache,
+ what: 'update_feed'
+ },
+ success: function(response, options){
+
+ var o = Ext.util.JSON.decode(response.responseText);
+
+ if (o.success) {
+
+ this.setStatusBar('qo-kregator-done', id_texte + ' : ' + QoKregator.StatutDone);
+ this.PanelFeedTree.getNodeById(_nodeID).ui.removeClass("x-tree-node-disabled");
+ this.updateFeedInfo(_nodeID, o.unseen, o.new_nb_item);
+
+ // if there is new items & items for this feed are displayed, we update the grid
+ if (o.new_nb_item > o.old_nb_item && this.curFeedId == id_Feed) {
+ this.dsItems.reload();
+ }
+
+ } else {
+
+ this.setStatusBar('qo-kregator-error', QoKregator.StatutUpdateFeedNok + id_texte);
+
+ this.PanelFeedTree.getNodeById(_nodeID).ui.removeClass("x-tree-node-disabled");
+ this.PanelFeedTree.getNodeById(_nodeID).ui.addClass("x-tree-node-error");
+ }
+
+ if (NextFeedIndex >= 0) {
+ this.goUpdateAllFeed(NextFeedIndex);
+ }
+
+ }
+ });
+ }, //updateFeed
+
+ renderDate: function(TmpDate, GoFormat) {
+
+ if (TmpDate == '0000-00-00 00:00:00') { return '-'; }
+
+ var dt = new Date();
+ dt = Date.parseDate(TmpDate, "Y-m-d h:i:s");
+
+ return dt.format(GoFormat);
+
+ }, //renderDate
+
+ setContentFontSize: function(choice) {
+
+ if( Ext.select('.qo-kregator-feed-content') ) {
+ Ext.select('.qo-kregator-feed-content').setStyle('font-size', this.ConfContentFontSize+'px');
+ }
+ } // setContentFontSize
+
+});
Added: trunk/qo-kregator/uninstall.sql
===================================================================
--- trunk/qo-kregator/uninstall.sql (rev 0)
+++ trunk/qo-kregator/uninstall.sql 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,38 @@
+-- delete data content
+delete from `qo_groups_has_modules`
+where `qo_modules_id` in (
+ select `id`
+ from `qo_modules`
+ where `module_id` = 'QoKregator'
+);
+
+delete from `qo_modules_dependencies`
+where `qo_modules_id` in (
+ select `id`
+ from `qo_modules`
+ where `module_id` = 'QoKregator'
+);
+
+delete from `qo_modules_stylesheets`
+where `qo_modules_id` in (
+ select `id`
+ from `qo_modules`
+ where `module_id` = 'QoKregator'
+);
+
+delete from `qo_modules_files`
+where `qo_modules_id` in (
+ select `id`
+ from `qo_modules`
+ where `module_id` = 'QoKregator'
+);
+
+delete from `qo_modules`
+where `module_id` = 'QoKregator';
+
+commit;
+
+DROP TABLE `qo-kregator-conf`;
+DROP TABLE `qo-kregator-dir`;
+DROP TABLE `qo-kregator-items`;
+commit;
\ No newline at end of file
Added: trunk/qo-kregator/ux/FileUploadField/FileUploadField.js
===================================================================
--- trunk/qo-kregator/ux/FileUploadField/FileUploadField.js (rev 0)
+++ trunk/qo-kregator/ux/FileUploadField/FileUploadField.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,129 @@
+/*
+ * Ext JS Library 2.2
+ * Copyright(c) 2006-2008, Ext JS, LLC.
+ * licensing@xxxxxxxxx
+ *
+ * http://extjs.com/license
+ */
+
+
+Ext.form.FileUploadField = Ext.extend(Ext.form.TextField, {
+ /**
+ * @cfg {String} buttonText The button text to display on the upload button (defaults to
+ * 'Browse...'). Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
+ * value will be used instead if available.
+ */
+ buttonText: 'Browse...',
+ /**
+ * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
+ * text field (defaults to false). If true, all inherited TextField members will still be available.
+ */
+ buttonOnly: false,
+ /**
+ * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
+ * (defaults to 3). Note that this only applies if {@link #buttonOnly} = false.
+ */
+ buttonOffset: 3,
+ /**
+ * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
+ */
+
+ // private
+ readOnly: true,
+
+ /**
+ * @hide
+ * @method autoSize
+ */
+ autoSize: Ext.emptyFn,
+
+ // private
+ initComponent: function(){
+ Ext.form.FileUploadField.superclass.initComponent.call(this);
+
+ this.addEvents(
+ /**
+ * @event fileselected
+ * Fires when the underlying file input field's value has changed from the user
+ * selecting a new file from the system file selection dialog.
+ * @param {Ext.form.FileUploadField} this
+ * @param {String} value The file value returned by the underlying file input field
+ */
+ 'fileselected'
+ );
+ },
+
+ // private
+ onRender : function(ct, position){
+ Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);
+
+ this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
+ this.el.addClass('x-form-file-text');
+ this.el.dom.removeAttribute('name');
+
+ this.fileInput = this.wrap.createChild({
+ id: this.getFileInputId(),
+ name: this.name||this.getId(),
+ cls: 'x-form-file',
+ tag: 'input',
+ type: 'file',
+ size: 1
+ });
+
+ var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
+ text: this.buttonText
+ });
+ this.button = new Ext.Button(Ext.apply(btnCfg, {
+ renderTo: this.wrap,
+ cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
+ }));
+
+ if(this.buttonOnly){
+ this.el.hide();
+ this.wrap.setWidth(this.button.getEl().getWidth());
+ }
+
+ this.fileInput.on('change', function(){
+ var v = this.fileInput.dom.value;
+ this.setValue(v);
+ this.fireEvent('fileselected', this, v);
+ }, this);
+ },
+
+ // private
+ getFileInputId: function(){
+ return this.id+'-file';
+ },
+
+ // private
+ onResize : function(w, h){
+ Ext.form.FileUploadField.superclass.onResize.call(this, w, h);
+
+ this.wrap.setWidth(w);
+
+ if(!this.buttonOnly){
+ var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
+ this.el.setWidth(w);
+ }
+ },
+
+ // private
+ preFocus : Ext.emptyFn,
+
+ // private
+ getResizeEl : function(){
+ return this.wrap;
+ },
+
+ // private
+ getPositionEl : function(){
+ return this.wrap;
+ },
+
+ // private
+ alignErrorIcon : function(){
+ this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
+ }
+
+});
+Ext.reg('fileuploadfield', Ext.form.FileUploadField);
\ No newline at end of file
Added: trunk/qo-kregator/ux/MultiselectItemSelector/DDView.js
===================================================================
--- trunk/qo-kregator/ux/MultiselectItemSelector/DDView.js (rev 0)
+++ trunk/qo-kregator/ux/MultiselectItemSelector/DDView.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,551 @@
+Array.prototype.contains = function(element) {
+ return this.indexOf(element) !== -1;
+};
+
+Ext.namespace("Ext.ux");
+
+/**
+ * @class Ext.ux.DDView
+ * A DnD enabled version of Ext.View.
+ * @param {Element/String} container The Element in which to create the View.
+ * @param {String} tpl The template string used to create the markup for each element of the View
+ * @param {Object} config The configuration properties. These include all the config options of
+ * {@link Ext.View} plus some specific to this class.<br>
+ * <p>
+ * Drag/drop is implemented by adding {@link Ext.data.Record}s to the target DDView. If copying is
+ * not being performed, the original {@link Ext.data.Record} is removed from the source DDView.<br>
+ * <p>
+ * The following extra CSS rules are needed to provide insertion point highlighting:<pre><code>
+.x-view-drag-insert-above {
+ border-top:1px dotted #3366cc;
+}
+.x-view-drag-insert-below {
+ border-bottom:1px dotted #3366cc;
+}
+</code></pre>
+ *
+ */
+Ext.ux.DDView = function(config) {
+ if (!config.itemSelector) {
+ var tpl = config.tpl;
+ if (this.classRe.test(tpl)) {
+ config.tpl = tpl.replace(this.classRe, 'class=$1x-combo-list-item $2$1');
+ }
+ else {
+ config.tpl = tpl.replace(this.tagRe, '$1 class="x-combo-list-item" $2');
+ }
+ config.itemSelector = ".x-combo-list-item";
+ }
+ Ext.ux.DDView.superclass.constructor.call(this, Ext.apply(config, {
+ border: false
+ }));
+};
+
+Ext.extend(Ext.ux.DDView, Ext.DataView, {
+/** @cfg {String/Array} dragGroup The ddgroup name(s) for the View's DragZone. */
+/** @cfg {String/Array} dropGroup The ddgroup name(s) for the View's DropZone. */
+/** @cfg {Boolean} copy Causes drag operations to copy nodes rather than move. */
+/** @cfg {Boolean} allowCopy Causes ctrl/drag operations to copy nodes rather than move. */
+
+ sortDir: 'ASC',
+
+ isFormField: true,
+
+ classRe: /class=(['"])(.*)\1/,
+
+ tagRe: /(<\w*)(.*?>)/,
+
+ reset: Ext.emptyFn,
+
+ clearInvalid: Ext.form.Field.prototype.clearInvalid,
+
+ msgTarget: 'qtip',
+
+ afterRender: function() {
+ Ext.ux.DDView.superclass.afterRender.call(this);
+ if (this.dragGroup) {
+ this.setDraggable(this.dragGroup.split(","));
+ }
+ if (this.dropGroup) {
+ this.setDroppable(this.dropGroup.split(","));
+ }
+ if (this.deletable) {
+ this.setDeletable();
+ }
+ this.isDirtyFlag = false;
+ this.addEvents(
+ "drop"
+ );
+ },
+
+ validate: function() {
+ return true;
+ },
+
+ destroy: function() {
+ this.purgeListeners();
+ this.getEl().removeAllListeners();
+ this.getEl().remove();
+ if (this.dragZone) {
+ if (this.dragZone.destroy) {
+ this.dragZone.destroy();
+ }
+ }
+ if (this.dropZone) {
+ if (this.dropZone.destroy) {
+ this.dropZone.destroy();
+ }
+ }
+ },
+
+/** Allows this class to be an Ext.form.Field so it can be found using {@link Ext.form.BasicForm#findField}. */
+ getName: function() {
+ return this.name;
+ },
+
+/** Loads the View from a JSON string representing the Records to put into the Store. */
+ setValue: function(v) {
+ if (!this.store) {
+ throw "DDView.setValue(). DDView must be constructed with a valid Store";
+ }
+ var data = {};
+ data[this.store.reader.meta.root] = v ? [].concat(v) : [];
+ this.store.proxy = new Ext.data.MemoryProxy(data);
+ this.store.load();
+ },
+
+/** @return {String} a parenthesised list of the ids of the Records in the View. */
+ getValue: function() {
+ var result = '(';
+ this.store.each(function(rec) {
+ result += rec.id + ',';
+ });
+ return result.substr(0, result.length - 1) + ')';
+ },
+
+ getIds: function() {
+ var i = 0, result = new Array(this.store.getCount());
+ this.store.each(function(rec) {
+ result[i++] = rec.id;
+ });
+ return result;
+ },
+
+ isDirty: function() {
+ return this.isDirtyFlag;
+ },
+
+/**
+ * Part of the Ext.dd.DropZone interface. If no target node is found, the
+ * whole Element becomes the target, and this causes the drop gesture to append.
+ */
+ getTargetFromEvent : function(e) {
+ var target = e.getTarget();
+ while ((target !== null) && (target.parentNode != this.el.dom)) {
+ target = target.parentNode;
+ }
+ if (!target) {
+ target = this.el.dom.lastChild || this.el.dom;
+ }
+ return target;
+ },
+
+/**
+ * Create the drag data which consists of an object which has the property "ddel" as
+ * the drag proxy element.
+ */
+ getDragData : function(e) {
+ var target = this.findItemFromChild(e.getTarget());
+ if(target) {
+ if (!this.isSelected(target)) {
+ delete this.ignoreNextClick;
+ this.onItemClick(target, this.indexOf(target), e);
+ this.ignoreNextClick = true;
+ }
+ var dragData = {
+ sourceView: this,
+ viewNodes: [],
+ records: [],
+ copy: this.copy || (this.allowCopy && e.ctrlKey)
+ };
+ if (this.getSelectionCount() == 1) {
+ var i = this.getSelectedIndexes()[0];
+ var n = this.getNode(i);
+ dragData.viewNodes.push(dragData.ddel = n);
+ dragData.records.push(this.store.getAt(i));
+ dragData.repairXY = Ext.fly(n).getXY();
+ } else {
+ dragData.ddel = document.createElement('div');
+ dragData.ddel.className = 'multi-proxy';
+ this.collectSelection(dragData);
+ }
+ return dragData;
+ }
+ return false;
+ },
+
+// override the default repairXY.
+ getRepairXY : function(e){
+ return this.dragData.repairXY;
+ },
+
+/** Put the selections into the records and viewNodes Arrays. */
+ collectSelection: function(data) {
+ data.repairXY = Ext.fly(this.getSelectedNodes()[0]).getXY();
+ if (this.preserveSelectionOrder === true) {
+ Ext.each(this.getSelectedIndexes(), function(i) {
+ var n = this.getNode(i);
+ var dragNode = n.cloneNode(true);
+ dragNode.id = Ext.id();
+ data.ddel.appendChild(dragNode);
+ data.records.push(this.store.getAt(i));
+ data.viewNodes.push(n);
+ }, this);
+ } else {
+ var i = 0;
+ this.store.each(function(rec){
+ if (this.isSelected(i)) {
+ var n = this.getNode(i);
+ var dragNode = n.cloneNode(true);
+ dragNode.id = Ext.id();
+ data.ddel.appendChild(dragNode);
+ data.records.push(this.store.getAt(i));
+ data.viewNodes.push(n);
+ }
+ i++;
+ }, this);
+ }
+ },
+
+/** Specify to which ddGroup items in this DDView may be dragged. */
+ setDraggable: function(ddGroup) {
+ if (ddGroup instanceof Array) {
+ Ext.each(ddGroup, this.setDraggable, this);
+ return;
+ }
+ if (this.dragZone) {
+ this.dragZone.addToGroup(ddGroup);
+ } else {
+ this.dragZone = new Ext.dd.DragZone(this.getEl(), {
+ containerScroll: true,
+ ddGroup: ddGroup
+ });
+// Draggability implies selection. DragZone's mousedown selects the element.
+ if (!this.multiSelect) { this.singleSelect = true; }
+
+// Wire the DragZone's handlers up to methods in *this*
+ this.dragZone.getDragData = this.getDragData.createDelegate(this);
+ this.dragZone.getRepairXY = this.getRepairXY;
+ this.dragZone.onEndDrag = this.onEndDrag;
+ }
+ },
+
+/** Specify from which ddGroup this DDView accepts drops. */
+ setDroppable: function(ddGroup) {
+ if (ddGroup instanceof Array) {
+ Ext.each(ddGroup, this.setDroppable, this);
+ return;
+ }
+ if (this.dropZone) {
+ this.dropZone.addToGroup(ddGroup);
+ } else {
+ this.dropZone = new Ext.dd.DropZone(this.getEl(), {
+ owningView: this,
+ containerScroll: true,
+ ddGroup: ddGroup
+ });
+
+// Wire the DropZone's handlers up to methods in *this*
+ this.dropZone.getTargetFromEvent = this.getTargetFromEvent.createDelegate(this);
+ this.dropZone.onNodeEnter = this.onNodeEnter.createDelegate(this);
+ this.dropZone.onNodeOver = this.onNodeOver.createDelegate(this);
+ this.dropZone.onNodeOut = this.onNodeOut.createDelegate(this);
+ this.dropZone.onNodeDrop = this.onNodeDrop.createDelegate(this);
+ }
+ },
+
+/** Decide whether to drop above or below a View node. */
+ getDropPoint : function(e, n, dd){
+ if (n == this.el.dom) { return "above"; }
+ var t = Ext.lib.Dom.getY(n), b = t + n.offsetHeight;
+ var c = t + (b - t) / 2;
+ var y = Ext.lib.Event.getPageY(e);
+ if(y <= c) {
+ return "above";
+ }else{
+ return "below";
+ }
+ },
+
+ isValidDropPoint: function(pt, n, data) {
+ if (!data.viewNodes || (data.viewNodes.length != 1)) {
+ return true;
+ }
+ var d = data.viewNodes[0];
+ if (d == n) {
+ return false;
+ }
+ if ((pt == "below") && (n.nextSibling == d)) {
+ return false;
+ }
+ if ((pt == "above") && (n.previousSibling == d)) {
+ return false;
+ }
+ return true;
+ },
+
+ onNodeEnter : function(n, dd, e, data){
+ if (this.highlightColor && (data.sourceView != this)) {
+ this.el.highlight(this.highlightColor);
+ }
+ return false;
+ },
+
+ onNodeOver : function(n, dd, e, data){
+ var dragElClass = this.dropNotAllowed;
+ var pt = this.getDropPoint(e, n, dd);
+ if (this.isValidDropPoint(pt, n, data)) {
+ if (this.appendOnly || this.sortField) {
+ return "x-tree-drop-ok-below";
+ }
+
+// set the insert point style on the target node
+ if (pt) {
+ var targetElClass;
+ if (pt == "above"){
+ dragElClass = n.previousSibling ? "x-tree-drop-ok-between" : "x-tree-drop-ok-above";
+ targetElClass = "x-view-drag-insert-above";
+ } else {
+ dragElClass = n.nextSibling ? "x-tree-drop-ok-between" : "x-tree-drop-ok-below";
+ targetElClass = "x-view-drag-insert-below";
+ }
+ if (this.lastInsertClass != targetElClass){
+ Ext.fly(n).replaceClass(this.lastInsertClass, targetElClass);
+ this.lastInsertClass = targetElClass;
+ }
+ }
+ }
+ return dragElClass;
+ },
+
+ onNodeOut : function(n, dd, e, data){
+ this.removeDropIndicators(n);
+ },
+
+ onNodeDrop : function(n, dd, e, data){
+ if (this.fireEvent("drop", this, n, dd, e, data) === false) {
+ return false;
+ }
+ var pt = this.getDropPoint(e, n, dd);
+ var insertAt = (this.appendOnly || (n == this.el.dom)) ? this.store.getCount() : n.viewIndex;
+ if (pt == "below") {
+ insertAt++;
+ }
+
+// Validate if dragging within a DDView
+ if (data.sourceView == this) {
+// If the first element to be inserted below is the target node, remove it
+ if (pt == "below") {
+ if (data.viewNodes[0] == n) {
+ data.viewNodes.shift();
+ }
+ } else { // If the last element to be inserted above is the target node, remove it
+ if (data.viewNodes[data.viewNodes.length - 1] == n) {
+ data.viewNodes.pop();
+ }
+ }
+
+// Nothing to drop...
+ if (!data.viewNodes.length) {
+ return false;
+ }
+
+// If we are moving DOWN, then because a store.remove() takes place first,
+// the insertAt must be decremented.
+ if (insertAt > this.store.indexOf(data.records[0])) {
+ insertAt--;
+ }
+ }
+
+// Dragging from a Tree. Use the Tree's recordFromNode function.
+ if (data.node instanceof Ext.tree.TreeNode) {
+ var r = data.node.getOwnerTree().recordFromNode(data.node);
+ if (r) {
+ data.records = [ r ];
+ }
+ }
+
+ if (!data.records) {
+ alert("Programming problem. Drag data contained no Records");
+ return false;
+ }
+
+ for (var i = 0; i < data.records.length; i++) {
+ var r = data.records[i];
+ var dup = this.store.getById(r.id);
+ if (dup && (dd != this.dragZone)) {
+ if(!this.allowDup && !this.allowTrash){
+ Ext.fly(this.getNode(this.store.indexOf(dup))).frame("red", 1);
+ return true
+ }
+ var x=new Ext.data.Record();
+ r.id=x.id;
+ delete x;
+ }
+ if (data.copy) {
+ this.store.insert(insertAt++, r.copy());
+ } else {
+ if (data.sourceView) {
+ data.sourceView.isDirtyFlag = true;
+ data.sourceView.store.remove(r);
+ }
+ if(!this.allowTrash)this.store.insert(insertAt++, r);
+ }
+ if(this.sortField){
+ this.store.sort(this.sortField, this.sortDir);
+ }
+ this.isDirtyFlag = true;
+ }
+ this.dragZone.cachedTarget = null;
+ return true;
+ },
+
+// Ensure the multi proxy is removed
+ onEndDrag: function(data, e) {
+ var d = Ext.get(this.dragData.ddel);
+ if (d && d.hasClass("multi-proxy")) {
+ d.remove();
+ //delete this.dragData.ddel;
+ }
+ },
+
+ removeDropIndicators : function(n){
+ if(n){
+ Ext.fly(n).removeClass([
+ "x-view-drag-insert-above",
+ "x-view-drag-insert-left",
+ "x-view-drag-insert-right",
+ "x-view-drag-insert-below"]);
+ this.lastInsertClass = "_noclass";
+ }
+ },
+
+/**
+ * Utility method. Add a delete option to the DDView's context menu.
+ * @param {String} imageUrl The URL of the "delete" icon image.
+ */
+ setDeletable: function(imageUrl) {
+ if (!this.singleSelect && !this.multiSelect) {
+ this.singleSelect = true;
+ }
+ var c = this.getContextMenu();
+ this.contextMenu.on("itemclick", function(item) {
+ switch (item.id) {
+ case "delete":
+ this.remove(this.getSelectedIndexes());
+ break;
+ }
+ }, this);
+ this.contextMenu.add({
+ icon: imageUrl || AU.resolveUrl("/images/delete.gif"),
+ id: "delete",
+ text: AU.getMessage("deleteItem")
+ });
+ },
+
+/** Return the context menu for this DDView. */
+ getContextMenu: function() {
+ if (!this.contextMenu) {
+// Create the View's context menu
+ this.contextMenu = new Ext.menu.Menu({
+ id: this.id + "-contextmenu"
+ });
+ this.el.on("contextmenu", this.showContextMenu, this);
+ }
+ return this.contextMenu;
+ },
+
+ disableContextMenu: function() {
+ if (this.contextMenu) {
+ this.el.un("contextmenu", this.showContextMenu, this);
+ }
+ },
+
+ showContextMenu: function(e, item) {
+ item = this.findItemFromChild(e.getTarget());
+ if (item) {
+ e.stopEvent();
+ this.select(this.getNode(item), this.multiSelect && e.ctrlKey, true);
+ this.contextMenu.showAt(e.getXY());
+ }
+ },
+
+/**
+ * Remove {@link Ext.data.Record}s at the specified indices.
+ * @param {Array/Number} selectedIndices The index (or Array of indices) of Records to remove.
+ */
+ remove: function(selectedIndices) {
+ selectedIndices = [].concat(selectedIndices);
+ for (var i = 0; i < selectedIndices.length; i++) {
+ var rec = this.store.getAt(selectedIndices[i]);
+ this.store.remove(rec);
+ }
+ },
+
+/**
+ * Double click fires the event, but also, if this is draggable, and there is only one other
+ * related DropZone that is in another DDView, it drops the selected node on that DDView.
+ */
+ onDblClick : function(e){
+ var item = this.findItemFromChild(e.getTarget());
+ if(item){
+ if (this.fireEvent("dblclick", this, this.indexOf(item), item, e) === false) {
+ return false;
+ }
+ if (this.dragGroup) {
+ var targets = Ext.dd.DragDropMgr.getRelated(this.dragZone, true);
+
+// Remove instances of this View's DropZone
+ while (targets.contains(this.dropZone)) {
+ targets.remove(this.dropZone);
+ }
+
+// If there's only one other DropZone, and it is owned by a DDView, then drop it in
+ if ((targets.length == 1) && (targets[0].owningView)) {
+ this.dragZone.cachedTarget = null;
+ var el = Ext.get(targets[0].getEl());
+ var box = el.getBox(true);
+ targets[0].onNodeDrop(el.dom, {
+ target: el.dom,
+ xy: [box.x, box.y + box.height - 1]
+ }, null, this.getDragData(e));
+ }
+ }
+ }
+ },
+
+ onItemClick : function(item, index, e){
+// The DragZone's mousedown->getDragData already handled selection
+ if (this.ignoreNextClick) {
+ delete this.ignoreNextClick;
+ return;
+ }
+
+ if(this.fireEvent("beforeclick", this, index, item, e) === false){
+ return false;
+ }
+ if(this.multiSelect || this.singleSelect){
+ if(this.multiSelect && e.shiftKey && this.lastSelection){
+ this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
+ } else if (this.isSelected(item) && e.ctrlKey) {
+ this.deselect(item);
+ }else{
+ this.deselect(item);
+ this.select(item, this.multiSelect && e.ctrlKey);
+ this.lastSelection = item;
+ }
+ e.preventDefault();
+ }
+ return true;
+ }
+});
Added: trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.css
===================================================================
--- trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.css (rev 0)
+++ trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.css 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,19 @@
+.ux-mselect{
+ overflow:auto;
+ background:white;
+ position:relative; /* for calculating scroll offsets */
+ zoom:1;
+ overflow:auto;
+}
+.ux-mselect-item{
+ font:normal 12px tahoma, arial, helvetica, sans-serif;
+ padding:2px;
+ border:1px solid #fff;
+ white-space: nowrap;
+ cursor:pointer;
+}
+.ux-mselect-selected{
+ border:1px dotted #a3bae9 !important;
+ background:#DFE8F6;
+ cursor:pointer;
+}
Added: trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.js
===================================================================
--- trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.js (rev 0)
+++ trunk/qo-kregator/ux/MultiselectItemSelector/Multiselect.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,1081 @@
+Array.prototype.contains = function(element) {
+ return this.indexOf(element) !== -1;
+};
+
+Ext.namespace("Ext.ux");
+
+/**
+ * @class Ext.ux.DDView
+ * A DnD enabled version of Ext.View.
+ * @param {Element/String} container The Element in which to create the View.
+ * @param {String} tpl The template string used to create the markup for each element of the View
+ * @param {Object} config The configuration properties. These include all the config options of
+ * {@link Ext.View} plus some specific to this class.<br>
+ * <p>
+ * Drag/drop is implemented by adding {@link Ext.data.Record}s to the target DDView. If copying is
+ * not being performed, the original {@link Ext.data.Record} is removed from the source DDView.<br>
+ * <p>
+ * The following extra CSS rules are needed to provide insertion point highlighting:<pre><code>
+.x-view-drag-insert-above {
+ border-top:1px dotted #3366cc;
+}
+.x-view-drag-insert-below {
+ border-bottom:1px dotted #3366cc;
+}
+</code></pre>
+ *
+ */
+Ext.ux.DDView = function(config) {
+ if (!config.itemSelector) {
+ var tpl = config.tpl;
+ if (this.classRe.test(tpl)) {
+ config.tpl = tpl.replace(this.classRe, 'class=$1x-combo-list-item $2$1');
+ }
+ else {
+ config.tpl = tpl.replace(this.tagRe, '$1 class="x-combo-list-item" $2');
+ }
+ config.itemSelector = ".x-combo-list-item";
+ }
+ Ext.ux.DDView.superclass.constructor.call(this, Ext.apply(config, {
+ border: false
+ }));
+};
+
+Ext.extend(Ext.ux.DDView, Ext.DataView, {
+/** @cfg {String/Array} dragGroup The ddgroup name(s) for the View's DragZone. */
+/** @cfg {String/Array} dropGroup The ddgroup name(s) for the View's DropZone. */
+/** @cfg {Boolean} copy Causes drag operations to copy nodes rather than move. */
+/** @cfg {Boolean} allowCopy Causes ctrl/drag operations to copy nodes rather than move. */
+
+ sortDir: 'ASC',
+
+ isFormField: true,
+
+ classRe: /class=(['"])(.*)\1/,
+
+ tagRe: /(<\w*)(.*?>)/,
+
+ reset: Ext.emptyFn,
+
+ clearInvalid: Ext.form.Field.prototype.clearInvalid,
+
+ msgTarget: 'qtip',
+
+ afterRender: function() {
+ Ext.ux.DDView.superclass.afterRender.call(this);
+ if (this.dragGroup) {
+ this.setDraggable(this.dragGroup.split(","));
+ }
+ if (this.dropGroup) {
+ this.setDroppable(this.dropGroup.split(","));
+ }
+ if (this.deletable) {
+ this.setDeletable();
+ }
+ this.isDirtyFlag = false;
+ this.addEvents(
+ "drop"
+ );
+ },
+
+ validate: function() {
+ return true;
+ },
+
+ destroy: function() {
+ this.purgeListeners();
+ this.getEl().removeAllListeners();
+ this.getEl().remove();
+ if (this.dragZone) {
+ if (this.dragZone.destroy) {
+ this.dragZone.destroy();
+ }
+ }
+ if (this.dropZone) {
+ if (this.dropZone.destroy) {
+ this.dropZone.destroy();
+ }
+ }
+ },
+
+/** Allows this class to be an Ext.form.Field so it can be found using {@link Ext.form.BasicForm#findField}. */
+ getName: function() {
+ return this.name;
+ },
+
+/** Loads the View from a JSON string representing the Records to put into the Store. */
+ setValue: function(v) {
+ if (!this.store) {
+ throw "DDView.setValue(). DDView must be constructed with a valid Store";
+ }
+ var data = {};
+ data[this.store.reader.meta.root] = v ? [].concat(v) : [];
+ this.store.proxy = new Ext.data.MemoryProxy(data);
+ this.store.load();
+ },
+
+/** @return {String} a parenthesised list of the ids of the Records in the View. */
+ getValue: function() {
+ var result = '(';
+ this.store.each(function(rec) {
+ result += rec.id + ',';
+ });
+ return result.substr(0, result.length - 1) + ')';
+ },
+
+ getIds: function() {
+ var i = 0, result = new Array(this.store.getCount());
+ this.store.each(function(rec) {
+ result[i++] = rec.id;
+ });
+ return result;
+ },
+
+ isDirty: function() {
+ return this.isDirtyFlag;
+ },
+
+/**
+ * Part of the Ext.dd.DropZone interface. If no target node is found, the
+ * whole Element becomes the target, and this causes the drop gesture to append.
+ */
+ getTargetFromEvent : function(e) {
+ var target = e.getTarget();
+ while ((target !== null) && (target.parentNode != this.el.dom)) {
+ target = target.parentNode;
+ }
+ if (!target) {
+ target = this.el.dom.lastChild || this.el.dom;
+ }
+ return target;
+ },
+
+/**
+ * Create the drag data which consists of an object which has the property "ddel" as
+ * the drag proxy element.
+ */
+ getDragData : function(e) {
+ var target = this.findItemFromChild(e.getTarget());
+ if(target) {
+ if (!this.isSelected(target)) {
+ delete this.ignoreNextClick;
+ this.onItemClick(target, this.indexOf(target), e);
+ this.ignoreNextClick = true;
+ }
+ var dragData = {
+ sourceView: this,
+ viewNodes: [],
+ records: [],
+ copy: this.copy || (this.allowCopy && e.ctrlKey)
+ };
+ if (this.getSelectionCount() == 1) {
+ var i = this.getSelectedIndexes()[0];
+ var n = this.getNode(i);
+ dragData.viewNodes.push(dragData.ddel = n);
+ dragData.records.push(this.store.getAt(i));
+ dragData.repairXY = Ext.fly(n).getXY();
+ } else {
+ dragData.ddel = document.createElement('div');
+ dragData.ddel.className = 'multi-proxy';
+ this.collectSelection(dragData);
+ }
+ return dragData;
+ }
+ return false;
+ },
+
+// override the default repairXY.
+ getRepairXY : function(e){
+ return this.dragData.repairXY;
+ },
+
+/** Put the selections into the records and viewNodes Arrays. */
+ collectSelection: function(data) {
+ data.repairXY = Ext.fly(this.getSelectedNodes()[0]).getXY();
+ if (this.preserveSelectionOrder === true) {
+ Ext.each(this.getSelectedIndexes(), function(i) {
+ var n = this.getNode(i);
+ var dragNode = n.cloneNode(true);
+ dragNode.id = Ext.id();
+ data.ddel.appendChild(dragNode);
+ data.records.push(this.store.getAt(i));
+ data.viewNodes.push(n);
+ }, this);
+ } else {
+ var i = 0;
+ this.store.each(function(rec){
+ if (this.isSelected(i)) {
+ var n = this.getNode(i);
+ var dragNode = n.cloneNode(true);
+ dragNode.id = Ext.id();
+ data.ddel.appendChild(dragNode);
+ data.records.push(this.store.getAt(i));
+ data.viewNodes.push(n);
+ }
+ i++;
+ }, this);
+ }
+ },
+
+/** Specify to which ddGroup items in this DDView may be dragged. */
+ setDraggable: function(ddGroup) {
+ if (ddGroup instanceof Array) {
+ Ext.each(ddGroup, this.setDraggable, this);
+ return;
+ }
+ if (this.dragZone) {
+ this.dragZone.addToGroup(ddGroup);
+ } else {
+ this.dragZone = new Ext.dd.DragZone(this.getEl(), {
+ containerScroll: true,
+ ddGroup: ddGroup
+ });
+// Draggability implies selection. DragZone's mousedown selects the element.
+ if (!this.multiSelect) { this.singleSelect = true; }
+
+// Wire the DragZone's handlers up to methods in *this*
+ this.dragZone.getDragData = this.getDragData.createDelegate(this);
+ this.dragZone.getRepairXY = this.getRepairXY;
+ this.dragZone.onEndDrag = this.onEndDrag;
+ }
+ },
+
+/** Specify from which ddGroup this DDView accepts drops. */
+ setDroppable: function(ddGroup) {
+ if (ddGroup instanceof Array) {
+ Ext.each(ddGroup, this.setDroppable, this);
+ return;
+ }
+ if (this.dropZone) {
+ this.dropZone.addToGroup(ddGroup);
+ } else {
+ this.dropZone = new Ext.dd.DropZone(this.getEl(), {
+ owningView: this,
+ containerScroll: true,
+ ddGroup: ddGroup
+ });
+
+// Wire the DropZone's handlers up to methods in *this*
+ this.dropZone.getTargetFromEvent = this.getTargetFromEvent.createDelegate(this);
+ this.dropZone.onNodeEnter = this.onNodeEnter.createDelegate(this);
+ this.dropZone.onNodeOver = this.onNodeOver.createDelegate(this);
+ this.dropZone.onNodeOut = this.onNodeOut.createDelegate(this);
+ this.dropZone.onNodeDrop = this.onNodeDrop.createDelegate(this);
+ }
+ },
+
+/** Decide whether to drop above or below a View node. */
+ getDropPoint : function(e, n, dd){
+ if (n == this.el.dom) { return "above"; }
+ var t = Ext.lib.Dom.getY(n), b = t + n.offsetHeight;
+ var c = t + (b - t) / 2;
+ var y = Ext.lib.Event.getPageY(e);
+ if(y <= c) {
+ return "above";
+ }else{
+ return "below";
+ }
+ },
+
+ isValidDropPoint: function(pt, n, data) {
+ if (!data.viewNodes || (data.viewNodes.length != 1)) {
+ return true;
+ }
+ var d = data.viewNodes[0];
+ if (d == n) {
+ return false;
+ }
+ if ((pt == "below") && (n.nextSibling == d)) {
+ return false;
+ }
+ if ((pt == "above") && (n.previousSibling == d)) {
+ return false;
+ }
+ return true;
+ },
+
+ onNodeEnter : function(n, dd, e, data){
+ if (this.highlightColor && (data.sourceView != this)) {
+ this.el.highlight(this.highlightColor);
+ }
+ return false;
+ },
+
+ onNodeOver : function(n, dd, e, data){
+ var dragElClass = this.dropNotAllowed;
+ var pt = this.getDropPoint(e, n, dd);
+ if (this.isValidDropPoint(pt, n, data)) {
+ if (this.appendOnly || this.sortField) {
+ return "x-tree-drop-ok-below";
+ }
+
+// set the insert point style on the target node
+ if (pt) {
+ var targetElClass;
+ if (pt == "above"){
+ dragElClass = n.previousSibling ? "x-tree-drop-ok-between" : "x-tree-drop-ok-above";
+ targetElClass = "x-view-drag-insert-above";
+ } else {
+ dragElClass = n.nextSibling ? "x-tree-drop-ok-between" : "x-tree-drop-ok-below";
+ targetElClass = "x-view-drag-insert-below";
+ }
+ if (this.lastInsertClass != targetElClass){
+ Ext.fly(n).replaceClass(this.lastInsertClass, targetElClass);
+ this.lastInsertClass = targetElClass;
+ }
+ }
+ }
+ return dragElClass;
+ },
+
+ onNodeOut : function(n, dd, e, data){
+ this.removeDropIndicators(n);
+ },
+
+ onNodeDrop : function(n, dd, e, data){
+ if (this.fireEvent("drop", this, n, dd, e, data) === false) {
+ return false;
+ }
+ var pt = this.getDropPoint(e, n, dd);
+ var insertAt = (this.appendOnly || (n == this.el.dom)) ? this.store.getCount() : n.viewIndex;
+ if (pt == "below") {
+ insertAt++;
+ }
+
+// Validate if dragging within a DDView
+ if (data.sourceView == this) {
+// If the first element to be inserted below is the target node, remove it
+ if (pt == "below") {
+ if (data.viewNodes[0] == n) {
+ data.viewNodes.shift();
+ }
+ } else { // If the last element to be inserted above is the target node, remove it
+ if (data.viewNodes[data.viewNodes.length - 1] == n) {
+ data.viewNodes.pop();
+ }
+ }
+
+// Nothing to drop...
+ if (!data.viewNodes.length) {
+ return false;
+ }
+
+// If we are moving DOWN, then because a store.remove() takes place first,
+// the insertAt must be decremented.
+ if (insertAt > this.store.indexOf(data.records[0])) {
+ insertAt--;
+ }
+ }
+
+// Dragging from a Tree. Use the Tree's recordFromNode function.
+ if (data.node instanceof Ext.tree.TreeNode) {
+ var r = data.node.getOwnerTree().recordFromNode(data.node);
+ if (r) {
+ data.records = [ r ];
+ }
+ }
+
+ if (!data.records) {
+ alert("Programming problem. Drag data contained no Records");
+ return false;
+ }
+
+ for (var i = 0; i < data.records.length; i++) {
+ var r = data.records[i];
+ var dup = this.store.getById(r.id);
+ if (dup && (dd != this.dragZone)) {
+ if(!this.allowDup && !this.allowTrash){
+ Ext.fly(this.getNode(this.store.indexOf(dup))).frame("red", 1);
+ return true
+ }
+ var x=new Ext.data.Record();
+ r.id=x.id;
+ delete x;
+ }
+ if (data.copy) {
+ this.store.insert(insertAt++, r.copy());
+ } else {
+ if (data.sourceView) {
+ data.sourceView.isDirtyFlag = true;
+ data.sourceView.store.remove(r);
+ }
+ if(!this.allowTrash)this.store.insert(insertAt++, r);
+ }
+ if(this.sortField){
+ this.store.sort(this.sortField, this.sortDir);
+ }
+ this.isDirtyFlag = true;
+ }
+ this.dragZone.cachedTarget = null;
+ return true;
+ },
+
+// Ensure the multi proxy is removed
+ onEndDrag: function(data, e) {
+ var d = Ext.get(this.dragData.ddel);
+ if (d && d.hasClass("multi-proxy")) {
+ d.remove();
+ //delete this.dragData.ddel;
+ }
+ },
+
+ removeDropIndicators : function(n){
+ if(n){
+ Ext.fly(n).removeClass([
+ "x-view-drag-insert-above",
+ "x-view-drag-insert-left",
+ "x-view-drag-insert-right",
+ "x-view-drag-insert-below"]);
+ this.lastInsertClass = "_noclass";
+ }
+ },
+
+/**
+ * Utility method. Add a delete option to the DDView's context menu.
+ * @param {String} imageUrl The URL of the "delete" icon image.
+ */
+ setDeletable: function(imageUrl) {
+ if (!this.singleSelect && !this.multiSelect) {
+ this.singleSelect = true;
+ }
+ var c = this.getContextMenu();
+ this.contextMenu.on("itemclick", function(item) {
+ switch (item.id) {
+ case "delete":
+ this.remove(this.getSelectedIndexes());
+ break;
+ }
+ }, this);
+ this.contextMenu.add({
+ icon: imageUrl || AU.resolveUrl("/images/delete.gif"),
+ id: "delete",
+ text: AU.getMessage("deleteItem")
+ });
+ },
+
+/** Return the context menu for this DDView. */
+ getContextMenu: function() {
+ if (!this.contextMenu) {
+// Create the View's context menu
+ this.contextMenu = new Ext.menu.Menu({
+ id: this.id + "-contextmenu"
+ });
+ this.el.on("contextmenu", this.showContextMenu, this);
+ }
+ return this.contextMenu;
+ },
+
+ disableContextMenu: function() {
+ if (this.contextMenu) {
+ this.el.un("contextmenu", this.showContextMenu, this);
+ }
+ },
+
+ showContextMenu: function(e, item) {
+ item = this.findItemFromChild(e.getTarget());
+ if (item) {
+ e.stopEvent();
+ this.select(this.getNode(item), this.multiSelect && e.ctrlKey, true);
+ this.contextMenu.showAt(e.getXY());
+ }
+ },
+
+/**
+ * Remove {@link Ext.data.Record}s at the specified indices.
+ * @param {Array/Number} selectedIndices The index (or Array of indices) of Records to remove.
+ */
+ remove: function(selectedIndices) {
+ selectedIndices = [].concat(selectedIndices);
+ for (var i = 0; i < selectedIndices.length; i++) {
+ var rec = this.store.getAt(selectedIndices[i]);
+ this.store.remove(rec);
+ }
+ },
+
+/**
+ * Double click fires the event, but also, if this is draggable, and there is only one other
+ * related DropZone that is in another DDView, it drops the selected node on that DDView.
+ */
+ onDblClick : function(e){
+ var item = this.findItemFromChild(e.getTarget());
+ if(item){
+ if (this.fireEvent("dblclick", this, this.indexOf(item), item, e) === false) {
+ return false;
+ }
+ if (this.dragGroup) {
+ var targets = Ext.dd.DragDropMgr.getRelated(this.dragZone, true);
+
+// Remove instances of this View's DropZone
+ while (targets.contains(this.dropZone)) {
+ targets.remove(this.dropZone);
+ }
+
+// If there's only one other DropZone, and it is owned by a DDView, then drop it in
+ if ((targets.length == 1) && (targets[0].owningView)) {
+ this.dragZone.cachedTarget = null;
+ var el = Ext.get(targets[0].getEl());
+ var box = el.getBox(true);
+ targets[0].onNodeDrop(el.dom, {
+ target: el.dom,
+ xy: [box.x, box.y + box.height - 1]
+ }, null, this.getDragData(e));
+ }
+ }
+ }
+ },
+
+ onItemClick : function(item, index, e){
+// The DragZone's mousedown->getDragData already handled selection
+ if (this.ignoreNextClick) {
+ delete this.ignoreNextClick;
+ return;
+ }
+
+ if(this.fireEvent("beforeclick", this, index, item, e) === false){
+ return false;
+ }
+ if(this.multiSelect || this.singleSelect){
+ if(this.multiSelect && e.shiftKey && this.lastSelection){
+ this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
+ } else if (this.isSelected(item) && e.ctrlKey) {
+ this.deselect(item);
+ }else{
+ this.deselect(item);
+ this.select(item, this.multiSelect && e.ctrlKey);
+ this.lastSelection = item;
+ }
+ e.preventDefault();
+ }
+ return true;
+ }
+});
+
+
+//version 3.0
+
+Ext.ux.Multiselect = Ext.extend(Ext.form.Field, {
+ store:null,
+ dataFields:[],
+ data:[],
+ width:100,
+ height:100,
+ displayField:0,
+ valueField:1,
+ allowBlank:true,
+ minLength:0,
+ maxLength:Number.MAX_VALUE,
+ blankText:Ext.form.TextField.prototype.blankText,
+ minLengthText:'Minimum {0} item(s) required',
+ maxLengthText:'Maximum {0} item(s) allowed',
+ copy:false,
+ allowDup:false,
+ allowTrash:false,
+ legend:null,
+ focusClass:undefined,
+ delimiter:',',
+ view:null,
+ dragGroup:null,
+ dropGroup:null,
+ tbar:null,
+ appendOnly:false,
+ sortField:null,
+ sortDir:'ASC',
+ defaultAutoCreate : {tag: "div"},
+
+ initComponent: function(){
+ Ext.ux.Multiselect.superclass.initComponent.call(this);
+ this.addEvents({
+ 'dblclick' : true,
+ 'click' : true,
+ 'change' : true,
+ 'drop' : true
+ });
+ },
+ onRender: function(ct, position){
+ var fs, cls, tpl;
+ Ext.ux.Multiselect.superclass.onRender.call(this, ct, position);
+
+ cls = 'ux-mselect';
+
+ fs = new Ext.form.FieldSet({
+ renderTo:this.el,
+ title:this.legend,
+ height:this.height,
+ width:this.width,
+ style:"padding:1px;",
+ tbar:this.tbar
+ });
+ if(!this.legend)fs.el.down('.'+fs.headerCls).remove();
+ fs.body.addClass(cls);
+
+ tpl = '<tpl for="."><div class="' + cls + '-item';
+ if(Ext.isIE || Ext.isIE7)tpl+='" unselectable=on';
+ else tpl+=' x-unselectable"';
+ tpl+='>{' + this.displayField + '}</div></tpl>';
+
+ if(!this.store){
+ this.store = new Ext.data.SimpleStore({
+ fields: this.dataFields,
+ data : this.data
+ });
+ }
+
+ this.view = new Ext.ux.DDView({
+ multiSelect: true, store: this.store, selectedClass: cls+"-selected", tpl:tpl,
+ allowDup:this.allowDup, copy: this.copy, allowTrash: this.allowTrash,
+ dragGroup: this.dragGroup, dropGroup: this.dropGroup, itemSelector:"."+cls+"-item",
+ isFormField:false, applyTo:fs.body, appendOnly:this.appendOnly,
+ sortField:this.sortField, sortDir:this.sortDir
+ });
+
+ fs.add(this.view);
+
+ this.view.on('click', this.onViewClick, this);
+ this.view.on('beforeClick', this.onViewBeforeClick, this);
+ this.view.on('dblclick', this.onViewDblClick, this);
+ this.view.on('drop', function(ddView, n, dd, e, data){
+ return this.fireEvent("drop", ddView, n, dd, e, data);
+ }, this);
+
+ this.hiddenName = this.name;
+ var hiddenTag={tag: "input", type: "hidden", value: "", name:this.name};
+ if (this.isFormField) {
+ this.hiddenField = this.el.createChild(hiddenTag);
+ } else {
+ this.hiddenField = Ext.get(document.body).createChild(hiddenTag);
+ }
+ fs.doLayout();
+ },
+
+ initValue:Ext.emptyFn,
+
+ onViewClick: function(vw, index, node, e) {
+ var arrayIndex = this.preClickSelections.indexOf(index);
+ if (arrayIndex != -1)
+ {
+ this.preClickSelections.splice(arrayIndex, 1);
+ this.view.clearSelections(true);
+ this.view.select(this.preClickSelections);
+ }
+ this.fireEvent('change', this, this.getValue(), this.hiddenField.dom.value);
+ this.hiddenField.dom.value = this.getValue();
+ this.fireEvent('click', this, e);
+ this.validate();
+ },
+
+ onViewBeforeClick: function(vw, index, node, e) {
+ this.preClickSelections = this.view.getSelectedIndexes();
+ if (this.disabled) {return false;}
+ },
+
+ onViewDblClick : function(vw, index, node, e) {
+ return this.fireEvent('dblclick', vw, index, node, e);
+ },
+
+ getValue: function(valueField){
+ var returnArray = [];
+ var selectionsArray = this.view.getSelectedIndexes();
+ if (selectionsArray.length == 0) {return '';}
+ for (var i=0; i<selectionsArray.length; i++) {
+ returnArray.push(this.store.getAt(selectionsArray[i]).get(((valueField != null)? valueField : this.valueField)));
+ }
+ return returnArray.join(this.delimiter);
+ },
+
+ setValue: function(values) {
+ var index;
+ var selections = [];
+ this.view.clearSelections();
+ this.hiddenField.dom.value = '';
+
+ if (!values || (values == '')) { return; }
+
+ if (!(values instanceof Array)) { values = values.split(this.delimiter); }
+ for (var i=0; i<values.length; i++) {
+ index = this.view.store.indexOf(this.view.store.query(this.valueField,
+ new RegExp('^' + values[i] + '$', "i")).itemAt(0));
+ selections.push(index);
+ }
+ this.view.select(selections);
+ this.hiddenField.dom.value = this.getValue();
+ this.validate();
+ },
+
+ reset : function() {
+ this.setValue('');
+ },
+
+ getRawValue: function(valueField) {
+ var tmp = this.getValue(valueField);
+ if (tmp.length) {
+ tmp = tmp.split(this.delimiter);
+ }
+ else{
+ tmp = [];
+ }
+ return tmp;
+ },
+
+ setRawValue: function(values){
+ setValue(values);
+ },
+
+ validateValue : function(value){
+ if (value.length < 1) { // if it has no value
+ if (this.allowBlank) {
+ this.clearInvalid();
+ return true;
+ } else {
+ this.markInvalid(this.blankText);
+ return false;
+ }
+ }
+ if (value.length < this.minLength) {
+ this.markInvalid(String.format(this.minLengthText, this.minLength));
+ return false;
+ }
+ if (value.length > this.maxLength) {
+ this.markInvalid(String.format(this.maxLengthText, this.maxLength));
+ return false;
+ }
+ return true;
+ }
+});
+
+Ext.reg("multiselect", Ext.ux.Multiselect);
+
+Ext.ux.ItemSelector = Ext.extend(Ext.form.Field, {
+ msWidth:200,
+ msHeight:300,
+ hideNavIcons:false,
+ imagePath:"",
+ iconUp:"up2.gif",
+ iconDown:"down2.gif",
+ iconLeft:"left2.gif",
+ iconRight:"right2.gif",
+ iconTop:"top2.gif",
+ iconBottom:"bottom2.gif",
+ drawUpIcon:true,
+ drawDownIcon:true,
+ drawLeftIcon:true,
+ drawRightIcon:true,
+ drawTopIcon:true,
+ drawBotIcon:true,
+ fromStore:null,
+ toStore:null,
+ fromData:null,
+ toData:null,
+ displayField:0,
+ valueField:1,
+ switchToFrom:false,
+ allowDup:false,
+ focusClass:undefined,
+ delimiter:',',
+ readOnly:false,
+ toLegend:null,
+ fromLegend:null,
+ toSortField:null,
+ fromSortField:null,
+ toSortDir:'ASC',
+ fromSortDir:'ASC',
+ toTBar:null,
+ fromTBar:null,
+ bodyStyle:null,
+ border:false,
+ defaultAutoCreate:{tag: "div"},
+
+ initComponent: function(){
+ Ext.ux.ItemSelector.superclass.initComponent.call(this);
+ this.addEvents({
+ 'rowdblclick' : true,
+ 'change' : true
+ });
+ },
+
+ onRender: function(ct, position){
+ Ext.ux.ItemSelector.superclass.onRender.call(this, ct, position);
+
+ this.fromMultiselect = new Ext.ux.Multiselect({
+ legend: this.fromLegend,
+ delimiter: this.delimiter,
+ allowDup: this.allowDup,
+ copy: this.allowDup,
+ allowTrash: this.allowDup,
+ dragGroup: this.readOnly ? null : "drop2-"+this.el.dom.id,
+ dropGroup: this.readOnly ? null : "drop1-"+this.el.dom.id,
+ width: this.msWidth,
+ height: this.msHeight,
+ dataFields: this.dataFields,
+ data: this.fromData,
+ displayField: this.displayField,
+ valueField: this.valueField,
+ store: this.fromStore,
+ isFormField: false,
+ tbar: this.fromTBar,
+ appendOnly: true,
+ sortField: this.fromSortField,
+ sortDir: this.fromSortDir
+ });
+ this.fromMultiselect.on('dblclick', this.onRowDblClick, this);
+
+ if (!this.toStore) {
+ this.toStore = new Ext.data.SimpleStore({
+ fields: this.dataFields,
+ data : this.toData
+ });
+ }
+ this.toStore.on('add', this.valueChanged, this);
+ this.toStore.on('remove', this.valueChanged, this);
+ this.toStore.on('load', this.valueChanged, this);
+
+ this.toMultiselect = new Ext.ux.Multiselect({
+ legend: this.toLegend,
+ delimiter: this.delimiter,
+ allowDup: this.allowDup,
+ dragGroup: this.readOnly ? null : "drop1-"+this.el.dom.id,
+ //dropGroup: this.readOnly ? null : "drop2-"+this.el.dom.id+(this.toSortField ? "" : ",drop1-"+this.el.dom.id),
+ dropGroup: this.readOnly ? null : "drop2-"+this.el.dom.id+",drop1-"+this.el.dom.id,
+ width: this.msWidth,
+ height: this.msHeight,
+ displayField: this.displayField,
+ valueField: this.valueField,
+ store: this.toStore,
+ isFormField: false,
+ tbar: this.toTBar,
+ sortField: this.toSortField,
+ sortDir: this.toSortDir
+ });
+ this.toMultiselect.on('dblclick', this.onRowDblClick, this);
+
+ var p = new Ext.Panel({
+ bodyStyle:this.bodyStyle,
+ border:this.border,
+ layout:"table",
+ layoutConfig:{columns:3}
+ });
+ p.add(this.switchToFrom ? this.toMultiselect : this.fromMultiselect);
+ var icons = new Ext.Panel({header:false});
+ p.add(icons);
+ p.add(this.switchToFrom ? this.fromMultiselect : this.toMultiselect);
+ p.render(this.el);
+ icons.el.down('.'+icons.bwrapCls).remove();
+
+ if (this.imagePath!="" && this.imagePath.charAt(this.imagePath.length-1)!="/")
+ this.imagePath+="/";
+ this.iconUp = this.imagePath + (this.iconUp || 'up2.gif');
+ this.iconDown = this.imagePath + (this.iconDown || 'down2.gif');
+ this.iconLeft = this.imagePath + (this.iconLeft || 'left2.gif');
+ this.iconRight = this.imagePath + (this.iconRight || 'right2.gif');
+ this.iconTop = this.imagePath + (this.iconTop || 'top2.gif');
+ this.iconBottom = this.imagePath + (this.iconBottom || 'bottom2.gif');
+ var el=icons.getEl();
+ if (!this.toSortField) {
+ this.toTopIcon = el.createChild({tag:'img', src:this.iconTop, style:{cursor:'pointer', margin:'2px'}});
+ el.createChild({tag: 'br'});
+ this.upIcon = el.createChild({tag:'img', src:this.iconUp, style:{cursor:'pointer', margin:'2px'}});
+ el.createChild({tag: 'br'});
+ }
+ this.addIcon = el.createChild({tag:'img', src:this.switchToFrom?this.iconLeft:this.iconRight, style:{cursor:'pointer', margin:'2px'}});
+ el.createChild({tag: 'br'});
+ this.removeIcon = el.createChild({tag:'img', src:this.switchToFrom?this.iconRight:this.iconLeft, style:{cursor:'pointer', margin:'2px'}});
+ el.createChild({tag: 'br'});
+ if (!this.toSortField) {
+ this.downIcon = el.createChild({tag:'img', src:this.iconDown, style:{cursor:'pointer', margin:'2px'}});
+ el.createChild({tag: 'br'});
+ this.toBottomIcon = el.createChild({tag:'img', src:this.iconBottom, style:{cursor:'pointer', margin:'2px'}});
+ }
+ if (!this.readOnly) {
+ if (!this.toSortField) {
+ this.toTopIcon.on('click', this.toTop, this);
+ this.upIcon.on('click', this.up, this);
+ this.downIcon.on('click', this.down, this);
+ this.toBottomIcon.on('click', this.toBottom, this);
+ }
+ this.addIcon.on('click', this.fromTo, this);
+ this.removeIcon.on('click', this.toFrom, this);
+ }
+ if (!this.drawUpIcon || this.hideNavIcons) { this.upIcon.dom.style.display='none'; }
+ if (!this.drawDownIcon || this.hideNavIcons) { this.downIcon.dom.style.display='none'; }
+ if (!this.drawLeftIcon || this.hideNavIcons) { this.addIcon.dom.style.display='none'; }
+ if (!this.drawRightIcon || this.hideNavIcons) { this.removeIcon.dom.style.display='none'; }
+ if (!this.drawTopIcon || this.hideNavIcons) { this.toTopIcon.dom.style.display='none'; }
+ if (!this.drawBotIcon || this.hideNavIcons) { this.toBottomIcon.dom.style.display='none'; }
+
+ var tb = p.body.first();
+ this.el.setWidth(p.body.first().getWidth());
+ p.body.removeClass();
+
+ this.hiddenName = this.name;
+ var hiddenTag={tag: "input", type: "hidden", value: "", name:this.name};
+ this.hiddenField = this.el.createChild(hiddenTag);
+ this.valueChanged(this.toStore);
+ },
+
+ initValue:Ext.emptyFn,
+
+ toTop : function() {
+ var selectionsArray = this.toMultiselect.view.getSelectedIndexes();
+ var records = [];
+ if (selectionsArray.length > 0) {
+ selectionsArray.sort();
+ for (var i=0; i<selectionsArray.length; i++) {
+ record = this.toMultiselect.view.store.getAt(selectionsArray[i]);
+ records.push(record);
+ }
+ selectionsArray = [];
+ for (var i=records.length-1; i>-1; i--) {
+ record = records[i];
+ this.toMultiselect.view.store.remove(record);
+ this.toMultiselect.view.store.insert(0, record);
+ selectionsArray.push(((records.length - 1) - i));
+ }
+ }
+ this.toMultiselect.view.refresh();
+ this.toMultiselect.view.select(selectionsArray);
+ },
+
+ toBottom : function() {
+ var selectionsArray = this.toMultiselect.view.getSelectedIndexes();
+ var records = [];
+ if (selectionsArray.length > 0) {
+ selectionsArray.sort();
+ for (var i=0; i<selectionsArray.length; i++) {
+ record = this.toMultiselect.view.store.getAt(selectionsArray[i]);
+ records.push(record);
+ }
+ selectionsArray = [];
+ for (var i=0; i<records.length; i++) {
+ record = records[i];
+ this.toMultiselect.view.store.remove(record);
+ this.toMultiselect.view.store.add(record);
+ selectionsArray.push((this.toMultiselect.view.store.getCount()) - (records.length - i));
+ }
+ }
+ this.toMultiselect.view.refresh();
+ this.toMultiselect.view.select(selectionsArray);
+ },
+
+ up : function() {
+ var record = null;
+ var selectionsArray = this.toMultiselect.view.getSelectedIndexes();
+ selectionsArray.sort();
+ var newSelectionsArray = [];
+ if (selectionsArray.length > 0) {
+ for (var i=0; i<selectionsArray.length; i++) {
+ record = this.toMultiselect.view.store.getAt(selectionsArray[i]);
+ if ((selectionsArray[i] - 1) >= 0) {
+ this.toMultiselect.view.store.remove(record);
+ this.toMultiselect.view.store.insert(selectionsArray[i] - 1, record);
+ newSelectionsArray.push(selectionsArray[i] - 1);
+ }
+ }
+ this.toMultiselect.view.refresh();
+ this.toMultiselect.view.select(newSelectionsArray);
+ }
+ },
+
+ down : function() {
+ var record = null;
+ var selectionsArray = this.toMultiselect.view.getSelectedIndexes();
+ selectionsArray.sort();
+ selectionsArray.reverse();
+ var newSelectionsArray = [];
+ if (selectionsArray.length > 0) {
+ for (var i=0; i<selectionsArray.length; i++) {
+ record = this.toMultiselect.view.store.getAt(selectionsArray[i]);
+ if ((selectionsArray[i] + 1) < this.toMultiselect.view.store.getCount()) {
+ this.toMultiselect.view.store.remove(record);
+ this.toMultiselect.view.store.insert(selectionsArray[i] + 1, record);
+ newSelectionsArray.push(selectionsArray[i] + 1);
+ }
+ }
+ this.toMultiselect.view.refresh();
+ this.toMultiselect.view.select(newSelectionsArray);
+ }
+ },
+
+ fromTo : function() {
+ var selectionsArray = this.fromMultiselect.view.getSelectedIndexes();
+ var records = [];
+ if (selectionsArray.length > 0) {
+ for (var i=0; i<selectionsArray.length; i++) {
+ record = this.fromMultiselect.view.store.getAt(selectionsArray[i]);
+ records.push(record);
+ }
+ if(!this.allowDup)selectionsArray = [];
+ for (var i=0; i<records.length; i++) {
+ record = records[i];
+ if(this.allowDup){
+ var x=new Ext.data.Record();
+ record.id=x.id;
+ delete x;
+ this.toMultiselect.view.store.add(record);
+ }else{
+ this.fromMultiselect.view.store.remove(record);
+ this.toMultiselect.view.store.add(record);
+ selectionsArray.push((this.toMultiselect.view.store.getCount() - 1));
+ }
+ }
+ }
+ this.toMultiselect.view.refresh();
+ this.fromMultiselect.view.refresh();
+ if(this.toSortField)this.toMultiselect.store.sort(this.toSortField, this.toSortDir);
+ if(this.allowDup)this.fromMultiselect.view.select(selectionsArray);
+ else this.toMultiselect.view.select(selectionsArray);
+ },
+
+ toFrom : function() {
+ var selectionsArray = this.toMultiselect.view.getSelectedIndexes();
+ var records = [];
+ if (selectionsArray.length > 0) {
+ for (var i=0; i<selectionsArray.length; i++) {
+ record = this.toMultiselect.view.store.getAt(selectionsArray[i]);
+ records.push(record);
+ }
+ selectionsArray = [];
+ for (var i=0; i<records.length; i++) {
+ record = records[i];
+ this.toMultiselect.view.store.remove(record);
+ if(!this.allowDup){
+ this.fromMultiselect.view.store.add(record);
+ selectionsArray.push((this.fromMultiselect.view.store.getCount() - 1));
+ }
+ }
+ }
+ this.fromMultiselect.view.refresh();
+ this.toMultiselect.view.refresh();
+ if(this.fromSortField)this.fromMultiselect.store.sort(this.fromSortField, this.fromSortDir);
+ this.fromMultiselect.view.select(selectionsArray);
+ },
+
+ valueChanged: function(store) {
+ var record = null;
+ var values = [];
+ for (var i=0; i<store.getCount(); i++) {
+ record = store.getAt(i);
+ values.push(record.get(this.valueField));
+ }
+ this.hiddenField.dom.value = values.join(this.delimiter);
+ this.fireEvent('change', this, this.getValue(), this.hiddenField.dom.value);
+ },
+
+ getValue : function() {
+ return this.hiddenField.dom.value;
+ },
+
+ onRowDblClick : function(vw, index, node, e) {
+ return this.fireEvent('rowdblclick', vw, index, node, e);
+ },
+
+ reset: function(){
+ range = this.toMultiselect.store.getRange();
+ this.toMultiselect.store.removeAll();
+ if (!this.allowDup) {
+ this.fromMultiselect.store.add(range);
+ this.fromMultiselect.store.sort(this.displayField,'ASC');
+ }
+ this.valueChanged(this.toMultiselect.store);
+ }
+});
+
+Ext.reg("itemselector", Ext.ux.ItemSelector);
\ No newline at end of file
Added: trunk/qo-kregator/ux/MultiselectItemSelector/bottom2.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/MultiselectItemSelector/bottom2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/MultiselectItemSelector/down2.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/MultiselectItemSelector/down2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/MultiselectItemSelector/left2.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/MultiselectItemSelector/left2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/MultiselectItemSelector/right2.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/MultiselectItemSelector/right2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/MultiselectItemSelector/top2.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/MultiselectItemSelector/top2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/MultiselectItemSelector/up2.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/MultiselectItemSelector/up2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/miframe/miframe.js
===================================================================
--- trunk/qo-kregator/ux/miframe/miframe.js (rev 0)
+++ trunk/qo-kregator/ux/miframe/miframe.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,2569 @@
+/* global Ext */
+/*******************************************************************************
+ * This file is distributed on an AS IS BASIS WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * ***********************************************************************************
+ *
+ * License: ux.ManagedIFrame and ux.ManagedIFramePanel 1.2 are licensed under
+ * the terms of the Open Source LGPL 3.0 license:
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Commercial use is prohibited without a Commercial License. See
+ * http://licensing.theactivegroup.com.
+ *
+ * Donations are welcomed: http://donate.theactivegroup.com
+ *
+ * <p>
+ * An Ext.Element harness for iframe elements.
+ *
+ * Adds Ext.UpdateManager(Updater) support and a compatible 'update' method for
+ * writing content directly into an iFrames' document structure.
+ *
+ * Signals various DOM/document states as the frames content changes with
+ * 'domready', 'documentloaded', and 'exception' events. The domready event is
+ * only raised when a proper security context exists for the frame's DOM to
+ * permit modification. (ie, Updates via Updater or documents retrieved from
+ * same-domain servers).
+ *
+ * Frame sand-box permits eval/script-tag writes of javascript source. (See
+ * execScript, writeScript, and loadFunction methods for more info.)
+ *
+ * Usage:<br>
+ *
+ * <pre><code>
+ * // Harnessed from an existing Iframe from markup:
+ * var i = new Ext.ux.ManagedIFrame("myIframe");
+ * // Replace the iFrames document structure with the response from the requested URL.
+ * i.load("http://myserver.com/index.php", "param1=1&param2=2");
+ *
+ * // Notes: this is not the same as setting the Iframes src property !
+ * // Content loaded in this fashion does not share the same document namespaces as it's parent --
+ * // meaning, there (by default) will be no Ext namespace defined in it since the document is
+ * // overwritten after each call to the update method, and no styleSheets.
+ * </code></pre>
+ *
+ * <br>
+ *
+ * Release: 1.2.1( 11/3/2008)
+ * Mod: Corrected <noframes> support (unsupportedText)
+ * Mod: Improved domready detection for Opera, Webkit, and IE. jsDOC updates.
+ * Mod: MIFP frameConfig now honors either frameConfig:{id:'someId': name:'someName',....}
+ * or frameConfig: {autoCreate:{ id:'someId': name:'someName',....}}
+ * Add: resetUrl class property to override the reset URL used by default with the reset method.
+ * Add: (MIF/MIFP):setLocation method. Identical to setSrc, but uses location.replace
+ * on the frame instead, preventing a History update.
+ * Add: scope parameter to
+ * all methods supporting callbacks
+ * Mod: callbacks are invoke as soon as domready status is detected.
+ * Mod: MIFPanel now honors the contentEl cfg option, meaning IFRAMEs authored in page markup
+ * may be converted to MIFrames when the Panel is rendered.
+ *
+ * 1.2 (8/22/2008) FF3 Compatibility Fixes, loadMask tweaks
+ *
+ * 1.1 (4/13/2008) Adds Ext.Element, CSS Selectors (query,select) fly, and CSS
+ * interface support (same-domain only) Adds blur,focus,unload events
+ * (same-domain only)
+ *
+ */
+
+(function() {
+
+ var EV = Ext.lib.Event;
+ var MIM;
+ /**
+ * @class Ext.ux.ManagedIFrame
+ * @extends Ext.Element
+ * @extends Ext.util.Observable
+ * @version: 1.2.1 - 10/9/2008
+ * @license <a href="http://www.gnu.org/licenses/lgpl.html">LGPL 3.0</a>
+ * @author: Doug Hendricks. Forum ID: <a href="http://extjs.com/forum/member.php?u=8730">hendricd</a>
+ * @donate <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+<input type="hidden" name="cmd" value="_donations">
+<input type="hidden" name="business" value="doug@xxxxxxxxxxxxxxxxxx">
+<input type="hidden" name="item_name" value="ux.ManagedIFrame">
+<input type="hidden" name="item_number" value="MIF/P">
+<input type="hidden" name="no_shipping" value="1">
+<input type="hidden" name="return" value="http://donate.theactivegroup.com/thankyou.html">
+<input type="hidden" name="cn" value="Optional Comments">
+<input type="hidden" name="currency_code" value="USD">
+<input type="hidden" name="tax" value="0">
+<input type="hidden" name="lc" value="US">
+<input type="hidden" name="bn" value="PP-DonationsBF">
+<input type="image" src="http://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
+<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
+</form>
+ *
+ * @cfg {Boolean/Object} autoCreate True to auto generate the IFRAME element, or a {@link Ext.DomHelper} config of the IFRAME to create
+ * @cfg {String} html Any markup to be applied to the IFRAME's document content when rendered.
+ * @cfg {Object} loadMask An {@link Ext.LoadMask} config or true to mask the iframe while using the update or setSrc methods (defaults to false).
+ * @cfg {Object} src The src attribute to be assigned to the Iframe after initialization (overrides the autoCreate config src attribute)
+ * @constructor
+ * @param {Mixed} el, Config object The iframe element or it's id to harness or a valid config object.
+ */
+
+ /** @private */
+
+ Ext.ux.ManagedIFrame = function() {
+ var args = Array.prototype.slice.call(arguments, 0),
+ el = Ext.get(args[0]),
+ config = args[0];
+
+ if (el && el.dom && el.dom.tagName == 'IFRAME') {
+ config = args[1] || {};
+ } else {
+ config = args[0] || args[1] || {};
+
+ el = config.autoCreate ? Ext.get(Ext.DomHelper.append(
+ config.autoCreate.parent || Ext.getBody(), Ext.apply({
+ tag : 'iframe',
+ frameborder : 0,
+ src : (Ext.isIE && Ext.isSecure)? Ext.SSL_SECURE_URL: 'about:blank'
+ }, config.autoCreate)))
+ : null;
+
+ if(el && this.unsupportedText){
+ Ext.DomHelper.append(el.dom.parentNode, {tag:'noframes',html:this.unsupportedText } );
+ }
+ }
+
+ if (!el || el.dom.tagName != 'IFRAME') { return el; }
+
+ el.dom.name || (el.dom.name = el.dom.id); // make sure there is a valid frame name
+ el.dom.ownerEl = el;
+
+ this.addEvents({
+ /**
+ * Fires when the frame gets focus. Note: This event is only
+ * available when overwriting the iframe document using the
+ * {@link #Ext.ux.ManagedIFrame-update} method and to pages
+ * retrieved from a "same-origin" domain. Returning false from the
+ * eventHandler [MAY] NOT cancel the event, as this event is NOT
+ * ALWAYS cancellable in all browsers.
+ *
+ * @event focus
+ * @param {Ext.ux.ManagedIFrame} this
+ * @param {Ext.Event} event
+ *
+ */
+ "focus" : true,
+
+ /**
+ * Fires when the frame is blurred (loses focus). Note: This event
+ * is only available when overwriting the iframe document using the
+ * update method and to pages retrieved from a "same-origin" domain.
+ * Returning false from the eventHandler [MAY] NOT cancel the event,
+ * as this event is NOT ALWAYS cancellable in all browsers.
+ *
+ * @event blur
+ * @param {Ext.ux.ManagedIFrame} this
+ * @param {Ext.Event} event
+ */
+ "blur" : true,
+
+ /**
+ * Note: This event is only available when overwriting the iframe
+ * document using the {@link #Ext.ux.ManagedIFrame-update} method
+ * and to documents retrieved from a "same-origin" domains. Fires
+ * when(if) the frames window object raises the unload event<br />
+ * Note: Opera does not raise this event.
+ *
+ * @event unload
+ * @param {Ext.ux.ManagedIFrame} this
+ * @param {Ext.Event} event
+ */
+ "unload" : true,
+
+ /**
+ * Note: This event is only available when overwriting the iframe
+ * document using the {@link #Ext.ux.ManagedIFrame-update} method
+ * and to documents retrieved from a "same-origin" domains. Fires
+ * ONLY when an iFrame's Document(DOM) has reach a state where the
+ * DOM may be manipulated (ie same domain policy) Returning false
+ * from the eventHandler stops further event (documentloaded)
+ * processing.
+ *
+ * @event domready
+ * @param {Ext.ux.ManagedIFrame} this
+ */
+ "domready" : true,
+
+ /**
+ * Fires when the iFrame has reached a loaded/complete state.
+ *
+ * @event documentloaded
+ * @param {Ext.ux.ManagedIFrame} this
+ */
+ "documentloaded" : true,
+
+ /**
+ * Fires when the frame actions raise an error
+ *
+ * @event exception
+ * @param {Ext.ux.ManagedIFrame} this
+ * @param {Error|string} exception
+ */
+ "exception" : true,
+ /**
+ * Fires upon receipt of a message generated by window.sendMessage
+ * method of the embedded Iframe.window object
+ *
+ * @event message
+ * @param {Ext.ux.ManagedIFrame} this
+ * @param {Object} message members:
+ * <ul>
+ * <li><b>type</b> {string}
+ * <p class="sub-desc">
+ * literal "message"
+ * </p>
+ * </li>
+ * <li><b>data</b> {Mixed}
+ * <p class="sub-desc">
+ * the message payload]
+ * </p>
+ * </li>
+ * <li><b>domain</b> {String}
+ * <p class="sub-desc">
+ * the document domain from which the message originated
+ * </p>
+ * </li>
+ * <li><b>uri</b> {string}
+ * <p class="sub-desc">
+ * the document URI of the message sender
+ * </p>
+ * </li>
+ * <li><b>source</b> (Object)
+ * <p class="sub-desc">
+ * the window context of the message sender
+ * </p>
+ * </li>
+ * <li><b>tag</b> {string}
+ * <p class="sub-desc">
+ * optional reference tag sent by the message sender }
+ * </p>
+ * </li>
+ * </ul>
+ */
+ "message" : true
+ // "message:tagName" is supported for X-frame messaging
+ /**
+ * Alternate event handler syntax for message:tag filtering
+ * Fires upon receipt of a message generated by
+ * window.sendMessage method which includes a specific tag value
+ * of the embedded Iframe.window object
+ *
+ * @event message:tag
+ * @param {Ext.ux.ManagedIFrame} this
+ * @param {Object} message members:
+ * <ul>
+ * <li><b>type</b> {string}
+ * <p class="sub-desc">
+ * literal "message"
+ * </p>
+ * </li>
+ * <li><b>data</b> {Mixed}
+ * <p class="sub-desc">
+ * the message payload]
+ * </p>
+ * </li>
+ * <li><b>domain</b> {String}
+ * <p class="sub-desc">
+ * the document domain from which the message
+ * originated
+ * </p>
+ * </li>
+ * <li><b>uri</b> {string}
+ * <p class="sub-desc">
+ * the document URI of the message sender
+ * </p>
+ * </li>
+ * <li><b>source</b> (Object)
+ * <p class="sub-desc">
+ * the window context of the message sender
+ * </p>
+ * </li>
+ * <li><b>tag</b> {string}
+ * <p class="sub-desc">
+ * optional reference tag sent by the message sender }
+ * </p>
+ * </li>
+ * </ul>
+ */
+
+ });
+
+ if (config.listeners) {
+ this.listeners = config.listeners;
+ Ext.ux.ManagedIFrame.superclass.constructor.call(this);
+ }
+
+ Ext.apply(el, this); // apply this class interface ( pseudo Decorator
+ // )
+
+ el.addClass('x-managed-iframe');
+ if (config.style) {
+ el.applyStyles(config.style);
+ }
+
+ Ext.apply(el, {
+ disableMessaging : config.disableMessaging === true,
+ loadMask : !!config.loadMask ? Ext.apply({
+ msg : 'Loading..',
+ msgCls : 'x-mask-loading',
+ maskEl : null,
+ hideOnReady : false,
+ disabled : false
+ }, config.loadMask) : false
+
+ ,
+ _windowContext : null,
+ eventsFollowFrameLinks : typeof config.eventsFollowFrameLinks == 'undefined'
+ ? true : config.eventsFollowFrameLinks
+ });
+
+
+ if(el.loadMask ){
+ el.loadMask.maskEl ||
+ ( el.loadMask.maskEl = el.parent('.x-managed-iframe-mask') || el.parent().addClass('x-managed-iframe-mask'));
+ }
+
+
+ var um = el.updateManager = new Ext.UpdateManager(el, true);
+ um.showLoadIndicator = config.showLoadIndicator || false;
+
+ Ext.ux.ManagedIFrame.Manager.register(el);
+
+ if (config.src) {
+ el.setSrc(config.src);
+ } else {
+ var content = config.html || config.content || false;
+
+ if (content) {
+ el.reset(null,function(frame){
+ // permit the syntax for supported arguments: content or [content, loadScripts, callback, scope]
+ frame.update.apply(el, [].concat(content)); });
+ }
+ }
+
+ return el;
+ };
+
+
+ Ext.extend(Ext.ux.ManagedIFrame, Ext.util.Observable, {
+ /** (read-only) The last known URI set programmatically by the Component
+ * @cfg {String|Function} src The target URI of the Component to set after render.
+ * @property
+ * @type String
+ */
+ src : null,
+
+ /** (read-only) For "same-origin" frames only. Provides a reference to
+ * the Ext.util.CSS singleton to manipulate the style sheets of the frame's
+ * embedded document.
+ *
+ * @property
+ * @type Ext.util.CSS
+ */
+ CSS : null,
+
+ /** Provides a reference to the managing Ext.ux.ManagedIFrame.Manager instance.
+ *
+ * @property
+ * @type Ext.ux.ManagedIFrame.Manager
+ */
+ manager : null,
+
+ /**
+ * Enables/disables internal cross-frame messaging interface
+ * @cfg {Boolean} disableMessaging False to enable cross-frame messaging API
+ * Default = true
+ *
+ */
+ disableMessaging : true,
+
+ /**
+ * @cfg {String} resetUrl Frame document reset string for use with the {@link #Ext.ux.ManagedIFrame-reset} method.
+ * Defaults:<p> For IE on SSL domains - the current value of Ext.SSL_SECURE_URL<p> "about:blank" for all others.
+ */
+ resetUrl : (function(){
+ if(Ext.isIE && Ext.isSecure){
+ return Ext.SSL_SECURE_URL;
+ } else {
+ return 'about:blank';
+ }
+ })(),
+
+ /**
+ * @cfg {String} unsupportedText Text to display when the IFRAMES.FRAMESETS are disabled by the browser.
+ *
+ */
+ unsupportedText : 'Inline frames are NOT enabled\/supported by your browser.',
+
+ /**
+ * Sets the embedded Iframe src property. Note: invoke the function with
+ * no arguments to refresh the iframe based on the current src value.
+ *
+ * @param {String/Function} url (Optional) A string or reference to a Function that
+ * returns a URI string when called
+ * @param {Boolean} discardUrl (Optional) If not passed as <tt>false</tt>
+ * the URL of this action becomes the default SRC attribute
+ * for this iframe, and will be subsequently used in future
+ * setSrc calls (emulates autoRefresh by calling setSrc
+ * without params).
+ * @param {Function} callback (Optional) A callback function invoked when the
+ * frame document has been fully loaded.
+ * @param {Object} scope (Optional) scope by which the callback function is
+ * invoked.
+ */
+ setSrc : function(url, discardUrl, callback, scope) {
+
+ var src = url || this.src || this.resetUrl;
+
+ this._windowContext = null;
+ this._unHook();
+ this._frameAction = this.frameInit = this._domReady = false;
+
+ this.showMask();
+
+ (function() {
+ var s = this._targetURI = typeof src == 'function' ? src() || '' : src;
+ try {
+ this._frameAction = true; // signal listening now
+ this._callBack = typeof callback == 'function' ? callback.createDelegate(scope) : null;
+ this.dom.src = s;
+ this.frameInit = true; // control initial event chatter
+ this.checkDOM();
+ } catch (ex) {
+ this.fireEvent('exception', this, ex);
+ }
+
+ }).defer(10, this);
+
+ if (discardUrl !== true) {
+ this.src = src;
+ }
+
+ return this;
+
+ },
+ /**
+ * Sets the embedded Iframe location using its replace method. Note: invoke the function with
+ * no arguments to refresh the iframe based on the current src value.
+ *
+ * @param {String/Function} url (Optional) A string or reference to a Function that
+ * returns a URI string when called
+ * @param {Boolean} discardUrl (Optional) If not passed as <tt>false</tt>
+ * the URL of this action becomes the default SRC attribute
+ * for this iframe, and will be subsequently used in future
+ * setSrc calls (emulates autoRefresh by calling setSrc
+ * without params).
+ * @param {Function} callback (Optional) A callback function invoked when the
+ * frame document has been fully loaded.
+ * @param {Object} scope (Optional) scope by which the callback function is
+ * invoked.
+ *
+ */
+
+ setLocation : function(url, discardUrl, callback, scope) {
+
+ var src = url || this.src || this.resetUrl;
+
+ this._windowContext = null;
+ this._unHook();
+ this._frameAction = this.frameInit = this._domReady = false;
+
+ this.showMask();
+
+ (function() {
+ var s = this._targetURI = typeof src == 'function' ? src()
+ || '' : src;
+ try {
+ this._frameAction = true; // signal listening now
+ this._callBack = typeof callback == 'function' ? callback.createDelegate(scope) : null;
+ this.getWindow().location.replace(s);
+ this.frameInit = true; // control initial event chatter
+ this.checkDOM();
+ } catch (ex) {
+ this.fireEvent('exception', this, ex);
+ }
+
+ }).defer(10, this);
+
+ if (discardUrl !== true) {
+ this.src = src;
+ }
+
+ return this;
+
+ },
+ /**
+ * Resets the frame to a neutral (blank document) state without
+ * loadMasking.
+ *
+ * @param {String}
+ * src (Optional) A specific reset string (eg. 'about:blank')
+ * to use for resetting the frame.
+ * @param {Function}
+ * callback (Optional) A callback function invoked when the
+ * frame reset is complete.
+ * @param {Object}
+ * scope (Optional) scope by which the callback function is
+ * invoked.
+ */
+ reset : function(src, callback, scope) {
+
+ this._unHook();
+
+ var loadMaskOff = false;
+ if(this.loadMask){
+ loadMaskOff = this.loadMask.disabled;
+ this.loadMask.disabled = false;
+ }
+
+
+ this._callBack = function(frame) {
+ if(frame.loadMask){
+ frame.loadMask.disabled = loadMaskOff;
+ };
+ frame._frameAction = false;
+ frame.frameInit = true;
+ this._isReset= false;
+
+ if (callback) {
+ callback.call(scope || window, frame);
+ }
+ };
+ this.hideMask(true);
+ this._frameAction = false; // no chatter on reset
+ this.frameInit = true
+ this._isReset= true;
+ var s = src;
+ if (typeof src == 'function') { s = src();}
+
+ s = this._targetURI = Ext.isEmpty(s, true)? this.resetUrl: s;
+ this.getWindow().location.href = s;
+
+ return this;
+
+ },
+
+ /**
+ * Regular Expression filter pattern for script tag removal.
+ * @cfg {regexp} scriptRE script removal RegeXp
+ * Default: "/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/gi"
+ */
+ scriptRE : /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/gi,
+
+ /**
+ * Write(replacing) string content into the IFrames document structure
+ * @param {String} content The new content
+ * @param {Boolean} loadScripts
+ * (optional) true to also render and process embedded scripts
+ * @param {Function} callback (Optional) A callback function invoked when the
+ * frame document has been written and fully loaded. @param {Object}
+ * scope (Optional) scope by which the callback function is invoked.
+ */
+ update : function(content, loadScripts, callback, scope) {
+
+ loadScripts = loadScripts || this.getUpdateManager().loadScripts || false;
+
+ content = Ext.DomHelper.markup(content || '');
+ content = loadScripts === true ? content : content.replace(this.scriptRE, "");
+
+ var doc;
+
+ if ((doc = this.getDocument()) && !!content.length) {
+
+ this._unHook();
+ this._windowContext = this.src = null;
+ this._targetURI = location.href;
+
+ this.frameInit = true; // control initial event chatter
+ this.showMask();
+
+ (function() {
+ this._callBack = typeof callback == 'function' ? callback.createDelegate(scope) : null;
+ doc.open();
+ this._frameAction = true;
+ doc.write(content);
+ doc.close();
+
+ this.checkDOM();
+ }).defer(10, this);
+
+ } else {
+ this.hideMask(true);
+
+ if (callback) {
+ callback.call(scope, this);
+ }
+ }
+ return this;
+ },
+
+ /**
+ * Enables/disables internal cross-frame messaging interface
+ *
+ * @cfg {Boolean} disableMessaging False to enable cross-frame messaging
+ * API (default is True)
+ */
+ disableMessaging : true,
+
+ /**
+ * @private, frame messaging interface (for same-domain-policy frames
+ * only)
+ */
+ _XFrameMessaging : function() {
+ // each tag gets a hash queue ($ = no tag ).
+ var tagStack = { '$' : [] };
+ var isEmpty = function(v, allowBlank) {
+ return v === null || v === undefined
+ || (!allowBlank ? v === '' : false);
+ };
+ window.sendMessage = function(message, tag, origin) {
+ var MIF;
+ if (MIF = arguments.callee.manager) {
+ if (message._fromHost) {
+ var fn, result;
+ // only raise matching-tag handlers
+ var compTag = message.tag || tag || null;
+ var mstack = !isEmpty(compTag) ? tagStack[compTag.toLowerCase()] || [] : tagStack["$"];
+
+ for (var i = 0, l = mstack.length; i < l; i++) {
+ if (fn = mstack[i]) {
+ result = fn.apply(fn.__scope, arguments) === false? false: result;
+ if (fn.__single) {
+ mstack[i] = null;
+ }
+ if (result === false) {
+ break;
+ }
+ }
+ }
+
+ return result;
+ } else {
+
+ message = {
+ type : isEmpty(tag) ? 'message' : 'message:'
+ + tag.toLowerCase().replace(/^\s+|\s+$/g,''),
+ data : message,
+ domain : origin || document.domain,
+ uri : document.documentURI,
+ source : window,
+ tag : isEmpty(tag) ? null : tag.toLowerCase()
+ };
+
+ try {
+ return MIF.disableMessaging !== true
+ ? MIF.fireEvent.call(MIF, message.type,MIF, message)
+ : null;
+ } catch (ex) {
+ } // trap for message:tag handlers not yet defined
+
+ return null;
+ }
+
+ }
+ };
+ window.onhostmessage = function(fn, scope, single, tag) {
+
+ if (typeof fn == 'function') {
+ if (!isEmpty(fn.__index)) {
+ throw "onhostmessage: duplicate handler definition"
+ + (tag ? " for tag:" + tag : '');
+ }
+
+ var k = isEmpty(tag) ? "$" : tag.toLowerCase();
+ tagStack[k] || (tagStack[k] = []);
+ Ext.apply(fn, {
+ __tag : k,
+ __single : single || false,
+ __scope : scope || window,
+ __index : tagStack[k].length
+ });
+ tagStack[k].push(fn);
+
+ } else {
+ throw "onhostmessage: function required";
+ }
+
+ };
+ window.unhostmessage = function(fn) {
+ if (typeof fn == 'function' && typeof fn.__index != 'undefined') {
+ var k = fn.__tag || "$";
+ tagStack[k][fn.__index] = null;
+ }
+ };
+
+ },
+
+ /**
+ * Method to retrieve frame's history object.
+ * @return {object} or null if permission was denied
+ */
+ getHistory : function(){
+ var h=null;
+ try{ h=this.getWindow().history; }catch(eh){}
+ return h;
+
+ },
+ /**
+ * Method to retrieve embedded frame Element objects. Uses simple
+ * caching (per frame) to consistently return the same object.
+ * Automatically fixes if an object was recreated with the same id via
+ * AJAX or DOM.
+ *
+ * @param {Mixed}
+ * el The id of the node, a DOM Node or an existing Element.
+ * @return {Element} The Element object (or null if no matching element
+ * was found)
+ */
+
+ get : function(el) {
+ return MIM.El.get(this, el);
+ },
+
+ /**
+ * Gets the globally shared flyweight Element for the frame, with the
+ * passed node as the active element. Do not store a reference to this
+ * element - the dom node can be overwritten by other code.
+ *
+ * @param {String/HTMLElement}
+ * el The dom node or id
+ * @param {String}
+ * named (optional) Allows for creation of named reusable
+ * flyweights to prevent conflicts (e.g. internally Ext uses
+ * "_internal")
+ * @return {Element} The shared Element object (or null if no matching
+ * element was found)
+ */
+
+ fly : function(el, named) {
+ named = named || '_global';
+ el = this.getDom(el);
+ if (!el) {
+ return null;
+ }
+ if (!MIM._flyweights[named]) {
+ MIM._flyweights[named] = new Ext.Element.Flyweight();
+ }
+ MIM._flyweights[named].dom = el;
+ return MIM._flyweights[named];
+ },
+ /**
+ * Return the dom node for the passed string (id), dom node, or
+ * Ext.Element relative to the embedded frame document context.
+ *
+ * @param {Mixed} el
+ * @return HTMLElement
+ */
+
+ getDom : function(el) {
+ var d;
+ if (!el || !(d = this.getDocument())) {
+ return null;
+ }
+ return el.dom ? el.dom : (typeof el == 'string' ? d
+ .getElementById(el) : el);
+
+ },
+ /**
+ * Creates a {@link Ext.CompositeElement} for child nodes based on the
+ * passed CSS selector (the selector should not contain an id).
+ *
+ * @param {String} selector The CSS selector
+ * @param {Boolean} unique (optional) True to create a unique Ext.Element for
+ * each child (defaults to false, which creates a single
+ * shared flyweight object)
+ * @return {Ext.CompositeElement/Ext.CompositeElementLite} The composite element
+ */
+
+ select : function(selector, unique) {
+ var d;
+ return (d = this.getDocument()) ? Ext.Element.select(selector,unique, d) : null;
+ },
+
+ /**
+ * Selects frame document child nodes based on the passed CSS selector
+ * (the selector should not contain an id).
+ *
+ * @param {String} selector The CSS selector
+ * @return {Array} An array of the matched nodes
+ */
+
+ query : function(selector) {
+ var d;
+ return (d = this.getDocument()) ? Ext.DomQuery.select(selector, d): null;
+ },
+
+ /**
+ * Returns the frame's current HTML document object as an
+ * {@link Ext.Element}.
+ *
+ * @return {Ext.Element} The document
+ */
+
+ getDoc : function() {
+ return this.get(this.getDocument());
+ },
+
+ /**
+ * Removes a DOM Element from the embedded documents
+ *
+ * @param {Element/String} node The node id or node Element to remove
+ *
+ */
+
+ removeNode : function(node) {
+ MIM.removeNode(this, this.getDom(node));
+ },
+
+ /** @private : clear all event listeners and Element cache */
+
+ _unHook : function() {
+
+ var elcache, h = MIM.getFrameHash(this) || {};
+
+ if (this._hooked && h && (elcache = h.elCache)) {
+
+ for (var id in elcache) {
+ var el = elcache[id];
+
+ if (el.removeAllListeners) {
+ el.removeAllListeners();
+ }
+ delete elcache[id];
+ }
+ if (h.docEl) {
+ h.docEl.removeAllListeners();
+ h.docEl = null;
+ delete h.docEl;
+ }
+ }
+
+ this.CSS = this.CSS ? this.CSS.destroy() : null;
+ this._hooked = this._domReady = this._domFired = false;
+
+ },
+ // Private execScript sandbox and messaging interface
+
+ _renderHook : function() {
+
+ this._windowContext = null;
+ this.CSS = this.CSS ? this.CSS.destroy() : null;
+ this._hooked = false;
+ try {
+ if (this.writeScript('(function(){(window.hostMIF = parent.Ext.get("'
+ + this.dom.id
+ + '"))._windowContext='
+ + (Ext.isIE
+ ? 'window'
+ : '{eval:function(s){return eval(s);}}')
+ + ';})();')) {
+ this._frameProxy || (this._frameProxy = MIM.eventProxy.createDelegate(this));
+ var w;
+
+ if(w = this.getWindow()){
+ EV.doAdd(w, 'focus', this._frameProxy);
+ EV.doAdd(w, 'blur', this._frameProxy);
+ EV.doAdd(w, 'unload', this._frameProxy);
+ }
+
+ if (this.disableMessaging !== true) {
+ this.loadFunction({
+ name : 'XMessage',
+ fn : this._XFrameMessaging
+ }, false, true);
+ var sm;
+ if (sm = w.sendMessage) {
+ sm.manager = this;
+ }
+ }
+ this.CSS = new CSSInterface(this.getDocument());
+
+ }
+
+ } catch (ex) {
+ }
+
+ return this.domWritable();
+
+ },
+ /**
+ * dispatch a message to the embedded frame-window context
+ * @name sendMessage
+ * @methodOf Ext.ux.ManagedIFrame
+ * @param {Mixed} message The message payload @param {String} tag Optional reference tag @param
+ * {String} origin Optional domain designation of the sender (defaults
+ * to document.domain).
+ */
+ sendMessage : function(message, tag, origin) {
+ var win;
+ if (this.disableMessaging !== true && (win = this.getWindow())) {
+ // support frame-to-frame messaging relay
+ tag || (tag = message.tag || '');
+ tag = tag.toLowerCase();
+ message = Ext.applyIf(message.data ? message : {
+ data : message
+ }, {
+ type : Ext.isEmpty(tag) ? 'message' : 'message:'
+ + tag,
+ domain : origin || document.domain,
+ uri : document.documentURI,
+ source : window,
+ tag : tag || null,
+ _fromHost : this
+ });
+ return win.sendMessage ? win.sendMessage.call(null, message,
+ tag, origin) : null;
+ }
+ return null;
+
+ },
+
+ /** @private */
+ _windowContext : null,
+
+ /**
+ * If sufficient privilege exists, returns the frame's current document
+ * as an HTMLElement.
+ *
+ * @return {HTMLElement} The frame document or false if access to
+ * document object was denied.
+ */
+ getDocument : function() {
+ var win = this.getWindow(), doc = null;
+ try {
+ doc = (Ext.isIE && win ? win.document : null)
+ || this.dom.contentDocument
+ || window.frames[this.id].document || null;
+ } catch (gdEx) {
+ return false; // signifies probable access restriction
+ }
+ return doc;
+ },
+
+ /**
+ * If sufficient privilege exists, returns the frame's current document
+ * body as an HTMLElement.
+ *
+ * @return {HTMLElement} The frame document body or Null if access to
+ * document object was denied.
+ */
+ getBody : function() {
+ var d;
+ return (d = this.getDocument()) ? d.body : null;
+ },
+
+ /**
+ * Attempt to retrieve the frames current URI via frame's document object
+ * @return {string} The frame document's current URI or the last know URI if permission was denied.
+ */
+ getDocumentURI : function() {
+ var URI, d;
+ try {
+ URI = this.src && (d = this.getDocument()) ? d.location.href: null;
+ } catch (ex) { // will fail on NON-same-origin domains
+ }
+ return URI || (typeof this.src == 'function' ? this.src() : this.src);
+ // fallback to last known
+ },
+
+ /**
+ * Attempt to retrieve the frames current URI via frame's Window object
+ * @return {string} The frame document's current URI or the last know URI if permission was denied.
+ */
+ getWindowURI : function() {
+ var URI, w;
+ try {
+ URI = (w = this.getWindow()) ? w.location.href : null;
+ } catch (ex) {
+ } // will fail on NON-same-origin domains
+ return URI || (typeof this.src == 'function' ? this.src() : this.src);
+ // fallback to last known
+ },
+
+ /**
+ * Returns the frame's current window object.
+ *
+ * @return {Window} The frame Window object.
+ */
+ getWindow : function() {
+ var dom = this.dom, win = null;
+ try {
+ win = dom.contentWindow || window.frames[dom.name] || null;
+ } catch (gwEx) {
+ }
+ return win;
+ },
+
+ /**
+ * Print the contents of the Iframes (if we own the document)
+ */
+ print : function() {
+ var win;
+ try {
+ if( win = this.getWindow()){
+ if (Ext.isIE) {
+ win.focus();
+ }
+ win.print();
+ }
+ } catch (ex) {
+ throw 'print exception: ' + (ex.description || ex.message || ex);
+ }
+ },
+ /** @private */
+ destroy : function() {
+ this.removeAllListeners();
+ if (this.loadMask) {
+ this.hideMask(true);
+ Ext.apply(this.loadMask, {
+ masker : null,
+ maskEl : null
+ });
+ }
+
+ if (this.dom) {
+
+ Ext.ux.ManagedIFrame.Manager.deRegister(this);
+ this.dom.ownerEl = this._windowContext = null;
+ // IE Iframe cleanup
+ if (Ext.isIE && this.dom.src) {
+ this.dom.src = 'javascript:false';
+ }
+ this._maskEl = null;
+ this.remove();
+ }
+
+
+
+ },
+ /**
+ * Returns the general DOM modification capability of the frame. @return
+ * {Boolean} If True, the frame's DOM can be manipulated, queried, and
+ * Event Listeners set.
+ */
+
+ domWritable : function() {
+ return !!this._windowContext;
+ },
+ /**
+ * eval a javascript code block(string) within the context of the
+ * Iframes window object.
+ * @param {String} block A valid ('eval'able) script source block.
+ * @param {Boolean} useDOM if true, inserts the function
+ * into a dynamic script tag, false does a simple eval on the function
+ * definition. (useful for debugging) <p> Note: will only work after a
+ * successful iframe.(Updater) update or after same-domain document has
+ * been hooked, otherwise an exception is raised.
+ */
+
+ execScript : function(block, useDOM) {
+ try {
+ if (this.domWritable()) {
+ if (useDOM) {
+ this.writeScript(block);
+ } else {
+ return this._windowContext.eval(block);
+ }
+
+ } else {
+ throw 'execScript:non-secure context'
+ }
+ } catch (ex) {
+ this.fireEvent('exception', this, ex);
+ return false;
+ }
+ return true;
+
+ },
+
+ /**
+ * write a <script> block into the iframe's document
+ * @param {String} block A valid (executable) script source block.
+ * @param {object} attributes Additional Script tag attributes to apply to the script
+ * Element (for other language specs [vbscript, Javascript] etc.) <p>
+ * Note: writeScript will only work after a successful iframe.(Updater)
+ * update or after same-domain document has been hooked, otherwise an
+ * exception is raised.
+ */
+
+ writeScript : function(block, attributes) {
+ attributes = Ext.apply({}, attributes || {}, {
+ type : "text/javascript",
+ text : block
+ });
+
+ try {
+ var head, script, doc = this.getDocument();
+ if (doc && typeof doc.getElementsByTagName != 'undefined') {
+ if (!(head = doc.getElementsByTagName("head")[0])) {
+ // some browsers (Webkit, Safari) do not auto-create
+ // head elements during document.write
+ head = doc.createElement("head");
+ doc.getElementsByTagName("html")[0].appendChild(head);
+ }
+ if (head && (script = doc.createElement("script"))) {
+ for (var attrib in attributes) {
+ if (attributes.hasOwnProperty(attrib)
+ && attrib in script) {
+ script[attrib] = attributes[attrib];
+ }
+ }
+ return !!head.appendChild(script);
+ }
+ }
+ } catch (ex) {
+
+ this.fireEvent('exception', this, ex);
+ }
+ return false;
+ },
+
+ /**
+ * Eval a function definition into the iframe window context.
+ * @param {String/Object} fn Name of the function or function map
+ * object: {name:'encodeHTML',fn:Ext.util.Format.htmlEncode}
+ * @param {Boolean} useDOM if true, inserts the fn into a dynamic script tag,
+ * false does a simple eval on the function definition
+ * @param {Boolean} invokeIt if true, the function specified is also executed in the
+ * Window context of the frame. Function arguments are not supported.
+ * @example <pre><code> var trim = function(s){ return s.replace(
+ * /^\s+|\s+$/g,''); }; iframe.loadFunction('trim');
+ * iframe.loadFunction({name:'myTrim',fn:String.prototype.trim ||
+ * trim});</code></pre>
+ */
+
+ loadFunction : function(fn, useDOM, invokeIt) {
+
+ var name = fn.name || fn;
+ var fn = fn.fn || window[fn];
+ this.execScript(name + '=' + fn, useDOM); // fn.toString coercion
+ if (invokeIt) {
+ this.execScript(name + '()'); // no args only
+ }
+ },
+
+ /**
+ * Forcefully show the defined loadMask
+ * @param {String} msg Mask text to display during the mask operation, defaults to previous defined
+ * loadMask config value.
+ * @param {String} msgCls The CSS class to apply to the loading message element (defaults to "x-mask-loading")
+ * @param {Boolean} forced True to show the mask regardless of document
+ * ready/loaded state.
+ */
+
+ showMask : function(msg, msgCls, forced) {
+ var lmask = this.loadMask;
+
+ if (lmask && !lmask.disabled) {
+ lmask.masker
+ || (lmask.masker = Ext.get(lmask.maskEl
+ || this.dom.parentNode || this.wrap({
+ tag : 'div',
+ style : {
+ position : 'static'
+ }
+ })));
+ (function () {
+ //this.masker.repaint();
+ this._vis = !!this.masker.mask(msg || this.msg, msgCls
+ || this.msgCls);
+ }).defer(lmask.delay || 10, lmask)
+
+ }
+ },
+ /**
+ * Forcefully hide the defined loadMask @param {Boolean} forced True to
+ * hide the mask regardless of document ready/loaded state.
+ */
+
+ hideMask : function(forced) {
+ var tlm = this.loadMask;
+
+ if (tlm && !tlm.disabled && tlm.masker) {
+ if (forced || (tlm.hideOnReady && this._domReady)) {
+
+ tlm.masker.unmask();
+ tlm._vis = false;
+
+ }
+ }
+ },
+
+ /**
+ * @private
+ * Evaluate the Iframes readyState/load event to determine its
+ * 'load' state, and raise the 'domready/documentloaded' event when
+ * applicable.
+ */
+
+ loadHandler : function(e, target) {
+
+ if (!this.frameInit || (!this._frameAction && !this.eventsFollowFrameLinks)) {
+ return;
+ }
+ target || (target = {});
+ var rstatus = (e && typeof e.type !== 'undefined' ? e.type: this.dom.readyState);
+
+ switch (rstatus) {
+
+ case 'domready' : // MIF
+ if (this._domReady) { return; }
+ this._domReady = true;
+
+ if (this._frameAction
+ && this.getDocumentURI() != 'about:blank'
+ && (this._hooked = this._renderHook())) {
+ // Only raise if sandBox injection succeeded (same origin)
+ this._domFired = true;
+ this.fireEvent("domready", this);
+ }
+ case 'domfail' : // MIF
+ this._domReady = true;
+ this.hideMask();
+
+ break;
+ case 'load' : // Gecko, Opera, IE
+ case 'complete' :
+
+ if (!this._domReady) { // one last try for slow DOMS.
+ this.loadHandler({
+ type : 'domready',
+ id : this.id
+ }, this.dom);
+ }
+ this.hideMask(true);
+ if (this._frameAction || this.eventsFollowFrameLinks) {
+ // not going to wait for the event chain, as it's not
+ // cancellable anyhow.
+ this.fireEvent.defer(1, this, ["documentloaded", this]);
+ // setSrc and update method (async) callbacks are called
+ // ASAP.
+ if (this._callBack) {
+ this._callBack.defer(1, null, [this]);
+ }
+ }
+ this._frameAction = this._frameInit = false;
+
+ if (this.eventsFollowFrameLinks) { // reset for link
+ // tracking
+ this._domFired = this._domReady = false;
+ }
+
+ break;
+ default :
+ }
+
+ this.frameState = rstatus;
+
+ },
+ /**
+ * @private
+ * Poll the Iframes document structure to determine DOM ready
+ * state, and raise the 'domready' event when applicable.
+ */
+
+ checkDOM : function(win) {
+ if (Ext.isOpera || Ext.isGecko || !this._frameAction) { return; }
+ // initialise the counter
+ var n = 0, manager = this, domReady = false,
+ b, l, d, max = 300, polling = false,
+ startLocation = (this.getDocument() || {location : {}}).location.href;
+
+ (function() { // DOM polling for IE and others
+
+ d = manager.getDocument() || {location : {}};
+
+ // wait for location.href transition
+ polling = (d.location.href !== startLocation || d.location.href === manager._targetURI);
+
+ if (!manager._frameAction || manager._domReady) {
+ return;
+ }
+
+ domReady = polling && ((b = manager.getBody()) && !!(b.innerHTML || '').length) || false;
+
+ // null href is a 'same-origin' document access violation,
+ // so we assume the DOM is built when the browser updates it
+ if (d.location.href && !domReady && (++n < max)) {
+ setTimeout(arguments.callee, 2); // try again
+ return;
+ }
+
+ manager.loadHandler({ type : domReady ? 'domready' : 'domfail'});
+
+ })();
+ }
+ });
+
+ /** @private
+ * Stylesheet Frame interface object
+ */
+ var styleCamelRe = /(-[a-z])/gi;
+ var styleCamelFn = function(m, a) {
+ return a.charAt(1).toUpperCase();
+ };
+ /** @private */
+ var CSSInterface = function(hostDocument) {
+ var doc;
+ if (hostDocument) {
+
+ doc = hostDocument;
+
+ return {
+ rules : null,
+
+ destroy : function(){ return doc = null; },
+ /**
+ * Creates a stylesheet from a text blob of rules. These rules
+ * will be wrapped in a STYLE tag and appended to the HEAD of
+ * the document.
+ *
+ * @param {String}
+ * cssText The text containing the css rules
+ * @param {String}
+ * id An id to add to the stylesheet for later
+ * removal
+ * @return {StyleSheet}
+ */
+ createStyleSheet : function(cssText, id) {
+ var ss;
+
+ if (!doc)
+ return;
+ var head = doc.getElementsByTagName("head")[0];
+ var rules = doc.createElement("style");
+ rules.setAttribute("type", "text/css");
+ if (id) {
+ rules.setAttribute("id", id);
+ }
+ if (Ext.isIE) {
+ head.appendChild(rules);
+ ss = rules.styleSheet;
+ ss.cssText = cssText;
+ } else {
+ try {
+ rules.appendChild(doc.createTextNode(cssText));
+ } catch (e) {
+ rules.cssText = cssText;
+ }
+ head.appendChild(rules);
+ ss = rules.styleSheet
+ ? rules.styleSheet
+ : (rules.sheet || doc.styleSheets[doc.styleSheets.length
+ - 1]);
+ }
+ this.cacheStyleSheet(ss);
+ return ss;
+ },
+
+ /**
+ * Removes a style or link tag by id
+ *
+ * @param {String}
+ * id The id of the tag
+ */
+ removeStyleSheet : function(id) {
+
+ if (!doc)
+ return;
+ var existing = doc.getElementById(id);
+ if (existing) {
+ existing.parentNode.removeChild(existing);
+ }
+ },
+
+ /**
+ * Dynamically swaps an existing stylesheet reference for a new
+ * one
+ *
+ * @param {String}
+ * id The id of an existing link tag to remove
+ * @param {String}
+ * url The href of the new stylesheet to include
+ */
+ swapStyleSheet : function(id, url) {
+ this.removeStyleSheet(id);
+
+ if (!doc)
+ return;
+ var ss = doc.createElement("link");
+ ss.setAttribute("rel", "stylesheet");
+ ss.setAttribute("type", "text/css");
+ ss.setAttribute("id", id);
+ ss.setAttribute("href", url);
+ doc.getElementsByTagName("head")[0].appendChild(ss);
+ },
+
+ /**
+ * Refresh the rule cache if you have dynamically added
+ * stylesheets
+ *
+ * @return {Object} An object (hash) of rules indexed by
+ * selector
+ */
+ refreshCache : function() {
+ return this.getRules(true);
+ },
+
+ // private
+ cacheStyleSheet : function(ss) {
+ if (this.rules) {
+ this.rules = {};
+ }
+ try {// try catch for cross domain access issue
+ var ssRules = ss.cssRules || ss.rules;
+ for (var j = ssRules.length - 1; j >= 0; --j) {
+ this.rules[ssRules[j].selectorText] = ssRules[j];
+ }
+ } catch (e) {
+ }
+ },
+
+ /**
+ * Gets all css rules for the document
+ *
+ * @param {Boolean}
+ * refreshCache true to refresh the internal cache
+ * @return {Object} An object (hash) of rules indexed by
+ * selector
+ */
+ getRules : function(refreshCache) {
+ if (this.rules == null || refreshCache) {
+ this.rules = {};
+
+ if (doc) {
+ var ds = doc.styleSheets;
+ for (var i = 0, len = ds.length; i < len; i++) {
+ try {
+ this.cacheStyleSheet(ds[i]);
+ } catch (e) {
+ }
+ }
+ }
+ }
+ return this.rules;
+ },
+
+ /**
+ * Gets an an individual CSS rule by selector(s)
+ *
+ * @param {String/Array}
+ * selector The CSS selector or an array of selectors
+ * to try. The first selector that is found is
+ * returned.
+ * @param {Boolean}
+ * refreshCache true to refresh the internal cache if
+ * you have recently updated any rules or added
+ * styles dynamically
+ * @return {CSSRule} The CSS rule or null if one is not found
+ */
+ getRule : function(selector, refreshCache) {
+ var rs = this.getRules(refreshCache);
+ if (!Ext.isArray(selector)) {
+ return rs[selector];
+ }
+ for (var i = 0; i < selector.length; i++) {
+ if (rs[selector[i]]) {
+ return rs[selector[i]];
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Updates a rule property
+ *
+ * @param {String/Array}
+ * selector If it's an array it tries each selector
+ * until it finds one. Stops immediately once one is
+ * found.
+ * @param {String}
+ * property The css property
+ * @param {String}
+ * value The new value for the property
+ * @return {Boolean} true If a rule was found and updated
+ */
+ updateRule : function(selector, property, value) {
+ if (!Ext.isArray(selector)) {
+ var rule = this.getRule(selector);
+ if (rule) {
+ rule.style[property.replace(styleCamelRe,
+ styleCamelFn)] = value;
+ return true;
+ }
+ } else {
+ for (var i = 0; i < selector.length; i++) {
+ if (this.updateRule(selector[i], property, value)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ };
+ }
+ };
+
+ /**
+ * @class Ext.ux.panel.ManagedIFrame
+ * @extends Ext.Panel
+ * @version: 1.2.1
+ * @license <a href="http://www.gnu.org/licenses/lgpl.html">LGPL 3.0</a>
+ * @author: Doug Hendricks. Forum ID: <a
+ * href="http://extjs.com/forum/member.php?u=8730">hendricd</a> Copyright
+ * 2007-2008, Active Group, Inc. All rights reserved.
+ *
+ * @constructor Create a new Ext.ux.panel.ManagedIFrame @param {Object}
+ * config The config object
+ */
+ Ext.ux.ManagedIframePanel = Ext.extend(Ext.Panel, {
+
+ /**
+ * Fires when the frame gets focus. Note: This event is only available
+ * when overwriting the iframe document using the update method and to
+ * pages retrieved from a "same domain". Returning false from the
+ * eventHandler [MAY] NOT cancel the event, as this event is NOT ALWAYS
+ * cancellable in all browsers.
+ *
+ * @event focus
+ * @param {Ext.ux.ManagedIFrame} this.iframe
+ * @param {Ext.Event}
+ *
+ */
+
+ /**
+ * Fires when the frame is blurred (loses focus).
+ *
+ * @event blur
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ * @param {Ext.Event}
+ * Note: This event is only available when overwriting the
+ * iframe document using the update method and to pages
+ * retrieved from a "same domain". Returning false from the
+ * eventHandler [MAY] NOT cancel the event, as this event is
+ * NOT ALWAYS cancellable in all browsers.
+ */
+
+ /**
+ * Note: This event is only available when overwriting the iframe
+ * document using the update method and to pages retrieved from a "same
+ * domain". Note: Opera does not raise this event.
+ *
+ * @event unload * Fires when(if) the frames window object raises the
+ * unload event
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ * @param {Ext.Event}
+ */
+
+ /**
+ * Note: This event is only available when overwriting the iframe
+ * document using the update method and to pages retrieved from a "same
+ * domain". Returning false from the eventHandler stops further event
+ * (documentloaded) processing.
+ *
+ * @event domready Fires ONLY when an iFrame's Document(DOM) has reach a
+ * state where the DOM may be manipulated (ie same domain policy)
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ */
+
+ /**
+ * Fires when the iFrame has reached a loaded/complete state.
+ *
+ * @event documentloaded
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ */
+
+ /**
+ * Fires when the frame actions raise an error
+ *
+ * @event exception
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ * @param {Error/string}
+ * exception
+ */
+
+ /**
+ * Fires upon receipt of a message generated by window.sendMessage
+ * method of the embedded Iframe.window object
+ *
+ * @event message
+ *
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ * @param {object}
+ * message (members: type: {string} literal "message", data
+ * {Mixed} [the message payload], domain [the document domain
+ * from which the message originated ], uri {string} the
+ * document URI of the message sender source (Object) the
+ * window context of the message sender tag {string} optional
+ * reference tag sent by the message sender
+ */
+
+ /**
+ * Alternate event handler syntax for message:tag filtering Fires upon
+ * receipt of a message generated by window.sendMessage method which
+ * includes a specific tag value of the embedded Iframe.window object
+ *
+ * @event message:tag
+ * @param {Ext.ux.ManagedIFrame}
+ * this.iframe
+ * @param {object}
+ * message (members: type: {string} literal "message", data
+ * {Mixed} [the message payload], domain [the document domain
+ * from which the message originated ], uri {string} the
+ * document URI of the message sender source (Object) the
+ * window context of the message sender tag {string} optional
+ * reference tag sent by the message sender
+ */
+ // "message:tagName" is supported for X-frame messaging
+
+ /**
+ * @cfg {String/Function} defaultSrc Cached Iframe.src url (or Function
+ * that returns it) to use for initial rendering and refreshes.
+ * Overwritten every time {@link Ext.ux.panel.ManagedIframe#setSrc}
+ * is called unless "discardUrl" param is set to true.
+ */
+ defaultSrc : null,
+
+ /**
+ * @cfg {Object/String} bodyStyle Inline style rules applied to the
+ * Panel body prior to render.
+ */
+ bodyStyle : { position : 'relative' },
+
+
+ /**
+ * @cfg {Object} frameStyle Custom CSS styles to be applied to the
+ * Ext.ux.ManagedIframe frame element in the format expected by
+ * {@link Ext.Element#applyStyles} (defaults to CSS Rule
+ * {overflow:'auto'}).
+ */
+ frameStyle : { overflow : 'auto' },
+
+ /**
+ * @cfg {Object} frameConfig Custom DOMHelper config for iframe node
+ * specifications (eg. name, id, frameBorder, etc) Note: To
+ * specify/override with a unique Element id or name for the
+ * underlying iframe, use the autoCreate config option with it:
+ *
+ * @example
+ * var MIF = new Ext.ux.ManagedIframePanel({
+ * frameConfig : {
+ * autoCreate : {
+ * id : 'frameA',
+ * name : 'frameA'
+ * },
+ * disableMessaging : false
+ * },
+ * defaultSrc : 'sites/customerList.html'
+ * });
+ *
+ */
+ frameConfig : null,
+
+ /**
+ * @cfg {String} hideMode How this component should hidden. Supported
+ * values are "visibility" (css visibility), "offsets" (negative
+ * offset position), "display" (css display), and "nosize"
+ * (height/width set to zero (0px) - defaults to "display" for
+ * Internet Explorer and "nosize" for all other browsers (to
+ * prevent frame re-initialization after reflow of frame
+ * parentNodes).
+ */
+ hideMode : !Ext.isIE ? 'nosize' : 'display',
+
+ shimCls : 'x-frame-shim',
+
+ /**
+ * @cfg {String} shimUrl The url of a transparent graphic image used to
+ * shim the frame (during drag or other) shimming operation.
+ * Defaults to Ext.BLANK_IMG_URL.
+ */
+ shimUrl : null,
+ /**
+ * @cfg {Object} loadMask An {@link Ext.LoadMask} config or true to mask
+ * the frame while loading (defaults to false). Additional loadMask
+ * configuration options: hideOnReady : {Boolean} False to hide the
+ * loadMask when the frame document is fully loaded rather than on
+ * domready.
+ */
+ loadMask : false,
+ stateful : false,
+ animCollapse : Ext.isIE && Ext.enableFx,
+ /** @private class override */
+ autoScroll : false,
+ /**
+ * @cfg {Boolean} closable Set True by default in the event a site
+ * times-out while loadMasked
+ */
+ closable : true,
+ /** @private */
+ ctype : "Ext.ux.ManagedIframePanel",
+ /** @private class override */
+ showLoadIndicator : false,
+
+ /**
+ * @cfg {String/Object} unsupportedText Text (or Ext.DOMHelper config)
+ * to display within the rendered iframe tag to indicate the frame
+ * is not supported/enabled in the browser.
+ */
+ unsupportedText : 'Inline frames are NOT enabled\/supported by your browser.',
+
+ /** @private */
+
+ initComponent : function() {
+
+ var f = this.frameConfig ? this.frameConfig.autoCreate || this.frameConfig : {};
+
+ var frCfg = { id : f.id || Ext.id()};
+ frCfg.name = f.name || frCfg.id;
+
+ if(Ext.isIE && Ext.isSecure){
+ frCfg.src = Ext.SSL_SECURE_URL;
+ }
+
+ var frameTag = Ext.apply({
+ tag : 'iframe',
+ frameborder : 0,
+ cls : 'x-managed-iframe',
+ style : this.frameStyle || f.style || {}
+ }, frCfg );
+
+ var unsup = this.unsupportedText? {tag:'noframes',html:this.unsupportedText } : [];
+
+ this.bodyCfg || (this.bodyCfg = {
+ // shared masking DIV for hosting loadMask/dragMask
+ cls : this.baseCls +'-body',
+ children : this.contentEl? [] : [frameTag].concat(unsup)
+ });
+
+ this.autoScroll = false; // Force off as the Iframe manages this
+ this.items = null;
+
+ // setup stateful events if not defined
+ if (this.stateful !== false) {
+ this.stateEvents || (this.stateEvents = ['documentloaded']);
+ }
+
+ Ext.ux.ManagedIframePanel.superclass.initComponent.call(this);
+
+ this.monitorResize || (this.monitorResize = !!this.fitToParent);
+
+ this.addEvents({
+ documentloaded : true,
+ domready : true,
+ message : true,
+ exception : true,
+ blur : true,
+ focus : true
+ });
+
+ // apply the addListener patch for 'message:tagging'
+ this.addListener = this.on;
+
+ },
+ /** @private */
+ doLayout : function() {
+ // only resize (to Parent) if the panel is NOT in a layout.
+ // parentNode should have {style:overflow:hidden;} applied.
+ if (this.fitToParent && !this.ownerCt) {
+ var pos = this.getPosition(), size = (Ext.get(this.fitToParent)
+ || this.getEl().parent()).getViewSize();
+ this.setSize(size.width - pos[0], size.height - pos[1]);
+ }
+ Ext.ux.ManagedIframePanel.superclass.doLayout.apply(this, arguments);
+
+ },
+
+ /** @private */
+ beforeDestroy : function() {
+
+ if (this.rendered) {
+
+ if (this.tools) {
+ for (var k in this.tools) {
+ Ext.destroy(this.tools[k]);
+ }
+ }
+
+ if (this.header && this.headerAsText) {
+ var s;
+ if (s = this.header.child('span'))s.remove(true,true);
+ this.header.update('');
+ }
+
+ Ext.each(['iframe', 'shim', 'header', 'topToolbar',
+ 'bottomToolbar', 'footer', 'loadMask', 'body',
+ 'bwrap'],
+ function(elName) {
+ if (this[elName]) {
+ if (typeof this[elName].destroy == 'function') {
+ this[elName].destroy();
+ } else {
+ Ext.destroy(this[elName]);
+ }
+
+ this[elName] = null;
+ delete this[elName];
+ }
+ }, this);
+ }
+
+ Ext.ux.ManagedIframePanel.superclass.beforeDestroy.call(this);
+ },
+ /** @private */
+ onDestroy : function() {
+ // Yes, Panel.super (Component), since we're doing Panel cleanup
+ // beforeDestroy instead.
+ Ext.Panel.superclass.onDestroy.call(this);
+ },
+
+ /** @private */
+ afterRender : function(container) {
+
+ var html = this.html; //preserve for frame-writing
+ delete this.html;
+
+ Ext.ux.ManagedIframePanel.superclass.afterRender.apply(this,arguments);
+
+ if (this.iframe = this.body.child('iframe')) {
+
+ this.iframe.ownerCt = this;
+
+ if (this.loadMask) {
+ //resolve possible maskEl by Element name eg. 'body', 'bwrap', 'actionEl'
+ var mEl;
+ if(mEl = this.loadMask.maskEl){
+ this.loadMask.maskEl = this[mEl] || mEl || this.body;
+ this.loadMask.maskEl.addClass('x-managed-iframe-mask');
+ }
+
+ this.loadMask = Ext.apply({
+ disabled : false,
+ hideOnReady : false
+ }, this.loadMask);
+ }
+
+ this.getUpdater().showLoadIndicator = this.showLoadIndicator || false;
+
+ // Enable auto-dragMask if the panel participates in (nested?)
+ // border layout.
+ // Setup event handlers on the SplitBars to enable the frame
+ // dragMask when needed
+ var ownerCt = this.ownerCt;
+ while (ownerCt) {
+ ownerCt.on('afterlayout', function(container, layout) {
+ var MIM = Ext.ux.ManagedIFrame.Manager, st = false;
+ Ext.each(['north', 'south', 'east', 'west'],
+ function(region) {
+ var reg;
+ if ((reg = layout[region])
+ && reg.splitEl) {
+ st = true;
+ if (!reg.split._splitTrapped) {
+ reg.split.on(
+ 'beforeresize',
+ MIM.showShims, MIM);
+ reg.split._splitTrapped = true;
+ }
+ }
+ }, this);
+ if (st && !this._splitTrapped) {
+ this.on('resize', MIM.hideShims, MIM);
+ this._splitTrapped = true;
+ }
+
+ }, this, { single : true}); // and discard
+
+ ownerCt = ownerCt.ownerCt; // nested layouts?
+ }
+
+ // create the shimming agent if not specified in markup
+ this.shim = Ext.get(this.body.child('.' + this.shimCls))
+ || Ext.DomHelper.append(this.body,{
+ tag : 'img',
+ src : this.shimUrl || Ext.BLANK_IMAGE_URL,
+ cls : this.shimCls,
+ galleryimg : "no"
+ }, true);
+ // Set the Visibility Mode for el, bwrap for
+ // collapse/expands/hide/show
+ var El = Ext.Element;
+ var mode = El[this.hideMode.toUpperCase()] || 'x-hide-nosize';
+ Ext.each([this[this.collapseEl], this.floating ? null : this.getActionEl(),this.iframe],
+ function(el) {
+ if (el)
+ el.setVisibilityMode(mode);
+ }, this);
+
+ if (this.iframe = new Ext.ux.ManagedIFrame(this.iframe, {
+ loadMask : this.loadMask,
+ showLoadIndicator: this.showLoadIndicator,
+ disableMessaging : this.disableMessaging,
+ style : this.frameStyle,
+ src : this.defaultSrc,
+ html : html
+ }))
+ {
+ this.loadMask = this.iframe.loadMask;
+ this.iframe.ownerCt = this;
+ this.relayEvents(this.iframe, ["blur", "focus", "unload",
+ "documentloaded", "domready", "exception",
+ "message"].concat(this._msgTagHandlers || []));
+ delete this._msgTagHandlers;
+ }
+
+ }
+ },
+
+ /**
+ * dispatch a message to the embedded frame-window context
+ * @name sendMessage
+ * @methodOf Ext.ux.panel.ManagedIframe
+ * @param {Mixed} message The message payload
+ * @param {String} tag Optional reference tag
+ * @param {String} origin Optional domain designation of the sender
+ * (defaults to document.domain).
+ */
+
+ sendMessage : function() {
+ if (this.iframe) {
+ this.iframe.sendMessage.apply(this.iframe, arguments);
+ }
+ },
+
+ /** @private
+ * relay all defined 'message:tag' event handlers
+ */
+ on : function(name) {
+ var tagRE = /^message\:/i, n = null;
+ if (typeof name == 'object') {
+ for (var na in name) {
+ if (!this.filterOptRe.test(na) && tagRE.test(na)) {
+ n || (n = []);
+ n.push(na.toLowerCase());
+ }
+ }
+ } else if (tagRE.test(name)) {
+ n = [name.toLowerCase()];
+ }
+
+ if (this.getFrame() && n) {
+ this.relayEvents(this.iframe, n);
+ } else {
+ this._msgTagHandlers || (this._msgTagHandlers = []);
+ if (n)
+ this._msgTagHandlers = this._msgTagHandlers.concat(n);
+ // queued for onRender when iframe is available
+ }
+ Ext.ux.ManagedIframePanel.superclass.on.apply(this, arguments);
+ },
+
+ /**
+ * Sets the embedded Iframe src property. Note: invoke the function with
+ * no arguments to refresh the iframe based on the current src value.
+ *
+ * @param {String/Function} url (Optional) A string or reference to a Function that
+ * returns a URI string when called
+ * @param {Boolean} discardUrl (Optional) If not passed as <tt>false</tt>
+ * the URL of this action becomes the default SRC attribute
+ * for this iframe, and will be subsequently used in future
+ * setSrc calls (emulates autoRefresh by calling setSrc
+ * without params).
+ * @param {Function} callback (Optional) A callback function invoked when the
+ * frame document has been fully loaded.
+ * @param {Object} scope (Optional) scope by which the callback function is
+ * invoked.
+ */
+ setSrc : function(url, discardUrl, callback, scope) {
+ url = url || this.defaultSrc || false;
+
+ if (!url)
+ return this;
+
+ if (url.url) {
+ callback = url.callback || false;
+ discardUrl = url.discardUrl || false;
+ url = url.url || false;
+ scope = url.scope || null;
+ }
+
+ if (this.rendered && this.iframe) {
+ var u = url || this.iframe.resetUrl;
+ this.iframe.setSrc(u, discardUrl, callback, scope);
+ }
+
+ return this;
+ },
+
+ /**
+ * Sets the embedded Iframe location using its replace method. Note: invoke the function with
+ * no arguments to refresh the iframe based on the current src value.
+ *
+ * @param {String/Function} url (Optional) A string or reference to a Function that
+ * returns a URI string when called
+ * @param {Boolean} discardUrl (Optional) If not passed as <tt>false</tt>
+ * the URL of this action becomes the default SRC attribute
+ * for this iframe, and will be subsequently used in future
+ * setSrc calls (emulates autoRefresh by calling setSrc
+ * without params).
+ * @param {Function} callback (Optional) A callback function invoked when the
+ * frame document has been fully loaded.
+ * @param {Object} scope (Optional) scope by which the callback function is
+ * invoked.
+ */
+ setLocation : function(url, discardUrl, callback, scope) {
+ url = url || this.defaultSrc || false;
+
+ if (!url)
+ return this;
+
+ if (url.url) {
+ callback = url.callback || false;
+ discardUrl = url.discardUrl || false;
+ url = url.url || false;
+ scope = url.scope || null;
+ }
+
+ if (this.rendered && this.iframe) {
+ var u = url || this.iframe.resetUrl;
+ this.iframe.setLocation(u, discardUrl, callback, scope);
+ }
+
+ return this;
+ },
+
+ /**
+ * @private //Make it state-aware
+ */
+ getState : function() {
+
+ var URI = this.iframe ? this.iframe.getDocumentURI() || null : null;
+ return Ext.apply(Ext.ux.ManagedIframePanel.superclass.getState.call(this)
+ || {}, URI ? {
+ defaultSrc : typeof URI == 'function' ? URI() : URI
+ } : null);
+
+ },
+
+ /**
+ * Get the {@link Ext.Updater} for this panel's iframe/or body. Enables
+ * Ajax-based document replacement of this panel's iframe document.
+ *
+ * @return {Ext.Updater} The Updater
+ */
+ getUpdater : function() {
+ return this.rendered
+ ? (this.iframe || this.body).getUpdater()
+ : null;
+ },
+ /**
+ * Get the embedded iframe Ext.Element for this panel
+ *
+ * @return {Ext.Element} The Panels Ext.ux.ManagedIFrame instance.
+ */
+ getFrame : function() {
+ return this.rendered ? this.iframe : null
+ },
+
+ /**
+ * Returns the frame's current window object.
+ *
+ * @return {Window} The frame Window object.
+ */
+ getFrameWindow : function() {
+ return this.rendered && this.iframe
+ ? this.iframe.getWindow()
+ : null;
+ },
+
+ /**
+ * If sufficient privilege exists, returns the frame's current document
+ * as an HTMLElement.
+ *
+ * @return {HTMLElement} The frame document or false if access to
+ * document object was denied.
+ */
+ getFrameDocument : function() {
+ return this.rendered && this.iframe
+ ? this.iframe.getDocument()
+ : null;
+ },
+
+ /**
+ * Get the embedded iframe's document as an Ext.Element.
+ *
+ * @return {Ext.Element object} or null if unavailable
+ */
+ getFrameDoc : function() {
+ return this.rendered && this.iframe ? this.iframe.getDoc() : null;
+ },
+
+ /**
+ * If sufficient privilege exists, returns the frame's current document
+ * body as an HTMLElement.
+ *
+ * @return {HTMLElement} The frame document body or Null if access to
+ * document object was denied.
+ */
+ getFrameBody : function() {
+ return this.rendered && this.iframe ? this.iframe.getBody() : null;
+ },
+
+ /**
+ * Loads this panel's iframe immediately with content returned from an
+ * XHR call.
+ *
+ * @param {Object/String/Function}
+ * config A config object containing any of the following
+ * options:
+ *
+ * <pre><code>
+ * panel.load({
+ * url: "your-url.php",
+ * params: {param1: "foo", param2: "bar"}, // or a URL encoded string
+ * callback: yourFunction,
+ * scope: yourObject, // optional scope for the callback
+ * discardUrl: false,
+ * nocache: false,
+ * text: "Loading...",
+ * timeout: 30,
+ * scripts: false,
+ * renderer:{render:function(el, response, updater, callback){....}} //optional custom renderer
+ * });
+ *
+ * </code></pre>
+ *
+ * The only required property is url. The optional properties
+ * nocache, text and scripts are shorthand for
+ * disableCaching, indicatorText and loadScripts and are used
+ * to set their associated property on this panel Updater
+ * instance.
+ * @return {Ext.Panel} this
+ */
+ load : function(loadCfg) {
+ var um;
+ if (um = this.getUpdater()) {
+ if (loadCfg && loadCfg.renderer) {
+ um.setRenderer(loadCfg.renderer);
+ delete loadCfg.renderer;
+ }
+ um.update.apply(um, arguments);
+ }
+ return this;
+ },
+
+ /** @private */
+ doAutoLoad : function() {
+ this.load(typeof this.autoLoad == 'object' ? this.autoLoad : {
+ url : this.autoLoad
+ });
+ }
+
+ });
+
+ Ext.ux.ManagedIFrame.Manager = MIM = function() {
+ var frames = {};
+
+ // private DOMFrameContentLoaded handler for browsers (Gecko, Webkit) that support it.
+
+
+ var implementation = {
+ readyHandler : function(e) {
+
+ try {
+
+ var $frame = e.target.ownerEl;
+ if ($frame && $frame._frameAction){
+
+ $frame.loadHandler.call($frame,{type : 'domready'});
+
+ }
+
+ } catch (rhEx) {return} //nested iframes will throw when accessing target.id
+
+ },
+ /**
+ * @cfg {String} shimCls
+ * @default "x-frame-shim"
+ * The default CSS rule applied to ManagedIFrame image shims to toggle their visibility.
+ */
+ shimCls : 'x-frame-shim',
+
+ /** @private */
+ register : function(frame) {
+ frame.manager = this;
+ frames[frame.id] = frames[frame.dom.name] = {
+ ref : frame,
+ elCache : {}
+ };
+
+ // Hook the Iframes loaded state handler
+ frame.dom[Ext.isIE?'onreadystatechange':'onload'] = frame.loadHandler.createDelegate(frame);
+ return frame;
+ },
+ /** @private */
+ deRegister : function(frame) {
+ frame._unHook();
+ frame.dom.onload = frame.dom.onreadystatechange = null;
+ delete frames[frame.id];
+ delete frames[frame.dom.name];
+
+ },
+ /**
+ * Toggles the built-in MIF shim off on all visible ManagedIFrames
+ * @methodOf Ext.ux.ManagedIFrame.Manager
+ * @param none
+ */
+ hideShims : function() {
+
+ if (!this.shimApplied)
+ return;
+ Ext.select('.' + this.shimCls, true).removeClass(this.shimCls
+ + '-on');
+ this.shimApplied = false;
+ },
+
+ /**
+ * Mask ALL ManagedIframes (eg. when a region-layout.splitter is on the move.)
+ * @methodOf Ext.ux.ManagedIFrame.Manager
+ * @param none
+ */
+ showShims : function() {
+ if (!this.shimApplied) {
+ this.shimApplied = true;
+ // Activate the shimCls globally
+ Ext.select('.' + this.shimCls, true).addClass(this.shimCls
+ + '-on');
+ }
+
+ },
+
+ /**
+ * Retrieve a ManagedIframe instance by its DOM ID
+ * @methodOf Ext.ux.ManagedIFrame.Manager
+ * @param {Ext.ux.ManagedIFrame/string} id
+ */
+ getFrameById : function(id) {
+ return typeof id == 'string' ? (frames[id] ? frames[id].ref
+ || null : null) : null;
+ },
+
+ /**
+ * Retrieve a ManagedIframe instance by its DOM name
+ * @methodOf Ext.ux.ManagedIFrame.Manager
+ * @param {Ext.ux.ManagedIFrame/string} name
+ */
+ getFrameByName : function(name) {
+ return this.getFrameById(name);
+ },
+ /** @private */
+ // retrieve the internal frameCache object
+ getFrameHash : function(frame) {
+ return frame.id ? frames[frame.id] : null;
+
+ },
+
+ /** @private */
+ // to be called under the scope of the managing MIF
+ eventProxy : function(e) {
+
+ if (!e)
+ return;
+ e = Ext.EventObject.setEvent(e);
+ var be = e.browserEvent || e;
+
+ // same-domain unloads should clear ElCache for use with the
+ // next document rendering
+ if (e.type == 'unload') {
+ this._unHook();
+ }
+
+ if (!be['eventPhase']
+ || (be['eventPhase'] == (be['AT_TARGET'] || 2))) {
+ return this.fireEvent(e.type, e);
+ }
+ },
+ /** @private */
+ _flyweights : {},
+
+ /** @private */
+ destroy : function() {
+
+ if (document.addEventListener) {
+ window.removeEventListener("DOMFrameContentLoaded", this.readyHandler, true);
+ }
+
+ },
+
+ // safe removal of embedded frame elements
+ removeNode : Ext.isIE ? function(frame, n) {
+ frame = MIM.getFrameHash(frame);
+ if (frame && n && n.tagName != 'BODY') {
+ d = frame.scratchDiv
+ || (frame.scratchDiv = frame.getDocument().createElement('div'));
+ d.appendChild(n);
+ d.innerHTML = '';
+ }
+ } : function(frame, n) {
+ if (n && n.parentNode && n.tagName != 'BODY') {
+ n.parentNode.removeChild(n);
+ }
+ }
+
+ };
+ if (document.addEventListener) { // for Gecko and Opera and any who
+ // might support it later
+ //Ext.EventManager.on
+
+ window.addEventListener("DOMFrameContentLoaded", implementation.readyHandler, true);
+
+ }
+
+ Ext.EventManager.on(window, 'beforeunload', implementation.destroy,implementation);
+ return implementation;
+
+ }();
+
+ MIM.showDragMask = MIM.showShims;
+ MIM.hideDragMask = MIM.hideShims;
+
+ // Provide an Ext.Element interface to frame document elements
+ /** @private */
+ MIM.El = function(frame, el, forceNew) {
+
+ var frameObj;
+ frame = (frameObj = MIM.getFrameHash(frame)) ? frameObj.ref : null;
+
+ if (!frame) {
+ return null;
+ }
+ var elCache = frameObj.elCache || (frameObj.elCache = {});
+
+ var dom = frame.getDom(el);
+
+ if (!dom) { // invalid id/element
+ return null;
+ }
+ var id = dom.id;
+ if (forceNew !== true && id && elCache[id]) { // element object
+ // already exists
+ return elCache[id];
+ }
+
+ /**
+ * The DOM element
+ *
+ * @type HTMLElement
+ */
+ this.dom = dom;
+
+ /**
+ * The DOM element ID
+ *
+ * @type String
+ */
+ this.id = id || Ext.id(dom);
+ };
+ /** @private */
+ MIM.El.get = function(frame, el) {
+ var ex, elm, id, doc;
+ if (!frame || !el) {
+ return null;
+ }
+
+ var frameObj;
+ frame = (frameObj = MIM.getFrameHash(frame)) ? frameObj.ref : null;
+
+ if (!frame) {
+ return null;
+ }
+
+ var elCache = frameObj.elCache || (frameObj.elCache = {});
+
+ if (!(doc = frame.getDocument())) {
+ return null;
+ }
+ if (typeof el == "string") { // element id
+ if (!(elm = frame.getDom(el))) {
+ return null;
+ }
+ if (ex = elCache[el]) {
+ ex.dom = elm;
+ } else {
+ ex = elCache[el] = new MIM.El(frame, elm);
+ }
+ return ex;
+ } else if (el.tagName) { // dom element
+ if (!(id = el.id)) {
+ id = Ext.id(el);
+ }
+ if (ex = elCache[id]) {
+ ex.dom = el;
+ } else {
+ ex = elCache[id] = new MIM.El(frame, el);
+ }
+ return ex;
+ } else if (el instanceof MIM.El) {
+ if (el != frameObj.docEl) {
+ el.dom = frame.getDom(el.id) || el.dom; // refresh dom element
+ // in case no longer
+ // valid,
+ // catch case where it hasn't been appended
+ elCache[el.id] = el; // in case it was created directly with
+ // Element(), let's cache it
+ }
+ return el;
+ } else if (el.isComposite) {
+ return el;
+ } else if (Ext.isArray(el)) {
+ return frame.select(el);
+ } else if (el == doc) {
+ // create a bogus element object representing the document object
+ if (!frameObj.docEl) {
+ var f = function() {
+ };
+ f.prototype = MIM.El.prototype;
+ frameObj.docEl = new f();
+ frameObj.docEl.dom = doc;
+ }
+ return frameObj.docEl;
+ }
+ return null;
+
+ };
+
+ Ext.apply(MIM.El.prototype, Ext.Element.prototype);
+
+ Ext.ns('Ext.ux.panel', 'Ext.ux.portlet');
+ Ext.reg('iframepanel', Ext.ux.panel.ManagedIframe = Ext.ux.ManagedIframePanel);
+
+ /**
+ * @class Ext.ux.portlet.ManagedIFrame
+ * @extends Ext.ux.panel.ManagedIframe
+ * @version: 1.2 @license <a
+ * href="http://www.gnu.org/licenses/lgpl.html">LGPL 3.0</a> @author: Doug
+ * Hendricks. Forum ID: <a
+ * href="http://extjs.com/forum/member.php?u=8730">hendricd</a> Copyright
+ * 2007-2008, Active Group, Inc. All rights reserved.
+ *
+ * @constructor Create a new Ext.ux.portlet.ManagedIFrame @param {Object}
+ * config The config object
+ */
+
+ Ext.ux.ManagedIframePortlet = Ext.extend(Ext.ux.ManagedIframePanel, {
+ anchor : '100%',
+ frame : true,
+ collapseEl : 'bwrap',
+ collapsible : true,
+ draggable : true,
+ cls : 'x-portlet'
+ });
+
+ Ext.reg('iframeportlet',Ext.ux.portlet.ManagedIframe = Ext.ux.ManagedIframePortlet);
+
+ /** @private
+ * override adds a third visibility feature to Ext.Element: Now an elements'
+ * visibility may be handled by application of a custom (hiding) CSS
+ * className. The class is removed to make the Element visible again
+ */
+
+ Ext.apply(Ext.Element.prototype, {
+ setVisible : function(visible, animate) {
+ if (!animate || !Ext.lib.Anim) {
+ if (this.visibilityMode == Ext.Element.DISPLAY) {
+ this.setDisplayed(visible);
+ } else if (this.visibilityMode == Ext.Element.VISIBILITY) {
+ this.fixDisplay();
+ this.dom.style.visibility = visible ? "visible" : "hidden";
+ } else {
+ this[visible ? 'removeClass' : 'addClass'](String(this.visibilityMode));
+ }
+
+ } else {
+ // closure for composites
+ var dom = this.dom;
+ var visMode = this.visibilityMode;
+
+ if (visible) {
+ this.setOpacity(.01);
+ this.setVisible(true);
+ }
+ this.anim({
+ opacity : {
+ to : (visible ? 1 : 0)
+ }
+ }, this.preanim(arguments, 1), null, .35, 'easeIn',
+ function() {
+
+ if (!visible) {
+ if (visMode == Ext.Element.DISPLAY) {
+ dom.style.display = "none";
+ } else if (visMode == Ext.Element.VISIBILITY) {
+ dom.style.visibility = "hidden";
+ } else {
+ Ext.get(dom).addClass(String(visMode));
+ }
+ Ext.get(dom).setOpacity(1);
+ }
+ });
+ }
+ return this;
+ },
+ /** @private
+ * Checks whether the element is currently visible using both visibility
+ * and display properties.
+ *
+ * @param {Boolean}
+ * deep (optional) True to walk the dom and see if parent
+ * elements are hidden (defaults to false)
+ * @return {Boolean} True if the element is currently visible, else
+ * false
+ */
+ isVisible : function(deep) {
+ var vis = !(this.hasClass(this.visibilityMode) || this.getStyle("visibility") == "hidden"
+ || this.getStyle("display") == "none" );
+ if (deep !== true || !vis) {
+ return vis;
+ }
+ var p = this.dom.parentNode;
+ while (p && p.tagName.toLowerCase() != "body") {
+ if (!Ext.fly(p, '_isVisible').isVisible()) {
+ return false;
+ }
+ p = p.parentNode;
+ }
+ return true;
+ }
+ });
+ /** @private */
+ Ext.onReady(function() {
+ // Generate CSS Rules but allow for overrides.
+ var CSS = Ext.util.CSS, rules = [];
+
+ CSS.getRule('.x-managed-iframe')|| (rules.push('.x-managed-iframe {height:100%;width:100%;overflow:auto;position:relative;}'));
+ CSS.getRule('.x-managed-iframe-mask')|| (rules.push('.x-managed-iframe-mask{position:relative;zoom:1;}'));
+ if (!CSS.getRule('.x-frame-shim')) {
+ rules.push('.x-frame-shim {z-index:8500;position:absolute;top:0px;left:0px;background:transparent!important;overflow:hidden;display:none;}');
+ rules.push('.x-frame-shim-on{width:100%;height:100%;display:block;zoom:1;}');
+ rules.push('.ext-ie6 .x-frame-shim{margin-left:5px;margin-top:3px;}');
+ }
+ CSS.getRule('.x-hide-nosize')|| (rules.push('.x-hide-nosize,.x-hide-nosize *{height:0px!important;width:0px!important;border:none;}'));
+
+ if (!!rules.length) {
+ CSS.createStyleSheet(rules.join(' '));
+ }
+ });
+})();
+/** @sourceURL=<miframe.js> */
+if (Ext.provide) {
+ Ext.provide('miframe');
+}
\ No newline at end of file
Added: trunk/qo-kregator/ux/miframe/v_03-11-2008
===================================================================
--- trunk/qo-kregator/ux/miframe/v_03-11-2008 (rev 0)
+++ trunk/qo-kregator/ux/miframe/v_03-11-2008 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,3 @@
+ExtJs Forum : http://extjs.com/forum/showthread.php?t=40961
+Google Code : http://code.google.com/p/managediframe/source/browse/
+Credits : Doug Hendricks (http://extjs.com/forum/member.php?u=8730)
Added: trunk/qo-kregator/ux/spinner/Spinner.css
===================================================================
--- trunk/qo-kregator/ux/spinner/Spinner.css (rev 0)
+++ trunk/qo-kregator/ux/spinner/Spinner.css 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,50 @@
+.x-form-spinner-proxy{
+ /*background-color:#ff00cc;*/
+}
+.x-form-field-wrap .x-form-spinner-trigger {
+ background:transparent url(spinner.gif) no-repeat 0 0;
+}
+
+.x-form-field-wrap .x-form-spinner-overup{
+ background-position:-17px 0;
+}
+.x-form-field-wrap .x-form-spinner-clickup{
+ background-position:-34px 0;
+}
+.x-form-field-wrap .x-form-spinner-overdown{
+ background-position:-51px 0;
+}
+.x-form-field-wrap .x-form-spinner-clickdown{
+ background-position:-68px 0;
+}
+
+
+.x-trigger-wrap-focus .x-form-spinner-trigger{
+ background-position:-85px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-overup{
+ background-position:-102px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-clickup{
+ background-position:-119px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-overdown{
+ background-position:-136px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-clickdown{
+ background-position:-153px 0;
+}
+.x-trigger-wrap-focus .x-form-trigger{
+ border-bottom: 1px solid #7eadd9;
+}
+
+.x-form-field-wrap .x-form-spinner-splitter {
+ line-height:1px;
+ font-size:1px;
+ background:transparent url(spinner-split.gif) no-repeat 0 0;
+ position:absolute;
+ cursor: n-resize;
+}
+.x-trigger-wrap-focus .x-form-spinner-splitter{
+ background-position:-14px 0;
+}
Added: trunk/qo-kregator/ux/spinner/Spinner.js
===================================================================
--- trunk/qo-kregator/ux/spinner/Spinner.js (rev 0)
+++ trunk/qo-kregator/ux/spinner/Spinner.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,302 @@
+/**
+ * Copyright (c) 2008, Steven Chim
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Ext.ux.form.Spinner Class
+ *
+ * @author Steven Chim
+ * @version Spinner.js 2008-08-27 v0.35
+ *
+ * @class Ext.ux.form.Spinner
+ * @extends Ext.form.TriggerField
+ */
+
+Ext.namespace("Ext.ux.form");
+
+Ext.ux.form.Spinner = function(config){
+ Ext.ux.form.Spinner.superclass.constructor.call(this, config);
+ this.addEvents({
+ 'spin' : true,
+ 'spinup' : true,
+ 'spindown' : true
+ });
+}
+
+Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
+ triggerClass : 'x-form-spinner-trigger',
+ splitterClass : 'x-form-spinner-splitter',
+
+ alternateKey : Ext.EventObject.shiftKey,
+ strategy : undefined,
+
+ //private
+ onRender : function(ct, position){
+ Ext.ux.form.Spinner.superclass.onRender.call(this, ct, position);
+
+ this.splitter = this.wrap.createChild({tag:'div', cls:this.splitterClass, style:'width:13px; height:2px;'});
+ this.splitter.show().setRight( (Ext.isIE) ? 1 : 2 );
+ this.splitter.show().setTop(10);
+
+ this.proxy = this.trigger.createProxy('', this.splitter, true);
+ this.proxy.addClass("x-form-spinner-proxy");
+ this.proxy.setStyle('left','0px');
+ this.proxy.setSize(14, 1);
+ this.proxy.hide();
+ this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {dragElId: this.proxy.id});
+
+ this.initSpinner();
+ },
+
+ //private
+ initTrigger : function(){
+ this.trigger.addClassOnOver('x-form-trigger-over');
+ this.trigger.addClassOnClick('x-form-trigger-click');
+ },
+
+ //private
+ initSpinner : function(){
+ this.keyNav = new Ext.KeyNav(this.el, {
+ "up" : function(e){
+ e.preventDefault();
+ this.onSpinUp();
+ },
+
+ "down" : function(e){
+ e.preventDefault();
+ this.onSpinDown();
+ },
+
+ "pageUp" : function(e){
+ e.preventDefault();
+ this.onSpinUpAlternate();
+ },
+
+ "pageDown" : function(e){
+ e.preventDefault();
+ this.onSpinDownAlternate();
+ },
+
+ scope : this
+ });
+
+ this.repeater = new Ext.util.ClickRepeater(this.trigger);
+ this.repeater.on("click", this.onTriggerClick, this, {preventDefault:true});
+ this.trigger.on("mouseover", this.onMouseOver, this, {preventDefault:true});
+ this.trigger.on("mouseout", this.onMouseOut, this, {preventDefault:true});
+ this.trigger.on("mousemove", this.onMouseMove, this, {preventDefault:true});
+ this.trigger.on("mousedown", this.onMouseDown, this, {preventDefault:true});
+ this.trigger.on("mouseup", this.onMouseUp, this, {preventDefault:true});
+ this.wrap.on("mousewheel", this.handleMouseWheel, this);
+
+ this.dd.setXConstraint(0, 0, 10)
+ this.dd.setYConstraint(1500, 1500, 10);
+ this.dd.endDrag = this.endDrag.createDelegate(this);
+ this.dd.startDrag = this.startDrag.createDelegate(this);
+ this.dd.onDrag = this.onDrag.createDelegate(this);
+
+ /*
+ jsakalos suggestion
+ http://extjs.com/forum/showthread.php?p=121850#post121850 */
+ if('object' == typeof this.strategy && this.strategy.xtype) {
+ switch(this.strategy.xtype) {
+ case 'number':
+ this.strategy = new Ext.ux.form.Spinner.NumberStrategy(this.strategy);
+ break;
+
+ case 'date':
+ this.strategy = new Ext.ux.form.Spinner.DateStrategy(this.strategy);
+ break;
+
+ case 'time':
+ this.strategy = new Ext.ux.form.Spinner.TimeStrategy(this.strategy);
+ break;
+
+ default:
+ delete(this.strategy);
+ break;
+ }
+ delete(this.strategy.xtype);
+ }
+
+ if(this.strategy == undefined){
+ this.strategy = new Ext.ux.form.Spinner.NumberStrategy();
+ }
+ },
+
+ //private
+ onMouseOver : function(){
+ if(this.disabled){
+ return;
+ }
+ var middle = this.getMiddle();
+ this.__tmphcls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
+ this.trigger.addClass(this.__tmphcls);
+ },
+
+ //private
+ onMouseOut : function(){
+ this.trigger.removeClass(this.__tmphcls);
+ },
+
+ //private
+ onMouseMove : function(){
+ if(this.disabled){
+ return;
+ }
+ var middle = this.getMiddle();
+ if( ((Ext.EventObject.getPageY() > middle) && this.__tmphcls == "x-form-spinner-overup") ||
+ ((Ext.EventObject.getPageY() < middle) && this.__tmphcls == "x-form-spinner-overdown")){
+ }
+ },
+
+ //private
+ onMouseDown : function(){
+ if(this.disabled){
+ return;
+ }
+ var middle = this.getMiddle();
+ this.__tmpccls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
+ this.trigger.addClass(this.__tmpccls);
+ },
+
+ //private
+ onMouseUp : function(){
+ this.trigger.removeClass(this.__tmpccls);
+ },
+
+ //private
+ onTriggerClick : function(){
+ if(this.disabled || this.getEl().dom.readOnly){
+ return;
+ }
+ var middle = this.getMiddle();
+ var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down';
+ this['onSpin'+ud]();
+ },
+
+ //private
+ getMiddle : function(){
+ var t = this.trigger.getTop();
+ var h = this.trigger.getHeight();
+ var middle = t + (h/2);
+ return middle;
+ },
+
+ //private
+ //checks if control is allowed to spin
+ isSpinnable : function(){
+ if(this.disabled || this.getEl().dom.readOnly){
+ Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly
+ return false;
+ }
+ return true;
+ },
+
+ handleMouseWheel : function(e){
+ //disable scrolling when not focused
+ if(this.wrap.hasClass('x-trigger-wrap-focus') == false){
+ return;
+ }
+
+ var delta = e.getWheelDelta();
+ if(delta > 0){
+ this.onSpinUp();
+ e.stopEvent();
+ } else if(delta < 0){
+ this.onSpinDown();
+ e.stopEvent();
+ }
+ },
+
+ //private
+ startDrag : function(){
+ this.proxy.show();
+ this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
+ },
+
+ //private
+ endDrag : function(){
+ this.proxy.hide();
+ },
+
+ //private
+ onDrag : function(){
+ if(this.disabled){
+ return;
+ }
+ var y = Ext.fly(this.dd.getDragEl()).getTop();
+ var ud = '';
+
+ if(this._previousY > y){ud = 'Up';} //up
+ if(this._previousY < y){ud = 'Down';} //down
+
+ if(ud != ''){
+ this['onSpin'+ud]();
+ }
+
+ this._previousY = y;
+ },
+
+ //private
+ onSpinUp : function(){
+ if(this.isSpinnable() == false) {
+ return;
+ }
+ if(Ext.EventObject.shiftKey == true){
+ this.onSpinUpAlternate();
+ return;
+ }else{
+ this.strategy.onSpinUp(this);
+ }
+ this.fireEvent("spin", this);
+ this.fireEvent("spinup", this);
+ },
+
+ //private
+ onSpinDown : function(){
+ if(this.isSpinnable() == false) {
+ return;
+ }
+ if(Ext.EventObject.shiftKey == true){
+ this.onSpinDownAlternate();
+ return;
+ }else{
+ this.strategy.onSpinDown(this);
+ }
+ this.fireEvent("spin", this);
+ this.fireEvent("spindown", this);
+ },
+
+ //private
+ onSpinUpAlternate : function(){
+ if(this.isSpinnable() == false) {
+ return;
+ }
+ this.strategy.onSpinUpAlternate(this);
+ this.fireEvent("spin", this);
+ this.fireEvent("spinup", this);
+ },
+
+ //private
+ onSpinDownAlternate : function(){
+ if(this.isSpinnable() == false) {
+ return;
+ }
+ this.strategy.onSpinDownAlternate(this);
+ this.fireEvent("spin", this);
+ this.fireEvent("spindown", this);
+ }
+
+});
+
+Ext.reg('uxspinner', Ext.ux.form.Spinner);
Added: trunk/qo-kregator/ux/spinner/SpinnerStrategy.js
===================================================================
--- trunk/qo-kregator/ux/spinner/SpinnerStrategy.js (rev 0)
+++ trunk/qo-kregator/ux/spinner/SpinnerStrategy.js 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1,172 @@
+/**
+ * Copyright (c) 2008, Steven Chim
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/***
+ * Abstract Strategy
+ */
+Ext.ux.form.Spinner.Strategy = function(config){
+ Ext.apply(this, config);
+};
+
+Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
+ defaultValue : 0,
+ minValue : undefined,
+ maxValue : undefined,
+ incrementValue : 1,
+ alternateIncrementValue : 5,
+ validationTask : new Ext.util.DelayedTask(),
+
+ onSpinUp : function(field){
+ this.spin(field, false, false);
+ },
+
+ onSpinDown : function(field){
+ this.spin(field, true, false);
+ },
+
+ onSpinUpAlternate : function(field){
+ this.spin(field, false, true);
+ },
+
+ onSpinDownAlternate : function(field){
+ this.spin(field, true, true);
+ },
+
+ spin : function(field, down, alternate){
+ this.validationTask.delay(500, function(){field.validate()});
+ //extend
+ },
+
+ fixBoundries : function(value){
+ return value;
+ //overwrite
+ }
+
+});
+
+/***
+ * Concrete Strategy: Numbers
+ */
+Ext.ux.form.Spinner.NumberStrategy = function(config){
+ Ext.ux.form.Spinner.NumberStrategy.superclass.constructor.call(this, config);
+};
+
+Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {
+
+ allowDecimals : true,
+ decimalPrecision : 2,
+
+ spin : function(field, down, alternate){
+ Ext.ux.form.Spinner.NumberStrategy.superclass.spin.call(this, field, down, alternate);
+
+ var v = parseFloat(field.getValue());
+ var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
+
+ (down == true) ? v -= incr : v += incr ;
+ v = (isNaN(v)) ? this.defaultValue : v;
+ v = this.fixBoundries(v);
+ field.setRawValue(v);
+ },
+
+ fixBoundries : function(value){
+ var v = value;
+
+ if(this.minValue != undefined && v < this.minValue){
+ v = this.minValue;
+ }
+ if(this.maxValue != undefined && v > this.maxValue){
+ v = this.maxValue;
+ }
+
+ return this.fixPrecision(v);
+ },
+
+ // private
+ fixPrecision : function(value){
+ var nan = isNaN(value);
+ if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
+ return nan ? '' : value;
+ }
+ return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
+ }
+});
+
+
+/***
+ * Concrete Strategy: Date
+ */
+Ext.ux.form.Spinner.DateStrategy = function(config){
+ Ext.ux.form.Spinner.DateStrategy.superclass.constructor.call(this, config);
+};
+
+Ext.extend(Ext.ux.form.Spinner.DateStrategy, Ext.ux.form.Spinner.Strategy, {
+ defaultValue : new Date(),
+ format : "Y-m-d",
+ incrementValue : 1,
+ incrementConstant : Date.DAY,
+ alternateIncrementValue : 1,
+ alternateIncrementConstant : Date.MONTH,
+
+ spin : function(field, down, alternate){
+ Ext.ux.form.Spinner.DateStrategy.superclass.spin.call(this);
+
+ var v = field.getRawValue();
+
+ v = Date.parseDate(v, this.format);
+ var dir = (down == true) ? -1 : 1 ;
+ var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
+ var dtconst = (alternate == true) ? this.alternateIncrementConstant : this.incrementConstant;
+
+ if(typeof this.defaultValue == 'string'){
+ this.defaultValue = Date.parseDate(this.defaultValue, this.format);
+ }
+
+ v = (v) ? v.add(dtconst, dir*incr) : this.defaultValue;
+
+ v = this.fixBoundries(v);
+ field.setRawValue(Ext.util.Format.date(v,this.format));
+ },
+
+ //private
+ fixBoundries : function(date){
+ var dt = date;
+ var min = (typeof this.minValue == 'string') ? Date.parseDate(this.minValue, this.format) : this.minValue ;
+ var max = (typeof this.maxValue == 'string') ? Date.parseDate(this.maxValue, this.format) : this.maxValue ;
+
+ if(this.minValue != undefined && dt < min){
+ dt = min;
+ }
+ if(this.maxValue != undefined && dt > max){
+ dt = max;
+ }
+
+ return dt;
+ }
+
+});
+
+
+/***
+ * Concrete Strategy: Time
+ */
+Ext.ux.form.Spinner.TimeStrategy = function(config){
+ Ext.ux.form.Spinner.TimeStrategy.superclass.constructor.call(this, config);
+};
+
+Ext.extend(Ext.ux.form.Spinner.TimeStrategy, Ext.ux.form.Spinner.DateStrategy, {
+ format : "H:i",
+ incrementValue : 1,
+ incrementConstant : Date.MINUTE,
+ alternateIncrementValue : 1,
+ alternateIncrementConstant : Date.HOUR
+});
Added: trunk/qo-kregator/ux/spinner/spinner-split.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/spinner/spinner-split.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/spinner/spinner.gif
===================================================================
(Binary files differ)
Property changes on: trunk/qo-kregator/ux/spinner/spinner.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/qo-kregator/ux/spinner/v_0.35.txt
===================================================================
--- trunk/qo-kregator/ux/spinner/v_0.35.txt (rev 0)
+++ trunk/qo-kregator/ux/spinner/v_0.35.txt 2008-11-03 20:45:59 UTC (rev 1)
@@ -0,0 +1 @@
+